introduce next/prev as a direction for focus/move commands.

This commit is contained in:
wil 2016-12-22 18:46:00 +01:00
parent bc3dc97026
commit 0ff9fe9a7a
6 changed files with 75 additions and 14 deletions

View file

@ -6,7 +6,9 @@ enum movement_direction {
MOVE_UP, MOVE_UP,
MOVE_DOWN, MOVE_DOWN,
MOVE_PARENT, MOVE_PARENT,
MOVE_CHILD MOVE_CHILD,
MOVE_NEXT,
MOVE_PREV
}; };
#include "container.h" #include "container.h"
@ -40,4 +42,3 @@ extern bool suspend_workspace_cleanup;
bool move_focus(enum movement_direction direction); bool move_focus(enum movement_direction direction);
#endif #endif

View file

@ -46,6 +46,10 @@ struct cmd_results *cmd_focus(int argc, char **argv) {
move_focus(MOVE_PARENT); move_focus(MOVE_PARENT);
} else if (strcasecmp(argv[0], "child") == 0) { } else if (strcasecmp(argv[0], "child") == 0) {
move_focus(MOVE_CHILD); move_focus(MOVE_CHILD);
} else if (strcasecmp(argv[0], "next") == 0) {
move_focus(MOVE_NEXT);
} else if (strcasecmp(argv[0], "prev") == 0) {
move_focus(MOVE_PREV);
} else if (strcasecmp(argv[0], "mode_toggle") == 0) { } else if (strcasecmp(argv[0], "mode_toggle") == 0) {
int i; int i;
swayc_t *workspace = swayc_active_workspace(); swayc_t *workspace = swayc_active_workspace();

View file

@ -49,7 +49,8 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
} else if (strcasecmp(argv[0], "splitv") == 0) { } else if (strcasecmp(argv[0], "splitv") == 0) {
swayc_change_layout(parent, L_VERT); swayc_change_layout(parent, L_VERT);
} else if (strcasecmp(argv[0], "toggle") == 0 && argc == 2 && strcasecmp(argv[1], "split") == 0) { } else if (strcasecmp(argv[0], "toggle") == 0 && argc == 2 && strcasecmp(argv[1], "split") == 0) {
if (parent->layout == L_HORIZ && (parent->workspace_layout == L_NONE || parent->workspace_layout == L_HORIZ)) { if (parent->layout == L_HORIZ && (parent->workspace_layout == L_NONE ||
parent->workspace_layout == L_HORIZ)) {
swayc_change_layout(parent, L_VERT); swayc_change_layout(parent, L_VERT);
} else { } else {
swayc_change_layout(parent, L_HORIZ); swayc_change_layout(parent, L_HORIZ);

View file

@ -13,7 +13,7 @@ struct cmd_results *cmd_move(int argc, char **argv) {
if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) { if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) {
return error; return error;
} }
const char* expected_syntax = "Expected 'move <left|right|up|down>' or " const char* expected_syntax = "Expected 'move <left|right|up|down|next|prev>' or "
"'move <container|window> to workspace <name>' or " "'move <container|window> to workspace <name>' or "
"'move <container|window|workspace> to output <name|direction>' or " "'move <container|window|workspace> to output <name|direction>' or "
"'move position mouse'"; "'move position mouse'";
@ -27,6 +27,10 @@ struct cmd_results *cmd_move(int argc, char **argv) {
move_container(view, MOVE_UP); move_container(view, MOVE_UP);
} else if (strcasecmp(argv[0], "down") == 0) { } else if (strcasecmp(argv[0], "down") == 0) {
move_container(view, MOVE_DOWN); move_container(view, MOVE_DOWN);
} else if (strcasecmp(argv[0], "next") == 0) {
move_container(view, MOVE_NEXT);
} else if (strcasecmp(argv[0], "prev") == 0) {
move_container(view, MOVE_PREV);
} else if (strcasecmp(argv[0], "container") == 0 || strcasecmp(argv[0], "window") == 0) { } else if (strcasecmp(argv[0], "container") == 0 || strcasecmp(argv[0], "window") == 0) {
// "move container ... // "move container ...
if ((error = checkarg(argc, "move container/window", EXPECTED_AT_LEAST, 4))) { if ((error = checkarg(argc, "move container/window", EXPECTED_AT_LEAST, 4))) {

View file

@ -251,7 +251,7 @@ void swap_geometry(swayc_t *a, swayc_t *b) {
} }
void move_container(swayc_t *container, enum movement_direction dir) { void move_container(swayc_t *container, enum movement_direction dir) {
enum swayc_layouts layout; enum swayc_layouts layout = L_NONE;
if (container->is_floating if (container->is_floating
|| (container->type != C_VIEW && container->type != C_CONTAINER)) { || (container->type != C_VIEW && container->type != C_CONTAINER)) {
return; return;
@ -260,7 +260,7 @@ void move_container(swayc_t *container, enum movement_direction dir) {
layout = L_VERT; layout = L_VERT;
} else if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { } else if (dir == MOVE_LEFT || dir == MOVE_RIGHT) {
layout = L_HORIZ; layout = L_HORIZ;
} else { } else if (! (dir == MOVE_NEXT || dir == MOVE_PREV)) {
return; return;
} }
swayc_t *parent = container->parent; swayc_t *parent = container->parent;
@ -284,18 +284,51 @@ void move_container(swayc_t *container, enum movement_direction dir) {
container,parent,child); container,parent,child);
if (parent->layout == layout if (parent->layout == layout
|| (parent->layout == L_TABBED && layout == L_HORIZ) || (parent->layout == L_TABBED && layout == L_HORIZ)
|| (parent->layout == L_STACKED && layout == L_VERT)) { || (parent->layout == L_STACKED && layout == L_VERT)
|| is_auto_layout(parent->layout)) {
int diff; int diff;
// If it has ascended (parent has moved up), no container is removed // If it has ascended (parent has moved up), no container is removed
// so insert it at index, or index+1. // so insert it at index, or index+1.
// if it has not, the moved container is removed, so it needs to be // if it has not, the moved container is removed, so it needs to be
// inserted at index-1, or index+1 // inserted at index-1, or index+1
if (ascended) { if (ascended) {
diff = dir == MOVE_LEFT || dir == MOVE_UP ? 0 : 1; diff = dir == MOVE_LEFT || dir == MOVE_UP || dir == MOVE_PREV ? 0 : 1;
} else { } else {
diff = dir == MOVE_LEFT || dir == MOVE_UP ? -1 : 1; diff = dir == MOVE_LEFT || dir == MOVE_UP || dir == MOVE_PREV ? -1 : 1;
}
int idx = index_child(child);
int desired = idx + diff;
if (dir == MOVE_NEXT || dir == MOVE_PREV) {
// Next/Prev always wrap.
if (desired < 0) {
desired += parent->children->length;
} else if (desired >= parent->children->length) {
desired = 0;
}
// if move command makes container change from master to slave
// (or the contrary), reset its geometry an the one of the replaced item.
if (parent->nb_master &&
(uint_fast32_t) parent->children->length > parent->nb_master) {
swayc_t *swap_geom = NULL;
// if child is being promoted/demoted, it will swap geometry
// with the sibling being demoted/promoted.
if ((dir == MOVE_NEXT && desired == 0)
|| (dir == MOVE_PREV && (uint_fast32_t) desired == parent->nb_master - 1)) {
swap_geom = parent->children->items[parent->nb_master - 1];
} else if ((dir == MOVE_NEXT && (uint_fast32_t) desired == parent->nb_master)
|| (dir == MOVE_PREV && desired == parent->children->length - 1)) {
swap_geom = parent->children->items[parent->nb_master];
}
if (swap_geom) {
double h = child->height;
double w = child->width;
child->width = swap_geom->width;
child->height = swap_geom->height;
swap_geom->width = w;
swap_geom->height = h;
}
}
} }
int desired = index_child(child) + diff;
// when it has ascended, legal insertion position is 0:len // when it has ascended, legal insertion position is 0:len
// when it has not, legal insertion position is 0:len-1 // when it has not, legal insertion position is 0:len-1
if (desired >= 0 && desired - ascended < parent->children->length) { if (desired >= 0 && desired - ascended < parent->children->length) {
@ -308,7 +341,8 @@ void move_container(swayc_t *container, enum movement_direction dir) {
// insert it next to focused container // insert it next to focused container
if (parent->layout == layout if (parent->layout == layout
|| (parent->layout == L_TABBED && layout == L_HORIZ) || (parent->layout == L_TABBED && layout == L_HORIZ)
|| (parent->layout == L_STACKED && layout == L_VERT)) { || (parent->layout == L_STACKED && layout == L_VERT)
|| is_auto_layout(parent->layout)) {
desired = (diff < 0) * parent->children->length; desired = (diff < 0) * parent->children->length;
} else { } else {
desired = index_child(child->focused) + 1; desired = index_child(child->focused) + 1;
@ -325,7 +359,7 @@ void move_container(swayc_t *container, enum movement_direction dir) {
} }
} }
// Change parent layout if we need to // Change parent layout if we need to
if (parent->children->length == 1 && parent->layout != layout) { if (parent->children->length == 1 && parent->layout != layout && layout != L_NONE) {
/* swayc_change_layout(parent, layout); */ /* swayc_change_layout(parent, layout); */
parent->layout = layout; parent->layout = layout;
continue; continue;
@ -1310,6 +1344,21 @@ swayc_t *get_swayc_in_direction_under(swayc_t *container, enum movement_directio
return parent; return parent;
} }
} }
if (dir == MOVE_PREV || dir == MOVE_NEXT) {
int focused_idx = index_child(container);
if (focused_idx == -1) {
return NULL;
} else {
int desired = (focused_idx + (dir == MOVE_NEXT ? 1 : -1)) %
parent->children->length;
if (desired < 0) {
desired += parent->children->length;
}
return parent->children->items[desired];
}
}
// If moving to an adjacent output we need a starting position (since this // If moving to an adjacent output we need a starting position (since this
// output might border to multiple outputs). // output might border to multiple outputs).
struct wlc_point abs_pos; struct wlc_point abs_pos;

View file

@ -92,8 +92,10 @@ They are expected to be used with **bindsym** or at runtime through **swaymsg**(
focused container. <n> can be a positive or negative integer. These commands focused container. <n> can be a positive or negative integer. These commands
only have an effect if the focused container uses one of the "auto" layouts. only have an effect if the focused container uses one of the "auto" layouts.
**move** <left|right|up|down>:: **move** <left|right|up|down|next|prev>::
Moves the focused container _left_, _right_, _up_, or _down_. Moves the focused container _left_, _right_, _up_, or _down_. Moving
to _prev_ or _next_ swaps the container with its sibling in the same
container.
**move** <container|window> to workspace <name>:: **move** <container|window> to workspace <name>::
Moves the focused container to the workspace identified by _name_. Moves the focused container to the workspace identified by _name_.