diff --git a/src/client.c b/src/client.c index 704e0e8..046fa7e 100644 --- a/src/client.c +++ b/src/client.c @@ -186,38 +186,68 @@ client_next_with_pos(struct client *bc, enum position p) 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 client_swap2(struct client *c1, struct client *c2) { + struct client *c; struct tag *t; + struct geo g; /* Conflict / errors */ if(c1 == c2 || !c1 || !c2) return; - /* are swapped geos compatible? */ - if(client_winsize(c1, &c2->geo) - || client_winsize(c2, &c1->geo)) - return; + /* Reverse FREE/TILED flags if there are different */ + FLAG_SWAP2(c1->flags, c2->flags, CLIENT_FREE); + FLAG_SWAP2(c1->flags, c2->flags, CLIENT_TILED); if(c1->screen != 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) { + c1->flags |= CLIENT_IGNORE_LAYOUT; + c2->flags |= CLIENT_IGNORE_LAYOUT; + t = c1->tag; tag_client(c2->tag, c1); tag_client(t, c2); } - c1->tgeo = c2->geo; - c2->tgeo = c1->geo; + g = c1->geo; + client_moveresize(c1, &c2->geo); + client_moveresize(c2, &g); c1->flags |= CLIENT_IGNORE_ENTER; c2->flags |= CLIENT_IGNORE_ENTER; - - client_moveresize(c1, &c1->tgeo); - client_moveresize(c2, &c2->tgeo); } static inline struct client* @@ -491,7 +521,7 @@ client_tab_focus(struct client *c) void _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 */ if(c->flags & (CLIENT_TABBED | CLIENT_TABMASTER) @@ -505,12 +535,7 @@ _client_tab(struct client *c, struct client *cm) cm->tabmaster = c; if(cm->flags & CLIENT_FREE) - { - /* 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]; - } + swap_int((int*)&m[0], (int*)&m[1]); c->flags |= m[0]; c->flags &= ~m[1]; @@ -597,7 +622,7 @@ client_focus(struct client *c) client_frame_update(c, CCOL(c)); if(c->flags & CLIENT_FREE - && !(c->flags & (CLIENT_FULLSCREEN | CLIENT_TABMASTER))) + && !(c->flags & (CLIENT_FULLSCREEN | CLIENT_TABBED))) XRaiseWindow(W->dpy, c->frame); 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.w = wa->width; 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; if(!scan) @@ -1072,8 +1097,6 @@ client_moveresize(struct client *c, struct geo *g) client_winsize(c, g); } - c->fgeo = c->geo; - /* Real geo regarding full root size */ c->rgeo.x += c->screen->ugeo.x; c->rgeo.y += c->screen->ugeo.y; diff --git a/src/layout.c b/src/layout.c index 5ee1c27..a83311e 100644 --- a/src/layout.c +++ b/src/layout.c @@ -556,9 +556,6 @@ uicb_layout_hmirror(Uicb cmd) void layout_client(struct client *c) { - if(c->flags & CLIENT_TABBED) - c = c->tabmaster; - if(c->flags & CLIENT_IGNORE_LAYOUT) { c->flags ^= CLIENT_IGNORE_LAYOUT; @@ -569,7 +566,7 @@ layout_client(struct client *c) { layout_split_arrange_closed(c); c->flags ^= CLIENT_TILED; - client_moveresize(c, &c->fgeo); + client_moveresize(c, &c->geo); XRaiseWindow(W->dpy, c->frame); } else if(!(c->flags & CLIENT_TABBED)) diff --git a/src/mouse.c b/src/mouse.c index a58aac9..dc3a50d 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -24,6 +24,7 @@ mouse_resize(struct client *c) XEvent ev; Window w; int d, u, ox, oy, ix, iy; + int mx, my; XQueryPointer(W->dpy, W->root, &w, &w, &ox, &oy, &d, &d, (uint *)&u); XGrabServer(W->dpy); @@ -48,16 +49,22 @@ mouse_resize(struct client *c) if(ev.type != MotionNotify) continue; + mx = ev.xmotion.x_root; + my = ev.xmotion.y_root; + if(c->flags & CLIENT_FREE) { _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 - : ev.xmotion.x_root - c->geo.x); - c->geo.h = ((ev.xmotion.y_root - c->geo.y <= (c->sizeh[MINH] + c->tbarw + c->border)) + : mx - c->geo.x); + c->geo.h = ((my - c->geo.y <= (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); @@ -71,18 +78,18 @@ mouse_resize(struct client *c) { _REV_BORDER(); - if(ix >= c->geo.x + (c->geo.w >> 1)) - _fac_resize(c, Right, ev.xmotion.x_root - ox); + if(ix >= c->rgeo.x + (c->geo.w >> 1)) + _fac_resize(c, Right, mx - ox); 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)) - _fac_resize(c, Bottom, ev.xmotion.y_root - oy); + if(iy >= c->rgeo.y + (c->geo.h >> 1)) + _fac_resize(c, Bottom, my - oy); else - _fac_resize(c, Top, oy - ev.xmotion.y_root); + _fac_resize(c, Top, oy - my); - ox = ev.xmotion.x_root; - oy = ev.xmotion.y_root; + ox = mx; + oy = my; _REV_BORDER(); } diff --git a/src/screen.h b/src/screen.h index 16b0dcb..bd9e6ee 100644 --- a/src/screen.h +++ b/src/screen.h @@ -22,22 +22,26 @@ screen_gb_id(int id) } static inline struct screen* -screen_gb_mouse(void) +screen_gb_geo(int x, int y) { 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; int d, x, y; XQueryPointer(W->dpy, W->root, &w, &w, &x, &y, &d, &d, (unsigned int *)&d); - SLIST_FOREACH(s, &W->h.screen, next) - if(INAREA(x, y, s->geo)) - break; - - if(!s) - s = SLIST_FIRST(&W->h.screen); - - return s; + return screen_gb_geo(x, y); } void screen_init(void); diff --git a/src/tag.c b/src/tag.c index d749aa0..3541e9d 100644 --- a/src/tag.c +++ b/src/tag.c @@ -110,7 +110,10 @@ tag_client(struct tag *t, struct client *c) SLIST_FOREACH(cc, &c->prevtag->clients, tnext) if(cc->tabmaster == c) + { + cc->flags |= CLIENT_IGNORE_LAYOUT; tag_client(t, cc); + } } if(t != c->screen->seltag || c->flags & CLIENT_TABBED) diff --git a/src/util.h b/src/util.h index efc13e7..6e794f3 100644 --- a/src/util.h +++ b/src/util.h @@ -63,6 +63,14 @@ swap_ptr(void **x, void **y) *y = t; } +static inline void +swap_int(int *x, int *y) +{ + *y = *x ^ *y; + *x = *y ^ *x; + *y = *x ^ *y; +} + static inline enum position str_to_position(char *str) { diff --git a/src/wmfs.h b/src/wmfs.h index 03742b4..98a5b1b 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -177,7 +177,7 @@ struct client struct tag *tag, *prevtag; struct screen *screen; 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 theme *theme; struct client *tabmaster;