microsoft / wslg

Enabling the Windows Subsystem for Linux to include support for Wayland and X server related scenarios
MIT License
10.11k stars 304 forks source link

support customized keyboard layout (with KLC file) #173

Open hwdef opened 3 years ago

hwdef commented 3 years ago

Is your feature request related to a problem? Please describe.

I use dvorak keyboard layout, and I can not find a way to change the wslg keyboard from qwerty to dvorak

Describe the solution you'd like

Describe alternatives you've considered

Additional context

susannemoog commented 3 years ago

You could try calling setxkbmap us dvorak-alt-intl -model pc102 - that worked for me (see https://susi.dev/dev-env-2020 at the bottom for my solution from last year, seems to continue working with wslg).

hwdef commented 3 years ago

@susannemoog
ok, thank you!😃

viniavila commented 3 years ago

You could try calling setxkbmap us dvorak-alt-intl -model pc102 - that worked for me (see https://susi.dev/dev-env-2020 at the bottom for my solution from last year, seems to continue working with wslg).

This just worked for Qt programs, Gnome programs requires layout change in weston.ini, but when changing /mnt/wslg/.config/weston.ini (which is the file weston.log says is consulted) nothing happens

cpbotha commented 3 years ago

Indeed, some applications work through xwayland and then weston (the wayland compositor), and therefore the setxkbmap invocation works, but other (wayland-compatible) applications go directly through weston.

If anyone has any tips as to changing weston's keyboard layout (via the weston.ini suggested by @viniavila for example) I would be grateful.

cpbotha commented 3 years ago

I have figured out a hacky way of changing the Wayland (weston) keyboard layout.

In short, you can edit weston.ini in the hidden wslg system instance and then send the weston process a HUP signal so it reloads this new config.

Step by step:

  1. enter the WSLg system instance by doing wsl..exe --system

  2. cat /home/wslg/.config/weston.ini to see the current config, it should look like this:

    
    [xwayland]
    disable_access_control=true

[input-method] path=


3. Add the relevant keyboard layout variables. In my case I want dvorak: `echo -e "\n[keyboard]\nkeymap_layout=us\nkeymap_variant=dvorak\n" >> /home/wslg/.config/weston.ini`

4. Confirm that the weston.ini now looks something like this:

[xwayland] disable_access_control=true

[input-method] path=

[keyboard] keymap_layout=us keymap_variant=dvorak



5. Tell the weston process to restart by sending it the HUP signal: `pkill -HUP weston` (this will restart it, so any gui apps of yours will be killed)

Wayland apps you start during this session will use the new keymap. If I understand the docs correctly, the WSLg system instance is ephemeral, so the next time you restart wsl (with `--shutdown`) or reboot your machine, you'll have to do it again.

For extra credit, build your own WSLg system distro and use that. ;)
hideyukn88 commented 3 years ago

@cpbotha , thanks for write up! actually weston should be trying to "sync" the keyboard layout based on what Windows client software (RDP client) reports.

For example, when I use with Japanese keyboard, Windows reports like below (logged in weston.log).

     [12:08:56.935] kbd_layout:0xe0010411 kbd_type:0x7 kbd_subType:0x2 kbd_functionKeys:0xc

And RDP backend in weston will try to match above to rules in Xkb.

      [12:08:56.935] convert_rdp_keyboard_to_xkb_rule_names: matching layout=jp variant=(null)

And Xkb will compile matching layout (below is debug output from Xkb if enabled).

    xkbcommon: DEBUG: Compiling from RMLVO: rules 'evdev', model 'jp106', layout 'jp', variant '(null)', options '(null)'
    xkbcommon: DEBUG: Compiling from KcCGST: keycodes 'evdev+aliases(qwerty)', types 'complete', compat 'complete+japan', symbols 'pc+jp+inet(evdev)'

And for US-dvorak case, it should be like below.

    [12:29:59.328] kbd_layout:0x10409 kbd_type:0x4 kbd_subType:0x0 kbd_functionKeys:0xc
    [12:29:59.328] convert_rdp_keyboard_to_xkb_rule_names: matching layout=us variant=dvorak

    xkbcommon: DEBUG: Compiling from RMLVO: rules 'evdev', model 'pc102', layout 'us', variant 'dvorak', options '(null)'
    xkbcommon: DEBUG: Compiling from KcCGST: keycodes 'evdev+aliases(qwerty)', types 'complete', compat 'complete', symbols 'pc+us(dvorak)+inet(evdev)'

And above should have same effect as configuring at weston.ini. Thus, when "auto-sync" doesn't work, there is 3 possibilities, I think.

1: The layout Windows Client software reported doesn't match your settings in Windows (but this is very unlikely, I think). 2: RDP-backend failed to convert or convert to wrong Xkb settings. 3: The corresponding Xkb rules (and etc) is not installed in system-distro. (but this doesn't apply to your case since configuring weston.ini does fix it).

Would you please take a look your weston.log to see what Windows client reports and what Xkb rules RDP-backend covert to ?

Thank you very much for trying out WSLg and helping us!

cpbotha commented 3 years ago

Would you please take a look your weston.log to see what Windows client reports and what Xkb rules RDP-backend covert to ?

Thank you very much @hideyukn88 for spending your time on this, and explaining this mechanism.

I just checked my weston.log and see this:

[07:27:59.623] kbd_layout:0xa0010409 kbd_type:0x2110110 kbd_subType:0x2 kbd_functionKeys:0xc

The text convert_rdp_keyboard_ is nowhere to be found in the weston.log.

This is very possibly because I use the dvaltint keyboard layout from [1], a special Dvorak layout with no dead keys that supports AltGr as a compose key, so I can also type the diacritics I need in Afrikaans ad Dutch (ô, ï, ë, for example).

Is there any way for me to modify that keymap (I have the KLC file) so that WSLg does recognize it as layout US variant Dvorak, or maybe some other approach?

[1] http://keyboards.jargon-file.org/ see "United States-Dvorak International Alternate"

hideyukn88 commented 3 years ago

@cpbotha , thanks for checking out and explaining your issues, so in summary...

1: Since you are using customized keyboard layout (using KLC file), the kbd_layout and kbd_type (which Windows reports to WSLg) are not standard one defined in Remote desktop protocol (below link), thus those can't be recognized by RDP-backend, and it ends up not changing anything, left as default English layout, or as you do, configured with the override from weston.ini.

https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/00f1da4a-ee9c-421a-852f-c19f92343d73

2: Since you are using customized keyboard layout, does override by weston.ini give you exactly what you have in Windows side? I image it is not since that weston config sets Xkb to standard English Dvorak layout, not which might not match perfectly with your customized one, am I right?

Thus the possible solutions are...

a: Offer a way to override keyboard layout which can remain across WSL restarts, which eliminate the needs to update weston.ini every time. This sounds workaround, but it helps a lot, I guess. This also helps when the match done by RDP-backend is not exactly what user want.

b: Offer a way to configure Xkb with custom Xkb configuration files, thus if user has non-standard layout, which is not available at system-distro by default, they have an option to configure it and apply using solution a:

c: (very unlikely to be done, but ideally better) When custom keyboard layout file are being used in Windows side, auto generate Xkb configuration from KLC (or any other source) if necessary, and auto apply it.

We will continue to explore more options for solution, please feel free to send us feedbacks!

hideyukn88 commented 3 years ago

@hwdef, as I commented above (https://github.com/microsoft/wslg/issues/173#issuecomment-849894177), would you please check weston.log and see what layout is reported from Windows and being converted for Xkb? thanks!

hwdef commented 3 years ago

@hideyukn88

Sorry, I don't have a wslg environment anymore and can't test it for you

cpbotha commented 3 years ago

2: Since you are using customized keyboard layout, does override by weston.ini give you exactly what you have in Windows side? I image it is not since that weston config sets Xkb to standard English Dvorak layout, not which might not match perfectly with your customized one, am I right?

You are right, it does not match perfectly, but for my purposes it's good enough. In any case, I can customise XKB as I usually have to do on my Linux setups in any case.

Thus the possible solutions are... a: Offer a way to override keyboard layout which can remain across WSL restarts, which eliminate the needs to update b: Offer a way to configure Xkb with custom Xkb configuration files, thus if user has non-standard layout, which is not c: (very unlikely to be done, but ideally better) When custom keyboard layout file are being used in Windows side, auto generate Xkb configuration from KLC (or any other source) if necessary, and auto apply it.

I would personally be happy with any of these!

Thank you again!

alesimula commented 3 years ago

@cpbotha I implemented your hacky solution in a more permanent way, I just appended this small script at the end of ~/.profile; the script also creates a file called 'state-wslg-config-initialized' inside /mnt/wsl/ to "maintain a state" and run it only once at WSL boot

# Temporary fix for WSLg keyboard layout (only change the first line)
KEYMAP_LAYOUT=it
if [ ! -f /mnt/wsl/state-wslg-config-initialized ]; then
read -r -d '' GWSL_SYSTEM_CONFIG_COMMANDS <<EOF
KEYMAP_LAYOUT=\`grep -r '^keymap_layout=.*\$' /home/wslg/.config/weston.ini\`;if [ -z \$KEYMAP_LAYOUT ]; then sed -i '$ a\[keyboard]\nkeymap_layout=`echo ${KEYMAP_LAYOUT}`\n' /home/wslg/.config/weston.ini;pkill -HUP weston;touch /mnt/wsl/state-wslg-config-initialized;fi
EOF
wsl.exe -d $WSL_DISTRO_NAME --system ${GWSL_SYSTEM_CONFIG_COMMANDS}
fi

I also tried using the /etc/wsl.conf 'command' option to run a command at boot, but running any Windows executable would throw an error so I sticked to the above solution; hope this helps someone

slavistan commented 2 years ago

I'm using a custom keyboard layout for which I have a KLC file for Windows and an xkb/symbols file for Linux. Where should I put the xkb/symbols file for it to register the layout? The few XWayland applications which I'd like to use don't recognize my keystrokes, and instead seem to use the regular us layout.

My attempts to simply copy the xkb/symbols file to the /usr/share/X11/xkb/symbols directory on my WSL2/Linux distro were unsuccessful. While I can merrily change between existing layouts (setxkbmap de, setxkbmap en), the attempt to execute setxkbmap k6, where k6 is my own layout, results in Error loading new keyboard description.

I've tried applying @cpbotha's hack after copying my custom layout file into the hidden WSL2-distro. This causes XWayland applications to crash on the first keystroke.

Is there a way forward for people who have custom keyboard layout files on both, Windows and Linux?

ncaq commented 1 year ago

I try https://github.com/microsoft/wslg/issues/173#issuecomment-910172263 solution. I write to .profile.

wsl.exe --user root --system bash -c "echo '[keyboard]' >> /home/wslg/.config/weston.ini"
wsl.exe --user root --system bash -c "echo 'keymap_layout=us' >> /home/wslg/.config/weston.ini"
wsl.exe --user root --system bash -c "echo 'keymap_variant=dvorak' >> /home/wslg/.config/weston.ini"
wsl.exe --user root --system pkill -HUP weston

But, It did not work.

weston.log

convert_rdp_keyboard_to_xkb_rule_names: matching model=pc105 layout=us variant=(null) options=(null)

I believe it is bad that Windows is automatically trying to sync keyboard settings with RDP and WSLg.

I am using a physical US keyboard in Windows (specifically Realforce), with the region and language set to Japanese, and using kbddv.dll in the registry. Using Dvorak sequence on Windows 10 (20H2) without any external tools - Qiita This is the method described in the following page.

The reason why I am doing this hack is that there is a circumstance that Japanese conversion systems like Google Japanese Input or MSIME do not work on Windows unless it is set to Japanese, but Dvorak does not exist in the Japanese keyboard variants.

When I see that the settings by setxkbmap work via XWayland, I believe that this behavior is not what Microsoft intended. For some reason, it only reverts to QWERTY for a split second when I shift the focus to an app... It would be nice if an option to turn off keyboard layout synchronization via RDP could be added per wslgconfig.

Cremesis commented 1 year ago

I'm currently using an Italian keyboard with a self made KLC layout because, as a developer, I also want a shortcut for the "backtick" (`) character without having the only choice to use a US keyboard instead...

Previous solutions don't work for me, I don't get what's the problem :\

In my case the affected application is google-chrome.

WSL version: 1.1.0.0
Kernel version: 5.15.83.1
WSLg version: 1.0.48
MSRDC version: 1.2.3770
Direct3D version: 1.608.2-61064218
DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows version: 10.0.22623.1245
ncaq commented 1 year ago

This is not a direct solution, but I will post my workaround.

I decided to use Keyhac to solve this problem. This is a keymapper that allows you to write settings in Python.

You can use Keyhac as a https://github.com/ncaq/keyhac-config/blob/16f91349b9fd8321e0b914ba9a592eb68fffc22a/config.py#L150 Configure it as follows.

Then all keystrokes can be freely substituted if the focus is on a window under the control of a WSLg process. This control method may have latency problems, but for now, it didn't bother me much for my use of Emacs.

For more details, please refer to the following article in Japanese. Dvorak input with Wayland native in WSLg to counter QWERTY on its own and Japanese input - ncaq

pdevelopement commented 1 year ago

I recently installed ubuntu on wsl and when i open Chrome browser by terminal with google-chrome it opens it but when am typing in browser it shows it in Cyrillic. Why ? I did not sync it or anything. It does it by default!

hideyukn88 commented 1 year ago

@pdevelopement, would you please share /mnt/wslg/weston.log? if not prefer to share whole, please share every line contain kbd_layout or xkb, thanks!

fargiolas commented 1 year ago

Same issue here, custom Italian layout created with MSKLC to have tilde and backticks (by the way is there any other way to have an italian keyboard with those on windows?).

In the logs you can see what happens when I switch between the two layouts. My custom layout (0xa0000410) doesn't have an xkb counter part and it defaults to "us", italian (0x410) does have a matching layout and maps to normal xkb layout. Ironically xkb layouts have tilde and backticks so I get them on wslg apps with the standard Italian layout but I lose them in the WSL shell because it uses windows keymap...

Setting a keymap in weston.ini doesn't do anything for me. Any other idea?

[15:04:32.814] Client: LanguageImeInfo: ProfileType: 2 (TF_PROFILETYPE_KEYBOARDLAYOUT)
[15:04:32.814] Client: LanguageImeInfo: LanguageID: 0x410
[15:04:32.814] Client: LanguageImeInfo: LanguageProfileCLSID: GUID_NULL
[15:04:32.814] Client: LanguageImeInfo: ProfileGUID: GUID_NULL
[15:04:32.814] Client: LanguageImeInfo: KeyboardLayout: 0xa0000410
[15:04:32.814] convert_rdp_keyboard_to_xkb_rule_names: matching model=pc105 layout=us variant=(null) options=(null)
[15:04:32.819] rail_client_LanguageImeInfo_callback: new keyboard layout: 0xa0000410
[15:04:36.052] Client: LanguageImeInfo: ProfileType: 2 (TF_PROFILETYPE_KEYBOARDLAYOUT)
[15:04:36.052] Client: LanguageImeInfo: LanguageID: 0x410
[15:04:36.052] Client: LanguageImeInfo: LanguageProfileCLSID: GUID_NULL
[15:04:36.052] Client: LanguageImeInfo: ProfileGUID: GUID_NULL
[15:04:36.052] Client: LanguageImeInfo: KeyboardLayout: 0x410
[15:04:36.052] convert_rdp_keyboard_to_xkb_rule_names: matching model=pc105 layout=it variant=(null) options=(null)

@hideyukn88 guess the issue is the weston rdp backend, I believe it should honor the keymap set in weston.ini so you would have a way to set the desired keymap if the automatic mapping fails.

And wslg should probably have a sane persistent way to edit weston.ini so it's not lost when wsl shuts down.

rigel314 commented 1 year ago

I use programmer dvorak, and I have to install a custom keyboard layout for windows. The [keyboard] section of weston.ini used to work, but it no longer works for me. However, setxkbmap us dvp appears to work for both xwayland applications and direct wayland applications now. Which is nice because when I forget to do the weston.ini tweak, I don't have to SIGHUP the weston process.

fargiolas commented 1 year ago

However, setxkbmap us dvp appears to work for both xwayland applications and direct wayland applications now.

how do you run setxkbmap? inside a wsl shell? it gives me a "cannot open display" error.

rigel314 commented 1 year ago

I'm on win11. I use archlinux in wsl2 (imported from the archlinux docker base tar) and I have the default user setup as root. Other than that, I don't really have anything special happening. setxkbmap us dvp just works after printing WARNING: Running setxkbmap against an XWayland server

