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/frame.h"
7 #include "openbox/screen.h"
15 static gpointer setup_func(GHashTable *config);
16 static gpointer setup_shrink_func(GHashTable *config);
17 static void free_func(gpointer o);
18 static gboolean run_func(const ObActionListRun *data, gpointer options);
20 void action_growtoedge_startup(void)
22 action_register("GrowToEdge", OB_ACTION_DEFAULT_FILTER_SINGLE,
23 setup_func, free_func, run_func);
24 action_register("ShrinkToEdge", OB_ACTION_DEFAULT_FILTER_SINGLE,
25 setup_shrink_func, free_func, run_func);
28 static gpointer setup_func(GHashTable *config)
33 o = g_slice_new0(Options);
34 o->dir = OB_DIRECTION_NORTH;
37 v = g_hash_table_lookup(config, "direction");
38 if (v && action_value_is_string(v)) {
39 const gchar *s = action_value_string(v);
40 if (!g_ascii_strcasecmp(s, "north") ||
41 !g_ascii_strcasecmp(s, "up"))
42 o->dir = OB_DIRECTION_NORTH;
43 else if (!g_ascii_strcasecmp(s, "south") ||
44 !g_ascii_strcasecmp(s, "down"))
45 o->dir = OB_DIRECTION_SOUTH;
46 else if (!g_ascii_strcasecmp(s, "west") ||
47 !g_ascii_strcasecmp(s, "left"))
48 o->dir = OB_DIRECTION_WEST;
49 else if (!g_ascii_strcasecmp(s, "east") ||
50 !g_ascii_strcasecmp(s, "right"))
51 o->dir = OB_DIRECTION_EAST;
57 static gpointer setup_shrink_func(GHashTable *config)
61 o = setup_func(config);
67 static gboolean do_grow(const ObActionListRun *data, gint x, gint y, gint w, gint h)
69 gint realw, realh, lw, lh;
73 client_try_configure(data->client, &x, &y, &realw, &realh,
75 /* if it's going to be resized smaller than it intended, don't
76 move the window over */
77 if (x != data->client->area.x) x += w - realw;
78 if (y != data->client->area.y) y += h - realh;
80 if (x != data->client->area.x || y != data->client->area.y ||
81 realw != data->client->area.width ||
82 realh != data->client->area.height)
84 action_client_move(data, TRUE);
85 client_move_resize(data->client, x, y, realw, realh);
86 action_client_move(data, FALSE);
92 static void free_func(gpointer o)
94 g_slice_free(Options, o);
97 /* Always return FALSE because its not interactive */
98 static gboolean run_func(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) &&
108 data->client->shaded))
115 client_find_resize_directional(data->client, o->dir, TRUE,
117 if (do_grow(data, x, y, w, h))
121 /* we couldn't grow, so try shrink! */
122 opp = (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH :
123 (o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH :
124 (o->dir == OB_DIRECTION_EAST ? OB_DIRECTION_WEST :
125 OB_DIRECTION_EAST)));
126 client_find_resize_directional(data->client, opp, FALSE,
129 case OB_DIRECTION_NORTH:
130 half = data->client->area.y + data->client->area.height / 2;
136 case OB_DIRECTION_SOUTH:
137 half = data->client->area.height / 2;
141 case OB_DIRECTION_WEST:
142 half = data->client->area.x + data->client->area.width / 2;
148 case OB_DIRECTION_EAST:
149 half = data->client->area.width / 2;
153 default: g_assert_not_reached();
155 if (do_grow(data, x, y, w, h))