Jade Dungeon

X11 输入配置

键盘

Linux系统,每个输入设备(ls -l /dev/input)都有以下的过程。

/keyboard/scancode/input driver/keycode/X server XKB/keysym

推荐从底层下手,改变scancode

交换CapslockCtrl

hwdb配置,修改scancode,每次变更好需要执行以下命令,才可生效。

sudo udevadm hwdb --update和sudo udevadm trigger
#/etc/udev/hwdb.d/79-a9-keyboard.hwdb
evdev:input:b0011v0001p0001*  # buitlin keyboard
 KEYBOARD_KEY_3a=leftctrl     # caps -> ctrl_l
 KEYBOARD_KEY_1d=capslock     # ctrl_l -> caps 

evdev:input:b0003v046Ap0011*  # usb keyboard
 KEYBOARD_KEY_70039=leftctrl  # caps -> ctrl_l
 KEYBOARD_KEY_700e0=capslock  # ctrl_l -> caps 

hwdb配置

制作此配置文件,需要evtest命令,sudo apt-get install evtest

首先记录KEYBOARD_KEY_,然后在记录设备

# root权限执行,或直接输入device路径,如/dev/input/event4
sudo evtest
# 输出如下
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0:	Lid Switch
/dev/input/event1:	Power Button
/dev/input/event2:	Sleep Button
/dev/input/event3:	Power Button
/dev/input/event4:	AT Translated Set 2 keyboard
/dev/input/event5:	Video Bus
/dev/input/event6:	Video Bus
/dev/input/event7:	SynPS/2 Synaptics TouchPad
/dev/input/event8:	Intel HID events
/dev/input/event9:	Integrated_Webcam_HD: Integrate
/dev/input/event10:	Dell WMI hotkeys
/dev/input/event11:	DLL06E5:01 06CB:7A13 Touchpad
/dev/input/event12:	HDA Intel PCH Headphone Mic
/dev/input/event13:	HDA Intel PCH HDMI/DP,pcm=3
/dev/input/event14:	HDA Intel PCH HDMI/DP,pcm=7
/dev/input/event15:	HDA Intel PCH HDMI/DP,pcm=8
/dev/input/event16:	HDA Intel PCH HDMI/DP,pcm=9
/dev/input/event17:	HDA Intel PCH HDMI/DP,pcm=10
/dev/input/event18:	Bluetooth Mouse M557
Select the device event number [0-18]: 
# 选择4,这是内置键盘,此时按需要修改的键,如Caps,Ctrl_L,Alt_R
Event: time 1532248945.036950, -------------- SYN_REPORT ------------
Event: time 1532248945.174908, type 4 (EV_MSC), code 4 (MSC_SCAN), value 3a
Event: time 1532248945.174908, type 1 (EV_KEY), code 29 (KEY_LEFTCTRL), value 0
Event: time 1532248948.101240, -------------- SYN_REPORT ------------
Event: time 1532248948.245571, type 4 (EV_MSC), code 4 (MSC_SCAN), value 1d
Event: time 1532248948.245571, type 1 (EV_KEY), code 58 (KEY_CAPSLOCK), value 0
Event: time 1532248948.245571, -------------- SYN_REPORT ------------
Event: time 1532248951.262652, type 4 (EV_MSC), code 4 (MSC_SCAN), value b8
Event: time 1532248951.262652, type 1 (EV_KEY), code 29 (KEY_LEFTCTRL), value 1
# 其中 value部分,就是对应的 KEYBOARD_KEY_,是16进制

接下来记录evdev:input:

