1 #include "openbox/action.h"
2 #include "openbox/action_list_run.h"
3 #include "openbox/config_value.h"
4 #include "openbox/client.h"
5 #include "openbox/client_set.h"
6 #include "openbox/screen.h"
7 #include "openbox/frame.h"
8 #include "openbox/config.h"
21 static gpointer setup_func(GHashTable *config);
22 static void free_func(gpointer options);
23 static gboolean run_func(const ObClientSet *set,
24 const ObActionListRun *data, gpointer options);
26 void action_resizerelative_startup(void)
28 action_register("ResizeRelative", OB_ACTION_DEFAULT_FILTER_SINGLE,
29 setup_func, free_func, run_func);
32 static gpointer setup_func(GHashTable *config)
37 o = g_slice_new0(Options);
39 v = g_hash_table_lookup(config, "left");
40 if (v && config_value_is_string(v))
41 config_value_fraction(v, &o->left, &o->left_denom);
42 v = g_hash_table_lookup(config, "right");
43 if (v && config_value_is_string(v))
44 config_value_fraction(v, &o->right, &o->right_denom);
45 v = g_hash_table_lookup(config, "top");
46 if (v && config_value_is_string(v))
47 config_value_fraction(v, &o->top, &o->top_denom);
48 v = g_hash_table_lookup(config, "bottom");
49 if (v && config_value_is_string(v))
50 config_value_fraction(v, &o->bottom, &o->bottom_denom);
55 static void free_func(gpointer o)
57 g_slice_free(Options, o);
60 static gboolean each_run(ObClient *c, const ObActionListRun *data,
64 gint x, y, ow, xoff, nw, oh, yoff, nh, lw, lh;
65 gint left = o->left, right = o->right, top = o->top, bottom = o->bottom;
68 left = left * c->area.width / o->left_denom;
70 right = right * c->area.width / o->right_denom;
72 top = top * c->area.height / o->top_denom;
74 bottom = bottom * c->area.height / o->bottom_denom;
76 // When resizing, if the resize has a non-zero value then make sure it
77 // is at least as big as the size increment so the window does actually
82 xoff = -MAX(left, (left ? c->size_inc.width : 0));
83 nw = ow + MAX(right + left, (right + left ? c->size_inc.width : 0));
85 yoff = -MAX(top, (top ? c->size_inc.height : 0));
86 nh = oh + MAX(bottom + top, (bottom + top ? c->size_inc.height : 0));
88 client_try_configure(c, &x, &y, &nw, &nh, &lw, &lh, TRUE);
89 xoff = xoff == 0 ? 0 :
90 (xoff < 0 ? MAX(xoff, ow-nw) : MIN(xoff, ow-nw));
91 yoff = yoff == 0 ? 0 :
92 (yoff < 0 ? MAX(yoff, oh-nh) : MIN(yoff, oh-nh));
94 client_move_resize(c, x + xoff, y + yoff, nw, nh);
99 /* Always return FALSE because its not interactive */
100 static gboolean run_func(const ObClientSet *set,
101 const ObActionListRun *data, gpointer options)
103 if (!client_set_is_empty(set)) {
104 action_client_move(data, TRUE);
105 client_set_run(set, data, each_run, options);
106 action_client_move(data, FALSE);