diff options
Diffstat (limited to 'sway/commands/focus.c')
-rw-r--r-- | sway/commands/focus.c | 49 |
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 | ||
93 | static struct sway_node *node_get_in_direction(struct sway_container *container, | 94 | static 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 | ||
177 | static 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 | |||
175 | static struct cmd_results *focus_mode(struct sway_workspace *ws, | 208 | static 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); |