From d6649a8a4ba19fda25fe8607bc62acea8acb5fed Mon Sep 17 00:00:00 2001 From: BrassyPanache Date: Wed, 13 Jan 2021 01:10:38 +1100 Subject: [PATCH] Expose ICCCM input status In certain situations windows can have their input field set to false but still expect to receive input focus by passively listening to key presses via a parent window. The ICCCM specification outlines how focus should be given to clients. Further reading: https://tronche.com/gui/x/icccm/sec-4.html#s-4.1.7 Relates to #2604 --- include/wlr/xwayland.h | 17 ++++++++++++++++- xwayland/xwm.c | 32 ++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index fd14ff25..7dcb3935 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -119,6 +119,18 @@ struct wlr_xwayland_surface_size_hints { uint32_t win_gravity; }; +/** + * This represents the input focus described as follows: + * + * https://www.x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html#input_focus + */ +enum wlr_xwayland_icccm_input_model { + WLR_ICCCM_INPUT_MODEL_NONE = 0, + WLR_ICCCM_INPUT_MODEL_PASSIVE = 1, + WLR_ICCCM_INPUT_MODEL_LOCAL = 2, + WLR_ICCCM_INPUT_MODEL_GLOBAL = 3, +}; + /** * An Xwayland user interface component. It has an absolute position in * layout-local coordinates. @@ -303,7 +315,10 @@ void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface); * false if it should be ignored */ bool wlr_xwayland_or_surface_wants_focus( - const struct wlr_xwayland_surface *surface); + const struct wlr_xwayland_surface *xsurface); + +enum wlr_xwayland_icccm_input_model wlr_xwayland_icccm_input_model( + const struct wlr_xwayland_surface *xsurface); #endif diff --git a/xwayland/xwm.c b/xwayland/xwm.c index a80a2ec6..10424f47 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -579,6 +579,7 @@ static void read_surface_hints(struct wlr_xwm *xwm, if (xsurface->hints == NULL) { return; } + memcpy(xsurface->hints, &hints, sizeof(struct wlr_xwayland_surface_hints)); xsurface->hints_urgency = xcb_icccm_wm_hints_get_urgency(&hints); @@ -1967,8 +1968,7 @@ void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface) { } bool wlr_xwayland_or_surface_wants_focus( - const struct wlr_xwayland_surface *surface) { - bool ret = true; + const struct wlr_xwayland_surface *xsurface) { static enum atom_name needles[] = { NET_WM_WINDOW_TYPE_COMBO, NET_WM_WINDOW_TYPE_DND, @@ -1980,12 +1980,32 @@ bool wlr_xwayland_or_surface_wants_focus( NET_WM_WINDOW_TYPE_TOOLTIP, NET_WM_WINDOW_TYPE_UTILITY, }; + for (size_t i = 0; i < sizeof(needles) / sizeof(needles[0]); ++i) { - if (xwm_atoms_contains(surface->xwm, surface->window_type, - surface->window_type_len, needles[i])) { - ret = false; + if (xwm_atoms_contains(xsurface->xwm, xsurface->window_type, + xsurface->window_type_len, needles[i])) { + return false; } } - return ret; + return true; +} + +enum wlr_xwayland_icccm_input_model wlr_xwayland_icccm_input_model( + const struct wlr_xwayland_surface *xsurface) { + bool take_focus = xwm_atoms_contains(xsurface->xwm, + xsurface->protocols, xsurface->protocols_len, + WM_TAKE_FOCUS); + + if (xsurface->hints && xsurface->hints->input) { + if (take_focus) { + return WLR_ICCCM_INPUT_MODEL_LOCAL; + } + return WLR_ICCCM_INPUT_MODEL_PASSIVE; + } else { + if (take_focus) { + return WLR_ICCCM_INPUT_MODEL_GLOBAL; + } + } + return WLR_ICCCM_INPUT_MODEL_NONE; }