]> Dogcows Code - chaz/openbox/blob - openbox/action.c
when ending actions which can move windows, and we were using the mouse, instead...
[chaz/openbox] / openbox / action.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3 action.c for the Openbox window manager
4 Copyright (c) 2003 Ben Jansens
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 See the COPYING file for a copy of the GNU General Public License.
17 */
18
19 #include "debug.h"
20 #include "client.h"
21 #include "focus.h"
22 #include "moveresize.h"
23 #include "menu.h"
24 #include "prop.h"
25 #include "stacking.h"
26 #include "screen.h"
27 #include "action.h"
28 #include "openbox.h"
29 #include "grab.h"
30 #include "keyboard.h"
31 #include "event.h"
32 #include "config.h"
33
34 #include <glib.h>
35
36 inline void client_action_start(union ActionData *data)
37 {
38 if (config_focus_follow)
39 if (data->any.context != OB_FRAME_CONTEXT_CLIENT && !data->any.button)
40 grab_pointer(TRUE, OB_CURSOR_NONE);
41 }
42
43 inline void client_action_end(union ActionData *data)
44 {
45 if (config_focus_follow)
46 if (data->any.context != OB_FRAME_CONTEXT_CLIENT) {
47 if (!data->any.button) {
48 grab_pointer(FALSE, OB_CURSOR_NONE);
49 } else {
50 ObClient *c;
51
52 if ((c = client_under_pointer()))
53 event_enter_client(c);
54 }
55 }
56 }
57
58 typedef struct ActionString {
59 const gchar *name;
60 void (*func)(union ActionData *);
61 void (*setup)(ObAction **, ObUserAction uact);
62 } ActionString;
63
64 static ObAction *action_new(void (*func)(union ActionData *data),
65 ObUserAction uact)
66 {
67 ObAction *a = g_new0(ObAction, 1);
68 a->func = func;
69
70 return a;
71 }
72
73 void action_free(ObAction *a)
74 {
75 if (a == NULL) return;
76
77 /* deal with pointers */
78 if (a->func == action_execute || a->func == action_restart)
79 g_free(a->data.execute.path);
80 else if (a->func == action_showmenu)
81 g_free(a->data.showmenu.name);
82
83 g_free(a);
84 }
85
86 void setup_action_directional_focus_north(ObAction **a, ObUserAction uact)
87 {
88 (*a)->data.interdiraction.inter.any.interactive = TRUE;
89 (*a)->data.interdiraction.direction = OB_DIRECTION_NORTH;
90 }
91
92 void setup_action_directional_focus_east(ObAction **a, ObUserAction uact)
93 {
94 (*a)->data.interdiraction.inter.any.interactive = TRUE;
95 (*a)->data.interdiraction.direction = OB_DIRECTION_EAST;
96 }
97
98 void setup_action_directional_focus_south(ObAction **a, ObUserAction uact)
99 {
100 (*a)->data.interdiraction.inter.any.interactive = TRUE;
101 (*a)->data.interdiraction.direction = OB_DIRECTION_SOUTH;
102 }
103
104 void setup_action_directional_focus_west(ObAction **a, ObUserAction uact)
105 {
106 (*a)->data.interdiraction.inter.any.interactive = TRUE;
107 (*a)->data.interdiraction.direction = OB_DIRECTION_WEST;
108 }
109
110 void setup_action_directional_focus_northeast(ObAction **a, ObUserAction uact)
111 {
112 (*a)->data.interdiraction.inter.any.interactive = TRUE;
113 (*a)->data.interdiraction.direction = OB_DIRECTION_NORTHEAST;
114 }
115
116 void setup_action_directional_focus_southeast(ObAction **a, ObUserAction uact)
117 {
118 (*a)->data.interdiraction.inter.any.interactive = TRUE;
119 (*a)->data.interdiraction.direction = OB_DIRECTION_SOUTHEAST;
120 }
121
122 void setup_action_directional_focus_southwest(ObAction **a, ObUserAction uact)
123 {
124 (*a)->data.interdiraction.inter.any.interactive = TRUE;
125 (*a)->data.interdiraction.direction = OB_DIRECTION_SOUTHWEST;
126 }
127
128 void setup_action_directional_focus_northwest(ObAction **a, ObUserAction uact)
129 {
130 (*a)->data.interdiraction.inter.any.interactive = TRUE;
131 (*a)->data.interdiraction.direction = OB_DIRECTION_NORTHWEST;
132 }
133
134 void setup_action_send_to_desktop(ObAction **a, ObUserAction uact)
135 {
136 (*a)->data.sendto.follow = TRUE;
137 }
138
139 void setup_action_send_to_desktop_prev(ObAction **a, ObUserAction uact)
140 {
141 (*a)->data.sendtodir.inter.any.interactive = TRUE;
142 (*a)->data.sendtodir.dir = OB_DIRECTION_WEST;
143 (*a)->data.sendtodir.linear = TRUE;
144 (*a)->data.sendtodir.wrap = TRUE;
145 (*a)->data.sendtodir.follow = TRUE;
146 }
147
148 void setup_action_send_to_desktop_next(ObAction **a, ObUserAction uact)
149 {
150 (*a)->data.sendtodir.inter.any.interactive = TRUE;
151 (*a)->data.sendtodir.dir = OB_DIRECTION_EAST;
152 (*a)->data.sendtodir.linear = TRUE;
153 (*a)->data.sendtodir.wrap = TRUE;
154 (*a)->data.sendtodir.follow = TRUE;
155 }
156
157 void setup_action_send_to_desktop_left(ObAction **a, ObUserAction uact)
158 {
159 (*a)->data.sendtodir.inter.any.interactive = TRUE;
160 (*a)->data.sendtodir.dir = OB_DIRECTION_WEST;
161 (*a)->data.sendtodir.linear = FALSE;
162 (*a)->data.sendtodir.wrap = TRUE;
163 (*a)->data.sendtodir.follow = TRUE;
164 }
165
166 void setup_action_send_to_desktop_right(ObAction **a, ObUserAction uact)
167 {
168 (*a)->data.sendtodir.inter.any.interactive = TRUE;
169 (*a)->data.sendtodir.dir = OB_DIRECTION_EAST;
170 (*a)->data.sendtodir.linear = FALSE;
171 (*a)->data.sendtodir.wrap = TRUE;
172 (*a)->data.sendtodir.follow = TRUE;
173 }
174
175 void setup_action_send_to_desktop_up(ObAction **a, ObUserAction uact)
176 {
177 (*a)->data.sendtodir.inter.any.interactive = TRUE;
178 (*a)->data.sendtodir.dir = OB_DIRECTION_NORTH;
179 (*a)->data.sendtodir.linear = FALSE;
180 (*a)->data.sendtodir.wrap = TRUE;
181 (*a)->data.sendtodir.follow = TRUE;
182 }
183
184 void setup_action_send_to_desktop_down(ObAction **a, ObUserAction uact)
185 {
186 (*a)->data.sendtodir.inter.any.interactive = TRUE;
187 (*a)->data.sendtodir.dir = OB_DIRECTION_SOUTH;
188 (*a)->data.sendtodir.linear = FALSE;
189 (*a)->data.sendtodir.wrap = TRUE;
190 (*a)->data.sendtodir.follow = TRUE;
191 }
192
193 void setup_action_desktop_prev(ObAction **a, ObUserAction uact)
194 {
195 (*a)->data.desktopdir.inter.any.interactive = TRUE;
196 (*a)->data.desktopdir.dir = OB_DIRECTION_WEST;
197 (*a)->data.desktopdir.linear = TRUE;
198 (*a)->data.desktopdir.wrap = TRUE;
199 }
200
201 void setup_action_desktop_next(ObAction **a, ObUserAction uact)
202 {
203 (*a)->data.desktopdir.inter.any.interactive = TRUE;
204 (*a)->data.desktopdir.dir = OB_DIRECTION_EAST;
205 (*a)->data.desktopdir.linear = TRUE;
206 (*a)->data.desktopdir.wrap = TRUE;
207 }
208
209 void setup_action_desktop_left(ObAction **a, ObUserAction uact)
210 {
211 (*a)->data.desktopdir.inter.any.interactive = TRUE;
212 (*a)->data.desktopdir.dir = OB_DIRECTION_WEST;
213 (*a)->data.desktopdir.linear = FALSE;
214 (*a)->data.desktopdir.wrap = TRUE;
215 }
216
217 void setup_action_desktop_right(ObAction **a, ObUserAction uact)
218 {
219 (*a)->data.desktopdir.inter.any.interactive = TRUE;
220 (*a)->data.desktopdir.dir = OB_DIRECTION_EAST;
221 (*a)->data.desktopdir.linear = FALSE;
222 (*a)->data.desktopdir.wrap = TRUE;
223 }
224
225 void setup_action_desktop_up(ObAction **a, ObUserAction uact)
226 {
227 (*a)->data.desktopdir.inter.any.interactive = TRUE;
228 (*a)->data.desktopdir.dir = OB_DIRECTION_NORTH;
229 (*a)->data.desktopdir.linear = FALSE;
230 (*a)->data.desktopdir.wrap = TRUE;
231 }
232
233 void setup_action_desktop_down(ObAction **a, ObUserAction uact)
234 {
235 (*a)->data.desktopdir.inter.any.interactive = TRUE;
236 (*a)->data.desktopdir.dir = OB_DIRECTION_SOUTH;
237 (*a)->data.desktopdir.linear = FALSE;
238 (*a)->data.desktopdir.wrap = TRUE;
239 }
240
241 void setup_action_cycle_windows_next(ObAction **a, ObUserAction uact)
242 {
243 (*a)->data.cycle.inter.any.interactive = TRUE;
244 (*a)->data.cycle.linear = FALSE;
245 (*a)->data.cycle.forward = TRUE;
246 }
247
248 void setup_action_cycle_windows_previous(ObAction **a, ObUserAction uact)
249 {
250 (*a)->data.cycle.inter.any.interactive = TRUE;
251 (*a)->data.cycle.linear = FALSE;
252 (*a)->data.cycle.forward = FALSE;
253 }
254
255 void setup_action_movetoedge_north(ObAction **a, ObUserAction uact)
256 {
257 (*a)->data.diraction.direction = OB_DIRECTION_NORTH;
258 }
259
260 void setup_action_movetoedge_south(ObAction **a, ObUserAction uact)
261 {
262 (*a)->data.diraction.direction = OB_DIRECTION_SOUTH;
263 }
264
265 void setup_action_movetoedge_east(ObAction **a, ObUserAction uact)
266 {
267 (*a)->data.diraction.direction = OB_DIRECTION_EAST;
268 }
269
270 void setup_action_movetoedge_west(ObAction **a, ObUserAction uact)
271 {
272 (*a)->data.diraction.direction = OB_DIRECTION_WEST;
273 }
274
275 void setup_action_growtoedge_north(ObAction **a, ObUserAction uact)
276 {
277 (*a)->data.diraction.direction = OB_DIRECTION_NORTH;
278 }
279
280 void setup_action_growtoedge_south(ObAction **a, ObUserAction uact)
281 {
282 (*a)->data.diraction.direction = OB_DIRECTION_SOUTH;
283 }
284
285 void setup_action_growtoedge_east(ObAction **a, ObUserAction uact)
286 {
287 (*a)->data.diraction.direction = OB_DIRECTION_EAST;
288 }
289
290 void setup_action_growtoedge_west(ObAction **a, ObUserAction uact)
291 {
292 (*a)->data.diraction.direction = OB_DIRECTION_WEST;
293 }
294
295 void setup_action_top_layer(ObAction **a, ObUserAction uact)
296 {
297 (*a)->data.layer.layer = 1;
298 }
299
300 void setup_action_normal_layer(ObAction **a, ObUserAction uact)
301 {
302 (*a)->data.layer.layer = 0;
303 }
304
305 void setup_action_bottom_layer(ObAction **a, ObUserAction uact)
306 {
307 (*a)->data.layer.layer = -1;
308 }
309
310 void setup_action_move(ObAction **a, ObUserAction uact)
311 {
312 (*a)->data.moveresize.move = TRUE;
313 (*a)->data.moveresize.keyboard =
314 (uact == OB_USER_ACTION_KEYBOARD_KEY ||
315 uact == OB_USER_ACTION_MENU_SELECTION);
316 }
317
318 void setup_action_resize(ObAction **a, ObUserAction uact)
319 {
320 (*a)->data.moveresize.move = FALSE;
321 (*a)->data.moveresize.keyboard =
322 (uact == OB_USER_ACTION_KEYBOARD_KEY ||
323 uact == OB_USER_ACTION_MENU_SELECTION);
324 }
325
326 void setup_action_showmenu(ObAction **a, ObUserAction uact)
327 {
328 /* you cannot call ShowMenu from inside a menu, cuz the menu code makes
329 assumptions that there is only one menu (and submenus) open at
330 a time! */
331 if (uact == OB_USER_ACTION_MENU_SELECTION) {
332 action_free(*a);
333 a = NULL;
334 }
335 }
336
337 ActionString actionstrings[] =
338 {
339 {
340 "execute",
341 action_execute,
342 NULL
343 },
344 {
345 "directionalfocusnorth",
346 action_directional_focus,
347 setup_action_directional_focus_north
348 },
349 {
350 "directionalfocuseast",
351 action_directional_focus,
352 setup_action_directional_focus_east
353 },
354 {
355 "directionalfocussouth",
356 action_directional_focus,
357 setup_action_directional_focus_south
358 },
359 {
360 "directionalfocuswest",
361 action_directional_focus,
362 setup_action_directional_focus_west
363 },
364 {
365 "directionalfocusnortheast",
366 action_directional_focus,
367 setup_action_directional_focus_northeast
368 },
369 {
370 "directionalfocussoutheast",
371 action_directional_focus,
372 setup_action_directional_focus_southeast
373 },
374 {
375 "directionalfocussouthwest",
376 action_directional_focus,
377 setup_action_directional_focus_southwest
378 },
379 {
380 "directionalfocusnorthwest",
381 action_directional_focus,
382 setup_action_directional_focus_northwest
383 },
384 {
385 "activate",
386 action_activate,
387 NULL
388 },
389 {
390 "focus",
391 action_focus,
392 NULL
393 },
394 {
395 "unfocus",
396 action_unfocus,
397 NULL
398 },
399 {
400 "iconify",
401 action_iconify,
402 NULL
403 },
404 {
405 "raiselower",
406 action_raiselower,
407 NULL
408 },
409 {
410 "raise",
411 action_raise,
412 NULL
413 },
414 {
415 "lower",
416 action_lower,
417 NULL
418 },
419 {
420 "close",
421 action_close,
422 NULL
423 },
424 {
425 "kill",
426 action_kill,
427 NULL
428 },
429 {
430 "shadelower",
431 action_shadelower,
432 NULL
433 },
434 {
435 "unshaderaise",
436 action_unshaderaise,
437 NULL
438 },
439 {
440 "shade",
441 action_shade,
442 NULL
443 },
444 {
445 "unshade",
446 action_unshade,
447 NULL
448 },
449 {
450 "toggleshade",
451 action_toggle_shade,
452 NULL
453 },
454 {
455 "toggleomnipresent",
456 action_toggle_omnipresent,
457 NULL
458 },
459 {
460 "moverelativehorz",
461 action_move_relative_horz,
462 NULL
463 },
464 {
465 "moverelativevert",
466 action_move_relative_vert,
467 NULL
468 },
469 {
470 "resizerelativehorz",
471 action_resize_relative_horz,
472 NULL
473 },
474 {
475 "resizerelativevert",
476 action_resize_relative_vert,
477 NULL
478 },
479 {
480 "maximizefull",
481 action_maximize_full,
482 NULL
483 },
484 {
485 "unmaximizefull",
486 action_unmaximize_full,
487 NULL
488 },
489 {
490 "togglemaximizefull",
491 action_toggle_maximize_full,
492 NULL
493 },
494 {
495 "maximizehorz",
496 action_maximize_horz,
497 NULL
498 },
499 {
500 "unmaximizehorz",
501 action_unmaximize_horz,
502 NULL
503 },
504 {
505 "togglemaximizehorz",
506 action_toggle_maximize_horz,
507 NULL
508 },
509 {
510 "maximizevert",
511 action_maximize_vert,
512 NULL
513 },
514 {
515 "unmaximizevert",
516 action_unmaximize_vert,
517 NULL
518 },
519 {
520 "togglemaximizevert",
521 action_toggle_maximize_vert,
522 NULL
523 },
524 {
525 "sendtodesktop",
526 action_send_to_desktop,
527 setup_action_send_to_desktop
528 },
529 {
530 "sendtodesktopnext",
531 action_send_to_desktop_dir,
532 setup_action_send_to_desktop_next
533 },
534 {
535 "sendtodesktopprevious",
536 action_send_to_desktop_dir,
537 setup_action_send_to_desktop_prev
538 },
539 {
540 "sendtodesktopright",
541 action_send_to_desktop_dir,
542 setup_action_send_to_desktop_right
543 },
544 {
545 "sendtodesktopleft",
546 action_send_to_desktop_dir,
547 setup_action_send_to_desktop_left
548 },
549 {
550 "sendtodesktopup",
551 action_send_to_desktop_dir,
552 setup_action_send_to_desktop_up
553 },
554 {
555 "sendtodesktopdown",
556 action_send_to_desktop_dir,
557 setup_action_send_to_desktop_down
558 },
559 {
560 "desktop",
561 action_desktop,
562 NULL
563 },
564 {
565 "desktopnext",
566 action_desktop_dir,
567 setup_action_desktop_next
568 },
569 {
570 "desktopprevious",
571 action_desktop_dir,
572 setup_action_desktop_prev
573 },
574 {
575 "desktopright",
576 action_desktop_dir,
577 setup_action_desktop_right
578 },
579 {
580 "desktopleft",
581 action_desktop_dir,
582 setup_action_desktop_left
583 },
584 {
585 "desktopup",
586 action_desktop_dir,
587 setup_action_desktop_up
588 },
589 {
590 "desktopdown",
591 action_desktop_dir,
592 setup_action_desktop_down
593 },
594 {
595 "toggledecorations",
596 action_toggle_decorations,
597 NULL
598 },
599 {
600 "move",
601 action_moveresize,
602 setup_action_move
603 },
604 {
605 "resize",
606 action_moveresize,
607 setup_action_resize
608 },
609 {
610 "toggleshowdesktop",
611 action_toggle_show_desktop,
612 NULL
613 },
614 {
615 "showdesktop",
616 action_show_desktop,
617 NULL
618 },
619 {
620 "unshowdesktop",
621 action_unshow_desktop,
622 NULL
623 },
624 {
625 "desktoplast",
626 action_desktop_last,
627 NULL
628 },
629 {
630 "reconfigure",
631 action_reconfigure,
632 NULL
633 },
634 {
635 "restart",
636 action_restart,
637 NULL
638 },
639 {
640 "exit",
641 action_exit,
642 NULL
643 },
644 {
645 "showmenu",
646 action_showmenu,
647 setup_action_showmenu
648 },
649 {
650 "sendtotoplayer",
651 action_send_to_layer,
652 setup_action_top_layer
653 },
654 {
655 "togglealwaysontop",
656 action_toggle_layer,
657 setup_action_top_layer
658 },
659 {
660 "sendtonormallayer",
661 action_send_to_layer,
662 setup_action_normal_layer
663 },
664 {
665 "sendtobottomlayer",
666 action_send_to_layer,
667 setup_action_bottom_layer
668 },
669 {
670 "togglealwaysonbottom",
671 action_toggle_layer,
672 setup_action_bottom_layer
673 },
674 {
675 "nextwindow",
676 action_cycle_windows,
677 setup_action_cycle_windows_next
678 },
679 {
680 "previouswindow",
681 action_cycle_windows,
682 setup_action_cycle_windows_previous
683 },
684 {
685 "movetoedgenorth",
686 action_movetoedge,
687 setup_action_movetoedge_north
688 },
689 {
690 "movetoedgesouth",
691 action_movetoedge,
692 setup_action_movetoedge_south
693 },
694 {
695 "movetoedgewest",
696 action_movetoedge,
697 setup_action_movetoedge_west
698 },
699 {
700 "movetoedgeeast",
701 action_movetoedge,
702 setup_action_movetoedge_east
703 },
704 {
705 "growtoedgenorth",
706 action_growtoedge,
707 setup_action_growtoedge_north
708 },
709 {
710 "growtoedgesouth",
711 action_growtoedge,
712 setup_action_growtoedge_south
713 },
714 {
715 "growtoedgewest",
716 action_growtoedge,
717 setup_action_growtoedge_west
718 },
719 {
720 "growtoedgeeast",
721 action_growtoedge,
722 setup_action_growtoedge_east
723 },
724 {
725 NULL,
726 NULL,
727 NULL
728 }
729 };
730
731 ObAction *action_from_string(const gchar *name, ObUserAction uact)
732 {
733 ObAction *a = NULL;
734 gboolean exist = FALSE;
735 int i;
736
737 for (i = 0; actionstrings[i].name; i++)
738 if (!g_ascii_strcasecmp(name, actionstrings[i].name)) {
739 exist = TRUE;
740 a = action_new(actionstrings[i].func, uact);
741 if (actionstrings[i].setup)
742 actionstrings[i].setup(&a, uact);
743 /* only key bindings can be interactive. thus saith the xor. */
744 if (uact != OB_USER_ACTION_KEYBOARD_KEY)
745 a->data.any.interactive = FALSE;
746 break;
747 }
748 if (!exist)
749 g_warning("Invalid action '%s' requested. No such action exists.",
750 name);
751 if (!a)
752 g_warning("Invalid use of action '%s'. Action will be ignored.", name);
753 return a;
754 }
755
756 ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
757 ObUserAction uact)
758 {
759 char *actname;
760 ObAction *act = NULL;
761 xmlNodePtr n;
762
763 if (parse_attr_string("name", node, &actname)) {
764 if ((act = action_from_string(actname, uact))) {
765 if (act->func == action_execute || act->func == action_restart) {
766 if ((n = parse_find_node("execute", node->xmlChildrenNode))) {
767 gchar *s = parse_string(doc, n);
768 act->data.execute.path = parse_expand_tilde(s);
769 g_free(s);
770 }
771 } else if (act->func == action_showmenu) {
772 if ((n = parse_find_node("menu", node->xmlChildrenNode)))
773 act->data.showmenu.name = parse_string(doc, n);
774 } else if (act->func == action_move_relative_horz ||
775 act->func == action_move_relative_vert ||
776 act->func == action_resize_relative_horz ||
777 act->func == action_resize_relative_vert) {
778 if ((n = parse_find_node("delta", node->xmlChildrenNode)))
779 act->data.relative.delta = parse_int(doc, n);
780 } else if (act->func == action_desktop) {
781 if ((n = parse_find_node("desktop", node->xmlChildrenNode)))
782 act->data.desktop.desk = parse_int(doc, n);
783 if (act->data.desktop.desk > 0) act->data.desktop.desk--;
784 } else if (act->func == action_send_to_desktop) {
785 if ((n = parse_find_node("desktop", node->xmlChildrenNode)))
786 act->data.sendto.desk = parse_int(doc, n);
787 if (act->data.sendto.desk > 0) act->data.sendto.desk--;
788 if ((n = parse_find_node("follow", node->xmlChildrenNode)))
789 act->data.sendto.follow = parse_bool(doc, n);
790 } else if (act->func == action_desktop_dir) {
791 if ((n = parse_find_node("wrap", node->xmlChildrenNode)))
792 act->data.desktopdir.wrap = parse_bool(doc, n);
793 } else if (act->func == action_send_to_desktop_dir) {
794 if ((n = parse_find_node("wrap", node->xmlChildrenNode)))
795 act->data.sendtodir.wrap = parse_bool(doc, n);
796 if ((n = parse_find_node("follow", node->xmlChildrenNode)))
797 act->data.sendtodir.follow = parse_bool(doc, n);
798 } else if (act->func == action_activate) {
799 if ((n = parse_find_node("here", node->xmlChildrenNode)))
800 act->data.activate.here = parse_bool(doc, n);
801 } else if (act->func == action_cycle_windows) {
802 if ((n = parse_find_node("linear", node->xmlChildrenNode)))
803 act->data.cycle.linear = parse_bool(doc, n);
804 }
805 }
806 g_free(actname);
807 }
808 return act;
809 }
810
811 void action_run_list(GSList *acts, ObClient *c, ObFrameContext context,
812 guint state, guint button, gint x, gint y,
813 gboolean cancel, gboolean done)
814 {
815 GSList *it;
816 ObAction *a;
817 gboolean inter = FALSE;
818
819 if (!acts)
820 return;
821
822 if (x < 0 && y < 0)
823 screen_pointer_pos(&x, &y);
824
825 if (grab_on_keyboard())
826 inter = TRUE;
827 else
828 for (it = acts; it; it = g_slist_next(it)) {
829 a = it->data;
830 if (a->data.any.interactive) {
831 inter = TRUE;
832 break;
833 }
834 }
835
836 if (!inter) {
837 /* sometimes when we execute another app as an action,
838 it won't work right unless we XUngrabKeyboard first,
839 even though we grabbed the key/button Asychronously.
840 e.g. "gnome-panel-control --main-menu" */
841 XUngrabKeyboard(ob_display, event_lasttime);
842 }
843
844 for (it = acts; it; it = g_slist_next(it)) {
845 a = it->data;
846
847 a->data.any.c = c;
848 a->data.any.context = context;
849 a->data.any.x = x;
850 a->data.any.y = y;
851
852 a->data.any.button = button;
853
854 if (a->data.any.interactive) {
855 a->data.inter.cancel = cancel;
856 a->data.inter.final = done;
857 if (!(cancel || done))
858 keyboard_interactive_grab(state, c, a);
859 }
860
861 a->func(&a->data);
862 }
863 }
864
865 void action_execute(union ActionData *data)
866 {
867 GError *e = NULL;
868 char *cmd;
869 if (data->execute.path) {
870 cmd = g_filename_from_utf8(data->execute.path, -1, NULL, NULL, NULL);
871 if (cmd) {
872 if (!g_spawn_command_line_async(cmd, &e)) {
873 g_warning("failed to execute '%s': %s",
874 cmd, e->message);
875 }
876 g_free(cmd);
877 } else {
878 g_warning("failed to convert '%s' from utf8", data->execute.path);
879 }
880 }
881 }
882
883 void action_activate(union ActionData *data)
884 {
885 if (data->activate.any.c)
886 client_activate(data->activate.any.c, data->activate.here);
887 }
888
889 void action_focus(union ActionData *data)
890 {
891 if (data->client.any.c)
892 client_focus(data->client.any.c);
893 }
894
895 void action_unfocus (union ActionData *data)
896 {
897 if (data->client.any.c)
898 client_unfocus(data->client.any.c);
899 }
900
901 void action_iconify(union ActionData *data)
902 {
903 if (data->client.any.c)
904 client_iconify(data->client.any.c, TRUE, TRUE);
905 }
906
907 void action_raiselower(union ActionData *data)
908 {
909 ObClient *c = data->client.any.c;
910 GList *it;
911 gboolean raise = FALSE;
912
913 if (!c) return;
914
915 for (it = stacking_list; it; it = g_list_next(it)) {
916 ObClient *cit = it->data;
917
918 if (cit == c) break;
919 if (client_normal(cit) == client_normal(c) &&
920 cit->layer == c->layer &&
921 cit->frame->visible)
922 {
923 if (RECT_INTERSECTS_RECT(cit->frame->area, c->frame->area)) {
924 raise = TRUE;
925 break;
926 }
927 }
928 }
929
930 if (raise) {
931 client_action_start(data);
932 stacking_raise(CLIENT_AS_WINDOW(c));
933 client_action_end(data);
934 } else {
935 client_action_start(data);
936 stacking_lower(CLIENT_AS_WINDOW(c));
937 client_action_end(data);
938 }
939 }
940
941 void action_raise(union ActionData *data)
942 {
943 if (data->client.any.c) {
944 client_action_start(data);
945 stacking_raise(CLIENT_AS_WINDOW(data->client.any.c));
946 client_action_end(data);
947 }
948 }
949
950 void action_unshaderaise(union ActionData *data)
951 {
952 if (data->client.any.c) {
953 if (data->client.any.c->shaded) {
954 client_action_start(data);
955 client_shade(data->client.any.c, FALSE);
956 client_action_end(data);
957 } else {
958 client_action_start(data);
959 stacking_raise(CLIENT_AS_WINDOW(data->client.any.c));
960 client_action_end(data);
961 }
962 }
963 }
964
965 void action_shadelower(union ActionData *data)
966 {
967 if (data->client.any.c) {
968 if (data->client.any.c->shaded)
969 stacking_lower(CLIENT_AS_WINDOW(data->client.any.c));
970 else {
971 client_action_start(data);
972 client_shade(data->client.any.c, TRUE);
973 client_action_end(data);
974 }
975 }
976 }
977
978 void action_lower(union ActionData *data)
979 {
980 if (data->client.any.c) {
981 client_action_start(data);
982 stacking_lower(CLIENT_AS_WINDOW(data->client.any.c));
983 client_action_end(data);
984 }
985 }
986
987 void action_close(union ActionData *data)
988 {
989 if (data->client.any.c)
990 client_close(data->client.any.c);
991 }
992
993 void action_kill(union ActionData *data)
994 {
995 if (data->client.any.c)
996 client_kill(data->client.any.c);
997 }
998
999 void action_shade(union ActionData *data)
1000 {
1001 if (data->client.any.c) {
1002 client_action_start(data);
1003 client_shade(data->client.any.c, TRUE);
1004 client_action_end(data);
1005 }
1006 }
1007
1008 void action_unshade(union ActionData *data)
1009 {
1010 if (data->client.any.c) {
1011 client_action_start(data);
1012 client_shade(data->client.any.c, FALSE);
1013 client_action_end(data);
1014 }
1015 }
1016
1017 void action_toggle_shade(union ActionData *data)
1018 {
1019 if (data->client.any.c) {
1020 client_action_start(data);
1021 client_shade(data->client.any.c, !data->client.any.c->shaded);
1022 client_action_end(data);
1023 }
1024 }
1025
1026 void action_toggle_omnipresent(union ActionData *data)
1027 {
1028 if (data->client.any.c)
1029 client_set_desktop(data->client.any.c,
1030 data->client.any.c->desktop == DESKTOP_ALL ?
1031 screen_desktop : DESKTOP_ALL, FALSE);
1032 }
1033
1034 void action_move_relative_horz(union ActionData *data)
1035 {
1036 ObClient *c = data->relative.any.c;
1037 if (c) {
1038 client_action_start(data);
1039 client_move(c, c->area.x + data->relative.delta, c->area.y);
1040 client_action_end(data);
1041 }
1042 }
1043
1044 void action_move_relative_vert(union ActionData *data)
1045 {
1046 ObClient *c = data->relative.any.c;
1047 if (c) {
1048 client_action_start(data);
1049 client_move(c, c->area.x, c->area.y + data->relative.delta);
1050 client_action_end(data);
1051 }
1052 }
1053
1054 void action_resize_relative_horz(union ActionData *data)
1055 {
1056 ObClient *c = data->relative.any.c;
1057 if (c) {
1058 client_action_start(data);
1059 client_resize(c,
1060 c->area.width + data->relative.delta * c->size_inc.width,
1061 c->area.height);
1062 client_action_end(data);
1063 }
1064 }
1065
1066 void action_resize_relative_vert(union ActionData *data)
1067 {
1068 ObClient *c = data->relative.any.c;
1069 if (c && !c->shaded) {
1070 client_action_start(data);
1071 client_resize(c, c->area.width, c->area.height +
1072 data->relative.delta * c->size_inc.height);
1073 client_action_end(data);
1074 }
1075 }
1076
1077 void action_maximize_full(union ActionData *data)
1078 {
1079 if (data->client.any.c) {
1080 client_action_start(data);
1081 client_maximize(data->client.any.c, TRUE, 0, TRUE);
1082 client_action_end(data);
1083 }
1084 }
1085
1086 void action_unmaximize_full(union ActionData *data)
1087 {
1088 if (data->client.any.c) {
1089 client_action_start(data);
1090 client_maximize(data->client.any.c, FALSE, 0, TRUE);
1091 client_action_end(data);
1092 }
1093 }
1094
1095 void action_toggle_maximize_full(union ActionData *data)
1096 {
1097 if (data->client.any.c) {
1098 client_action_start(data);
1099 client_maximize(data->client.any.c,
1100 !(data->client.any.c->max_horz ||
1101 data->client.any.c->max_vert),
1102 0, TRUE);
1103 client_action_end(data);
1104 }
1105 }
1106
1107 void action_maximize_horz(union ActionData *data)
1108 {
1109 if (data->client.any.c) {
1110 client_action_start(data);
1111 client_maximize(data->client.any.c, TRUE, 1, TRUE);
1112 client_action_end(data);
1113 }
1114 }
1115
1116 void action_unmaximize_horz(union ActionData *data)
1117 {
1118 if (data->client.any.c) {
1119 client_action_start(data);
1120 client_maximize(data->client.any.c, FALSE, 1, TRUE);
1121 client_action_end(data);
1122 }
1123 }
1124
1125 void action_toggle_maximize_horz(union ActionData *data)
1126 {
1127 if (data->client.any.c) {
1128 client_action_start(data);
1129 client_maximize(data->client.any.c,
1130 !data->client.any.c->max_horz, 1, TRUE);
1131 client_action_end(data);
1132 }
1133 }
1134
1135 void action_maximize_vert(union ActionData *data)
1136 {
1137 if (data->client.any.c) {
1138 client_action_start(data);
1139 client_maximize(data->client.any.c, TRUE, 2, TRUE);
1140 client_action_end(data);
1141 }
1142 }
1143
1144 void action_unmaximize_vert(union ActionData *data)
1145 {
1146 if (data->client.any.c) {
1147 client_action_start(data);
1148 client_maximize(data->client.any.c, FALSE, 2, TRUE);
1149 client_action_end(data);
1150 }
1151 }
1152
1153 void action_toggle_maximize_vert(union ActionData *data)
1154 {
1155 if (data->client.any.c) {
1156 client_action_start(data);
1157 client_maximize(data->client.any.c,
1158 !data->client.any.c->max_vert, 2, TRUE);
1159 client_action_end(data);
1160 }
1161 }
1162
1163 void action_send_to_desktop(union ActionData *data)
1164 {
1165 ObClient *c = data->sendto.any.c;
1166
1167 if (!c || !client_normal(c)) return;
1168
1169 if (data->sendto.desk < screen_num_desktops ||
1170 data->sendto.desk == DESKTOP_ALL) {
1171 client_set_desktop(c, data->sendto.desk, data->sendto.follow);
1172 if (data->sendto.follow)
1173 screen_set_desktop(data->sendto.desk);
1174 }
1175 }
1176
1177 void action_desktop(union ActionData *data)
1178 {
1179 if (data->desktop.desk < screen_num_desktops ||
1180 data->desktop.desk == DESKTOP_ALL)
1181 screen_set_desktop(data->desktop.desk);
1182 }
1183
1184 void action_desktop_dir(union ActionData *data)
1185 {
1186 guint d;
1187
1188 d = screen_cycle_desktop(data->desktopdir.dir,
1189 data->desktopdir.wrap,
1190 data->sendtodir.linear,
1191 data->desktopdir.inter.any.interactive,
1192 data->desktopdir.inter.final,
1193 data->desktopdir.inter.cancel);
1194 screen_set_desktop(d);
1195 }
1196
1197 void action_send_to_desktop_dir(union ActionData *data)
1198 {
1199 ObClient *c = data->sendtodir.inter.any.c;
1200 guint d;
1201
1202 if (!c || !client_normal(c)) return;
1203
1204 d = screen_cycle_desktop(data->sendtodir.dir, data->sendtodir.wrap,
1205 data->sendtodir.linear,
1206 data->sendtodir.inter.any.interactive,
1207 data->sendtodir.inter.final,
1208 data->sendtodir.inter.cancel);
1209 client_set_desktop(c, d, data->sendtodir.follow);
1210 if (data->sendtodir.follow)
1211 screen_set_desktop(d);
1212 }
1213
1214 void action_desktop_last(union ActionData *data)
1215 {
1216 screen_set_desktop(screen_last_desktop);
1217 }
1218
1219 void action_toggle_decorations(union ActionData *data)
1220 {
1221 ObClient *c = data->client.any.c;
1222
1223 if (c) {
1224 client_action_start(data);
1225 c->decorate = !c->decorate;
1226 client_setup_decor_and_functions(c);
1227 client_action_end(data);
1228 }
1229 }
1230
1231 static guint32 pick_corner(int x, int y, int cx, int cy, int cw, int ch)
1232 {
1233 if (x - cx > cw / 2) {
1234 if (y - cy > ch / 2)
1235 return prop_atoms.net_wm_moveresize_size_bottomright;
1236 else
1237 return prop_atoms.net_wm_moveresize_size_topright;
1238 } else {
1239 if (y - cy > ch / 2)
1240 return prop_atoms.net_wm_moveresize_size_bottomleft;
1241 else
1242 return prop_atoms.net_wm_moveresize_size_topleft;
1243 }
1244 }
1245
1246 void action_moveresize(union ActionData *data)
1247 {
1248 ObClient *c = data->moveresize.any.c;
1249 guint32 corner;
1250
1251 if (!c || !client_normal(c)) return;
1252
1253 if (data->moveresize.keyboard) {
1254 corner = (data->moveresize.move ?
1255 prop_atoms.net_wm_moveresize_move_keyboard :
1256 prop_atoms.net_wm_moveresize_size_keyboard);
1257 } else {
1258 corner = (data->moveresize.move ?
1259 prop_atoms.net_wm_moveresize_move :
1260 pick_corner(data->any.x, data->any.y,
1261 c->frame->area.x, c->frame->area.y,
1262 /* use the client size because the frame
1263 can be differently sized (shaded
1264 windows) and we want this based on the
1265 clients size */
1266 c->area.width + c->frame->size.left +
1267 c->frame->size.right,
1268 c->area.height + c->frame->size.top +
1269 c->frame->size.bottom));
1270 }
1271
1272 moveresize_start(c, data->any.x, data->any.y, data->any.button, corner);
1273 }
1274
1275 void action_reconfigure(union ActionData *data)
1276 {
1277 ob_reconfigure();
1278 }
1279
1280 void action_restart(union ActionData *data)
1281 {
1282 ob_restart_other(data->execute.path);
1283 }
1284
1285 void action_exit(union ActionData *data)
1286 {
1287 ob_exit(0);
1288 }
1289
1290 void action_showmenu(union ActionData *data)
1291 {
1292 if (data->showmenu.name) {
1293 menu_show(data->showmenu.name, data->any.x, data->any.y,
1294 data->showmenu.any.c);
1295 }
1296 }
1297
1298 void action_cycle_windows(union ActionData *data)
1299 {
1300 focus_cycle(data->cycle.forward, data->cycle.linear,
1301 data->cycle.inter.any.interactive,
1302 data->cycle.inter.final, data->cycle.inter.cancel);
1303 }
1304
1305 void action_directional_focus(union ActionData *data)
1306 {
1307 focus_directional_cycle(data->interdiraction.direction,
1308 data->interdiraction.inter.any.interactive,
1309 data->interdiraction.inter.final,
1310 data->interdiraction.inter.cancel);
1311 }
1312
1313 void action_movetoedge(union ActionData *data)
1314 {
1315 int x, y;
1316 ObClient *c = data->diraction.any.c;
1317
1318 if (!c)
1319 return;
1320 x = c->frame->area.x;
1321 y = c->frame->area.y;
1322
1323 switch(data->diraction.direction) {
1324 case OB_DIRECTION_NORTH:
1325 y = client_directional_edge_search(c, OB_DIRECTION_NORTH);
1326 break;
1327 case OB_DIRECTION_WEST:
1328 x = client_directional_edge_search(c, OB_DIRECTION_WEST);
1329 break;
1330 case OB_DIRECTION_SOUTH:
1331 y = client_directional_edge_search(c, OB_DIRECTION_SOUTH) -
1332 c->frame->area.height;
1333 break;
1334 case OB_DIRECTION_EAST:
1335 x = client_directional_edge_search(c, OB_DIRECTION_EAST) -
1336 c->frame->area.width;
1337 break;
1338 default:
1339 g_assert_not_reached();
1340 }
1341 frame_frame_gravity(c->frame, &x, &y);
1342 client_action_start(data);
1343 client_move(c, x, y);
1344 client_action_end(data);
1345
1346 }
1347
1348 void action_growtoedge(union ActionData *data)
1349 {
1350 int x, y, width, height, dest;
1351 ObClient *c = data->diraction.any.c;
1352 Rect *a;
1353
1354 if (!c)
1355 return;
1356
1357 a = screen_area(c->desktop);
1358 x = c->frame->area.x;
1359 y = c->frame->area.y;
1360 width = c->frame->area.width;
1361 height = c->frame->area.height;
1362
1363 switch(data->diraction.direction) {
1364 case OB_DIRECTION_NORTH:
1365 dest = client_directional_edge_search(c, OB_DIRECTION_NORTH);
1366 if (a->y == y)
1367 height = c->frame->area.height / 2;
1368 else {
1369 height = c->frame->area.y + c->frame->area.height - dest;
1370 y = dest;
1371 }
1372 break;
1373 case OB_DIRECTION_WEST:
1374 dest = client_directional_edge_search(c, OB_DIRECTION_WEST);
1375 if (a->x == x)
1376 width = c->frame->area.width / 2;
1377 else {
1378 width = c->frame->area.x + c->frame->area.width - dest;
1379 x = dest;
1380 }
1381 break;
1382 case OB_DIRECTION_SOUTH:
1383 dest = client_directional_edge_search(c, OB_DIRECTION_SOUTH);
1384 if (a->y + a->height == y + c->frame->area.height) {
1385 height = c->frame->area.height / 2;
1386 y = a->y + a->height - height;
1387 } else
1388 height = dest - c->frame->area.y;
1389 y += (height - c->frame->area.height) % c->size_inc.height;
1390 height -= (height - c->frame->area.height) % c->size_inc.height;
1391 break;
1392 case OB_DIRECTION_EAST:
1393 dest = client_directional_edge_search(c, OB_DIRECTION_EAST);
1394 if (a->x + a->width == x + c->frame->area.width) {
1395 width = c->frame->area.width / 2;
1396 x = a->x + a->width - width;
1397 } else
1398 width = dest - c->frame->area.x;
1399 x += (width - c->frame->area.width) % c->size_inc.width;
1400 width -= (width - c->frame->area.width) % c->size_inc.width;
1401 break;
1402 default:
1403 g_assert_not_reached();
1404 }
1405 frame_frame_gravity(c->frame, &x, &y);
1406 width -= c->frame->size.left + c->frame->size.right;
1407 height -= c->frame->size.top + c->frame->size.bottom;
1408 client_action_start(data);
1409 client_move_resize(c, x, y, width, height);
1410 client_action_end(data);
1411 }
1412
1413 void action_send_to_layer(union ActionData *data)
1414 {
1415 if (data->layer.any.c)
1416 client_set_layer(data->layer.any.c, data->layer.layer);
1417 }
1418
1419 void action_toggle_layer(union ActionData *data)
1420 {
1421 ObClient *c = data->layer.any.c;
1422
1423 if (c) {
1424 client_action_start(data);
1425 if (data->layer.layer < 0)
1426 client_set_layer(c, c->below ? 0 : -1);
1427 else if (data->layer.layer > 0)
1428 client_set_layer(c, c->above ? 0 : 1);
1429 client_action_end(data);
1430 }
1431 }
1432
1433 void action_toggle_show_desktop(union ActionData *data)
1434 {
1435 screen_show_desktop(!screen_showing_desktop);
1436 }
1437
1438 void action_show_desktop(union ActionData *data)
1439 {
1440 screen_show_desktop(TRUE);
1441 }
1442
1443 void action_unshow_desktop(union ActionData *data)
1444 {
1445 screen_show_desktop(FALSE);
1446 }
This page took 0.107526 seconds and 4 git commands to generate.