My $DISPLAY is automatically setup as :0.

%USERPROFILE%/.wslconfig

[wsl2]
swap=16GB

/etc/wsl.conf

[boot]
systemd=true

wsl.exe --version

WSL version: 1.1.6.0
Kernel version: 5.15.90.1
WSLg version: 1.0.50
MSRDC version: 1.2.3770
Direct3D version: 1.608.2-61064218
DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows version: 10.0.22621.1413
fargiolas commented 1 year ago

setxkbmap us dvp just works after printing WARNING: Running setxkbmap against an XWayland server

Thanks, it still doesn't do anything here (ubuntu 22.04), tested it with native wayland apps, not sure on XWayland as I don't use any. I don't get your warning though. Also tried running it from wsl --system both with user root and wslg. Still nothing. Same for setting keyboard in weston.ini. Weston still does its windows to xkb mapping and there isn't apparently any way to force a different layout on the linux side.

Anybody knows a good work around for this while this issue gets eventually fixed?


Kernel version: 5.15.90.1
WSLg version: 1.0.51
MSRDC version: 1.2.3770
Direct3D version: 1.608.2-61064218
DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows version: 10.0.19042.2728```
hungyiloo commented 1 year ago

I'm getting the same issue now too. The weston.ini [keyboard] hack has stopped working, and none of the suggested setxkbmap methods are having any effect. I'm not able to use the Colemak keyboard layout in wslg anymore as of the latest Windows update.

WSL version: 1.2.0.0
Kernel version: 5.15.90.1
WSLg version: 1.0.51
MSRDC version: 1.2.3770
Direct3D version: 1.608.2-61064218
DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows version: 10.0.22621.1555
abdelmounim-dev commented 1 year ago

3. echo -e "\n[keyboard]\nkeymap_layout=us\nkeymap_variant=dvorak\n" >> /home/wslg/.config/weston.ini

when I execute this command this is the output -bash: /home/wslg/.config/weston.ini: Permission denied any solution?

ncaq commented 1 year ago

@abdelmounim-dev

I am sure this is the case. In the end, the rewrite method didn't work because it reset the system.

wsl.exe --user root --system bash -c 'echo [keyboard] >> /home/wslg/.config/weston.ini'
Konamiman commented 1 year ago

In case it helps someone: this happened to me because I'm traveling and temporarily using a Japanese keyboard, thus I have configured Windows to use the Japanese keyboard layout; but turns out I hadn't the Japanese locale installed in the WSL-ed Ubuntu I use.

I found the solution here:

  1. From inside WSL I ran sudo dpkg-reconfigure locales
  2. Selected all the ja_JP entries in the list
  3. Pressed the tab key to select <Ok>, then Enter
  4. wsl --shutdown

Not sure if related or just a coincidence but I also had to reboot my computer because VSCode was no longer able to access the WSL filesystem.

Some explicit error message/logging would definitely be helpful in these cases (when WSL is unable to match the Windows keyboard layout and has to resort to a default configuration).

WesleyBlancoYuan commented 7 months ago

I'm using a custom keyboard layout for which I have a KLC file for Windows and an xkb/symbols file for Linux. Where should I put the xkb/symbols file for it to register the layout? The few XWayland applications which I'd like to use don't recognize my keystrokes, and instead seem to use the regular us layout.

My attempts to simply copy the xkb/symbols file to the /usr/share/X11/xkb/symbols directory on my WSL2/Linux distro were unsuccessful. While I can merrily change between existing layouts (setxkbmap de, setxkbmap en), the attempt to execute setxkbmap k6, where k6 is my own layout, results in Error loading new keyboard description.

I've tried applying @cpbotha's hack after copying my custom layout file into the hidden WSL2-distro. This causes XWayland applications to crash on the first keystroke.

Is there a way forward for people who have custom keyboard layout files on both, Windows and Linux?

You should edit evdev files too. Check here: https://askubuntu.com/questions/896822/custom-keyboard-layout-behaves-like-last-selected

WesleyBlancoYuan commented 7 months ago

If you use customised keyboard layout and it's not automatically translated by WSL, I recommend to follow this question https://askubuntu.com/questions/875163/is-it-possible-to-use-a-custom-keyboard-layout-without-sudo-access-if-so-how