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);