diff --git a/include/layout.h b/include/layout.h index 2d2a1113..f462bdb3 100644 --- a/include/layout.h +++ b/include/layout.h @@ -37,10 +37,13 @@ swayc_t *replace_child(swayc_t *child, swayc_t *new_child); // a sibling, or to a floating window, or NULL swayc_t *remove_child(swayc_t *child); -// 2 containers are swapped, they inherit eachothers geometry and focus +// 2 containers are swapped, they inherit eachothers focus void swap_container(swayc_t *a, swayc_t *b); -void move_container(swayc_t* container,swayc_t* root,enum movement_direction direction); +// 2 Containers geometry are swapped, used with `swap_container` +void swap_geometry(swayc_t *a, swayc_t *b); + +void move_container(swayc_t* container, enum movement_direction direction); void move_container_to(swayc_t* container, swayc_t* destination); // Layout diff --git a/sway/commands.c b/sway/commands.c index 1d88e724..de98b624 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -209,7 +209,7 @@ static bool cmd_floating(struct sway_config *config, int argc, char **argv) { destroy_container(remove_child(view)); // and move it into workspace floating - add_floating(swayc_active_workspace(),view); + add_floating(swayc_active_workspace(), view); view->x = (swayc_active_workspace()->width - view->width)/2; view->y = (swayc_active_workspace()->height - view->height)/2; if (view->desired_width != -1) { @@ -351,13 +351,13 @@ static bool cmd_move(struct sway_config *config, int argc, char **argv) { swayc_t *view = get_focused_container(&root_container); if (strcasecmp(argv[0], "left") == 0) { - move_container(view,&root_container,MOVE_LEFT); + move_container(view, MOVE_LEFT); } else if (strcasecmp(argv[0], "right") == 0) { - move_container(view,&root_container,MOVE_RIGHT); + move_container(view, MOVE_RIGHT); } else if (strcasecmp(argv[0], "up") == 0) { - move_container(view,&root_container,MOVE_UP); + move_container(view, MOVE_UP); } else if (strcasecmp(argv[0], "down") == 0) { - move_container(view,&root_container,MOVE_DOWN); + move_container(view, MOVE_DOWN); } else if (strcasecmp(argv[0], "container") == 0 || strcasecmp(argv[0], "window") == 0) { // "move container to workspace x" if (!checkarg(argc, "move container/window", EXPECTED_EQUAL_TO, 4) || @@ -389,7 +389,7 @@ static bool cmd_move(struct sway_config *config, int argc, char **argv) { } static bool cmd_orientation(struct sway_config *config, int argc, char **argv) { - if (strcasecmp(argv[0],"horizontal") == 0) { + if (strcasecmp(argv[0], "horizontal") == 0) { config->default_orientation = L_HORIZ; } else if (strcasecmp(argv[0], "vertical") == 0) { config->default_orientation = L_VERT; diff --git a/sway/input_state.c b/sway/input_state.c index a7febc08..2743a9ea 100644 --- a/sway/input_state.c +++ b/sway/input_state.c @@ -297,6 +297,7 @@ void pointer_mode_update(void) { && !pointer_state.view->is_floating) { // Swap them around swap_container(pointer_state.view, initial.ptr); + swap_geometry(pointer_state.view, initial.ptr); update_geometry(pointer_state.view); update_geometry(initial.ptr); // Set focus back to initial view diff --git a/sway/layout.c b/sway/layout.c index f04007ed..103ede52 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -47,6 +47,20 @@ void add_child(swayc_t *parent, swayc_t *child) { } } +void insert_child(swayc_t *parent, swayc_t *child, int index) { + if (index > parent->children->length) { + index = parent->children->length; + } + if (index < 0) { + index = 0; + } + list_insert(parent->children, index, child); + child->parent = parent; + if (!parent->focused) { + parent->focused = child; + } +} + void add_floating(swayc_t *ws, swayc_t *child) { sway_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", child, child->type, child->width, child->height, ws, ws->type, ws->width, ws->height); @@ -161,7 +175,9 @@ void swap_container(swayc_t *a, swayc_t *b) { if (b_parent->focused == b && a_parent != b_parent) { b_parent->focused = a; } - // and their geometry +} + +void swap_geometry(swayc_t *a, swayc_t *b) { double x = a->x; double y = a->y; double w = a->width; @@ -176,48 +192,78 @@ void swap_container(swayc_t *a, swayc_t *b) { b->height = h; } -//TODO: Implement horizontal movement. -//TODO: Implement move to a different workspace. -void move_container(swayc_t *container,swayc_t* root,enum movement_direction direction) { - sway_log(L_DEBUG, "Moved window"); - swayc_t *temp; - int i; - int clength = root->children->length; - //Rearrange - for (i = 0; i < clength; ++i) { - swayc_t *child = root->children->items[i]; - if (child->handle == container->handle){ - if (clength == 1){ - //Only one container, meh. +// TODO fix workspace movement, as in +// [a][b][c] => |move b| => [aa][cc] +// [a][b][c] => |down | => [bbbbbb] +// +void move_container(swayc_t *container, enum movement_direction dir) { + enum swayc_layouts layout; + if (container->is_floating) { + return; + } + if (dir == MOVE_UP || dir == MOVE_DOWN) { + layout = L_VERT; + } else if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { + layout = L_HORIZ; + } else { + return; + } + swayc_t *parent = container->parent; + swayc_t *child = container; + while (true) { + sway_log(L_DEBUG, "container:%p, parent:%p, child %p,", + container,parent,child); + if (parent->layout == layout) { + int diff; + // When child == container the container is removed, + // so when inserting it back in, it needs to be -1, or 1 + // inserts at 1-1 or 1+1 + // 0 1 2 3 => 0 1 2 => 0 1 2 3 or 0 1 2 3 + // |0|1|2| => |0|2| => |1|0|2| or |0|2|1| + // When child != container, no container is removed + // inserts at 1+0 or 1+1 + // 0 1 2 3 => 0 1 2 3 4 or 0 1 2 3 4 + // |0|1|2| => |0|n|1|2| or |0|1|n|2| + if (child == container) { + diff = dir == MOVE_LEFT || dir == MOVE_UP ? -1 : 1; + } else { + diff = dir == MOVE_LEFT || dir == MOVE_UP ? 0 : 1; + } + int desired = index_child(child) + diff; + // Legal position + // when child == container, desired must be less then parent, + // when child != container, desired can be equal to parent length + if (desired >= 0 && desired - (child != container) < parent->children->length) { + // Case where we descend into a container + if (child == container) { + child = parent->children->items[desired]; + // Move container Into child container. + if (child->type == C_CONTAINER) { + parent = child; + desired = index_child(child->focused); + //reset geometry + container->width = container->height = 0; + } + } + swayc_t *old_parent = remove_child(container); + insert_child(parent, container, desired); + destroy_container(old_parent); + sway_log(L_DEBUG,"Moving to %p %d",parent, desired); break; } - if (direction == MOVE_LEFT && i > 0){ - temp = root->children->items[i-1]; - root->children->items[i] = temp; - root->children->items[i-1] = container; - arrange_windows(&root_container,-1,-1); - } - else if (direction == MOVE_RIGHT && i < clength-1){ - temp = root->children->items[i+1]; - root->children->items[i] = temp; - root->children->items[i+1] = container; - arrange_windows(&root_container,-1,-1); - - } - else if (direction == MOVE_UP){ - sway_log(L_INFO, "Moving up not implemented"); - } - else if (direction == MOVE_DOWN){ - sway_log(L_INFO, "Moving down not implemented"); - } - - break; } - else if (child->children != NULL){ - move_container(container,child,direction); + child = parent; + parent = child->parent; + if (!parent || child->type == C_WORKSPACE) { + sway_log(L_DEBUG, "Failed to move container"); + return; } } - + // Dirty hack to fix a certain case + arrange_windows(parent, -1, -1); + arrange_windows(parent->parent, -1, -1); + update_visibility(parent->parent); + set_focused_container_for(parent->parent, container); } void move_container_to(swayc_t* container, swayc_t* destination) { @@ -484,13 +530,7 @@ swayc_t *get_swayc_in_direction_under(swayc_t *container, enum movement_directio } if (can_move) { - for (i = 0; i < parent->children->length; ++i) { - swayc_t *child = parent->children->items[i]; - if (child == container) { - break; - } - } - int desired = i + diff; + int desired = index_child(container) + diff; if (desired < 0 || desired >= parent->children->length) { can_move = false; } else {