1 #include "openbox/action.h"
2 #include "openbox/action_list_run.h"
3 #include "openbox/action_value.h"
4 #include "openbox/misc.h"
5 #include "openbox/client.h"
6 #include "openbox/client_set.h"
7 #include "openbox/frame.h"
8 #include "openbox/screen.h"
16 static gpointer setup_func(GHashTable *config);
17 static gpointer setup_shrink_func(GHashTable *config);
18 static void free_func(gpointer o);
19 static gboolean run_func(const ObClientSet *set,
20 const ObActionListRun *data, gpointer options);
22 void action_growtoedge_startup(void)
24 action_register("GrowToEdge", OB_ACTION_DEFAULT_FILTER_SINGLE,
25 setup_func, free_func, run_func);
26 action_register("ShrinkToEdge", OB_ACTION_DEFAULT_FILTER_SINGLE,
27 setup_shrink_func, free_func, run_func);
30 static gpointer setup_func(GHashTable *config)
35 o = g_slice_new0(Options);
36 o->dir = OB_DIRECTION_NORTH;
39 v = g_hash_table_lookup(config, "direction");
40 if (v && action_value_is_string(v)) {
41 const gchar *s = action_value_string(v);
42 if (!g_ascii_strcasecmp(s, "north") ||
43 !g_ascii_strcasecmp(s, "up"))
44 o->dir = OB_DIRECTION_NORTH;
45 else if (!g_ascii_strcasecmp(s, "south") ||
46 !g_ascii_strcasecmp(s, "down"))
47 o->dir = OB_DIRECTION_SOUTH;
48 else if (!g_ascii_strcasecmp(s, "west") ||
49 !g_ascii_strcasecmp(s, "left"))
50 o->dir = OB_DIRECTION_WEST;
51 else if (!g_ascii_strcasecmp(s, "east") ||
52 !g_ascii_strcasecmp(s, "right"))
53 o->dir = OB_DIRECTION_EAST;
59 static gpointer setup_shrink_func(GHashTable *config)
63 o = setup_func(config);
69 static gboolean do_grow(const ObActionListRun *data, gint x, gint y, gint w, gint h)
71 gint realw, realh, lw, lh;
75 client_try_configure(data->target, &x, &y, &realw, &realh,
77 /* if it's going to be resized smaller than it intended, don't
78 move the window over */
79 if (x != data->target->area.x) x += w - realw;
80 if (y != data->target->area.y) y += h - realh;
82 if (x != data->target->area.x || y != data->target->area.y ||
83 realw != data->target->area.width ||
84 realh != data->target->area.height)
86 client_move_resize(data->target, x, y, realw, realh);
92 static void free_func(gpointer o)
94 g_slice_free(Options, o);
97 static gboolean each_run(ObClient *c,
98 const ObActionListRun *data, gpointer options)
100 Options *o = options;
106 /* don't allow vertical resize if shaded */
107 ((o->dir == OB_DIRECTION_NORTH || o->dir == OB_DIRECTION_SOUTH) &&
115 client_find_resize_directional(c, o->dir, TRUE, &x, &y, &w, &h);
116 if (do_grow(data, x, y, w, h))
120 /* we couldn't grow, so try shrink! */
121 opp = (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH :
122 (o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH :
123 (o->dir == OB_DIRECTION_EAST ? OB_DIRECTION_WEST :
124 OB_DIRECTION_EAST)));
125 client_find_resize_directional(c, opp, FALSE, &x, &y, &w, &h);
127 case OB_DIRECTION_NORTH:
128 half = c->area.y + c->area.height / 2;
134 case OB_DIRECTION_SOUTH:
135 half = c->area.height / 2;
139 case OB_DIRECTION_WEST:
140 half = c->area.x + c->area.width / 2;
146 case OB_DIRECTION_EAST:
147 half = c->area.width / 2;
151 default: g_assert_not_reached();
153 if (do_grow(data, x, y, w, h))
159 /* Always return FALSE because its not interactive */
160 static gboolean run_func(const ObClientSet *set,
161 const ObActionListRun *data, gpointer options)
163 if (!client_set_is_empty(set)) {
164 action_client_move(data, TRUE);
165 client_set_run(set, data, each_run, options);
166 action_client_move(data, FALSE);