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 | |
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.
-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; |