mirror of
https://github.com/labwc/labwc.git
synced 2025-11-02 09:01:47 -05:00
xwayland: 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. v2: add caution not to use view_offer_focus() directly v3: remove obsolete comment
This commit is contained in:
parent
95552c261d
commit
c00baa1651
5 changed files with 51 additions and 15 deletions
|
|
@ -77,16 +77,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) {
|
||||
|
|
|
|||
|
|
@ -388,6 +388,15 @@ view_is_focusable(struct view *view)
|
|||
return (view->mapped || view->minimized);
|
||||
}
|
||||
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -94,11 +94,6 @@ xwayland_view_wants_focus(struct view *view)
|
|||
* Globally Active client windows may receive a WM_TAKE_FOCUS
|
||||
* message from the window manager. If they want the focus, they
|
||||
* should respond with a SetInputFocus request.
|
||||
*
|
||||
* [Currently, labwc does not fully support clients voluntarily
|
||||
* taking focus via the WM_TAKE_FOCUS + SetInputFocus mechanism.
|
||||
* Instead, we try to guess whether the window wants focus based
|
||||
* on some heuristics -- see below.]
|
||||
*/
|
||||
case WLR_ICCCM_INPUT_MODEL_GLOBAL:
|
||||
/*
|
||||
|
|
@ -135,6 +130,12 @@ xwayland_view_has_strut_partial(struct view *view)
|
|||
return (bool)xsurface->strut_partial;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
@ -331,6 +332,7 @@ handle_destroy(struct wl_listener *listener, void *data)
|
|||
wl_list_remove(&xwayland_view->set_override_redirect.link);
|
||||
wl_list_remove(&xwayland_view->set_strut_partial.link);
|
||||
wl_list_remove(&xwayland_view->set_window_type.link);
|
||||
wl_list_remove(&xwayland_view->focus_in.link);
|
||||
wl_list_remove(&xwayland_view->map_request.link);
|
||||
|
||||
view_destroy(view);
|
||||
|
|
@ -559,6 +561,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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the initial geometry of maximized/fullscreen views before
|
||||
* actually mapping them, so that they can do their initial layout and
|
||||
|
|
@ -916,6 +930,7 @@ static const struct view_impl xwayland_view_impl = {
|
|||
.append_children = xwayland_view_append_children,
|
||||
.get_size_hints = xwayland_view_get_size_hints,
|
||||
.wants_focus = xwayland_view_wants_focus,
|
||||
.offer_focus = xwayland_view_offer_focus,
|
||||
.has_strut_partial = xwayland_view_has_strut_partial,
|
||||
.contains_window_type = xwayland_view_contains_window_type,
|
||||
.get_pid = xwayland_view_get_pid,
|
||||
|
|
@ -964,6 +979,7 @@ xwayland_view_create(struct server *server,
|
|||
CONNECT_SIGNAL(xsurface, xwayland_view, set_override_redirect);
|
||||
CONNECT_SIGNAL(xsurface, xwayland_view, set_strut_partial);
|
||||
CONNECT_SIGNAL(xsurface, xwayland_view, set_window_type);
|
||||
CONNECT_SIGNAL(xsurface, xwayland_view, focus_in);
|
||||
CONNECT_SIGNAL(xsurface, xwayland_view, map_request);
|
||||
|
||||
view_init(view);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue