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