1 #include "openbox/actions.h"
2 #include "openbox/screen.h"
3 #include "openbox/client.h"
4 #include "openbox/openbox.h"
5 #include "obt/keyboard.h"
31 static gpointer setup_go_func(xmlNodePtr node,
32 ObActionsIPreFunc *pre,
33 ObActionsIInputFunc *input,
34 ObActionsICancelFunc *cancel,
35 ObActionsIPostFunc *post);
36 static gpointer setup_send_func(xmlNodePtr node,
37 ObActionsIPreFunc *pre,
38 ObActionsIInputFunc *input,
39 ObActionsICancelFunc *cancel,
40 ObActionsIPostFunc *post);
41 static gboolean run_func(ObActionsData *data, gpointer options);
43 static gboolean i_pre_func(guint state, gpointer options);
44 static gboolean i_input_func(guint initial_state,
48 static void i_post_func(gpointer options);
50 /* 3.4-compatibility */
51 static gpointer setup_go_last_func(xmlNodePtr node);
52 static gpointer setup_send_last_func(xmlNodePtr node);
53 static gpointer setup_go_abs_func(xmlNodePtr node);
54 static gpointer setup_send_abs_func(xmlNodePtr node);
55 static gpointer setup_go_next_func(xmlNodePtr node,
56 ObActionsIPreFunc *pre,
57 ObActionsIInputFunc *input,
58 ObActionsICancelFunc *cancel,
59 ObActionsIPostFunc *post);
60 static gpointer setup_send_next_func(xmlNodePtr node,
61 ObActionsIPreFunc *pre,
62 ObActionsIInputFunc *input,
63 ObActionsICancelFunc *cancel,
64 ObActionsIPostFunc *post);
65 static gpointer setup_go_prev_func(xmlNodePtr node,
66 ObActionsIPreFunc *pre,
67 ObActionsIInputFunc *input,
68 ObActionsICancelFunc *cancel,
69 ObActionsIPostFunc *post);
70 static gpointer setup_send_prev_func(xmlNodePtr node,
71 ObActionsIPreFunc *pre,
72 ObActionsIInputFunc *input,
73 ObActionsICancelFunc *cancel,
74 ObActionsIPostFunc *post);
75 static gpointer setup_go_left_func(xmlNodePtr node,
76 ObActionsIPreFunc *pre,
77 ObActionsIInputFunc *input,
78 ObActionsICancelFunc *cancel,
79 ObActionsIPostFunc *post);
80 static gpointer setup_send_left_func(xmlNodePtr node,
81 ObActionsIPreFunc *pre,
82 ObActionsIInputFunc *input,
83 ObActionsICancelFunc *cancel,
84 ObActionsIPostFunc *post);
85 static gpointer setup_go_right_func(xmlNodePtr node,
86 ObActionsIPreFunc *pre,
87 ObActionsIInputFunc *input,
88 ObActionsICancelFunc *cancel,
89 ObActionsIPostFunc *post);
90 static gpointer setup_send_right_func(xmlNodePtr node,
91 ObActionsIPreFunc *pre,
92 ObActionsIInputFunc *input,
93 ObActionsICancelFunc *cancel,
94 ObActionsIPostFunc *post);
95 static gpointer setup_go_up_func(xmlNodePtr node,
96 ObActionsIPreFunc *pre,
97 ObActionsIInputFunc *input,
98 ObActionsICancelFunc *cancel,
99 ObActionsIPostFunc *post);
100 static gpointer setup_send_up_func(xmlNodePtr node,
101 ObActionsIPreFunc *pre,
102 ObActionsIInputFunc *input,
103 ObActionsICancelFunc *cancel,
104 ObActionsIPostFunc *post);
105 static gpointer setup_go_down_func(xmlNodePtr node,
106 ObActionsIPreFunc *pre,
107 ObActionsIInputFunc *input,
108 ObActionsICancelFunc *cancel,
109 ObActionsIPostFunc *post);
110 static gpointer setup_send_down_func(xmlNodePtr node,
111 ObActionsIPreFunc *pre,
112 ObActionsIInputFunc *input,
113 ObActionsICancelFunc *cancel,
114 ObActionsIPostFunc *post);
116 void action_desktop_startup(void)
118 actions_register_i("GoToDesktop", setup_go_func, g_free, run_func);
119 actions_register_i("SendToDesktop", setup_send_func, g_free, run_func);
120 /* 3.4-compatibility */
121 actions_register("DesktopLast", setup_go_last_func, g_free, run_func);
122 actions_register("SendToDesktopLast", setup_send_last_func,
124 actions_register("Desktop", setup_go_abs_func, g_free, run_func);
125 actions_register("SendToDesktop", setup_send_abs_func, g_free, run_func);
126 actions_register_i("DesktopNext", setup_go_next_func, g_free, run_func);
127 actions_register_i("SendToDesktopNext", setup_send_next_func,
129 actions_register_i("DesktopPrevious", setup_go_prev_func,
131 actions_register_i("SendToDesktopPrevious", setup_send_prev_func,
133 actions_register_i("DesktopLeft", setup_go_left_func, g_free, run_func);
134 actions_register_i("SendToDesktopLeft", setup_send_left_func,
136 actions_register_i("DesktopRight", setup_go_right_func, g_free, run_func);
137 actions_register_i("SendToDesktopRight", setup_send_right_func,
139 actions_register_i("DesktopUp", setup_go_up_func, g_free, run_func);
140 actions_register_i("SendToDesktopUp", setup_send_up_func,
142 actions_register_i("DesktopDown", setup_go_down_func, g_free, run_func);
143 actions_register_i("SendToDesktopDown", setup_send_down_func,
147 static gpointer setup_func(xmlNodePtr node,
148 ObActionsIPreFunc *pre,
149 ObActionsIInputFunc *input,
150 ObActionsICancelFunc *cancel,
151 ObActionsIPostFunc *post)
156 o = g_new0(Options, 1);
157 /* don't go anywhere if there are no options given */
159 o->u.abs.desktop = screen_desktop;
160 /* wrap by default - it's handy! */
161 o->u.rel.wrap = TRUE;
163 if ((n = obt_xml_find_node(node, "to"))) {
164 gchar *s = obt_xml_node_string(n);
165 if (!g_ascii_strcasecmp(s, "last"))
167 else if (!g_ascii_strcasecmp(s, "next")) {
169 o->u.rel.linear = TRUE;
170 o->u.rel.dir = OB_DIRECTION_EAST;
172 else if (!g_ascii_strcasecmp(s, "previous")) {
174 o->u.rel.linear = TRUE;
175 o->u.rel.dir = OB_DIRECTION_WEST;
177 else if (!g_ascii_strcasecmp(s, "north") ||
178 !g_ascii_strcasecmp(s, "up")) {
180 o->u.rel.dir = OB_DIRECTION_NORTH;
182 else if (!g_ascii_strcasecmp(s, "south") ||
183 !g_ascii_strcasecmp(s, "down")) {
185 o->u.rel.dir = OB_DIRECTION_SOUTH;
187 else if (!g_ascii_strcasecmp(s, "west") ||
188 !g_ascii_strcasecmp(s, "left")) {
190 o->u.rel.dir = OB_DIRECTION_WEST;
192 else if (!g_ascii_strcasecmp(s, "east") ||
193 !g_ascii_strcasecmp(s, "right")) {
195 o->u.rel.dir = OB_DIRECTION_EAST;
199 o->u.abs.desktop = atoi(s) - 1;
204 if ((n = obt_xml_find_node(node, "wrap")))
205 o->u.rel.wrap = obt_xml_node_bool(n);
211 static gpointer setup_go_func(xmlNodePtr node,
212 ObActionsIPreFunc *pre,
213 ObActionsIInputFunc *input,
214 ObActionsICancelFunc *cancel,
215 ObActionsIPostFunc *post)
219 o = setup_func(node, pre, input, cancel, post);
220 if (o->type == RELATIVE) {
221 o->interactive = TRUE;
223 *input = i_input_func;
230 static gpointer setup_send_func(xmlNodePtr node,
231 ObActionsIPreFunc *pre,
232 ObActionsIInputFunc *input,
233 ObActionsICancelFunc *cancel,
234 ObActionsIPostFunc *post)
239 o = setup_func(node, pre, input, cancel, post);
243 if ((n = obt_xml_find_node(node, "follow")))
244 o->follow = obt_xml_node_bool(n);
246 if (o->type == RELATIVE && o->follow) {
247 o->interactive = TRUE;
249 *input = i_input_func;
256 /* Always return FALSE because its not interactive */
257 static gboolean run_func(ObActionsData *data, gpointer options)
259 Options *o = options;
264 d = screen_last_desktop;
267 d = o->u.abs.desktop;
270 d = screen_find_desktop(screen_desktop,
271 o->u.rel.dir, o->u.rel.wrap, o->u.rel.linear);
274 g_assert_not_reached();
277 if (d < screen_num_desktops && d != screen_desktop) {
280 actions_client_move(data, TRUE);
281 if (o->send && data->client && client_normal(data->client)) {
282 client_set_desktop(data->client, d, o->follow, FALSE);
287 screen_set_desktop(d, TRUE);
289 client_bring_helper_windows(data->client);
292 actions_client_move(data, FALSE);
295 return o->interactive;
298 static gboolean i_input_func(guint initial_state,
305 mods = obt_keyboard_only_modmasks(e->xkey.state);
306 if (e->type == KeyRelease) {
307 /* remove from the state the mask of the modifier key being
308 released, if it is a modifier key being released that is */
309 mods &= ~obt_keyboard_keycode_to_modmask(e->xkey.keycode);
312 if (e->type == KeyPress) {
313 /* Escape cancels no matter what */
314 if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) {
318 /* There were no modifiers and they pressed enter */
319 else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN) &&
325 /* They released the modifiers */
326 else if (e->type == KeyRelease && initial_state && !(mods & initial_state))
334 static gboolean i_pre_func(guint initial_state, gpointer options)
336 if (!initial_state) {
337 Options *o = options;
338 o->interactive = FALSE;
342 screen_show_desktop_popup(screen_desktop, TRUE);
347 static void i_post_func(gpointer options)
349 screen_hide_desktop_popup();
352 /* 3.4-compatilibity */
353 static gpointer setup_follow(xmlNodePtr node)
356 Options *o = g_new0(Options, 1);
359 if ((n = obt_xml_find_node(node, "follow")))
360 o->follow = obt_xml_node_bool(n);
364 static gpointer setup_go_last_func(xmlNodePtr node)
366 Options *o = g_new0(Options, 1);
371 static gpointer setup_send_last_func(xmlNodePtr node)
373 Options *o = setup_follow(node);
378 static gpointer setup_go_abs_func(xmlNodePtr node)
381 Options *o = g_new0(Options, 1);
383 if ((n = obt_xml_find_node(node, "desktop")))
384 o->u.abs.desktop = obt_xml_node_int(n) - 1;
386 o->u.abs.desktop = screen_desktop;
390 static gpointer setup_send_abs_func(xmlNodePtr node)
393 Options *o = setup_follow(node);
395 if ((n = obt_xml_find_node(node, "desktop")))
396 o->u.abs.desktop = obt_xml_node_int(n) - 1;
398 o->u.abs.desktop = screen_desktop;
402 static void setup_rel(Options *o, xmlNodePtr node, gboolean lin,
404 ObActionsIPreFunc *pre,
405 ObActionsIInputFunc *input,
406 ObActionsIPostFunc *post)
411 o->u.rel.linear = lin;
413 o->u.rel.wrap = TRUE;
415 if ((n = obt_xml_find_node(node, "wrap")))
416 o->u.rel.wrap = obt_xml_node_bool(n);
419 o->interactive = TRUE;
421 *input = i_input_func;
426 static gpointer setup_go_next_func(xmlNodePtr node,
427 ObActionsIPreFunc *pre,
428 ObActionsIInputFunc *input,
429 ObActionsICancelFunc *cancel,
430 ObActionsIPostFunc *post)
432 Options *o = g_new0(Options, 1);
433 setup_rel(o, node, TRUE, OB_DIRECTION_EAST, pre, input, post);
437 static gpointer setup_send_next_func(xmlNodePtr node,
438 ObActionsIPreFunc *pre,
439 ObActionsIInputFunc *input,
440 ObActionsICancelFunc *cancel,
441 ObActionsIPostFunc *post)
443 Options *o = setup_follow(node);
444 setup_rel(o, node, TRUE, OB_DIRECTION_EAST,
445 pre, (o->follow ? input : NULL), post);
449 static gpointer setup_go_prev_func(xmlNodePtr node,
450 ObActionsIPreFunc *pre,
451 ObActionsIInputFunc *input,
452 ObActionsICancelFunc *cancel,
453 ObActionsIPostFunc *post)
455 Options *o = g_new0(Options, 1);
456 setup_rel(o, node, TRUE, OB_DIRECTION_WEST, pre, input, post);
460 static gpointer setup_send_prev_func(xmlNodePtr node,
461 ObActionsIPreFunc *pre,
462 ObActionsIInputFunc *input,
463 ObActionsICancelFunc *cancel,
464 ObActionsIPostFunc *post)
466 Options *o = setup_follow(node);
467 setup_rel(o, node, TRUE, OB_DIRECTION_WEST,
468 pre, (o->follow ? input : NULL), post);
472 static gpointer setup_go_left_func(xmlNodePtr node,
473 ObActionsIPreFunc *pre,
474 ObActionsIInputFunc *input,
475 ObActionsICancelFunc *cancel,
476 ObActionsIPostFunc *post)
478 Options *o = g_new0(Options, 1);
479 setup_rel(o, node, FALSE, OB_DIRECTION_WEST, pre, input, post);
483 static gpointer setup_send_left_func(xmlNodePtr node,
484 ObActionsIPreFunc *pre,
485 ObActionsIInputFunc *input,
486 ObActionsICancelFunc *cancel,
487 ObActionsIPostFunc *post)
489 Options *o = setup_follow(node);
490 setup_rel(o, node, FALSE, OB_DIRECTION_WEST,
491 pre, (o->follow ? input : NULL), post);
495 static gpointer setup_go_right_func(xmlNodePtr node,
496 ObActionsIPreFunc *pre,
497 ObActionsIInputFunc *input,
498 ObActionsICancelFunc *cancel,
499 ObActionsIPostFunc *post)
501 Options *o = g_new0(Options, 1);
502 setup_rel(o, node, FALSE, OB_DIRECTION_EAST, pre, input, post);
506 static gpointer setup_send_right_func(xmlNodePtr node,
507 ObActionsIPreFunc *pre,
508 ObActionsIInputFunc *input,
509 ObActionsICancelFunc *cancel,
510 ObActionsIPostFunc *post)
512 Options *o = setup_follow(node);
513 setup_rel(o, node, FALSE, OB_DIRECTION_EAST,
514 pre, (o->follow ? input : NULL), post);
518 static gpointer setup_go_up_func(xmlNodePtr node,
519 ObActionsIPreFunc *pre,
520 ObActionsIInputFunc *input,
521 ObActionsICancelFunc *cancel,
522 ObActionsIPostFunc *post)
524 Options *o = g_new0(Options, 1);
525 setup_rel(o, node, FALSE, OB_DIRECTION_NORTH, pre, input, post);
529 static gpointer setup_send_up_func(xmlNodePtr node,
530 ObActionsIPreFunc *pre,
531 ObActionsIInputFunc *input,
532 ObActionsICancelFunc *cancel,
533 ObActionsIPostFunc *post)
535 Options *o = setup_follow(node);
536 setup_rel(o, node, FALSE, OB_DIRECTION_NORTH,
537 pre, (o->follow ? input : NULL), post);
541 static gpointer setup_go_down_func(xmlNodePtr node,
542 ObActionsIPreFunc *pre,
543 ObActionsIInputFunc *input,
544 ObActionsICancelFunc *cancel,
545 ObActionsIPostFunc *post)
547 Options *o = g_new0(Options, 1);
548 setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH, pre, input, post);
552 static gpointer setup_send_down_func(xmlNodePtr node,
553 ObActionsIPreFunc *pre,
554 ObActionsIInputFunc *input,
555 ObActionsICancelFunc *cancel,
556 ObActionsIPostFunc *post)
558 Options *o = setup_follow(node);
559 setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH,
560 pre, (o->follow ? input : NULL), post);