From 2c34c10c5f7edaa397e261f1b2361ba04b4858ba Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sun, 1 Sep 2013 15:17:11 -0400 Subject: [PATCH 1/7] Use the BSEARCH() macro in overlap placement Currently the code rolls its own binary search, but now that we have a well-tested binary search implementation in obt/ we can make use of that. --- openbox/place_overlap.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/openbox/place_overlap.c b/openbox/place_overlap.c index ac7255bf0..11e79e5f4 100644 --- a/openbox/place_overlap.c +++ b/openbox/place_overlap.c @@ -19,6 +19,7 @@ #include "config.h" #include "geom.h" #include "place_overlap.h" +#include "obt/bsearch.h" #include @@ -175,24 +176,23 @@ static int total_overlap(const Rect* client_rects, provide a binary search function at all. So, tricky as it is, if we want to avoid linear scan of the edge array, we have to roll our own. */ -static int grid_position(int value, - const int* edges, - int max_edges) +static int find_first_grid_position_greater_or_equal(int search_value, + const int* edges, + int max_edges) { - int low = 0; - int high = max_edges - 1; - int mid = low + (high - low) / 2; - while (low != mid) { - if (value < edges[mid]) - high = mid; - else if (value > edges[mid]) - low = mid; - else /* value == edges[mid] */ - return mid; - mid = low + (high - low) / 2; - } - /* we get here when low == mid. can have low == high or low == high - 1 */ - return (value <= edges[low] ? low : high); + g_assert(max_edges >= 2); + g_assert(search_value >= edges[0]); + g_assert(search_value <= edges[max_edges - 1]); + + BSEARCH_SETUP(); + BSEARCH(int, edges, 0, max_edges, search_value); + + if (BSEARCH_FOUND()) + return BSEARCH_AT(); + + g_assert(BSEARCH_FOUND_NEAREST_SMALLER()); + /* Get the nearest larger instead. */ + return BSEARCH_AT() + 1; } static void expand_width(Rect* r, int by) @@ -263,9 +263,11 @@ static void center_in_field(Point* top_left, { /* Find minimal rectangle. */ int orig_right_edge_index = - grid_position(top_left->x + req_size->width, x_edges, max_edges); + find_first_grid_position_greater_or_equal( + top_left->x + req_size->width, x_edges, max_edges); int orig_bottom_edge_index = - grid_position(top_left->y + req_size->height, y_edges, max_edges); + find_first_grid_position_greater_or_equal( + top_left->y + req_size->height, y_edges, max_edges); ExpandInfo i = { .top_left = top_left, .orig_width = x_edges[orig_right_edge_index] - top_left->x, From 1d665d474c7748cbab3408ed19d0cbc2a347c81e Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sun, 1 Sep 2013 15:24:46 -0400 Subject: [PATCH 2/7] Remove now-incorrect comment --- openbox/place_overlap.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/openbox/place_overlap.c b/openbox/place_overlap.c index 11e79e5f4..3725b24f1 100644 --- a/openbox/place_overlap.c +++ b/openbox/place_overlap.c @@ -171,11 +171,6 @@ static int total_overlap(const Rect* client_rects, return overlap; } -/* Unfortunately, the libc bsearch() function cannot be used to find the - position of a value that is not in the array, and glib doesn't - provide a binary search function at all. So, tricky as it is, if we - want to avoid linear scan of the edge array, we have to roll our - own. */ static int find_first_grid_position_greater_or_equal(int search_value, const int* edges, int max_edges) From 92f649b9f42b9a4b4db8ddb6d154dfec69a76a63 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Sat, 28 Aug 2010 02:21:18 -0300 Subject: [PATCH 3/7] Created a 'GrowToFill' action. (Bug 3356) --- openbox/actions/growtoedge.c | 110 ++++++++++++++++++++++++++++++++--- 1 file changed, 103 insertions(+), 7 deletions(-) diff --git a/openbox/actions/growtoedge.c b/openbox/actions/growtoedge.c index d5a7bfdd9..940792f76 100644 --- a/openbox/actions/growtoedge.c +++ b/openbox/actions/growtoedge.c @@ -8,6 +8,7 @@ typedef struct { ObDirection dir; gboolean shrink; + gboolean fill; } Options; static gpointer setup_func(xmlNodePtr node); @@ -19,6 +20,7 @@ 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) { @@ -31,6 +33,7 @@ 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) @@ -41,6 +44,7 @@ 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); @@ -62,6 +66,17 @@ static gpointer setup_func(xmlNodePtr node) return o; } +static gpointer setup_fill_func(xmlNodePtr node) +{ + Options *o; + + o = setup_func(node); + o->fill = TRUE; + + return o; +} + + static gpointer setup_shrink_func(xmlNodePtr node) { Options *o; @@ -107,26 +122,107 @@ static gboolean run_func(ObActionsData *data, gpointer options) { Options *o = options; gint x, y, w, h; + ObDirection opp; gint half; - if (!data->client || - /* don't allow vertical resize if shaded */ - ((o->dir == OB_DIRECTION_NORTH || o->dir == OB_DIRECTION_SOUTH) && - data->client->shaded)) - { + if (!data->client) + return FALSE; + if (data->client->shaded) { + gboolean doing_verical_resize = + o->dir == OB_DIRECTION_NORTH || + o->dir == OB_DIRECTION_SOUTH || + o->fill; + if (doing_verical_resize) + return FALSE; + } + + if (o->fill) { + if (o->shrink) { + /* We don't have any implementation of shrinking for the FillToGrow + action. */ + 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); return FALSE; } if (!o->shrink) { - /* try grow */ + /* Try grow. */ client_find_resize_directional(data->client, o->dir, TRUE, &x, &y, &w, &h); + if (do_grow(data, x, y, w, h)) return FALSE; } - /* we couldn't grow, so try shrink! */ + /* 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 : From ef0b3b0193ebaa40daf5f6ede442c3f71eea763f Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sun, 1 Sep 2013 16:48:39 -0400 Subject: [PATCH 4/7] Clean up the FillToEdge action implementation 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 | 154 +++++++++++++++++------------------ openbox/client.c | 86 ++++++++++++++++--- openbox/client.h | 18 +++- openbox/moveresize.c | 9 +- 4 files changed, 169 insertions(+), 98 deletions(-) diff --git a/openbox/actions/growtoedge.c b/openbox/actions/growtoedge.c index 940792f76..3a2138066 100644 --- a/openbox/actions/growtoedge.c +++ b/openbox/actions/growtoedge.c @@ -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) { diff --git a/openbox/client.c b/openbox/client.c index c97abd5ac..d7389a65d 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -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) diff --git a/openbox/client.h b/openbox/client.h index 5ae2d3d2f..a753b123b 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -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 diff --git a/openbox/moveresize.c b/openbox/moveresize.c index 333a1bea5..d12a64de5 100644 --- a/openbox/moveresize.c +++ b/openbox/moveresize.c @@ -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; From 59b18a994f252c8f643ed1af1352be3f008128ab Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sun, 1 Sep 2013 17:37:53 -0400 Subject: [PATCH 5/7] Allow FillToEdge to grow when all its edges are blocked. This change points out how useless the return value from client_find_resize_directional() was, so it also removes that. When all edges are blocked, the FillToEdge action will try to grow all four edges agin without blocking any of them on their current edge. This more closely matches the behaviour of the GrowToEdge action. --- openbox/actions/growtoedge.c | 122 ++++++++++++++++++++--------------- openbox/client.c | 16 ++--- openbox/client.h | 13 ++-- 3 files changed, 79 insertions(+), 72 deletions(-) diff --git a/openbox/actions/growtoedge.c b/openbox/actions/growtoedge.c index 3a2138066..fa1b2c7ed 100644 --- a/openbox/actions/growtoedge.c +++ b/openbox/actions/growtoedge.c @@ -123,6 +123,58 @@ static gboolean do_grow(ObActionsData *data, gint x, gint y, gint w, gint h) return FALSE; } +static gboolean do_grow_all_edges(ObActionsData* data, + ObClientDirectionalResizeType resize_type) +{ + gint x, y, w, h; + gint temp_x, temp_y, temp_w, temp_h; + + client_find_resize_directional(data->client, + OB_DIRECTION_NORTH, + resize_type, + &temp_x, &temp_y, &temp_w, &temp_h); + y = temp_y; + h = temp_h; + + client_find_resize_directional(data->client, + OB_DIRECTION_SOUTH, + resize_type, + &temp_x, &temp_y, &temp_w, &temp_h); + h += temp_h - data->client->area.height; + + + client_find_resize_directional(data->client, + OB_DIRECTION_WEST, + resize_type, + &temp_x, &temp_y, &temp_w, &temp_h); + x = temp_x; + w = temp_w; + + client_find_resize_directional(data->client, + OB_DIRECTION_EAST, + resize_type, + &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. */ + int lw, lh; + client_try_configure(data->client, &x, &y, &w, &h, &lw, &lh, TRUE); + + if (x == data->client->area.x && + y == data->client->area.y && + w == data->client->area.width && + h == data->client->area.height) + { + return FALSE; + } + + actions_client_move(data, TRUE); + client_move_resize(data->client, x, y, w, h); + actions_client_move(data, FALSE); + return TRUE; +} + static void free_func(gpointer o) { g_slice_free(Options, o); @@ -132,20 +184,16 @@ static void free_func(gpointer o) static gboolean run_func(ObActionsData *data, gpointer options) { Options *o = options; - gint x, y, w, h; - - gint half; if (!data->client) return FALSE; - if (data->client->shaded) { - gboolean doing_verical_resize = - o->dir == OB_DIRECTION_NORTH || - o->dir == OB_DIRECTION_SOUTH || - o->fill; - if (doing_verical_resize) + + gboolean doing_verical_resize = + o->dir == OB_DIRECTION_NORTH || + o->dir == OB_DIRECTION_SOUTH || + o->fill; + if (data->client->shaded && doing_verical_resize) return FALSE; - } if (o->fill) { if (o->shrink) { @@ -154,53 +202,18 @@ static gboolean run_func(ObActionsData *data, gpointer options) return FALSE; } - 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; + if (do_grow_all_edges(data, CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE)) + return FALSE; - 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); - } + /* If all the edges are blocked, then allow them to jump past their + current block points. */ + do_grow_all_edges(data, CLIENT_RESIZE_GROW); return FALSE; } if (!o->shrink) { + gint x, y, w, h; + /* Try grow. */ client_find_resize_directional(data->client, o->dir, @@ -217,10 +230,15 @@ static gboolean run_func(ObActionsData *data, gpointer options) (o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH : (o->dir == OB_DIRECTION_EAST ? OB_DIRECTION_WEST : OB_DIRECTION_EAST))); + + gint x, y, w, h; + gint half; + client_find_resize_directional(data->client, opposite, CLIENT_RESIZE_SHRINK, &x, &y, &w, &h); + switch (opposite) { case OB_DIRECTION_NORTH: half = data->client->area.y + data->client->area.height / 2; diff --git a/openbox/client.c b/openbox/client.c index d7389a65d..5e6569e0e 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -4535,19 +4535,16 @@ void client_find_move_directional(ObClient *self, ObDirection dir, frame_frame_gravity(self->frame, x, y); } -gboolean client_find_resize_directional( - ObClient *self, - ObDirection side, - ObClientDirectionalResizeType resize_type, - gint *x, gint *y, gint *w, gint *h) +void 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: @@ -4647,27 +4644,23 @@ gboolean client_find_resize_directional( 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; - changed = delta ? TRUE : changed; break; default: g_assert_not_reached(); @@ -4675,7 +4668,6 @@ gboolean client_find_resize_directional( 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) diff --git a/openbox/client.h b/openbox/client.h index a753b123b..11a014000 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -496,14 +496,11 @@ typedef enum { 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); +/*! Moves the client area passed in to grow/shrink the given edge. */ +void 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 From c96dc60341e10225919865aa7dbb9256cddcb8ed Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Sun, 1 Sep 2013 22:45:48 -0300 Subject: [PATCH 6/7] Adding 'once' option to GrowToEdge action. --- data/rc.xsd | 1 + openbox/actions/growtoedge.c | 56 ++++++++++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/data/rc.xsd b/data/rc.xsd index 75dd660e8..7a2318959 100644 --- a/data/rc.xsd +++ b/data/rc.xsd @@ -176,6 +176,7 @@ + diff --git a/openbox/actions/growtoedge.c b/openbox/actions/growtoedge.c index fa1b2c7ed..605dd113e 100644 --- a/openbox/actions/growtoedge.c +++ b/openbox/actions/growtoedge.c @@ -9,6 +9,7 @@ typedef struct { ObDirection dir; gboolean shrink; gboolean fill; + gboolean once; } Options; static gpointer setup_grow_func(xmlNodePtr node); @@ -69,10 +70,15 @@ static gpointer setup_grow_func(xmlNodePtr node) { Options *o; + xmlNodePtr n; + o = setup_func(node); o->shrink = FALSE; o->fill = FALSE; + if ((n = obt_xml_find_node(node, "once"))) + o->once = obt_xml_node_bool(n); + return o; } @@ -80,9 +86,15 @@ static gpointer setup_fill_func(xmlNodePtr node) { Options *o; + xmlNodePtr n; + o = setup_func(node); o->shrink = FALSE; o->fill = TRUE; + o->once = FALSE; + + if ((n = obt_xml_find_node(node, "once"))) + o->once = obt_xml_node_bool(n); return o; } @@ -91,9 +103,15 @@ static gpointer setup_shrink_func(xmlNodePtr node) { Options *o; + xmlNodePtr n; + o = setup_func(node); o->shrink = TRUE; o->fill = FALSE; + o->once = FALSE; + + if ((n = obt_xml_find_node(node, "once"))) + o->once = obt_xml_node_bool(n); return o; } @@ -207,7 +225,10 @@ static gboolean run_func(ObActionsData *data, gpointer options) /* If all the edges are blocked, then allow them to jump past their current block points. */ - do_grow_all_edges(data, CLIENT_RESIZE_GROW); + if (!o->once) { + do_grow_all_edges(data, CLIENT_RESIZE_GROW); + } + return FALSE; } @@ -215,10 +236,17 @@ static gboolean run_func(ObActionsData *data, gpointer options) gint x, y, w, h; /* Try grow. */ - client_find_resize_directional(data->client, + if (o->once) { + client_find_resize_directional(data->client, + o->dir, + CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE, + &x, &y, &w, &h); + } else { + client_find_resize_directional(data->client, o->dir, CLIENT_RESIZE_GROW, &x, &y, &w, &h); + } if (do_grow(data, x, y, w, h)) return FALSE; @@ -278,6 +306,12 @@ static gpointer setup_north_func(xmlNodePtr node) Options *o = g_slice_new0(Options); o->shrink = FALSE; o->dir = OB_DIRECTION_NORTH; + o->once = FALSE; + + xmlNodePtr n; + if ((n = obt_xml_find_node(node, "once"))) + o->once = obt_xml_node_bool(n); + return o; } @@ -286,6 +320,12 @@ static gpointer setup_south_func(xmlNodePtr node) Options *o = g_slice_new0(Options); o->shrink = FALSE; o->dir = OB_DIRECTION_SOUTH; + o->once = FALSE; + + xmlNodePtr n; + if ((n = obt_xml_find_node(node, "once"))) + o->once = obt_xml_node_bool(n); + return o; } @@ -294,6 +334,12 @@ static gpointer setup_east_func(xmlNodePtr node) Options *o = g_slice_new0(Options); o->shrink = FALSE; o->dir = OB_DIRECTION_EAST; + o->once = FALSE; + + xmlNodePtr n; + if ((n = obt_xml_find_node(node, "once"))) + o->once = obt_xml_node_bool(n); + return o; } @@ -302,5 +348,11 @@ static gpointer setup_west_func(xmlNodePtr node) Options *o = g_slice_new0(Options); o->shrink = FALSE; o->dir = OB_DIRECTION_WEST; + o->once = FALSE; + + xmlNodePtr n; + if ((n = obt_xml_find_node(node, "once"))) + o->once = obt_xml_node_bool(n); + return o; } From 7ecec5c5d42dce7a29e00cdfeefecdec86d11778 Mon Sep 17 00:00:00 2001 From: Lucas Augusto Deters Date: Mon, 2 Sep 2013 23:09:18 -0300 Subject: [PATCH 7/7] Code cleanup. --- openbox/actions/growtoedge.c | 44 +++++------------------------------- 1 file changed, 6 insertions(+), 38 deletions(-) diff --git a/openbox/actions/growtoedge.c b/openbox/actions/growtoedge.c index 605dd113e..0fb376062 100644 --- a/openbox/actions/growtoedge.c +++ b/openbox/actions/growtoedge.c @@ -63,6 +63,9 @@ static gpointer setup_func(xmlNodePtr node) g_free(s); } + if ((n = obt_xml_find_node(node, "once"))) + o->once = obt_xml_node_bool(n); + return o; } @@ -70,15 +73,10 @@ static gpointer setup_grow_func(xmlNodePtr node) { Options *o; - xmlNodePtr n; - o = setup_func(node); o->shrink = FALSE; o->fill = FALSE; - if ((n = obt_xml_find_node(node, "once"))) - o->once = obt_xml_node_bool(n); - return o; } @@ -86,15 +84,9 @@ static gpointer setup_fill_func(xmlNodePtr node) { Options *o; - xmlNodePtr n; - o = setup_func(node); o->shrink = FALSE; o->fill = TRUE; - o->once = FALSE; - - if ((n = obt_xml_find_node(node, "once"))) - o->once = obt_xml_node_bool(n); return o; } @@ -103,15 +95,9 @@ static gpointer setup_shrink_func(xmlNodePtr node) { Options *o; - xmlNodePtr n; - o = setup_func(node); o->shrink = TRUE; o->fill = FALSE; - o->once = FALSE; - - if ((n = obt_xml_find_node(node, "once"))) - o->once = obt_xml_node_bool(n); return o; } @@ -225,9 +211,8 @@ static gboolean run_func(ObActionsData *data, gpointer options) /* If all the edges are blocked, then allow them to jump past their current block points. */ - if (!o->once) { + if (!o->once) do_grow_all_edges(data, CLIENT_RESIZE_GROW); - } return FALSE; } @@ -236,17 +221,16 @@ static gboolean run_func(ObActionsData *data, gpointer options) gint x, y, w, h; /* Try grow. */ - if (o->once) { + if (o->once) client_find_resize_directional(data->client, o->dir, CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE, &x, &y, &w, &h); - } else { + else client_find_resize_directional(data->client, o->dir, CLIENT_RESIZE_GROW, &x, &y, &w, &h); - } if (do_grow(data, x, y, w, h)) return FALSE; @@ -308,10 +292,6 @@ static gpointer setup_north_func(xmlNodePtr node) o->dir = OB_DIRECTION_NORTH; o->once = FALSE; - xmlNodePtr n; - if ((n = obt_xml_find_node(node, "once"))) - o->once = obt_xml_node_bool(n); - return o; } @@ -322,10 +302,6 @@ static gpointer setup_south_func(xmlNodePtr node) o->dir = OB_DIRECTION_SOUTH; o->once = FALSE; - xmlNodePtr n; - if ((n = obt_xml_find_node(node, "once"))) - o->once = obt_xml_node_bool(n); - return o; } @@ -336,10 +312,6 @@ static gpointer setup_east_func(xmlNodePtr node) o->dir = OB_DIRECTION_EAST; o->once = FALSE; - xmlNodePtr n; - if ((n = obt_xml_find_node(node, "once"))) - o->once = obt_xml_node_bool(n); - return o; } @@ -350,9 +322,5 @@ static gpointer setup_west_func(xmlNodePtr node) o->dir = OB_DIRECTION_WEST; o->once = FALSE; - xmlNodePtr n; - if ((n = obt_xml_find_node(node, "once"))) - o->once = obt_xml_node_bool(n); - return o; }