]> icculus.org git repositories - dana/openbox.git/blob - openbox/actions/resizerelative.c
Rename ObActionValue to ObConfigValue. This holds one of three types.
[dana/openbox.git] / openbox / actions / resizerelative.c
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"
9
10 typedef struct {
11     gint left;
12     gint left_denom;
13     gint right;
14     gint right_denom;
15     gint top;
16     gint top_denom;
17     gint bottom;
18     gint bottom_denom;
19 } Options;
20
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);
25
26 void action_resizerelative_startup(void)
27 {
28     action_register("ResizeRelative", OB_ACTION_DEFAULT_FILTER_SINGLE,
29                     setup_func, free_func, run_func);
30 }
31
32 static gpointer setup_func(GHashTable *config)
33 {
34     ObConfigValue *v;
35     Options *o;
36
37     o = g_slice_new0(Options);
38
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);
51
52     return o;
53 }
54
55 static void free_func(gpointer o)
56 {
57     g_slice_free(Options, o);
58 }
59
60 static gboolean each_run(ObClient *c, const ObActionListRun *data,
61                          gpointer options)
62 {
63     Options *o = options;
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;
66
67     if (o->left_denom)
68         left = left * c->area.width / o->left_denom;
69     if (o->right_denom)
70         right = right * c->area.width / o->right_denom;
71     if (o->top_denom)
72         top = top * c->area.height / o->top_denom;
73     if (o->bottom_denom)
74         bottom = bottom * c->area.height / o->bottom_denom;
75
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
78     // resize.
79     x = c->area.x;
80     y = c->area.y;
81     ow = c->area.width;
82     xoff = -MAX(left, (left ? c->size_inc.width : 0));
83     nw = ow + MAX(right + left, (right + left ? c->size_inc.width : 0));
84     oh = c->area.height;
85     yoff = -MAX(top, (top ? c->size_inc.height : 0));
86     nh = oh + MAX(bottom + top, (bottom + top ? c->size_inc.height : 0));
87
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));
93
94     client_move_resize(c, x + xoff, y + yoff, nw, nh);
95
96     return TRUE;
97 }
98
99 /* Always return FALSE because its not interactive */
100 static gboolean run_func(const ObClientSet *set,
101                          const ObActionListRun *data, gpointer options)
102 {
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);
107     }
108     return FALSE;
109 }