Skip to content

Draft: backends/native: Support XKB Keysyms for pointer control

Peter Hutterer requested to merge whot/mutter:wip/pointer-keysyms into main

XKB has two approaches to pointer control: The PointerKeys actions in Xorg (search for 'PtrBtn' in your keymap) which are interpreted and handled by the XKB implementation. But only in Xorg, libxkbcommon does not support thoes actions and mutter native has a hardcoded implementation of the mousekeys feature featuring NumLock and the keypad.

XKB also defines a number of keysyms representing pointer movements and button events, e.g. XKB_KEY_Pointer_UpRight and XKB_KEY_Pointer_Button1. Hook up (some of) those keysyms to their intended meaning so that a key sending the keysym XKB_KEY_Pointer_Button1 triggers a left button click.

This allows users to assign arbitrary keys to pointer actions, useful in particular for devices with specific keys that (should) emulate pointer events.

One possible option is this setup (explainer) which assigns WASD for pointer movement and Q/E for left/right button clicks:

$ export XDG_CONFIG_HOME=$HOME/.config
$ mkdir -p $XDG_CONFIG_HOME/xkb/{rules,symbols,types}
$ cat > $XDG_CONFIG_HOME/xkb/symbols/pointerkeys <<EOF
partial modifier_keys
xkb_symbols "wasd" {
    key  <AD02> {	[  NoSymbol, NoSymbol,	Pointer_Up	], type[Group1] = "LEVEL_THREE_NUMLOCK"	};
    key  <AC01> {	[  NoSymbol, NoSymbol,	Pointer_Left	], type[Group1] = "LEVEL_THREE_NUMLOCK"	};
    key  <AC02> {	[  NoSymbol, NoSymbol,	Pointer_Down	], type[Group1] = "LEVEL_THREE_NUMLOCK"	};
    key  <AC03> {	[  NoSymbol, NoSymbol,	Pointer_Right	], type[Group1] = "LEVEL_THREE_NUMLOCK"	};

    key  <AD01> {	[  NoSymbol, NoSymbol,	Pointer_Button1	], type[Group1] = "LEVEL_THREE_NUMLOCK"	};
    key  <AD03> {	[  NoSymbol, NoSymbol,	Pointer_Button3	], type[Group1] = "LEVEL_THREE_NUMLOCK"	};
};
EOF
$ cat > $XDG_CONFIG_HOME/xkb/types/numlock <<EOF
default partial xkb_types "level3" {
    type "LEVEL_THREE_NUMLOCK" {
        modifiers = Shift + NumLock;
        map[None] = Level1;
        map[Shift] = Level2;
        preserve[Shift] = Shift;
        map[NumLock] = Level3;
        level_name[Level1] = "Base";
        level_name[Level2] = "Shift";
        level_name[Level3] = "NumLock";
    };
};
EOF
$ cat > $HOME/.config/xkb/rules/evdev << EOF
! option = symbols
  pointerkeys:wasd = +pointerkeys(wasd)

! option			=	types
  pointerkeys:wasd = +numlock(level3)

// Include the system 'evdev' file
! include %S/evdev
  EOF

Test with the "xkbcli interactive-evdev" tool to ensure it takes effect first, then enable via the pointerkeys:wasd option:

$ gsettings set org.gnome.desktop.input-sources xkb-options "['pointerkeys:wasd']"

cc @bentiss


This is mostly a PoC for now unless there's more interest in it. Related libxkbcommon issue #4348

Merge request reports