xwayland: Factor out focus_next_surface() from unmanaged_handle_unmap()

- Eliminate multiple "return" paths in unmanaged_handle_unmap(), which
  were a bug waiting to happen.
- Use wl_list_for_each_reverse() rather than wl_list_for_each() to find
  the topmost (most-recently-created) unmanaged surface.
- Only call desktop_focus_topmost_mapped_view() if the unmapped surface
  was actually focused.
This commit is contained in:
John Lindgren 2022-09-03 13:10:33 -04:00 committed by Consolatis
parent d405a2b3c6
commit 05b7afd05a

View file

@ -51,6 +51,38 @@ unmanaged_handle_map(struct wl_listener *listener, void *data)
wlr_scene_node_set_position(unmanaged->node, xsurface->x, xsurface->y);
}
static void
focus_next_surface(struct server *server, struct wlr_xwayland_surface *xsurface)
{
/*
* Try to focus on parent surface
* This seems to fix JetBrains/Intellij window focus issues
*/
if (xsurface->parent && xsurface->parent->surface
&& wlr_xwayland_or_surface_wants_focus(xsurface->parent)) {
seat_focus_surface(&server->seat, xsurface->parent->surface);
return;
}
/* Try to focus on last created unmanaged xwayland surface */
struct xwayland_unmanaged *u;
struct wl_list *list = &server->unmanaged_surfaces;
wl_list_for_each_reverse (u, list, link) {
struct wlr_xwayland_surface *prev = u->xwayland_surface;
if (wlr_xwayland_or_surface_wants_focus(prev)) {
seat_focus_surface(&server->seat, prev->surface);
return;
}
}
/*
* If we don't find a surface to focus fall back
* to the topmost mapped view. This fixes dmenu
* not giving focus back when closed with ESC.
*/
desktop_focus_topmost_mapped_view(server);
}
static void
unmanaged_handle_unmap(struct wl_listener *listener, void *data)
{
@ -72,34 +104,8 @@ unmanaged_handle_unmap(struct wl_listener *listener, void *data)
unmanaged->node = NULL;
if (seat->seat->keyboard_state.focused_surface == xsurface->surface) {
/*
* Try to focus on parent surface
* This seems to fix JetBrains/Intellij window focus issues
*/
if (xsurface->parent && xsurface->parent->surface
&& wlr_xwayland_or_surface_wants_focus(xsurface->parent)) {
seat_focus_surface(seat, xsurface->parent->surface);
return;
}
/* Try to focus on last created unmanaged xwayland surface */
struct xwayland_unmanaged *u;
struct wl_list *list = &unmanaged->server->unmanaged_surfaces;
wl_list_for_each (u, list, link) {
struct wlr_xwayland_surface *prev = u->xwayland_surface;
if (!wlr_xwayland_or_surface_wants_focus(prev)) {
continue;
}
seat_focus_surface(seat, prev->surface);
return;
}
focus_next_surface(unmanaged->server, xsurface);
}
/*
* If we don't find a surface to focus fall back
* to the topmost mapped view. This fixes dmenu
* not giving focus back when closed with ESC.
*/
desktop_focus_topmost_mapped_view(unmanaged->server);
}
static void