Clean up the FillToEdge action implementation
authorDana Jansens <danakj@orodu.net>
Sun, 1 Sep 2013 20:48:39 +0000 (16:48 -0400)
committerDana Jansens <danakj@orodu.net>
Mon, 2 Sep 2013 18:10:37 +0000 (14:10 -0400)
This extend the client_find_resize_directional() method to support
two growing modes, and return a bool for whether it was able to grow/shrink.

The client_find_resize_directional() method now takes an enum instead
of a bool, with two growing modes. The old mode which always tries to
grow, the a new mode that will only grow if the client's edge is not
already at a grow stopping point (ie against the edge of another window).

openbox/actions/growtoedge.c
openbox/client.c
openbox/client.h
openbox/moveresize.c

index 940792f..3a21380 100644 (file)
@@ -11,7 +11,8 @@ typedef struct {
     gboolean fill;
 } Options;
 
-static gpointer setup_func(xmlNodePtr node);
+static gpointer setup_grow_func(xmlNodePtr node);
+static gpointer setup_fill_func(xmlNodePtr node);
 static gpointer setup_shrink_func(xmlNodePtr node);
 static void free_func(gpointer o);
 static gboolean run_func(ObActionsData *data, gpointer options);
@@ -20,11 +21,12 @@ static gpointer setup_north_func(xmlNodePtr node);
 static gpointer setup_south_func(xmlNodePtr node);
 static gpointer setup_east_func(xmlNodePtr node);
 static gpointer setup_west_func(xmlNodePtr node);
-static gpointer setup_fill_func(xmlNodePtr node);
 
 void action_growtoedge_startup(void)
 {
-    actions_register("GrowToEdge", setup_func,
+    actions_register("GrowToEdge", setup_grow_func,
+                     free_func, run_func);
+    actions_register("GrowToFill", setup_fill_func,
                      free_func, run_func);
     actions_register("ShrinkToEdge", setup_shrink_func,
                      free_func, run_func);
@@ -33,7 +35,6 @@ void action_growtoedge_startup(void)
     actions_register("GrowToEdgeSouth", setup_south_func, free_func, run_func);
     actions_register("GrowToEdgeEast", setup_east_func, free_func, run_func);
     actions_register("GrowToEdgeWest", setup_west_func, free_func, run_func);
-    actions_register("GrowToFill", setup_fill_func, free_func, run_func);
 }
 
 static gpointer setup_func(xmlNodePtr node)
@@ -43,8 +44,6 @@ static gpointer setup_func(xmlNodePtr node)
 
     o = g_slice_new0(Options);
     o->dir = OB_DIRECTION_NORTH;
-    o->shrink = FALSE;
-    o->fill = FALSE;
 
     if ((n = obt_xml_find_node(node, "direction"))) {
         gchar *s = obt_xml_node_string(n);
@@ -66,23 +65,35 @@ static gpointer setup_func(xmlNodePtr node)
     return o;
 }
 
+static gpointer setup_grow_func(xmlNodePtr node)
+{
+    Options *o;
+
+    o = setup_func(node);
+    o->shrink = FALSE;
+    o->fill = FALSE;
+
+    return o;
+}
+
 static gpointer setup_fill_func(xmlNodePtr node)
 {
     Options *o;
 
     o = setup_func(node);
+    o->shrink = FALSE;
     o->fill = TRUE;
 
     return o;
 }
 
-
 static gpointer setup_shrink_func(xmlNodePtr node)
 {
     Options *o;
 
     o = setup_func(node);
     o->shrink = TRUE;
+    o->fill = FALSE;
 
     return o;
 }
@@ -123,7 +134,6 @@ static gboolean run_func(ObActionsData *data, gpointer options)
     Options *o = options;
     gint x, y, w, h;
 
-    ObDirection opp;
     gint half;
 
     if (!data->client)
@@ -144,78 +154,57 @@ static gboolean run_func(ObActionsData *data, gpointer options)
             return FALSE;
         }
 
-        gint head, size;
-        gint e_start, e_size;
-        gboolean near;
-
-        gint north_edge;
-        head = RECT_TOP(data->client->frame->area)+1;
-        size = data->client->frame->area.height;
-        e_start = RECT_LEFT(data->client->frame->area);
-        e_size = data->client->frame->area.width;
-
-        client_find_edge_directional(data->client, OB_DIRECTION_NORTH,
-                                     head, size, e_start, e_size,
-                                     &north_edge, &near);
-
-        gint south_edge;
-        head = RECT_BOTTOM(data->client->frame->area)-1;
-        size = data->client->frame->area.height;
-        e_start = RECT_LEFT(data->client->frame->area);
-        e_size = data->client->frame->area.width;
-
-        client_find_edge_directional(data->client, OB_DIRECTION_SOUTH,
-                                     head, size, e_start, e_size,
-                                     &south_edge, &near);
-
-        gint east_edge;
-        head = RECT_RIGHT(data->client->frame->area)-1;
-        size = data->client->frame->area.width;
-        e_start = RECT_TOP(data->client->frame->area);
-        e_size = data->client->frame->area.height;
-
-        client_find_edge_directional(data->client, OB_DIRECTION_EAST,
-                                     head, size, e_start, e_size,
-                                     &east_edge, &near);
-
-        gint west_edge;
-        head = RECT_LEFT(data->client->frame->area)+1;
-        size = data->client->frame->area.width;
-        e_start = RECT_TOP(data->client->frame->area);
-        e_size = data->client->frame->area.height;
-
-        client_find_edge_directional(data->client, OB_DIRECTION_WEST,
-                                     head, size, e_start, e_size,
-                                     &west_edge, &near);
-
-        /* Calculate the client pos and size, based on frame pos and size.
-         */
-
-        gint w_client_delta =
-            data->client->frame->area.width - data->client->area.width;
-        gint h_client_delta =
-            data->client->frame->area.height - data->client->area.height;
-
-        gint x_client_delta =
-            data->client->area.x - data->client->frame->area.x;
-        gint y_client_delta =
-            data->client->area.y - data->client->frame->area.y;
-
-        x = west_edge + x_client_delta + 1;
-        y = north_edge + y_client_delta + 1;
-
-        w = east_edge - west_edge - w_client_delta - 1;
-        h = south_edge - north_edge - h_client_delta - 1;
-
-        /* grow passing client pos and size */
-
-        do_grow(data, x, y, w, h);
+        ObClientDirectionalResizeType grow = CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE;
+
+        gint temp_x;
+        gint temp_y;
+        gint temp_w;
+        gint temp_h;
+
+        client_find_resize_directional(data->client,
+                                       OB_DIRECTION_NORTH,
+                                       grow,
+                                       &temp_x, &temp_y, &temp_w, &temp_h);
+        y = temp_y;
+        h = temp_h;
+
+        client_find_resize_directional(data->client,
+                                       OB_DIRECTION_SOUTH,
+                                       grow,
+                                       &temp_x, &temp_y, &temp_w, &temp_h);
+        h += temp_h - data->client->area.height;
+
+
+        client_find_resize_directional(data->client,
+                                       OB_DIRECTION_WEST,
+                                       grow,
+                                       &temp_x, &temp_y, &temp_w, &temp_h);
+        x = temp_x;
+        w = temp_w;
+
+        client_find_resize_directional(data->client,
+                                       OB_DIRECTION_EAST,
+                                       grow,
+                                       &temp_x, &temp_y, &temp_w, &temp_h);
+        w += temp_w - data->client->area.width;
+
+        /* When filling, we allow the window to move to an arbitrary x/y
+           position, since we'll be growing the other edge as well. */
+        if (x != data->client->area.x || y != data->client->area.y ||
+            w != data->client->area.width || h != data->client->area.height)
+        {
+            actions_client_move(data, TRUE);
+            client_move_resize(data->client, x, y, w, h);
+            actions_client_move(data, FALSE);
+        }
         return FALSE;
     }
 
     if (!o->shrink) {
         /* Try grow. */
-        client_find_resize_directional(data->client, o->dir, TRUE,
+        client_find_resize_directional(data->client,
+                                       o->dir,
+                                       CLIENT_RESIZE_GROW,
                                        &x, &y, &w, &h);
 
         if (do_grow(data, x, y, w, h))
@@ -223,13 +212,16 @@ static gboolean run_func(ObActionsData *data, gpointer options)
     }
 
     /* We couldn't grow, so try shrink! */
-    opp = (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH :
-           (o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH :
-            (o->dir == OB_DIRECTION_EAST ? OB_DIRECTION_WEST :
-             OB_DIRECTION_EAST)));
-    client_find_resize_directional(data->client, opp, FALSE,
+    ObDirection opposite =
+        (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH :
+         (o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH :
+          (o->dir == OB_DIRECTION_EAST ? OB_DIRECTION_WEST :
+           OB_DIRECTION_EAST)));
+    client_find_resize_directional(data->client,
+                                   opposite,
+                                   CLIENT_RESIZE_SHRINK,
                                    &x, &y, &w, &h);
-    switch (opp) {
+    switch (opposite) {
     case OB_DIRECTION_NORTH:
         half = data->client->area.y + data->client->area.height / 2;
         if (y > half) {
index c97abd5..d7389a6 100644 (file)
@@ -4535,40 +4535,97 @@ void client_find_move_directional(ObClient *self, ObDirection dir,
     frame_frame_gravity(self->frame, x, y);
 }
 
-void client_find_resize_directional(ObClient *self, ObDirection side,
-                                    gboolean grow,
-                                    gint *x, gint *y, gint *w, gint *h)
+gboolean client_find_resize_directional(
+    ObClient *self,
+    ObDirection side,
+    ObClientDirectionalResizeType resize_type,
+    gint *x, gint *y, gint *w, gint *h)
 {
     gint head;
     gint e, e_start, e_size, delta;
     gboolean near;
     ObDirection dir;
 
+    gboolean changed = FALSE;
+
+    gboolean grow;
+    switch (resize_type) {
+    case CLIENT_RESIZE_GROW:
+        grow = TRUE;
+        break;
+    case CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE:
+        grow = TRUE;
+        break;
+    case CLIENT_RESIZE_SHRINK:
+        grow = FALSE;
+        break;
+    }
+
     switch (side) {
     case OB_DIRECTION_EAST:
-        head = RECT_RIGHT(self->frame->area) +
-            (self->size_inc.width - 1) * (grow ? 1 : 0);
+        head = RECT_RIGHT(self->frame->area);
+        switch (resize_type) {
+        case CLIENT_RESIZE_GROW:
+            head += self->size_inc.width - 1;
+            break;
+        case CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE:
+            head -= 1;
+            break;
+        case CLIENT_RESIZE_SHRINK:
+            break;
+        }
+
         e_start = RECT_TOP(self->frame->area);
         e_size = self->frame->area.height;
         dir = grow ? OB_DIRECTION_EAST : OB_DIRECTION_WEST;
         break;
     case OB_DIRECTION_WEST:
-        head = RECT_LEFT(self->frame->area) -
-            (self->size_inc.width - 1) * (grow ? 1 : 0);
+        head = RECT_LEFT(self->frame->area);
+        switch (resize_type) {
+        case CLIENT_RESIZE_GROW:
+            head -= self->size_inc.width - 1;
+            break;
+        case CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE:
+            head += 1;
+            break;
+        case CLIENT_RESIZE_SHRINK:
+            break;
+        }
+
         e_start = RECT_TOP(self->frame->area);
         e_size = self->frame->area.height;
         dir = grow ? OB_DIRECTION_WEST : OB_DIRECTION_EAST;
         break;
     case OB_DIRECTION_NORTH:
-        head = RECT_TOP(self->frame->area) -
-            (self->size_inc.height - 1) * (grow ? 1 : 0);
+        head = RECT_TOP(self->frame->area);
+        switch (resize_type) {
+        case CLIENT_RESIZE_GROW:
+            head -= self->size_inc.height - 1;
+            break;
+        case CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE:
+            head += 1;
+            break;
+        case CLIENT_RESIZE_SHRINK:
+            break;
+        }
+
         e_start = RECT_LEFT(self->frame->area);
         e_size = self->frame->area.width;
         dir = grow ? OB_DIRECTION_NORTH : OB_DIRECTION_SOUTH;
         break;
     case OB_DIRECTION_SOUTH:
-        head = RECT_BOTTOM(self->frame->area) +
-            (self->size_inc.height - 1) * (grow ? 1 : 0);
+        head = RECT_BOTTOM(self->frame->area);
+        switch (resize_type) {
+        case CLIENT_RESIZE_GROW:
+            head += self->size_inc.height - 1;
+            break;
+        case CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE:
+            head -= 1;
+            break;
+        case CLIENT_RESIZE_SHRINK:
+            break;
+        }
+
         e_start = RECT_LEFT(self->frame->area);
         e_size = self->frame->area.width;
         dir = grow ? OB_DIRECTION_SOUTH : OB_DIRECTION_NORTH;
@@ -4590,30 +4647,35 @@ void client_find_resize_directional(ObClient *self, ObDirection side,
         if (grow == near) --e;
         delta = e - RECT_RIGHT(self->frame->area);
         *w += delta;
+        changed = delta ? TRUE : changed;
         break;
     case OB_DIRECTION_WEST:
         if (grow == near) ++e;
         delta = RECT_LEFT(self->frame->area) - e;
         *x -= delta;
         *w += delta;
+        changed = delta ? TRUE : changed;
         break;
     case OB_DIRECTION_NORTH:
         if (grow == near) ++e;
         delta = RECT_TOP(self->frame->area) - e;
         *y -= delta;
         *h += delta;
+        changed = delta ? TRUE : changed;
         break;
     case OB_DIRECTION_SOUTH:
         if (grow == near) --e;
         delta = e - RECT_BOTTOM(self->frame->area);
         *h += delta;
-        break;
+        changed = delta ? TRUE : changed;
+       break;
     default:
         g_assert_not_reached();
     }
     frame_frame_gravity(self->frame, x, y);
     *w -= self->frame->size.left + self->frame->size.right;
     *h -= self->frame->size.top + self->frame->size.bottom;
+    return changed;
 }
 
 ObClient* client_under_pointer(void)
index 5ae2d3d..a753b12 100644 (file)
@@ -489,9 +489,21 @@ void client_find_edge_directional(ObClient *self, ObDirection dir,
                                   gint *dest, gboolean *near_edge);
 void client_find_move_directional(ObClient *self, ObDirection dir,
                                   gint *x, gint *y);
-void client_find_resize_directional(ObClient *self, ObDirection side,
-                                    gboolean grow,
-                                    gint *x, gint *y, gint *w, gint *h);
+
+typedef enum {
+    CLIENT_RESIZE_GROW,
+    CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE,
+    CLIENT_RESIZE_SHRINK,
+} ObClientDirectionalResizeType;
+
+/*! Moves the client area passed in to grow/shrink the given edge.
+  @return TRUE if any change was made to the client area.
+*/
+gboolean client_find_resize_directional(
+    ObClient *self,
+    ObDirection side,
+    ObClientDirectionalResizeType resize_type,
+    gint *x, gint *y, gint *w, gint *h);
 
 /*! Fullscreen's or unfullscreen's the client window
   @param fs true if the window should be made fullscreen; false if it should
index 333a1be..d12a64d 100644 (file)
@@ -795,8 +795,13 @@ static void resize_with_keys(KeySym sym, guint state)
         else /* if (sym == XK_Up)) */
             dir = OB_DIRECTION_NORTH;
 
-        client_find_resize_directional(moveresize_client, key_resize_edge,
-                                       key_resize_edge == dir,
+        ObClientDirectionalResizeType resize_type =
+            key_resize_edge == dir ? CLIENT_RESIZE_GROW
+                                   : CLIENT_RESIZE_SHRINK;
+
+        client_find_resize_directional(moveresize_client,
+                                       key_resize_edge,
+                                       resize_type,
                                        &x, &y, &w, &h);
         dw = w - moveresize_client->area.width;
         dh = h - moveresize_client->area.height;