mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
view/xwayland: avoid focusing views that don't want focus
XWayland views can self-declare that they don't want keyboard focus via the ICCCM WM_HINTS property. Most of the logic is already in place to avoid giving focus to such views (e.g. taskbars). Add a couple of missing pieces to make this work: - Hook up view_isfocusable() to look at WM_HINTS for XWayland views - Adjust desktop_focus_topmost_mapped_view() to skip unfocusable views
This commit is contained in:
parent
d503370a77
commit
7e72bf975f
10 changed files with 29 additions and 13 deletions
|
|
@ -378,7 +378,7 @@ void foreign_toplevel_update_outputs(struct view *view);
|
|||
void desktop_focus_view(struct view *view, bool raise);
|
||||
void desktop_arrange_all_views(struct server *server);
|
||||
void desktop_focus_output(struct output *output);
|
||||
struct view *desktop_topmost_mapped_view(struct server *server);
|
||||
struct view *desktop_topmost_focusable_view(struct server *server);
|
||||
|
||||
enum lab_cycle_dir {
|
||||
LAB_CYCLE_DIR_NONE,
|
||||
|
|
@ -393,7 +393,7 @@ enum lab_cycle_dir {
|
|||
*/
|
||||
struct view *desktop_cycle_view(struct server *server, struct view *start_view,
|
||||
enum lab_cycle_dir dir);
|
||||
void desktop_focus_topmost_mapped_view(struct server *server);
|
||||
void desktop_focus_topmost_view(struct server *server);
|
||||
|
||||
void keyboard_cancel_keybind_repeat(struct keyboard *keyboard);
|
||||
void keyboard_key_notify(struct wl_listener *listener, void *data);
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ struct view_impl {
|
|||
struct view *(*get_root)(struct view *self);
|
||||
void (*append_children)(struct view *self, struct wl_array *children);
|
||||
struct view_size_hints (*get_size_hints)(struct view *self);
|
||||
/* if not implemented, view is assumed to want focus */
|
||||
bool (*wants_focus)(struct view *self);
|
||||
};
|
||||
|
||||
struct view {
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ desktop_cycle_view(struct server *server, struct view *start_view,
|
|||
}
|
||||
|
||||
struct view *
|
||||
desktop_topmost_mapped_view(struct server *server)
|
||||
desktop_topmost_focusable_view(struct server *server)
|
||||
{
|
||||
struct view *view;
|
||||
struct wl_list *node_list;
|
||||
|
|
@ -202,7 +202,7 @@ desktop_topmost_mapped_view(struct server *server)
|
|||
continue;
|
||||
}
|
||||
view = node_view_from_node(node);
|
||||
if (view->mapped) {
|
||||
if (view->mapped && view_isfocusable(view)) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
|
@ -210,9 +210,9 @@ desktop_topmost_mapped_view(struct server *server)
|
|||
}
|
||||
|
||||
void
|
||||
desktop_focus_topmost_mapped_view(struct server *server)
|
||||
desktop_focus_topmost_view(struct server *server)
|
||||
{
|
||||
struct view *view = desktop_topmost_mapped_view(server);
|
||||
struct view *view = desktop_topmost_focusable_view(server);
|
||||
if (view) {
|
||||
desktop_focus_view(view, /*raise*/ true);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -496,7 +496,7 @@ seat_set_focus_layer(struct seat *seat, struct wlr_layer_surface_v1 *layer)
|
|||
{
|
||||
if (!layer) {
|
||||
seat->focused_layer = NULL;
|
||||
desktop_focus_topmost_mapped_view(seat->server);
|
||||
desktop_focus_topmost_view(seat->server);
|
||||
return;
|
||||
}
|
||||
seat_focus(seat, layer->surface);
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ handle_unlock(struct wl_listener *listener, void *data)
|
|||
{
|
||||
struct session_lock *lock = wl_container_of(listener, lock, unlock);
|
||||
session_lock_destroy(lock);
|
||||
desktop_focus_topmost_mapped_view(g_server);
|
||||
desktop_focus_topmost_view(g_server);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -118,6 +118,9 @@ view_isfocusable(struct view *view)
|
|||
if (!view->surface) {
|
||||
return false;
|
||||
}
|
||||
if (view->impl->wants_focus && !view->impl->wants_focus(view)) {
|
||||
return false;
|
||||
}
|
||||
return (view->mapped || view->minimized);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ workspaces_switch_to(struct workspace *target, bool update_focus)
|
|||
if (update_focus) {
|
||||
struct view *view = server->focused_view;
|
||||
if (!view || !view_is_always_on_top(view)) {
|
||||
desktop_focus_topmost_mapped_view(server);
|
||||
desktop_focus_topmost_view(server);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -554,7 +554,7 @@ xdg_toplevel_view_unmap(struct view *view, bool client_request)
|
|||
view->mapped = false;
|
||||
wlr_scene_node_set_enabled(&view->scene_tree->node, false);
|
||||
wl_list_remove(&view->commit.link);
|
||||
desktop_focus_topmost_mapped_view(view->server);
|
||||
desktop_focus_topmost_view(view->server);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ focus_next_surface(struct server *server, struct wlr_xwayland_surface *xsurface)
|
|||
* to the topmost mapped view. This fixes dmenu
|
||||
* not giving focus back when closed with ESC.
|
||||
*/
|
||||
desktop_focus_topmost_mapped_view(server);
|
||||
desktop_focus_topmost_view(server);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -166,7 +166,7 @@ unmanaged_handle_request_activate(struct wl_listener *listener, void *data)
|
|||
* Validate that the unmanaged surface trying to grab focus is actually
|
||||
* a child of the topmost mapped view before granting the request.
|
||||
*/
|
||||
struct view *view = desktop_topmost_mapped_view(server);
|
||||
struct view *view = desktop_topmost_focusable_view(server);
|
||||
if (view && view->type == LAB_XWAYLAND_VIEW) {
|
||||
struct wlr_xwayland_surface *surf =
|
||||
wlr_xwayland_surface_from_wlr_surface(view->surface);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,16 @@ xwayland_view_get_size_hints(struct view *view)
|
|||
};
|
||||
}
|
||||
|
||||
static bool
|
||||
xwayland_view_wants_focus(struct view *view)
|
||||
{
|
||||
xcb_icccm_wm_hints_t *hints = xwayland_surface_from_view(view)->hints;
|
||||
if (!hints) {
|
||||
return true;
|
||||
}
|
||||
return (bool)hints->input;
|
||||
}
|
||||
|
||||
static struct wlr_xwayland_surface *
|
||||
top_parent_of(struct view *view)
|
||||
{
|
||||
|
|
@ -505,7 +515,7 @@ xwayland_view_unmap(struct view *view, bool client_request)
|
|||
view->mapped = false;
|
||||
wl_list_remove(&view->commit.link);
|
||||
wlr_scene_node_set_enabled(&view->scene_tree->node, false);
|
||||
desktop_focus_topmost_mapped_view(view->server);
|
||||
desktop_focus_topmost_view(view->server);
|
||||
|
||||
/*
|
||||
* If the view was explicitly unmapped by the client (rather
|
||||
|
|
@ -634,6 +644,7 @@ static const struct view_impl xwayland_view_impl = {
|
|||
.get_root = xwayland_view_get_root,
|
||||
.append_children = xwayland_view_append_children,
|
||||
.get_size_hints = xwayland_view_get_size_hints,
|
||||
.wants_focus = xwayland_view_wants_focus,
|
||||
};
|
||||
|
||||
void
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue