Browse Source

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

Martin Duquesnoy 12 years ago
parent
commit
32f8c69a81
7 changed files with 88 additions and 46 deletions
  1. 43 20
      src/client.c
  2. 1 4
      src/layout.c
  3. 19 12
      src/mouse.c
  4. 13 9
      src/screen.h
  5. 3 0
      src/tag.c
  6. 8 0
      src/util.h
  7. 1 1
      src/wmfs.h

+ 43 - 20
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;

+ 1 - 4
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))

+ 19 - 12
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();
           }

+ 13 - 9
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;
-     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;
+               return s;
+
+     return SLIST_FIRST(&W->h.screen);
+}
+
+static inline struct screen*
+screen_gb_mouse(void)
+{
+     Window w;
+     int d, x, y;
 
-     if(!s)
-          s = SLIST_FIRST(&W->h.screen);
+     XQueryPointer(W->dpy, W->root, &w, &w, &x, &y, &d, &d, (unsigned int *)&d);
 
-     return s;
+     return screen_gb_geo(x, y);
 }
 
 void screen_init(void);

+ 3 - 0
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)

+ 8 - 0
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)
 {

+ 1 - 1
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;