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"
9 #include "obt/keyboard.h"
14 gboolean dock_windows
;
15 gboolean desktop_windows
;
16 ObDirection direction
;
22 static gboolean cycling
= FALSE
;
24 static gpointer
setup_func(xmlNodePtr node
);
25 static gpointer
setup_cycle_func(xmlNodePtr node
,
26 ObActionsIPreFunc
*pre
,
27 ObActionsIInputFunc
*input
,
28 ObActionsICancelFunc
*cancel
,
29 ObActionsIPostFunc
*post
);
30 static gpointer
setup_target_func(xmlNodePtr node
);
31 static void free_func(gpointer options
);
32 static gboolean
run_func(ObActionsData
*data
, gpointer options
);
33 static gboolean
i_input_func(guint initial_state
,
37 static void i_cancel_func(gpointer options
);
39 static void end_cycle(gboolean cancel
, guint state
, Options
*o
);
41 /* 3.4-compatibility */
42 static gpointer
setup_north_cycle_func(xmlNodePtr node
,
43 ObActionsIPreFunc
*pre
,
44 ObActionsIInputFunc
*in
,
45 ObActionsICancelFunc
*c
,
46 ObActionsIPostFunc
*post
);
47 static gpointer
setup_south_cycle_func(xmlNodePtr node
,
48 ObActionsIPreFunc
*pre
,
49 ObActionsIInputFunc
*in
,
50 ObActionsICancelFunc
*c
,
51 ObActionsIPostFunc
*post
);
52 static gpointer
setup_east_cycle_func(xmlNodePtr node
,
53 ObActionsIPreFunc
*pre
,
54 ObActionsIInputFunc
*in
,
55 ObActionsICancelFunc
*c
,
56 ObActionsIPostFunc
*post
);
57 static gpointer
setup_west_cycle_func(xmlNodePtr node
,
58 ObActionsIPreFunc
*pre
,
59 ObActionsIInputFunc
*in
,
60 ObActionsICancelFunc
*c
,
61 ObActionsIPostFunc
*post
);
62 static gpointer
setup_northwest_cycle_func(xmlNodePtr node
,
63 ObActionsIPreFunc
*pre
,
64 ObActionsIInputFunc
*in
,
65 ObActionsICancelFunc
*c
,
66 ObActionsIPostFunc
*post
);
67 static gpointer
setup_northeast_cycle_func(xmlNodePtr node
,
68 ObActionsIPreFunc
*pre
,
69 ObActionsIInputFunc
*in
,
70 ObActionsICancelFunc
*c
,
71 ObActionsIPostFunc
*post
);
72 static gpointer
setup_southwest_cycle_func(xmlNodePtr node
,
73 ObActionsIPreFunc
*pre
,
74 ObActionsIInputFunc
*in
,
75 ObActionsICancelFunc
*c
,
76 ObActionsIPostFunc
*post
);
77 static gpointer
setup_southeast_cycle_func(xmlNodePtr node
,
78 ObActionsIPreFunc
*pre
,
79 ObActionsIInputFunc
*in
,
80 ObActionsICancelFunc
*c
,
81 ObActionsIPostFunc
*post
);
82 static gpointer
setup_north_target_func(xmlNodePtr node
);
83 static gpointer
setup_south_target_func(xmlNodePtr node
);
84 static gpointer
setup_east_target_func(xmlNodePtr node
);
85 static gpointer
setup_west_target_func(xmlNodePtr node
);
86 static gpointer
setup_northwest_target_func(xmlNodePtr node
);
87 static gpointer
setup_northeast_target_func(xmlNodePtr node
);
88 static gpointer
setup_southwest_target_func(xmlNodePtr node
);
89 static gpointer
setup_southeast_target_func(xmlNodePtr node
);
91 void action_directionalwindows_startup(void)
93 actions_register_i("DirectionalCycleWindows", setup_cycle_func
, free_func
,
95 actions_register("DirectionalTargetWindow", setup_target_func
, free_func
,
97 /* 3.4-compatibility */
98 actions_register_i("DirectionalFocusNorth", setup_north_cycle_func
,
100 actions_register_i("DirectionalFocusSouth", setup_south_cycle_func
,
101 free_func
, run_func
);
102 actions_register_i("DirectionalFocusWest", setup_west_cycle_func
,
103 free_func
, run_func
);
104 actions_register_i("DirectionalFocusEast", setup_east_cycle_func
,
105 free_func
, run_func
);
106 actions_register_i("DirectionalFocusNorthWest", setup_northwest_cycle_func
,
107 free_func
, run_func
);
108 actions_register_i("DirectionalFocusNorthEast", setup_northeast_cycle_func
,
109 free_func
, run_func
);
110 actions_register_i("DirectionalFocusSouthWest", setup_southwest_cycle_func
,
111 free_func
, run_func
);
112 actions_register_i("DirectionalFocusSouthEast", setup_southeast_cycle_func
,
113 free_func
, run_func
);
114 actions_register("DirectionalTargetNorth", setup_north_target_func
,
115 free_func
, run_func
);
116 actions_register("DirectionalTargetSouth", setup_south_target_func
,
117 free_func
, run_func
);
118 actions_register("DirectionalTargetWest", setup_west_target_func
,
119 free_func
, run_func
);
120 actions_register("DirectionalTargetEast", setup_east_target_func
,
121 free_func
, run_func
);
122 actions_register("DirectionalTargetNorthWest", setup_northwest_target_func
,
123 free_func
, run_func
);
124 actions_register("DirectionalTargetNorthEast", setup_northeast_target_func
,
125 free_func
, run_func
);
126 actions_register("DirectionalTargetSouthWest", setup_southwest_target_func
,
127 free_func
, run_func
);
128 actions_register("DirectionalTargetSouthEast", setup_southeast_target_func
,
129 free_func
, run_func
);
132 static gpointer
setup_func(xmlNodePtr node
)
137 o
= g_new0(Options
, 1);
141 if ((n
= obt_xml_find_node(node
, "dialog")))
142 o
->dialog
= obt_xml_node_bool(n
);
143 if ((n
= obt_xml_find_node(node
, "bar")))
144 o
->bar
= obt_xml_node_bool(n
);
145 if ((n
= obt_xml_find_node(node
, "raise")))
146 o
->raise
= obt_xml_node_bool(n
);
147 if ((n
= obt_xml_find_node(node
, "panels")))
148 o
->dock_windows
= obt_xml_node_bool(n
);
149 if ((n
= obt_xml_find_node(node
, "desktop")))
150 o
->desktop_windows
= obt_xml_node_bool(n
);
151 if ((n
= obt_xml_find_node(node
, "direction"))) {
152 gchar
*s
= obt_xml_node_string(n
);
153 if (!g_ascii_strcasecmp(s
, "north") ||
154 !g_ascii_strcasecmp(s
, "up"))
155 o
->direction
= OB_DIRECTION_NORTH
;
156 else if (!g_ascii_strcasecmp(s
, "northwest"))
157 o
->direction
= OB_DIRECTION_NORTHWEST
;
158 else if (!g_ascii_strcasecmp(s
, "northeast"))
159 o
->direction
= OB_DIRECTION_NORTHEAST
;
160 else if (!g_ascii_strcasecmp(s
, "west") ||
161 !g_ascii_strcasecmp(s
, "left"))
162 o
->direction
= OB_DIRECTION_WEST
;
163 else if (!g_ascii_strcasecmp(s
, "east") ||
164 !g_ascii_strcasecmp(s
, "right"))
165 o
->direction
= OB_DIRECTION_EAST
;
166 else if (!g_ascii_strcasecmp(s
, "south") ||
167 !g_ascii_strcasecmp(s
, "down"))
168 o
->direction
= OB_DIRECTION_SOUTH
;
169 else if (!g_ascii_strcasecmp(s
, "southwest"))
170 o
->direction
= OB_DIRECTION_SOUTHWEST
;
171 else if (!g_ascii_strcasecmp(s
, "southeast"))
172 o
->direction
= OB_DIRECTION_SOUTHEAST
;
176 if ((n
= obt_xml_find_node(node
, "finalactions"))) {
179 m
= obt_xml_find_node(n
->children
, "action");
181 ObActionsAct
*action
= actions_parse(m
);
182 if (action
) o
->actions
= g_slist_append(o
->actions
, action
);
183 m
= obt_xml_find_node(m
->next
, "action");
187 o
->actions
= g_slist_prepend(o
->actions
,
188 actions_parse_string("Focus"));
189 o
->actions
= g_slist_prepend(o
->actions
,
190 actions_parse_string("Raise"));
191 o
->actions
= g_slist_prepend(o
->actions
,
192 actions_parse_string("Unshade"));
198 static gpointer
setup_cycle_func(xmlNodePtr node
,
199 ObActionsIPreFunc
*pre
,
200 ObActionsIInputFunc
*input
,
201 ObActionsICancelFunc
*cancel
,
202 ObActionsIPostFunc
*post
)
204 Options
*o
= setup_func(node
);
205 o
->interactive
= TRUE
;
206 *input
= i_input_func
;
207 *cancel
= i_cancel_func
;
211 static gpointer
setup_target_func(xmlNodePtr node
)
213 Options
*o
= setup_func(node
);
214 o
->interactive
= FALSE
;
218 static void free_func(gpointer options
)
220 Options
*o
= options
;
223 actions_act_unref(o
->actions
->data
);
224 o
->actions
= g_slist_delete_link(o
->actions
, o
->actions
);
230 static gboolean
run_func(ObActionsData
*data
, gpointer options
)
232 Options
*o
= options
;
235 end_cycle(FALSE
, data
->state
, o
);
237 struct _ObClient
*ft
;
239 ft
= focus_directional_cycle(o
->direction
,
249 if (o
->raise
&& ft
) stacking_temp_raise(CLIENT_AS_WINDOW(ft
));
252 return o
->interactive
;
255 static gboolean
i_input_func(guint initial_state
,
262 mods
= obt_keyboard_only_modmasks(e
->xkey
.state
);
263 if (e
->type
== KeyRelease
) {
264 /* remove from the state the mask of the modifier key being
265 released, if it is a modifier key being released that is */
266 mods
&= ~obt_keyboard_keycode_to_modmask(e
->xkey
.keycode
);
269 if (e
->type
== KeyPress
) {
270 /* Escape cancels no matter what */
271 if (ob_keycode_match(e
->xkey
.keycode
, OB_KEY_ESCAPE
)) {
272 end_cycle(TRUE
, e
->xkey
.state
, options
);
276 /* There were no modifiers and they pressed enter */
277 else if (ob_keycode_match(e
->xkey
.keycode
, OB_KEY_RETURN
) &&
280 end_cycle(FALSE
, e
->xkey
.state
, options
);
284 /* They released the modifiers */
285 else if (e
->type
== KeyRelease
&& initial_state
&& !(mods
& initial_state
))
287 end_cycle(FALSE
, e
->xkey
.state
, options
);
294 static void i_cancel_func(gpointer options
)
296 /* we get cancelled when we move focus, but we're not cycling anymore, so
299 end_cycle(TRUE
, 0, options
);
302 static void end_cycle(gboolean cancel
, guint state
, Options
*o
)
304 struct _ObClient
*ft
;
306 ft
= focus_directional_cycle(o
->direction
,
316 actions_run_acts(o
->actions
, OB_USER_ACTION_KEYBOARD_KEY
,
317 state
, -1, -1, 0, OB_FRAME_CONTEXT_NONE
, ft
);
322 /* 3.4-compatibility */
323 static gpointer
setup_north_cycle_func(xmlNodePtr node
,
324 ObActionsIPreFunc
*pre
,
325 ObActionsIInputFunc
*input
,
326 ObActionsICancelFunc
*cancel
,
327 ObActionsIPostFunc
*post
)
329 Options
*o
= setup_cycle_func(node
, pre
, input
, cancel
, post
);
330 o
->direction
= OB_DIRECTION_NORTH
;
334 static gpointer
setup_south_cycle_func(xmlNodePtr node
,
335 ObActionsIPreFunc
*pre
,
336 ObActionsIInputFunc
*input
,
337 ObActionsICancelFunc
*cancel
,
338 ObActionsIPostFunc
*post
)
340 Options
*o
= setup_cycle_func(node
, pre
, input
, cancel
, post
);
341 o
->direction
= OB_DIRECTION_SOUTH
;
345 static gpointer
setup_east_cycle_func(xmlNodePtr node
,
346 ObActionsIPreFunc
*pre
,
347 ObActionsIInputFunc
*input
,
348 ObActionsICancelFunc
*cancel
,
349 ObActionsIPostFunc
*post
)
351 Options
*o
= setup_cycle_func(node
, pre
, input
, cancel
, post
);
352 o
->direction
= OB_DIRECTION_EAST
;
356 static gpointer
setup_west_cycle_func(xmlNodePtr node
,
357 ObActionsIPreFunc
*pre
,
358 ObActionsIInputFunc
*input
,
359 ObActionsICancelFunc
*cancel
,
360 ObActionsIPostFunc
*post
)
362 Options
*o
= setup_cycle_func(node
, pre
, input
, cancel
, post
);
363 o
->direction
= OB_DIRECTION_WEST
;
367 static gpointer
setup_northwest_cycle_func(xmlNodePtr node
,
368 ObActionsIPreFunc
*pre
,
369 ObActionsIInputFunc
*input
,
370 ObActionsICancelFunc
*cancel
,
371 ObActionsIPostFunc
*post
)
373 Options
*o
= setup_cycle_func(node
, pre
, input
, cancel
, post
);
374 o
->direction
= OB_DIRECTION_NORTHWEST
;
378 static gpointer
setup_northeast_cycle_func(xmlNodePtr node
,
379 ObActionsIPreFunc
*pre
,
380 ObActionsIInputFunc
*input
,
381 ObActionsICancelFunc
*cancel
,
382 ObActionsIPostFunc
*post
)
384 Options
*o
= setup_cycle_func(node
, pre
, input
, cancel
, post
);
385 o
->direction
= OB_DIRECTION_EAST
;
389 static gpointer
setup_southwest_cycle_func(xmlNodePtr node
,
390 ObActionsIPreFunc
*pre
,
391 ObActionsIInputFunc
*input
,
392 ObActionsICancelFunc
*cancel
,
393 ObActionsIPostFunc
*post
)
395 Options
*o
= setup_cycle_func(node
, pre
, input
, cancel
, post
);
396 o
->direction
= OB_DIRECTION_SOUTHWEST
;
400 static gpointer
setup_southeast_cycle_func(xmlNodePtr node
,
401 ObActionsIPreFunc
*pre
,
402 ObActionsIInputFunc
*input
,
403 ObActionsICancelFunc
*cancel
,
404 ObActionsIPostFunc
*post
)
406 Options
*o
= setup_cycle_func(node
, pre
, input
, cancel
, post
);
407 o
->direction
= OB_DIRECTION_SOUTHEAST
;
411 static gpointer
setup_north_target_func(xmlNodePtr node
)
413 Options
*o
= setup_target_func(node
);
414 o
->direction
= OB_DIRECTION_NORTH
;
418 static gpointer
setup_south_target_func(xmlNodePtr node
)
420 Options
*o
= setup_target_func(node
);
421 o
->direction
= OB_DIRECTION_SOUTH
;
425 static gpointer
setup_east_target_func(xmlNodePtr node
)
427 Options
*o
= setup_target_func(node
);
428 o
->direction
= OB_DIRECTION_EAST
;
432 static gpointer
setup_west_target_func(xmlNodePtr node
)
434 Options
*o
= setup_target_func(node
);
435 o
->direction
= OB_DIRECTION_WEST
;
439 static gpointer
setup_northwest_target_func(xmlNodePtr node
)
441 Options
*o
= setup_target_func(node
);
442 o
->direction
= OB_DIRECTION_NORTHWEST
;
446 static gpointer
setup_northeast_target_func(xmlNodePtr node
)
448 Options
*o
= setup_target_func(node
);
449 o
->direction
= OB_DIRECTION_NORTHEAST
;
453 static gpointer
setup_southwest_target_func(xmlNodePtr node
)
455 Options
*o
= setup_target_func(node
);
456 o
->direction
= OB_DIRECTION_SOUTHWEST
;
460 static gpointer
setup_southeast_target_func(xmlNodePtr node
)
462 Options
*o
= setup_target_func(node
);
463 o
->direction
= OB_DIRECTION_SOUTHEAST
;