reintroduce xwayland is_unmanaged

153f37bdf5 (#1145) removed the
wlr_xwayland_is_unamanged function while fixing OR, because it was
belieived that it's supposed to work around the broken OR handling.

This was a misunderstanding. is_unmanaged is (while sort of a hack)
intended to work around inherent differences between "real" X sessions
and our Xwayland/wayland situation.

The main reason it exists is to support applications like rofi and dzen,
while not handing focus to other OR windows (which should *not* be
required).
Traditionally, these applications just grabbed input from X and didn't
need to be focused by any logic in the WM. Which of course doesn't work
in wayland compositors. So we have to give them focus in some way.
Giving *every* OR window focus, breaks other applications that don't
expect focus to change.

A testcase that was pointed out to me where wlr_xwayland_is_unamanged was
breaking things is https://github.com/swaywm/sway/issues/2128 (syncplay,
gitk, gitgui)
Supposedly it broke using keyboard to navigate the menus.
I can't reproduce this with this patch. The popups can be navigated as
long as the parent has focus.
This commit is contained in:
Markus Ongyerth 2018-07-29 11:20:16 +02:00
parent f1b65b34a6
commit 81cc842f8f
3 changed files with 51 additions and 1 deletions

View file

@ -209,4 +209,29 @@ struct wlr_xwayland_surface *wlr_xwayland_surface_from_wlr_surface(
void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface);
/** Metric to guess if an OR window should "receive" focus
*
* In the pure X setups, window managers usually straight up ignore override
* redirect windows, and never touch them. (we have to handle them for mapping)
*
* When such a window wants to receive keyboard input (e.g. rofi/dzen) it will
* use mechanics we don't support (sniffing/grabbing input).
* [Sadly this is unrelated to xwayland-keyboard-grab]
*
* To still support these windows, while keeping general OR semantics as is, we
* need to hand a subset of windows focus.
* The dirty truth is, we need to hand focus to any Xwayland window, though
* pretending this window has focus makes it easier to handle unmap.
*
* This function provides a handy metric based on the window type to guess if
* the OR window wants focus.
* It's probably not perfect, nor exactly intended but works in practice.
*
* Returns: true if the window should receive focus
* false if it should be ignored
*/
bool wlr_xwayland_or_surface_wants_focus(
const struct wlr_xwayland_surface *surface);
#endif

View file

@ -1124,7 +1124,8 @@ void roots_seat_set_focus(struct roots_seat *seat, struct roots_view *view) {
#ifdef WLR_HAS_XWAYLAND
if (view && view->type == ROOTS_XWAYLAND_VIEW &&
view->xwayland_surface->override_redirect) {
!wlr_xwayland_or_surface_wants_focus(
view->xwayland_surface)) {
return;
}
#endif

View file

@ -1703,3 +1703,27 @@ void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface) {
surface->xwm->ping_timeout);
surface->pinging = true;
}
bool wlr_xwayland_or_surface_wants_focus(
const struct wlr_xwayland_surface *surface) {
bool ret = true;
static enum atom_name needles[] = {
NET_WM_WINDOW_TYPE_COMBO,
NET_WM_WINDOW_TYPE_DND,
NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
NET_WM_WINDOW_TYPE_MENU,
NET_WM_WINDOW_TYPE_NOTIFICATION,
NET_WM_WINDOW_TYPE_POPUP_MENU,
NET_WM_WINDOW_TYPE_SPLASH,
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;
}
}
return ret;
}