aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree
diff options
context:
space:
mode:
authorLibravatar Ronan Pigott <ronan@rjp.ie>2023-02-19 17:22:37 -0700
committerLibravatar Tudor Brindus <vulcainus@gmail.com>2023-02-19 20:07:39 -0500
commit633d409b8897aec48ad1e328cb04261faa2b1a0b (patch)
tree3fa8778e8cc77cfccad215e4ad41b631b20a3045 /sway/tree
parentFix map_to_output * turning off device (diff)
downloadsway-633d409b8897aec48ad1e328cb04261faa2b1a0b.tar.gz
sway-633d409b8897aec48ad1e328cb04261faa2b1a0b.tar.zst
sway-633d409b8897aec48ad1e328cb04261faa2b1a0b.zip
container: rehome the container_swap function into container.c
This function was already declared in container.h but defined in commands/swap.c for some unknown reason. Everything in commands/ assumes the handler context has been set appropriately by the command preludes but this function snuck its way into seatop_* which doesn't set anything in the handler context. The fact that the seatop drag actions manipulate the focus without custody of the seat means they are definitely very broken in multiseat.
Diffstat (limited to 'sway/tree')
-rw-r--r--sway/tree/container.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 20701081..335dae87 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -1764,3 +1764,177 @@ int container_squash(struct sway_container *con) {
1764 } 1764 }
1765 return change; 1765 return change;
1766} 1766}
1767
1768static void swap_places(struct sway_container *con1,
1769 struct sway_container *con2) {
1770 struct sway_container *temp = malloc(sizeof(struct sway_container));
1771 temp->pending.x = con1->pending.x;
1772 temp->pending.y = con1->pending.y;
1773 temp->pending.width = con1->pending.width;
1774 temp->pending.height = con1->pending.height;
1775 temp->width_fraction = con1->width_fraction;
1776 temp->height_fraction = con1->height_fraction;
1777 temp->pending.parent = con1->pending.parent;
1778 temp->pending.workspace = con1->pending.workspace;
1779 bool temp_floating = container_is_floating(con1);
1780
1781 con1->pending.x = con2->pending.x;
1782 con1->pending.y = con2->pending.y;
1783 con1->pending.width = con2->pending.width;
1784 con1->pending.height = con2->pending.height;
1785 con1->width_fraction = con2->width_fraction;
1786 con1->height_fraction = con2->height_fraction;
1787
1788 con2->pending.x = temp->pending.x;
1789 con2->pending.y = temp->pending.y;
1790 con2->pending.width = temp->pending.width;
1791 con2->pending.height = temp->pending.height;
1792 con2->width_fraction = temp->width_fraction;
1793 con2->height_fraction = temp->height_fraction;
1794
1795 int temp_index = container_sibling_index(con1);
1796 if (con2->pending.parent) {
1797 container_insert_child(con2->pending.parent, con1,
1798 container_sibling_index(con2));
1799 } else if (container_is_floating(con2)) {
1800 workspace_add_floating(con2->pending.workspace, con1);
1801 } else {
1802 workspace_insert_tiling(con2->pending.workspace, con1,
1803 container_sibling_index(con2));
1804 }
1805 if (temp->pending.parent) {
1806 container_insert_child(temp->pending.parent, con2, temp_index);
1807 } else if (temp_floating) {
1808 workspace_add_floating(temp->pending.workspace, con2);
1809 } else {
1810 workspace_insert_tiling(temp->pending.workspace, con2, temp_index);
1811 }
1812
1813 free(temp);
1814}
1815
1816static void swap_focus(struct sway_container *con1,
1817 struct sway_container *con2, struct sway_seat *seat,
1818 struct sway_container *focus) {
1819 if (focus == con1 || focus == con2) {
1820 struct sway_workspace *ws1 = con1->pending.workspace;
1821 struct sway_workspace *ws2 = con2->pending.workspace;
1822 enum sway_container_layout layout1 = container_parent_layout(con1);
1823 enum sway_container_layout layout2 = container_parent_layout(con2);
1824 if (focus == con1 && (layout2 == L_TABBED || layout2 == L_STACKED)) {
1825 if (workspace_is_visible(ws2)) {
1826 seat_set_focus(seat, &con2->node);
1827 }
1828 seat_set_focus_container(seat, ws1 != ws2 ? con2 : con1);
1829 } else if (focus == con2 && (layout1 == L_TABBED
1830 || layout1 == L_STACKED)) {
1831 if (workspace_is_visible(ws1)) {
1832 seat_set_focus(seat, &con1->node);
1833 }
1834 seat_set_focus_container(seat, ws1 != ws2 ? con1 : con2);
1835 } else if (ws1 != ws2) {
1836 seat_set_focus_container(seat, focus == con1 ? con2 : con1);
1837 } else {
1838 seat_set_focus_container(seat, focus);
1839 }
1840 } else {
1841 seat_set_focus_container(seat, focus);
1842 }
1843
1844 if (root->fullscreen_global) {
1845 seat_set_focus(seat,
1846 seat_get_focus_inactive(seat, &root->fullscreen_global->node));
1847 }
1848}
1849
1850void container_swap(struct sway_container *con1, struct sway_container *con2) {
1851 if (!sway_assert(con1 && con2, "Cannot swap with nothing")) {
1852 return;
1853 }
1854 if (!sway_assert(!container_has_ancestor(con1, con2)
1855 && !container_has_ancestor(con2, con1),
1856 "Cannot swap ancestor and descendant")) {
1857 return;
1858 }
1859
1860 sway_log(SWAY_DEBUG, "Swapping containers %zu and %zu",
1861 con1->node.id, con2->node.id);
1862
1863 bool scratch1 = con1->scratchpad;
1864 bool hidden1 = container_is_scratchpad_hidden(con1);
1865 bool scratch2 = con2->scratchpad;
1866 bool hidden2 = container_is_scratchpad_hidden(con2);
1867 if (scratch1) {
1868 if (hidden1) {
1869 root_scratchpad_show(con1);
1870 }
1871 root_scratchpad_remove_container(con1);
1872 }
1873 if (scratch2) {
1874 if (hidden2) {
1875 root_scratchpad_show(con2);
1876 }
1877 root_scratchpad_remove_container(con2);
1878 }
1879
1880 enum sway_fullscreen_mode fs1 = con1->pending.fullscreen_mode;
1881 if (fs1) {
1882 container_fullscreen_disable(con1);
1883 }
1884 enum sway_fullscreen_mode fs2 = con2->pending.fullscreen_mode;
1885 if (fs2) {
1886 container_fullscreen_disable(con2);
1887 }
1888
1889 struct sway_seat *seat = input_manager_current_seat();
1890 struct sway_container *focus = seat_get_focused_container(seat);
1891 struct sway_workspace *vis1 =
1892 output_get_active_workspace(con1->pending.workspace->output);
1893 struct sway_workspace *vis2 =
1894 output_get_active_workspace(con2->pending.workspace->output);
1895 if (!sway_assert(vis1 && vis2, "con1 or con2 are on an output without a"
1896 "workspace. This should not happen")) {
1897 return;
1898 }
1899
1900 char *stored_prev_name = NULL;
1901 if (seat->prev_workspace_name) {
1902 stored_prev_name = strdup(seat->prev_workspace_name);
1903 }
1904
1905 swap_places(con1, con2);
1906
1907 if (!workspace_is_visible(vis1)) {
1908 seat_set_focus(seat, seat_get_focus_inactive(seat, &vis1->node));
1909 }
1910 if (!workspace_is_visible(vis2)) {
1911 seat_set_focus(seat, seat_get_focus_inactive(seat, &vis2->node));
1912 }
1913
1914 swap_focus(con1, con2, seat, focus);
1915
1916 if (stored_prev_name) {
1917 free(seat->prev_workspace_name);
1918 seat->prev_workspace_name = stored_prev_name;
1919 }
1920
1921 if (scratch1) {
1922 root_scratchpad_add_container(con2, NULL);
1923 if (!hidden1) {
1924 root_scratchpad_show(con2);
1925 }
1926 }
1927 if (scratch2) {
1928 root_scratchpad_add_container(con1, NULL);
1929 if (!hidden2) {
1930 root_scratchpad_show(con1);
1931 }
1932 }
1933
1934 if (fs1) {
1935 container_set_fullscreen(con2, fs1);
1936 }
1937 if (fs2) {
1938 container_set_fullscreen(con1, fs2);
1939 }
1940}