Finalize client free mode with multi-screen, mouse and swap

This commit is contained in:
Martin Duquesnoy 2012-01-28 21:34:39 +01:00
parent 2ac4d8ffd0
commit 32f8c69a81
7 changed files with 88 additions and 46 deletions

View File

@ -186,38 +186,68 @@ client_next_with_pos(struct client *bc, enum position p)
return c; return c;
} }
#define FLAG_SWAP2(f1, f2, m1) \
if((f1 & m1) != (f2 & m1)) \
{ \
f1 ^= m1; \
f2 ^= m1; \
}
#define SWAP_ARRANGE_TAB(C) \
SLIST_FOREACH(c, &C->tag->clients, tnext) \
{ \
if(c->tabmaster == C) \
{ \
c->screen = C->screen; \
if((C->flags & CLIENT_FREE) != (c->flags & CLIENT_FREE)) \
{ \
c->flags ^= CLIENT_FREE; \
c->flags ^= CLIENT_TILED; \
} \
} \
}
void void
client_swap2(struct client *c1, struct client *c2) client_swap2(struct client *c1, struct client *c2)
{ {
struct client *c;
struct tag *t; struct tag *t;
struct geo g;
/* Conflict / errors */ /* Conflict / errors */
if(c1 == c2 || !c1 || !c2) if(c1 == c2 || !c1 || !c2)
return; return;
/* are swapped geos compatible? */ /* Reverse FREE/TILED flags if there are different */
if(client_winsize(c1, &c2->geo) FLAG_SWAP2(c1->flags, c2->flags, CLIENT_FREE);
|| client_winsize(c2, &c1->geo)) FLAG_SWAP2(c1->flags, c2->flags, CLIENT_TILED);
return;
if(c1->screen != c2->screen) if(c1->screen != c2->screen)
swap_ptr((void**)&c1->screen, (void**)&c2->screen); swap_ptr((void**)&c1->screen, (void**)&c2->screen);
/*
* Arrange flags for all tabbed client of
* possible c1/c2 tabmaster
*/
if(c1->flags & CLIENT_TABMASTER)
SWAP_ARRANGE_TAB(c1);
if(c2->flags & CLIENT_TABMASTER)
SWAP_ARRANGE_TAB(c2);
if(c1->tag != c2->tag) if(c1->tag != c2->tag)
{ {
c1->flags |= CLIENT_IGNORE_LAYOUT;
c2->flags |= CLIENT_IGNORE_LAYOUT;
t = c1->tag; t = c1->tag;
tag_client(c2->tag, c1); tag_client(c2->tag, c1);
tag_client(t, c2); tag_client(t, c2);
} }
c1->tgeo = c2->geo; g = c1->geo;
c2->tgeo = c1->geo; client_moveresize(c1, &c2->geo);
client_moveresize(c2, &g);
c1->flags |= CLIENT_IGNORE_ENTER; c1->flags |= CLIENT_IGNORE_ENTER;
c2->flags |= CLIENT_IGNORE_ENTER; c2->flags |= CLIENT_IGNORE_ENTER;
client_moveresize(c1, &c1->tgeo);
client_moveresize(c2, &c2->tgeo);
} }
static inline struct client* static inline struct client*
@ -491,7 +521,7 @@ client_tab_focus(struct client *c)
void void
_client_tab(struct client *c, struct client *cm) _client_tab(struct client *c, struct client *cm)
{ {
long m[2] = { CLIENT_TILED, CLIENT_FREE }; Flags m[2] = { CLIENT_TILED, CLIENT_FREE };
/* Do not tab already tabbed client */ /* Do not tab already tabbed client */
if(c->flags & (CLIENT_TABBED | CLIENT_TABMASTER) if(c->flags & (CLIENT_TABBED | CLIENT_TABMASTER)
@ -505,12 +535,7 @@ _client_tab(struct client *c, struct client *cm)
cm->tabmaster = c; cm->tabmaster = c;
if(cm->flags & CLIENT_FREE) if(cm->flags & CLIENT_FREE)
{ swap_int((int*)&m[0], (int*)&m[1]);
/* Swap masks to add/del from cm->flags */
m[1] = m[0] ^ m[1];
m[0] = m[1] ^ m[0];
m[1] = m[0] ^ m[1];
}
c->flags |= m[0]; c->flags |= m[0];
c->flags &= ~m[1]; c->flags &= ~m[1];
@ -597,7 +622,7 @@ client_focus(struct client *c)
client_frame_update(c, CCOL(c)); client_frame_update(c, CCOL(c));
if(c->flags & CLIENT_FREE if(c->flags & CLIENT_FREE
&& !(c->flags & (CLIENT_FULLSCREEN | CLIENT_TABMASTER))) && !(c->flags & (CLIENT_FULLSCREEN | CLIENT_TABBED)))
XRaiseWindow(W->dpy, c->frame); XRaiseWindow(W->dpy, c->frame);
XSetInputFocus(W->dpy, c->win, RevertToPointerRoot, CurrentTime); XSetInputFocus(W->dpy, c->win, RevertToPointerRoot, CurrentTime);
@ -891,7 +916,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->fgeo = c->geo; c->tgeo = c->wgeo = c->rgeo = c->geo;
c->tbgeo = NULL; c->tbgeo = NULL;
if(!scan) if(!scan)
@ -1072,8 +1097,6 @@ client_moveresize(struct client *c, struct geo *g)
client_winsize(c, g); client_winsize(c, g);
} }
c->fgeo = c->geo;
/* Real geo regarding full root size */ /* Real geo regarding full root size */
c->rgeo.x += c->screen->ugeo.x; c->rgeo.x += c->screen->ugeo.x;
c->rgeo.y += c->screen->ugeo.y; c->rgeo.y += c->screen->ugeo.y;

View File

@ -556,9 +556,6 @@ uicb_layout_hmirror(Uicb cmd)
void void
layout_client(struct client *c) layout_client(struct client *c)
{ {
if(c->flags & CLIENT_TABBED)
c = c->tabmaster;
if(c->flags & CLIENT_IGNORE_LAYOUT) if(c->flags & CLIENT_IGNORE_LAYOUT)
{ {
c->flags ^= CLIENT_IGNORE_LAYOUT; c->flags ^= CLIENT_IGNORE_LAYOUT;
@ -569,7 +566,7 @@ layout_client(struct client *c)
{ {
layout_split_arrange_closed(c); layout_split_arrange_closed(c);
c->flags ^= CLIENT_TILED; c->flags ^= CLIENT_TILED;
client_moveresize(c, &c->fgeo); client_moveresize(c, &c->geo);
XRaiseWindow(W->dpy, c->frame); XRaiseWindow(W->dpy, c->frame);
} }
else if(!(c->flags & CLIENT_TABBED)) else if(!(c->flags & CLIENT_TABBED))

View File

@ -24,6 +24,7 @@ mouse_resize(struct client *c)
XEvent ev; XEvent ev;
Window w; Window w;
int d, u, ox, oy, ix, iy; int d, u, ox, oy, ix, iy;
int mx, my;
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);
@ -48,16 +49,22 @@ mouse_resize(struct client *c)
if(ev.type != MotionNotify) if(ev.type != MotionNotify)
continue; continue;
mx = ev.xmotion.x_root;
my = ev.xmotion.y_root;
if(c->flags & CLIENT_FREE) if(c->flags & CLIENT_FREE)
{ {
_REV_SBORDER(c); _REV_SBORDER(c);
c->geo.w = ((ev.xmotion.x_root - c->geo.x <= c->sizeh[MINW] + c->border + c->border) mx -= c->screen->ugeo.x;
my -= c->screen->ugeo.y;
c->geo.w = ((mx - c->geo.x <= c->sizeh[MINW] + c->border + c->border)
? c->sizeh[MINW] + c->border + c->border ? c->sizeh[MINW] + c->border + c->border
: ev.xmotion.x_root - c->geo.x); : mx - c->geo.x);
c->geo.h = ((ev.xmotion.y_root - c->geo.y <= (c->sizeh[MINH] + c->tbarw + c->border)) c->geo.h = ((my - c->geo.y <= (c->sizeh[MINH] + c->tbarw + c->border))
? c->sizeh[MINH] + c->tbarw + c->border ? c->sizeh[MINH] + c->tbarw + c->border
: ev.xmotion.y_root - c->geo.y); : my - c->geo.y);
client_geo_hints(&c->geo, (int*)c->sizeh); client_geo_hints(&c->geo, (int*)c->sizeh);
@ -71,18 +78,18 @@ mouse_resize(struct client *c)
{ {
_REV_BORDER(); _REV_BORDER();
if(ix >= c->geo.x + (c->geo.w >> 1)) if(ix >= c->rgeo.x + (c->geo.w >> 1))
_fac_resize(c, Right, ev.xmotion.x_root - ox); _fac_resize(c, Right, mx - ox);
else else
_fac_resize(c, Left, ox - ev.xmotion.x_root); _fac_resize(c, Left, ox - mx);
if(iy >= c->geo.y + (c->geo.h >> 1)) if(iy >= c->rgeo.y + (c->geo.h >> 1))
_fac_resize(c, Bottom, ev.xmotion.y_root - oy); _fac_resize(c, Bottom, my - oy);
else else
_fac_resize(c, Top, oy - ev.xmotion.y_root); _fac_resize(c, Top, oy - my);
ox = ev.xmotion.x_root; ox = mx;
oy = ev.xmotion.y_root; oy = my;
_REV_BORDER(); _REV_BORDER();
} }

View File

@ -22,22 +22,26 @@ screen_gb_id(int id)
} }
static inline struct screen* static inline struct screen*
screen_gb_mouse(void) screen_gb_geo(int x, int y)
{ {
struct screen *s; struct screen *s;
SLIST_FOREACH(s, &W->h.screen, next)
if(INAREA(x, y, s->geo))
return s;
return SLIST_FIRST(&W->h.screen);
}
static inline struct screen*
screen_gb_mouse(void)
{
Window w; Window w;
int d, x, y; int d, x, y;
XQueryPointer(W->dpy, W->root, &w, &w, &x, &y, &d, &d, (unsigned int *)&d); XQueryPointer(W->dpy, W->root, &w, &w, &x, &y, &d, &d, (unsigned int *)&d);
SLIST_FOREACH(s, &W->h.screen, next) return screen_gb_geo(x, y);
if(INAREA(x, y, s->geo))
break;
if(!s)
s = SLIST_FIRST(&W->h.screen);
return s;
} }
void screen_init(void); void screen_init(void);

View File

@ -110,8 +110,11 @@ tag_client(struct tag *t, struct client *c)
SLIST_FOREACH(cc, &c->prevtag->clients, tnext) SLIST_FOREACH(cc, &c->prevtag->clients, tnext)
if(cc->tabmaster == c) if(cc->tabmaster == c)
{
cc->flags |= CLIENT_IGNORE_LAYOUT;
tag_client(t, cc); tag_client(t, cc);
} }
}
if(t != c->screen->seltag || c->flags & CLIENT_TABBED) if(t != c->screen->seltag || c->flags & CLIENT_TABBED)
client_unmap(c); client_unmap(c);

View File

@ -63,6 +63,14 @@ swap_ptr(void **x, void **y)
*y = t; *y = t;
} }
static inline void
swap_int(int *x, int *y)
{
*y = *x ^ *y;
*x = *y ^ *x;
*y = *x ^ *y;
}
static inline enum position static inline enum position
str_to_position(char *str) str_to_position(char *str)
{ {

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, fgeo; struct geo geo, wgeo, tgeo, ttgeo, rgeo, *tbgeo;
struct colpair ncol, scol; struct colpair ncol, scol;
struct theme *theme; struct theme *theme;
struct client *tabmaster; struct client *tabmaster;