aboutsummaryrefslogtreecommitdiff
path: root/sway/tree/layout.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree/layout.c')
-rw-r--r--sway/tree/layout.c122
1 files changed, 80 insertions, 42 deletions
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index 1f898f8a..1f82e534 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -6,6 +6,7 @@
#include <string.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_output_layout.h>
+#include "config.h"
#include "sway/debug.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
@@ -39,9 +40,12 @@ void layout_init(void) {
root_container.sway_root = calloc(1, sizeof(*root_container.sway_root));
root_container.sway_root->output_layout = wlr_output_layout_create();
wl_list_init(&root_container.sway_root->outputs);
+#ifdef HAVE_XWAYLAND
wl_list_init(&root_container.sway_root->xwayland_unmanaged);
+#endif
wl_list_init(&root_container.sway_root->drag_icons);
wl_signal_init(&root_container.sway_root->events.new_container);
+ root_container.sway_root->scratchpad = create_list();
root_container.sway_root->output_layout_change.notify =
output_layout_handle_change;
@@ -62,10 +66,9 @@ static int index_child(const struct sway_container *child) {
static void container_handle_fullscreen_reparent(struct sway_container *con,
struct sway_container *old_parent) {
- if (con->type != C_VIEW || !con->sway_view->is_fullscreen) {
+ if (!con->is_fullscreen) {
return;
}
- struct sway_view *view = con->sway_view;
struct sway_container *old_workspace = old_parent;
if (old_workspace && old_workspace->type != C_WORKSPACE) {
old_workspace = container_parent(old_workspace, C_WORKSPACE);
@@ -81,19 +84,27 @@ static void container_handle_fullscreen_reparent(struct sway_container *con,
// Mark the new workspace as fullscreen
if (new_workspace->sway_workspace->fullscreen) {
- view_set_fullscreen(new_workspace->sway_workspace->fullscreen, false);
+ container_set_fullscreen(
+ new_workspace->sway_workspace->fullscreen, false);
}
- new_workspace->sway_workspace->fullscreen = view;
- // Resize view to new output dimensions
+ new_workspace->sway_workspace->fullscreen = con;
+
+ // Resize container to new output dimensions
struct sway_container *output = new_workspace->parent;
- view->x = output->x;
- view->y = output->y;
- view->width = output->width;
- view->height = output->height;
con->x = output->x;
con->y = output->y;
con->width = output->width;
con->height = output->height;
+
+ if (con->type == C_VIEW) {
+ struct sway_view *view = con->sway_view;
+ view->x = output->x;
+ view->y = output->y;
+ view->width = output->width;
+ view->height = output->height;
+ } else {
+ arrange_windows(new_workspace);
+ }
}
void container_insert_child(struct sway_container *parent,
@@ -135,10 +146,14 @@ void container_add_child(struct sway_container *parent,
list_add(parent->children, child);
child->parent = parent;
container_handle_fullscreen_reparent(child, old_parent);
+ if (old_parent) {
+ container_set_dirty(old_parent);
+ }
+ container_set_dirty(child);
}
struct sway_container *container_remove_child(struct sway_container *child) {
- if (child->type == C_VIEW && child->sway_view->is_fullscreen) {
+ if (child->is_fullscreen) {
struct sway_container *workspace = container_parent(child, C_WORKSPACE);
workspace->sway_workspace->fullscreen = NULL;
}
@@ -153,6 +168,9 @@ struct sway_container *container_remove_child(struct sway_container *child) {
child->parent = NULL;
container_notify_subtree_changed(parent);
+ container_set_dirty(parent);
+ container_set_dirty(child);
+
return parent;
}
@@ -199,7 +217,9 @@ void container_move_to(struct sway_container *container,
container_sort_workspaces(new_parent);
seat_set_focus(seat, new_parent);
workspace_output_raise_priority(container, old_parent, new_parent);
- ipc_event_workspace(container, NULL, "move");
+ ipc_event_workspace(NULL, container, "move");
+ } else if (container->type == C_VIEW) {
+ ipc_event_window(container, "move");
}
container_notify_subtree_changed(old_parent);
container_notify_subtree_changed(new_parent);
@@ -218,10 +238,10 @@ void container_move_to(struct sway_container *container,
if (focus_ws->type != C_WORKSPACE) {
focus_ws = container_parent(focus_ws, C_WORKSPACE);
}
- seat_set_focus(seat,
- new_workspace->sway_workspace->fullscreen->swayc);
- if (focus_ws != new_workspace) {
- seat_set_focus(seat, focus);
+ if (focus_ws == new_workspace) {
+ struct sway_container *new_focus = seat_get_focus_inactive(seat,
+ new_workspace->sway_workspace->fullscreen);
+ seat_set_focus(seat, new_focus);
}
}
}
@@ -364,10 +384,18 @@ void container_move(struct sway_container *container,
struct sway_container *sibling = NULL;
struct sway_container *current = container;
struct sway_container *parent = current->parent;
+ struct sway_container *top = &root_container;
// If moving a fullscreen view, only consider outputs
- if (container->type == C_VIEW && container->sway_view->is_fullscreen) {
+ if (container->is_fullscreen) {
current = container_parent(container, C_OUTPUT);
+ } else if (container_is_fullscreen_or_child(container) ||
+ container_is_floating_or_child(container)) {
+ // If we've fullscreened a split container, only allow the child to move
+ // around within the fullscreen parent.
+ // Same with floating a split container.
+ struct sway_container *ws = container_parent(container, C_WORKSPACE);
+ top = ws->sway_workspace->fullscreen;
}
struct sway_container *new_parent = container_flatten(parent);
@@ -377,7 +405,7 @@ void container_move(struct sway_container *container,
}
while (!sibling) {
- if (current->type == C_ROOT) {
+ if (current == top) {
return;
}
@@ -441,8 +469,12 @@ void container_move(struct sway_container *container,
if ((index == parent->children->length - 1 && offs > 0)
|| (index == 0 && offs < 0)) {
if (current->parent == container->parent) {
- if (parent->layout == L_TABBED
- || parent->layout == L_STACKED) {
+ if (parent->parent->layout == L_FLOATING) {
+ return;
+ }
+ if (!parent->is_fullscreen &&
+ (parent->layout == L_TABBED ||
+ parent->layout == L_STACKED)) {
move_out_of_tabs_stacks(container, current,
move_dir, offs);
return;
@@ -463,10 +495,14 @@ void container_move(struct sway_container *container,
sibling = parent->children->items[index + offs];
wlr_log(WLR_DEBUG, "Selecting sibling id:%zd", sibling->id);
}
- } else if (parent->layout == L_TABBED
- || parent->layout == L_STACKED) {
+ } else if (!parent->is_fullscreen &&
+ parent->parent->layout != L_FLOATING &&
+ (parent->layout == L_TABBED ||
+ parent->layout == L_STACKED)) {
move_out_of_tabs_stacks(container, current, move_dir, offs);
return;
+ } else if (parent->parent->layout == L_FLOATING) {
+ return;
} else {
wlr_log(WLR_DEBUG, "Moving up to find a parallel container");
current = current->parent;
@@ -544,6 +580,10 @@ void container_move(struct sway_container *container,
container_notify_subtree_changed(old_parent);
container_notify_subtree_changed(container->parent);
+ if (container->type == C_VIEW) {
+ ipc_event_window(container, "move");
+ }
+
if (old_parent) {
seat_set_focus(config->handler_context.seat, old_parent);
seat_set_focus(config->handler_context.seat, container);
@@ -558,10 +598,11 @@ void container_move(struct sway_container *container,
next_ws = container_parent(next_ws, C_WORKSPACE);
}
if (last_ws && next_ws && last_ws != next_ws) {
- ipc_event_workspace(last_ws, container, "focus");
+ ipc_event_workspace(last_ws, next_ws, "focus");
workspace_detect_urgent(last_ws);
workspace_detect_urgent(next_ws);
}
+ container_end_mouse_operation(container);
}
enum sway_container_layout container_get_default_layout(
@@ -691,22 +732,18 @@ struct sway_container *container_get_in_direction(
enum movement_direction dir) {
struct sway_container *parent = container->parent;
- if (container_is_floating(container)) {
- return NULL;
+ if (dir == MOVE_CHILD) {
+ return seat_get_focus_inactive(seat, container);
}
-
- if (container->type == C_VIEW && container->sway_view->is_fullscreen) {
- if (dir == MOVE_PARENT || dir == MOVE_CHILD) {
+ if (container->is_fullscreen) {
+ if (dir == MOVE_PARENT) {
return NULL;
}
container = container_parent(container, C_OUTPUT);
parent = container->parent;
} else {
- if (dir == MOVE_CHILD) {
- return seat_get_focus_inactive(seat, container);
- }
if (dir == MOVE_PARENT) {
- if (parent->type == C_OUTPUT) {
+ if (parent->type == C_OUTPUT || container_is_floating(container)) {
return NULL;
} else {
return parent;
@@ -755,7 +792,8 @@ struct sway_container *container_get_in_direction(
}
sway_assert(next_workspace, "Next container has no workspace");
if (next_workspace->sway_workspace->fullscreen) {
- return next_workspace->sway_workspace->fullscreen->swayc;
+ return seat_get_focus_inactive(seat,
+ next_workspace->sway_workspace->fullscreen);
}
if (next->children && next->children->length) {
// TODO consider floating children as well
@@ -963,13 +1001,13 @@ static void swap_focus(struct sway_container *con1,
if (focus == con1 && (con2->parent->layout == L_TABBED
|| con2->parent->layout == L_STACKED)) {
if (workspace_is_visible(ws2)) {
- seat_set_focus_warp(seat, con2, false);
+ seat_set_focus_warp(seat, con2, false, true);
}
seat_set_focus(seat, ws1 != ws2 ? con2 : con1);
} else if (focus == con2 && (con1->parent->layout == L_TABBED
|| con1->parent->layout == L_STACKED)) {
if (workspace_is_visible(ws1)) {
- seat_set_focus_warp(seat, con1, false);
+ seat_set_focus_warp(seat, con1, false, true);
}
seat_set_focus(seat, ws1 != ws2 ? con1 : con2);
} else if (ws1 != ws2) {
@@ -1002,13 +1040,13 @@ void container_swap(struct sway_container *con1, struct sway_container *con2) {
wlr_log(WLR_DEBUG, "Swapping containers %zu and %zu", con1->id, con2->id);
- int fs1 = con1->type == C_VIEW && con1->sway_view->is_fullscreen;
- int fs2 = con2->type == C_VIEW && con2->sway_view->is_fullscreen;
+ int fs1 = con1->is_fullscreen;
+ int fs2 = con2->is_fullscreen;
if (fs1) {
- view_set_fullscreen(con1->sway_view, false);
+ container_set_fullscreen(con1, false);
}
if (fs2) {
- view_set_fullscreen(con2->sway_view, false);
+ container_set_fullscreen(con2, false);
}
struct sway_seat *seat = input_manager_get_default_seat(input_manager);
@@ -1041,10 +1079,10 @@ void container_swap(struct sway_container *con1, struct sway_container *con2) {
prev_workspace_name = stored_prev_name;
}
- if (fs1 && con2->type == C_VIEW) {
- view_set_fullscreen(con2->sway_view, true);
+ if (fs1) {
+ container_set_fullscreen(con2, true);
}
- if (fs2 && con1->type == C_VIEW) {
- view_set_fullscreen(con1->sway_view, true);
+ if (fs2) {
+ container_set_fullscreen(con1, true);
}
}