Browse Source

Add client size hints support

Martin Duquesnoy 12 years ago
parent
commit
ad5c4101ee
3 changed files with 130 additions and 9 deletions
  1. 103 0
      src/client.c
  2. 14 9
      src/layout.c
  3. 13 0
      src/wmfs.h

+ 103 - 0
src/client.c

@@ -295,6 +295,69 @@ uicb_client_close(Uicb cmd)
           client_close(W->client);
 }
 
+static void
+client_get_sizeh(struct client *c)
+{
+     long msize;
+     XSizeHints size;
+
+     memset(c->sizeh, 0, SHLAST);
+
+     if(!XGetWMNormalHints(W->dpy, c->win, &size, &msize) || !size.flags)
+          size.flags = PSize;
+
+     /* base */
+     if(size.flags & PBaseSize)
+     {
+          c->sizeh[BASEW] = size.base_width;
+          c->sizeh[BASEH] = size.base_height;
+     }
+     else if(size.flags & PMinSize)
+     {
+          c->sizeh[BASEW] = size.min_width;
+          c->sizeh[BASEH] = size.min_height;
+     }
+
+     /* inc */
+     if(size.flags & PResizeInc)
+     {
+          c->sizeh[INCW] = size.width_inc;
+          c->sizeh[INCH] = size.height_inc;
+     }
+
+     /* max */
+     if(size.flags & PMaxSize)
+     {
+          c->sizeh[MAXW] = size.max_width;
+          c->sizeh[MAXH] = size.max_height;
+     }
+
+     /* min */
+     if(size.flags & PMinSize)
+     {
+          c->sizeh[MINW] = (size.min_width ? size.min_width : 1);
+          c->sizeh[MINH] = (size.min_height ? size.min_height: 1);
+     }
+     else if(size.flags & PBaseSize)
+     {
+          c->sizeh[MINW] = (size.base_width ? size.base_width : 1);
+          c->sizeh[MINH] = (size.base_height ? size.base_height : 1);
+     }
+
+     /* aspect */
+     if(size.flags & PAspect)
+     {
+          c->sizeh[MINAX] = size.min_aspect.x;
+          c->sizeh[MAXAX] = size.max_aspect.x;
+          c->sizeh[MINAY] = size.min_aspect.y;
+          c->sizeh[MAXAY] = size.max_aspect.y;
+     }
+
+     if(c->sizeh[MAXW] && c->sizeh[MINW] && c->sizeh[MAXH] && c->sizeh[MINH]
+        && c->sizeh[MAXW] == c->sizeh[MINW] && c->sizeh[MAXH] == c->sizeh[MINH])
+          c->flags |= CLIENT_HINT_FLAG;
+}
+
 struct client*
 client_new(Window w, XWindowAttributes *wa)
 {
@@ -314,6 +377,7 @@ client_new(Window w, XWindowAttributes *wa)
      c->tgeo = c->wgeo = c->geo;
 
      /* Set tag */
+     client_get_sizeh(c);
      tag_client(W->screen->seltag, c);
 
      /* X window attributes */
@@ -335,6 +399,43 @@ client_new(Window w, XWindowAttributes *wa)
      return c;
 }
 
+static void
+client_geo_hints(struct geo *g, int *s)
+{
+     /* base */
+     g->w -= s[BASEW];
+     g->h -= s[BASEH];
+
+     /* aspect */
+     if((s[MINAY] | s[MAXAY] | s[MINAX] | s[MAXAX]) > 0)
+     {
+          if(g->w * s[MAXAY] > g->h * s[MAXAX])
+               g->w = g->h * s[MAXAX] / s[MAXAY];
+          else if(g->w * s[MINAY] < g->h * s[MINAX])
+               g->h = g->w * s[MINAY] / s[MINAX];
+     }
+
+     /* incremental */
+     if(s[INCW])
+          g->w -= g->w % s[INCW];
+     if(s[INCH])
+          g->h -= g->h % s[INCH];
+
+     /* base dimension */
+     g->w += s[BASEW];
+     g->h += s[BASEH];
+
+     if(s[MINW] > 0 && g->w < s[MINW])
+          g->w = s[MINW];
+     if(s[MINH] > 0 && g->h < s[MINH])
+          g->h = s[MINH];
+     if(s[MAXW] > 0 && g->w > s[MAXW])
+          g->w = s[MAXW];
+     if(s[MAXH] > 0 && g->h > s[MAXH])
+          g->h = s[MAXH];
+}
+
+
 void
 client_moveresize(struct client *c, struct geo *g)
 {
@@ -348,6 +449,8 @@ client_moveresize(struct client *c, struct geo *g)
      c->wgeo.w = g->w - (bord << 1);
      c->wgeo.h = g->h - (bord << 1);
 
+     client_geo_hints(&c->wgeo, (int*)c->sizeh);
+
      XMoveResizeWindow(W->dpy, c->win,
                        c->wgeo.x, c->wgeo.y,
                        c->wgeo.w, c->wgeo.h);

+ 14 - 9
src/layout.c

@@ -93,6 +93,15 @@ layout_split_check_row_dir(struct client *c, struct client *g, enum position p)
  *            '-.__     _.'  ~
  *                 `````   ~
  */
+#define _ARRANGE_SINGLE_PARENT(p)                                 \
+     do {                                                         \
+          if((c = client_next_with_pos(ghost, p)))                \
+               if(GEO_CHECK2(ghost->geo, c->geo, p))              \
+               {                                                  \
+                    layout_split_arrange_size(&ghost->geo, c, p); \
+                    return;                                       \
+               }                                                  \
+     } while(/* CONSTCOND */ 0);
 void
 layout_split_arrange_closed(struct client *ghost)
 {
@@ -110,15 +119,11 @@ layout_split_arrange_closed(struct client *ghost)
       * |     |  C  | ->   C   -> |     |v v v|
       * |_____|_____| ->       -> |_____|_____|
       */
-     for(p = Right; p < Center; ++p)  /* Check every direction */
-     {
-          if((c = client_next_with_pos(ghost, p)))
-               if(GEO_CHECK2(ghost->geo, c->geo, p))
-               {
-                    layout_split_arrange_size(&ghost->geo, c, p);
-                    return;
-               }
-     }
+     _ARRANGE_SINGLE_PARENT(Right);
+     _ARRANGE_SINGLE_PARENT(Left);
+     _ARRANGE_SINGLE_PARENT(Top);
+     _ARRANGE_SINGLE_PARENT(Bottom);
+
 
      /* Check row parents for full resize
       * Example case:

+ 13 - 0
src/wmfs.h

@@ -49,6 +49,17 @@ enum position
      PositionLast
 };
 
+enum size_hints
+{
+     BASEW, BASEH,
+     INCW,  INCH,
+     MAXW,  MAXH,
+     MINW,  MINH,
+     MINAX, MINAY,
+     MAXAX, MAXAY,
+     SHLAST
+};
+
 /*
  * Structures
  */
@@ -122,7 +133,9 @@ struct client
      struct screen *screen;
      struct barwin *titlebar;
      struct geo geo, tgeo, wgeo;
+     int sizeh[SHLAST];
      char *title;
+#define CLIENT_HINT_FLAG 0x01
      Flags flags;
      Window win;
      SLIST_ENTRY(client) next;  /* Global list */