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"
13 gboolean dock_windows
;
14 gboolean desktop_windows
;
15 ObDirection direction
;
21 static gboolean cycling
= FALSE
;
23 static gpointer
setup_func(xmlNodePtr node
);
24 static gpointer
setup_cycle_func(xmlNodePtr node
,
25 ObActionsIPreFunc
*pre
,
26 ObActionsIInputFunc
*input
,
27 ObActionsICancelFunc
*cancel
,
28 ObActionsIPostFunc
*post
);
29 static gpointer
setup_target_func(xmlNodePtr node
);
30 static void free_func(gpointer options
);
31 static gboolean
run_func(ObActionsData
*data
, gpointer options
);
32 static gboolean
i_input_func(guint initial_state
,
36 static void i_cancel_func(gpointer options
);
38 static void end_cycle(gboolean cancel
, guint state
, Options
*o
);
40 /* 3.4-compatibility */
41 static gpointer
setup_north_cycle_func(xmlNodePtr node
,
42 ObActionsIPreFunc
*pre
,
43 ObActionsIInputFunc
*in
,
44 ObActionsICancelFunc
*c
,
45 ObActionsIPostFunc
*post
);
46 static gpointer
setup_south_cycle_func(xmlNodePtr node
,
47 ObActionsIPreFunc
*pre
,
48 ObActionsIInputFunc
*in
,
49 ObActionsICancelFunc
*c
,
50 ObActionsIPostFunc
*post
);
51 static gpointer
setup_east_cycle_func(xmlNodePtr node
,
52 ObActionsIPreFunc
*pre
,
53 ObActionsIInputFunc
*in
,
54 ObActionsICancelFunc
*c
,
55 ObActionsIPostFunc
*post
);
56 static gpointer
setup_west_cycle_func(xmlNodePtr node
,
57 ObActionsIPreFunc
*pre
,
58 ObActionsIInputFunc
*in
,
59 ObActionsICancelFunc
*c
,
60 ObActionsIPostFunc
*post
);
61 static gpointer
setup_northwest_cycle_func(xmlNodePtr node
,
62 ObActionsIPreFunc
*pre
,
63 ObActionsIInputFunc
*in
,
64 ObActionsICancelFunc
*c
,
65 ObActionsIPostFunc
*post
);
66 static gpointer
setup_northeast_cycle_func(xmlNodePtr node
,
67 ObActionsIPreFunc
*pre
,
68 ObActionsIInputFunc
*in
,
69 ObActionsICancelFunc
*c
,
70 ObActionsIPostFunc
*post
);
71 static gpointer
setup_southwest_cycle_func(xmlNodePtr node
,
72 ObActionsIPreFunc
*pre
,
73 ObActionsIInputFunc
*in
,
74 ObActionsICancelFunc
*c
,
75 ObActionsIPostFunc
*post
);
76 static gpointer
setup_southeast_cycle_func(xmlNodePtr node
,
77 ObActionsIPreFunc
*pre
,
78 ObActionsIInputFunc
*in
,
79 ObActionsICancelFunc
*c
,
80 ObActionsIPostFunc
*post
);
81 static gpointer
setup_north_target_func(xmlNodePtr node
);
82 static gpointer
setup_south_target_func(xmlNodePtr node
);
83 static gpointer
setup_east_target_func(xmlNodePtr node
);
84 static gpointer
setup_west_target_func(xmlNodePtr node
);
85 static gpointer
setup_northwest_target_func(xmlNodePtr node
);
86 static gpointer
setup_northeast_target_func(xmlNodePtr node
);
87 static gpointer
setup_southwest_target_func(xmlNodePtr node
);
88 static gpointer
setup_southeast_target_func(xmlNodePtr node
);
90 void action_directionalwindows_startup(void)
92 actions_register_i("DirectionalCycleWindows", setup_cycle_func
, free_func
,
94 actions_register("DirectionalTargetWindow", setup_target_func
, free_func
,
96 /* 3.4-compatibility */
97 actions_register_i("DirectionalFocusNorth", setup_north_cycle_func
,
99 actions_register_i("DirectionalFocusSouth", setup_south_cycle_func
,
100 free_func
, run_func
);
101 actions_register_i("DirectionalFocusWest", setup_west_cycle_func
,
102 free_func
, run_func
);
103 actions_register_i("DirectionalFocusEast", setup_east_cycle_func
,
104 free_func
, run_func
);
105 actions_register_i("DirectionalFocusNorthWest", setup_northwest_cycle_func
,
106 free_func
, run_func
);
107 actions_register_i("DirectionalFocusNorthEast", setup_northeast_cycle_func
,
108 free_func
, run_func
);
109 actions_register_i("DirectionalFocusSouthWest", setup_southwest_cycle_func
,
110 free_func
, run_func
);
111 actions_register_i("DirectionalFocusSouthEast", setup_southeast_cycle_func
,
112 free_func
, run_func
);
113 actions_register("DirectionalTargetNorth", setup_north_target_func
,
114 free_func
, run_func
);
115 actions_register("DirectionalTargetSouth", setup_south_target_func
,
116 free_func
, run_func
);
117 actions_register("DirectionalTargetWest", setup_west_target_func
,
118 free_func
, run_func
);
119 actions_register("DirectionalTargetEast", setup_east_target_func
,
120 free_func
, run_func
);
121 actions_register("DirectionalTargetNorthWest", setup_northwest_target_func
,
122 free_func
, run_func
);
123 actions_register("DirectionalTargetNorthEast", setup_northeast_target_func
,
124 free_func
, run_func
);
125 actions_register("DirectionalTargetSouthWest", setup_southwest_target_func
,
126 free_func
, run_func
);
127 actions_register("DirectionalTargetSouthEast", setup_southeast_target_func
,
128 free_func
, run_func
);
131 static gpointer
setup_func(xmlNodePtr node
)
136 o
= g_new0(Options
, 1);
140 if ((n
= obt_xml_find_node(node
, "dialog")))
141 o
->dialog
= obt_xml_node_bool(n
);
142 if ((n
= obt_xml_find_node(node
, "bar")))
143 o
->bar
= obt_xml_node_bool(n
);
144 if ((n
= obt_xml_find_node(node
, "raise")))
145 o
->raise
= obt_xml_node_bool(n
);
146 if ((n
= obt_xml_find_node(node
, "panels")))
147 o
->dock_windows
= obt_xml_node_bool(n
);
148 if ((n
= obt_xml_find_node(node
, "desktop")))
149 o
->desktop_windows
= obt_xml_node_bool(n
);
150 if ((n
= obt_xml_find_node(node
, "direction"))) {
151 gchar
*s
= obt_xml_node_string(n
);
152 if (!g_ascii_strcasecmp(s
, "north") ||
153 !g_ascii_strcasecmp(s
, "up"))
154 o
->direction
= OB_DIRECTION_NORTH
;
155 else if (!g_ascii_strcasecmp(s
, "northwest"))
156 o
->direction
= OB_DIRECTION_NORTHWEST
;
157 else if (!g_ascii_strcasecmp(s
, "northeast"))
158 o
->direction
= OB_DIRECTION_NORTHEAST
;
159 else if (!g_ascii_strcasecmp(s
, "west") ||
160 !g_ascii_strcasecmp(s
, "left"))
161 o
->direction
= OB_DIRECTION_WEST
;
162 else if (!g_ascii_strcasecmp(s
, "east") ||
163 !g_ascii_strcasecmp(s
, "right"))
164 o
->direction
= OB_DIRECTION_EAST
;
165 else if (!g_ascii_strcasecmp(s
, "south") ||
166 !g_ascii_strcasecmp(s
, "down"))
167 o
->direction
= OB_DIRECTION_SOUTH
;
168 else if (!g_ascii_strcasecmp(s
, "southwest"))
169 o
->direction
= OB_DIRECTION_SOUTHWEST
;
170 else if (!g_ascii_strcasecmp(s
, "southeast"))
171 o
->direction
= OB_DIRECTION_SOUTHEAST
;
175 if ((n
= obt_xml_find_node(node
, "finalactions"))) {
178 m
= obt_xml_find_node(n
->children
, "action");
180 ObActionsAct
*action
= actions_parse(m
);
181 if (action
) o
->actions
= g_slist_append(o
->actions
, action
);
182 m
= obt_xml_find_node(m
->next
, "action");
186 o
->actions
= g_slist_prepend(o
->actions
,
187 actions_parse_string("Focus"));
188 o
->actions
= g_slist_prepend(o
->actions
,
189 actions_parse_string("Raise"));
190 o
->actions
= g_slist_prepend(o
->actions
,
191 actions_parse_string("Unshade"));
197 static gpointer
setup_cycle_func(xmlNodePtr node
,
198 ObActionsIPreFunc
*pre
,
199 ObActionsIInputFunc
*input
,
200 ObActionsICancelFunc
*cancel
,
201 ObActionsIPostFunc
*post
)
203 Options
*o
= setup_func(node
);
204 o
->interactive
= TRUE
;
205 *input
= i_input_func
;
206 *cancel
= i_cancel_func
;
210 static gpointer
setup_target_func(xmlNodePtr node
)
212 Options
*o
= setup_func(node
);
213 o
->interactive
= FALSE
;
217 static void free_func(gpointer options
)
219 Options
*o
= options
;
222 actions_act_unref(o
->actions
->data
);
223 o
->actions
= g_slist_delete_link(o
->actions
, o
->actions
);
229 static gboolean
run_func(ObActionsData
*data
, gpointer options
)
231 Options
*o
= options
;
234 end_cycle(FALSE
, data
->state
, o
);
236 struct _ObClient
*ft
;
238 ft
= focus_directional_cycle(o
->direction
,
248 if (o
->raise
&& ft
) stacking_temp_raise(CLIENT_AS_WINDOW(ft
));
251 return o
->interactive
;
254 static gboolean
i_input_func(guint initial_state
,
259 if (e
->type
== KeyPress
) {
260 /* Escape cancels no matter what */
261 if (ob_keycode_match(e
->xkey
.keycode
, OB_KEY_ESCAPE
)) {
262 end_cycle(TRUE
, e
->xkey
.state
, options
);
266 /* There were no modifiers and they pressed enter */
267 else if (ob_keycode_match(e
->xkey
.keycode
, OB_KEY_RETURN
) &&
270 end_cycle(FALSE
, e
->xkey
.state
, options
);
274 /* They released the modifiers */
275 else if (e
->type
== KeyRelease
&& initial_state
&&
276 (e
->xkey
.state
& initial_state
) == 0)
278 end_cycle(FALSE
, e
->xkey
.state
, options
);
285 static void i_cancel_func(gpointer options
)
287 /* we get cancelled when we move focus, but we're not cycling anymore, so
290 end_cycle(TRUE
, 0, options
);
293 static void end_cycle(gboolean cancel
, guint state
, Options
*o
)
295 struct _ObClient
*ft
;
297 ft
= focus_directional_cycle(o
->direction
,
307 actions_run_acts(o
->actions
, OB_USER_ACTION_KEYBOARD_KEY
,
308 state
, -1, -1, 0, OB_FRAME_CONTEXT_NONE
, ft
);
313 /* 3.4-compatibility */
314 static gpointer
setup_north_cycle_func(xmlNodePtr node
,
315 ObActionsIPreFunc
*pre
,
316 ObActionsIInputFunc
*input
,
317 ObActionsICancelFunc
*cancel
,
318 ObActionsIPostFunc
*post
)
320 Options
*o
= setup_cycle_func(node
, pre
, input
, cancel
, post
);
321 o
->direction
= OB_DIRECTION_NORTH
;
325 static gpointer
setup_south_cycle_func(xmlNodePtr node
,
326 ObActionsIPreFunc
*pre
,
327 ObActionsIInputFunc
*input
,
328 ObActionsICancelFunc
*cancel
,
329 ObActionsIPostFunc
*post
)
331 Options
*o
= setup_cycle_func(node
, pre
, input
, cancel
, post
);
332 o
->direction
= OB_DIRECTION_SOUTH
;
336 static gpointer
setup_east_cycle_func(xmlNodePtr node
,
337 ObActionsIPreFunc
*pre
,
338 ObActionsIInputFunc
*input
,
339 ObActionsICancelFunc
*cancel
,
340 ObActionsIPostFunc
*post
)
342 Options
*o
= setup_cycle_func(node
, pre
, input
, cancel
, post
);
343 o
->direction
= OB_DIRECTION_EAST
;
347 static gpointer
setup_west_cycle_func(xmlNodePtr node
,
348 ObActionsIPreFunc
*pre
,
349 ObActionsIInputFunc
*input
,
350 ObActionsICancelFunc
*cancel
,
351 ObActionsIPostFunc
*post
)
353 Options
*o
= setup_cycle_func(node
, pre
, input
, cancel
, post
);
354 o
->direction
= OB_DIRECTION_WEST
;
358 static gpointer
setup_northwest_cycle_func(xmlNodePtr node
,
359 ObActionsIPreFunc
*pre
,
360 ObActionsIInputFunc
*input
,
361 ObActionsICancelFunc
*cancel
,
362 ObActionsIPostFunc
*post
)
364 Options
*o
= setup_cycle_func(node
, pre
, input
, cancel
, post
);
365 o
->direction
= OB_DIRECTION_NORTHWEST
;
369 static gpointer
setup_northeast_cycle_func(xmlNodePtr node
,
370 ObActionsIPreFunc
*pre
,
371 ObActionsIInputFunc
*input
,
372 ObActionsICancelFunc
*cancel
,
373 ObActionsIPostFunc
*post
)
375 Options
*o
= setup_cycle_func(node
, pre
, input
, cancel
, post
);
376 o
->direction
= OB_DIRECTION_EAST
;
380 static gpointer
setup_southwest_cycle_func(xmlNodePtr node
,
381 ObActionsIPreFunc
*pre
,
382 ObActionsIInputFunc
*input
,
383 ObActionsICancelFunc
*cancel
,
384 ObActionsIPostFunc
*post
)
386 Options
*o
= setup_cycle_func(node
, pre
, input
, cancel
, post
);
387 o
->direction
= OB_DIRECTION_SOUTHWEST
;
391 static gpointer
setup_southeast_cycle_func(xmlNodePtr node
,
392 ObActionsIPreFunc
*pre
,
393 ObActionsIInputFunc
*input
,
394 ObActionsICancelFunc
*cancel
,
395 ObActionsIPostFunc
*post
)
397 Options
*o
= setup_cycle_func(node
, pre
, input
, cancel
, post
);
398 o
->direction
= OB_DIRECTION_SOUTHEAST
;
402 static gpointer
setup_north_target_func(xmlNodePtr node
)
404 Options
*o
= setup_target_func(node
);
405 o
->direction
= OB_DIRECTION_NORTH
;
409 static gpointer
setup_south_target_func(xmlNodePtr node
)
411 Options
*o
= setup_target_func(node
);
412 o
->direction
= OB_DIRECTION_SOUTH
;
416 static gpointer
setup_east_target_func(xmlNodePtr node
)
418 Options
*o
= setup_target_func(node
);
419 o
->direction
= OB_DIRECTION_EAST
;
423 static gpointer
setup_west_target_func(xmlNodePtr node
)
425 Options
*o
= setup_target_func(node
);
426 o
->direction
= OB_DIRECTION_WEST
;
430 static gpointer
setup_northwest_target_func(xmlNodePtr node
)
432 Options
*o
= setup_target_func(node
);
433 o
->direction
= OB_DIRECTION_NORTHWEST
;
437 static gpointer
setup_northeast_target_func(xmlNodePtr node
)
439 Options
*o
= setup_target_func(node
);
440 o
->direction
= OB_DIRECTION_NORTHEAST
;
444 static gpointer
setup_southwest_target_func(xmlNodePtr node
)
446 Options
*o
= setup_target_func(node
);
447 o
->direction
= OB_DIRECTION_SOUTHWEST
;
451 static gpointer
setup_southeast_target_func(xmlNodePtr node
)
453 Options
*o
= setup_target_func(node
);
454 o
->direction
= OB_DIRECTION_SOUTHEAST
;