aboutsummaryrefslogtreecommitdiffstats
path: root/sway/commands/focus.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2019-03-20 22:16:53 +1000
committerLibravatar Drew DeVault <sir@cmpwn.com>2019-03-20 08:55:28 -0600
commitcdcc2a5bb52a34865eee2ec3d09a38b047c08ffd (patch)
tree326f7c5be7a51d56ce5617d6bc536c94db3cf129 /sway/commands/focus.c
parentSupport WLR_INPUT_DEVICE_SWITCH in sway (diff)
downloadsway-cdcc2a5bb52a34865eee2ec3d09a38b047c08ffd.tar.gz
sway-cdcc2a5bb52a34865eee2ec3d09a38b047c08ffd.tar.zst
sway-cdcc2a5bb52a34865eee2ec3d09a38b047c08ffd.zip
Support focus <direction> for floating containers
This kind of worked before in that focus would change, but it wasn't intentionally supported and had side effects such as not raising the container, and being unable to cycle through all floaters depending on the direction used. This commit makes it properly supported. The new focus is chosen based on the distance to the center point of each floating container in the workspace, and the container is raised. In a multi output setup, if both visible workspaces have floating containers, focus will NOT cross into the other output. It is assumed the user will use a workspace binding in this case. If two floating containers occupy the exact same center point and you try to focus in a direction, the behaviour is undefined.
Diffstat (limited to 'sway/commands/focus.c')
-rw-r--r--sway/commands/focus.c49
1 files changed, 45 insertions, 4 deletions
diff --git a/sway/commands/focus.c b/sway/commands/focus.c
index 6344a765..33d01405 100644
--- a/sway/commands/focus.c
+++ b/sway/commands/focus.c
@@ -1,3 +1,4 @@
1#include <float.h>
1#include <strings.h> 2#include <strings.h>
2#include <wlr/types/wlr_output_layout.h> 3#include <wlr/types/wlr_output_layout.h>
3#include "log.h" 4#include "log.h"
@@ -90,8 +91,9 @@ static struct sway_node *get_node_in_output_direction(
90 return &ws->node; 91 return &ws->node;
91} 92}
92 93
93static struct sway_node *node_get_in_direction(struct sway_container *container, 94static struct sway_node *node_get_in_direction_tiling(
94 struct sway_seat *seat, enum wlr_direction dir) { 95 struct sway_container *container, struct sway_seat *seat,
96 enum wlr_direction dir) {
95 struct sway_container *wrap_candidate = NULL; 97 struct sway_container *wrap_candidate = NULL;
96 struct sway_container *current = container; 98 struct sway_container *current = container;
97 while (current) { 99 while (current) {
@@ -172,6 +174,37 @@ static struct sway_node *node_get_in_direction(struct sway_container *container,
172 return NULL; 174 return NULL;
173} 175}
174 176
177static struct sway_node *node_get_in_direction_floating(
178 struct sway_container *con, struct sway_seat *seat,
179 enum wlr_direction dir) {
180 double ref_lx = con->x + con->width / 2;
181 double ref_ly = con->y + con->height / 2;
182 double closest_distance = DBL_MAX;
183 struct sway_container *closest_con = NULL;
184
185 for (int i = 0; i < con->workspace->floating->length; i++) {
186 struct sway_container *floater = con->workspace->floating->items[i];
187 if (floater == con) {
188 continue;
189 }
190 float distance = dir == WLR_DIRECTION_LEFT || dir == WLR_DIRECTION_RIGHT
191 ? (floater->x + floater->width / 2) - ref_lx
192 : (floater->y + floater->height / 2) - ref_ly;
193 if (dir == WLR_DIRECTION_LEFT || dir == WLR_DIRECTION_UP) {
194 distance = -distance;
195 }
196 if (distance < 0) {
197 continue;
198 }
199 if (distance < closest_distance) {
200 closest_distance = distance;
201 closest_con = floater;
202 }
203 }
204
205 return closest_con ? &closest_con->node : NULL;
206}
207
175static struct cmd_results *focus_mode(struct sway_workspace *ws, 208static struct cmd_results *focus_mode(struct sway_workspace *ws,
176 struct sway_seat *seat, bool floating) { 209 struct sway_seat *seat, bool floating) {
177 struct sway_container *new_focus = NULL; 210 struct sway_container *new_focus = NULL;
@@ -330,11 +363,19 @@ struct cmd_results *cmd_focus(int argc, char **argv) {
330 return cmd_results_new(CMD_SUCCESS, NULL); 363 return cmd_results_new(CMD_SUCCESS, NULL);
331 } 364 }
332 365
333 struct sway_node *next_focus = 366 struct sway_node *next_focus = NULL;
334 node_get_in_direction(container, seat, direction); 367 if (container_is_floating(container)) {
368 next_focus = node_get_in_direction_floating(container, seat, direction);
369 } else {
370 next_focus = node_get_in_direction_tiling(container, seat, direction);
371 }
335 if (next_focus) { 372 if (next_focus) {
336 seat_set_focus(seat, next_focus); 373 seat_set_focus(seat, next_focus);
337 seat_consider_warp_to_focus(seat); 374 seat_consider_warp_to_focus(seat);
375
376 if (next_focus->type == N_CONTAINER) {
377 container_raise_floating(next_focus->sway_container);
378 }
338 } 379 }
339 380
340 return cmd_results_new(CMD_SUCCESS, NULL); 381 return cmd_results_new(CMD_SUCCESS, NULL);