From 8bb40c24c7b045df0d43e9f22c096d1473f6f9f6 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 11 Sep 2018 21:34:21 +1000 Subject: Implement tiling drag Hold floating_modifier and drag a tiling view to a new location. --- sway/tree/container.c | 12 +++++++++--- sway/tree/view.c | 2 +- sway/tree/workspace.c | 13 +++++++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) (limited to 'sway/tree') diff --git a/sway/tree/container.c b/sway/tree/container.c index 0a69f8d5..ff10c1ab 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -835,8 +835,14 @@ void container_end_mouse_operation(struct sway_container *container) { struct sway_seat *seat; wl_list_for_each(seat, &input_manager->seats, link) { if (seat->op_container == container) { + seat->op_target_node = NULL; // ensure tiling move doesn't apply seat_end_mouse_operation(seat); } + // If the user is doing a tiling drag over this container, + // keep the operation active but unset the target container. + if (seat->op_target_node == &container->node) { + seat->op_target_node = NULL; + } } } @@ -1086,13 +1092,13 @@ void container_insert_child(struct sway_container *parent, } void container_add_sibling(struct sway_container *fixed, - struct sway_container *active) { + struct sway_container *active, int side) { if (active->workspace) { container_detach(active); } list_t *siblings = container_get_siblings(fixed); int index = list_find(siblings, fixed); - list_insert(siblings, index + 1, active); + list_insert(siblings, index + side, active); active->parent = fixed->parent; active->workspace = fixed->workspace; container_for_each_child(active, set_workspace, NULL); @@ -1145,7 +1151,7 @@ void container_detach(struct sway_container *child) { void container_replace(struct sway_container *container, struct sway_container *replacement) { - container_add_sibling(container, replacement); + container_add_sibling(container, replacement, 1); container_detach(container); } diff --git a/sway/tree/view.c b/sway/tree/view.c index 65ac8b32..d4ffa06b 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -529,7 +529,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { view->container = container_create(view); if (target_sibling) { - container_add_sibling(target_sibling, view->container); + container_add_sibling(target_sibling, view->container, 1); } else { workspace_add_tiling(ws, view->container); } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index b8e90892..d4b57a0f 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -694,3 +694,16 @@ void workspace_get_box(struct sway_workspace *workspace, struct wlr_box *box) { box->width = workspace->width; box->height = workspace->height; } + +static void count_tiling_views(struct sway_container *con, void *data) { + if (con->view && !container_is_floating_or_child(con)) { + size_t *count = data; + *count += 1; + } +} + +size_t workspace_num_tiling_views(struct sway_workspace *ws) { + size_t count = 0; + workspace_for_each_container(ws, count_tiling_views, &count); + return count; +} -- cgit v1.2.3 From df95c61044c37b511922db03eb5bd868b374e9d4 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Tue, 11 Sep 2018 23:38:17 +1000 Subject: Fix crash in workspace_wrap_children When workspace_wrap_children is called on a workspace which has a fullscreen child and the fullscreen child is a direct child of the workspace, sway would crash. The workspace's fullscreen pointer is unset when the fullscreen container is detached and applied again when added to a parent, but in this case the parent hadn't yet been added to the workspace which meant con->workspace was NULL. The fix makes container_handle_fullscreen_reparent return if there's no workspace, and the fullscreen pointer is reapplied in workspace_wrap_children. --- sway/tree/container.c | 3 ++- sway/tree/workspace.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'sway/tree') diff --git a/sway/tree/container.c b/sway/tree/container.c index ff10c1ab..21a0cd76 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1063,7 +1063,8 @@ list_t *container_get_current_siblings(struct sway_container *container) { } void container_handle_fullscreen_reparent(struct sway_container *con) { - if (!con->is_fullscreen || con->workspace->fullscreen == con) { + if (!con->is_fullscreen || !con->workspace || + con->workspace->fullscreen == con) { return; } if (con->workspace->fullscreen) { diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index d4b57a0f..18746430 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -557,6 +557,7 @@ struct sway_container *workspace_find_container(struct sway_workspace *ws, } struct sway_container *workspace_wrap_children(struct sway_workspace *ws) { + struct sway_container *fs = ws->fullscreen; struct sway_container *middle = container_create(NULL); middle->layout = ws->layout; while (ws->tiling->length) { @@ -565,6 +566,7 @@ struct sway_container *workspace_wrap_children(struct sway_workspace *ws) { container_add_child(middle, child); } workspace_add_tiling(ws, middle); + ws->fullscreen = fs; return middle; } -- cgit v1.2.3 From 679c7eb08c16daea8e3e1cff7bcf179e116d0e8e Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 12 Sep 2018 08:46:46 +1000 Subject: Minor fixes to tiling drag implementation * Make container_add_sibling's `after` argument a boolean. * Use a constant for drop layout border * Make thickness an int * Add button state check * Move comments in seat_end_move_tiling --- include/sway/tree/container.h | 2 +- sway/input/cursor.c | 22 ++++++++++++++-------- sway/input/seat.c | 6 ++---- sway/tree/container.c | 4 ++-- 4 files changed, 19 insertions(+), 15 deletions(-) (limited to 'sway/tree') diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 94d30ced..5e281a2f 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -283,7 +283,7 @@ void container_insert_child(struct sway_container *parent, * Side should be 0 to add before, or 1 to add after. */ void container_add_sibling(struct sway_container *parent, - struct sway_container *child, int side); + struct sway_container *child, bool after); void container_detach(struct sway_container *child); diff --git a/sway/input/cursor.c b/sway/input/cursor.c index b0f8e531..dc66d82d 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -26,6 +26,10 @@ #include "sway/tree/workspace.h" #include "wlr-layer-shell-unstable-v1-protocol.h" +// When doing a tiling drag, this is the thickness of the dropzone +// when dragging to the edge of a layout container. +#define DROP_LAYOUT_BORDER 30 + static uint32_t get_current_time_msec() { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -229,7 +233,7 @@ static void handle_move_floating_motion(struct sway_seat *seat, } static void resize_box(struct wlr_box *box, enum wlr_edges edge, - size_t thickness) { + int thickness) { switch (edge) { case WLR_EDGE_TOP: box->height = thickness; @@ -297,15 +301,17 @@ static void handle_move_tiling_motion(struct sway_seat *seat, con->parent ? container_get_box(con->parent, &parent) : workspace_get_box(con->workspace, &parent); if (layout == L_HORIZ || layout == L_TABBED) { - if (cursor->cursor->y < parent.y + 30) { + if (cursor->cursor->y < parent.y + DROP_LAYOUT_BORDER) { edge = WLR_EDGE_TOP; - } else if (cursor->cursor->y > parent.y + parent.height - 30) { + } else if (cursor->cursor->y > parent.y + parent.height + - DROP_LAYOUT_BORDER) { edge = WLR_EDGE_BOTTOM; } } else if (layout == L_VERT || layout == L_STACKED) { - if (cursor->cursor->x < parent.x + 30) { + if (cursor->cursor->x < parent.x + DROP_LAYOUT_BORDER) { edge = WLR_EDGE_LEFT; - } else if (cursor->cursor->x > parent.x + parent.width - 30) { + } else if (cursor->cursor->x > parent.x + parent.width + - DROP_LAYOUT_BORDER) { edge = WLR_EDGE_RIGHT; } } @@ -313,7 +319,7 @@ static void handle_move_tiling_motion(struct sway_seat *seat, seat->op_target_node = node_get_parent(&con->node); seat->op_target_edge = edge; node_get_box(seat->op_target_node, &seat->op_drop_box); - resize_box(&seat->op_drop_box, edge, 30); + resize_box(&seat->op_drop_box, edge, DROP_LAYOUT_BORDER); desktop_damage_box(&seat->op_drop_box); return; } @@ -890,8 +896,8 @@ void dispatch_cursor_button(struct sway_cursor *cursor, } // Handle moving a tiling container - if (config->tiling_drag && mod_pressed && !is_floating_or_child && - !cont->is_fullscreen) { + if (config->tiling_drag && mod_pressed && state == WLR_BUTTON_PRESSED && + !is_floating_or_child && !cont->is_fullscreen) { seat_pointer_notify_button(seat, time_msec, button, state); seat_begin_move_tiling(seat, cont, button); return; diff --git a/sway/input/seat.c b/sway/input/seat.c index 231b545b..8704f90f 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1050,9 +1050,8 @@ static void seat_end_move_tiling(struct sway_seat *seat) { // Moving container into empty workspace if (target_node->type == N_WORKSPACE && edge == WLR_EDGE_NONE) { workspace_add_tiling(new_ws, con); - - // Moving container before/after another } else if (target_node->type == N_CONTAINER) { + // Moving container before/after another struct sway_container *target = target_node->sway_container; enum sway_container_layout layout = container_parent_layout(target); if (edge && !is_parallel(layout, edge)) { @@ -1061,9 +1060,8 @@ static void seat_end_move_tiling(struct sway_seat *seat) { container_split(target, new_layout); } container_add_sibling(target, con, after); - - // Target is a workspace which requires splitting } else { + // Target is a workspace which requires splitting enum sway_container_layout new_layout = edge == WLR_EDGE_TOP || edge == WLR_EDGE_BOTTOM ? L_VERT : L_HORIZ; workspace_split(new_ws, new_layout); diff --git a/sway/tree/container.c b/sway/tree/container.c index 21a0cd76..df064573 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1093,13 +1093,13 @@ void container_insert_child(struct sway_container *parent, } void container_add_sibling(struct sway_container *fixed, - struct sway_container *active, int side) { + struct sway_container *active, bool after) { if (active->workspace) { container_detach(active); } list_t *siblings = container_get_siblings(fixed); int index = list_find(siblings, fixed); - list_insert(siblings, index + side, active); + list_insert(siblings, index + after, active); active->parent = fixed->parent; active->workspace = fixed->workspace; container_for_each_child(active, set_workspace, NULL); -- cgit v1.2.3