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);
|
struct view_size_hints (*get_size_hints)(struct view *self);
|
||||||
/* if not implemented, VIEW_WANTS_FOCUS_ALWAYS is assumed */
|
/* if not implemented, VIEW_WANTS_FOCUS_ALWAYS is assumed */
|
||||||
enum view_wants_focus (*wants_focus)(struct view *self);
|
enum view_wants_focus (*wants_focus)(struct view *self);
|
||||||
|
void (*offer_focus)(struct view *self);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct view {
|
struct view {
|
||||||
|
|
@ -320,6 +321,8 @@ view_is_focusable(struct view *view) {
|
||||||
return view_is_focusable_from(view, NULL);
|
return view_is_focusable_from(view, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void view_offer_focus(struct view *view);
|
||||||
|
|
||||||
void view_toggle_keybinds(struct view *view);
|
void view_toggle_keybinds(struct view *view);
|
||||||
|
|
||||||
void view_set_activated(struct view *view, bool activated);
|
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_decorations;
|
||||||
struct wl_listener set_override_redirect;
|
struct wl_listener set_override_redirect;
|
||||||
struct wl_listener set_strut_partial;
|
struct wl_listener set_strut_partial;
|
||||||
|
struct wl_listener focus_in;
|
||||||
|
|
||||||
/* Not (yet) implemented */
|
/* Not (yet) implemented */
|
||||||
/* struct wl_listener set_role; */
|
/* struct wl_listener set_role; */
|
||||||
|
|
|
||||||
|
|
@ -67,17 +67,20 @@ desktop_focus_view(struct view *view, bool raise)
|
||||||
workspaces_switch_to(view->workspace, /*update_focus*/ false);
|
workspaces_switch_to(view->workspace, /*update_focus*/ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
switch (view_wants_focus(view)) {
|
||||||
* Give input focus, even if the view claims not to want it (see
|
case VIEW_WANTS_FOCUS_ALWAYS:
|
||||||
* view->impl->wants_focus). This is a workaround for so-called
|
; /* works around "a label can only be part of a statement" */
|
||||||
* "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;
|
struct seat *seat = &view->server->seat;
|
||||||
if (view->surface != seat->seat->keyboard_state.focused_surface) {
|
if (view->surface != seat->seat->keyboard_state.focused_surface) {
|
||||||
seat_focus_surface(seat, view->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) {
|
if (raise) {
|
||||||
view_move_to_front(view);
|
view_move_to_front(view);
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,15 @@ view_is_focusable_from(struct view *view, struct wlr_surface *prev)
|
||||||
&& prev && view_is_related(view, 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
|
* All view_apply_xxx_geometry() functions must *not* modify
|
||||||
* any state besides repositioning or resizing the view.
|
* any state besides repositioning or resizing the view.
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,12 @@ xwayland_view_wants_focus(struct view *view)
|
||||||
return VIEW_WANTS_FOCUS_NEVER;
|
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 *
|
static struct wlr_xwayland_surface *
|
||||||
top_parent_of(struct view *view)
|
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_decorations.link);
|
||||||
wl_list_remove(&xwayland_view->set_override_redirect.link);
|
wl_list_remove(&xwayland_view->set_override_redirect.link);
|
||||||
wl_list_remove(&xwayland_view->set_strut_partial.link);
|
wl_list_remove(&xwayland_view->set_strut_partial.link);
|
||||||
|
wl_list_remove(&xwayland_view->focus_in.link);
|
||||||
|
|
||||||
view_destroy(view);
|
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
|
static void
|
||||||
set_initial_position(struct view *view,
|
set_initial_position(struct view *view,
|
||||||
struct wlr_xwayland_surface *xwayland_surface)
|
struct wlr_xwayland_surface *xwayland_surface)
|
||||||
|
|
@ -790,6 +809,7 @@ static const struct view_impl xwayland_view_impl = {
|
||||||
.is_related = xwayland_view_is_related,
|
.is_related = xwayland_view_is_related,
|
||||||
.get_size_hints = xwayland_view_get_size_hints,
|
.get_size_hints = xwayland_view_get_size_hints,
|
||||||
.wants_focus = xwayland_view_wants_focus,
|
.wants_focus = xwayland_view_wants_focus,
|
||||||
|
.offer_focus = xwayland_view_offer_focus,
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -834,6 +854,7 @@ xwayland_view_create(struct server *server,
|
||||||
CONNECT_SIGNAL(xsurface, xwayland_view, set_decorations);
|
CONNECT_SIGNAL(xsurface, xwayland_view, set_decorations);
|
||||||
CONNECT_SIGNAL(xsurface, xwayland_view, set_override_redirect);
|
CONNECT_SIGNAL(xsurface, xwayland_view, set_override_redirect);
|
||||||
CONNECT_SIGNAL(xsurface, xwayland_view, set_strut_partial);
|
CONNECT_SIGNAL(xsurface, xwayland_view, set_strut_partial);
|
||||||
|
CONNECT_SIGNAL(xsurface, xwayland_view, focus_in);
|
||||||
|
|
||||||
wl_list_insert(&view->server->views, &view->link);
|
wl_list_insert(&view->server->views, &view->link);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue