aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRonan Pigott <rpigott@berkeley.edu>2019-10-24 11:41:04 -0700
committerDrew DeVault <sir@cmpwn.com>2019-10-27 11:02:57 -0400
commitf5f12a69f6280dba4f8b05290bd81385d6e6c268 (patch)
treefc6bdf29a71499edf9210bd70c0a549dedd75933
parentec14a00e8c6751d0b73ca0ad5f756e4165092b87 (diff)
focus: support focus prev|next [sibling]
-rw-r--r--sway/commands/focus.c61
-rw-r--r--sway/sway.5.scd5
2 files changed, 58 insertions, 8 deletions
diff --git a/sway/commands/focus.c b/sway/commands/focus.c
index 93d1effe..99c7e61e 100644
--- a/sway/commands/focus.c
+++ b/sway/commands/focus.c
@@ -14,6 +14,42 @@
#include "stringop.h"
#include "util.h"
+static bool get_direction_from_next_prev(struct sway_container *container,
+ struct sway_seat *seat, const char *name, enum wlr_direction *out) {
+ enum sway_container_layout parent_layout = container_parent_layout(container);
+ if (strcasecmp(name, "prev") == 0) {
+ switch (parent_layout) {
+ case L_HORIZ:
+ case L_TABBED:
+ *out = WLR_DIRECTION_LEFT;
+ break;
+ case L_VERT:
+ case L_STACKED:
+ *out = WLR_DIRECTION_UP;
+ break;
+ default:
+ return false;
+ }
+ } else if (strcasecmp(name, "next") == 0) {
+ switch (parent_layout) {
+ case L_HORIZ:
+ case L_TABBED:
+ *out = WLR_DIRECTION_RIGHT;
+ break;
+ case L_VERT:
+ case L_STACKED:
+ *out = WLR_DIRECTION_DOWN;
+ break;
+ default:
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
static bool parse_direction(const char *name,
enum wlr_direction *out) {
if (strcasecmp(name, "left") == 0) {
@@ -93,7 +129,7 @@ static struct sway_node *get_node_in_output_direction(
static struct sway_node *node_get_in_direction_tiling(
struct sway_container *container, struct sway_seat *seat,
- enum wlr_direction dir) {
+ enum wlr_direction dir, bool descend) {
struct sway_container *wrap_candidate = NULL;
struct sway_container *current = container;
while (current) {
@@ -148,9 +184,13 @@ static struct sway_node *node_get_in_direction_tiling(
}
} else {
struct sway_container *desired_con = siblings->items[desired];
- struct sway_container *c = seat_get_focus_inactive_view(
- seat, &desired_con->node);
- return &c->node;
+ if (!descend) {
+ return &desired_con->node;
+ } else {
+ struct sway_container *c = seat_get_focus_inactive_view(
+ seat, &desired_con->node);
+ return &c->node;
+ }
}
}
@@ -348,10 +388,15 @@ struct cmd_results *cmd_focus(int argc, char **argv) {
}
enum wlr_direction direction = 0;
+ bool descend = true;
if (!parse_direction(argv[0], &direction)) {
- return cmd_results_new(CMD_INVALID,
- "Expected 'focus <direction|parent|child|mode_toggle|floating|tiling>' "
- "or 'focus output <direction|name>'");
+ if (!get_direction_from_next_prev(container, seat, argv[0], &direction)) {
+ return cmd_results_new(CMD_INVALID,
+ "Expected 'focus <direction|next|prev|parent|child|mode_toggle|floating|tiling>' "
+ "or 'focus output <direction|name>'");
+ } else if (argc == 2 && strcasecmp(argv[1], "sibling") == 0) {
+ descend = false;
+ }
}
if (node->type == N_WORKSPACE) {
@@ -373,7 +418,7 @@ struct cmd_results *cmd_focus(int argc, char **argv) {
if (container_is_floating(container)) {
next_focus = node_get_in_direction_floating(container, seat, direction);
} else {
- next_focus = node_get_in_direction_tiling(container, seat, direction);
+ next_focus = node_get_in_direction_tiling(container, seat, direction, descend);
}
if (next_focus) {
seat_set_focus(seat, next_focus);
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index 63b5465a..8315f8a1 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -120,6 +120,11 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1).
*focus* up|right|down|left
Moves focus to the next container in the specified direction.
+*focus* prev|next [sibling]
+ Moves focus to the previous or next container in the current layout. By default,
+ the last active child of the newly focused container will be focused. The _sibling_
+ option indicates not to immediately focus a child of the container.
+
*focus* child
Moves focus to the last-focused child of the focused container.