X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Factions%2Fgrowtoedge.c;h=d5a7bfdd9e8a30c476dcf2203c45aa8f189e3dc3;hb=b7ddaa5728b5449449e3ea14cf84252285bbc794;hp=5d4647f779fa504e18ccdcc98a079aca16cf3388;hpb=055cef6c5ddae81fe8976ad83cfa4d60248c0f49;p=chaz%2Fopenbox diff --git a/openbox/actions/growtoedge.c b/openbox/actions/growtoedge.c index 5d4647f7..d5a7bfdd 100644 --- a/openbox/actions/growtoedge.c +++ b/openbox/actions/growtoedge.c @@ -7,31 +7,43 @@ typedef struct { ObDirection dir; + gboolean shrink; } Options; -static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node); -static void free_func(gpointer options); +static gpointer setup_func(xmlNodePtr node); +static gpointer setup_shrink_func(xmlNodePtr node); +static void free_func(gpointer o); static gboolean run_func(ObActionsData *data, gpointer options); +/* 3.4-compatibility */ +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); -void action_growtoedge_startup() +void action_growtoedge_startup(void) { - actions_register("GrowToEdge", - setup_func, - free_func, - run_func, - NULL, NULL); + actions_register("GrowToEdge", setup_func, + free_func, run_func); + actions_register("ShrinkToEdge", setup_shrink_func, + free_func, run_func); + /* 3.4-compatibility */ + actions_register("GrowToEdgeNorth", setup_north_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("GrowToEdgeWest", setup_west_func, free_func, run_func); } -static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node) +static gpointer setup_func(xmlNodePtr node) { xmlNodePtr n; Options *o; - o = g_new0(Options, 1); + o = g_slice_new0(Options); o->dir = OB_DIRECTION_NORTH; + o->shrink = FALSE; - if ((n = parse_find_node("direction", node))) { - gchar *s = parse_string(doc, n); + if ((n = obt_xml_find_node(node, "direction"))) { + gchar *s = obt_xml_node_string(n); if (!g_ascii_strcasecmp(s, "north") || !g_ascii_strcasecmp(s, "up")) o->dir = OB_DIRECTION_NORTH; @@ -50,87 +62,139 @@ static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node) return o; } -static void free_func(gpointer options) +static gpointer setup_shrink_func(xmlNodePtr node) { - Options *o = options; + Options *o; + + o = setup_func(node); + o->shrink = TRUE; - g_free(o); + return o; +} + +static gboolean do_grow(ObActionsData *data, gint x, gint y, gint w, gint h) +{ + gint realw, realh, lw, lh; + + realw = w; + realh = h; + client_try_configure(data->client, &x, &y, &realw, &realh, + &lw, &lh, TRUE); + /* if it's going to be resized smaller than it intended, don't + move the window over */ + if (x != data->client->area.x) x += w - realw; + if (y != data->client->area.y) y += h - realh; + + if (x != data->client->area.x || y != data->client->area.y || + realw != data->client->area.width || + realh != data->client->area.height) + { + actions_client_move(data, TRUE); + client_move_resize(data->client, x, y, realw, realh); + actions_client_move(data, FALSE); + return TRUE; + } + return FALSE; +} + +static void free_func(gpointer o) +{ + g_slice_free(Options, o); } /* Always return FALSE because its not interactive */ 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)) + { + return FALSE; + } - if (data->client) { - gint x, y, width, height, dest; - ObClient *c = data->client; - Rect *a; - - a = screen_area(c->desktop, SCREEN_AREA_ALL_MONITORS, &c->frame->area); - x = c->frame->area.x; - y = c->frame->area.y; - /* get the unshaded frame's dimensions..if it is shaded */ - width = c->area.width + c->frame->size.left + c->frame->size.right; - height = c->area.height + c->frame->size.top + c->frame->size.bottom; - - switch(o->dir) { - case OB_DIRECTION_NORTH: - if (c->shaded) break; /* don't allow vertical resize if shaded */ - - dest = client_directional_edge_search(c, o->dir, FALSE); - if (a->y == y) - height = height / 2; - else { - height = c->frame->area.y + height - dest; - y = dest; - } - break; - case OB_DIRECTION_WEST: - dest = client_directional_edge_search(c, o->dir, FALSE); - if (a->x == x) - width = width / 2; - else { - width = c->frame->area.x + width - dest; - x = dest; - } - break; - case OB_DIRECTION_SOUTH: - if (c->shaded) break; /* don't allow vertical resize if shaded */ - - dest = client_directional_edge_search(c, o->dir, FALSE); - if (a->y + a->height == y + c->frame->area.height) { - height = c->frame->area.height / 2; - y = a->y + a->height - height; - } else - height = dest - c->frame->area.y; - y += (height - c->frame->area.height) % c->size_inc.height; - height -= (height - c->frame->area.height) % c->size_inc.height; - break; - case OB_DIRECTION_EAST: - dest = client_directional_edge_search(c, o->dir, FALSE); - if (a->x + a->width == x + c->frame->area.width) { - width = c->frame->area.width / 2; - x = a->x + a->width - width; - } else - width = dest - c->frame->area.x; - x += (width - c->frame->area.width) % c->size_inc.width; - width -= (width - c->frame->area.width) % c->size_inc.width; - break; - default: - g_assert_not_reached(); + if (!o->shrink) { + /* 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! */ + 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, + &x, &y, &w, &h); + switch (opp) { + case OB_DIRECTION_NORTH: + half = data->client->area.y + data->client->area.height / 2; + if (y > half) { + h += y - half; + y = half; } + break; + case OB_DIRECTION_SOUTH: + half = data->client->area.height / 2; + if (h < half) + h = half; + break; + case OB_DIRECTION_WEST: + half = data->client->area.x + data->client->area.width / 2; + if (x > half) { + w += x - half; + x = half; + } + break; + case OB_DIRECTION_EAST: + half = data->client->area.width / 2; + if (w < half) + w = half; + break; + default: g_assert_not_reached(); + } + if (do_grow(data, x, y, w, h)) + return FALSE; - width -= c->frame->size.left + c->frame->size.right; - height -= c->frame->size.top + c->frame->size.bottom; - frame_frame_gravity(c->frame, &x, &y); + return FALSE; +} - actions_client_move(data, FALSE); - client_move_resize(c, x, y, width, height); - actions_client_move(data, TRUE); +/* 3.4-compatibility */ +static gpointer setup_north_func(xmlNodePtr node) +{ + Options *o = g_slice_new0(Options); + o->shrink = FALSE; + o->dir = OB_DIRECTION_NORTH; + return o; +} - g_free(a); - } +static gpointer setup_south_func(xmlNodePtr node) +{ + Options *o = g_slice_new0(Options); + o->shrink = FALSE; + o->dir = OB_DIRECTION_SOUTH; + return o; +} - return FALSE; +static gpointer setup_east_func(xmlNodePtr node) +{ + Options *o = g_slice_new0(Options); + o->shrink = FALSE; + o->dir = OB_DIRECTION_EAST; + return o; +} + +static gpointer setup_west_func(xmlNodePtr node) +{ + Options *o = g_slice_new0(Options); + o->shrink = FALSE; + o->dir = OB_DIRECTION_WEST; + return o; }