ch11ng / exwm

Emacs X Window Manager
2.85k stars 135 forks source link

Changing keyboard layout #908

Open shader opened 1 year ago

shader commented 1 year ago

What's the recommended way to change a keyboard layout during use?

I normally use the colemak layout, but i have an external keyboard that has a custom layout assuming qwerty input mappings. If I try to use setxkbmap to change the keyboard layout, it mostly works in subordinate X windows (e.g. Firefox) but not in the exwm keys that don't go to Firefox (e.g. C-x ...).

I think this is an EXWM issue, because of the way it affects those specially grabbed keys. Any workaround ideas or things I should test?

tazjin commented 1 year ago

You can use Emacs input methods in EXWM via toggle-input-method (I think the default shortcut is C-\). This works in all X windows that support xim input (which excludes e.g. modern Qt applications, but definitely works in Firefox/Chromium).

This requires a little bit of setup, on the Emacs side:

(require 'exwm-xim)
(exwm-xim-enable)

and on your session level, these environment variables:

    XMODIFIERS = "@im=exwm-xim";
    GTK_IM_MODULE = "xim";
    QT_IM_MODULE = "xim";
    CLUTTER_IM_MODULE = "xim";

For the occasional case where I have to type something in Russian or Arabic in a Qt-window (e.g. Quassel IRC), I have shortcuts that use setxkbmap which also affects shortcuts in Emacs (making them mostly impossible to use). To work around this I set the shortcuts in Emacs in all alphabets, which is a bit cumbersome, but fortunately not actually needed very often.

medranocalvo commented 1 year ago

I don't fully understand the issue, possibly because I don't usually change keyboard layouts. There is some support in EXWM for updating the global keys "when the keyboard is updated" (see exwm-input--init and xcb-keysyms.el), but I'm not sure which cases it supports. Neither I'm sure what behaviour you miss.

Please, create a minimum configuration and set of steps that allow me to reproduce the issue (see for example https://github.com/ch11ng/exwm/issues/924#issuecomment-1715085681).

eval-on-point commented 1 year ago

I don't completely understand the issue either, but I have had a good experience mapping my keyboards with kmonad/kmonad: An advanced keyboard manager rather than setxkbmap. This changes my keyboard layout globally, not just in X11 sessions.

shader commented 1 year ago

Well, I just spent an hour or two but couldn't get a truly minimal config working (couldn't get a minimal exwm config to work on my system for some reason).

However, I was able to narrow down some cases where the problem occurs and where it doesn't, so maybe this will be enough for you to reproduce it.

Potentially confounding configuration

I'm not expecting you to try reproducing my configs; just thought I should mention them briefly since I wasn't able to bypass them to make a working minimal setup. I'm using guix system, and configuring exwm primarily with a custom doom module based on https://github.com/doomemacs/doomemacs/pull/4004/ (never got merged). I also experimented with configuring exwm-xim but I'm not sure if it's working right now or not.

Variant A - produces problem

In xinitrc:

setxkbmap us -variant colemak &
exec emacs -f exwm-enable

Once exwm is loaded:

M-x async-shell-command RET firefox
C-c w c     ; doom keybinding for create workspace, really any "C-c" or "C-x" command that would be captured by exwm in line mode and not sent to firefox should be a good test

Expected result -> nothing unusual happens; chord input correctly

In some terminal:

setxkbmap us -model pc105

Changes the layout back to qwerty. Most keys should work as expected in any emacs buffer, or when typing in firefox (e.g. input fields, C-t for new tab, etc.) However, "captured keys" don't notice the change:

Variant B - doesn't have problem

I only found this while working on making a minimal config today.

In xinitrc:

exec emacs -f exwm-enable

Later, in terminal: setkbmap us -variant colemak; proceed as above after "exwm loaded". No problems with captured keys in either layout.

Workaround

Since my objective was to switch to qwerty for my external keyboard (since it handles layouts itself via firmware), I found it was easier to just use kmonad and only set the layout for the internal keyboard. Then the layout works everywhere, and I don't have to switch when attaching the external.

Another potential workaround based on variant B above would is just to not call setxkbmap until after emacs launches, and call setxkbmap during emacs' init after exwm instead.

eval-on-point commented 1 year ago
setxkbmap us -variant colemak &
exec emacs -f exwm-enable

stands out to me as a possible issue. The & is telling the shell to execute setxkbmap in the background. So, emacs may be launching before setxkbmap is finished changing the layout. What happens if you remove the &?

shader commented 1 year ago

What happens if you remove the &?

I tried it; no difference. Good catch though.

shobute commented 9 months ago

Since my objective was to switch to qwerty for my external keyboard (since it handles layouts itself via firmware), I found it was easier to just use kmonad and only set the layout for the internal keyboard.

Note that kmonad isn't needed here. You can set the layout for a specific keyboard with setxkbmap using the -device flag (device IDs can be found with xinput list, see the man page for more information). That way you can change the layout for one keyboard, while leaving any others alone.