]> Dogcows Code - chaz/openbox/blob - openbox/actions/directionalwindows.c
Merge branch 'backport' into work
[chaz/openbox] / openbox / actions / directionalwindows.c
1 #include "openbox/actions.h"
2 #include "openbox/event.h"
3 #include "openbox/stacking.h"
4 #include "openbox/window.h"
5 #include "openbox/focus_cycle.h"
6 #include "openbox/openbox.h"
7 #include "openbox/misc.h"
8 #include "gettext.h"
9
10 typedef struct {
11 gboolean interactive;
12 gboolean dialog;
13 gboolean dock_windows;
14 gboolean desktop_windows;
15 ObDirection direction;
16 gboolean bar;
17 gboolean raise;
18 GSList *actions;
19 } Options;
20
21 static gboolean cycling = FALSE;
22
23 static gpointer setup_func(xmlNodePtr node);
24 static gpointer setup_cycle_func(xmlNodePtr node);
25 static gpointer setup_target_func(xmlNodePtr node);
26 static void free_func(gpointer options);
27 static gboolean run_func(ObActionsData *data, gpointer options);
28 static gboolean i_input_func(guint initial_state,
29 XEvent *e,
30 gpointer options,
31 gboolean *used);
32 static void i_cancel_func(gpointer options);
33
34 static void end_cycle(gboolean cancel, guint state, Options *o);
35
36 /* 3.4-compatibility */
37 static gpointer setup_north_cycle_func(xmlNodePtr node);
38 static gpointer setup_south_cycle_func(xmlNodePtr node);
39 static gpointer setup_east_cycle_func(xmlNodePtr node);
40 static gpointer setup_west_cycle_func(xmlNodePtr node);
41 static gpointer setup_northwest_cycle_func(xmlNodePtr node);
42 static gpointer setup_northeast_cycle_func(xmlNodePtr node);
43 static gpointer setup_southwest_cycle_func(xmlNodePtr node);
44 static gpointer setup_southeast_cycle_func(xmlNodePtr node);
45 static gpointer setup_north_target_func(xmlNodePtr node);
46 static gpointer setup_south_target_func(xmlNodePtr node);
47 static gpointer setup_east_target_func(xmlNodePtr node);
48 static gpointer setup_west_target_func(xmlNodePtr node);
49 static gpointer setup_northwest_target_func(xmlNodePtr node);
50 static gpointer setup_northeast_target_func(xmlNodePtr node);
51 static gpointer setup_southwest_target_func(xmlNodePtr node);
52 static gpointer setup_southeast_target_func(xmlNodePtr node);
53
54 void action_directionalwindows_startup(void)
55 {
56 actions_register("DirectionalCycleWindows", setup_cycle_func, free_func,
57 run_func, i_input_func, i_cancel_func);
58 actions_register("DirectionalTargetWindow", setup_target_func, free_func,
59 run_func, NULL, NULL);
60 /* 3.4-compatibility */
61 actions_register("DirectionalFocusNorth", setup_north_cycle_func,
62 free_func, run_func, i_input_func, i_cancel_func);
63 actions_register("DirectionalFocusSouth", setup_south_cycle_func,
64 free_func, run_func, i_input_func, i_cancel_func);
65 actions_register("DirectionalFocusWest", setup_west_cycle_func,
66 free_func, run_func, i_input_func, i_cancel_func);
67 actions_register("DirectionalFocusEast", setup_east_cycle_func,
68 free_func, run_func, i_input_func, i_cancel_func);
69 actions_register("DirectionalFocusNorthWest", setup_northwest_cycle_func,
70 free_func, run_func, i_input_func, i_cancel_func);
71 actions_register("DirectionalFocusNorthEast", setup_northeast_cycle_func,
72 free_func, run_func, i_input_func, i_cancel_func);
73 actions_register("DirectionalFocusSouthWest", setup_southwest_cycle_func,
74 free_func, run_func, i_input_func, i_cancel_func);
75 actions_register("DirectionalFocusSouthEast", setup_southeast_cycle_func,
76 free_func, run_func, i_input_func, i_cancel_func);
77 actions_register("DirectionalTargetNorth", setup_north_target_func,
78 free_func, run_func, i_input_func, i_cancel_func);
79 actions_register("DirectionalTargetSouth", setup_south_target_func,
80 free_func, run_func, i_input_func, i_cancel_func);
81 actions_register("DirectionalTargetWest", setup_west_target_func,
82 free_func, run_func, i_input_func, i_cancel_func);
83 actions_register("DirectionalTargetEast", setup_east_target_func,
84 free_func, run_func, i_input_func, i_cancel_func);
85 actions_register("DirectionalTargetNorthWest", setup_northwest_target_func,
86 free_func, run_func, i_input_func, i_cancel_func);
87 actions_register("DirectionalTargetNorthEast", setup_northeast_target_func,
88 free_func, run_func, i_input_func, i_cancel_func);
89 actions_register("DirectionalTargetSouthWest", setup_southwest_target_func,
90 free_func, run_func, i_input_func, i_cancel_func);
91 actions_register("DirectionalTargetSouthEast", setup_southeast_target_func,
92 free_func, run_func, i_input_func, i_cancel_func);
93 }
94
95 static gpointer setup_func(xmlNodePtr node)
96 {
97 xmlNodePtr n;
98 Options *o;
99
100 o = g_new0(Options, 1);
101 o->dialog = TRUE;
102 o->bar = TRUE;
103
104 if ((n = obt_parse_find_node(node, "dialog")))
105 o->dialog = obt_parse_node_bool(n);
106 if ((n = obt_parse_find_node(node, "bar")))
107 o->bar = obt_parse_node_bool(n);
108 if ((n = obt_parse_find_node(node, "raise")))
109 o->raise = obt_parse_node_bool(n);
110 if ((n = obt_parse_find_node(node, "panels")))
111 o->dock_windows = obt_parse_node_bool(n);
112 if ((n = obt_parse_find_node(node, "desktop")))
113 o->desktop_windows = obt_parse_node_bool(n);
114 if ((n = obt_parse_find_node(node, "direction"))) {
115 gchar *s = obt_parse_node_string(n);
116 if (!g_ascii_strcasecmp(s, "north") ||
117 !g_ascii_strcasecmp(s, "up"))
118 o->direction = OB_DIRECTION_NORTH;
119 else if (!g_ascii_strcasecmp(s, "northwest"))
120 o->direction = OB_DIRECTION_NORTHWEST;
121 else if (!g_ascii_strcasecmp(s, "northeast"))
122 o->direction = OB_DIRECTION_NORTHEAST;
123 else if (!g_ascii_strcasecmp(s, "west") ||
124 !g_ascii_strcasecmp(s, "left"))
125 o->direction = OB_DIRECTION_WEST;
126 else if (!g_ascii_strcasecmp(s, "east") ||
127 !g_ascii_strcasecmp(s, "right"))
128 o->direction = OB_DIRECTION_EAST;
129 else if (!g_ascii_strcasecmp(s, "south") ||
130 !g_ascii_strcasecmp(s, "down"))
131 o->direction = OB_DIRECTION_SOUTH;
132 else if (!g_ascii_strcasecmp(s, "southwest"))
133 o->direction = OB_DIRECTION_SOUTHWEST;
134 else if (!g_ascii_strcasecmp(s, "southeast"))
135 o->direction = OB_DIRECTION_SOUTHEAST;
136 g_free(s);
137 }
138
139 if ((n = obt_parse_find_node(node, "finalactions"))) {
140 xmlNodePtr m;
141
142 m = obt_parse_find_node(n->children, "action");
143 while (m) {
144 ObActionsAct *action = actions_parse(m);
145 if (action) o->actions = g_slist_append(o->actions, action);
146 m = obt_parse_find_node(m->next, "action");
147 }
148 }
149 else {
150 o->actions = g_slist_prepend(o->actions,
151 actions_parse_string("Focus"));
152 o->actions = g_slist_prepend(o->actions,
153 actions_parse_string("Raise"));
154 o->actions = g_slist_prepend(o->actions,
155 actions_parse_string("Unshade"));
156 }
157
158 return o;
159 }
160
161 static gpointer setup_cycle_func(xmlNodePtr node)
162 {
163 Options *o = setup_func(node);
164 o->interactive = TRUE;
165 return o;
166 }
167
168 static gpointer setup_target_func(xmlNodePtr node)
169 {
170 Options *o = setup_func(node);
171 o->interactive = FALSE;
172 return o;
173 }
174
175 static void free_func(gpointer options)
176 {
177 Options *o = options;
178
179 while (o->actions) {
180 actions_act_unref(o->actions->data);
181 o->actions = g_slist_delete_link(o->actions, o->actions);
182 }
183
184 g_free(o);
185 }
186
187 static gboolean run_func(ObActionsData *data, gpointer options)
188 {
189 Options *o = options;
190
191 if (!o->interactive)
192 end_cycle(FALSE, data->state, o);
193 else {
194 struct _ObClient *ft;
195
196 ft = focus_directional_cycle(o->direction,
197 o->dock_windows,
198 o->desktop_windows,
199 TRUE,
200 o->bar,
201 o->dialog,
202 FALSE, FALSE);
203 cycling = TRUE;
204
205 stacking_restore();
206 if (o->raise && ft) stacking_temp_raise(CLIENT_AS_WINDOW(ft));
207 }
208
209 return o->interactive;
210 }
211
212 static gboolean i_input_func(guint initial_state,
213 XEvent *e,
214 gpointer options,
215 gboolean *used)
216 {
217 if (e->type == KeyPress) {
218 /* Escape cancels no matter what */
219 if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) {
220 end_cycle(TRUE, e->xkey.state, options);
221 return FALSE;
222 }
223
224 /* There were no modifiers and they pressed enter */
225 else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN) &&
226 !initial_state)
227 {
228 end_cycle(FALSE, e->xkey.state, options);
229 return FALSE;
230 }
231 }
232 /* They released the modifiers */
233 else if (e->type == KeyRelease && initial_state &&
234 (e->xkey.state & initial_state) == 0)
235 {
236 end_cycle(FALSE, e->xkey.state, options);
237 return FALSE;
238 }
239
240 return TRUE;
241 }
242
243 static void i_cancel_func(gpointer options)
244 {
245 /* we get cancelled when we move focus, but we're not cycling anymore, so
246 just ignore that */
247 if (cycling)
248 end_cycle(TRUE, 0, options);
249 }
250
251 static void end_cycle(gboolean cancel, guint state, Options *o)
252 {
253 struct _ObClient *ft;
254
255 ft = focus_directional_cycle(o->direction,
256 o->dock_windows,
257 o->desktop_windows,
258 o->interactive,
259 o->bar,
260 o->dialog,
261 TRUE, cancel);
262 cycling = FALSE;
263
264 if (ft)
265 actions_run_acts(o->actions, OB_USER_ACTION_KEYBOARD_KEY,
266 state, -1, -1, 0, OB_FRAME_CONTEXT_NONE, ft);
267
268 stacking_restore();
269 }
270
271 /* 3.4-compatibility */
272 static gpointer setup_north_cycle_func(xmlNodePtr node)
273 {
274 Options *o = setup_cycle_func(node);
275 o->direction = OB_DIRECTION_NORTH;
276 return o;
277 }
278
279 static gpointer setup_south_cycle_func(xmlNodePtr node)
280 {
281 Options *o = setup_cycle_func(node);
282 o->direction = OB_DIRECTION_SOUTH;
283 return o;
284 }
285
286 static gpointer setup_east_cycle_func(xmlNodePtr node)
287 {
288 Options *o = setup_cycle_func(node);
289 o->direction = OB_DIRECTION_EAST;
290 return o;
291 }
292
293 static gpointer setup_west_cycle_func(xmlNodePtr node)
294 {
295 Options *o = setup_cycle_func(node);
296 o->direction = OB_DIRECTION_WEST;
297 return o;
298 }
299
300 static gpointer setup_northwest_cycle_func(xmlNodePtr node)
301 {
302 Options *o = setup_cycle_func(node);
303 o->direction = OB_DIRECTION_NORTHWEST;
304 return o;
305 }
306
307 static gpointer setup_northeast_cycle_func(xmlNodePtr node)
308 {
309 Options *o = setup_cycle_func(node);
310 o->direction = OB_DIRECTION_EAST;
311 return o;
312 }
313
314 static gpointer setup_southwest_cycle_func(xmlNodePtr node)
315 {
316 Options *o = setup_cycle_func(node);
317 o->direction = OB_DIRECTION_SOUTHWEST;
318 return o;
319 }
320
321 static gpointer setup_southeast_cycle_func(xmlNodePtr node)
322 {
323 Options *o = setup_cycle_func(node);
324 o->direction = OB_DIRECTION_SOUTHEAST;
325 return o;
326 }
327
328 static gpointer setup_north_target_func(xmlNodePtr node)
329 {
330 Options *o = setup_target_func(node);
331 o->direction = OB_DIRECTION_NORTH;
332 return o;
333 }
334
335 static gpointer setup_south_target_func(xmlNodePtr node)
336 {
337 Options *o = setup_target_func(node);
338 o->direction = OB_DIRECTION_SOUTH;
339 return o;
340 }
341
342 static gpointer setup_east_target_func(xmlNodePtr node)
343 {
344 Options *o = setup_target_func(node);
345 o->direction = OB_DIRECTION_EAST;
346 return o;
347 }
348
349 static gpointer setup_west_target_func(xmlNodePtr node)
350 {
351 Options *o = setup_target_func(node);
352 o->direction = OB_DIRECTION_WEST;
353 return o;
354 }
355
356 static gpointer setup_northwest_target_func(xmlNodePtr node)
357 {
358 Options *o = setup_target_func(node);
359 o->direction = OB_DIRECTION_NORTHWEST;
360 return o;
361 }
362
363 static gpointer setup_northeast_target_func(xmlNodePtr node)
364 {
365 Options *o = setup_target_func(node);
366 o->direction = OB_DIRECTION_NORTHEAST;
367 return o;
368 }
369
370 static gpointer setup_southwest_target_func(xmlNodePtr node)
371 {
372 Options *o = setup_target_func(node);
373 o->direction = OB_DIRECTION_SOUTHWEST;
374 return o;
375 }
376
377 static gpointer setup_southeast_target_func(xmlNodePtr node)
378 {
379 Options *o = setup_target_func(node);
380 o->direction = OB_DIRECTION_SOUTHEAST;
381 return o;
382 }
383
This page took 0.046452 seconds and 4 git commands to generate.