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 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
,
32 static void i_cancel_func(gpointer options
);
34 static void end_cycle(gboolean cancel
, guint state
, Options
*o
);
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
);
54 void action_directionalwindows_startup(void)
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
);
95 static gpointer
setup_func(xmlNodePtr node
)
100 o
= g_new0(Options
, 1);
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
;
139 if ((n
= obt_parse_find_node(node
, "finalactions"))) {
142 m
= obt_parse_find_node(n
->children
, "action");
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");
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"));
161 static gpointer
setup_cycle_func(xmlNodePtr node
)
163 Options
*o
= setup_func(node
);
164 o
->interactive
= TRUE
;
168 static gpointer
setup_target_func(xmlNodePtr node
)
170 Options
*o
= setup_func(node
);
171 o
->interactive
= FALSE
;
175 static void free_func(gpointer options
)
177 Options
*o
= options
;
180 actions_act_unref(o
->actions
->data
);
181 o
->actions
= g_slist_delete_link(o
->actions
, o
->actions
);
187 static gboolean
run_func(ObActionsData
*data
, gpointer options
)
189 Options
*o
= options
;
192 end_cycle(FALSE
, data
->state
, o
);
194 struct _ObClient
*ft
;
196 ft
= focus_directional_cycle(o
->direction
,
206 if (o
->raise
&& ft
) stacking_temp_raise(CLIENT_AS_WINDOW(ft
));
209 return o
->interactive
;
212 static gboolean
i_input_func(guint initial_state
,
217 if (e
->type
== KeyPress
) {
218 /* Escape cancels no matter what */
219 if (e
->xkey
.keycode
== ob_keycode(OB_KEY_ESCAPE
)) {
220 end_cycle(TRUE
, e
->xkey
.state
, options
);
224 /* There were no modifiers and they pressed enter */
225 else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RETURN
) &&
228 end_cycle(FALSE
, e
->xkey
.state
, options
);
232 /* They released the modifiers */
233 else if (e
->type
== KeyRelease
&& initial_state
&&
234 (e
->xkey
.state
& initial_state
) == 0)
236 end_cycle(FALSE
, e
->xkey
.state
, options
);
243 static void i_cancel_func(gpointer options
)
245 /* we get cancelled when we move focus, but we're not cycling anymore, so
248 end_cycle(TRUE
, 0, options
);
251 static void end_cycle(gboolean cancel
, guint state
, Options
*o
)
253 struct _ObClient
*ft
;
255 ft
= focus_directional_cycle(o
->direction
,
265 actions_run_acts(o
->actions
, OB_USER_ACTION_KEYBOARD_KEY
,
266 state
, -1, -1, 0, OB_FRAME_CONTEXT_NONE
, ft
);
271 /* 3.4-compatibility */
272 static gpointer
setup_north_cycle_func(xmlNodePtr node
)
274 Options
*o
= setup_cycle_func(node
);
275 o
->direction
= OB_DIRECTION_NORTH
;
279 static gpointer
setup_south_cycle_func(xmlNodePtr node
)
281 Options
*o
= setup_cycle_func(node
);
282 o
->direction
= OB_DIRECTION_SOUTH
;
286 static gpointer
setup_east_cycle_func(xmlNodePtr node
)
288 Options
*o
= setup_cycle_func(node
);
289 o
->direction
= OB_DIRECTION_EAST
;
293 static gpointer
setup_west_cycle_func(xmlNodePtr node
)
295 Options
*o
= setup_cycle_func(node
);
296 o
->direction
= OB_DIRECTION_WEST
;
300 static gpointer
setup_northwest_cycle_func(xmlNodePtr node
)
302 Options
*o
= setup_cycle_func(node
);
303 o
->direction
= OB_DIRECTION_NORTHWEST
;
307 static gpointer
setup_northeast_cycle_func(xmlNodePtr node
)
309 Options
*o
= setup_cycle_func(node
);
310 o
->direction
= OB_DIRECTION_EAST
;
314 static gpointer
setup_southwest_cycle_func(xmlNodePtr node
)
316 Options
*o
= setup_cycle_func(node
);
317 o
->direction
= OB_DIRECTION_SOUTHWEST
;
321 static gpointer
setup_southeast_cycle_func(xmlNodePtr node
)
323 Options
*o
= setup_cycle_func(node
);
324 o
->direction
= OB_DIRECTION_SOUTHEAST
;
328 static gpointer
setup_north_target_func(xmlNodePtr node
)
330 Options
*o
= setup_target_func(node
);
331 o
->direction
= OB_DIRECTION_NORTH
;
335 static gpointer
setup_south_target_func(xmlNodePtr node
)
337 Options
*o
= setup_target_func(node
);
338 o
->direction
= OB_DIRECTION_SOUTH
;
342 static gpointer
setup_east_target_func(xmlNodePtr node
)
344 Options
*o
= setup_target_func(node
);
345 o
->direction
= OB_DIRECTION_EAST
;
349 static gpointer
setup_west_target_func(xmlNodePtr node
)
351 Options
*o
= setup_target_func(node
);
352 o
->direction
= OB_DIRECTION_WEST
;
356 static gpointer
setup_northwest_target_func(xmlNodePtr node
)
358 Options
*o
= setup_target_func(node
);
359 o
->direction
= OB_DIRECTION_NORTHWEST
;
363 static gpointer
setup_northeast_target_func(xmlNodePtr node
)
365 Options
*o
= setup_target_func(node
);
366 o
->direction
= OB_DIRECTION_NORTHEAST
;
370 static gpointer
setup_southwest_target_func(xmlNodePtr node
)
372 Options
*o
= setup_target_func(node
);
373 o
->direction
= OB_DIRECTION_SOUTHWEST
;
377 static gpointer
setup_southeast_target_func(xmlNodePtr node
)
379 Options
*o
= setup_target_func(node
);
380 o
->direction
= OB_DIRECTION_SOUTHEAST
;