This file contains key overrides to pilot the Keychron K2 on Sway On X11 you would use `xmodmap` (man 1 xmodmap) to do something like: ``` $ xmodmap -pke | grep Delete keycode 91 = KP_Delete KP_Decimal KP_Delete KP_Decimal KP_Delete KP_Separator keycode 119 = Delete Insert Delete Insert Delete Insert $ xmodmap -e "keycode 119 = Delete Insert Delete NoSymbol Delete" ``` This command will have no effect on Wayland. Some troubleshooting for Linux: https://github.com/Kurgol/keychron Have the F1-12 keys behave like function keys (not sure it persists after a reboot) ``` echo 0 | sudo tee /sys/module/hid_apple/parameters/fnmode ``` src: https://github.com/Kurgol/keychron/blob/master/k2.md#f-keys-on-ubuntu On Sway we have to write a xkb file that overrides in part (or completely replace) the default X11 keybindings. This override file will be parsed and validated by Sway. When editing this file don't forget to reload Sway after any change. General syntax is [detailed here](https://www.charvolant.org/doug/xkb/html/node5.html) Fully commented example: ``` # "partial" indicates that this map doesn't cover a complete keyboard # "alphanumeric_keys" describes which section of the keyboard is being covered default partial alphanumeric_keys # "basic" declares symbol map name xkb_symbols "basic" { # define a base layout to inherit include "us(altgr-intl)" include "level3(caps_switch)" # name of the layout name[Group1] = "Keychron"; # map Del key to delete or insert, i.e.: # Press delete -> delete # Press shift+delete -> insert key { [ Delete, Insert ] }; # map left alt to left super (this mapping is always used) key { [ Alt_L ] }; # map left super to left alt (this mapping is always used) key { [ Super_L ] }; }; # define two options: # - toggle keyboard layout (e.g. US,DE,IT,FR, ...) on Mod+Space combo press # - turn Capslock into another Ctrl xkb_options grp:win_space_toggle,caps:ctrl_modifier ``` A single key remapping in detail: `` is the physical key identifier. These identifiers can be found on the image map in the [documentation page](https://www.charvolant.org/doug/xkb/html/node5.html#Fig:KeyNames). `{ [ Delete, Insert ] }` are symbols emitted on screen. The full list of symbols is mapped [is found here](https://www.charvolant.org/doug/xkb/html/node5.html#SECTION00053000000000000000). Symbols names are derived from [this mapping](https://cgit.freedesktop.org/xorg/proto/x11proto/tree/keysymdef.h) (removing `XL_`). Number and ordering of parameters inside square brackets means: - 1st: no modifier (if only this value is present, it applies implicitely for any modifiers) - 2nd: shift - 3rd: ctrl - 4th: ctrl-shift - 5th...Nth : MOD1-MOD5 For available `xkb_options` options: see `man 7 xkeyboard-config` (jump to "OPTIONS") When this file will be loaded in Sway, you can check its effect by using `xev -event keyboard` (to filter only the keyboard events). Before: ``` KeyPress event, serial 42, synthetic NO, window 0x600001, root 0x2ac, subw 0x0, time 3805675, (264,614), root:(1229,650), state 0x0, keycode 64 (keysym 0xffe9, Alt_L), same_screen YES, XLookupString gives 0 bytes: XmbLookupString gives 0 bytes: XFilterEvent returns: False KeyRelease event, serial 42, synthetic NO, window 0x600001, root 0x2ac, subw 0x0, time 3805714, (264,614), root:(1229,650), state 0x8, keycode 64 (keysym 0xffe9, Alt_L), same_screen YES, XLookupString gives 0 bytes: XFilterEvent returns: False ``` We have two events `KeyPress` and `KeyRelease`. Please notice the line with `keycode 64` and the resulting key `Alt_L` key. After: ``` KeyPress event, serial 42, synthetic NO, window 0x600001, root 0x2ac, subw 0x0, time 3841745, (27,367), root:(992,403), state 0x4000, keycode 64 (keysym 0xffeb, Super_L), same_screen YES, XKeysymToKeycode returns keycode: 133 XLookupString gives 0 bytes: XmbLookupString gives 0 bytes: XFilterEvent returns: False KeyRelease event, serial 42, synthetic NO, window 0x600001, root 0x2ac, subw 0x0, time 3841776, (27,367), root:(992,403), state 0x4008, keycode 64 (keysym 0xffeb, Super_L), same_screen YES, XKeysymToKeycode returns keycode: 133 XLookupString gives 0 bytes: XFilterEvent returns: False ``` Please notice the new line `XKeysymToKeycode` with the remapped keycode 133 and the resulting key `Super_L` key. ### How Sway sees the Keychron K2 ``` $ swaymsg -t get_inputs Input device: Keychron K2 System Control Type: Keyboard Identifier: 1452:591:Keychron_K2_System_Control Product ID: 591 Vendor ID: 1452 Active Keyboard Layout: Keychron Libinput Send Events: enabled Input device: Keychron K2 Consumer Control Type: Mouse Identifier: 1452:591:Keychron_K2_Consumer_Control Product ID: 591 Vendor ID: 1452 Libinput Send Events: enabled Input device: Keychron K2 Consumer Control Type: Keyboard Identifier: 1452:591:Keychron_K2_Consumer_Control Product ID: 591 Vendor ID: 1452 Active Keyboard Layout: Keychron Libinput Send Events: enabled Input device: Keychron K2 Keyboard Type: Keyboard Identifier: 1452:591:Keychron_K2_Keyboard Product ID: 591 Vendor ID: 1452 Active Keyboard Layout: Keychron Libinput Send Events: enabled ``` ### Mapping mouse movements to keys `sudo apt install libinput-tools` `sudo libinput debug-events` See this example: https://github.com/mpsq/dotfiles/blob/master/.config/libinput-gestures.conf Sway sees the following "mouse/touchpad" devices on my Thinkpad: ``` Input device: TPPS/2 IBM TrackPoint Type: Mouse Identifier: 2:10:TPPS/2_IBM_TrackPoint Product ID: 10 Vendor ID: 2 Libinput Send Events: enabled Input device: Synaptics TM3276-022 Type: Touchpad Identifier: 1739:0:Synaptics_TM3276-022 Product ID: 0 Vendor ID: 1739 Libinput Send Events: enabled ``` I see some ways to accomplish this. 1) Find a way to use the Keychron "mouse" device ``` Input device: Keychron K2 Consumer Control Type: Mouse Identifier: 1452:591:Keychron_K2_Consumer_Control Product ID: 591 Vendor ID: 1452 Libinput Send Events: enabled ``` $ libinput list-devices ``` Device: Keychron Keychron K2 Kernel: /dev/input/event16 Group: 5 Seat: seat0, default Capabilities: keyboard Tap-to-click: n/a Tap-and-drag: n/a Tap drag lock: n/a Left-handed: n/a Nat.scrolling: n/a Middle emulation: n/a Calibration: n/a Scroll methods: none Click methods: none Disable-w-typing: n/a Accel profiles: n/a Rotation: n/a Device: Keychron Keychron K2 Kernel: /dev/input/event17 Group: 5 Seat: seat0, default Capabilities: keyboard pointer Tap-to-click: n/a Tap-and-drag: n/a Tap drag lock: n/a Left-handed: disabled Nat.scrolling: disabled Middle emulation: disabled Calibration: n/a Scroll methods: button Click methods: none Disable-w-typing: n/a Accel profiles: flat *adaptive Rotation: n/a ``` 2) Use the `MouseKeys` XKB extension to remap keys to mouse movements (this is an X11 feature, nothing to do with Wayland but in theory wlroots/sway support XKB key customizations so this XKB Option *should* work) Problem: it is meant to use with the numeric keypad. By default mapped to Shift+Numlock modifier. Customizing these two things looks hard. References: https://www.x.org/releases/X11R7.6/doc/kbproto/xkbproto.html#the_mousekeys_control The MouseKeys control lets a user control all the mouse functions from the keyboard. When MouseKeys are enabled, all keys with MouseKeys actions bound to them generate core pointer events instead of normal key press and release events. https://www.x.org/releases/X11R7.6/doc/kbproto/xkbproto.html#keysyms_used_to_control_the_core_pointer On X11 you enable it with: `setxkbmap -option keypad:pointerkeys` and customize the parameters with: https://unix.stackexchange.com/questions/609367/setting-pointerkeys-numpad-as-mouse-keys-parameters-acceleration-delay-etc KeySyms Used to Control The Core Pointer. To start with, I'm probably interested in: `POINTER UP`, `POINTER DOWN`, `POINTER LEFT` and `POINTER RIGHT`. [Controls for Using the Mouse from the Keyboard](https://www.x.org/releases/X11R7.6/doc/libX11/specs/XKB/xkblib.html#controls_for_using_the_mouse_from_the_keyboard) What's the difference with [Pointer_EnableKeys](https://www.toomanyatoms.com/computer/Pointer_EnableKeys.html)? 3) Remap a key to a mouse movement from my custom XKB file Reference: https://wiki.archlinux.org/index.php/X_KeyBoard_extension#Mouse_control Problem: could not figure out how to implement the above suggestion 4) Using `libinput` to remap a key to a POINTER_MOTION event For a starting point, see the [mousemapper.sh](https://github.com/mathportillo/wayland-mouse-mapper) script (uses [evemu-tools](https://manpages.ubuntu.com/manpages/hirsute/man1/evemu-device.1.html) to simulate a device) - Debug libinput events for Thinkpad movements: ``` # libinput debug-events event5 POINTER_MOTION +4.08s -4.74/ 0.00 ( -9.00/ +0.00) event5 POINTER_MOTION +4.09s -4.74/ 0.00 ( -9.00/ +0.00) event5 POINTER_MOTION +4.09s -4.21/ 0.53 ( -8.00/ +1.00) event5 POINTER_MOTION +4.10s -3.68/ 1.05 ( -7.00/ +2.00) ``` - Record keystrokes from Keychron # libinput record --show-keycodes /dev/input/event16 --output-file=keychron.yml - Record mouse from Thinkpad touchpad (Synaptics TM3276-022) # libinput record --show-keycodes /dev/input/event6 --output-file=touchpad.yml - Replay # libinput replay touchpad.yml - Send a `PAGE_DOWN` event ([EV_KEY event](https://www.kernel.org/doc/html/latest/input/event-codes.html?#ev-key)) ``` evemu-event /dev/input/event16 --sync --type EV_KEY --code KEY_PAGEDOWN --value 1 && evemu-event /dev/input/event16 --sync --type EV_KEY --code KEY_PAGEDOWN --value 0 ``` - Send a MTS (multitouch pads) event ([absolute coordinates](https://www.kernel.org/doc/html/latest/input/event-codes.html?#touchscreens)) evemu-event /dev/input/event6 --sync --type EV_ABS --code ABS_MT_POSITION_Y --value 600 - Send a mouse event ([relative coordinates](https://www.kernel.org/doc/html/latest/input/event-codes.html?#mice)) evemu-event /dev/input/event6 --sync --type EV_REL --code REL_Y --value 10 I wrote a proof of concept script (`filter.py`) and talked with the [libinput maintainer](https://lists.freedesktop.org/archives/input-tools/2020-December/001551.html), this is a dead end.