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
,
637 data
->relative
.delta
* c
->size_inc
.width
,
638 c
->area
.height
, TRUE
, TRUE
);
641 void action_resize_relative_vert(union ActionData
*data
)
643 Client
*c
= data
->relative
.c
;
645 client_configure(c
, Corner_TopLeft
, c
->area
.x
, c
->area
.y
,
646 c
->area
.width
, c
->area
.height
+
647 data
->relative
.delta
* c
->size_inc
.height
,
651 void action_maximize_full(union ActionData
*data
)
654 client_maximize(data
->client
.c
, TRUE
, 0, TRUE
);
657 void action_unmaximize_full(union ActionData
*data
)
660 client_maximize(data
->client
.c
, FALSE
, 0, TRUE
);
663 void action_toggle_maximize_full(union ActionData
*data
)
666 client_maximize(data
->client
.c
,
667 !(data
->client
.c
->max_horz
||
668 data
->client
.c
->max_vert
),
672 void action_maximize_horz(union ActionData
*data
)
675 client_maximize(data
->client
.c
, TRUE
, 1, TRUE
);
678 void action_unmaximize_horz(union ActionData
*data
)
681 client_maximize(data
->client
.c
, FALSE
, 1, TRUE
);
684 void action_toggle_maximize_horz(union ActionData
*data
)
687 client_maximize(data
->client
.c
, !data
->client
.c
->max_horz
, 1, TRUE
);
690 void action_maximize_vert(union ActionData
*data
)
693 client_maximize(data
->client
.c
, TRUE
, 2, TRUE
);
696 void action_unmaximize_vert(union ActionData
*data
)
699 client_maximize(data
->client
.c
, FALSE
, 2, TRUE
);
702 void action_toggle_maximize_vert(union ActionData
*data
)
705 client_maximize(data
->client
.c
, !data
->client
.c
->max_vert
, 2, TRUE
);
708 void action_send_to_desktop(union ActionData
*data
)
710 if (data
->sendto
.c
) {
711 if (data
->sendto
.desk
< screen_num_desktops
||
712 data
->sendto
.desk
== DESKTOP_ALL
) {
713 client_set_desktop(data
->desktop
.c
,
714 data
->sendto
.desk
, data
->sendto
.follow
);
715 if (data
->sendto
.follow
) screen_set_desktop(data
->sendto
.desk
);
720 void action_send_to_next_desktop(union ActionData
*data
)
724 if (!data
->sendtonextprev
.c
) return;
726 d
= screen_desktop
+ 1;
727 if (d
>= screen_num_desktops
) {
728 if (!data
->sendtonextprev
.wrap
) return;
731 client_set_desktop(data
->sendtonextprev
.c
, d
, data
->sendtonextprev
.follow
);
732 if (data
->sendtonextprev
.follow
) screen_set_desktop(d
);
735 void action_send_to_previous_desktop(union ActionData
*data
)
739 if (!data
->sendtonextprev
.c
) return;
741 d
= screen_desktop
- 1;
742 if (d
>= screen_num_desktops
) {
743 if (!data
->sendtonextprev
.wrap
) return;
744 d
= screen_num_desktops
- 1;
746 client_set_desktop(data
->sendtonextprev
.c
, d
, data
->sendtonextprev
.follow
);
747 if (data
->sendtonextprev
.follow
) screen_set_desktop(d
);
750 void action_desktop(union ActionData
*data
)
752 if (data
->desktop
.desk
< screen_num_desktops
||
753 data
->desktop
.desk
== DESKTOP_ALL
)
754 screen_set_desktop(data
->desktop
.desk
);
757 void action_next_desktop(union ActionData
*data
)
761 d
= screen_desktop
+ 1;
762 if (d
>= screen_num_desktops
) {
763 if (!data
->nextprevdesktop
.wrap
) return;
766 screen_set_desktop(d
);
769 void action_previous_desktop(union ActionData
*data
)
773 d
= screen_desktop
- 1;
774 if (d
>= screen_num_desktops
) {
775 if (!data
->nextprevdesktop
.wrap
) return;
776 d
= screen_num_desktops
- 1;
778 screen_set_desktop(d
);
781 static void cur_row_col(guint
*r
, guint
*c
)
783 switch (screen_desktop_layout
.orientation
) {
784 case Orientation_Horz
:
785 switch (screen_desktop_layout
.start_corner
) {
787 *r
= screen_desktop
/ screen_desktop_layout
.columns
;
788 *c
= screen_desktop
% screen_desktop_layout
.columns
;
790 case Corner_BottomLeft
:
791 *r
= screen_desktop_layout
.rows
- 1 -
792 screen_desktop
/ screen_desktop_layout
.columns
;
793 *c
= screen_desktop
% screen_desktop_layout
.columns
;
795 case Corner_TopRight
:
796 *r
= screen_desktop
/ screen_desktop_layout
.columns
;
797 *c
= screen_desktop_layout
.columns
- 1 -
798 screen_desktop
% screen_desktop_layout
.columns
;
800 case Corner_BottomRight
:
801 *r
= screen_desktop_layout
.rows
- 1 -
802 screen_desktop
/ screen_desktop_layout
.columns
;
803 *c
= screen_desktop_layout
.columns
- 1 -
804 screen_desktop
% screen_desktop_layout
.columns
;
808 case Orientation_Vert
:
809 switch (screen_desktop_layout
.start_corner
) {
811 *r
= screen_desktop
% screen_desktop_layout
.rows
;
812 *c
= screen_desktop
/ screen_desktop_layout
.rows
;
814 case Corner_BottomLeft
:
815 *r
= screen_desktop_layout
.rows
- 1 -
816 screen_desktop
% screen_desktop_layout
.rows
;
817 *c
= screen_desktop
/ screen_desktop_layout
.rows
;
819 case Corner_TopRight
:
820 *r
= screen_desktop
% screen_desktop_layout
.rows
;
821 *c
= screen_desktop_layout
.columns
- 1 -
822 screen_desktop
/ screen_desktop_layout
.rows
;
824 case Corner_BottomRight
:
825 *r
= screen_desktop_layout
.rows
- 1 -
826 screen_desktop
% screen_desktop_layout
.rows
;
827 *c
= screen_desktop_layout
.columns
- 1 -
828 screen_desktop
/ screen_desktop_layout
.rows
;
835 static guint
translate_row_col(guint r
, guint c
)
837 switch (screen_desktop_layout
.orientation
) {
838 case Orientation_Horz
:
839 switch (screen_desktop_layout
.start_corner
) {
841 return r
% screen_desktop_layout
.rows
*
842 screen_desktop_layout
.columns
+
843 c
% screen_desktop_layout
.columns
;
844 case Corner_BottomLeft
:
845 return (screen_desktop_layout
.rows
- 1 -
846 r
% screen_desktop_layout
.rows
) *
847 screen_desktop_layout
.columns
+
848 c
% screen_desktop_layout
.columns
;
849 case Corner_TopRight
:
850 return r
% screen_desktop_layout
.rows
*
851 screen_desktop_layout
.columns
+
852 (screen_desktop_layout
.columns
- 1 -
853 c
% screen_desktop_layout
.columns
);
854 case Corner_BottomRight
:
855 return (screen_desktop_layout
.rows
- 1 -
856 r
% screen_desktop_layout
.rows
) *
857 screen_desktop_layout
.columns
+
858 (screen_desktop_layout
.columns
- 1 -
859 c
% screen_desktop_layout
.columns
);
861 case Orientation_Vert
:
862 switch (screen_desktop_layout
.start_corner
) {
864 return c
% screen_desktop_layout
.columns
*
865 screen_desktop_layout
.rows
+
866 r
% screen_desktop_layout
.rows
;
867 case Corner_BottomLeft
:
868 return c
% screen_desktop_layout
.columns
*
869 screen_desktop_layout
.rows
+
870 (screen_desktop_layout
.rows
- 1 -
871 r
% screen_desktop_layout
.rows
);
872 case Corner_TopRight
:
873 return (screen_desktop_layout
.columns
- 1 -
874 c
% screen_desktop_layout
.columns
) *
875 screen_desktop_layout
.rows
+
876 r
% screen_desktop_layout
.rows
;
877 case Corner_BottomRight
:
878 return (screen_desktop_layout
.columns
- 1 -
879 c
% screen_desktop_layout
.columns
) *
880 screen_desktop_layout
.rows
+
881 (screen_desktop_layout
.rows
- 1 -
882 r
% screen_desktop_layout
.rows
);
885 g_assert_not_reached();
889 void action_next_desktop_column(union ActionData
*data
)
895 if (c
>= screen_desktop_layout
.columns
)
897 d
= translate_row_col(r
, c
);
898 if (d
>= screen_num_desktops
) {
899 if (!data
->nextprevdesktop
.wrap
) return;
902 d
= translate_row_col(r
, c
);
903 if (d
< screen_num_desktops
)
904 screen_set_desktop(d
);
907 void action_previous_desktop_column(union ActionData
*data
)
913 if (c
>= screen_desktop_layout
.columns
)
914 c
= screen_desktop_layout
.columns
- 1;
915 d
= translate_row_col(r
, c
);
916 if (d
>= screen_num_desktops
) {
917 if (!data
->nextprevdesktop
.wrap
) return;
920 d
= translate_row_col(r
, c
);
921 if (d
< screen_num_desktops
)
922 screen_set_desktop(d
);
925 void action_next_desktop_row(union ActionData
*data
)
931 if (r
>= screen_desktop_layout
.rows
)
933 d
= translate_row_col(r
, c
);
934 if (d
>= screen_num_desktops
) {
935 if (!data
->nextprevdesktop
.wrap
) return;
938 d
= translate_row_col(r
, c
);
939 if (d
< screen_num_desktops
)
940 screen_set_desktop(d
);
943 void action_previous_desktop_row(union ActionData
*data
)
949 if (r
>= screen_desktop_layout
.rows
)
950 r
= screen_desktop_layout
.rows
- 1;
951 d
= translate_row_col(r
, c
);
952 if (d
>= screen_num_desktops
) {
953 if (!data
->nextprevdesktop
.wrap
) return;
956 d
= translate_row_col(r
, c
);
957 if (d
< screen_num_desktops
)
958 screen_set_desktop(d
);
961 void action_toggle_decorations(union ActionData
*data
)
963 Client
*c
= data
->client
.c
;;
967 c
->disabled_decorations
= c
->disabled_decorations
? 0 : ~0;
968 client_setup_decor_and_functions(c
);
971 void action_moveresize(union ActionData
*data
)
973 Client
*c
= data
->moveresize
.c
;
975 if (!c
|| !client_normal(c
)) return;
977 moveresize_start(c
, data
->moveresize
.x
, data
->moveresize
.y
,
978 data
->moveresize
.button
, data
->moveresize
.corner
);
981 void action_restart(union ActionData
*data
)
983 ob_restart_path
= data
->execute
.path
;
984 ob_shutdown
= ob_restart
= TRUE
;
987 void action_exit(union ActionData
*data
)
992 void action_showmenu(union ActionData
*data
)
994 if (data
->showmenu
.name
) {
995 menu_show(data
->showmenu
.name
, data
->showmenu
.x
, data
->showmenu
.y
,
1000 void action_cycle_windows(union ActionData
*data
)
1004 c
= focus_cycle(data
->cycle
.forward
, data
->cycle
.linear
, data
->cycle
.final
,
1005 data
->cycle
.cancel
);
1008 void action_directional_focus(union ActionData
*data
)
1012 if (!data
->dfocus
.c
)
1014 if ((nf
= client_find_directional(data
->dfocus
.c
, data
->dfocus
.direction
)))
1015 client_activate(nf
);