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);
while(c)
FOREACH_NFCLIENT(c, &t->clients, tnext)
{
if(c->flags & CLIENT_FREE)
continue;
if(INAREA(x, y, c->geo))
return c;
c = SLIST_NEXT(c, tnext);
}
return NULL;
@ -579,6 +580,10 @@ client_focus(struct client *c)
client_grabbuttons(c, true);
client_tab_focus(c);
client_frame_update(c, CCOL(c));
if(c->flags & CLIENT_FREE)
XRaiseWindow(W->dpy, c->frame);
XSetInputFocus(W->dpy, c->win, RevertToPointerRoot, CurrentTime);
}
else
@ -825,7 +830,7 @@ client_apply_rule(struct client *c)
c->theme = r->theme;
if(r->flags & RULE_FREE)
{ /* TODO */ }
c->flags |= CLIENT_FREE;
if(r->flags & RULE_MAX)
{ /* TODO */ }
@ -833,7 +838,7 @@ client_apply_rule(struct client *c)
if(r->flags & RULE_IGNORE_TAG)
{ /* TODO */ }
c->flags = r->flags | CLIENT_RULED;
c->flags |= CLIENT_RULED;
}
flags = 0;
}
@ -863,7 +868,7 @@ client_new(Window w, XWindowAttributes *wa, bool scan)
c->geo.y = wa->y;
c->geo.w = wa->width;
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;
client_apply_rule(c);
@ -1021,7 +1026,10 @@ client_moveresize(struct client *c, struct geo *g)
if(c->flags & CLIENT_TABBED)
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(client_winsize(c, g))
@ -1099,7 +1107,7 @@ _fac_arrange_row(struct client *c, enum position p, int fac)
struct client *cc;
/* 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))
_fac_apply(cc, p, fac);
}
@ -1115,7 +1123,7 @@ _fac_check_to_reverse(struct client *c)
* resize client because of possible error with next
* clients in linked list.
*/
SLIST_FOREACH(gc, &c->tag->clients, tnext)
FOREACH_NFCLIENT(gc, &c->tag->clients, tnext)
if(gc->flags & CLIENT_FAC_APPLIED
&& 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)
return;
SLIST_FOREACH(cc, &c->tag->clients, tnext)
FOREACH_NFCLIENT(cc, &c->tag->clients, tnext)
cc->ttgeo = cc->tgeo;
if(GEO_CHECK2(c->tgeo, gc->tgeo, p))
@ -1164,17 +1172,17 @@ client_apply_tgeo(struct tag *t)
{
struct client *c;
SLIST_FOREACH(c, &t->clients, tnext)
FOREACH_NFCLIENT(c, &t->clients, tnext)
{
client_moveresize(c, &c->tgeo);
c->flags &= ~CLIENT_FAC_APPLIED;
}
}
#define _REV_BORDER() \
do { \
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);
void
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 */
else
{
SLIST_FOREACH(gc, &c->tag->clients, tnext)
FOREACH_NFCLIENT(gc, &c->tag->clients, tnext)
{
gc->tgeo = gc->geo;
gc->flags &= ~CLIENT_DID_WINSIZE;

View File

@ -13,6 +13,11 @@
#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);
struct client *client_gb_win(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_prev_set", uicb_layout_prev_set },
{ "layout_next_set", uicb_layout_next_set },
{ "layout_toggle_free", uicb_layout_toggle_free },
/* Client */
{ "client_close", uicb_client_close },

View File

@ -23,7 +23,7 @@ layout_save_set(struct tag *t)
l = xcalloc(1, sizeof(struct layout_set));
SLIST_INIT(&l->geos);
SLIST_FOREACH(c, &t->clients, tnext)
FOREACH_NFCLIENT(c, &t->clients, tnext)
{
g = xcalloc(1, sizeof(struct geo_list));
g->geo = c->geo;
@ -49,7 +49,7 @@ layout_apply_set(struct tag *t, struct layout_set *l)
struct client *c;
int nc = 1;
SLIST_FOREACH(c, &t->clients, tnext)
FOREACH_NFCLIENT(c, &t->clients, tnext)
++nc;
/* 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;
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))
&& 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))
{
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))
&& GEO_CHECK_ROW(cc->geo, ghost->geo, p))
{
@ -366,14 +366,16 @@ layout_split_integrate(struct client *c, struct client *sc)
{
struct geo g;
/* No sc */
if(!sc || sc == c || sc->tag != c->tag)
/* No sc or not compatible sc */
if(!sc || sc == c || sc->tag != c->tag
|| sc->flags & CLIENT_FREE)
{
/*
* Not even a first client in list, then
* 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);
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 f2 = 1 / f1;
SLIST_FOREACH(c, &t->clients, tnext)
FOREACH_NFCLIENT(c, &t->clients, tnext)
{
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.. */
SLIST_FOREACH(c, &t->clients, tnext)
FOREACH_NFCLIENT(c, &t->clients, tnext)
layout_fix_hole(c);
layout_save_set(t);
@ -518,7 +520,7 @@ uicb_layout_vmirror(Uicb cmd)
(void)cmd;
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);
client_moveresize(c, &c->geo);
@ -533,7 +535,7 @@ uicb_layout_hmirror(Uicb cmd)
(void)cmd;
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);
client_moveresize(c, &c->geo);
@ -541,3 +543,36 @@ uicb_layout_hmirror(Uicb cmd)
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_arrange_closed(struct client *ghost);
inline void layout_fix_hole(struct client *c);
void layout_client(struct client *c);
void uicb_layout_vmirror(Uicb cmd);
void uicb_layout_hmirror(Uicb cmd);
void uicb_layout_rotate_left(Uicb cmd);
void uicb_layout_rotate_right(Uicb cmd);
void uicb_layout_prev_set(Uicb cmd);
void uicb_layout_next_set(Uicb cmd);
void uicb_layout_toggle_free(Uicb cmd);
#endif /* LAYOUT_H */

View File

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

View File

@ -74,7 +74,7 @@ tag_client(struct tag *t, struct client *c)
if(c->tag == t)
return;
if(!(c->flags & CLIENT_IGNORE_LAYOUT))
if(!(c->flags & (CLIENT_IGNORE_LAYOUT | CLIENT_FREE)))
layout_split_arrange_closed(c);
if(!(c->flags & CLIENT_REMOVEALL))
@ -98,18 +98,11 @@ tag_client(struct tag *t, struct client *c)
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);
infobar_elem_screen_update(t->screen, ElemTag);
if(c->flags & CLIENT_IGNORE_LAYOUT)
c->flags ^= CLIENT_IGNORE_LAYOUT;
else if(!(c->flags & CLIENT_TABBED))
layout_split_integrate(c, t->sel);
layout_client(c);
if(c->flags & CLIENT_TABMASTER && c->prevtag)
{

View File

@ -177,7 +177,7 @@ struct client
struct tag *tag, *prevtag;
struct screen *screen;
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 theme *theme;
struct client *tabmaster;
@ -196,6 +196,7 @@ struct client
#define CLIENT_REMOVEALL 0x200
#define CLIENT_MAPPED 0x400
#define CLIENT_FULLSCREEN 0x800
#define CLIENT_FREE 0x1000
Flags flags;
Window win, frame, tmp;
SLIST_ENTRY(client) next; /* Global list */