From 7727d54faf2939e30f82da562de83dbcda1749db Mon Sep 17 00:00:00 2001 From: Jonathan Buch Date: Thu, 27 Sep 2018 18:32:55 +0200 Subject: Fix focusing topmost floating windows Re-focus on the container on which the cursor hovers over. A special case is, if there are menus or other subsurfaces open in the focused container. It will prefer the focused container as long as there are subsurfaces. This commit starts caching the previous node as well as the previous x/y cursor position. Re-calculating the previous focused node by looking at the current state of the cursor position does not work, if the environment changes. --- sway/tree/container.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sway/tree') diff --git a/sway/tree/container.c b/sway/tree/container.c index a069b177..f9ddf3d6 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -369,6 +369,13 @@ struct sway_container *container_at(struct sway_workspace *workspace, } // 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; + } + surface_at_view(focus, lx, ly, surface, sx, sy); if (*surface) { return focus; -- cgit v1.2.3 From 7e978d7a4c521a98b9f44274cd65791b06266ed3 Mon Sep 17 00:00:00 2001 From: Jonathan Buch Date: Wed, 3 Oct 2018 11:05:30 +0200 Subject: 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. --- sway/tree/container.c | 50 +++++++++++--------------------------------------- 1 file changed, 11 insertions(+), 39 deletions(-) (limited to 'sway/tree') 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, 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; -- cgit v1.2.3 From 426c33f4dc2515867a0d3b04cb865d5cad091d10 Mon Sep 17 00:00:00 2001 From: Jonathan Buch Date: Wed, 3 Oct 2018 11:26:46 +0200 Subject: Reenable popup-handling for determining focus This reenables the popup-handling code before the floating-window focus change. --- sway/tree/container.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'sway/tree') diff --git a/sway/tree/container.c b/sway/tree/container.c index f069a9e9..9db7aed1 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -356,16 +356,33 @@ 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 = NULL; + struct sway_container *c; - // First cast a ray to handle floating windows + // 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) { + c = surface_at_view(focus, lx, ly, surface, sx, sy); + if (c && surface_is_popup(*surface)) { + return c; + } + *surface = NULL; + } + // 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; } } - + // If focused is tiling, focused view's non-popups + if (focus && focus->view && !is_floating) { + if ((c = surface_at_view(focus, lx, ly, surface, sx, sy))) { + return c; + } + } // Tiling (non-focused) if ((c = tiling_container_at(&workspace->node, lx, ly, surface, sx, sy))) { return c; -- cgit v1.2.3