1 #include "openbox/actions.h"
2 #include "openbox/misc.h"
3 #include "openbox/client.h"
4 #include "openbox/frame.h"
5 #include "openbox/screen.h"
14 static gpointer setup_func(xmlNodePtr node);
15 static gpointer setup_shrink_func(xmlNodePtr node);
16 static void free_func(gpointer o);
17 static gboolean run_func(ObActionsData *data, gpointer options);
18 /* 3.4-compatibility */
19 static gpointer setup_north_func(xmlNodePtr node);
20 static gpointer setup_south_func(xmlNodePtr node);
21 static gpointer setup_east_func(xmlNodePtr node);
22 static gpointer setup_west_func(xmlNodePtr node);
23 static gpointer setup_fill_func(xmlNodePtr node);
25 void action_growtoedge_startup(void)
27 actions_register("GrowToEdge", setup_func,
29 actions_register("ShrinkToEdge", setup_shrink_func,
31 /* 3.4-compatibility */
32 actions_register("GrowToEdgeNorth", setup_north_func, free_func, run_func);
33 actions_register("GrowToEdgeSouth", setup_south_func, free_func, run_func);
34 actions_register("GrowToEdgeEast", setup_east_func, free_func, run_func);
35 actions_register("GrowToEdgeWest", setup_west_func, free_func, run_func);
36 actions_register("GrowToFill", setup_fill_func, free_func, run_func);
39 static gpointer setup_func(xmlNodePtr node)
44 o = g_slice_new0(Options);
45 o->dir = OB_DIRECTION_NORTH;
49 if ((n = obt_xml_find_node(node, "direction"))) {
50 gchar *s = obt_xml_node_string(n);
51 if (!g_ascii_strcasecmp(s, "north") ||
52 !g_ascii_strcasecmp(s, "up"))
53 o->dir = OB_DIRECTION_NORTH;
54 else if (!g_ascii_strcasecmp(s, "south") ||
55 !g_ascii_strcasecmp(s, "down"))
56 o->dir = OB_DIRECTION_SOUTH;
57 else if (!g_ascii_strcasecmp(s, "west") ||
58 !g_ascii_strcasecmp(s, "left"))
59 o->dir = OB_DIRECTION_WEST;
60 else if (!g_ascii_strcasecmp(s, "east") ||
61 !g_ascii_strcasecmp(s, "right"))
62 o->dir = OB_DIRECTION_EAST;
69 static gpointer setup_fill_func(xmlNodePtr node)
80 static gpointer setup_shrink_func(xmlNodePtr node)
90 static gboolean do_grow(ObActionsData *data, gint x, gint y, gint w, gint h)
92 gint realw, realh, lw, lh;
96 client_try_configure(data->client, &x, &y, &realw, &realh,
98 /* if it's going to be resized smaller than it intended, don't
99 move the window over */
100 if (x != data->client->area.x) x += w - realw;
101 if (y != data->client->area.y) y += h - realh;
103 if (x != data->client->area.x || y != data->client->area.y ||
104 realw != data->client->area.width ||
105 realh != data->client->area.height)
107 actions_client_move(data, TRUE);
108 client_move_resize(data->client, x, y, realw, realh);
109 actions_client_move(data, FALSE);
115 static void free_func(gpointer o)
117 g_slice_free(Options, o);
120 /* Always return FALSE because its not interactive */
121 static gboolean run_func(ObActionsData *data, gpointer options)
123 Options *o = options;
131 if (data->client->shaded) {
132 gboolean doing_verical_resize =
133 o->dir == OB_DIRECTION_NORTH ||
134 o->dir == OB_DIRECTION_SOUTH ||
136 if (doing_verical_resize)
142 /* We don't have any implementation of shrinking for the FillToGrow
148 gint e_start, e_size;
152 head = RECT_TOP(data->client->frame->area)+1;
153 size = data->client->frame->area.height;
154 e_start = RECT_LEFT(data->client->frame->area);
155 e_size = data->client->frame->area.width;
157 client_find_edge_directional(data->client, OB_DIRECTION_NORTH,
158 head, size, e_start, e_size,
162 head = RECT_BOTTOM(data->client->frame->area)-1;
163 size = data->client->frame->area.height;
164 e_start = RECT_LEFT(data->client->frame->area);
165 e_size = data->client->frame->area.width;
167 client_find_edge_directional(data->client, OB_DIRECTION_SOUTH,
168 head, size, e_start, e_size,
172 head = RECT_RIGHT(data->client->frame->area)-1;
173 size = data->client->frame->area.width;
174 e_start = RECT_TOP(data->client->frame->area);
175 e_size = data->client->frame->area.height;
177 client_find_edge_directional(data->client, OB_DIRECTION_EAST,
178 head, size, e_start, e_size,
182 head = RECT_LEFT(data->client->frame->area)+1;
183 size = data->client->frame->area.width;
184 e_start = RECT_TOP(data->client->frame->area);
185 e_size = data->client->frame->area.height;
187 client_find_edge_directional(data->client, OB_DIRECTION_WEST,
188 head, size, e_start, e_size,
191 /* Calculate the client pos and size, based on frame pos and size.
194 gint w_client_delta =
195 data->client->frame->area.width - data->client->area.width;
196 gint h_client_delta =
197 data->client->frame->area.height - data->client->area.height;
199 gint x_client_delta =
200 data->client->area.x - data->client->frame->area.x;
201 gint y_client_delta =
202 data->client->area.y - data->client->frame->area.y;
204 x = west_edge + x_client_delta + 1;
205 y = north_edge + y_client_delta + 1;
207 w = east_edge - west_edge - w_client_delta - 1;
208 h = south_edge - north_edge - h_client_delta - 1;
210 /* grow passing client pos and size */
212 do_grow(data, x, y, w, h);
218 client_find_resize_directional(data->client, o->dir, TRUE,
221 if (do_grow(data, x, y, w, h))
225 /* We couldn't grow, so try shrink! */
226 opp = (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH :
227 (o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH :
228 (o->dir == OB_DIRECTION_EAST ? OB_DIRECTION_WEST :
229 OB_DIRECTION_EAST)));
230 client_find_resize_directional(data->client, opp, FALSE,
233 case OB_DIRECTION_NORTH:
234 half = data->client->area.y + data->client->area.height / 2;
240 case OB_DIRECTION_SOUTH:
241 half = data->client->area.height / 2;
245 case OB_DIRECTION_WEST:
246 half = data->client->area.x + data->client->area.width / 2;
252 case OB_DIRECTION_EAST:
253 half = data->client->area.width / 2;
257 default: g_assert_not_reached();
259 if (do_grow(data, x, y, w, h))
265 /* 3.4-compatibility */
266 static gpointer setup_north_func(xmlNodePtr node)
268 Options *o = g_slice_new0(Options);
270 o->dir = OB_DIRECTION_NORTH;
274 static gpointer setup_south_func(xmlNodePtr node)
276 Options *o = g_slice_new0(Options);
278 o->dir = OB_DIRECTION_SOUTH;
282 static gpointer setup_east_func(xmlNodePtr node)
284 Options *o = g_slice_new0(Options);
286 o->dir = OB_DIRECTION_EAST;
290 static gpointer setup_west_func(xmlNodePtr node)
292 Options *o = g_slice_new0(Options);
294 o->dir = OB_DIRECTION_WEST;