Begin to work on free client

This commit is contained in:
Martin Duquesnoy 2012-01-26 18:02:47 +01:00
parent 7c4e9d8dbc
commit 6b349bb4e4
8 changed files with 174 additions and 74 deletions

View File

@ -136,12 +136,13 @@ client_gb_pos(struct tag *t, int x, int y)
{ {
struct client *c = SLIST_FIRST(&t->clients); struct client *c = SLIST_FIRST(&t->clients);
while(c) FOREACH_NFCLIENT(c, &t->clients, tnext)
{ {
if(c->flags & CLIENT_FREE)
continue;
if(INAREA(x, y, c->geo)) if(INAREA(x, y, c->geo))
return c; return c;
c = SLIST_NEXT(c, tnext);
} }
return NULL; return NULL;
@ -579,6 +580,10 @@ client_focus(struct client *c)
client_grabbuttons(c, true); client_grabbuttons(c, true);
client_tab_focus(c); client_tab_focus(c);
client_frame_update(c, CCOL(c)); client_frame_update(c, CCOL(c));
if(c->flags & CLIENT_FREE)
XRaiseWindow(W->dpy, c->frame);
XSetInputFocus(W->dpy, c->win, RevertToPointerRoot, CurrentTime); XSetInputFocus(W->dpy, c->win, RevertToPointerRoot, CurrentTime);
} }
else else
@ -825,7 +830,7 @@ client_apply_rule(struct client *c)
c->theme = r->theme; c->theme = r->theme;
if(r->flags & RULE_FREE) if(r->flags & RULE_FREE)
{ /* TODO */ } c->flags |= CLIENT_FREE;
if(r->flags & RULE_MAX) if(r->flags & RULE_MAX)
{ /* TODO */ } { /* TODO */ }
@ -833,7 +838,7 @@ client_apply_rule(struct client *c)
if(r->flags & RULE_IGNORE_TAG) if(r->flags & RULE_IGNORE_TAG)
{ /* TODO */ } { /* TODO */ }
c->flags = r->flags | CLIENT_RULED; c->flags |= CLIENT_RULED;
} }
flags = 0; flags = 0;
} }
@ -863,7 +868,7 @@ client_new(Window w, XWindowAttributes *wa, bool scan)
c->geo.y = wa->y; c->geo.y = wa->y;
c->geo.w = wa->width; c->geo.w = wa->width;
c->geo.h = wa->height; c->geo.h = wa->height;
c->tgeo = c->wgeo = c->rgeo = c->geo; c->tgeo = c->wgeo = c->rgeo = c->fgeo = c->geo;
c->tbgeo = NULL; c->tbgeo = NULL;
client_apply_rule(c); client_apply_rule(c);
@ -1021,7 +1026,10 @@ client_moveresize(struct client *c, struct geo *g)
if(c->flags & CLIENT_TABBED) if(c->flags & CLIENT_TABBED)
return false; return false;
c->ttgeo = c->tgeo = c->rgeo = c->geo = *g; if(c->flags & CLIENT_FREE)
c->fgeo = c->rgeo = c->geo = *g;
else
c->ttgeo = c->tgeo = c->rgeo = c->geo = *g;
if(!(c->flags & CLIENT_DID_WINSIZE)) if(!(c->flags & CLIENT_DID_WINSIZE))
if(client_winsize(c, g)) if(client_winsize(c, g))
@ -1099,7 +1107,7 @@ _fac_arrange_row(struct client *c, enum position p, int fac)
struct client *cc; struct client *cc;
/* Travel clients to search row parents and apply fac */ /* Travel clients to search row parents and apply fac */
SLIST_FOREACH(cc, &c->tag->clients, tnext) FOREACH_NFCLIENT(cc, &c->tag->clients, tnext)
if(GEO_PARENTROW(g, cc->tgeo, p)) if(GEO_PARENTROW(g, cc->tgeo, p))
_fac_apply(cc, p, fac); _fac_apply(cc, p, fac);
} }
@ -1115,7 +1123,7 @@ _fac_check_to_reverse(struct client *c)
* resize client because of possible error with next * resize client because of possible error with next
* clients in linked list. * clients in linked list.
*/ */
SLIST_FOREACH(gc, &c->tag->clients, tnext) FOREACH_NFCLIENT(gc, &c->tag->clients, tnext)
if(gc->flags & CLIENT_FAC_APPLIED if(gc->flags & CLIENT_FAC_APPLIED
&& client_winsize(gc, &gc->tgeo)) && client_winsize(gc, &gc->tgeo))
{ {
@ -1142,7 +1150,7 @@ _fac_resize(struct client *c, enum position p, int fac)
if(!gc || gc->screen != c->screen) if(!gc || gc->screen != c->screen)
return; return;
SLIST_FOREACH(cc, &c->tag->clients, tnext) FOREACH_NFCLIENT(cc, &c->tag->clients, tnext)
cc->ttgeo = cc->tgeo; cc->ttgeo = cc->tgeo;
if(GEO_CHECK2(c->tgeo, gc->tgeo, p)) if(GEO_CHECK2(c->tgeo, gc->tgeo, p))
@ -1164,17 +1172,17 @@ client_apply_tgeo(struct tag *t)
{ {
struct client *c; struct client *c;
SLIST_FOREACH(c, &t->clients, tnext) FOREACH_NFCLIENT(c, &t->clients, tnext)
{ {
client_moveresize(c, &c->tgeo); client_moveresize(c, &c->tgeo);
c->flags &= ~CLIENT_FAC_APPLIED; c->flags &= ~CLIENT_FAC_APPLIED;
} }
} }
#define _REV_BORDER() \ #define _REV_BORDER() \
do { \ do { \
SLIST_FOREACH(gc, &c->tag->clients, tnext) \ FOREACH_NFCLIENT(gc, &c->tag->clients, tnext) \
draw_reversed_rect(W->root, gc, true); \ draw_reversed_rect(W->root, gc, true); \
} while(/* CONSTCOND */ 0); } while(/* CONSTCOND */ 0);
void void
client_fac_resize(struct client *c, enum position p, int fac) client_fac_resize(struct client *c, enum position p, int fac)
@ -1256,7 +1264,7 @@ client_fac_resize(struct client *c, enum position p, int fac)
/* Aborted with escape, Set back original geos */ /* Aborted with escape, Set back original geos */
else else
{ {
SLIST_FOREACH(gc, &c->tag->clients, tnext) FOREACH_NFCLIENT(gc, &c->tag->clients, tnext)
{ {
gc->tgeo = gc->geo; gc->tgeo = gc->geo;
gc->flags &= ~CLIENT_DID_WINSIZE; gc->flags &= ~CLIENT_DID_WINSIZE;

View File

@ -13,6 +13,11 @@
#define TCLIENT_CHECK(C) (C->flags & CLIENT_TABBED && !(C->flags & CLIENT_TABMASTER)) #define TCLIENT_CHECK(C) (C->flags & CLIENT_TABBED && !(C->flags & CLIENT_TABMASTER))
/* SLIST_FOREACH for client with no free client */
#define FOREACH_NFCLIENT(V, H, F) \
SLIST_FOREACH(V, H, F) \
if(!(V->flags & CLIENT_FREE))
inline void client_configure(struct client *c); inline void client_configure(struct client *c);
struct client *client_gb_win(Window w); struct client *client_gb_win(Window w);
struct client *client_gb_frame(Window w); struct client *client_gb_frame(Window w);

View File

@ -46,6 +46,7 @@ static const struct { char *name; void (*func)(Uicb cmd); } uicb_list[] =
{ "layout_rotate_right", uicb_layout_rotate_right }, { "layout_rotate_right", uicb_layout_rotate_right },
{ "layout_prev_set", uicb_layout_prev_set }, { "layout_prev_set", uicb_layout_prev_set },
{ "layout_next_set", uicb_layout_next_set }, { "layout_next_set", uicb_layout_next_set },
{ "layout_toggle_free", uicb_layout_toggle_free },
/* Client */ /* Client */
{ "client_close", uicb_client_close }, { "client_close", uicb_client_close },

View File

@ -23,7 +23,7 @@ layout_save_set(struct tag *t)
l = xcalloc(1, sizeof(struct layout_set)); l = xcalloc(1, sizeof(struct layout_set));
SLIST_INIT(&l->geos); SLIST_INIT(&l->geos);
SLIST_FOREACH(c, &t->clients, tnext) FOREACH_NFCLIENT(c, &t->clients, tnext)
{ {
g = xcalloc(1, sizeof(struct geo_list)); g = xcalloc(1, sizeof(struct geo_list));
g->geo = c->geo; g->geo = c->geo;
@ -49,7 +49,7 @@ layout_apply_set(struct tag *t, struct layout_set *l)
struct client *c; struct client *c;
int nc = 1; int nc = 1;
SLIST_FOREACH(c, &t->clients, tnext) FOREACH_NFCLIENT(c, &t->clients, tnext)
++nc; ++nc;
/* TODO: Adapt different client number case */ /* TODO: Adapt different client number case */
@ -275,7 +275,7 @@ layout_split_check_row_dir(struct client *c, struct client *g, enum position p)
struct client *cc; struct client *cc;
int s = 0, cs = (LDIR(p) ? g->geo.h : g->geo.w); int s = 0, cs = (LDIR(p) ? g->geo.h : g->geo.w);
SLIST_FOREACH(cc, &c->tag->clients, tnext) FOREACH_NFCLIENT(cc, &c->tag->clients, tnext)
if(GEO_PARENTROW(cgeo, cc->geo, RPOS(p)) if(GEO_PARENTROW(cgeo, cc->geo, RPOS(p))
&& GEO_CHECK_ROW(cc->geo, g->geo, p)) && GEO_CHECK_ROW(cc->geo, g->geo, p))
{ {
@ -347,7 +347,7 @@ layout_split_arrange_closed(struct client *ghost)
&& layout_split_check_row_dir(c, ghost, p)) && layout_split_check_row_dir(c, ghost, p))
{ {
g = c->geo; g = c->geo;
SLIST_FOREACH(cc, &c->tag->clients, tnext) FOREACH_NFCLIENT(cc, &c->tag->clients, tnext)
if(GEO_PARENTROW(g, cc->geo, RPOS(p)) if(GEO_PARENTROW(g, cc->geo, RPOS(p))
&& GEO_CHECK_ROW(cc->geo, ghost->geo, p)) && GEO_CHECK_ROW(cc->geo, ghost->geo, p))
{ {
@ -366,14 +366,16 @@ layout_split_integrate(struct client *c, struct client *sc)
{ {
struct geo g; struct geo g;
/* No sc */ /* No sc or not compatible sc */
if(!sc || sc == c || sc->tag != c->tag) if(!sc || sc == c || sc->tag != c->tag
|| sc->flags & CLIENT_FREE)
{ {
/* /*
* Not even a first client in list, then * Not even a first client in list, then
* maximize the lonely client * maximize the lonely client
*/ */
if(!(sc = SLIST_NEXT(SLIST_FIRST(&c->tag->clients), tnext))) if(!(sc = SLIST_NEXT(SLIST_FIRST(&c->tag->clients), tnext))
|| sc->flags & CLIENT_FREE)
{ {
client_maximize(c); client_maximize(c);
return; return;
@ -460,7 +462,7 @@ layout_rotate(struct tag *t, void (*pfunc)(struct geo*, struct geo*, struct geo*
float f1 = (float)t->screen->ugeo.w / (float)t->screen->ugeo.h; float f1 = (float)t->screen->ugeo.w / (float)t->screen->ugeo.h;
float f2 = 1 / f1; float f2 = 1 / f1;
SLIST_FOREACH(c, &t->clients, tnext) FOREACH_NFCLIENT(c, &t->clients, tnext)
{ {
pfunc(&g, ug, &c->geo); pfunc(&g, ug, &c->geo);
@ -474,7 +476,7 @@ layout_rotate(struct tag *t, void (*pfunc)(struct geo*, struct geo*, struct geo*
} }
/* Rotate sometimes do not set back perfect size.. */ /* Rotate sometimes do not set back perfect size.. */
SLIST_FOREACH(c, &t->clients, tnext) FOREACH_NFCLIENT(c, &t->clients, tnext)
layout_fix_hole(c); layout_fix_hole(c);
layout_save_set(t); layout_save_set(t);
@ -518,7 +520,7 @@ uicb_layout_vmirror(Uicb cmd)
(void)cmd; (void)cmd;
struct client *c; struct client *c;
SLIST_FOREACH(c, &W->screen->seltag->clients, tnext) FOREACH_NFCLIENT(c, &W->screen->seltag->clients, tnext)
{ {
c->geo.x = W->screen->ugeo.w - (c->geo.x + c->geo.w); c->geo.x = W->screen->ugeo.w - (c->geo.x + c->geo.w);
client_moveresize(c, &c->geo); client_moveresize(c, &c->geo);
@ -533,7 +535,7 @@ uicb_layout_hmirror(Uicb cmd)
(void)cmd; (void)cmd;
struct client *c; struct client *c;
SLIST_FOREACH(c, &W->screen->seltag->clients, tnext) FOREACH_NFCLIENT(c, &W->screen->seltag->clients, tnext)
{ {
c->geo.y = W->screen->ugeo.h - (c->geo.y + c->geo.h); c->geo.y = W->screen->ugeo.h - (c->geo.y + c->geo.h);
client_moveresize(c, &c->geo); client_moveresize(c, &c->geo);
@ -541,3 +543,36 @@ uicb_layout_hmirror(Uicb cmd)
layout_save_set(W->screen->seltag); layout_save_set(W->screen->seltag);
} }
void
layout_client(struct client *c)
{
if(c->flags & CLIENT_IGNORE_LAYOUT)
{
c->flags ^= CLIENT_IGNORE_LAYOUT;
return;
}
if(c->flags & CLIENT_FREE)
{
layout_split_arrange_closed(c);
client_moveresize(c, &c->fgeo);
XRaiseWindow(W->dpy, c->frame);
}
else if(!(c->flags & CLIENT_TABBED))
layout_split_integrate(c, c->tag->sel);
}
void
uicb_layout_toggle_free(Uicb cmd)
{
(void)cmd;
if(!(W->client))
return;
W->client->flags ^= CLIENT_FREE;
layout_client(W->client);
}

View File

@ -34,12 +34,14 @@ void layout_free_set(struct tag *t);
void layout_split_integrate(struct client *c, struct client *sc); void layout_split_integrate(struct client *c, struct client *sc);
void layout_split_arrange_closed(struct client *ghost); void layout_split_arrange_closed(struct client *ghost);
inline void layout_fix_hole(struct client *c); inline void layout_fix_hole(struct client *c);
void layout_client(struct client *c);
void uicb_layout_vmirror(Uicb cmd); void uicb_layout_vmirror(Uicb cmd);
void uicb_layout_hmirror(Uicb cmd); void uicb_layout_hmirror(Uicb cmd);
void uicb_layout_rotate_left(Uicb cmd); void uicb_layout_rotate_left(Uicb cmd);
void uicb_layout_rotate_right(Uicb cmd); void uicb_layout_rotate_right(Uicb cmd);
void uicb_layout_prev_set(Uicb cmd); void uicb_layout_prev_set(Uicb cmd);
void uicb_layout_next_set(Uicb cmd); void uicb_layout_next_set(Uicb cmd);
void uicb_layout_toggle_free(Uicb cmd);
#endif /* LAYOUT_H */ #endif /* LAYOUT_H */

View File

@ -9,11 +9,15 @@
#include "client.h" #include "client.h"
#include "draw.h" #include "draw.h"
#define _REV_BORDER() \
do { \ #define _REV_SBORDER(c) draw_reversed_rect(W->root, c, false);
SLIST_FOREACH(gc, &c->tag->clients, tnext) \
draw_reversed_rect(W->root, gc, true); \ #define _REV_BORDER() \
do { \
FOREACH_NFCLIENT(gc, &c->tag->clients, tnext) \
draw_reversed_rect(W->root, gc, true); \
} while(/* CONSTCOND */ 0); } while(/* CONSTCOND */ 0);
static void static void
mouse_resize(struct client *c) mouse_resize(struct client *c)
{ {
@ -25,7 +29,12 @@ mouse_resize(struct client *c)
XQueryPointer(W->dpy, W->root, &w, &w, &ox, &oy, &d, &d, (uint *)&u); XQueryPointer(W->dpy, W->root, &w, &w, &ox, &oy, &d, &d, (uint *)&u);
XGrabServer(W->dpy); XGrabServer(W->dpy);
_REV_BORDER(); if(c->flags & CLIENT_FREE)
{
_REV_SBORDER(c);
}
else
_REV_BORDER();
if(c->flags & CLIENT_TABBED && !(c->flags & CLIENT_TABMASTER)) if(c->flags & CLIENT_TABBED && !(c->flags & CLIENT_TABMASTER))
c = c->tabmaster; c = c->tabmaster;
@ -40,31 +49,54 @@ mouse_resize(struct client *c)
if(ev.type != MotionNotify) if(ev.type != MotionNotify)
continue; continue;
_REV_BORDER(); if(c->flags & CLIENT_FREE)
{
_REV_SBORDER(c);
if(ix >= c->geo.x + (c->geo.w >> 1)) c->geo.w = ((ev.xmotion.x_root - c->geo.x < c->sizeh[MINW])
_fac_resize(c, Right, ev.xmotion.x_root - ox); ? c->sizeh[MINW]
: ev.xmotion.x_root - c->geo.x);
c->geo.h = ((ev.xmotion.y_root - c->geo.y < c->sizeh[MINH])
? c->sizeh[MINH]
: ev.xmotion.y_root - c->geo.y);
_REV_SBORDER(c);
}
else else
_fac_resize(c, Left, ox - ev.xmotion.x_root); {
_REV_BORDER();
if(iy >= c->geo.y + (c->geo.h >> 1)) if(ix >= c->geo.x + (c->geo.w >> 1))
_fac_resize(c, Bottom, ev.xmotion.y_root - oy); _fac_resize(c, Right, ev.xmotion.x_root - ox);
else else
_fac_resize(c, Top, oy - ev.xmotion.y_root); _fac_resize(c, Left, ox - ev.xmotion.x_root);
ox = ev.xmotion.x_root; if(iy >= c->geo.y + (c->geo.h >> 1))
oy = ev.xmotion.y_root; _fac_resize(c, Bottom, ev.xmotion.y_root - oy);
else
_fac_resize(c, Top, oy - ev.xmotion.y_root);
_REV_BORDER(); ox = ev.xmotion.x_root;
oy = ev.xmotion.y_root;
_REV_BORDER();
}
XSync(W->dpy, false); XSync(W->dpy, false);
} while(ev.type != ButtonRelease); } while(ev.type != ButtonRelease);
_REV_BORDER(); if(c->flags & CLIENT_FREE)
{
client_apply_tgeo(c->tag); _REV_SBORDER(c);
layout_save_set(c->tag); client_moveresize(c, &c->geo);
}
else
{
_REV_BORDER();
client_apply_tgeo(c->tag);
layout_save_set(c->tag);
}
XUngrabServer(W->dpy); XUngrabServer(W->dpy);
} }
@ -88,7 +120,6 @@ mouse_drag_tag(struct client *c, Window w)
return NULL; return NULL;
} }
#define _REV_SBORDER(c) draw_reversed_rect(W->root, c, false);
void void
mouse_move(struct client *c, void (*func)(struct client*, struct client*)) mouse_move(struct client *c, void (*func)(struct client*, struct client*))
{ {
@ -96,11 +127,17 @@ mouse_move(struct client *c, void (*func)(struct client*, struct client*))
struct tag *t = NULL; struct tag *t = NULL;
XEvent ev; XEvent ev;
Window w; Window w;
int d, u; int d, u, ox, oy;
int ocx, ocy;
ocx = c->geo.x;
ocy = c->geo.y;
if(c->flags & CLIENT_TABBED && !(c->flags & CLIENT_TABMASTER)) if(c->flags & CLIENT_TABBED && !(c->flags & CLIENT_TABMASTER))
c = c->tabmaster; c = c->tabmaster;
XQueryPointer(W->dpy, W->root, &w, &w, &ox, &oy, &d, &d, (uint *)&u);
_REV_SBORDER(c); _REV_SBORDER(c);
do do
@ -110,23 +147,35 @@ mouse_move(struct client *c, void (*func)(struct client*, struct client*))
if(ev.type != MotionNotify) if(ev.type != MotionNotify)
continue; continue;
XQueryPointer(W->dpy, W->root, &w, &w, &d, &d, &d, &d, (uint *)&u); if(c->flags & CLIENT_FREE)
if(!(c2 = client_gb_win(w)))
if(!(c2 = client_gb_frame(w)))
c2 = client_gb_titlebar(w);
if(c2)
{ {
if(c2 != last) _REV_SBORDER(c);
{
_REV_SBORDER(last); c->geo.x = (ocx + (ev.xmotion.x_root - ox));
_REV_SBORDER(c2); c->geo.y = (ocy + (ev.xmotion.y_root - oy));
last = c2;
} _REV_SBORDER(c);
} }
else else
t = mouse_drag_tag(c, w); {
XQueryPointer(W->dpy, W->root, &w, &w, &d, &d, &d, &d, (uint *)&u);
if(!(c2 = client_gb_win(w)))
if(!(c2 = client_gb_frame(w)))
c2 = client_gb_titlebar(w);
if(c2)
{
if(c2 != last)
{
_REV_SBORDER(last);
_REV_SBORDER(c2);
last = c2;
}
}
else
t = mouse_drag_tag(c, w);
}
XSync(W->dpy, false); XSync(W->dpy, false);
@ -137,7 +186,13 @@ mouse_move(struct client *c, void (*func)(struct client*, struct client*))
else if(t && t != (struct tag*)c) else if(t && t != (struct tag*)c)
tag_client(t, c); tag_client(t, c);
else else
{
/* No func mean free client resize */
if(!func)
client_moveresize(c, &c->geo);
_REV_SBORDER(c); _REV_SBORDER(c);
}
} }
void void
@ -155,7 +210,7 @@ uicb_mouse_move(Uicb cmd)
(void)cmd; (void)cmd;
if(W->client && mouse_check_client(W->client)) if(W->client && mouse_check_client(W->client))
mouse_move(W->client, client_swap2); mouse_move(W->client, (W->client->flags & CLIENT_FREE ? NULL : client_swap2));
} }
void void

View File

@ -74,7 +74,7 @@ tag_client(struct tag *t, struct client *c)
if(c->tag == t) if(c->tag == t)
return; return;
if(!(c->flags & CLIENT_IGNORE_LAYOUT)) if(!(c->flags & (CLIENT_IGNORE_LAYOUT | CLIENT_FREE)))
layout_split_arrange_closed(c); layout_split_arrange_closed(c);
if(!(c->flags & CLIENT_REMOVEALL)) if(!(c->flags & CLIENT_REMOVEALL))
@ -98,18 +98,11 @@ tag_client(struct tag *t, struct client *c)
client_update_props(c, CPROP_LOC); client_update_props(c, CPROP_LOC);
/*
* Insert in new tag list before
* layout_split_integrate, because of set historic.
*/
SLIST_INSERT_HEAD(&t->clients, c, tnext); SLIST_INSERT_HEAD(&t->clients, c, tnext);
infobar_elem_screen_update(t->screen, ElemTag); infobar_elem_screen_update(t->screen, ElemTag);
if(c->flags & CLIENT_IGNORE_LAYOUT) layout_client(c);
c->flags ^= CLIENT_IGNORE_LAYOUT;
else if(!(c->flags & CLIENT_TABBED))
layout_split_integrate(c, t->sel);
if(c->flags & CLIENT_TABMASTER && c->prevtag) if(c->flags & CLIENT_TABMASTER && c->prevtag)
{ {

View File

@ -177,7 +177,7 @@ struct client
struct tag *tag, *prevtag; struct tag *tag, *prevtag;
struct screen *screen; struct screen *screen;
struct barwin *titlebar; struct barwin *titlebar;
struct geo geo, wgeo, tgeo, ttgeo, rgeo, *tbgeo; struct geo geo, wgeo, tgeo, ttgeo, rgeo, *tbgeo, fgeo;
struct colpair ncol, scol; struct colpair ncol, scol;
struct theme *theme; struct theme *theme;
struct client *tabmaster; struct client *tabmaster;
@ -196,6 +196,7 @@ struct client
#define CLIENT_REMOVEALL 0x200 #define CLIENT_REMOVEALL 0x200
#define CLIENT_MAPPED 0x400 #define CLIENT_MAPPED 0x400
#define CLIENT_FULLSCREEN 0x800 #define CLIENT_FULLSCREEN 0x800
#define CLIENT_FREE 0x1000
Flags flags; Flags flags;
Window win, frame, tmp; Window win, frame, tmp;
SLIST_ENTRY(client) next; /* Global list */ SLIST_ENTRY(client) next; /* Global list */