diff options
author | Jonathan Buch <jbuch@synyx.de> | 2018-10-03 11:05:30 +0200 |
---|---|---|
committer | Jonathan Buch <jbuch@synyx.de> | 2018-10-03 16:23:14 +0200 |
commit | 7e978d7a4c521a98b9f44274cd65791b06266ed3 (patch) | |
tree | 83a1f99fd42c41ae8f15ea0580fb864046dcf427 /sway/tree/container.c | |
parent | Fix focusing topmost floating windows (diff) | |
download | sway-7e978d7a4c521a98b9f44274cd65791b06266ed3.tar.gz sway-7e978d7a4c521a98b9f44274cd65791b06266ed3.tar.zst sway-7e978d7a4c521a98b9f44274cd65791b06266ed3.zip |
Use "raycasting" for determining focus for floating windows
Floating containers and their surfaces are ordered in "raised last".
This is used to detect the topmost surface and thus the focus.
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r-- | sway/tree/container.c | 50 |
1 files changed, 11 insertions, 39 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c index f9ddf3d6..f069a9e9 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -151,10 +151,10 @@ struct sway_container *container_find_child(struct sway_container *container, | |||
151 | return NULL; | 151 | return NULL; |
152 | } | 152 | } |
153 | 153 | ||
154 | static void surface_at_view(struct sway_container *con, double lx, double ly, | 154 | static struct sway_container *surface_at_view(struct sway_container *con, double lx, double ly, |
155 | struct wlr_surface **surface, double *sx, double *sy) { | 155 | struct wlr_surface **surface, double *sx, double *sy) { |
156 | if (!sway_assert(con->view, "Expected a view")) { | 156 | if (!sway_assert(con->view, "Expected a view")) { |
157 | return; | 157 | return NULL; |
158 | } | 158 | } |
159 | struct sway_view *view = con->view; | 159 | struct sway_view *view = con->view; |
160 | double view_sx = lx - view->x + view->geometry.x; | 160 | double view_sx = lx - view->x + view->geometry.x; |
@@ -184,7 +184,9 @@ static void surface_at_view(struct sway_container *con, double lx, double ly, | |||
184 | *sx = _sx; | 184 | *sx = _sx; |
185 | *sy = _sy; | 185 | *sy = _sy; |
186 | *surface = _surface; | 186 | *surface = _surface; |
187 | return con; | ||
187 | } | 188 | } |
189 | return NULL; | ||
188 | } | 190 | } |
189 | 191 | ||
190 | /** | 192 | /** |
@@ -354,46 +356,16 @@ static bool surface_is_popup(struct wlr_surface *surface) { | |||
354 | struct sway_container *container_at(struct sway_workspace *workspace, | 356 | struct sway_container *container_at(struct sway_workspace *workspace, |
355 | double lx, double ly, | 357 | double lx, double ly, |
356 | struct wlr_surface **surface, double *sx, double *sy) { | 358 | struct wlr_surface **surface, double *sx, double *sy) { |
357 | struct sway_container *c; | 359 | struct sway_container *c = NULL; |
358 | // Focused view's popups | ||
359 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
360 | struct sway_container *focus = seat_get_focused_container(seat); | ||
361 | bool is_floating = focus && container_is_floating_or_child(focus); | ||
362 | // Focused view's popups | ||
363 | if (focus && focus->view) { | ||
364 | surface_at_view(focus, lx, ly, surface, sx, sy); | ||
365 | if (*surface && surface_is_popup(*surface)) { | ||
366 | return focus; | ||
367 | } | ||
368 | *surface = NULL; | ||
369 | } | ||
370 | // If focused is floating, focused view's non-popups | ||
371 | if (focus && focus->view && is_floating) { | ||
372 | // only switch to unfocused container if focused container has no menus open | ||
373 | bool has_subsurfaces = wl_list_length(&focus->view->surface->subsurfaces) > 0; | ||
374 | c = floating_container_at(lx, ly, surface, sx, sy); | ||
375 | if (!has_subsurfaces && c && c->view && *surface && c != focus) { | ||
376 | return c; | ||
377 | } | ||
378 | 360 | ||
379 | surface_at_view(focus, lx, ly, surface, sx, sy); | 361 | // First cast a ray to handle floating windows |
380 | if (*surface) { | 362 | for (int i = workspace->floating->length - 1; i >= 0; --i) { |
381 | return focus; | 363 | struct sway_container *cn = workspace->floating->items[i]; |
382 | } | 364 | if (cn->view && (c = surface_at_view(cn, lx, ly, surface, sx, sy))) { |
383 | *surface = NULL; | 365 | return c; |
384 | } | ||
385 | // Floating (non-focused) | ||
386 | if ((c = floating_container_at(lx, ly, surface, sx, sy))) { | ||
387 | return c; | ||
388 | } | ||
389 | // If focused is tiling, focused view's non-popups | ||
390 | if (focus && focus->view && !is_floating) { | ||
391 | surface_at_view(focus, lx, ly, surface, sx, sy); | ||
392 | if (*surface) { | ||
393 | return focus; | ||
394 | } | 366 | } |
395 | *surface = NULL; | ||
396 | } | 367 | } |
368 | |||
397 | // Tiling (non-focused) | 369 | // Tiling (non-focused) |
398 | if ((c = tiling_container_at(&workspace->node, lx, ly, surface, sx, sy))) { | 370 | if ((c = tiling_container_at(&workspace->node, lx, ly, surface, sx, sy))) { |
399 | return c; | 371 | return c; |