mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	focus: support focus prev|next [sibling]
This commit is contained in:
		
							parent
							
								
									ec14a00e8c
								
							
						
					
					
						commit
						f5f12a69f6
					
				
					 2 changed files with 58 additions and 8 deletions
				
			
		| 
						 | 
					@ -14,6 +14,42 @@
 | 
				
			||||||
#include "stringop.h"
 | 
					#include "stringop.h"
 | 
				
			||||||
#include "util.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,
 | 
					static bool parse_direction(const char *name,
 | 
				
			||||||
		enum wlr_direction *out) {
 | 
							enum wlr_direction *out) {
 | 
				
			||||||
	if (strcasecmp(name, "left") == 0) {
 | 
						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(
 | 
					static struct sway_node *node_get_in_direction_tiling(
 | 
				
			||||||
		struct sway_container *container, struct sway_seat *seat,
 | 
							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 *wrap_candidate = NULL;
 | 
				
			||||||
	struct sway_container *current = container;
 | 
						struct sway_container *current = container;
 | 
				
			||||||
	while (current) {
 | 
						while (current) {
 | 
				
			||||||
| 
						 | 
					@ -148,9 +184,13 @@ static struct sway_node *node_get_in_direction_tiling(
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				struct sway_container *desired_con = siblings->items[desired];
 | 
									struct sway_container *desired_con = siblings->items[desired];
 | 
				
			||||||
				struct sway_container *c = seat_get_focus_inactive_view(
 | 
									if (!descend) {
 | 
				
			||||||
						seat, &desired_con->node);
 | 
										return &desired_con->node;
 | 
				
			||||||
				return &c->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;
 | 
						enum wlr_direction direction = 0;
 | 
				
			||||||
 | 
						bool descend = true;
 | 
				
			||||||
	if (!parse_direction(argv[0], &direction)) {
 | 
						if (!parse_direction(argv[0], &direction)) {
 | 
				
			||||||
		return cmd_results_new(CMD_INVALID,
 | 
							if (!get_direction_from_next_prev(container, seat, argv[0], &direction)) {
 | 
				
			||||||
			"Expected 'focus <direction|parent|child|mode_toggle|floating|tiling>' "
 | 
								return cmd_results_new(CMD_INVALID,
 | 
				
			||||||
			"or 'focus output <direction|name>'");
 | 
									"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) {
 | 
						if (node->type == N_WORKSPACE) {
 | 
				
			||||||
| 
						 | 
					@ -373,7 +418,7 @@ struct cmd_results *cmd_focus(int argc, char **argv) {
 | 
				
			||||||
	if (container_is_floating(container)) {
 | 
						if (container_is_floating(container)) {
 | 
				
			||||||
		next_focus = node_get_in_direction_floating(container, seat, direction);
 | 
							next_focus = node_get_in_direction_floating(container, seat, direction);
 | 
				
			||||||
	} else {
 | 
						} 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) {
 | 
						if (next_focus) {
 | 
				
			||||||
		seat_set_focus(seat, next_focus);
 | 
							seat_set_focus(seat, next_focus);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,6 +120,11 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1).
 | 
				
			||||||
*focus* up|right|down|left
 | 
					*focus* up|right|down|left
 | 
				
			||||||
	Moves focus to the next container in the specified direction.
 | 
						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
 | 
					*focus* child
 | 
				
			||||||
	Moves focus to the last-focused child of the focused container.
 | 
						Moves focus to the last-focused child of the focused container.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue