swaywm / sway

i3-compatible Wayland compositor
https://swaywm.org
MIT License
14.56k stars 1.11k forks source link

xkb_file setting does not apply to XWayland windows #5461

Open CRCulver opened 4 years ago

CRCulver commented 4 years ago

The xkb_file setting was introduced to close bug #3999, by which a user had reported that he was unable to load a keyboard map created as the output of xkbcomp. While setting xkb_file does make such a keyboard map apply to Wayland applications, input in XWayland windows still does not respect this keyboard map.

The xkb_file setting should ensure that the same keyboard map is applied to input in both Wayland applications and XWayland windows.

emersion commented 4 years ago

Your bug report is missing debug logs. Please add a link to the full debug log file.

emersion commented 4 years ago

Also attach your xkb_file source, please

CRCulver commented 4 years ago

I attach both here. sway.log and (renamed so that Github will accept it as an upload) xkb.dump.txt

The log describes launching a Sway session, opening Alacritty and typing into it (my xkb_file settings are applied correctly), then launching XWayland-based Emacs and Firefox (the xkb_file settings are not applied), and finally closing the session.

I see that in the past Firefox and Sway have not played together nicely, and the fault was on Firefox’s side. However, another application where the xkb_file setting fails to apply is urxvt, so I can confirm this is an issue with XWayland windows generally. (If requested, I can upload a new log in which urxvt is opened.)

isti115 commented 4 years ago

Hmm, I have just solved my issue of not being able to remap some keys, because they were defined in the inet(evdev) file by creating a custom xkb_keymap and overriding the precedence, and for me it works just fine in xwayland windows. (I've tested it in firefox and urxvt as well, also checked them using xeyes just to be sure.)

evelineraine commented 4 years ago

I had the same issue when my custom keymap (specified using xkb_file) worked in Wayland-native apps, like Alacritty, but not in XWayland apps, like Emacs.

keymap-file:

xkb_keymap {
    xkb_keycodes { include "evdev+foo"                };
    xkb_types    { include "complete"                 };
    xkb_compat   { include "complete"                 };
    xkb_symbols  { include "pc+inet(evdev)+us+raine"  };
    xkb_geometry { include "macintosh(macbook78)"     };
};

I discovered that was due to a weird error in my symbols/raine file. Sway ignored the error, but XWayland didn't load the keymap because of it.

I run xkbcomp -xkb -I$HOME/.config/xkb <keymap-file> to discover the error message.

When I fixed the error, my keymap works under XWayland apps too.

@CRCulver, I compiled your keymap file - I only see warnings, no errors. Are there no errors on your machine? Perhaps, you could try with a basic xkb_keymap like this and see if the Tilde key produces F in both Wayland & XWayland:

xkb_keymap {
    xkb_keycodes { include "evdev"                    };
    xkb_types    { include "complete"                 };
    xkb_compat   { include "complete"                 };
    xkb_geometry { include "pc(pc105)"                };
        xkb_symbols  { 
                include "pc+inet(evdev)+us"
                key <TLDE> { [ F ] };  
        };
};
zackw commented 3 years ago

I am having the same problem. In my case, the xkb file is completely written from scratch and has no inclusions. xkbcomp -xkb pbp-qwerty-nofn.xkb gives no errors or warnings.

The problem is most easily visible by comparing the behavior of xkbcli interactive-wayland with the behavior of xkbcli interactive-x11, e.g. upon pressing up-arrow and then Fn+up-arrow in each program I get

$ xkbcli interactive-wayland   # desired behavior
seat0: keysyms [ Up               ] unicode [  ] layout [ (null) (0) ] level [ 0 ] mods [ ] leds [ ] 
seat0: keysyms [ Super_L          ] unicode [  ] layout [ (null) (0) ] level [ 0 ] mods [ ] leds [ ] 
seat0: keysyms [ Prior            ] unicode [  ] layout [ (null) (0) ] level [ 1 ] mods [ -Mod3 ] leds [ ] 
seat0: keysyms [ Escape           ] unicode [  layout [ (null) (0) ] level [ 0 ] mods [ ] leds [ ] 

$ xkbcli interactive-x11  # incorrect, appears to be generic xkb_layout "us" behavior
keysyms [ Up               ] unicode [  ] layout [ English (US) (0) ] level [ 0 ] mods [ ] leds [ ] 
keysyms [ Super_R          ] unicode [  ] layout [ English (US) (0) ] level [ 0 ] mods [ ] leds [ ] 
keysyms [ Up               ] unicode [  ] layout [ English (US) (0) ] level [ 0 ] mods [ Mod3 ] leds [ ] 
keysyms [ Escape           ] unicode [  layout [ English (US) (0) ] level [ 0 ] mods [ ] leds [ ] 

In case it matters, this is the input specification:

# Generic choice for e.g. external USB keyboards
input type:keyboard {
    xkb_layout "us"
    xkb_options "caps:ctrl_modifier,altwin:meta_alt,altwin:hyper_win,compose:ralt"
}

# Custom configuration for the built-in keyboard
input 9610:30:Pine64_Pinebook_Pro {
    xkb_file "/usr/local/share/keymaps/pbp-qwerty-nofn.xkb"
}

I tried removing the "generic choice" block and applying pbp-qwerty-nofn.xkb to all type:keyboard inputs but this made no difference.

pbp-qwerty-nofn.xkb

zackw commented 3 years ago

sway-debug.log

This log covers: started up a fresh session of sway -d, opened a shell window, ran xkbcli interactive-wayland and xkbcli interactive-x11 as described in my previous message, quit. xkb_file "/usr/local/share/keymaps/pbp-qwerty-nofn.xkb" was applied to all input type:keyboard.

I'm using sway 1.5.1.

zackw commented 3 years ago

Update: With sway 1.6, I do get a flood of xkbcomp-related messages. These are supposedly warnings, but...

[INFO] [wlr] [xwayland/server.c:99] WAYLAND_SOCKET=35 Xwayland :0 -rootless -terminate -core -listenfd 33 -listenfd 34 -wm 86
glamor: No eglstream capable devices found
The XKEYBOARD keymap compiler (xkbcomp) reports:
> Warning: Could not resolve keysym XF8610ChannelsDown
> Warning: Could not resolve keysym XF8610ChannelsUp
> Warning: Could not resolve keysym XF863DMode
> Warning: Could not resolve keysym XF86ALSToggle
> Warning: Could not resolve keysym XF86Addressbook
> Warning: Could not resolve keysym XF86AppSelect
> Warning: Could not resolve keysym XF86AspectRatio
> Warning: Could not resolve keysym XF86Assistant
> Warning: Could not resolve keysym XF86AttendantOff
> Warning: Could not resolve keysym XF86AttendantOn
> Warning: Could not resolve keysym XF86AttendantToggle
> Warning: Could not resolve keysym XF86Audio
> Warning: Could not resolve keysym XF86AudioDesc
> Warning: Could not resolve keysym XF86Break
> Warning: Could not resolve keysym XF86BrightnessAuto
> Warning: Could not resolve keysym XF86BrightnessMax
> Warning: Could not resolve keysym XF86BrightnessMin
> Warning: Could not resolve keysym XF86Buttonconfig
> Warning: Could not resolve keysym XF86CameraDown
> Warning: Could not resolve keysym XF86CameraFocus
> Warning: Could not resolve keysym XF86CameraLeft
> Warning: Could not resolve keysym XF86CameraRight
> Warning: Could not resolve keysym XF86CameraUp
> Warning: Could not resolve keysym XF86CameraZoomIn
> Warning: Could not resolve keysym XF86CameraZoomOut
> Warning: Could not resolve keysym XF86ChannelDown
> Warning: Could not resolve keysym XF86ChannelUp
> Warning: Could not resolve keysym XF86ContextMenu
> Warning: Could not resolve keysym XF86ControlPanel
> Warning: Could not resolve keysym XF86DVD
> Warning: Could not resolve keysym XF86Data
> Warning: Could not resolve keysym XF86Database
> Warning: Could not resolve keysym XF86DisplayOff
> Warning: Could not resolve keysym XF86DisplayToggle
> Warning: Could not resolve keysym XF86Editor
> Warning: Could not resolve keysym XF86FastReverse
> Warning: Could not resolve keysym XF86Fn
> Warning: Could not resolve keysym XF86FnRightShift
> Warning: Could not resolve keysym XF86Fn_Esc
> Warning: Could not resolve keysym XF86GraphicsEditor
> Warning: Could not resolve keysym XF86HangupPhone
> Warning: Could not resolve keysym XF86Images
> Warning: Could not resolve keysym XF86Info
> Warning: Could not resolve keysym XF86Journal
> Warning: Could not resolve keysym XF86KbdInputAssistAccept
> Warning: Could not resolve keysym XF86KbdInputAssistCancel
> Warning: Could not resolve keysym XF86KbdInputAssistNext
> Warning: Could not resolve keysym XF86KbdInputAssistNextgroup
> Warning: Could not resolve keysym XF86KbdInputAssistPrev
> Warning: Could not resolve keysym XF86KbdInputAssistPrevgroup
> Warning: Could not resolve keysym XF86KbdLcdMenu1
> Warning: Could not resolve keysym XF86KbdLcdMenu2
> Warning: Could not resolve keysym XF86KbdLcdMenu3
> Warning: Could not resolve keysym XF86KbdLcdMenu4
> Warning: Could not resolve keysym XF86KbdLcdMenu5
> Warning: Could not resolve keysym XF86LeftDown
> Warning: Could not resolve keysym XF86LeftUp
> Warning: Could not resolve keysym XF86LightsToggle
> Warning: Could not resolve keysym XF86Macro1
> Warning: Could not resolve keysym XF86Macro2
> Warning: Could not resolve keysym XF86Macro3
> Warning: Could not resolve keysym XF86Macro4
> Warning: Could not resolve keysym XF86Macro5
> Warning: Could not resolve keysym XF86Macro6
> Warning: Could not resolve keysym XF86Macro7
> Warning: Could not resolve keysym XF86Macro8
> Warning: Could not resolve keysym XF86Macro9
> Warning: Could not resolve keysym XF86Macro10
> Warning: Could not resolve keysym XF86Macro11
> Warning: Could not resolve keysym XF86Macro12
> Warning: Could not resolve keysym XF86Macro13
> Warning: Could not resolve keysym XF86Macro14
> Warning: Could not resolve keysym XF86Macro15
> Warning: Could not resolve keysym XF86Macro16
> Warning: Could not resolve keysym XF86Macro17
> Warning: Could not resolve keysym XF86Macro18
> Warning: Could not resolve keysym XF86Macro19
> Warning: Could not resolve keysym XF86Macro20
> Warning: Could not resolve keysym XF86Macro21
> Warning: Could not resolve keysym XF86Macro22
> Warning: Could not resolve keysym XF86Macro23
> Warning: Could not resolve keysym XF86Macro24
> Warning: Could not resolve keysym XF86Macro25
> Warning: Could not resolve keysym XF86Macro26
> Warning: Could not resolve keysym XF86Macro27
> Warning: Could not resolve keysym XF86Macro28
> Warning: Could not resolve keysym XF86Macro29
> Warning: Could not resolve keysym XF86Macro30
> Warning: Could not resolve keysym XF86MacroPreset1
> Warning: Could not resolve keysym XF86MacroPreset2
> Warning: Could not resolve keysym XF86MacroPreset3
> Warning: Could not resolve keysym XF86MacroPresetCycle
> Warning: Could not resolve keysym XF86MacroRecordStart
> Warning: Could not resolve keysym XF86MacroRecordStop
> Warning: Could not resolve keysym XF86MediaRepeat
> Warning: Could not resolve keysym XF86MediaTopMenu
> Warning: Could not resolve keysym XF86NextFavorite
> Warning: Could not resolve keysym XF86NotificationCenter
> Warning: Could not resolve keysym XF86Numeric0
> Warning: Could not resolve keysym XF86Numeric1
> Warning: Could not resolve keysym XF86Numeric2
> Warning: Could not resolve keysym XF86Numeric3
> Warning: Could not resolve keysym XF86Numeric4
> Warning: Could not resolve keysym XF86Numeric5
> Warning: Could not resolve keysym XF86Numeric6
> Warning: Could not resolve keysym XF86Numeric7
> Warning: Could not resolve keysym XF86Numeric8
> Warning: Could not resolve keysym XF86Numeric9
> Warning: Could not resolve keysym XF86Numeric11
> Warning: Could not resolve keysym XF86Numeric12
> Warning: Could not resolve keysym XF86NumericA
> Warning: Could not resolve keysym XF86NumericB
> Warning: Could not resolve keysym XF86NumericC
> Warning: Could not resolve keysym XF86NumericD
> Warning: Could not resolve keysym XF86NumericPound
> Warning: Could not resolve keysym XF86NumericStar
> Warning: Could not resolve keysym XF86OnScreenKeyboard
> Warning: Could not resolve keysym XF86PauseRecord
> Warning: Could not resolve keysym XF86PickupPhone
> Warning: Could not resolve keysym XF86Presentation
> Warning: Could not resolve keysym XF86PrivacyScreenToggle
> Warning: Could not resolve keysym XF86RightDown
> Warning: Could not resolve keysym XF86RightUp
> Warning: Could not resolve keysym XF86RootMenu
> Warning: Could not resolve keysym XF86Screensaver
> Warning: Could not resolve keysym XF86SelectiveScreenshot
> Warning: Could not resolve keysym XF86SlowReverse
> Warning: Could not resolve keysym XF86SpellCheck
> Warning: Could not resolve keysym XF86StopRecord
> Warning: Could not resolve keysym XF86Taskmanager
> Warning: Could not resolve keysym XF86Unmute
> Warning: Could not resolve keysym XF86VOD
> Warning: Could not resolve keysym XF86VideoPhone
> Warning: Could not resolve keysym XF86VoiceCommand
> Warning: Could not resolve keysym XF86Voicemail
> Warning: Could not resolve keysym XF86WPSButton
> Warning: Could not resolve keysym XF86ZoomReset
Errors from xkbcomp are not fatal to the X server

Only four of these keysyms appear in my .xkb file.

    key <FK03> { [              F3,      XF86AudioMicMute,  XF86Switch_VT_3 ] };
    key <FK04> { [              F4,         XF86AudioMute,  XF86Switch_VT_4 ] };
    key <FK05> { [              F5,  XF86AudioLowerVolume,  XF86Switch_VT_5 ] };
    key <FK06> { [              F6,  XF86AudioRaiseVolume,  XF86Switch_VT_6 ] };

Running xkbcomp -w 10 -xkm /path/to/pbp-qwerty-nofn.xkb does not produce any errors, so the invocation must be different somehow when Xwayland runs xkbcomp.

I'd really appreciate advice on how to debug this further.

zackw commented 3 years ago

Further update: I instrumented the xkbcomp executable to log its command line. This revealed that Xwayland is using -w 1 and feeding the keymap to xkbcomp on standard input. It also revealed that xkbcomp gets run three times, and that the "Could not resolve keysym" warnings are generated twice: once from the first invocation, and again from the third invocation.

The full command line for all three invocations is:

/usr/bin/xkbcomp -w 1 -R/usr/share/X11/xkb -xkm - \
    -em1 'The XKEYBOARD keymap compiler (xkbcomp) reports:' \
    -emp '> ' \
    -eml 'Errors from xkbcomp are not fatal to the X server' \
    /tmp/server-0.xkm

Then I changed the instrumentation to record what gets supplied on standard input. The first and third time, it's this:

xkb_keymap "default" {
    xkb_keycodes             { include "evdev+aliases(qwerty)" };
    xkb_types                { include "complete" };
    xkb_compatibility        { include "complete" };
    xkb_symbols              { include "pc+us+inet(evdev)" };
    xkb_geometry             { include "pc(pc105)" };
};

And the second time, it's a normalized version of the file I specified as xkb_file (functionally, but not exactly, the same as the result of running xkbcomp -xkb on that file, I think).

So that pretty clearly determines why the xkb_file setting isn't effective in Xwayland windows: the third invocation of xkbcomp overwrites the desired keymap with these defaults. The "could not resolve keysym" warnings are a red herring; they are the natural result of /usr/share/X11/xkb/symbols/inet defining code-to-sym mappings for a whole bunch of keys that don't exist.

The bug, then, is that the first and third invocations of xkbcomp are happening at all, and I'm still hunting for why.

zackw commented 3 years ago

Now I have instrumented the Xwayland executable, so it's run with WAYLAND_DEBUG=1 and -verbose 255 and dumps all the output to a dedicated logfile.

The first invocation of xkbcomp happens during server initialization, before it gets around to asking the compositor for anything related to keyboard configuration, which is not a surprise. The second and third invocations happen right after each other and right after it does query for keyboard configuration:

[3691158.642] wl_seat@18.name("seat0")
[3691158.655] wl_seat@18.capabilities(3)
[3691158.671]  -> wl_seat@18.get_pointer(new id wl_pointer@21)
[3691158.689]  -> wl_pointer@21.set_cursor(0, nil, 0, 0)
[3691158.851]  -> zwp_relative_pointer_manager_v1@16.get_relative_pointer(new id zwp_relative_pointer_v1@22, wl_pointer@21)
[3691158.950]  -> wl_seat@18.get_keyboard(new id wl_keyboard@23)
(II) XKB: Reusing cached keymap
[3691159.335] wl_callback@15.done(4481)
[3691160.771] wl_keyboard@23.keymap(1, fd 4, 12814)
xkbcomp: invoked as
> '/usr/bin/xkbcomp' '-w' '1' '-R/usr/share/X11/xkb' '-xkm' '-' '-em1' 'The XKEYBOARD keymap compiler (xkbcomp) reports:' '-emp' '> ' '-eml' 'Errors from xkbcomp are not fatal to the X server' '/tmp/server-0.xkm'
(EE) Error loading keymap /tmp/server-0.xkm
(EE) XKB: Failed to load keymap. Loading default keymap instead.
xkbcomp: invoked as
> '/usr/bin/xkbcomp' '-w' '1' '-R/usr/share/X11/xkb' '-xkm' '-' '-em1' 'The XKEYBOARD keymap compiler (xkbcomp) reports:' '-emp' '> ' '-eml' 'Errors from xkbcomp are not fatal to the X server' '/tmp/server-0.xkm'
The XKEYBOARD keymap compiler (xkbcomp) reports:
[... the above flood of complaints about keysyms that can't be resolved ...]

OK, what exactly went wrong loading the keymap? My first suspicion was that there was something wrong with Xwayland's ability to read and write files in /tmp so I changed my instrumentation to run Xwayland under strace, but that wasn't it...

9276  openat(AT_FDCWD, "/tmp/server-0.xkm", O_RDONLY) = 11
9276  fstat(11, {st_mode=S_IFREG|0644, st_size=4168, ...}) = 0
9276  read(11, "\17mkx\26\10\377\5\37\0\0\0\4\0\1\0\370\0034\0\0\0\1\0\0\1,\4\1\0\1\0"..., 4096) = 4096
9276  write(2, "(EE) Error loading keymap /tmp/s"..., 44) = 44
9276  close(11)                         = 0

This is not a case of "Xwayland can't handle xkm files that are bigger than 4096 bytes" because the "default" keymap generates a xkm file that's 12368 bytes long, and that one gets read in fully. Rather, Xwayland objects to something within the first 4096 bytes of the file.

zackw commented 3 years ago

I feel like there ought to be some way to get Xwayland to print more detail about what it thinks is wrong with the xkm file, but I have been fiddling with the command line options for ages now with no luck, and the battery's about to run out on this troublesome laptop, so I'm just going to upload all three of the xkm files that get generated (1 and 3 are not identical, despite having been generated from the same input, ugh) and maybe someone else has a clever idea?

server-0.1.xkm.gz server-0.2.xkm.gz server-0.3.xkm.gz

zackw commented 3 years ago

N.B. At this point I am 99% sure sway isn't doing anything wrong, this is Xwayland's fault, and/or my custom xkb file is somehow incorrect in a way that neither xkbcomp nor the XKB processing within sway/wlroots itself cares about, but Xwayland does.

zackw commented 3 years ago

After source-diving Xwayland a bit I have found the root problem. Since I wrote my xkb file from scratch, I didn't bother with "virtual" modifiers, assuming that I could do everything I needed with the numbered modifiers (Mod1 etc). sway/libxkbcommon are fine with this, but Xwayland rejects compiled keymaps that don't have an "XKMVirtualMods" section.

Adding virtual_modifiers lines to the "types" and "compatibility" sections of the file (and tinkering with the "interpret" directives a bit) makes Xwayland happy, and xev reports keyboard events matching xkbcli interactive-wayland. xkbcli interactive-x11 now crashes, and Emacs is still not interpreting the keyboard events precisely as I wanted, but I'll take that up with those projects.

Recommendation: document that if you're going to use xkb_file and you care about X11 clients, the file needs to pass xkbcomp -w 10 -xkm <file> with no complaints; it needs to have xkb_symbols, xkb_keycodes, xkb_types, and xkb_compatibility sections; it needs to declare at least one virtual modifier; and even then watch out for misbehavior.

ghostface commented 3 years ago

@zackw thank you for your research. Could you post a working xkb_file of yours for reference purpose please?

rpigott commented 3 years ago

Ah, yeah, I've encountered this before as well. Sway is a little more permissive in the xkb files it accepts than xwayland, and that can be very confusing.

Is there a way we can tell when xwayland rejects a keymap? Not sure if we should reject these, but would definitely be worth printing an error.

emersion commented 3 years ago

Xwayland probably prints something already?

rpigott commented 3 years ago

It might yeah, I don't remember.

isti115 commented 3 years ago

Sway is a little more permissive in the xkb files it accepts than xwayland...

Yes, I can confirm having encountered this while creating my fully custom keymap from scratch, for example one thing I found was that Sway doesn't care about the length of the identifiers, but XWayland (and proper XOrg as well if I recall correctly) refuses to accept anything longer than four characters for keys.

I was able to discover this by continually trying to compile my keymap using xkbcomp, but I don't remember if it gave any proper error messages, or it was just a bunch of trial and error. I do know that I got pretty mad at XOrg though at one point, when it decided to overwrite my configuration source with the compiled version without any notice, so be careful and keep it copied somewhere safe!