# 选择上面的设备编号,event4,代入以下命令
grep "" /sys/class/input/event4/device/id/*
# 得到以下输出
/sys/class/input/event4/device/id/bustype:0011
/sys/class/input/event4/device/id/product:0001
/sys/class/input/event4/device/id/vendor:0001
/sys/class/input/event4/device/id/version:ab41

把上面的信息,都代入以下的格式

evdev:input:b[bustype]v[vendor]p[product]*
 KEYBOARD_KEY_[scancode]=[key code identifier]

注意,[bustype], [vendor], [product]都是4字符的,不够时前面补零。

同样的步骤,我们取得USB外接键盘的配置,一般来讲可以直接列出来,如果不存在,则

lsusb
# 大概如下输出,记住名字
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 8087:0a2b Intel Corp. 

ls -l /dev/input/by-id
# 大概如下输出,找到usb相配的名字,记住编号,如evnet9
usb-XXXXX -> ../event9

sudo evtest /dev/input/event9

以上配置完成后,一定要记得执行以下命令,

sudo udevadm hwdb --update
sudo udevadm trigger

触摸板

Thinkpad新触摸板禁用光标,把左键范围扩大到100%。方法为:

先安装xserver-xorg-input-synaptics

sudo apt install gnome-tweaks xserver-xorg-input-synaptics

启动gnome-tweaks,在input keyboarrd mouse里设置禁用触摸板。

也可以/usr/share/X11/xorg.conf.d/目录下添加配置文件, 文件名模式为99-*.conf,例如可以为99-touch.conf

Section "InputClass"
    Identifier "Default clickpad buttons"
    MatchDriver "synaptics"
    MatchDevicePath "/dev/input/event*"
    Option "ClickedPad" "true"
    Option "EmulateMidButtonTime" "0"
    Option "SoftButtonAreas" "66% 0 0 50% 33% 65% 0 50%"
    Option "AreaTopEdge" "100%"
    Option "PalmDetect" "1"
    Option "TapButton1" "1"
    Option "TapButton3" "2"
    Option "TapButton2" "3"
    Option "FastTaps" "1"
EndSection

Section "InputClass"
    Identifier "touchpad ignore duplicates"
    MatchIsTouchpad "on"
    MatchOS "Linux"
    MatchDevicePath "/dev/input/mouse*"
    Option "Ignore" "on"
EndSection

#Section "InputClass"
#	Identifier   "TrackPoint"
#	MatchProduct "TrackPoint"
#	MatchDriver  "evdev"
#	Option       "EmulateWheel"       "1"
#	Option       "EmulateWheelButton" "2"
#	Option       "XAxisMapping" 	  "6 7"
#EndSection

鼠标中键滚动

USB Optical Mouse

anwser 1

this works for me, Ubuntu 20.04/20.10: Note, it works everywhere, in every application. How to do this in wayland, I don't know although it is manipulating libinput so it should be possible.

This answer is merely an example of the accepted answer.

#/usr/share/X11/xorg.conf.d/41-libinput.conf
Section "InputClass"
        Identifier "Logitech USB Receiver Mouse"
        MatchIsPointer "on"
        MatchDevicePath "/dev/input/event*"
        Driver "libinput"
        Option "ScrollButton" "2"
        Option "ScrollMethod" "button"
        Option "NaturalScrolling" "true"
EndSection

anwser 2

To play with this configuration, use the xinput program (I don't know if there's a GUI frontend for it). First, run the following command to see the name of your pointing device:

$ xinput --list       
⎡ Virtual core pointer                          id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ Generic USB Mouse                         id=8    [slave  pointer  (2)]
⎜   ↳ Macintosh mouse button emulation          id=12   [slave  pointer  (2)]
⎣ Virtual core keyboard                         id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ Power Button                              id=7    [slave  keyboard (3)]
    ↳   USB Keyboard                            id=9    [slave  keyboard (3)]

For example, in the output above, the pointer device is Generic USB mouse. You can run the following command to list the properties that can be tuned:

xinput --list-props 'Generic USB Mouse'

The set of properties you're looking for are the “Evdev Wheel Emulation” ones. With the following settings, when the middle mouse button (button 2) is pressed, moving the mouse sends wheel events (4=up, 5=down, 6=left, 7=right).

xinput --set-prop 'Generic USB Mouse' 'Evdev Wheel Emulation' 1
xinput --set-prop 'Generic USB Mouse' 'Evdev Wheel Emulation Button' 2
xinput --set-prop 'Generic USB Mouse' 'Evdev Wheel Emulation Axes' 6 7 4 5

You may want to tweak other parameters (inertia, timeout).

You can put these commands in a script. Add #!/bin/sh as the very first line, and make the script file executable (e.g. chmod +x ~/bin/activate-wheel-emulation.sh). Then add that script to the list of commands to run when your session starts (gnome-session-properties lets you configure that).

If you have root access and you want to make the change for all users (acceptable on a home machine), it's simpler to do it via the X.org server configuration file. As root, create a file called /etc/X11/xorg.conf.d/wheel-emulation.conf containing settings for the mouse driver. The settings are the same but they're organized a bit differently.

Section "InputClass"
    Identifier "Wheel Emulation"
    MatchProduct "Generic USB Mouse"
    Option "EmulateWheel" "on"
    Option "EmulateWheelButton" "2"
    Option "XAxisMapping" "6 7"
    Option "YAxisMapping" "4 5"
EndSection

answer 3

his will work with all your applications without the need of installing anything.

Get your input deviceID. In my case was 11.

xinput list

If you want, list available properties with xinput list-props <deviceID>. If you are using libinput (the future/present), almost all properties will start with libinput. For evdev check my answer here. With libinput

Set mouse properties

xinput set-prop 11 "libinput Scroll Method Enabled" 0, 0, 1  # This is button
xinput set-prop 11 "libinput Button Scrolling Button" 2      # This is middle mouse. Already 2 by default

Description from man libinput:

  • libinput Scroll Method Enabled 3 boolean values (8 bit, 0 or 1), in order "two-finger", "edge", "button". Indicates which scroll method is currently enabled n this device.
  • libinput Button Scrolling Button 1 32-bit value. Sets the button number to use for button scrolling. This setting is independent of the scroll method, to nable button scrolling the method must be set to button-scrolling and a valid button must be set.

answer 3b

Save this file as a script (for example: ~/setup_middle_click_scrolling.sh), make it executable with chmod +x, then run it (you can delete it after you run). It enables middle-click to scroll and also adds a startup script so that you get the functionality whenever you log in.

#!/bin/bash
# Enables middle click to scroll (like Windows).
set -e

: ${SCRIPT_PATH:=$(realpath ~/.config/autostart/middle_click_to_scroll.sh)}
: ${DESKTOP_PATH:=~/.config/autostart/middle_click_to_scroll.desktop}

# Create dirs if they don't exist.
echo "$SCRIPT_PATH" "$DESKTOP_PATH" | xargs dirname | xargs mkdir -p

# Create a script that can be run on-demand.
# When run, it enables middle-click to scroll.
cat > "$SCRIPT_PATH" <<EOF
#!/bin/bash

# Get device IDs of all devices containing "pointer"
pointer_ids=($(xinput list | grep pointer | perl -p -e 's@.*?id=(\d+).*@\1@'))

for pointer_id in "${pointer_ids[@]}"; do
  # If the pointer supports scroll method, set middle click to scroll
  if xinput list-props "$pointer_id" | grep 'Scroll Method Enabled' &>/dev/null; then
    xinput set-prop "$pointer_id" 'libinput Scroll Method Enabled' 0 0 1
  fi
done
EOF
chmod +x "$SCRIPT_PATH"

# Create a desktop entry so it runs on startup.
cat > "$DESKTOP_PATH" <<EOF
[Desktop Entry]
Type=Application
Name=Middle click to scroll
Exec="$SCRIPT_PATH"
X-GNOME-Autostart-Phase=Initialization
Terminal=false
NoDisplay=true
EOF

"$SCRIPT_PATH"

Someone edited my post to change \({pointer_ids[@]} to \\){pointer_ids[@]} -- I don't know what shell you're using but that does not work in Bash, so I'm changing the answer back. I'm on bash 5.0.17.

answer 5

Expanding on Brandon Duffany's answer - his script didn't work on my system (Ubuntu 20.04.3 LTS) and after some debugging, I found it was likely because of the for loop. It behaved as if pointer_ids array was full of empty values and the script just kept returning unable to find device. I figured it was some bash trickery with badly recognized array values so I rewrote the loop.

I made smaller bash script file <path-to-file>/middle-click-emulation.sh:

#!/bin/bash
# Enables middle click to scroll (like Windows).
pointerids=($(xinput list | grep "pointer" | perl -p -e 's@.*?id=(\d+).*@\1@'))

for ((i = 0; i < ${#pointerids[@]}; i++))
do
  echo "Setting up for device id = ${pointerids[$i]}"
  # If the pointer supports scroll method, set middle click to scroll
  if xinput list-props ${pointerids[$i]} | grep 'Scroll Method Enabled' &>/dev/null; then
    xinput set-prop ${pointerids[$i]} 'libinput Scroll Method Enabled' 0 0 1
  fi
done

Manually created the desktop shortcut in ~/.config/autostart/middle_click_to_scroll.sh:

#!/usr/bin/env xdg-open
[Desktop Entry]
Type=Application
Name=Middle click to scroll emulation
Exec="<path-to-file>/middle-click-emulation.sh"
X-GNOME-Autostart-Phase=Initialization
Terminal=false
NoDisplay=true

And gave executable privileges to both the bash script and the desktop shortcut.

And then manually run the script cause I'm too lazy to reboot :-)

Thank you, Brandon :-)

PS: I think you can still use the Brandon's script which creates the desktop shortcuts for you if you replace just the for loop (watch out for the array name).