From f5e9df18a46240b4fdaebf540a1052e65507dcfe Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sun, 1 Sep 2013 16:48:39 -0400 Subject: [PATCH] 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 940792f..3a21380 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 c97abd5..d7389a6 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 5ae2d3d..a753b12 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 333a1be..d12a64d 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; -- 1.9.1