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).
This commit is contained in:
Dana Jansens 2013-09-01 16:48:39 -04:00
parent f757e7449f
commit f5e9df18a4
4 changed files with 162 additions and 91 deletions

View file

@ -11,7 +11,8 @@ typedef struct {
gboolean fill; gboolean fill;
} Options; } 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 gpointer setup_shrink_func(xmlNodePtr node);
static void free_func(gpointer o); static void free_func(gpointer o);
static gboolean run_func(ObActionsData *data, gpointer options); 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_south_func(xmlNodePtr node);
static gpointer setup_east_func(xmlNodePtr node); static gpointer setup_east_func(xmlNodePtr node);
static gpointer setup_west_func(xmlNodePtr node); static gpointer setup_west_func(xmlNodePtr node);
static gpointer setup_fill_func(xmlNodePtr node);
void action_growtoedge_startup(void) 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); free_func, run_func);
actions_register("ShrinkToEdge", setup_shrink_func, actions_register("ShrinkToEdge", setup_shrink_func,
free_func, run_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("GrowToEdgeSouth", setup_south_func, free_func, run_func);
actions_register("GrowToEdgeEast", setup_east_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("GrowToEdgeWest", setup_west_func, free_func, run_func);
actions_register("GrowToFill", setup_fill_func, free_func, run_func);
} }
static gpointer setup_func(xmlNodePtr node) static gpointer setup_func(xmlNodePtr node)
@ -43,8 +44,6 @@ static gpointer setup_func(xmlNodePtr node)
o = g_slice_new0(Options); o = g_slice_new0(Options);
o->dir = OB_DIRECTION_NORTH; o->dir = OB_DIRECTION_NORTH;
o->shrink = FALSE;
o->fill = FALSE;
if ((n = obt_xml_find_node(node, "direction"))) { if ((n = obt_xml_find_node(node, "direction"))) {
gchar *s = obt_xml_node_string(n); gchar *s = obt_xml_node_string(n);
@ -66,23 +65,35 @@ static gpointer setup_func(xmlNodePtr node)
return o; 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) static gpointer setup_fill_func(xmlNodePtr node)
{ {
Options *o; Options *o;
o = setup_func(node); o = setup_func(node);
o->shrink = FALSE;
o->fill = TRUE; o->fill = TRUE;
return o; return o;
} }
static gpointer setup_shrink_func(xmlNodePtr node) static gpointer setup_shrink_func(xmlNodePtr node)
{ {
Options *o; Options *o;
o = setup_func(node); o = setup_func(node);
o->shrink = TRUE; o->shrink = TRUE;
o->fill = FALSE;
return o; return o;
} }
@ -123,7 +134,6 @@ static gboolean run_func(ObActionsData *data, gpointer options)
Options *o = options; Options *o = options;
gint x, y, w, h; gint x, y, w, h;
ObDirection opp;
gint half; gint half;
if (!data->client) if (!data->client)
@ -144,78 +154,57 @@ static gboolean run_func(ObActionsData *data, gpointer options)
return FALSE; return FALSE;
} }
gint head, size; ObClientDirectionalResizeType grow = CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE;
gint e_start, e_size;
gboolean near;
gint north_edge; gint temp_x;
head = RECT_TOP(data->client->frame->area)+1; gint temp_y;
size = data->client->frame->area.height; gint temp_w;
e_start = RECT_LEFT(data->client->frame->area); gint temp_h;
e_size = data->client->frame->area.width;
client_find_edge_directional(data->client, OB_DIRECTION_NORTH, client_find_resize_directional(data->client,
head, size, e_start, e_size, OB_DIRECTION_NORTH,
&north_edge, &near); grow,
&temp_x, &temp_y, &temp_w, &temp_h);
y = temp_y;
h = temp_h;
gint south_edge; client_find_resize_directional(data->client,
head = RECT_BOTTOM(data->client->frame->area)-1; OB_DIRECTION_SOUTH,
size = data->client->frame->area.height; grow,
e_start = RECT_LEFT(data->client->frame->area); &temp_x, &temp_y, &temp_w, &temp_h);
e_size = data->client->frame->area.width; h += temp_h - data->client->area.height;
client_find_edge_directional(data->client, OB_DIRECTION_SOUTH,
head, size, e_start, e_size,
&south_edge, &near);
gint east_edge; client_find_resize_directional(data->client,
head = RECT_RIGHT(data->client->frame->area)-1; OB_DIRECTION_WEST,
size = data->client->frame->area.width; grow,
e_start = RECT_TOP(data->client->frame->area); &temp_x, &temp_y, &temp_w, &temp_h);
e_size = data->client->frame->area.height; x = temp_x;
w = temp_w;
client_find_edge_directional(data->client, OB_DIRECTION_EAST, client_find_resize_directional(data->client,
head, size, e_start, e_size, OB_DIRECTION_EAST,
&east_edge, &near); grow,
&temp_x, &temp_y, &temp_w, &temp_h);
w += temp_w - data->client->area.width;
gint west_edge; /* When filling, we allow the window to move to an arbitrary x/y
head = RECT_LEFT(data->client->frame->area)+1; position, since we'll be growing the other edge as well. */
size = data->client->frame->area.width; if (x != data->client->area.x || y != data->client->area.y ||
e_start = RECT_TOP(data->client->frame->area); w != data->client->area.width || h != data->client->area.height)
e_size = data->client->frame->area.height; {
actions_client_move(data, TRUE);
client_find_edge_directional(data->client, OB_DIRECTION_WEST, client_move_resize(data->client, x, y, w, h);
head, size, e_start, e_size, actions_client_move(data, FALSE);
&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; return FALSE;
} }
if (!o->shrink) { if (!o->shrink) {
/* Try grow. */ /* 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); &x, &y, &w, &h);
if (do_grow(data, 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! */ /* We couldn't grow, so try shrink! */
opp = (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH : ObDirection opposite =
(o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH : (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH :
(o->dir == OB_DIRECTION_EAST ? OB_DIRECTION_WEST : (o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH :
OB_DIRECTION_EAST))); (o->dir == OB_DIRECTION_EAST ? OB_DIRECTION_WEST :
client_find_resize_directional(data->client, opp, FALSE, OB_DIRECTION_EAST)));
client_find_resize_directional(data->client,
opposite,
CLIENT_RESIZE_SHRINK,
&x, &y, &w, &h); &x, &y, &w, &h);
switch (opp) { switch (opposite) {
case OB_DIRECTION_NORTH: case OB_DIRECTION_NORTH:
half = data->client->area.y + data->client->area.height / 2; half = data->client->area.y + data->client->area.height / 2;
if (y > half) { if (y > half) {

View file

@ -4535,40 +4535,97 @@ void client_find_move_directional(ObClient *self, ObDirection dir,
frame_frame_gravity(self->frame, x, y); frame_frame_gravity(self->frame, x, y);
} }
void client_find_resize_directional(ObClient *self, ObDirection side, gboolean client_find_resize_directional(
gboolean grow, ObClient *self,
gint *x, gint *y, gint *w, gint *h) ObDirection side,
ObClientDirectionalResizeType resize_type,
gint *x, gint *y, gint *w, gint *h)
{ {
gint head; gint head;
gint e, e_start, e_size, delta; gint e, e_start, e_size, delta;
gboolean near; gboolean near;
ObDirection dir; 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) { switch (side) {
case OB_DIRECTION_EAST: case OB_DIRECTION_EAST:
head = RECT_RIGHT(self->frame->area) + head = RECT_RIGHT(self->frame->area);
(self->size_inc.width - 1) * (grow ? 1 : 0); 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_start = RECT_TOP(self->frame->area);
e_size = self->frame->area.height; e_size = self->frame->area.height;
dir = grow ? OB_DIRECTION_EAST : OB_DIRECTION_WEST; dir = grow ? OB_DIRECTION_EAST : OB_DIRECTION_WEST;
break; break;
case OB_DIRECTION_WEST: case OB_DIRECTION_WEST:
head = RECT_LEFT(self->frame->area) - head = RECT_LEFT(self->frame->area);
(self->size_inc.width - 1) * (grow ? 1 : 0); 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_start = RECT_TOP(self->frame->area);
e_size = self->frame->area.height; e_size = self->frame->area.height;
dir = grow ? OB_DIRECTION_WEST : OB_DIRECTION_EAST; dir = grow ? OB_DIRECTION_WEST : OB_DIRECTION_EAST;
break; break;
case OB_DIRECTION_NORTH: case OB_DIRECTION_NORTH:
head = RECT_TOP(self->frame->area) - head = RECT_TOP(self->frame->area);
(self->size_inc.height - 1) * (grow ? 1 : 0); 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_start = RECT_LEFT(self->frame->area);
e_size = self->frame->area.width; e_size = self->frame->area.width;
dir = grow ? OB_DIRECTION_NORTH : OB_DIRECTION_SOUTH; dir = grow ? OB_DIRECTION_NORTH : OB_DIRECTION_SOUTH;
break; break;
case OB_DIRECTION_SOUTH: case OB_DIRECTION_SOUTH:
head = RECT_BOTTOM(self->frame->area) + head = RECT_BOTTOM(self->frame->area);
(self->size_inc.height - 1) * (grow ? 1 : 0); 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_start = RECT_LEFT(self->frame->area);
e_size = self->frame->area.width; e_size = self->frame->area.width;
dir = grow ? OB_DIRECTION_SOUTH : OB_DIRECTION_NORTH; 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; if (grow == near) --e;
delta = e - RECT_RIGHT(self->frame->area); delta = e - RECT_RIGHT(self->frame->area);
*w += delta; *w += delta;
changed = delta ? TRUE : changed;
break; break;
case OB_DIRECTION_WEST: case OB_DIRECTION_WEST:
if (grow == near) ++e; if (grow == near) ++e;
delta = RECT_LEFT(self->frame->area) - e; delta = RECT_LEFT(self->frame->area) - e;
*x -= delta; *x -= delta;
*w += delta; *w += delta;
changed = delta ? TRUE : changed;
break; break;
case OB_DIRECTION_NORTH: case OB_DIRECTION_NORTH:
if (grow == near) ++e; if (grow == near) ++e;
delta = RECT_TOP(self->frame->area) - e; delta = RECT_TOP(self->frame->area) - e;
*y -= delta; *y -= delta;
*h += delta; *h += delta;
changed = delta ? TRUE : changed;
break; break;
case OB_DIRECTION_SOUTH: case OB_DIRECTION_SOUTH:
if (grow == near) --e; if (grow == near) --e;
delta = e - RECT_BOTTOM(self->frame->area); delta = e - RECT_BOTTOM(self->frame->area);
*h += delta; *h += delta;
break; changed = delta ? TRUE : changed;
break;
default: default:
g_assert_not_reached(); g_assert_not_reached();
} }
frame_frame_gravity(self->frame, x, y); frame_frame_gravity(self->frame, x, y);
*w -= self->frame->size.left + self->frame->size.right; *w -= self->frame->size.left + self->frame->size.right;
*h -= self->frame->size.top + self->frame->size.bottom; *h -= self->frame->size.top + self->frame->size.bottom;
return changed;
} }
ObClient* client_under_pointer(void) ObClient* client_under_pointer(void)

View file

@ -489,9 +489,21 @@ void client_find_edge_directional(ObClient *self, ObDirection dir,
gint *dest, gboolean *near_edge); gint *dest, gboolean *near_edge);
void client_find_move_directional(ObClient *self, ObDirection dir, void client_find_move_directional(ObClient *self, ObDirection dir,
gint *x, gint *y); gint *x, gint *y);
void client_find_resize_directional(ObClient *self, ObDirection side,
gboolean grow, typedef enum {
gint *x, gint *y, gint *w, gint *h); 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 /*! Fullscreen's or unfullscreen's the client window
@param fs true if the window should be made fullscreen; false if it should @param fs true if the window should be made fullscreen; false if it should

View file

@ -795,8 +795,13 @@ static void resize_with_keys(KeySym sym, guint state)
else /* if (sym == XK_Up)) */ else /* if (sym == XK_Up)) */
dir = OB_DIRECTION_NORTH; dir = OB_DIRECTION_NORTH;
client_find_resize_directional(moveresize_client, key_resize_edge, ObClientDirectionalResizeType resize_type =
key_resize_edge == dir, 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); &x, &y, &w, &h);
dw = w - moveresize_client->area.width; dw = w - moveresize_client->area.width;
dh = h - moveresize_client->area.height; dh = h - moveresize_client->area.height;