mirror of
https://github.com/labwc/labwc.git
synced 2026-04-12 08:21:13 -04:00
experimental: use wlr_xwayland_surface_offer_focus()
Offer focus by sending WM_TAKE_FOCUS to a client window supporting it. The client may accept or ignore the offer. If it accepts, the surface will emit a focus_in signal notifying the compositor that it has received focus. The compositor should then call wlr_xwayland_surface_activate(surface, true). This is a more compatible method of giving focus to windows using the Globally Active input model (see wlr_xwayland_icccm_input_model()) than calling wlr_xwayland_surface_activate() unconditionally, since there is no reliable way to know in advance whether these windows want to be focused.
This commit is contained in:
parent
179a030bbe
commit
22b193254c
5 changed files with 47 additions and 10 deletions
|
|
@ -94,6 +94,7 @@ struct view_impl {
|
|||
struct view_size_hints (*get_size_hints)(struct view *self);
|
||||
/* if not implemented, VIEW_WANTS_FOCUS_ALWAYS is assumed */
|
||||
enum view_wants_focus (*wants_focus)(struct view *self);
|
||||
void (*offer_focus)(struct view *self);
|
||||
};
|
||||
|
||||
struct view {
|
||||
|
|
@ -320,6 +321,8 @@ view_is_focusable(struct view *view) {
|
|||
return view_is_focusable_from(view, NULL);
|
||||
}
|
||||
|
||||
void view_offer_focus(struct view *view);
|
||||
|
||||
void view_toggle_keybinds(struct view *view);
|
||||
|
||||
void view_set_activated(struct view *view, bool activated);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ struct xwayland_view {
|
|||
struct wl_listener set_decorations;
|
||||
struct wl_listener set_override_redirect;
|
||||
struct wl_listener set_strut_partial;
|
||||
struct wl_listener focus_in;
|
||||
|
||||
/* Not (yet) implemented */
|
||||
/* struct wl_listener set_role; */
|
||||
|
|
|
|||
|
|
@ -67,16 +67,19 @@ 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 = &view->server->seat;
|
||||
if (view->surface != seat->seat->keyboard_state.focused_surface) {
|
||||
seat_focus_surface(seat, view->surface);
|
||||
switch (view_wants_focus(view)) {
|
||||
case VIEW_WANTS_FOCUS_ALWAYS:
|
||||
; /* works around "a label can only be part of a statement" */
|
||||
struct seat *seat = &view->server->seat;
|
||||
if (view->surface != seat->seat->keyboard_state.focused_surface) {
|
||||
seat_focus_surface(seat, view->surface);
|
||||
}
|
||||
break;
|
||||
case VIEW_WANTS_FOCUS_OFFER:
|
||||
view_offer_focus(view);
|
||||
break;
|
||||
case VIEW_WANTS_FOCUS_NEVER:
|
||||
break;
|
||||
}
|
||||
|
||||
if (raise) {
|
||||
|
|
|
|||
|
|
@ -178,6 +178,15 @@ view_is_focusable_from(struct view *view, struct wlr_surface *prev)
|
|||
&& prev && view_is_related(view, prev)));
|
||||
}
|
||||
|
||||
void
|
||||
view_offer_focus(struct view *view)
|
||||
{
|
||||
assert(view);
|
||||
if (view->impl->offer_focus) {
|
||||
view->impl->offer_focus(view);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All view_apply_xxx_geometry() functions must *not* modify
|
||||
* any state besides repositioning or resizing the view.
|
||||
|
|
|
|||
|
|
@ -100,6 +100,12 @@ xwayland_view_wants_focus(struct view *view)
|
|||
return VIEW_WANTS_FOCUS_NEVER;
|
||||
}
|
||||
|
||||
static void
|
||||
xwayland_view_offer_focus(struct view *view)
|
||||
{
|
||||
wlr_xwayland_surface_offer_focus(xwayland_surface_from_view(view));
|
||||
}
|
||||
|
||||
static struct wlr_xwayland_surface *
|
||||
top_parent_of(struct view *view)
|
||||
{
|
||||
|
|
@ -280,6 +286,7 @@ handle_destroy(struct wl_listener *listener, void *data)
|
|||
wl_list_remove(&xwayland_view->set_decorations.link);
|
||||
wl_list_remove(&xwayland_view->set_override_redirect.link);
|
||||
wl_list_remove(&xwayland_view->set_strut_partial.link);
|
||||
wl_list_remove(&xwayland_view->focus_in.link);
|
||||
|
||||
view_destroy(view);
|
||||
}
|
||||
|
|
@ -467,6 +474,18 @@ handle_set_strut_partial(struct wl_listener *listener, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_focus_in(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct xwayland_view *xwayland_view =
|
||||
wl_container_of(listener, xwayland_view, focus_in);
|
||||
struct view *view = &xwayland_view->base;
|
||||
struct seat *seat = &view->server->seat;
|
||||
if (view->surface != seat->seat->keyboard_state.focused_surface) {
|
||||
seat_focus_surface(seat, view->surface);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_initial_position(struct view *view,
|
||||
struct wlr_xwayland_surface *xwayland_surface)
|
||||
|
|
@ -790,6 +809,7 @@ static const struct view_impl xwayland_view_impl = {
|
|||
.is_related = xwayland_view_is_related,
|
||||
.get_size_hints = xwayland_view_get_size_hints,
|
||||
.wants_focus = xwayland_view_wants_focus,
|
||||
.offer_focus = xwayland_view_offer_focus,
|
||||
};
|
||||
|
||||
void
|
||||
|
|
@ -834,6 +854,7 @@ xwayland_view_create(struct server *server,
|
|||
CONNECT_SIGNAL(xsurface, xwayland_view, set_decorations);
|
||||
CONNECT_SIGNAL(xsurface, xwayland_view, set_override_redirect);
|
||||
CONNECT_SIGNAL(xsurface, xwayland_view, set_strut_partial);
|
||||
CONNECT_SIGNAL(xsurface, xwayland_view, focus_in);
|
||||
|
||||
wl_list_insert(&view->server->views, &view->link);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue