1 #include "openbox/actions.h"
2 #include "openbox/event.h"
3 #include "openbox/focus_cycle.h"
4 #include "openbox/openbox.h"
5 #include "openbox/client.h"
6 #include "openbox/misc.h"
12 gboolean dock_windows;
13 gboolean desktop_windows;
14 ObDirection direction;
18 static gboolean cycling = FALSE;
20 static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
21 static gpointer setup_north_cycle_func(ObParseInst *i,
22 xmlDocPtr doc, xmlNodePtr node);
23 static gpointer setup_south_cycle_func(ObParseInst *i,
24 xmlDocPtr doc, xmlNodePtr node);
25 static gpointer setup_east_cycle_func(ObParseInst *i,
26 xmlDocPtr doc, xmlNodePtr node);
27 static gpointer setup_west_cycle_func(ObParseInst *i,
28 xmlDocPtr doc, xmlNodePtr node);
29 static gpointer setup_northwest_cycle_func(ObParseInst *i,
30 xmlDocPtr doc, xmlNodePtr node);
31 static gpointer setup_northeast_cycle_func(ObParseInst *i,
32 xmlDocPtr doc, xmlNodePtr node);
33 static gpointer setup_southwest_cycle_func(ObParseInst *i,
34 xmlDocPtr doc, xmlNodePtr node);
35 static gpointer setup_southeast_cycle_func(ObParseInst *i,
36 xmlDocPtr doc, xmlNodePtr node);
37 static gpointer setup_north_target_func(ObParseInst *i,
38 xmlDocPtr doc, xmlNodePtr node);
39 static gpointer setup_south_target_func(ObParseInst *i,
40 xmlDocPtr doc, xmlNodePtr node);
41 static gpointer setup_east_target_func(ObParseInst *i,
42 xmlDocPtr doc, xmlNodePtr node);
43 static gpointer setup_west_target_func(ObParseInst *i,
44 xmlDocPtr doc, xmlNodePtr node);
45 static gpointer setup_northwest_target_func(ObParseInst *i,
46 xmlDocPtr doc, xmlNodePtr node);
47 static gpointer setup_northeast_target_func(ObParseInst *i,
48 xmlDocPtr doc, xmlNodePtr node);
49 static gpointer setup_southwest_target_func(ObParseInst *i,
50 xmlDocPtr doc, xmlNodePtr node);
51 static gpointer setup_southeast_target_func(ObParseInst *i,
52 xmlDocPtr doc, xmlNodePtr node);
53 static void free_func(gpointer options);
54 static gboolean run_func(ObActionsData *data, gpointer options);
55 static gboolean i_input_func(guint initial_state,
59 static void i_cancel_func(gpointer options);
61 static void end_cycle(gboolean cancel, guint state, Options *o);
63 void action_directionalwindows_startup(void)
65 actions_register("DirectionalFocusNorth", setup_north_cycle_func,
66 free_func, run_func, i_input_func, i_cancel_func);
67 actions_register("DirectionalFocusSouth", setup_south_cycle_func,
68 free_func, run_func, i_input_func, i_cancel_func);
69 actions_register("DirectionalFocusWest", setup_west_cycle_func,
70 free_func, run_func, i_input_func, i_cancel_func);
71 actions_register("DirectionalFocusEast", setup_east_cycle_func,
72 free_func, run_func, i_input_func, i_cancel_func);
73 actions_register("DirectionalFocusNorthWest", setup_northwest_cycle_func,
74 free_func, run_func, i_input_func, i_cancel_func);
75 actions_register("DirectionalFocusNorthEast", setup_northeast_cycle_func,
76 free_func, run_func, i_input_func, i_cancel_func);
77 actions_register("DirectionalFocusSouthWest", setup_southwest_cycle_func,
78 free_func, run_func, i_input_func, i_cancel_func);
79 actions_register("DirectionalFocusSouthEast", setup_southeast_cycle_func,
80 free_func, run_func, i_input_func, i_cancel_func);
81 actions_register("DirectionalTargetNorth", setup_north_target_func,
82 free_func, run_func, i_input_func, i_cancel_func);
83 actions_register("DirectionalTargetSouth", setup_south_target_func,
84 free_func, run_func, i_input_func, i_cancel_func);
85 actions_register("DirectionalTargetWest", setup_west_target_func,
86 free_func, run_func, i_input_func, i_cancel_func);
87 actions_register("DirectionalTargetEast", setup_east_target_func,
88 free_func, run_func, i_input_func, i_cancel_func);
89 actions_register("DirectionalTargetNorthWest", setup_northwest_target_func,
90 free_func, run_func, i_input_func, i_cancel_func);
91 actions_register("DirectionalTargetNorthEast", setup_northeast_target_func,
92 free_func, run_func, i_input_func, i_cancel_func);
93 actions_register("DirectionalTargetSouthWest", setup_southwest_target_func,
94 free_func, run_func, i_input_func, i_cancel_func);
95 actions_register("DirectionalTargetSouthEast", setup_southeast_target_func,
96 free_func, run_func, i_input_func, i_cancel_func);
99 static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
104 o = g_new0(Options, 1);
107 if ((n = parse_find_node("dialog", node)))
108 o->dialog = parse_bool(doc, n);
109 if ((n = parse_find_node("panels", node)))
110 o->dock_windows = parse_bool(doc, n);
111 if ((n = parse_find_node("desktop", node)))
112 o->desktop_windows = parse_bool(doc, n);
114 if ((n = parse_find_node("finalactions", node))) {
117 m = parse_find_node("action", n->xmlChildrenNode);
119 ObActionsAct *action = actions_parse(i, doc, m);
120 if (action) o->actions = g_slist_prepend(o->actions, action);
121 m = parse_find_node("action", m->next);
125 o->actions = g_slist_prepend(o->actions,
126 actions_parse_string("Focus"));
127 o->actions = g_slist_prepend(o->actions,
128 actions_parse_string("Raise"));
129 o->actions = g_slist_prepend(o->actions,
130 actions_parse_string("Unshade"));
136 static gpointer setup_north_cycle_func(ObParseInst *i,
137 xmlDocPtr doc, xmlNodePtr node)
139 Options *o = setup_func(i, doc, node);
140 o->interactive = TRUE;
141 o->direction = OB_DIRECTION_NORTH;
145 static gpointer setup_south_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_SOUTH;
154 static gpointer setup_east_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_EAST;
163 static gpointer setup_west_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_WEST;
172 static gpointer setup_northwest_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_NORTHWEST;
181 static gpointer setup_northeast_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_EAST;
190 static gpointer setup_southwest_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_SOUTHWEST;
199 static gpointer setup_southeast_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_SOUTHEAST;
208 static gpointer setup_north_target_func(ObParseInst *i,
209 xmlDocPtr doc, xmlNodePtr node)
211 Options *o = setup_func(i, doc, node);
212 o->interactive = FALSE;
213 o->direction = OB_DIRECTION_NORTH;
217 static gpointer setup_south_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_SOUTH;
226 static gpointer setup_east_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_EAST;
235 static gpointer setup_west_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_WEST;
244 static gpointer setup_northwest_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_NORTHWEST;
253 static gpointer setup_northeast_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_NORTHEAST;
262 static gpointer setup_southwest_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_SOUTHWEST;
271 static gpointer setup_southeast_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_SOUTHEAST;
280 static void free_func(gpointer options)
282 Options *o = options;
285 actions_act_unref(o->actions->data);
286 o->actions = g_slist_delete_link(o->actions, o->actions);
292 static gboolean run_func(ObActionsData *data, gpointer options)
294 Options *o = options;
297 end_cycle(FALSE, data->state, o);
299 focus_directional_cycle(o->direction,
308 return o->interactive;
311 static gboolean i_input_func(guint initial_state,
316 if (e->type == KeyPress) {
317 /* Escape cancels no matter what */
318 if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) {
319 end_cycle(TRUE, e->xkey.state, options);
323 /* There were no modifiers and they pressed enter */
324 else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN) &&
327 end_cycle(FALSE, e->xkey.state, options);
331 /* They released the modifiers */
332 else if (e->type == KeyRelease && initial_state &&
333 (e->xkey.state & initial_state) == 0)
335 end_cycle(FALSE, e->xkey.state, options);
342 static void i_cancel_func(gpointer options)
344 /* we get cancelled when we move focus, but we're not cycling anymore, so
347 end_cycle(TRUE, 0, options);
350 static void end_cycle(gboolean cancel, guint state, Options *o)
352 struct _ObClient *ft;
354 ft = focus_directional_cycle(o->direction,
363 actions_run_acts(o->actions, OB_USER_ACTION_KEYBOARD_KEY,
364 state, -1, -1, 0, OB_FRAME_CONTEXT_NONE, ft);