1 #include "openbox/actions.h"
2 #include "openbox/screen.h"
3 #include "openbox/client.h"
4 #include "openbox/openbox.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_parse_find_node(node, "to"))) {
164 gchar *s = obt_parse_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_parse_find_node(node, "wrap")))
205 o->u.rel.wrap = obt_parse_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_parse_find_node(node, "follow")))
244 o->follow = obt_parse_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,
303 if (e->type == KeyPress) {
304 /* Escape cancels no matter what */
305 if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) {
309 /* There were no modifiers and they pressed enter */
310 else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN) &&
316 /* They released the modifiers */
317 else if (e->type == KeyRelease && initial_state &&
318 (e->xkey.state & initial_state) == 0)
326 static gboolean i_pre_func(guint initial_state, gpointer options)
328 if (!initial_state) {
329 Options *o = options;
330 o->interactive = FALSE;
334 screen_show_desktop_popup(screen_desktop, TRUE);
339 static void i_post_func(gpointer options)
341 screen_hide_desktop_popup();
344 /* 3.4-compatilibity */
345 static gpointer setup_follow(xmlNodePtr node)
348 Options *o = g_new0(Options, 1);
351 if ((n = obt_parse_find_node(node, "follow")))
352 o->follow = obt_parse_node_bool(n);
356 static gpointer setup_go_last_func(xmlNodePtr node)
358 Options *o = g_new0(Options, 1);
363 static gpointer setup_send_last_func(xmlNodePtr node)
365 Options *o = setup_follow(node);
370 static gpointer setup_go_abs_func(xmlNodePtr node)
373 Options *o = g_new0(Options, 1);
375 if ((n = obt_parse_find_node(node, "desktop")))
376 o->u.abs.desktop = obt_parse_node_int(n) - 1;
378 o->u.abs.desktop = screen_desktop;
382 static gpointer setup_send_abs_func(xmlNodePtr node)
385 Options *o = setup_follow(node);
387 if ((n = obt_parse_find_node(node, "desktop")))
388 o->u.abs.desktop = obt_parse_node_int(n) - 1;
390 o->u.abs.desktop = screen_desktop;
394 static void setup_rel(Options *o, xmlNodePtr node, gboolean lin,
396 ObActionsIPreFunc *pre,
397 ObActionsIInputFunc *input,
398 ObActionsIPostFunc *post)
403 o->u.rel.linear = lin;
405 o->u.rel.wrap = TRUE;
407 if ((n = obt_parse_find_node(node, "wrap")))
408 o->u.rel.wrap = obt_parse_node_bool(n);
411 o->interactive = TRUE;
413 *input = i_input_func;
418 static gpointer setup_go_next_func(xmlNodePtr node,
419 ObActionsIPreFunc *pre,
420 ObActionsIInputFunc *input,
421 ObActionsICancelFunc *cancel,
422 ObActionsIPostFunc *post)
424 Options *o = g_new0(Options, 1);
425 setup_rel(o, node, TRUE, OB_DIRECTION_EAST, pre, input, post);
429 static gpointer setup_send_next_func(xmlNodePtr node,
430 ObActionsIPreFunc *pre,
431 ObActionsIInputFunc *input,
432 ObActionsICancelFunc *cancel,
433 ObActionsIPostFunc *post)
435 Options *o = setup_follow(node);
436 setup_rel(o, node, TRUE, OB_DIRECTION_EAST,
437 pre, (o->follow ? input : NULL), post);
441 static gpointer setup_go_prev_func(xmlNodePtr node,
442 ObActionsIPreFunc *pre,
443 ObActionsIInputFunc *input,
444 ObActionsICancelFunc *cancel,
445 ObActionsIPostFunc *post)
447 Options *o = g_new0(Options, 1);
448 setup_rel(o, node, TRUE, OB_DIRECTION_WEST, pre, input, post);
452 static gpointer setup_send_prev_func(xmlNodePtr node,
453 ObActionsIPreFunc *pre,
454 ObActionsIInputFunc *input,
455 ObActionsICancelFunc *cancel,
456 ObActionsIPostFunc *post)
458 Options *o = setup_follow(node);
459 setup_rel(o, node, TRUE, OB_DIRECTION_WEST,
460 pre, (o->follow ? input : NULL), post);
464 static gpointer setup_go_left_func(xmlNodePtr node,
465 ObActionsIPreFunc *pre,
466 ObActionsIInputFunc *input,
467 ObActionsICancelFunc *cancel,
468 ObActionsIPostFunc *post)
470 Options *o = g_new0(Options, 1);
471 setup_rel(o, node, FALSE, OB_DIRECTION_WEST, pre, input, post);
475 static gpointer setup_send_left_func(xmlNodePtr node,
476 ObActionsIPreFunc *pre,
477 ObActionsIInputFunc *input,
478 ObActionsICancelFunc *cancel,
479 ObActionsIPostFunc *post)
481 Options *o = setup_follow(node);
482 setup_rel(o, node, FALSE, OB_DIRECTION_WEST,
483 pre, (o->follow ? input : NULL), post);
487 static gpointer setup_go_right_func(xmlNodePtr node,
488 ObActionsIPreFunc *pre,
489 ObActionsIInputFunc *input,
490 ObActionsICancelFunc *cancel,
491 ObActionsIPostFunc *post)
493 Options *o = g_new0(Options, 1);
494 setup_rel(o, node, FALSE, OB_DIRECTION_EAST, pre, input, post);
498 static gpointer setup_send_right_func(xmlNodePtr node,
499 ObActionsIPreFunc *pre,
500 ObActionsIInputFunc *input,
501 ObActionsICancelFunc *cancel,
502 ObActionsIPostFunc *post)
504 Options *o = setup_follow(node);
505 setup_rel(o, node, FALSE, OB_DIRECTION_EAST,
506 pre, (o->follow ? input : NULL), post);
510 static gpointer setup_go_up_func(xmlNodePtr node,
511 ObActionsIPreFunc *pre,
512 ObActionsIInputFunc *input,
513 ObActionsICancelFunc *cancel,
514 ObActionsIPostFunc *post)
516 Options *o = g_new0(Options, 1);
517 setup_rel(o, node, FALSE, OB_DIRECTION_NORTH, pre, input, post);
521 static gpointer setup_send_up_func(xmlNodePtr node,
522 ObActionsIPreFunc *pre,
523 ObActionsIInputFunc *input,
524 ObActionsICancelFunc *cancel,
525 ObActionsIPostFunc *post)
527 Options *o = setup_follow(node);
528 setup_rel(o, node, FALSE, OB_DIRECTION_NORTH,
529 pre, (o->follow ? input : NULL), post);
533 static gpointer setup_go_down_func(xmlNodePtr node,
534 ObActionsIPreFunc *pre,
535 ObActionsIInputFunc *input,
536 ObActionsICancelFunc *cancel,
537 ObActionsIPostFunc *post)
539 Options *o = g_new0(Options, 1);
540 setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH, pre, input, post);
544 static gpointer setup_send_down_func(xmlNodePtr node,
545 ObActionsIPreFunc *pre,
546 ObActionsIInputFunc *input,
547 ObActionsICancelFunc *cancel,
548 ObActionsIPostFunc *post)
550 Options *o = setup_follow(node);
551 setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH,
552 pre, (o->follow ? input : NULL), post);