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/client.h"
8 #include "openbox/misc.h"
14 gboolean dock_windows;
15 gboolean desktop_windows;
16 ObDirection direction;
22 static gboolean cycling = FALSE;
24 static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
25 static gpointer setup_north_cycle_func(ObParseInst *i,
26 xmlDocPtr doc, xmlNodePtr node);
27 static gpointer setup_south_cycle_func(ObParseInst *i,
28 xmlDocPtr doc, xmlNodePtr node);
29 static gpointer setup_east_cycle_func(ObParseInst *i,
30 xmlDocPtr doc, xmlNodePtr node);
31 static gpointer setup_west_cycle_func(ObParseInst *i,
32 xmlDocPtr doc, xmlNodePtr node);
33 static gpointer setup_northwest_cycle_func(ObParseInst *i,
34 xmlDocPtr doc, xmlNodePtr node);
35 static gpointer setup_northeast_cycle_func(ObParseInst *i,
36 xmlDocPtr doc, xmlNodePtr node);
37 static gpointer setup_southwest_cycle_func(ObParseInst *i,
38 xmlDocPtr doc, xmlNodePtr node);
39 static gpointer setup_southeast_cycle_func(ObParseInst *i,
40 xmlDocPtr doc, xmlNodePtr node);
41 static gpointer setup_north_target_func(ObParseInst *i,
42 xmlDocPtr doc, xmlNodePtr node);
43 static gpointer setup_south_target_func(ObParseInst *i,
44 xmlDocPtr doc, xmlNodePtr node);
45 static gpointer setup_east_target_func(ObParseInst *i,
46 xmlDocPtr doc, xmlNodePtr node);
47 static gpointer setup_west_target_func(ObParseInst *i,
48 xmlDocPtr doc, xmlNodePtr node);
49 static gpointer setup_northwest_target_func(ObParseInst *i,
50 xmlDocPtr doc, xmlNodePtr node);
51 static gpointer setup_northeast_target_func(ObParseInst *i,
52 xmlDocPtr doc, xmlNodePtr node);
53 static gpointer setup_southwest_target_func(ObParseInst *i,
54 xmlDocPtr doc, xmlNodePtr node);
55 static gpointer setup_southeast_target_func(ObParseInst *i,
56 xmlDocPtr doc, xmlNodePtr node);
57 static void free_func(gpointer options);
58 static gboolean run_func(ObActionsData *data, gpointer options);
59 static gboolean i_input_func(guint initial_state,
63 static void i_cancel_func(gpointer options);
65 static void end_cycle(gboolean cancel, guint state, Options *o);
67 void action_directionalwindows_startup(void)
69 actions_register("DirectionalFocusNorth", setup_north_cycle_func,
70 free_func, run_func, i_input_func, i_cancel_func);
71 actions_register("DirectionalFocusSouth", setup_south_cycle_func,
72 free_func, run_func, i_input_func, i_cancel_func);
73 actions_register("DirectionalFocusWest", setup_west_cycle_func,
74 free_func, run_func, i_input_func, i_cancel_func);
75 actions_register("DirectionalFocusEast", setup_east_cycle_func,
76 free_func, run_func, i_input_func, i_cancel_func);
77 actions_register("DirectionalFocusNorthWest", setup_northwest_cycle_func,
78 free_func, run_func, i_input_func, i_cancel_func);
79 actions_register("DirectionalFocusNorthEast", setup_northeast_cycle_func,
80 free_func, run_func, i_input_func, i_cancel_func);
81 actions_register("DirectionalFocusSouthWest", setup_southwest_cycle_func,
82 free_func, run_func, i_input_func, i_cancel_func);
83 actions_register("DirectionalFocusSouthEast", setup_southeast_cycle_func,
84 free_func, run_func, i_input_func, i_cancel_func);
85 actions_register("DirectionalTargetNorth", setup_north_target_func,
86 free_func, run_func, i_input_func, i_cancel_func);
87 actions_register("DirectionalTargetSouth", setup_south_target_func,
88 free_func, run_func, i_input_func, i_cancel_func);
89 actions_register("DirectionalTargetWest", setup_west_target_func,
90 free_func, run_func, i_input_func, i_cancel_func);
91 actions_register("DirectionalTargetEast", setup_east_target_func,
92 free_func, run_func, i_input_func, i_cancel_func);
93 actions_register("DirectionalTargetNorthWest", setup_northwest_target_func,
94 free_func, run_func, i_input_func, i_cancel_func);
95 actions_register("DirectionalTargetNorthEast", setup_northeast_target_func,
96 free_func, run_func, i_input_func, i_cancel_func);
97 actions_register("DirectionalTargetSouthWest", setup_southwest_target_func,
98 free_func, run_func, i_input_func, i_cancel_func);
99 actions_register("DirectionalTargetSouthEast", setup_southeast_target_func,
100 free_func, run_func, i_input_func, i_cancel_func);
103 static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
108 o = g_new0(Options, 1);
112 if ((n = parse_find_node("dialog", node)))
113 o->dialog = parse_bool(doc, n);
114 if ((n = parse_find_node("bar", node)))
115 o->bar = parse_bool(doc, n);
116 if ((n = parse_find_node("raise", node)))
117 o->raise = parse_bool(doc, n);
118 if ((n = parse_find_node("panels", node)))
119 o->dock_windows = parse_bool(doc, n);
120 if ((n = parse_find_node("desktop", node)))
121 o->desktop_windows = parse_bool(doc, n);
123 if ((n = parse_find_node("finalactions", node))) {
126 m = parse_find_node("action", n->xmlChildrenNode);
128 ObActionsAct *action = actions_parse(i, doc, m);
129 if (action) o->actions = g_slist_append(o->actions, action);
130 m = parse_find_node("action", m->next);
134 o->actions = g_slist_prepend(o->actions,
135 actions_parse_string("Focus"));
136 o->actions = g_slist_prepend(o->actions,
137 actions_parse_string("Raise"));
138 o->actions = g_slist_prepend(o->actions,
139 actions_parse_string("Unshade"));
145 static gpointer setup_north_cycle_func(ObParseInst *i,
146 xmlDocPtr doc, xmlNodePtr node)
148 Options *o = setup_func(i, doc, node);
149 o->interactive = TRUE;
150 o->direction = OB_DIRECTION_NORTH;
154 static gpointer setup_south_cycle_func(ObParseInst *i,
155 xmlDocPtr doc, xmlNodePtr node)
157 Options *o = setup_func(i, doc, node);
158 o->interactive = TRUE;
159 o->direction = OB_DIRECTION_SOUTH;
163 static gpointer setup_east_cycle_func(ObParseInst *i,
164 xmlDocPtr doc, xmlNodePtr node)
166 Options *o = setup_func(i, doc, node);
167 o->interactive = TRUE;
168 o->direction = OB_DIRECTION_EAST;
172 static gpointer setup_west_cycle_func(ObParseInst *i,
173 xmlDocPtr doc, xmlNodePtr node)
175 Options *o = setup_func(i, doc, node);
176 o->interactive = TRUE;
177 o->direction = OB_DIRECTION_WEST;
181 static gpointer setup_northwest_cycle_func(ObParseInst *i,
182 xmlDocPtr doc, xmlNodePtr node)
184 Options *o = setup_func(i, doc, node);
185 o->interactive = TRUE;
186 o->direction = OB_DIRECTION_NORTHWEST;
190 static gpointer setup_northeast_cycle_func(ObParseInst *i,
191 xmlDocPtr doc, xmlNodePtr node)
193 Options *o = setup_func(i, doc, node);
194 o->interactive = TRUE;
195 o->direction = OB_DIRECTION_EAST;
199 static gpointer setup_southwest_cycle_func(ObParseInst *i,
200 xmlDocPtr doc, xmlNodePtr node)
202 Options *o = setup_func(i, doc, node);
203 o->interactive = TRUE;
204 o->direction = OB_DIRECTION_SOUTHWEST;
208 static gpointer setup_southeast_cycle_func(ObParseInst *i,
209 xmlDocPtr doc, xmlNodePtr node)
211 Options *o = setup_func(i, doc, node);
212 o->interactive = TRUE;
213 o->direction = OB_DIRECTION_SOUTHEAST;
217 static gpointer setup_north_target_func(ObParseInst *i,
218 xmlDocPtr doc, xmlNodePtr node)
220 Options *o = setup_func(i, doc, node);
221 o->interactive = FALSE;
222 o->direction = OB_DIRECTION_NORTH;
226 static gpointer setup_south_target_func(ObParseInst *i,
227 xmlDocPtr doc, xmlNodePtr node)
229 Options *o = setup_func(i, doc, node);
230 o->interactive = FALSE;
231 o->direction = OB_DIRECTION_SOUTH;
235 static gpointer setup_east_target_func(ObParseInst *i,
236 xmlDocPtr doc, xmlNodePtr node)
238 Options *o = setup_func(i, doc, node);
239 o->interactive = FALSE;
240 o->direction = OB_DIRECTION_EAST;
244 static gpointer setup_west_target_func(ObParseInst *i,
245 xmlDocPtr doc, xmlNodePtr node)
247 Options *o = setup_func(i, doc, node);
248 o->interactive = FALSE;
249 o->direction = OB_DIRECTION_WEST;
253 static gpointer setup_northwest_target_func(ObParseInst *i,
254 xmlDocPtr doc, xmlNodePtr node)
256 Options *o = setup_func(i, doc, node);
257 o->interactive = FALSE;
258 o->direction = OB_DIRECTION_NORTHWEST;
262 static gpointer setup_northeast_target_func(ObParseInst *i,
263 xmlDocPtr doc, xmlNodePtr node)
265 Options *o = setup_func(i, doc, node);
266 o->interactive = FALSE;
267 o->direction = OB_DIRECTION_NORTHEAST;
271 static gpointer setup_southwest_target_func(ObParseInst *i,
272 xmlDocPtr doc, xmlNodePtr node)
274 Options *o = setup_func(i, doc, node);
275 o->interactive = FALSE;
276 o->direction = OB_DIRECTION_SOUTHWEST;
280 static gpointer setup_southeast_target_func(ObParseInst *i,
281 xmlDocPtr doc, xmlNodePtr node)
283 Options *o = setup_func(i, doc, node);
284 o->interactive = FALSE;
285 o->direction = OB_DIRECTION_SOUTHEAST;
289 static void free_func(gpointer options)
291 Options *o = options;
294 actions_act_unref(o->actions->data);
295 o->actions = g_slist_delete_link(o->actions, o->actions);
301 static gboolean run_func(ObActionsData *data, gpointer options)
303 Options *o = options;
306 end_cycle(FALSE, data->state, o);
308 struct _ObClient *ft;
310 ft = focus_directional_cycle(o->direction,
320 if (o->raise && ft) stacking_temp_raise(CLIENT_AS_WINDOW(ft));
323 return o->interactive;
326 static gboolean i_input_func(guint initial_state,
331 if (e->type == KeyPress) {
332 /* Escape cancels no matter what */
333 if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) {
334 end_cycle(TRUE, e->xkey.state, options);
338 /* There were no modifiers and they pressed enter */
339 else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN) &&
342 end_cycle(FALSE, e->xkey.state, options);
346 /* They released the modifiers */
347 else if (e->type == KeyRelease && initial_state &&
348 (e->xkey.state & initial_state) == 0)
350 end_cycle(FALSE, e->xkey.state, options);
357 static void i_cancel_func(gpointer options)
359 /* we get cancelled when we move focus, but we're not cycling anymore, so
362 end_cycle(TRUE, 0, options);
365 static void end_cycle(gboolean cancel, guint state, Options *o)
367 struct _ObClient *ft;
369 ft = focus_directional_cycle(o->direction,
379 actions_run_acts(o->actions, OB_USER_ACTION_KEYBOARD_KEY,
380 state, -1, -1, 0, OB_FRAME_CONTEXT_NONE, ft);