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_desktop_direction(Action *a)
89 a->data.sendtodir.wrap = TRUE;
90 a->data.sendtodir.follow = TRUE;
93 void setup_action_desktop_direction(Action *a)
95 a->data.desktopdir.wrap = TRUE;
98 void setup_action_move_keyboard(Action *a)
100 a->data.moveresize.corner = prop_atoms.net_wm_moveresize_move_keyboard;
103 void setup_action_move(Action *a)
105 a->data.moveresize.corner = prop_atoms.net_wm_moveresize_move;
108 void setup_action_resize(Action *a)
110 a->data.moveresize.corner = prop_atoms.net_wm_moveresize_size_topleft;
113 void setup_action_resize_keyboard(Action *a)
115 a->data.moveresize.corner = prop_atoms.net_wm_moveresize_size_keyboard;
118 void setup_action_cycle_windows_linear_next(Action *a)
120 a->data.cycle.linear = TRUE;
121 a->data.cycle.forward = TRUE;
124 void setup_action_cycle_windows_linear_previous(Action *a)
126 a->data.cycle.linear = TRUE;
127 a->data.cycle.forward = FALSE;
130 void setup_action_cycle_windows_next(Action *a)
132 a->data.cycle.linear = FALSE;
133 a->data.cycle.forward = TRUE;
136 void setup_action_cycle_windows_previous(Action *a)
138 a->data.cycle.linear = FALSE;
139 a->data.cycle.forward = FALSE;
142 void setup_action_movetoedge_north(Action *a)
144 a->data.diraction.direction = Direction_North;
147 void setup_action_movetoedge_south(Action *a)
149 a->data.diraction.direction = Direction_South;
152 void setup_action_movetoedge_east(Action *a)
154 a->data.diraction.direction = Direction_East;
157 void setup_action_movetoedge_west(Action *a)
159 a->data.diraction.direction = Direction_West;
162 void setup_action_top_layer(Action *a)
164 a->data.layer.layer = 1;
167 void setup_action_normal_layer(Action *a)
169 a->data.layer.layer = 0;
172 void setup_action_bottom_layer(Action *a)
174 a->data.layer.layer = -1;
177 ActionString actionstrings[] =
185 "directionalfocusnorth",
186 action_directional_focus,
187 setup_action_directional_focus_north
190 "directionalfocuseast",
191 action_directional_focus,
192 setup_action_directional_focus_east
195 "directionalfocussouth",
196 action_directional_focus,
197 setup_action_directional_focus_south
200 "directionalfocuswest",
201 action_directional_focus,
202 setup_action_directional_focus_west
205 "directionalfocusnortheast",
206 action_directional_focus,
207 setup_action_directional_focus_northeast
210 "directionalfocussoutheast",
211 action_directional_focus,
212 setup_action_directional_focus_southeast
215 "directionalfocussouthwest",
216 action_directional_focus,
217 setup_action_directional_focus_southwest
220 "directionalfocusnorthwest",
221 action_directional_focus,
222 setup_action_directional_focus_northwest
291 action_toggle_omnipresent,
296 action_move_relative_horz,
301 action_move_relative_vert,
305 "resizerelativehorz",
306 action_resize_relative_horz,
310 "resizerelativevert",
311 action_resize_relative_vert,
316 action_maximize_full,
321 action_unmaximize_full,
325 "togglemaximizefull",
326 action_toggle_maximize_full,
331 action_maximize_horz,
336 action_unmaximize_horz,
340 "togglemaximizehorz",
341 action_toggle_maximize_horz,
346 action_maximize_vert,
351 action_unmaximize_vert,
355 "togglemaximizevert",
356 action_toggle_maximize_vert,
361 action_send_to_desktop,
362 setup_action_send_to_desktop
365 "sendtodesktopright",
366 action_send_to_desktop_right,
367 setup_action_send_to_desktop_direction
371 action_send_to_desktop_left,
372 setup_action_send_to_desktop_direction
376 action_send_to_desktop_up,
377 setup_action_send_to_desktop_direction
381 action_send_to_desktop_down,
382 setup_action_send_to_desktop_direction
391 action_desktop_right,
392 setup_action_desktop_direction
397 setup_action_desktop_direction
402 setup_action_desktop_direction
407 setup_action_desktop_direction
411 action_toggle_decorations,
417 setup_action_move_keyboard
432 setup_action_resize_keyboard
436 action_toggle_show_desktop,
446 action_unshow_desktop,
466 action_send_to_layer,
467 setup_action_top_layer
472 setup_action_top_layer
476 action_send_to_layer,
477 setup_action_normal_layer
481 action_send_to_layer,
482 setup_action_bottom_layer
485 "togglealwaysonbottom",
487 setup_action_bottom_layer
491 action_cycle_windows,
492 setup_action_cycle_windows_linear_next
495 "previouswindowlinear",
496 action_cycle_windows,
497 setup_action_cycle_windows_linear_previous
501 action_cycle_windows,
502 setup_action_cycle_windows_next
506 action_cycle_windows,
507 setup_action_cycle_windows_previous
512 setup_action_movetoedge_north
517 setup_action_movetoedge_south
522 setup_action_movetoedge_west
527 setup_action_movetoedge_east
536 Action *action_from_string(char *name)
541 for (i = 0; actionstrings[i].name; i++)
542 if (!g_ascii_strcasecmp(name, actionstrings[i].name)) {
543 a = action_new(actionstrings[i].func);
544 if (actionstrings[i].setup)
545 actionstrings[i].setup(a);
551 void action_execute(union ActionData *data)
555 if (data->execute.path) {
556 cmd = g_filename_from_utf8(data->execute.path, -1, NULL, NULL, NULL);
558 if (!g_spawn_command_line_async(cmd, &e)) {
559 g_warning("failed to execute '%s': %s",
563 g_warning("failed to convert '%s' from utf8", data->execute.path);
568 void action_focus(union ActionData *data)
571 client_focus(data->client.c);
574 void action_unfocus (union ActionData *data)
577 client_unfocus(data->client.c);
580 void action_iconify(union ActionData *data)
583 client_iconify(data->client.c, TRUE, TRUE);
586 void action_focusraise(union ActionData *data)
588 if (data->client.c) {
589 client_focus(data->client.c);
590 stacking_raise(CLIENT_AS_WINDOW(data->client.c));
594 void action_raise(union ActionData *data)
597 stacking_raise(CLIENT_AS_WINDOW(data->client.c));
600 void action_unshaderaise(union ActionData *data)
602 if (data->client.c) {
603 if (data->client.c->shaded)
604 client_shade(data->client.c, FALSE);
606 stacking_raise(CLIENT_AS_WINDOW(data->client.c));
610 void action_shadelower(union ActionData *data)
612 if (data->client.c) {
613 if (data->client.c->shaded)
614 stacking_lower(CLIENT_AS_WINDOW(data->client.c));
616 client_shade(data->client.c, TRUE);
620 void action_lower(union ActionData *data)
623 stacking_lower(CLIENT_AS_WINDOW(data->client.c));
626 void action_close(union ActionData *data)
629 client_close(data->client.c);
632 void action_kill(union ActionData *data)
635 client_kill(data->client.c);
638 void action_shade(union ActionData *data)
641 client_shade(data->client.c, TRUE);
644 void action_unshade(union ActionData *data)
647 client_shade(data->client.c, FALSE);
650 void action_toggle_shade(union ActionData *data)
653 client_shade(data->client.c, !data->client.c->shaded);
656 void action_toggle_omnipresent(union ActionData *data)
659 client_set_desktop(data->client.c,
660 data->client.c->desktop == DESKTOP_ALL ?
661 screen_desktop : DESKTOP_ALL, FALSE);
664 void action_move_relative_horz(union ActionData *data)
666 Client *c = data->relative.c;
668 client_configure(c, Corner_TopLeft,
669 c->area.x + data->relative.delta, c->area.y,
670 c->area.width, c->area.height, TRUE, TRUE);
673 void action_move_relative_vert(union ActionData *data)
675 Client *c = data->relative.c;
677 client_configure(c, Corner_TopLeft,
678 c->area.x, c->area.y + data->relative.delta,
679 c->area.width, c->area.height, TRUE, TRUE);
682 void action_resize_relative_horz(union ActionData *data)
684 Client *c = data->relative.c;
686 client_configure(c, Corner_TopLeft, c->area.x, c->area.y,
688 data->relative.delta * c->size_inc.width,
689 c->area.height, TRUE, TRUE);
692 void action_resize_relative_vert(union ActionData *data)
694 Client *c = data->relative.c;
696 client_configure(c, Corner_TopLeft, c->area.x, c->area.y,
697 c->area.width, c->area.height +
698 data->relative.delta * c->size_inc.height,
702 void action_maximize_full(union ActionData *data)
705 client_maximize(data->client.c, TRUE, 0, TRUE);
708 void action_unmaximize_full(union ActionData *data)
711 client_maximize(data->client.c, FALSE, 0, TRUE);
714 void action_toggle_maximize_full(union ActionData *data)
717 client_maximize(data->client.c,
718 !(data->client.c->max_horz ||
719 data->client.c->max_vert),
723 void action_maximize_horz(union ActionData *data)
726 client_maximize(data->client.c, TRUE, 1, TRUE);
729 void action_unmaximize_horz(union ActionData *data)
732 client_maximize(data->client.c, FALSE, 1, TRUE);
735 void action_toggle_maximize_horz(union ActionData *data)
738 client_maximize(data->client.c, !data->client.c->max_horz, 1, TRUE);
741 void action_maximize_vert(union ActionData *data)
744 client_maximize(data->client.c, TRUE, 2, TRUE);
747 void action_unmaximize_vert(union ActionData *data)
750 client_maximize(data->client.c, FALSE, 2, TRUE);
753 void action_toggle_maximize_vert(union ActionData *data)
756 client_maximize(data->client.c, !data->client.c->max_vert, 2, TRUE);
759 void action_send_to_desktop(union ActionData *data)
761 if (data->sendto.c) {
762 if (data->sendto.desk < screen_num_desktops ||
763 data->sendto.desk == DESKTOP_ALL) {
764 client_set_desktop(data->desktop.c,
765 data->sendto.desk, data->sendto.follow);
766 if (data->sendto.follow) screen_set_desktop(data->sendto.desk);
771 void action_desktop(union ActionData *data)
773 if (data->desktop.desk < screen_num_desktops ||
774 data->desktop.desk == DESKTOP_ALL)
775 screen_set_desktop(data->desktop.desk);
778 static void cur_row_col(guint *r, guint *c)
780 switch (screen_desktop_layout.orientation) {
781 case Orientation_Horz:
782 switch (screen_desktop_layout.start_corner) {
784 *r = screen_desktop / screen_desktop_layout.columns;
785 *c = screen_desktop % screen_desktop_layout.columns;
787 case Corner_BottomLeft:
788 *r = screen_desktop_layout.rows - 1 -
789 screen_desktop / screen_desktop_layout.columns;
790 *c = screen_desktop % screen_desktop_layout.columns;
792 case Corner_TopRight:
793 *r = screen_desktop / screen_desktop_layout.columns;
794 *c = screen_desktop_layout.columns - 1 -
795 screen_desktop % screen_desktop_layout.columns;
797 case Corner_BottomRight:
798 *r = screen_desktop_layout.rows - 1 -
799 screen_desktop / screen_desktop_layout.columns;
800 *c = screen_desktop_layout.columns - 1 -
801 screen_desktop % screen_desktop_layout.columns;
805 case Orientation_Vert:
806 switch (screen_desktop_layout.start_corner) {
808 *r = screen_desktop % screen_desktop_layout.rows;
809 *c = screen_desktop / screen_desktop_layout.rows;
811 case Corner_BottomLeft:
812 *r = screen_desktop_layout.rows - 1 -
813 screen_desktop % screen_desktop_layout.rows;
814 *c = screen_desktop / screen_desktop_layout.rows;
816 case Corner_TopRight:
817 *r = screen_desktop % screen_desktop_layout.rows;
818 *c = screen_desktop_layout.columns - 1 -
819 screen_desktop / screen_desktop_layout.rows;
821 case Corner_BottomRight:
822 *r = screen_desktop_layout.rows - 1 -
823 screen_desktop % screen_desktop_layout.rows;
824 *c = screen_desktop_layout.columns - 1 -
825 screen_desktop / screen_desktop_layout.rows;
832 static guint translate_row_col(guint r, guint c)
834 switch (screen_desktop_layout.orientation) {
835 case Orientation_Horz:
836 switch (screen_desktop_layout.start_corner) {
838 return r % screen_desktop_layout.rows *
839 screen_desktop_layout.columns +
840 c % screen_desktop_layout.columns;
841 case Corner_BottomLeft:
842 return (screen_desktop_layout.rows - 1 -
843 r % screen_desktop_layout.rows) *
844 screen_desktop_layout.columns +
845 c % screen_desktop_layout.columns;
846 case Corner_TopRight:
847 return r % screen_desktop_layout.rows *
848 screen_desktop_layout.columns +
849 (screen_desktop_layout.columns - 1 -
850 c % screen_desktop_layout.columns);
851 case Corner_BottomRight:
852 return (screen_desktop_layout.rows - 1 -
853 r % screen_desktop_layout.rows) *
854 screen_desktop_layout.columns +
855 (screen_desktop_layout.columns - 1 -
856 c % screen_desktop_layout.columns);
858 case Orientation_Vert:
859 switch (screen_desktop_layout.start_corner) {
861 return c % screen_desktop_layout.columns *
862 screen_desktop_layout.rows +
863 r % screen_desktop_layout.rows;
864 case Corner_BottomLeft:
865 return c % screen_desktop_layout.columns *
866 screen_desktop_layout.rows +
867 (screen_desktop_layout.rows - 1 -
868 r % screen_desktop_layout.rows);
869 case Corner_TopRight:
870 return (screen_desktop_layout.columns - 1 -
871 c % screen_desktop_layout.columns) *
872 screen_desktop_layout.rows +
873 r % screen_desktop_layout.rows;
874 case Corner_BottomRight:
875 return (screen_desktop_layout.columns - 1 -
876 c % screen_desktop_layout.columns) *
877 screen_desktop_layout.rows +
878 (screen_desktop_layout.rows - 1 -
879 r % screen_desktop_layout.rows);
882 g_assert_not_reached();
886 void action_desktop_right(union ActionData *data)
892 if (c >= screen_desktop_layout.columns) {
893 if (!data->desktopdir.wrap) return;
896 d = translate_row_col(r, c);
897 if (d >= screen_num_desktops) {
898 if (!data->desktopdir.wrap) return;
901 d = translate_row_col(r, c);
902 if (d < screen_num_desktops)
903 screen_set_desktop(d);
906 void action_send_to_desktop_right(union ActionData *data)
910 if (data->sendtodir.c) {
913 if (c >= screen_desktop_layout.columns) {
914 if (!data->sendtodir.wrap) return;
917 d = translate_row_col(r, c);
918 if (d >= screen_num_desktops) {
919 if (!data->sendtodir.wrap) return;
922 d = translate_row_col(r, c);
923 if (d < screen_num_desktops) {
924 client_set_desktop(data->sendtodir.c, d, data->sendtodir.follow);
925 if (data->sendtodir.follow) screen_set_desktop(d);
930 void action_desktop_left(union ActionData *data)
936 if (c >= screen_desktop_layout.columns) {
937 if (!data->desktopdir.wrap) return;
938 c = screen_desktop_layout.columns - 1;
940 d = translate_row_col(r, c);
941 if (d >= screen_num_desktops) {
942 if (!data->desktopdir.wrap) return;
945 d = translate_row_col(r, c);
946 if (d < screen_num_desktops)
947 screen_set_desktop(d);
950 void action_send_to_desktop_left(union ActionData *data)
954 if (data->sendtodir.c) {
957 if (c >= screen_desktop_layout.columns) {
958 if (!data->sendtodir.wrap) return;
959 c = screen_desktop_layout.columns - 1;
961 d = translate_row_col(r, c);
962 if (d >= screen_num_desktops) {
963 if (!data->sendtodir.wrap) return;
966 d = translate_row_col(r, c);
967 if (d < screen_num_desktops) {
968 client_set_desktop(data->sendtodir.c, d, data->sendtodir.follow);
969 if (data->sendtodir.follow) screen_set_desktop(d);
974 void action_desktop_down(union ActionData *data)
980 if (r >= screen_desktop_layout.rows) {
981 if (!data->desktopdir.wrap) return;
984 d = translate_row_col(r, c);
985 if (d >= screen_num_desktops) {
986 if (!data->desktopdir.wrap) return;
989 d = translate_row_col(r, c);
990 if (d < screen_num_desktops)
991 screen_set_desktop(d);
994 void action_send_to_desktop_down(union ActionData *data)
998 if (data->sendtodir.c) {
1001 if (r >= screen_desktop_layout.rows) {
1002 if (!data->sendtodir.wrap) return;
1005 d = translate_row_col(r, c);
1006 if (d >= screen_num_desktops) {
1007 if (!data->sendtodir.wrap) return;
1010 d = translate_row_col(r, c);
1011 if (d < screen_num_desktops) {
1012 client_set_desktop(data->sendtodir.c, d, data->sendtodir.follow);
1013 if (data->sendtodir.follow) screen_set_desktop(d);
1018 void action_desktop_up(union ActionData *data)
1022 cur_row_col(&r, &c);
1024 if (r >= screen_desktop_layout.rows) {
1025 if (!data->desktopdir.wrap) return;
1026 r = screen_desktop_layout.rows - 1;
1028 d = translate_row_col(r, c);
1029 if (d >= screen_num_desktops) {
1030 if (!data->desktopdir.wrap) return;
1033 d = translate_row_col(r, c);
1034 if (d < screen_num_desktops)
1035 screen_set_desktop(d);
1038 void action_send_to_desktop_up(union ActionData *data)
1042 if (data->sendtodir.c) {
1043 cur_row_col(&r, &c);
1045 if (r >= screen_desktop_layout.rows) {
1046 if (!data->sendtodir.wrap) return;
1047 r = screen_desktop_layout.rows - 1;
1049 d = translate_row_col(r, c);
1050 if (d >= screen_num_desktops) {
1051 if (!data->sendtodir.wrap) return;
1054 d = translate_row_col(r, c);
1055 if (d < screen_num_desktops) {
1056 client_set_desktop(data->sendtodir.c, d, data->sendtodir.follow);
1057 if (data->sendtodir.follow) screen_set_desktop(d);
1062 void action_toggle_decorations(union ActionData *data)
1064 Client *c = data->client.c;;
1068 c->disabled_decorations = c->disabled_decorations ? 0 : ~0;
1069 client_setup_decor_and_functions(c);
1072 void action_moveresize(union ActionData *data)
1074 Client *c = data->moveresize.c;
1076 if (!c || !client_normal(c)) return;
1078 moveresize_start(c, data->moveresize.x, data->moveresize.y,
1079 data->moveresize.button, data->moveresize.corner);
1082 void action_restart(union ActionData *data)
1084 ob_restart_path = data->execute.path;
1085 ob_shutdown = ob_restart = TRUE;
1088 void action_exit(union ActionData *data)
1093 void action_showmenu(union ActionData *data)
1095 if (data->showmenu.name) {
1096 menu_show(data->showmenu.name, data->showmenu.x, data->showmenu.y,
1101 void action_cycle_windows(union ActionData *data)
1105 c = focus_cycle(data->cycle.forward, data->cycle.linear, data->cycle.final,
1106 data->cycle.cancel);
1109 void action_directional_focus(union ActionData *data)
1113 if (!data->diraction.c)
1115 if ((nf = client_find_directional(data->diraction.c,
1116 data->diraction.direction)))
1117 client_activate(nf);
1120 void action_movetoedge(union ActionData *data)
1123 Client *c = data->diraction.c;
1127 x = c->frame->area.x;
1128 y = c->frame->area.y;
1130 h = screen_area(c->desktop)->height;
1131 w = screen_area(c->desktop)->width;
1132 switch(data->diraction.direction) {
1133 case Direction_North:
1136 case Direction_West:
1139 case Direction_South:
1140 y = h - c->frame->area.height;
1142 case Direction_East:
1143 x = w - c->frame->area.width;
1146 frame_frame_gravity(c->frame, &x, &y);
1147 client_configure(c, Corner_TopLeft,
1148 x, y, c->area.width, c->area.height, TRUE, TRUE);
1152 void action_send_to_layer(union ActionData *data)
1155 client_set_layer(data->layer.c, data->layer.layer);
1158 void action_toggle_layer(union ActionData *data)
1160 Client *c = data->layer.c;
1163 if (data->layer.layer < 0)
1164 client_set_layer(c, c->below ? 0 : -1);
1165 else if (data->layer.layer > 0)
1166 client_set_layer(c, c->above ? 0 : 1);
1170 void action_toggle_show_desktop(union ActionData *data)
1172 screen_show_desktop(!screen_showing_desktop);
1175 void action_show_desktop(union ActionData *data)
1177 screen_show_desktop(TRUE);
1180 void action_unshow_desktop(union ActionData *data)
1182 screen_show_desktop(FALSE);