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
.diraction
.direction
= Direction_North
;
47 void setup_action_directional_focus_east(Action
*a
)
49 a
->data
.diraction
.direction
= Direction_East
;
52 void setup_action_directional_focus_south(Action
*a
)
54 a
->data
.diraction
.direction
= Direction_South
;
57 void setup_action_directional_focus_west(Action
*a
)
59 a
->data
.diraction
.direction
= Direction_West
;
62 void setup_action_directional_focus_northeast(Action
*a
)
64 a
->data
.diraction
.direction
= Direction_NorthEast
;
67 void setup_action_directional_focus_southeast(Action
*a
)
69 a
->data
.diraction
.direction
= Direction_SouthEast
;
72 void setup_action_directional_focus_southwest(Action
*a
)
74 a
->data
.diraction
.direction
= Direction_SouthWest
;
77 void setup_action_directional_focus_northwest(Action
*a
)
79 a
->data
.diraction
.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 void setup_action_movetoedge_north(Action
*a
)
155 a
->data
.diraction
.direction
= Direction_North
;
158 void setup_action_movetoedge_south(Action
*a
)
160 a
->data
.diraction
.direction
= Direction_South
;
163 void setup_action_movetoedge_east(Action
*a
)
165 a
->data
.diraction
.direction
= Direction_East
;
168 void setup_action_movetoedge_west(Action
*a
)
170 a
->data
.diraction
.direction
= Direction_West
;
173 ActionString actionstrings
[] =
181 "directionalfocusnorth",
182 action_directional_focus
,
183 setup_action_directional_focus_north
186 "directionalfocuseast",
187 action_directional_focus
,
188 setup_action_directional_focus_east
191 "directionalfocussouth",
192 action_directional_focus
,
193 setup_action_directional_focus_south
196 "directionalfocuswest",
197 action_directional_focus
,
198 setup_action_directional_focus_west
201 "directionalfocusnortheast",
202 action_directional_focus
,
203 setup_action_directional_focus_northeast
206 "directionalfocussoutheast",
207 action_directional_focus
,
208 setup_action_directional_focus_southeast
211 "directionalfocussouthwest",
212 action_directional_focus
,
213 setup_action_directional_focus_southwest
216 "directionalfocusnorthwest",
217 action_directional_focus
,
218 setup_action_directional_focus_northwest
287 action_toggle_omnipresent
,
292 action_move_relative_horz
,
297 action_move_relative_vert
,
301 "resizerelativehorz",
302 action_resize_relative_horz
,
306 "resizerelativevert",
307 action_resize_relative_vert
,
312 action_maximize_full
,
317 action_unmaximize_full
,
321 "togglemaximizefull",
322 action_toggle_maximize_full
,
327 action_maximize_horz
,
332 action_unmaximize_horz
,
336 "togglemaximizehorz",
337 action_toggle_maximize_horz
,
342 action_maximize_vert
,
347 action_unmaximize_vert
,
351 "togglemaximizevert",
352 action_toggle_maximize_vert
,
357 action_send_to_desktop
,
358 setup_action_send_to_desktop
362 action_send_to_next_desktop
,
363 setup_action_send_to_np_desktop
366 "sendtonextdesktopwrap",
367 action_send_to_next_desktop
,
368 setup_action_send_to_np_desktop_wrap
371 "sendtopreviousdesktop",
372 action_send_to_previous_desktop
,
373 setup_action_send_to_np_desktop
376 "sendtopreviousdesktopwrap",
377 action_send_to_previous_desktop
,
378 setup_action_send_to_np_desktop_wrap
388 setup_action_np_desktop
393 setup_action_np_desktop_wrap
397 action_previous_desktop
,
398 setup_action_np_desktop
401 "previousdesktopwrap",
402 action_previous_desktop
,
403 setup_action_np_desktop_wrap
407 action_next_desktop_column
,
408 setup_action_np_desktop
411 "nextdesktopcolumnwrap",
412 action_next_desktop_column
,
413 setup_action_np_desktop_wrap
416 "previousdesktopcolumn",
417 action_previous_desktop_column
,
418 setup_action_np_desktop
421 "previousdesktopcolumnwrap",
422 action_previous_desktop_column
,
423 setup_action_np_desktop_wrap
427 action_next_desktop_row
,
428 setup_action_np_desktop
431 "nextdesktoprowwrap",
432 action_next_desktop_row
,
433 setup_action_np_desktop_wrap
436 "previousdesktoprow",
437 action_previous_desktop_row
,
438 setup_action_np_desktop
441 "previousdesktoprowwrap",
442 action_previous_desktop_row
,
443 setup_action_np_desktop_wrap
447 action_toggle_decorations
,
453 setup_action_move_keyboard
468 setup_action_resize_keyboard
487 action_cycle_windows
,
488 setup_action_cycle_windows_linear_next
491 "previouswindowlinear",
492 action_cycle_windows
,
493 setup_action_cycle_windows_linear_previous
497 action_cycle_windows
,
498 setup_action_cycle_windows_next
502 action_cycle_windows
,
503 setup_action_cycle_windows_previous
508 setup_action_movetoedge_north
513 setup_action_movetoedge_south
518 setup_action_movetoedge_west
523 setup_action_movetoedge_east
532 Action
*action_from_string(char *name
)
537 for (i
= 0; actionstrings
[i
].name
; i
++)
538 if (!g_ascii_strcasecmp(name
, actionstrings
[i
].name
)) {
539 a
= action_new(actionstrings
[i
].func
);
540 if (actionstrings
[i
].setup
)
541 actionstrings
[i
].setup(a
);
547 void action_execute(union ActionData
*data
)
550 if (data
->execute
.path
)
551 if (!g_spawn_command_line_async(data
->execute
.path
, &e
)) {
552 g_warning("failed to execute '%s': %s",
553 data
->execute
.path
, e
->message
);
557 void action_focus(union ActionData
*data
)
560 client_focus(data
->client
.c
);
563 void action_unfocus (union ActionData
*data
)
566 client_unfocus(data
->client
.c
);
569 void action_iconify(union ActionData
*data
)
572 client_iconify(data
->client
.c
, TRUE
, TRUE
);
575 void action_focusraise(union ActionData
*data
)
577 if (data
->client
.c
) {
578 client_focus(data
->client
.c
);
579 stacking_raise(CLIENT_AS_WINDOW(data
->client
.c
));
583 void action_raise(union ActionData
*data
)
586 stacking_raise(CLIENT_AS_WINDOW(data
->client
.c
));
589 void action_unshaderaise(union ActionData
*data
)
591 if (data
->client
.c
) {
592 if (data
->client
.c
->shaded
)
593 client_shade(data
->client
.c
, FALSE
);
595 stacking_raise(CLIENT_AS_WINDOW(data
->client
.c
));
599 void action_shadelower(union ActionData
*data
)
601 if (data
->client
.c
) {
602 if (data
->client
.c
->shaded
)
603 stacking_lower(CLIENT_AS_WINDOW(data
->client
.c
));
605 client_shade(data
->client
.c
, TRUE
);
609 void action_lower(union ActionData
*data
)
612 stacking_lower(CLIENT_AS_WINDOW(data
->client
.c
));
615 void action_close(union ActionData
*data
)
618 client_close(data
->client
.c
);
621 void action_kill(union ActionData
*data
)
624 client_kill(data
->client
.c
);
627 void action_shade(union ActionData
*data
)
630 client_shade(data
->client
.c
, TRUE
);
633 void action_unshade(union ActionData
*data
)
636 client_shade(data
->client
.c
, FALSE
);
639 void action_toggle_shade(union ActionData
*data
)
642 client_shade(data
->client
.c
, !data
->client
.c
->shaded
);
645 void action_toggle_omnipresent(union ActionData
*data
)
648 client_set_desktop(data
->client
.c
,
649 data
->client
.c
->desktop
== DESKTOP_ALL
?
650 screen_desktop
: DESKTOP_ALL
, FALSE
);
653 void action_move_relative_horz(union ActionData
*data
)
655 Client
*c
= data
->relative
.c
;
657 client_configure(c
, Corner_TopLeft
,
658 c
->area
.x
+ data
->relative
.delta
, c
->area
.y
,
659 c
->area
.width
, c
->area
.height
, TRUE
, TRUE
);
662 void action_move_relative_vert(union ActionData
*data
)
664 Client
*c
= data
->relative
.c
;
666 client_configure(c
, Corner_TopLeft
,
667 c
->area
.x
, c
->area
.y
+ data
->relative
.delta
,
668 c
->area
.width
, c
->area
.height
, TRUE
, TRUE
);
671 void action_resize_relative_horz(union ActionData
*data
)
673 Client
*c
= data
->relative
.c
;
675 client_configure(c
, Corner_TopLeft
, c
->area
.x
, c
->area
.y
,
677 data
->relative
.delta
* c
->size_inc
.width
,
678 c
->area
.height
, TRUE
, TRUE
);
681 void action_resize_relative_vert(union ActionData
*data
)
683 Client
*c
= data
->relative
.c
;
685 client_configure(c
, Corner_TopLeft
, c
->area
.x
, c
->area
.y
,
686 c
->area
.width
, c
->area
.height
+
687 data
->relative
.delta
* c
->size_inc
.height
,
691 void action_maximize_full(union ActionData
*data
)
694 client_maximize(data
->client
.c
, TRUE
, 0, TRUE
);
697 void action_unmaximize_full(union ActionData
*data
)
700 client_maximize(data
->client
.c
, FALSE
, 0, TRUE
);
703 void action_toggle_maximize_full(union ActionData
*data
)
706 client_maximize(data
->client
.c
,
707 !(data
->client
.c
->max_horz
||
708 data
->client
.c
->max_vert
),
712 void action_maximize_horz(union ActionData
*data
)
715 client_maximize(data
->client
.c
, TRUE
, 1, TRUE
);
718 void action_unmaximize_horz(union ActionData
*data
)
721 client_maximize(data
->client
.c
, FALSE
, 1, TRUE
);
724 void action_toggle_maximize_horz(union ActionData
*data
)
727 client_maximize(data
->client
.c
, !data
->client
.c
->max_horz
, 1, TRUE
);
730 void action_maximize_vert(union ActionData
*data
)
733 client_maximize(data
->client
.c
, TRUE
, 2, TRUE
);
736 void action_unmaximize_vert(union ActionData
*data
)
739 client_maximize(data
->client
.c
, FALSE
, 2, TRUE
);
742 void action_toggle_maximize_vert(union ActionData
*data
)
745 client_maximize(data
->client
.c
, !data
->client
.c
->max_vert
, 2, TRUE
);
748 void action_send_to_desktop(union ActionData
*data
)
750 if (data
->sendto
.c
) {
751 if (data
->sendto
.desk
< screen_num_desktops
||
752 data
->sendto
.desk
== DESKTOP_ALL
) {
753 client_set_desktop(data
->desktop
.c
,
754 data
->sendto
.desk
, data
->sendto
.follow
);
755 if (data
->sendto
.follow
) screen_set_desktop(data
->sendto
.desk
);
760 void action_send_to_next_desktop(union ActionData
*data
)
764 if (!data
->sendtonextprev
.c
) return;
766 d
= screen_desktop
+ 1;
767 if (d
>= screen_num_desktops
) {
768 if (!data
->sendtonextprev
.wrap
) return;
771 client_set_desktop(data
->sendtonextprev
.c
, d
, data
->sendtonextprev
.follow
);
772 if (data
->sendtonextprev
.follow
) screen_set_desktop(d
);
775 void action_send_to_previous_desktop(union ActionData
*data
)
779 if (!data
->sendtonextprev
.c
) return;
781 d
= screen_desktop
- 1;
782 if (d
>= screen_num_desktops
) {
783 if (!data
->sendtonextprev
.wrap
) return;
784 d
= screen_num_desktops
- 1;
786 client_set_desktop(data
->sendtonextprev
.c
, d
, data
->sendtonextprev
.follow
);
787 if (data
->sendtonextprev
.follow
) screen_set_desktop(d
);
790 void action_desktop(union ActionData
*data
)
792 if (data
->desktop
.desk
< screen_num_desktops
||
793 data
->desktop
.desk
== DESKTOP_ALL
)
794 screen_set_desktop(data
->desktop
.desk
);
797 void action_next_desktop(union ActionData
*data
)
801 d
= screen_desktop
+ 1;
802 if (d
>= screen_num_desktops
) {
803 if (!data
->nextprevdesktop
.wrap
) return;
806 screen_set_desktop(d
);
809 void action_previous_desktop(union ActionData
*data
)
813 d
= screen_desktop
- 1;
814 if (d
>= screen_num_desktops
) {
815 if (!data
->nextprevdesktop
.wrap
) return;
816 d
= screen_num_desktops
- 1;
818 screen_set_desktop(d
);
821 static void cur_row_col(guint
*r
, guint
*c
)
823 switch (screen_desktop_layout
.orientation
) {
824 case Orientation_Horz
:
825 switch (screen_desktop_layout
.start_corner
) {
827 *r
= screen_desktop
/ screen_desktop_layout
.columns
;
828 *c
= screen_desktop
% screen_desktop_layout
.columns
;
830 case Corner_BottomLeft
:
831 *r
= screen_desktop_layout
.rows
- 1 -
832 screen_desktop
/ screen_desktop_layout
.columns
;
833 *c
= screen_desktop
% screen_desktop_layout
.columns
;
835 case Corner_TopRight
:
836 *r
= screen_desktop
/ screen_desktop_layout
.columns
;
837 *c
= screen_desktop_layout
.columns
- 1 -
838 screen_desktop
% screen_desktop_layout
.columns
;
840 case Corner_BottomRight
:
841 *r
= screen_desktop_layout
.rows
- 1 -
842 screen_desktop
/ screen_desktop_layout
.columns
;
843 *c
= screen_desktop_layout
.columns
- 1 -
844 screen_desktop
% screen_desktop_layout
.columns
;
848 case Orientation_Vert
:
849 switch (screen_desktop_layout
.start_corner
) {
851 *r
= screen_desktop
% screen_desktop_layout
.rows
;
852 *c
= screen_desktop
/ screen_desktop_layout
.rows
;
854 case Corner_BottomLeft
:
855 *r
= screen_desktop_layout
.rows
- 1 -
856 screen_desktop
% screen_desktop_layout
.rows
;
857 *c
= screen_desktop
/ screen_desktop_layout
.rows
;
859 case Corner_TopRight
:
860 *r
= screen_desktop
% screen_desktop_layout
.rows
;
861 *c
= screen_desktop_layout
.columns
- 1 -
862 screen_desktop
/ screen_desktop_layout
.rows
;
864 case Corner_BottomRight
:
865 *r
= screen_desktop_layout
.rows
- 1 -
866 screen_desktop
% screen_desktop_layout
.rows
;
867 *c
= screen_desktop_layout
.columns
- 1 -
868 screen_desktop
/ screen_desktop_layout
.rows
;
875 static guint
translate_row_col(guint r
, guint c
)
877 switch (screen_desktop_layout
.orientation
) {
878 case Orientation_Horz
:
879 switch (screen_desktop_layout
.start_corner
) {
881 return r
% screen_desktop_layout
.rows
*
882 screen_desktop_layout
.columns
+
883 c
% screen_desktop_layout
.columns
;
884 case Corner_BottomLeft
:
885 return (screen_desktop_layout
.rows
- 1 -
886 r
% screen_desktop_layout
.rows
) *
887 screen_desktop_layout
.columns
+
888 c
% screen_desktop_layout
.columns
;
889 case Corner_TopRight
:
890 return r
% screen_desktop_layout
.rows
*
891 screen_desktop_layout
.columns
+
892 (screen_desktop_layout
.columns
- 1 -
893 c
% screen_desktop_layout
.columns
);
894 case Corner_BottomRight
:
895 return (screen_desktop_layout
.rows
- 1 -
896 r
% screen_desktop_layout
.rows
) *
897 screen_desktop_layout
.columns
+
898 (screen_desktop_layout
.columns
- 1 -
899 c
% screen_desktop_layout
.columns
);
901 case Orientation_Vert
:
902 switch (screen_desktop_layout
.start_corner
) {
904 return c
% screen_desktop_layout
.columns
*
905 screen_desktop_layout
.rows
+
906 r
% screen_desktop_layout
.rows
;
907 case Corner_BottomLeft
:
908 return c
% screen_desktop_layout
.columns
*
909 screen_desktop_layout
.rows
+
910 (screen_desktop_layout
.rows
- 1 -
911 r
% screen_desktop_layout
.rows
);
912 case Corner_TopRight
:
913 return (screen_desktop_layout
.columns
- 1 -
914 c
% screen_desktop_layout
.columns
) *
915 screen_desktop_layout
.rows
+
916 r
% screen_desktop_layout
.rows
;
917 case Corner_BottomRight
:
918 return (screen_desktop_layout
.columns
- 1 -
919 c
% screen_desktop_layout
.columns
) *
920 screen_desktop_layout
.rows
+
921 (screen_desktop_layout
.rows
- 1 -
922 r
% screen_desktop_layout
.rows
);
925 g_assert_not_reached();
929 void action_next_desktop_column(union ActionData
*data
)
935 if (c
>= screen_desktop_layout
.columns
)
937 d
= translate_row_col(r
, c
);
938 if (d
>= screen_num_desktops
) {
939 if (!data
->nextprevdesktop
.wrap
) return;
942 d
= translate_row_col(r
, c
);
943 if (d
< screen_num_desktops
)
944 screen_set_desktop(d
);
947 void action_previous_desktop_column(union ActionData
*data
)
953 if (c
>= screen_desktop_layout
.columns
)
954 c
= screen_desktop_layout
.columns
- 1;
955 d
= translate_row_col(r
, c
);
956 if (d
>= screen_num_desktops
) {
957 if (!data
->nextprevdesktop
.wrap
) return;
960 d
= translate_row_col(r
, c
);
961 if (d
< screen_num_desktops
)
962 screen_set_desktop(d
);
965 void action_next_desktop_row(union ActionData
*data
)
971 if (r
>= screen_desktop_layout
.rows
)
973 d
= translate_row_col(r
, c
);
974 if (d
>= screen_num_desktops
) {
975 if (!data
->nextprevdesktop
.wrap
) return;
978 d
= translate_row_col(r
, c
);
979 if (d
< screen_num_desktops
)
980 screen_set_desktop(d
);
983 void action_previous_desktop_row(union ActionData
*data
)
989 if (r
>= screen_desktop_layout
.rows
)
990 r
= screen_desktop_layout
.rows
- 1;
991 d
= translate_row_col(r
, c
);
992 if (d
>= screen_num_desktops
) {
993 if (!data
->nextprevdesktop
.wrap
) return;
996 d
= translate_row_col(r
, c
);
997 if (d
< screen_num_desktops
)
998 screen_set_desktop(d
);
1001 void action_toggle_decorations(union ActionData
*data
)
1003 Client
*c
= data
->client
.c
;;
1007 c
->disabled_decorations
= c
->disabled_decorations
? 0 : ~0;
1008 client_setup_decor_and_functions(c
);
1011 void action_moveresize(union ActionData
*data
)
1013 Client
*c
= data
->moveresize
.c
;
1015 if (!c
|| !client_normal(c
)) return;
1017 moveresize_start(c
, data
->moveresize
.x
, data
->moveresize
.y
,
1018 data
->moveresize
.button
, data
->moveresize
.corner
);
1021 void action_restart(union ActionData
*data
)
1023 ob_restart_path
= data
->execute
.path
;
1024 ob_shutdown
= ob_restart
= TRUE
;
1027 void action_exit(union ActionData
*data
)
1032 void action_showmenu(union ActionData
*data
)
1034 if (data
->showmenu
.name
) {
1035 menu_show(data
->showmenu
.name
, data
->showmenu
.x
, data
->showmenu
.y
,
1040 void action_cycle_windows(union ActionData
*data
)
1044 c
= focus_cycle(data
->cycle
.forward
, data
->cycle
.linear
, data
->cycle
.final
,
1045 data
->cycle
.cancel
);
1048 void action_directional_focus(union ActionData
*data
)
1052 if (!data
->diraction
.c
)
1054 if ((nf
= client_find_directional(data
->diraction
.c
,
1055 data
->diraction
.direction
)))
1056 client_activate(nf
);
1059 void action_movetoedge(union ActionData
*data
)
1062 Client
*c
= data
->diraction
.c
;
1066 x
= c
->frame
->area
.x
;
1067 y
= c
->frame
->area
.y
;
1069 h
= screen_area(c
->desktop
)->height
;
1070 w
= screen_area(c
->desktop
)->width
;
1071 switch(data
->diraction
.direction
) {
1072 case Direction_North
:
1075 case Direction_West
:
1078 case Direction_South
:
1079 y
= h
- c
->frame
->area
.height
;
1081 case Direction_East
:
1082 x
= w
- c
->frame
->area
.width
;
1085 frame_frame_gravity(c
->frame
, &x
, &y
);
1086 client_configure(c
, Corner_TopLeft
,
1087 x
, y
, c
->area
.width
, c
->area
.height
, TRUE
, TRUE
);