aboutsummaryrefslogtreecommitdiffstats
path: root/sway/commands/focus.c
diff options
context:
space:
mode:
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);