From 613abdda6fa978480067a35c3adc46fb414b0b5c Mon Sep 17 00:00:00 2001 From: Tudor Brindus Date: Thu, 28 May 2020 18:45:39 -0400 Subject: [PATCH] xwayland: pass focus to previous unmanaged surface on unmap This is necessary because some applications (e.g. Jetbrains IDEs) represent their multi-level menus as unmanaged surfaces, and when closing a submenu, the main menu should get input focus. Closes #5347. --- sway/desktop/xwayland.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 8936c8bc..4bf5b6b8 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -94,6 +94,22 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) { struct sway_seat *seat = input_manager_current_seat(); if (seat->wlr_seat->keyboard_state.focused_surface == xsurface->surface) { + + // Try to find another unmanaged surface from the same process to pass + // focus to. This is necessary because some applications (e.g. Jetbrains + // IDEs) represent their multi-level menus as unmanaged surfaces, and + // when closing a submenu, the main menu should get input focus. + struct sway_xwayland_unmanaged *current; + wl_list_for_each(current, &root->xwayland_unmanaged, link) { + struct wlr_xwayland_surface *prev_xsurface = + current->wlr_xwayland_surface; + if (prev_xsurface->pid == xsurface->pid && + wlr_xwayland_or_surface_wants_focus(prev_xsurface)) { + seat_set_focus_surface(seat, prev_xsurface->surface, false); + return; + } + } + // Restore focus struct sway_node *previous = seat_get_focus_inactive(seat, &root->node); if (previous) {