3 #include "moveresize.h"
15 typedef struct ActionString
{
17 void (*func
)(union ActionData
*);
18 void (*setup
)(Action
*);
21 Action
*action_new(void (*func
)(union ActionData
*data
))
23 Action
*a
= g_new0(Action
, 1);
29 void action_free(Action
*a
)
31 if (a
== NULL
) return;
33 /* deal with pointers */
34 if (a
->func
== action_execute
|| a
->func
== action_restart
)
35 g_free(a
->data
.execute
.path
);
36 else if (a
->func
== action_showmenu
)
37 g_free(a
->data
.showmenu
.name
);
42 void setup_action_directional_focus_north(Action
*a
)
44 a
->data
.dfocus
.direction
= Direction_North
;
47 void setup_action_directional_focus_east(Action
*a
)
49 a
->data
.dfocus
.direction
= Direction_East
;
52 void setup_action_directional_focus_south(Action
*a
)
54 a
->data
.dfocus
.direction
= Direction_South
;
57 void setup_action_directional_focus_west(Action
*a
)
59 a
->data
.dfocus
.direction
= Direction_West
;
62 void setup_action_directional_focus_northeast(Action
*a
)
64 a
->data
.dfocus
.direction
= Direction_NorthEast
;
67 void setup_action_directional_focus_southeast(Action
*a
)
69 a
->data
.dfocus
.direction
= Direction_SouthEast
;
72 void setup_action_directional_focus_southwest(Action
*a
)
74 a
->data
.dfocus
.direction
= Direction_SouthWest
;
77 void setup_action_directional_focus_northwest(Action
*a
)
79 a
->data
.dfocus
.direction
= Direction_NorthWest
;
82 void setup_action_send_to_desktop(Action
*a
)
84 a
->data
.sendto
.follow
= TRUE
;
87 void setup_action_send_to_np_desktop(Action
*a
)
89 a
->data
.sendtonextprev
.wrap
= FALSE
;
90 a
->data
.sendtonextprev
.follow
= TRUE
;
93 void setup_action_send_to_np_desktop_wrap(Action
*a
)
95 a
->data
.sendtonextprev
.wrap
= TRUE
;
96 a
->data
.sendtonextprev
.follow
= TRUE
;
99 void setup_action_np_desktop(Action
*a
)
101 a
->data
.nextprevdesktop
.wrap
= FALSE
;
104 void setup_action_np_desktop_wrap(Action
*a
)
106 a
->data
.nextprevdesktop
.wrap
= TRUE
;
109 void setup_action_move_keyboard(Action
*a
)
111 a
->data
.moveresize
.corner
= prop_atoms
.net_wm_moveresize_move_keyboard
;
114 void setup_action_move(Action
*a
)
116 a
->data
.moveresize
.corner
= prop_atoms
.net_wm_moveresize_move
;
119 void setup_action_resize(Action
*a
)
121 a
->data
.moveresize
.corner
= prop_atoms
.net_wm_moveresize_size_topleft
;
124 void setup_action_resize_keyboard(Action
*a
)
126 a
->data
.moveresize
.corner
= prop_atoms
.net_wm_moveresize_size_keyboard
;
129 void setup_action_cycle_windows_linear_next(Action
*a
)
131 a
->data
.cycle
.linear
= TRUE
;
132 a
->data
.cycle
.forward
= TRUE
;
135 void setup_action_cycle_windows_linear_previous(Action
*a
)
137 a
->data
.cycle
.linear
= TRUE
;
138 a
->data
.cycle
.forward
= FALSE
;
141 void setup_action_cycle_windows_next(Action
*a
)
143 a
->data
.cycle
.linear
= FALSE
;
144 a
->data
.cycle
.forward
= TRUE
;
147 void setup_action_cycle_windows_previous(Action
*a
)
149 a
->data
.cycle
.linear
= FALSE
;
150 a
->data
.cycle
.forward
= FALSE
;
153 ActionString actionstrings
[] =
161 "directionalfocusnorth",
162 action_directional_focus
,
163 setup_action_directional_focus_north
166 "directionalfocuseast",
167 action_directional_focus
,
168 setup_action_directional_focus_east
171 "directionalfocussouth",
172 action_directional_focus
,
173 setup_action_directional_focus_south
176 "directionalfocuswest",
177 action_directional_focus
,
178 setup_action_directional_focus_west
181 "directionalfocusnortheast",
182 action_directional_focus
,
183 setup_action_directional_focus_northeast
186 "directionalfocussoutheast",
187 action_directional_focus
,
188 setup_action_directional_focus_southeast
191 "directionalfocussouthwest",
192 action_directional_focus
,
193 setup_action_directional_focus_southwest
196 "directionalfocusnorthwest",
197 action_directional_focus
,
198 setup_action_directional_focus_northwest
267 action_toggle_omnipresent
,
272 action_move_relative_horz
,
277 action_move_relative_vert
,
281 "resizerelativehorz",
282 action_resize_relative_horz
,
286 "resizerelativevert",
287 action_resize_relative_vert
,
292 action_maximize_full
,
297 action_unmaximize_full
,
301 "togglemaximizefull",
302 action_toggle_maximize_full
,
307 action_maximize_horz
,
312 action_unmaximize_horz
,
316 "togglemaximizehorz",
317 action_toggle_maximize_horz
,
322 action_maximize_vert
,
327 action_unmaximize_vert
,
331 "togglemaximizevert",
332 action_toggle_maximize_vert
,
337 action_send_to_desktop
,
338 setup_action_send_to_desktop
342 action_send_to_next_desktop
,
343 setup_action_send_to_np_desktop
346 "sendtonextdesktopwrap",
347 action_send_to_next_desktop
,
348 setup_action_send_to_np_desktop_wrap
351 "sendtopreviousdesktop",
352 action_send_to_previous_desktop
,
353 setup_action_send_to_np_desktop
356 "sendtopreviousdesktopwrap",
357 action_send_to_previous_desktop
,
358 setup_action_send_to_np_desktop_wrap
368 setup_action_np_desktop
373 setup_action_np_desktop_wrap
377 action_previous_desktop
,
378 setup_action_np_desktop
381 "previousdesktopwrap",
382 action_previous_desktop
,
383 setup_action_np_desktop_wrap
387 action_next_desktop_column
,
388 setup_action_np_desktop
391 "nextdesktopcolumnwrap",
392 action_next_desktop_column
,
393 setup_action_np_desktop_wrap
396 "previousdesktopcolumn",
397 action_previous_desktop_column
,
398 setup_action_np_desktop
401 "previousdesktopcolumnwrap",
402 action_previous_desktop_column
,
403 setup_action_np_desktop_wrap
407 action_next_desktop_row
,
408 setup_action_np_desktop
411 "nextdesktoprowwrap",
412 action_next_desktop_row
,
413 setup_action_np_desktop_wrap
416 "previousdesktoprow",
417 action_previous_desktop_row
,
418 setup_action_np_desktop
421 "previousdesktoprowwrap",
422 action_previous_desktop_row
,
423 setup_action_np_desktop_wrap
427 action_toggle_decorations
,
433 setup_action_move_keyboard
448 setup_action_resize_keyboard
467 action_cycle_windows
,
468 setup_action_cycle_windows_linear_next
471 "previouswindowlinear",
472 action_cycle_windows
,
473 setup_action_cycle_windows_linear_previous
477 action_cycle_windows
,
478 setup_action_cycle_windows_next
482 action_cycle_windows
,
483 setup_action_cycle_windows_previous
492 Action
*action_from_string(char *name
)
497 for (i
= 0; actionstrings
[i
].name
; i
++)
498 if (!g_ascii_strcasecmp(name
, actionstrings
[i
].name
)) {
499 a
= action_new(actionstrings
[i
].func
);
500 if (actionstrings
[i
].setup
)
501 actionstrings
[i
].setup(a
);
507 void action_execute(union ActionData
*data
)
510 if (data
->execute
.path
)
511 if (!g_spawn_command_line_async(data
->execute
.path
, &e
)) {
512 g_warning("failed to execute '%s': %s",
513 data
->execute
.path
, e
->message
);
517 void action_focus(union ActionData
*data
)
520 client_focus(data
->client
.c
);
523 void action_unfocus (union ActionData
*data
)
526 client_unfocus(data
->client
.c
);
529 void action_iconify(union ActionData
*data
)
532 client_iconify(data
->client
.c
, TRUE
, TRUE
);
535 void action_focusraise(union ActionData
*data
)
537 if (data
->client
.c
) {
538 client_focus(data
->client
.c
);
539 stacking_raise(CLIENT_AS_WINDOW(data
->client
.c
));
543 void action_raise(union ActionData
*data
)
546 stacking_raise(CLIENT_AS_WINDOW(data
->client
.c
));
549 void action_unshaderaise(union ActionData
*data
)
551 if (data
->client
.c
) {
552 if (data
->client
.c
->shaded
)
553 client_shade(data
->client
.c
, FALSE
);
555 stacking_raise(CLIENT_AS_WINDOW(data
->client
.c
));
559 void action_shadelower(union ActionData
*data
)
561 if (data
->client
.c
) {
562 if (data
->client
.c
->shaded
)
563 stacking_lower(CLIENT_AS_WINDOW(data
->client
.c
));
565 client_shade(data
->client
.c
, TRUE
);
569 void action_lower(union ActionData
*data
)
572 stacking_lower(CLIENT_AS_WINDOW(data
->client
.c
));
575 void action_close(union ActionData
*data
)
578 client_close(data
->client
.c
);
581 void action_kill(union ActionData
*data
)
584 client_kill(data
->client
.c
);
587 void action_shade(union ActionData
*data
)
590 client_shade(data
->client
.c
, TRUE
);
593 void action_unshade(union ActionData
*data
)
596 client_shade(data
->client
.c
, FALSE
);
599 void action_toggle_shade(union ActionData
*data
)
602 client_shade(data
->client
.c
, !data
->client
.c
->shaded
);
605 void action_toggle_omnipresent(union ActionData
*data
)
608 client_set_desktop(data
->client
.c
,
609 data
->client
.c
->desktop
== DESKTOP_ALL
?
610 screen_desktop
: DESKTOP_ALL
, FALSE
);
613 void action_move_relative_horz(union ActionData
*data
)
615 Client
*c
= data
->relative
.c
;
617 client_configure(c
, Corner_TopLeft
,
618 c
->area
.x
+ data
->relative
.delta
, c
->area
.y
,
619 c
->area
.width
, c
->area
.height
, TRUE
, TRUE
);
622 void action_move_relative_vert(union ActionData
*data
)
624 Client
*c
= data
->relative
.c
;
626 client_configure(c
, Corner_TopLeft
,
627 c
->area
.x
, c
->area
.y
+ data
->relative
.delta
,
628 c
->area
.width
, c
->area
.height
, TRUE
, TRUE
);
631 void action_resize_relative_horz(union ActionData
*data
)
633 Client
*c
= data
->relative
.c
;
635 client_configure(c
, Corner_TopLeft
, c
->area
.x
, c
->area
.y
,
636 c
->area
.width
+ data
->relative
.delta
,
637 c
->area
.height
, TRUE
, TRUE
);
640 void action_resize_relative_vert(union ActionData
*data
)
642 Client
*c
= data
->relative
.c
;
644 client_configure(c
, Corner_TopLeft
, c
->area
.x
, c
->area
.y
,
645 c
->area
.width
, c
->area
.height
+ data
->relative
.delta
,
649 void action_maximize_full(union ActionData
*data
)
652 client_maximize(data
->client
.c
, TRUE
, 0, TRUE
);
655 void action_unmaximize_full(union ActionData
*data
)
658 client_maximize(data
->client
.c
, FALSE
, 0, TRUE
);
661 void action_toggle_maximize_full(union ActionData
*data
)
664 client_maximize(data
->client
.c
,
665 !(data
->client
.c
->max_horz
||
666 data
->client
.c
->max_vert
),
670 void action_maximize_horz(union ActionData
*data
)
673 client_maximize(data
->client
.c
, TRUE
, 1, TRUE
);
676 void action_unmaximize_horz(union ActionData
*data
)
679 client_maximize(data
->client
.c
, FALSE
, 1, TRUE
);
682 void action_toggle_maximize_horz(union ActionData
*data
)
685 client_maximize(data
->client
.c
, !data
->client
.c
->max_horz
, 1, TRUE
);
688 void action_maximize_vert(union ActionData
*data
)
691 client_maximize(data
->client
.c
, TRUE
, 2, TRUE
);
694 void action_unmaximize_vert(union ActionData
*data
)
697 client_maximize(data
->client
.c
, FALSE
, 2, TRUE
);
700 void action_toggle_maximize_vert(union ActionData
*data
)
703 client_maximize(data
->client
.c
, !data
->client
.c
->max_vert
, 2, TRUE
);
706 void action_send_to_desktop(union ActionData
*data
)
708 if (data
->sendto
.c
) {
709 if (data
->sendto
.desk
< screen_num_desktops
||
710 data
->sendto
.desk
== DESKTOP_ALL
) {
711 client_set_desktop(data
->desktop
.c
,
712 data
->sendto
.desk
, data
->sendto
.follow
);
713 if (data
->sendto
.follow
) screen_set_desktop(data
->sendto
.desk
);
718 void action_send_to_next_desktop(union ActionData
*data
)
722 if (!data
->sendtonextprev
.c
) return;
724 d
= screen_desktop
+ 1;
725 if (d
>= screen_num_desktops
) {
726 if (!data
->sendtonextprev
.wrap
) return;
729 client_set_desktop(data
->sendtonextprev
.c
, d
, data
->sendtonextprev
.follow
);
730 if (data
->sendtonextprev
.follow
) screen_set_desktop(d
);
733 void action_send_to_previous_desktop(union ActionData
*data
)
737 if (!data
->sendtonextprev
.c
) return;
739 d
= screen_desktop
- 1;
740 if (d
>= screen_num_desktops
) {
741 if (!data
->sendtonextprev
.wrap
) return;
742 d
= screen_num_desktops
- 1;
744 client_set_desktop(data
->sendtonextprev
.c
, d
, data
->sendtonextprev
.follow
);
745 if (data
->sendtonextprev
.follow
) screen_set_desktop(d
);
748 void action_desktop(union ActionData
*data
)
750 if (data
->desktop
.desk
< screen_num_desktops
||
751 data
->desktop
.desk
== DESKTOP_ALL
)
752 screen_set_desktop(data
->desktop
.desk
);
755 void action_next_desktop(union ActionData
*data
)
759 d
= screen_desktop
+ 1;
760 if (d
>= screen_num_desktops
) {
761 if (!data
->nextprevdesktop
.wrap
) return;
764 screen_set_desktop(d
);
767 void action_previous_desktop(union ActionData
*data
)
771 d
= screen_desktop
- 1;
772 if (d
>= screen_num_desktops
) {
773 if (!data
->nextprevdesktop
.wrap
) return;
774 d
= screen_num_desktops
- 1;
776 screen_set_desktop(d
);
779 static void cur_row_col(guint
*r
, guint
*c
)
781 switch (screen_desktop_layout
.orientation
) {
782 case Orientation_Horz
:
783 switch (screen_desktop_layout
.start_corner
) {
785 *r
= screen_desktop
/ screen_desktop_layout
.columns
;
786 *c
= screen_desktop
% screen_desktop_layout
.columns
;
788 case Corner_BottomLeft
:
789 *r
= screen_desktop_layout
.rows
- 1 -
790 screen_desktop
/ screen_desktop_layout
.columns
;
791 *c
= screen_desktop
% screen_desktop_layout
.columns
;
793 case Corner_TopRight
:
794 *r
= screen_desktop
/ screen_desktop_layout
.columns
;
795 *c
= screen_desktop_layout
.columns
- 1 -
796 screen_desktop
% screen_desktop_layout
.columns
;
798 case Corner_BottomRight
:
799 *r
= screen_desktop_layout
.rows
- 1 -
800 screen_desktop
/ screen_desktop_layout
.columns
;
801 *c
= screen_desktop_layout
.columns
- 1 -
802 screen_desktop
% screen_desktop_layout
.columns
;
806 case Orientation_Vert
:
807 switch (screen_desktop_layout
.start_corner
) {
809 *r
= screen_desktop
% screen_desktop_layout
.rows
;
810 *c
= screen_desktop
/ screen_desktop_layout
.rows
;
812 case Corner_BottomLeft
:
813 *r
= screen_desktop_layout
.rows
- 1 -
814 screen_desktop
% screen_desktop_layout
.rows
;
815 *c
= screen_desktop
/ screen_desktop_layout
.rows
;
817 case Corner_TopRight
:
818 *r
= screen_desktop
% screen_desktop_layout
.rows
;
819 *c
= screen_desktop_layout
.columns
- 1 -
820 screen_desktop
/ screen_desktop_layout
.rows
;
822 case Corner_BottomRight
:
823 *r
= screen_desktop_layout
.rows
- 1 -
824 screen_desktop
% screen_desktop_layout
.rows
;
825 *c
= screen_desktop_layout
.columns
- 1 -
826 screen_desktop
/ screen_desktop_layout
.rows
;
833 static guint
translate_row_col(guint r
, guint c
)
835 switch (screen_desktop_layout
.orientation
) {
836 case Orientation_Horz
:
837 switch (screen_desktop_layout
.start_corner
) {
839 return r
% screen_desktop_layout
.rows
*
840 screen_desktop_layout
.columns
+
841 c
% screen_desktop_layout
.columns
;
842 case Corner_BottomLeft
:
843 return (screen_desktop_layout
.rows
- 1 -
844 r
% screen_desktop_layout
.rows
) *
845 screen_desktop_layout
.columns
+
846 c
% screen_desktop_layout
.columns
;
847 case Corner_TopRight
:
848 return r
% screen_desktop_layout
.rows
*
849 screen_desktop_layout
.columns
+
850 (screen_desktop_layout
.columns
- 1 -
851 c
% screen_desktop_layout
.columns
);
852 case Corner_BottomRight
:
853 return (screen_desktop_layout
.rows
- 1 -
854 r
% screen_desktop_layout
.rows
) *
855 screen_desktop_layout
.columns
+
856 (screen_desktop_layout
.columns
- 1 -
857 c
% screen_desktop_layout
.columns
);
859 case Orientation_Vert
:
860 switch (screen_desktop_layout
.start_corner
) {
862 return c
% screen_desktop_layout
.columns
*
863 screen_desktop_layout
.rows
+
864 r
% screen_desktop_layout
.rows
;
865 case Corner_BottomLeft
:
866 return c
% screen_desktop_layout
.columns
*
867 screen_desktop_layout
.rows
+
868 (screen_desktop_layout
.rows
- 1 -
869 r
% screen_desktop_layout
.rows
);
870 case Corner_TopRight
:
871 return (screen_desktop_layout
.columns
- 1 -
872 c
% screen_desktop_layout
.columns
) *
873 screen_desktop_layout
.rows
+
874 r
% screen_desktop_layout
.rows
;
875 case Corner_BottomRight
:
876 return (screen_desktop_layout
.columns
- 1 -
877 c
% screen_desktop_layout
.columns
) *
878 screen_desktop_layout
.rows
+
879 (screen_desktop_layout
.rows
- 1 -
880 r
% screen_desktop_layout
.rows
);
883 g_assert_not_reached();
887 void action_next_desktop_column(union ActionData
*data
)
893 if (c
>= screen_desktop_layout
.columns
)
895 d
= translate_row_col(r
, c
);
896 if (d
>= screen_num_desktops
) {
897 if (!data
->nextprevdesktop
.wrap
) return;
900 d
= translate_row_col(r
, c
);
901 if (d
< screen_num_desktops
)
902 screen_set_desktop(d
);
905 void action_previous_desktop_column(union ActionData
*data
)
911 if (c
>= screen_desktop_layout
.columns
)
912 c
= screen_desktop_layout
.columns
- 1;
913 d
= translate_row_col(r
, c
);
914 if (d
>= screen_num_desktops
) {
915 if (!data
->nextprevdesktop
.wrap
) return;
918 d
= translate_row_col(r
, c
);
919 if (d
< screen_num_desktops
)
920 screen_set_desktop(d
);
923 void action_next_desktop_row(union ActionData
*data
)
929 if (r
>= screen_desktop_layout
.rows
)
931 d
= translate_row_col(r
, c
);
932 if (d
>= screen_num_desktops
) {
933 if (!data
->nextprevdesktop
.wrap
) return;
936 d
= translate_row_col(r
, c
);
937 if (d
< screen_num_desktops
)
938 screen_set_desktop(d
);
941 void action_previous_desktop_row(union ActionData
*data
)
947 if (r
>= screen_desktop_layout
.rows
)
948 r
= screen_desktop_layout
.rows
- 1;
949 d
= translate_row_col(r
, c
);
950 if (d
>= screen_num_desktops
) {
951 if (!data
->nextprevdesktop
.wrap
) return;
954 d
= translate_row_col(r
, c
);
955 if (d
< screen_num_desktops
)
956 screen_set_desktop(d
);
959 void action_toggle_decorations(union ActionData
*data
)
961 Client
*c
= data
->client
.c
;;
965 c
->disabled_decorations
= c
->disabled_decorations
? 0 : ~0;
966 client_setup_decor_and_functions(c
);
969 void action_moveresize(union ActionData
*data
)
971 Client
*c
= data
->moveresize
.c
;
973 if (!c
|| !client_normal(c
)) return;
975 moveresize_start(c
, data
->moveresize
.x
, data
->moveresize
.y
,
976 data
->moveresize
.button
, data
->moveresize
.corner
);
979 void action_restart(union ActionData
*data
)
981 ob_restart_path
= data
->execute
.path
;
982 ob_shutdown
= ob_restart
= TRUE
;
985 void action_exit(union ActionData
*data
)
990 void action_showmenu(union ActionData
*data
)
992 if (data
->showmenu
.name
) {
993 menu_show(data
->showmenu
.name
, data
->showmenu
.x
, data
->showmenu
.y
,
998 void action_cycle_windows(union ActionData
*data
)
1002 c
= focus_cycle(data
->cycle
.forward
, data
->cycle
.linear
, data
->cycle
.final
,
1003 data
->cycle
.cancel
);
1006 void action_directional_focus(union ActionData
*data
)
1010 if (!data
->dfocus
.c
)
1012 if ((nf
= client_find_directional(data
->dfocus
.c
, data
->dfocus
.direction
)))
1013 client_activate(nf
);