From b7bd5a52e44283a0f551ede833bff5197ed53e65 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Mon, 2 Oct 2023 22:37:12 -0400 Subject: [PATCH] desktop: add commentary clarifying focus rules --- include/labwc.h | 21 +++++++++++++++++++++ src/desktop.c | 7 +++++++ src/xwayland.c | 3 ++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/include/labwc.h b/include/labwc.h index 0f6b2a2a..84d39d4f 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -375,6 +375,18 @@ void foreign_toplevel_update_outputs(struct view *view); * cannot assume this means that the window actually has keyboard * or pointer focus, in this compositor are they called together. */ + +/** + * desktop_focus_view() - do multiple things to make a view "active" and + * ready to use: + * - unminimize + * - switch to the workspace it's on + * - give input (keyboard) focus + * - optionally raise above other views + * + * It's okay to call this function even if the view isn't mapped or the + * session is locked/input is inhibited; it will simply do nothing. + */ void desktop_focus_view(struct view *view, bool raise); void desktop_arrange_all_views(struct server *server); void desktop_focus_output(struct output *output); @@ -393,6 +405,15 @@ enum lab_cycle_dir { */ struct view *desktop_cycle_view(struct server *server, struct view *start_view, enum lab_cycle_dir dir); + +/** + * desktop_focus_topmost_view() - focus the topmost view on the current + * workspace, skipping views that claim not to want focus (those can + * still be focused by explicit request, e.g. by clicking in them). + * + * This function is typically called when the focused view is hidden + * (closes, is minimized, etc.) to focus the "next" view underneath. + */ void desktop_focus_topmost_view(struct server *server); void keyboard_cancel_keybind_repeat(struct keyboard *keyboard); diff --git a/src/desktop.c b/src/desktop.c index 41c43afa..eac56453 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -73,6 +73,13 @@ desktop_focus_view(struct view *view, bool raise) workspaces_switch_to(view->workspace, /*update_focus*/ false); } + /* + * Give input focus, even if the view claims not to want it (see + * view->impl->wants_focus). This is a workaround for so-called + * "globally active" X11 views (MATLAB known to be one such) + * that expect to be able to control focus themselves, but can't + * under labwc since it's disallowed at the wlroots level. + */ struct seat *seat = &server->seat; if (view->surface != seat->seat->keyboard_state.focused_surface) { seat_focus_surface(seat, view->surface); diff --git a/src/xwayland.c b/src/xwayland.c index ec9fe4a2..265e63d9 100644 --- a/src/xwayland.c +++ b/src/xwayland.c @@ -49,7 +49,8 @@ xwayland_view_wants_focus(struct view *view) * Clients that use XSetInputFocus() to explicitly set the input * focus should set the WM_TAKE_FOCUS atom in WM_PROTOCOLS. * Currently, labwc does not support this method of taking focus - * and thus makes no use of WM_TAKE_FOCUS. + * and thus ignores WM_TAKE_FOCUS. These views can still be + * focused by explicit user action (e.g. clicking in them). */ return (bool)hints->input; }