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