From 13d1e26d696c5113a20dfc2f56c03ddb837a2eac Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 12 Jul 2021 09:46:25 +1000 Subject: Check for Xwayland and print a warning Running setxkbmap isn't supported by Xwayland, so let's warn the user that this won't work. Signed-off-by: Peter Hutterer Acked-by: Olivier Fourdan --- configure.ac | 3 ++- man/setxkbmap.man | 12 ++++++++++++ setxkbmap.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d5733ff..9b475d3 100644 --- a/configure.ac +++ b/configure.ac @@ -47,7 +47,8 @@ AC_ARG_WITH(xkb-config-root, AC_SUBST([XKBCONFIGROOT]) # Checks for pkg-config packages -PKG_CHECK_MODULES(SETXKBMAP, xkbfile x11) +# xrandr is needed for the XWayland check +PKG_CHECK_MODULES(SETXKBMAP, xkbfile x11 xrandr) # Allow checking code with lint, sparse, etc. XORG_WITH_LINT diff --git a/man/setxkbmap.man b/man/setxkbmap.man index 926b6f7..d02f25f 100644 --- a/man/setxkbmap.man +++ b/man/setxkbmap.man @@ -138,6 +138,18 @@ directly to the \fBxkbcomp\fP input. For example, the command makes both steps run on the same (client) machine and loads a keyboard map into the server. + +.SH "XWAYLAND" +Xwayland is an X server that uses a Wayland Compositor as backend. +Xwayland acts as translation layer between the X protocol and the Wayland +protocol but does not manage the keymaps - these are handled by the Wayland +Compositor. +.PP +Changing the keymap with \fBsetxkbmap\fP is not supported by Xwayland. +In most instances, using \fBsetxkbmap\fP on Xwayland is indicative of a +bug in a shell script and \fBsetxkbmap\fP will print a warning. Use the Wayland +Compositor's native XKB configuration methods instead. + .SH SEE ALSO xkbcomp(__appmansuffix__), xkeyboard-config(__miscmansuffix__) .SH FILES diff --git a/setxkbmap.c b/setxkbmap.c index 3af641e..68eb9a6 100644 --- a/setxkbmap.c +++ b/setxkbmap.c @@ -38,6 +38,7 @@ #include #include #include +#include #ifndef PATH_MAX #ifdef MAXPATHLEN @@ -1067,12 +1068,59 @@ applyComponentNames(void) return True; } +static Bool +is_xwayland(void) +{ + /* Code copied from xisxwayland.c */ + Bool rc = False; + XRRScreenResources *resources = NULL; + XRROutputInfo *output = NULL; + + /* There is no definitive way of checking for an XWayland server, + * but the two working methods are: + * - RandR output names in Xwayland are XWAYLAND0, XWAYLAND1, etc. + * - XI devices are xwayland-pointer:10, xwayland-keyboard:11 + * Let's go with the XRandR check here because it's slightly less + * code to write. + */ + + int event_base, error_base, major, minor; + if (!XRRQueryExtension(dpy, &event_base, &error_base) || + !XRRQueryVersion(dpy, &major, &minor)) { + /* e.g. Xnest, but definitely not Xwayland */ + goto out; + } + + resources = XRRGetScreenResourcesCurrent(dpy, DefaultRootWindow(dpy)); + if (!resources) { + goto out; + } + + output = XRRGetOutputInfo(dpy, resources, resources->outputs[0]); + if (!output) { + goto out; + } + + if (strncmp(output->name, "XWAYLAND", 8) == 0) + rc = True; + + XRRFreeOutputInfo(output); +out: + if (resources) + XRRFreeScreenResources(resources); + + return rc; +} int main(int argc, char **argv) { if ((!parseArgs(argc, argv)) || (!getDisplay(argc, argv))) exit(-1); + + if (is_xwayland()) + MSG("WARNING: Running setxkbmap against an XWayland server\n"); + settings.locale.value = setlocale(LC_ALL, settings.locale.value); settings.locale.src = FROM_SERVER; VMSG1(7, "locale is %s\n", settings.locale.value); -- cgit v1.2.3