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_grow_func(xmlNodePtr node);
15 static gpointer setup_fill_func(xmlNodePtr node);
16 static gpointer setup_shrink_func(xmlNodePtr node);
17 static void free_func(gpointer o);
18 static gboolean run_func(ObActionsData *data, gpointer options);
19 /* 3.4-compatibility */
20 static gpointer setup_north_func(xmlNodePtr node);
21 static gpointer setup_south_func(xmlNodePtr node);
22 static gpointer setup_east_func(xmlNodePtr node);
23 static gpointer setup_west_func(xmlNodePtr node);
25 void action_growtoedge_startup(void)
27 actions_register("GrowToEdge", setup_grow_func,
29 actions_register("GrowToFill", setup_fill_func,
31 actions_register("ShrinkToEdge", setup_shrink_func,
33 /* 3.4-compatibility */
34 actions_register("GrowToEdgeNorth", setup_north_func, free_func, run_func);
35 actions_register("GrowToEdgeSouth", setup_south_func, free_func, run_func);
36 actions_register("GrowToEdgeEast", setup_east_func, free_func, run_func);
37 actions_register("GrowToEdgeWest", setup_west_func, free_func, run_func);
40 static gpointer setup_func(xmlNodePtr node)
45 o = g_slice_new0(Options);
46 o->dir = OB_DIRECTION_NORTH;
48 if ((n = obt_xml_find_node(node, "direction"))) {
49 gchar *s = obt_xml_node_string(n);
50 if (!g_ascii_strcasecmp(s, "north") ||
51 !g_ascii_strcasecmp(s, "up"))
52 o->dir = OB_DIRECTION_NORTH;
53 else if (!g_ascii_strcasecmp(s, "south") ||
54 !g_ascii_strcasecmp(s, "down"))
55 o->dir = OB_DIRECTION_SOUTH;
56 else if (!g_ascii_strcasecmp(s, "west") ||
57 !g_ascii_strcasecmp(s, "left"))
58 o->dir = OB_DIRECTION_WEST;
59 else if (!g_ascii_strcasecmp(s, "east") ||
60 !g_ascii_strcasecmp(s, "right"))
61 o->dir = OB_DIRECTION_EAST;
68 static gpointer setup_grow_func(xmlNodePtr node)
79 static gpointer setup_fill_func(xmlNodePtr node)
90 static gpointer setup_shrink_func(xmlNodePtr node)
101 static gboolean do_grow(ObActionsData *data, gint x, gint y, gint w, gint h)
103 gint realw, realh, lw, lh;
107 client_try_configure(data->client, &x, &y, &realw, &realh,
109 /* if it's going to be resized smaller than it intended, don't
110 move the window over */
111 if (x != data->client->area.x) x += w - realw;
112 if (y != data->client->area.y) y += h - realh;
114 if (x != data->client->area.x || y != data->client->area.y ||
115 realw != data->client->area.width ||
116 realh != data->client->area.height)
118 actions_client_move(data, TRUE);
119 client_move_resize(data->client, x, y, realw, realh);
120 actions_client_move(data, FALSE);
126 static gboolean do_grow_all_edges(ObActionsData* data,
127 ObClientDirectionalResizeType resize_type)
130 gint temp_x, temp_y, temp_w, temp_h;
132 client_find_resize_directional(data->client,
135 &temp_x, &temp_y, &temp_w, &temp_h);
139 client_find_resize_directional(data->client,
142 &temp_x, &temp_y, &temp_w, &temp_h);
143 h += temp_h - data->client->area.height;
146 client_find_resize_directional(data->client,
149 &temp_x, &temp_y, &temp_w, &temp_h);
153 client_find_resize_directional(data->client,
156 &temp_x, &temp_y, &temp_w, &temp_h);
157 w += temp_w - data->client->area.width;
159 /* When filling, we allow the window to move to an arbitrary x/y
160 position, since we'll be growing the other edge as well. */
162 client_try_configure(data->client, &x, &y, &w, &h, &lw, &lh, TRUE);
164 if (x == data->client->area.x &&
165 y == data->client->area.y &&
166 w == data->client->area.width &&
167 h == data->client->area.height)
172 actions_client_move(data, TRUE);
173 client_move_resize(data->client, x, y, w, h);
174 actions_client_move(data, FALSE);
178 static void free_func(gpointer o)
180 g_slice_free(Options, o);
183 /* Always return FALSE because its not interactive */
184 static gboolean run_func(ObActionsData *data, gpointer options)
186 Options *o = options;
188 if (!data->client || actions_client_locked(data))
193 gboolean doing_vertical_resize =
194 o->dir == OB_DIRECTION_NORTH ||
195 o->dir == OB_DIRECTION_SOUTH ||
197 if (data->client->shaded && doing_vertical_resize)
202 /* We don't have any implementation of shrinking for the FillToGrow
207 if (do_grow_all_edges(data, CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE))
210 /* If all the edges are blocked, then allow them to jump past their
211 current block points. */
212 do_grow_all_edges(data, CLIENT_RESIZE_GROW);
220 client_find_resize_directional(data->client,
225 if (do_grow(data, x, y, w, h))
229 /* We couldn't grow, so try shrink! */
230 ObDirection opposite =
231 (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH :
232 (o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH :
233 (o->dir == OB_DIRECTION_EAST ? OB_DIRECTION_WEST :
234 OB_DIRECTION_EAST)));
239 client_find_resize_directional(data->client,
241 CLIENT_RESIZE_SHRINK,
245 case OB_DIRECTION_NORTH:
246 half = data->client->area.y + data->client->area.height / 2;
252 case OB_DIRECTION_SOUTH:
253 half = data->client->area.height / 2;
257 case OB_DIRECTION_WEST:
258 half = data->client->area.x + data->client->area.width / 2;
264 case OB_DIRECTION_EAST:
265 half = data->client->area.width / 2;
269 default: g_assert_not_reached();
271 if (do_grow(data, x, y, w, h))
277 /* 3.4-compatibility */
278 static gpointer setup_north_func(xmlNodePtr node)
280 Options *o = g_slice_new0(Options);
282 o->dir = OB_DIRECTION_NORTH;
286 static gpointer setup_south_func(xmlNodePtr node)
288 Options *o = g_slice_new0(Options);
290 o->dir = OB_DIRECTION_SOUTH;
294 static gpointer setup_east_func(xmlNodePtr node)
296 Options *o = g_slice_new0(Options);
298 o->dir = OB_DIRECTION_EAST;
302 static gpointer setup_west_func(xmlNodePtr node)
304 Options *o = g_slice_new0(Options);
306 o->dir = OB_DIRECTION_WEST;