mirror of
https://github.com/swaywm/sway.git
synced 2024-12-27 15:36:29 +01:00
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.
This commit is contained in:
parent
788118f194
commit
633d409b88
2 changed files with 175 additions and 174 deletions
|
@ -5,6 +5,7 @@
|
|||
#include "sway/commands.h"
|
||||
#include "sway/output.h"
|
||||
#include "sway/tree/arrange.h"
|
||||
#include "sway/tree/container.h"
|
||||
#include "sway/tree/root.h"
|
||||
#include "sway/tree/view.h"
|
||||
#include "sway/tree/workspace.h"
|
||||
|
@ -13,180 +14,6 @@
|
|||
static const char expected_syntax[] =
|
||||
"Expected 'swap container with id|con_id|mark <arg>'";
|
||||
|
||||
static void swap_places(struct sway_container *con1,
|
||||
struct sway_container *con2) {
|
||||
struct sway_container *temp = malloc(sizeof(struct sway_container));
|
||||
temp->pending.x = con1->pending.x;
|
||||
temp->pending.y = con1->pending.y;
|
||||
temp->pending.width = con1->pending.width;
|
||||
temp->pending.height = con1->pending.height;
|
||||
temp->width_fraction = con1->width_fraction;
|
||||
temp->height_fraction = con1->height_fraction;
|
||||
temp->pending.parent = con1->pending.parent;
|
||||
temp->pending.workspace = con1->pending.workspace;
|
||||
bool temp_floating = container_is_floating(con1);
|
||||
|
||||
con1->pending.x = con2->pending.x;
|
||||
con1->pending.y = con2->pending.y;
|
||||
con1->pending.width = con2->pending.width;
|
||||
con1->pending.height = con2->pending.height;
|
||||
con1->width_fraction = con2->width_fraction;
|
||||
con1->height_fraction = con2->height_fraction;
|
||||
|
||||
con2->pending.x = temp->pending.x;
|
||||
con2->pending.y = temp->pending.y;
|
||||
con2->pending.width = temp->pending.width;
|
||||
con2->pending.height = temp->pending.height;
|
||||
con2->width_fraction = temp->width_fraction;
|
||||
con2->height_fraction = temp->height_fraction;
|
||||
|
||||
int temp_index = container_sibling_index(con1);
|
||||
if (con2->pending.parent) {
|
||||
container_insert_child(con2->pending.parent, con1,
|
||||
container_sibling_index(con2));
|
||||
} else if (container_is_floating(con2)) {
|
||||
workspace_add_floating(con2->pending.workspace, con1);
|
||||
} else {
|
||||
workspace_insert_tiling(con2->pending.workspace, con1,
|
||||
container_sibling_index(con2));
|
||||
}
|
||||
if (temp->pending.parent) {
|
||||
container_insert_child(temp->pending.parent, con2, temp_index);
|
||||
} else if (temp_floating) {
|
||||
workspace_add_floating(temp->pending.workspace, con2);
|
||||
} else {
|
||||
workspace_insert_tiling(temp->pending.workspace, con2, temp_index);
|
||||
}
|
||||
|
||||
free(temp);
|
||||
}
|
||||
|
||||
static void swap_focus(struct sway_container *con1,
|
||||
struct sway_container *con2, struct sway_seat *seat,
|
||||
struct sway_container *focus) {
|
||||
if (focus == con1 || focus == con2) {
|
||||
struct sway_workspace *ws1 = con1->pending.workspace;
|
||||
struct sway_workspace *ws2 = con2->pending.workspace;
|
||||
enum sway_container_layout layout1 = container_parent_layout(con1);
|
||||
enum sway_container_layout layout2 = container_parent_layout(con2);
|
||||
if (focus == con1 && (layout2 == L_TABBED || layout2 == L_STACKED)) {
|
||||
if (workspace_is_visible(ws2)) {
|
||||
seat_set_focus(seat, &con2->node);
|
||||
}
|
||||
seat_set_focus_container(seat, ws1 != ws2 ? con2 : con1);
|
||||
} else if (focus == con2 && (layout1 == L_TABBED
|
||||
|| layout1 == L_STACKED)) {
|
||||
if (workspace_is_visible(ws1)) {
|
||||
seat_set_focus(seat, &con1->node);
|
||||
}
|
||||
seat_set_focus_container(seat, ws1 != ws2 ? con1 : con2);
|
||||
} else if (ws1 != ws2) {
|
||||
seat_set_focus_container(seat, focus == con1 ? con2 : con1);
|
||||
} else {
|
||||
seat_set_focus_container(seat, focus);
|
||||
}
|
||||
} else {
|
||||
seat_set_focus_container(seat, focus);
|
||||
}
|
||||
|
||||
if (root->fullscreen_global) {
|
||||
seat_set_focus(seat,
|
||||
seat_get_focus_inactive(seat, &root->fullscreen_global->node));
|
||||
}
|
||||
}
|
||||
|
||||
void container_swap(struct sway_container *con1, struct sway_container *con2) {
|
||||
if (!sway_assert(con1 && con2, "Cannot swap with nothing")) {
|
||||
return;
|
||||
}
|
||||
if (!sway_assert(!container_has_ancestor(con1, con2)
|
||||
&& !container_has_ancestor(con2, con1),
|
||||
"Cannot swap ancestor and descendant")) {
|
||||
return;
|
||||
}
|
||||
|
||||
sway_log(SWAY_DEBUG, "Swapping containers %zu and %zu",
|
||||
con1->node.id, con2->node.id);
|
||||
|
||||
bool scratch1 = con1->scratchpad;
|
||||
bool hidden1 = container_is_scratchpad_hidden(con1);
|
||||
bool scratch2 = con2->scratchpad;
|
||||
bool hidden2 = container_is_scratchpad_hidden(con2);
|
||||
if (scratch1) {
|
||||
if (hidden1) {
|
||||
root_scratchpad_show(con1);
|
||||
}
|
||||
root_scratchpad_remove_container(con1);
|
||||
}
|
||||
if (scratch2) {
|
||||
if (hidden2) {
|
||||
root_scratchpad_show(con2);
|
||||
}
|
||||
root_scratchpad_remove_container(con2);
|
||||
}
|
||||
|
||||
enum sway_fullscreen_mode fs1 = con1->pending.fullscreen_mode;
|
||||
if (fs1) {
|
||||
container_fullscreen_disable(con1);
|
||||
}
|
||||
enum sway_fullscreen_mode fs2 = con2->pending.fullscreen_mode;
|
||||
if (fs2) {
|
||||
container_fullscreen_disable(con2);
|
||||
}
|
||||
|
||||
struct sway_seat *seat = config->handler_context.seat;
|
||||
struct sway_container *focus = seat_get_focused_container(seat);
|
||||
struct sway_workspace *vis1 =
|
||||
output_get_active_workspace(con1->pending.workspace->output);
|
||||
struct sway_workspace *vis2 =
|
||||
output_get_active_workspace(con2->pending.workspace->output);
|
||||
if (!sway_assert(vis1 && vis2, "con1 or con2 are on an output without a"
|
||||
"workspace. This should not happen")) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *stored_prev_name = NULL;
|
||||
if (seat->prev_workspace_name) {
|
||||
stored_prev_name = strdup(seat->prev_workspace_name);
|
||||
}
|
||||
|
||||
swap_places(con1, con2);
|
||||
|
||||
if (!workspace_is_visible(vis1)) {
|
||||
seat_set_focus(seat, seat_get_focus_inactive(seat, &vis1->node));
|
||||
}
|
||||
if (!workspace_is_visible(vis2)) {
|
||||
seat_set_focus(seat, seat_get_focus_inactive(seat, &vis2->node));
|
||||
}
|
||||
|
||||
swap_focus(con1, con2, seat, focus);
|
||||
|
||||
if (stored_prev_name) {
|
||||
free(seat->prev_workspace_name);
|
||||
seat->prev_workspace_name = stored_prev_name;
|
||||
}
|
||||
|
||||
if (scratch1) {
|
||||
root_scratchpad_add_container(con2, NULL);
|
||||
if (!hidden1) {
|
||||
root_scratchpad_show(con2);
|
||||
}
|
||||
}
|
||||
if (scratch2) {
|
||||
root_scratchpad_add_container(con1, NULL);
|
||||
if (!hidden2) {
|
||||
root_scratchpad_show(con1);
|
||||
}
|
||||
}
|
||||
|
||||
if (fs1) {
|
||||
container_set_fullscreen(con2, fs1);
|
||||
}
|
||||
if (fs2) {
|
||||
container_set_fullscreen(con1, fs2);
|
||||
}
|
||||
}
|
||||
|
||||
static bool test_con_id(struct sway_container *container, void *data) {
|
||||
size_t *con_id = data;
|
||||
return container->node.id == *con_id;
|
||||
|
|
|
@ -1764,3 +1764,177 @@ int container_squash(struct sway_container *con) {
|
|||
}
|
||||
return change;
|
||||
}
|
||||
|
||||
static void swap_places(struct sway_container *con1,
|
||||
struct sway_container *con2) {
|
||||
struct sway_container *temp = malloc(sizeof(struct sway_container));
|
||||
temp->pending.x = con1->pending.x;
|
||||
temp->pending.y = con1->pending.y;
|
||||
temp->pending.width = con1->pending.width;
|
||||
temp->pending.height = con1->pending.height;
|
||||
temp->width_fraction = con1->width_fraction;
|
||||
temp->height_fraction = con1->height_fraction;
|
||||
temp->pending.parent = con1->pending.parent;
|
||||
temp->pending.workspace = con1->pending.workspace;
|
||||
bool temp_floating = container_is_floating(con1);
|
||||
|
||||
con1->pending.x = con2->pending.x;
|
||||
con1->pending.y = con2->pending.y;
|
||||
con1->pending.width = con2->pending.width;
|
||||
con1->pending.height = con2->pending.height;
|
||||
con1->width_fraction = con2->width_fraction;
|
||||
con1->height_fraction = con2->height_fraction;
|
||||
|
||||
con2->pending.x = temp->pending.x;
|
||||
con2->pending.y = temp->pending.y;
|
||||
con2->pending.width = temp->pending.width;
|
||||
con2->pending.height = temp->pending.height;
|
||||
con2->width_fraction = temp->width_fraction;
|
||||
con2->height_fraction = temp->height_fraction;
|
||||
|
||||
int temp_index = container_sibling_index(con1);
|
||||
if (con2->pending.parent) {
|
||||
container_insert_child(con2->pending.parent, con1,
|
||||
container_sibling_index(con2));
|
||||
} else if (container_is_floating(con2)) {
|
||||
workspace_add_floating(con2->pending.workspace, con1);
|
||||
} else {
|
||||
workspace_insert_tiling(con2->pending.workspace, con1,
|
||||
container_sibling_index(con2));
|
||||
}
|
||||
if (temp->pending.parent) {
|
||||
container_insert_child(temp->pending.parent, con2, temp_index);
|
||||
} else if (temp_floating) {
|
||||
workspace_add_floating(temp->pending.workspace, con2);
|
||||
} else {
|
||||
workspace_insert_tiling(temp->pending.workspace, con2, temp_index);
|
||||
}
|
||||
|
||||
free(temp);
|
||||
}
|
||||
|
||||
static void swap_focus(struct sway_container *con1,
|
||||
struct sway_container *con2, struct sway_seat *seat,
|
||||
struct sway_container *focus) {
|
||||
if (focus == con1 || focus == con2) {
|
||||
struct sway_workspace *ws1 = con1->pending.workspace;
|
||||
struct sway_workspace *ws2 = con2->pending.workspace;
|
||||
enum sway_container_layout layout1 = container_parent_layout(con1);
|
||||
enum sway_container_layout layout2 = container_parent_layout(con2);
|
||||
if (focus == con1 && (layout2 == L_TABBED || layout2 == L_STACKED)) {
|
||||
if (workspace_is_visible(ws2)) {
|
||||
seat_set_focus(seat, &con2->node);
|
||||
}
|
||||
seat_set_focus_container(seat, ws1 != ws2 ? con2 : con1);
|
||||
} else if (focus == con2 && (layout1 == L_TABBED
|
||||
|| layout1 == L_STACKED)) {
|
||||
if (workspace_is_visible(ws1)) {
|
||||
seat_set_focus(seat, &con1->node);
|
||||
}
|
||||
seat_set_focus_container(seat, ws1 != ws2 ? con1 : con2);
|
||||
} else if (ws1 != ws2) {
|
||||
seat_set_focus_container(seat, focus == con1 ? con2 : con1);
|
||||
} else {
|
||||
seat_set_focus_container(seat, focus);
|
||||
}
|
||||
} else {
|
||||
seat_set_focus_container(seat, focus);
|
||||
}
|
||||
|
||||
if (root->fullscreen_global) {
|
||||
seat_set_focus(seat,
|
||||
seat_get_focus_inactive(seat, &root->fullscreen_global->node));
|
||||
}
|
||||
}
|
||||
|
||||
void container_swap(struct sway_container *con1, struct sway_container *con2) {
|
||||
if (!sway_assert(con1 && con2, "Cannot swap with nothing")) {
|
||||
return;
|
||||
}
|
||||
if (!sway_assert(!container_has_ancestor(con1, con2)
|
||||
&& !container_has_ancestor(con2, con1),
|
||||
"Cannot swap ancestor and descendant")) {
|
||||
return;
|
||||
}
|
||||
|
||||
sway_log(SWAY_DEBUG, "Swapping containers %zu and %zu",
|
||||
con1->node.id, con2->node.id);
|
||||
|
||||
bool scratch1 = con1->scratchpad;
|
||||
bool hidden1 = container_is_scratchpad_hidden(con1);
|
||||
bool scratch2 = con2->scratchpad;
|
||||
bool hidden2 = container_is_scratchpad_hidden(con2);
|
||||
if (scratch1) {
|
||||
if (hidden1) {
|
||||
root_scratchpad_show(con1);
|
||||
}
|
||||
root_scratchpad_remove_container(con1);
|
||||
}
|
||||
if (scratch2) {
|
||||
if (hidden2) {
|
||||
root_scratchpad_show(con2);
|
||||
}
|
||||
root_scratchpad_remove_container(con2);
|
||||
}
|
||||
|
||||
enum sway_fullscreen_mode fs1 = con1->pending.fullscreen_mode;
|
||||
if (fs1) {
|
||||
container_fullscreen_disable(con1);
|
||||
}
|
||||
enum sway_fullscreen_mode fs2 = con2->pending.fullscreen_mode;
|
||||
if (fs2) {
|
||||
container_fullscreen_disable(con2);
|
||||
}
|
||||
|
||||
struct sway_seat *seat = input_manager_current_seat();
|
||||
struct sway_container *focus = seat_get_focused_container(seat);
|
||||
struct sway_workspace *vis1 =
|
||||
output_get_active_workspace(con1->pending.workspace->output);
|
||||
struct sway_workspace *vis2 =
|
||||
output_get_active_workspace(con2->pending.workspace->output);
|
||||
if (!sway_assert(vis1 && vis2, "con1 or con2 are on an output without a"
|
||||
"workspace. This should not happen")) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *stored_prev_name = NULL;
|
||||
if (seat->prev_workspace_name) {
|
||||
stored_prev_name = strdup(seat->prev_workspace_name);
|
||||
}
|
||||
|
||||
swap_places(con1, con2);
|
||||
|
||||
if (!workspace_is_visible(vis1)) {
|
||||
seat_set_focus(seat, seat_get_focus_inactive(seat, &vis1->node));
|
||||
}
|
||||
if (!workspace_is_visible(vis2)) {
|
||||
seat_set_focus(seat, seat_get_focus_inactive(seat, &vis2->node));
|
||||
}
|
||||
|
||||
swap_focus(con1, con2, seat, focus);
|
||||
|
||||
if (stored_prev_name) {
|
||||
free(seat->prev_workspace_name);
|
||||
seat->prev_workspace_name = stored_prev_name;
|
||||
}
|
||||
|
||||
if (scratch1) {
|
||||
root_scratchpad_add_container(con2, NULL);
|
||||
if (!hidden1) {
|
||||
root_scratchpad_show(con2);
|
||||
}
|
||||
}
|
||||
if (scratch2) {
|
||||
root_scratchpad_add_container(con1, NULL);
|
||||
if (!hidden2) {
|
||||
root_scratchpad_show(con1);
|
||||
}
|
||||
}
|
||||
|
||||
if (fs1) {
|
||||
container_set_fullscreen(con2, fs1);
|
||||
}
|
||||
if (fs2) {
|
||||
container_set_fullscreen(con1, fs2);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue