sway

i3-compatible Wayland compositor
git clone https://git.awy.one/sway
Log | Files | Refs | README | LICENSE

commit 7e978d7a4c521a98b9f44274cd65791b06266ed3
parent 7727d54faf2939e30f82da562de83dbcda1749db
Author: Jonathan Buch <jbuch@synyx.de>
Date:   Wed,  3 Oct 2018 11:05:30 +0200

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:
Msway/tree/container.c | 50+++++++++++---------------------------------------
1 file changed, 11 insertions(+), 39 deletions(-)

diff --git a/sway/tree/container.c b/sway/tree/container.c @@ -151,10 +151,10 @@ struct sway_container *container_find_child(struct sway_container *container, return NULL; } -static void surface_at_view(struct sway_container *con, double lx, double ly, +static struct sway_container *surface_at_view(struct sway_container *con, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { if (!sway_assert(con->view, "Expected a view")) { - return; + return NULL; } struct sway_view *view = con->view; 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, *sx = _sx; *sy = _sy; *surface = _surface; + return con; } + return NULL; } /** @@ -354,46 +356,16 @@ static bool surface_is_popup(struct wlr_surface *surface) { struct sway_container *container_at(struct sway_workspace *workspace, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { - struct sway_container *c; - // Focused view's popups - struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = seat_get_focused_container(seat); - bool is_floating = focus && container_is_floating_or_child(focus); - // Focused view's popups - if (focus && focus->view) { - surface_at_view(focus, lx, ly, surface, sx, sy); - if (*surface && surface_is_popup(*surface)) { - return focus; - } - *surface = NULL; - } - // If focused is floating, focused view's non-popups - if (focus && focus->view && is_floating) { - // only switch to unfocused container if focused container has no menus open - bool has_subsurfaces = wl_list_length(&focus->view->surface->subsurfaces) > 0; - c = floating_container_at(lx, ly, surface, sx, sy); - if (!has_subsurfaces && c && c->view && *surface && c != focus) { - return c; - } + struct sway_container *c = NULL; - surface_at_view(focus, lx, ly, surface, sx, sy); - if (*surface) { - return focus; - } - *surface = NULL; - } - // Floating (non-focused) - if ((c = floating_container_at(lx, ly, surface, sx, sy))) { - return c; - } - // If focused is tiling, focused view's non-popups - if (focus && focus->view && !is_floating) { - surface_at_view(focus, lx, ly, surface, sx, sy); - if (*surface) { - return focus; + // First cast a ray to handle floating windows + for (int i = workspace->floating->length - 1; i >= 0; --i) { + struct sway_container *cn = workspace->floating->items[i]; + if (cn->view && (c = surface_at_view(cn, lx, ly, surface, sx, sy))) { + return c; } - *surface = NULL; } + // Tiling (non-focused) if ((c = tiling_container_at(&workspace->node, lx, ly, surface, sx, sy))) { return c;