diff options
author | Brian Ashworth <bosrsf04@gmail.com> | 2018-05-26 11:02:21 -0400 |
---|---|---|
committer | Brian Ashworth <bosrsf04@gmail.com> | 2018-05-26 11:05:02 -0400 |
commit | 569f4e0e4c75562c38848ea0bbaeb3b2f230b1a9 (patch) | |
tree | 02716bf706478cc5ca73d892dfc34c8a327897b3 /sway/tree | |
parent | Replace oft-failing abort with if statement (diff) | |
download | sway-569f4e0e4c75562c38848ea0bbaeb3b2f230b1a9.tar.gz sway-569f4e0e4c75562c38848ea0bbaeb3b2f230b1a9.tar.zst sway-569f4e0e4c75562c38848ea0bbaeb3b2f230b1a9.zip |
Implement swap command
Diffstat (limited to 'sway/tree')
-rw-r--r-- | sway/tree/layout.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 21cec529..624d5516 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -882,3 +882,127 @@ void container_recursive_resize(struct sway_container *container, | |||
882 | } | 882 | } |
883 | } | 883 | } |
884 | } | 884 | } |
885 | |||
886 | static void swap_places(struct sway_container *con1, | ||
887 | struct sway_container *con2) { | ||
888 | struct sway_container *temp = malloc(sizeof(struct sway_container)); | ||
889 | temp->x = con1->x; | ||
890 | temp->y = con1->y; | ||
891 | temp->width = con1->width; | ||
892 | temp->height = con1->height; | ||
893 | temp->parent = con1->parent; | ||
894 | |||
895 | con1->x = con2->x; | ||
896 | con1->y = con2->y; | ||
897 | con1->width = con2->width; | ||
898 | con1->height = con2->height; | ||
899 | |||
900 | con2->x = temp->x; | ||
901 | con2->y = temp->y; | ||
902 | con2->width = temp->width; | ||
903 | con2->height = temp->height; | ||
904 | |||
905 | int temp_index = index_child(con1); | ||
906 | container_insert_child(con2->parent, con1, index_child(con2)); | ||
907 | container_insert_child(temp->parent, con2, temp_index); | ||
908 | |||
909 | free(temp); | ||
910 | } | ||
911 | |||
912 | static void swap_focus(struct sway_container *con1, | ||
913 | struct sway_container *con2, struct sway_seat *seat, | ||
914 | struct sway_container *focus) { | ||
915 | if (focus == con1 || focus == con2) { | ||
916 | struct sway_container *ws1 = container_parent(con1, C_WORKSPACE); | ||
917 | struct sway_container *ws2 = container_parent(con2, C_WORKSPACE); | ||
918 | if (focus == con1 && (con2->parent->layout == L_TABBED | ||
919 | || con2->parent->layout == L_STACKED)) { | ||
920 | if (workspace_is_visible(ws2)) { | ||
921 | seat_set_focus_warp(seat, con2, false); | ||
922 | } | ||
923 | seat_set_focus(seat, ws1 != ws2 ? con2 : con1); | ||
924 | } else if (focus == con2 && (con1->parent->layout == L_TABBED | ||
925 | || con1->parent->layout == L_STACKED)) { | ||
926 | if (workspace_is_visible(ws1)) { | ||
927 | seat_set_focus_warp(seat, con1, false); | ||
928 | } | ||
929 | seat_set_focus(seat, ws1 != ws2 ? con1 : con2); | ||
930 | } else if (ws1 != ws2) { | ||
931 | seat_set_focus(seat, focus == con1 ? con2 : con1); | ||
932 | } else { | ||
933 | seat_set_focus(seat, focus); | ||
934 | } | ||
935 | } else { | ||
936 | seat_set_focus(seat, focus); | ||
937 | } | ||
938 | } | ||
939 | |||
940 | void container_swap(struct sway_container *con1, struct sway_container *con2) { | ||
941 | if (!sway_assert(con1 && con2, "Cannot swap with nothing")) { | ||
942 | return; | ||
943 | } | ||
944 | if (!sway_assert(con1->type >= C_CONTAINER && con2->type >= C_CONTAINER, | ||
945 | "Can only swap containers and views")) { | ||
946 | return; | ||
947 | } | ||
948 | if (!sway_assert(!container_has_anscestor(con1, con2) | ||
949 | && !container_has_anscestor(con2, con1), | ||
950 | "Cannot swap anscestor and descendant")) { | ||
951 | return; | ||
952 | } | ||
953 | if (!sway_assert(con1->layout != L_FLOATING && con2->layout != L_FLOATING, | ||
954 | "Swapping with floating containers is not supported")) { | ||
955 | return; | ||
956 | } | ||
957 | |||
958 | wlr_log(L_DEBUG, "Swapping containers %zu and %zu", con1->id, con2->id); | ||
959 | |||
960 | int fs1 = con1->type == C_VIEW && con1->sway_view->is_fullscreen; | ||
961 | int fs2 = con2->type == C_VIEW && con2->sway_view->is_fullscreen; | ||
962 | if (fs1) { | ||
963 | view_set_fullscreen(con1->sway_view, false); | ||
964 | } | ||
965 | if (fs2) { | ||
966 | view_set_fullscreen(con2->sway_view, false); | ||
967 | } | ||
968 | |||
969 | struct sway_seat *seat = input_manager_get_default_seat(input_manager); | ||
970 | struct sway_container *focus = seat_get_focus(seat); | ||
971 | struct sway_container *vis1 = container_parent( | ||
972 | seat_get_focus_inactive(seat, container_parent(con1, C_OUTPUT)), | ||
973 | C_WORKSPACE); | ||
974 | struct sway_container *vis2 = container_parent( | ||
975 | seat_get_focus_inactive(seat, container_parent(con2, C_OUTPUT)), | ||
976 | C_WORKSPACE); | ||
977 | |||
978 | char *stored_prev_name = NULL; | ||
979 | if (prev_workspace_name) { | ||
980 | stored_prev_name = strdup(prev_workspace_name); | ||
981 | } | ||
982 | |||
983 | swap_places(con1, con2); | ||
984 | |||
985 | if (!workspace_is_visible(vis1)) { | ||
986 | seat_set_focus(seat, seat_get_focus_inactive(seat, vis1)); | ||
987 | } | ||
988 | if (!workspace_is_visible(vis2)) { | ||
989 | seat_set_focus(seat, seat_get_focus_inactive(seat, vis2)); | ||
990 | } | ||
991 | |||
992 | swap_focus(con1, con2, seat, focus); | ||
993 | |||
994 | if (stored_prev_name) { | ||
995 | free(prev_workspace_name); | ||
996 | prev_workspace_name = stored_prev_name; | ||
997 | } | ||
998 | |||
999 | arrange_children_of(con1->parent); | ||
1000 | arrange_children_of(con2->parent); | ||
1001 | |||
1002 | if (fs1 && con2->type == C_VIEW) { | ||
1003 | view_set_fullscreen(con2->sway_view, true); | ||
1004 | } | ||
1005 | if (fs2 && con1->type == C_VIEW) { | ||
1006 | view_set_fullscreen(con1->sway_view, true); | ||
1007 | } | ||
1008 | } | ||