DUAL-FUNCTION-KEYS(1) User Manuals DUAL-FUNCTION-KEYS(1) (NAME) interception - (dual function keys) (DESCRIPTION) . (modifier) : ctrl delete. . interception (). (QUICK START) 1. /etc/interception/dual-function-keys/my-mappings.yaml . () . 2. udevmon interception () : /etc/interception/udevmon.d/my-keyboards.yaml. . 3. udevmon: sudo systemctl enable udevmon 4. () udevmon: sudo systemctl restart udevmon 5. : journalctl -u udevmon. ( ). ignoring /etc/interception/udevmon.yaml, reason: bad file: /etc/interception/udevmon.yaml . (FUNCTIONALITY) (LS) . delete (DE) LS . - KEY: KEY_LEFTSHIFT TAP: KEY_DELETE HOLD: KEY_LEFTSHIFT (Tap) LS TAP_MILLIS ( ) DE. LS . . <---------200ms---------> <---------200ms---------> keyboard: LSv LS^ LSv LS^ computer sees: LSv LS^ DEv DE^ LSv LS^ (Double Tap) DOUBLE_TAP_MILLIS ( ) DE . <-------150ms-------> <---------200ms---------> keyboard: LSv LS^ LSv LS^ computer sees: LSv LS^ DEv DE^ DEv ..(repeats).. DE^ DOUBLE_TAP_MILLIS . (Consumption) TAP_MILLIS (tap) . ctrl-C. a . . (EV_REL EV_ABS) (Multiple Devices) . <-------150ms-------> <---------200ms---------> <-------150ms-------> <---------200ms---------> keyboard: LSv av a^ LS^ LSv LS^ LSv computer sees: LSv av a^ LS^ LSv LS^ DEv DE^ DEv ..(repeats).. (INSTALLATION) (Package Manager) [: ()] () (From Source) (). Interception Tools () . git clone https://gitlab.com/interception/linux/plugins/dual-function-keys.git cd dual-function-keys make && sudo make install /usr/local . config.mk ..SH " (CONFIGURATION)" : dual-function-keys udevmon dual-function- keys . (https://gitlab.com/interception/linux/plugins/dual-function- keys/-/tree/master/doc/examples.md) dual-function-keys udevmon.yaml . dual-function-keys yaml /etc/interception/dual-function-keys . ( ) #define input-event-codes.h (https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h) . # optional TIMING: TAP_MILLISEC: DOUBLE_TAP_MILLISEC: SYNTHETIC_KEYS_PAUSE_MILLISEC: # necessary MAPPINGS: - KEY: TAP: [ , ... ] HOLD: [ , ... ] # optional HOLD_START: [ AFTER_PRESS | AFTER_RELEASE | BEFORE_CONSUME | BEFORE_CONSUME_OR_RELEASE ] - KEY: ... : TIMING: TAP_MILLISEC: 200 DOUBLE_TAP_MILLISEC: 150 MAPPINGS: - KEY: KEY_LEFTSHIFT TAP: KEY_DELETE HOLD: KEY_LEFTSHIFT (Combo Keys) TAP " (combo)" space cadet (: MAPPINGS: - KEY: KEY_LEFTSHIFT TAP: [ KEY_LEFTSHIFT, KEY_9, ] HOLD: KEY_LEFTSHIFT HOLD " (combo)" (hyper modifier): MAPPINGS: - KEY: KEY_TAB TAP: KEY_TAB HOLD: [ KEY_LEFTCTRL, KEY_LEFTMETA, KEY_LEFTALT, ] "" . : TIMING: SYNTHETIC_KEYS_PAUSE_MILLISEC: 10 HOLD HOLD_START HOLD . HOLD_START: AFTER_PRESS HOLD_START AFTER_PRESS . HOLD_START: BEFORE_CONSUME HOLD KEY KEY . KEY (tap) TAP HOLD (modifiers) . MAPPINGS: - KEY: KEY_LEFTSHIFT TAP: KEY_DELETE HOLD: KEY_LEFTSHIFT HOLD_START: BEFORE_CONSUME <---------200ms---------> <---------200ms---------> keyboard: LSv LS^ LSv LS^ computer sees: DEv DE^ <-------150ms-------> <---------200ms---------> <-------150ms-------> <---------200ms---------> keyboard: LSv av a^ LS^ LSv LS^ LSv computer sees: LSv av a^ LS^ DEv DE^ DEv ..(repeats).. HOLD_START: BEFORE_CONSUME_OR_RELEASE BEFORE_CONSUME KEY HOLD . MAPPINGS: - KEY: KEY_LEFTSHIFT TAP: KEY_DELETE HOLD: KEY_LEFTSHIFT HOLD_START: BEFORE_CONSUME_OR_RELEASE <---------200ms---------> <---------200ms---------> keyboard: LSv LS^ LSv LS^ computer sees: DEv DE^ LSv LS^ (Hold) TAP_MILLISEC . (consumption) . MAPPINGS: - KEY: KEY_A TAP: KEY_A HOLD: [KEY_LEFTSHIFT, KEY_A] HOLD_START: AFTER_RELEASE <---------200ms---------> <---------200ms---------> keyboard: av a^ av a^ computer sees: av a^ Av A^ (Warning) (modifier) . alt-tab space-caps: MAPPINGS: - KEY: KEY_CAPSLOCK TAP: KEY_TAB HOLD: KEY_LEFTALT - KEY: KEY_SPACE TAP: KEY_SPACE HOLD: KEY_RIGHTALT HOLD_START: BEFORE_CONSUME HOLD_START: BEFORE_CONSUME_OR_RELEASE : MAPPINGS: - KEY: KEY_CAPSLOCK TAP: KEY_TAB HOLD: KEY_LEFTALT HOLD_START: BEFORE_CONSUME_OR_RELEASE - KEY: KEY_SPACE TAP: KEY_SPACE HOLD: KEY_LEFTALT HOLD_START: BEFORE_CONSUME_OR_RELEASE udevmon udevmon (Dual Function Keys) . (https://gitlab.com/interception/linux/tools#how-it-works) . - JOB: "intercept -g $DEVNODE | dual-function-keys -c | uinput -d $DEVNODE" DEVICE: NAME: : sudo uinput -p -d /dev/input/by-id/X X . EV_KEY EVENTS . /dev/input/by-id /dev/input . uinput -p Interception Tools: How It Works (https://gitlab.com/interception/linux/tools#how-it-works) . . dual-function-keys . /etc/interception/udevmon.d/my-keyboards.yaml : - JOB: "intercept -g $DEVNODE | dual-function-keys -c /etc/interception/dual-function-keys/home-row-modifiers.yaml | uinput -d $DEVNODE" DEVICE: NAME: "Minimalist Keyboard ABC" EVENTS: EV_KEY: [ KEY_LEFTSHIFT ] - JOB: "intercept -g $DEVNODE | dual-function-keys -c /etc/interception/dual-function-keys/thumb-cluster.yaml | uinput -d $DEVNODE" DEVICE: NAME: "Split Keyboard XYZ" EVENTS: EV_KEY: [ KEY_LEFTSHIFT ] (Multiple Devices) ctrl-scroll dual-function-keys ( ctrl ) (mux) (https://gitlab.com/interception/linux/tools#mux) . udevmon : - CMD: mux -c dfk -c my-keyboard -c my-mouse - JOB: - mux -i dfk | dual-function-keys -c /etc/interception/dual-function-keys/my-cfg.yaml | mux -o my-keyboard -o my-mouse - mux -i my-keyboard | uinput -c /etc/interception/udevmon.d/my-keyboard.yaml - mux -i my-mouse | uinput -c /etc/interception/udevmon.d/my-mouse.yaml - JOB: intercept -g $DEVNODE | mux -o dfk DEVICE: NAME: AT Translated Set 2 keyboard EVENTS: EV_KEY: [ KEY_LEFTCTRL ] - JOB: intercept -g $DEVNODE | mux -o dfk DEVICE: NAME: Razer Razer Naga Trinity EVENTS: EV_REL: [REL_WHEEL] EV_KEY: [BTN_LEFT] my-keyboard.yaml my-mouse.yaml udevmon . : sudo uinput -p -d /dev/input/by-id/usb-my-keyboard-kbd > my-keyboard.yaml (https://gitlab.com/interception/linux/plugins/dual-function- keys/-/issues/31#note_725722450) (on the fly) : - CMD: mux -c dfk -c my-keyboard -c my-mouse - JOB: - mux -i dfk | dual-function-keys -c /etc/interception/dual-function-keys/my-cfg.yaml | mux -o my-keyboard -o my-mouse - mux -i my-keyboard | uinput -d /dev/input/by-path/my-keyboard-event-kbd - mux -i my-mouse | uinput -d /dev/input/by-id/usb-my-mouse-event-mouse - JOB: intercept -g $DEVNODE | mux -o dfk DEVICE: LINK: /dev/input/by-path/my-keyboard-event-kbd - JOB: intercept -g $DEVNODE | mux -o dfk DEVICE: LINK: /dev/input/by-id/usb-my-mouse-event-mouse : dual-function-keys keycodes keysyms X11 Wayland . keycode->keysym XKB (https://www.x.org/wiki/XKB) xmodmap (https://wiki.archlinux.org/index.php/Xmodmap) dual-function-keys . XKB X11 : Option "XkbModel" "pc105" Option "XKbLayout" "us" Option "XkbVariant" "dvp" Option "XkbOptions" "caps:escape" (FAQ) . issue . dual-function-keys . . PR . udevmon q.m.k HHKB . QMK Firmware (https://qmk.fm) . Tap-Hold (https://docs.qmk.fm/#/tap_hold) ! dual-function-keys . : 1. QMK Firmware . 2. Tap-Hold (https://docs.qmk.fm) . 3. . Ergodox (~800 ) HHKB (~140) . xcape (https://github.com/alols/xcape) xcape tap/hold . XTestFakeKeyEvent ( ) . (window manager) . (Double Tap) DOUBLE_TAP_MILLISEC 0 . Key Combinations, No Double Tap (https://gitlab.com/interception/linux/plugins/dual-function- keys/-/blob/master/doc/examples.md#key-combinations-no-double-tap) . (CONTRIBUTORS) PR . pandoc dual-function-keys.md make doc . README.md dual-function-keys.1 . man -l dual-function-keys.1 . .editorconfig . (LICENSE) (C) 2020 Alexander Courtis (AUTHORS) Alexander Courtis. Dual Function Keys 2020/12/25 DUAL-FUNCTION-KEYS(1)