]> Dogcows Code - chaz/openbox/blob - openbox/actions/resize.c
47f45f5b2de4aadcfb3dbcc88870d67ae86bf701
[chaz/openbox] / openbox / actions / resize.c
1 #include "openbox/actions.h"
2 #include "openbox/moveresize.h"
3 #include "openbox/client.h"
4 #include "openbox/frame.h"
5 #include "obt/prop.h"
6
7 typedef struct {
8 gboolean corner_specified;
9 guint32 corner;
10 } Options;
11
12 static gpointer setup_func(xmlNodePtr node);
13 static gboolean run_func(ObActionsData *data, gpointer options);
14
15 static guint32 pick_corner(gint x, gint y, gint cx, gint cy, gint cw, gint ch,
16 gboolean shaded);
17
18 void action_resize_startup(void)
19 {
20 actions_register("Resize", setup_func, g_free, run_func, NULL, NULL);
21 }
22
23 static gpointer setup_func(xmlNodePtr node)
24 {
25 xmlNodePtr n;
26 Options *o;
27
28 o = g_new0(Options, 1);
29
30 if ((n = obt_parse_find_node(node, "edge"))) {
31 gchar *s = obt_parse_node_string(n);
32
33 o->corner_specified = TRUE;
34 if (!g_ascii_strcasecmp(s, "top"))
35 o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP);
36 else if (!g_ascii_strcasecmp(s, "bottom"))
37 o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM);
38 else if (!g_ascii_strcasecmp(s, "left"))
39 o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT);
40 else if (!g_ascii_strcasecmp(s, "right"))
41 o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT);
42 else if (!g_ascii_strcasecmp(s, "topleft"))
43 o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT);
44 else if (!g_ascii_strcasecmp(s, "topright"))
45 o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT);
46 else if (!g_ascii_strcasecmp(s, "bottomleft"))
47 o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT);
48 else if (!g_ascii_strcasecmp(s, "bottomright"))
49 o->corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT);
50 else
51 o->corner_specified = FALSE;
52
53 g_free(s);
54 }
55 return o;
56 }
57
58 /* Always return FALSE because its not interactive */
59 static gboolean run_func(ObActionsData *data, gpointer options)
60 {
61 Options *o = options;
62
63 if (data->client) {
64 ObClient *c = data->client;
65 guint32 corner;
66
67 if (!data->button)
68 corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD);
69 else if (o->corner_specified)
70 corner = o->corner; /* it was specified in the binding */
71 else
72 corner = pick_corner(data->x, data->y,
73 c->frame->area.x, c->frame->area.y,
74 /* use the client size because the frame
75 can be differently sized (shaded
76 windows) and we want this based on the
77 clients size */
78 c->area.width + c->frame->size.left +
79 c->frame->size.right,
80 c->area.height + c->frame->size.top +
81 c->frame->size.bottom, c->shaded);
82
83 moveresize_start(c, data->x, data->y, data->button, corner);
84 }
85
86 return FALSE;
87 }
88
89 static guint32 pick_corner(gint x, gint y, gint cx, gint cy, gint cw, gint ch,
90 gboolean shaded)
91 {
92 /* let's make x and y client relative instead of screen relative */
93 x = x - cx;
94 y = ch - (y - cy); /* y is inverted, 0 is at the bottom of the window */
95
96 #define X x*ch/cw
97 #define A -4*X + 7*ch/3
98 #define B 4*X -15*ch/9
99 #define C -X/4 + 2*ch/3
100 #define D X/4 + 5*ch/12
101 #define E X/4 + ch/3
102 #define F -X/4 + 7*ch/12
103 #define G 4*X - 4*ch/3
104 #define H -4*X + 8*ch/3
105 #define a (y > 5*ch/9)
106 #define b (x < 4*cw/9)
107 #define c (x > 5*cw/9)
108 #define d (y < 4*ch/9)
109
110 /*
111 Each of these defines (except X which is just there for fun), represents
112 the equation of a line. The lines they represent are shown in the diagram
113 below. Checking y against these lines, we are able to choose a region
114 of the window as shown.
115
116 +---------------------A-------|-------|-------B---------------------+
117 | |A B| |
118 | |A | | B| |
119 | | A B | |
120 | | A | | B | |
121 | | A B | |
122 | | A | | B | |
123 | northwest | A north B | northeast |
124 | | A | | B | |
125 | | A B | |
126 C---------------------+----A--+-------+--B----+---------------------D
127 |CCCCCCC | A B | DDDDDDD|
128 | CCCCCCCC | A | | B | DDDDDDDD |
129 | CCCCCCC A B DDDDDDD |
130 - - - - - - - - - - - +CCCCCCC+aaaaaaa+DDDDDDD+ - - - - - - - - - - - -
131 | | b c | | sh
132 | west | b move c | east | ad
133 | | b c | | ed
134 - - - - - - - - - - - +EEEEEEE+ddddddd+FFFFFFF+- - - - - - - - - - - -
135 | EEEEEEE G H FFFFFFF |
136 | EEEEEEEE | G | | H | FFFFFFFF |
137 |EEEEEEE | G H | FFFFFFF|
138 E---------------------+----G--+-------+--H----+---------------------F
139 | | G H | |
140 | | G | | H | |
141 | southwest | G south H | southeast |
142 | | G | | H | |
143 | | G H | |
144 | | G | | H | |
145 | | G H | |
146 | |G | | H| |
147 | |G H| |
148 +---------------------G-------|-------|-------H---------------------+
149 */
150
151 if (shaded) {
152 /* for shaded windows, you can only resize west/east and move */
153 if (b)
154 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT);
155 if (c)
156 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT);
157 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE);
158 }
159
160 if (y < A && y >= C)
161 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT);
162 else if (y >= A && y >= B && a)
163 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP);
164 else if (y < B && y >= D)
165 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT);
166 else if (y < C && y >= E && b)
167 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT);
168 else if (y < D && y >= F && c)
169 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT);
170 else if (y < E && y >= G)
171 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT);
172 else if (y < G && y < H && d)
173 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM);
174 else if (y >= H && y < F)
175 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT);
176 else
177 return OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE);
178
179 #undef X
180 #undef A
181 #undef B
182 #undef C
183 #undef D
184 #undef E
185 #undef F
186 #undef G
187 #undef H
188 #undef a
189 #undef b
190 #undef c
191 #undef d
192 }
This page took 0.040229 seconds and 4 git commands to generate.