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