Problem with `xkbOptions` - it doesn't seem to take effect

I’m using the following config for xserver:

  # Enable the X11 windowing system.
  services.xserver.enable = true;
  services.xserver.layout = "pl";
  services.xserver.xkbOptions = "ctrl:nocaps, shift:both_capslock";

  # Enable touchpad support.
  services.xserver.libinput.enable = true;

  # Enable the KDE Desktop Environment.
  # services.xserver.displayManager.sddm.enable = true;
  # services.xserver.desktopManager.plasma5.enable = true;
  services.xserver.displayManager.gdm.enable = true;
  services.xserver.displayManager.gdm.wayland = false;
  services.xserver.windowManager.i3.enable = true;

  services.xserver.desktopManager.gnome3 = {
    enable = true;
    flashback.customSessions = [
        {
          wmCommand = "${pkgs.i3}/bin/i3";
          wmLabel = "Gnome3 + i3";
          wmName = "gnome3-i3";
        }
    ];
  };

Unfortunately it doesn’t seem to affect xkb settings:

$  setxkbmap -print -verbose 10
Setting verbose level to 10
locale is C
Trying to load rules file ./rules/evdev...
Trying to load rules file /nix/store/635pkhbalfrhm057im2pqbd0iabaz3xv-setxkbmap-1.3.1/share/X11/xkb/rules/evdev...
Success.
Applied rules from evdev:
rules:      evdev
model:      pc104
layout:     pl,us,us
variant:    ,,
options:    eurosign:e
Trying to build keymap using the following components:
keycodes:   evdev+aliases(qwerty)
types:      complete
compat:     complete
symbols:    pc+pl+us:2+us:3+inet(evdev)+eurosign(e)
geometry:   pc(pc104)
xkb_keymap {
	xkb_keycodes  { include "evdev+aliases(qwerty)"	};
	xkb_types     { include "complete"	};
	xkb_compat    { include "complete"	};
	xkb_symbols   { include "pc+pl+us:2+us:3+inet(evdev)+eurosign(e)"	};
	xkb_geometry  { include "pc(pc104)"	};
};

If I use setxkbmap directly it works properly:

$ setxkbmap -option -option "ctrl:nocaps" -option "shift:both_capslock"
$  setxkbmap -print -verbose 10
Setting verbose level to 10
locale is C
Trying to load rules file ./rules/evdev...
Trying to load rules file /nix/store/635pkhbalfrhm057im2pqbd0iabaz3xv-setxkbmap-1.3.1/share/X11/xkb/rules/evdev...
Success.
Applied rules from evdev:
rules:      evdev
model:      pc104
layout:     pl,us,us
variant:    ,,
options:    ctrl:nocaps,shift:both_capslock
Trying to build keymap using the following components:
keycodes:   evdev+aliases(qwerty)
types:      complete
compat:     complete
symbols:    pc+pl+us:2+us:3+inet(evdev)+ctrl(nocaps)+shift(both_capslock)
geometry:   pc(pc104)
xkb_keymap {
	xkb_keycodes  { include "evdev+aliases(qwerty)"	};
	xkb_types     { include "complete"	};
	xkb_compat    { include "complete"	};
	xkb_symbols   { include "pc+pl+us:2+us:3+inet(evdev)+ctrl(nocaps)+shift(both_capslock)"	};
	xkb_geometry  { include "pc(pc104)"	};
};

Am I doing something wrong or does it seem like a bug? I’m on 19.09.

3 Likes

Not sure if it is true for GNOME Flashback, but regular GNOME uses gnome-settings-daemon to manage keyboard configuration. And its keyboard manager uses GSettings to store the keyboard configuration, only using the xkb config for initial set up:

You can clean up the settings using

gsettings reset org.gnome.desktop.input-sources xkb-options
gsettings reset org.gnome.desktop.input-sources sources

and the system defaults should be picked up after re-login.

8 Likes

Thanks, that indeed fixed the problem! I think that I somehow made it work on my previous linux installation, because I worked with Gnome+i3 before, but this is exactly the problem with other distros - you set something up by hand somewhere and then you forget about it.

I’m having the same issue with “none+i3”.
Possibly related, sway also has a keyboard issue since this started
and i think i18n.consoleKeymap moved to console.keyMap around the same time (the TTY’s are correctly set to dvorak)

i’m on nixos-unstable with a vanilla i3 config

services.xserver.layout = "dvorak, us";
services.xserver.xkbOptions = "grp:shifts_toggle, lv3:ralt_switch, compose:ralt";

this config seems to be correctly present in /etc/X11/xorg.conf.d/00-keyboard.conf

Identifier "Keyboard catchall"
MatchIsKeyboard "on"
Option "XkbModel" "pc104"
Option "XkbLayout" "dvorak, us"
Option "XkbOptions" "grp:shifts_toggle, lv3:ralt_switch, compose:ralt"
Option "XkbVariant" ""

though everything but the TTYs are set to qwerty, and the shifts_toggle does not work

1 Like

That is a completely different issue, unless you use gnome-settings-Daemon. I think dvorak, or maybe even us should be in xkbVariant option. And I heard xkbOptions should not contain white space.

i don’t have anything gnome set up
setxkbmap dvorak works for me
my configuration as is (minus the i18n change and maybe the services.xserver.displayManager.defaultSession change) used to work
i’ll try adding services.xserver.xkbVariant and removing the whitespace

though combined with the similar timing, i don’t believe this to be a different issue

oh and the first time it presented itself (after a reboot) it went away ~10m after login

This issue is only relevant to gnome-settings-daemon and is not new – it has always been there and it will continue to be present until we implement #54150.

Other than the spaces mentioned in Fix example for xkbOptions by juliancoffee · Pull Request #76947 · NixOS/nixpkgs · GitHub, I do not see anything wrong with your config.

my issue turned out to be hardware.ckb-next, indeed quite unrelated

If I have a brand new install of NixOS with Gnome Desktop, and I have not modified any dconf settings, should the services.xserver.xkbOptions work? Or do I need to delete that stuff from dconf regardless?

This is how I installed Gnome:

  services.xserver.desktopManager.gnome3.enable = true;
  services.xserver.xkbOptions = "ctrl:swapcaps";

and nothing else.

It gets set automatically when not already set, so if you change xkbOptions NixOS option after, you need to reset the dconf key.

1 Like

Ah ok, thanks for that insight. Can I somehow make sure the setting is not set in dconf in my configuration.nix?

Unfortunately, we only have way to set default GSettings values but since gnome-settings-daemon sets the value to one from xkb-config, the default value will not be used:

  services.xserver.desktopManager.gnome3 = {
    extraGSettingsOverridePackages = with pkgs; [ gnome3.gnome-settings-daemon ];
    extraGSettingsOverrides = ''
      # does not work
      [org.gnome.desktop.input-sources]
      sources=[('xkb', '${config.services.xserver.layout}${lib.optionalString (config.services.xserver.xkbVariant != "") "+" + config.services.xserver.xkbVariant}')]
      xkb-options=['${config.services.xserver.xkbOptions}']
    '';
  };

The proper method will be generating dconf databases (nixos/dconf: Allow creating custom databases · Issue #54150 · NixOS/nixpkgs · GitHub) but our modules cannot do that at the moment. You can either try to create dconf database yourself (see nixos/gdm: add autoSuspend option by chpatrick · Pull Request #63790 · NixOS/nixpkgs · GitHub), or use home-manager, which does have working dconf.settings option.

1 Like

Last question: do I run the gsettings commands with sudo or no?

EDIT:

I just ran the gsettings commands with and without sudo, then it disabled my capslock-as-control setting that I set with tweak tool (good so far, so my capslock key became back to being a capslock key).

Then, I logged out and back in, and my capslock key went back to being control (so far, I thought it was working, yaaaay).

Then I went and checked inside of Gnome tweak tool, and apparently the setting for swapping control with capslock was re-enabled again.

So it seems tweak tool setting is coming back. I tried disabling that setting manually, log out/in, but that setting keeps coming back.

Then I tried logging into Gnome as root, and in that case ctrl is ctrl and caps is caps, which is not what I expected. If the xkbOptions is system-wide, then I thought that when I logged in as root I would have the caps swapped with control, but that wasn’t the case.

So it seems that the option is still not working. Any ideas? Is gnome-tweak-tool giving me false positives because it keeps setting the option within the tool? Any idea why it does not work for root?

Well, as I wrote, gnome-settings-daemon will check if /org/gnome/desktop/input-sources/xkb-options setting is set and if not, it will set it from the value stored by the services.xserver.xkbOptions in /etc/X11/xorg.conf.d/00-keyboard.conf. GNOME Tweaks just show the value of /org/gnome/desktop/input-sources/xkb-options.

Not sure what you mean but the GSetting is the only thing relevant for GNOME after log-in. You can check the value directly using:

gsettings get org.gnome.desktop.input-sources xkb-options

I think sudo gsettings might not work because it would still see your dconf database instead of root’s. If you logged to root before it would still have the setting from the previous login.

It should not really set anything unless you click something. But you will still see the settings set by gnome-settings-daemon.

1 Like

You’re right! Instead of running gsettings with sudo while logged in as normal user, I ran sudo -i then rm -rf ~/.config/dconf, and then after logging in with root it worked as expected.

I’m thinking that maybe it’ll be better to do this stuff at the system level, as in for it to work even in the virtual terminals outside of X11.