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