diff options
author | Ryan Dwyer <[email protected]> | 2018-09-11 21:34:21 +1000 |
---|---|---|
committer | Ryan Dwyer <[email protected]> | 2018-09-11 21:34:21 +1000 |
commit | 8bb40c24c7b045df0d43e9f22c096d1473f6f9f6 (patch) | |
tree | 0c4dbac1173f92337e2cff63d45c7d8fe7a3557f /sway/input/seat.c | |
parent | ec9c4de564286d3795dd204e2c0a69b10f7572be (diff) |
Implement tiling drag
Hold floating_modifier and drag a tiling view to a new location.
Diffstat (limited to 'sway/input/seat.c')
-rw-r--r-- | sway/input/seat.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/sway/input/seat.c b/sway/input/seat.c index a908560a..86e5f809 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -975,6 +975,16 @@ void seat_begin_move_floating(struct sway_seat *seat, cursor_set_image(seat->cursor, "grab", NULL); } +void seat_begin_move_tiling(struct sway_seat *seat, + struct sway_container *con, uint32_t button) { + seat->operation = OP_MOVE_TILING; + seat->op_container = con; + seat->op_button = button; + seat->op_target_node = NULL; + seat->op_target_edge = 0; + cursor_set_image(seat->cursor, "grab", NULL); +} + void seat_begin_resize_floating(struct sway_seat *seat, struct sway_container *con, uint32_t button, enum wlr_edges edge) { if (!seat->cursor) { @@ -1015,6 +1025,68 @@ void seat_begin_resize_tiling(struct sway_seat *seat, seat->op_ref_height = con->height; } +static bool is_parallel(enum sway_container_layout layout, + enum wlr_edges edge) { + bool layout_is_horiz = layout == L_HORIZ || layout == L_TABBED; + bool edge_is_horiz = edge == WLR_EDGE_LEFT || edge == WLR_EDGE_RIGHT; + return layout_is_horiz == edge_is_horiz; +} + +static void seat_end_move_tiling(struct sway_seat *seat) { + struct sway_container *con = seat->op_container; + struct sway_container *old_parent = con->parent; + struct sway_workspace *old_ws = con->workspace; + struct sway_node *target_node = seat->op_target_node; + struct sway_workspace *new_ws = target_node->type == N_WORKSPACE ? + target_node->sway_workspace : target_node->sway_container->workspace; + enum wlr_edges edge = seat->op_target_edge; + int after = edge != WLR_EDGE_TOP && edge != WLR_EDGE_LEFT; + + container_detach(con); + if (old_parent) { + container_reap_empty(old_parent); + } + + // 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) { + struct sway_container *target = target_node->sway_container; + enum sway_container_layout layout = container_parent_layout(target); + if (edge && !is_parallel(layout, edge)) { + enum sway_container_layout new_layout = edge == WLR_EDGE_TOP || + edge == WLR_EDGE_BOTTOM ? L_VERT : L_HORIZ; + container_split(target, new_layout); + } + container_add_sibling(target, con, after); + + // Target is a workspace which requires splitting + } else { + enum sway_container_layout new_layout = edge == WLR_EDGE_TOP || + edge == WLR_EDGE_BOTTOM ? L_VERT : L_HORIZ; + workspace_split(new_ws, new_layout); + workspace_insert_tiling(new_ws, con, after); + } + + // This is a bit dirty, but we'll set the dimensions to that of a sibling. + // I don't think there's any other way to make it consistent without + // changing how we auto-size containers. + list_t *siblings = container_get_siblings(con); + if (siblings->length > 1) { + int index = list_find(siblings, con); + struct sway_container *sibling = index == 0 ? siblings->items[1] : siblings->items[index - 1]; + con->width = sibling->width; + con->height = sibling->height; + } + + arrange_workspace(old_ws); + if (new_ws != old_ws) { + arrange_workspace(new_ws); + } +} + void seat_end_mouse_operation(struct sway_seat *seat) { enum sway_seat_operation operation = seat->operation; if (seat->operation == OP_MOVE_FLOATING) { @@ -1022,6 +1094,8 @@ void seat_end_mouse_operation(struct sway_seat *seat) { // output again. struct sway_container *con = seat->op_container; container_floating_move_to(con, con->x, con->y); + } else if (seat->operation == OP_MOVE_TILING && seat->op_target_node) { + seat_end_move_tiling(seat); } seat->operation = OP_NONE; seat->op_container = NULL; |