问题描述
我周末一直在努力解决这个问题,需要重新映射我的鼠标按钮。
最佳方法
我有一个带有 9 个按钮的 Logitech 鼠标,按下 “middle button” (#2) 需要点击滚轮。我不喜欢这样,因为我很笨拙,当我尝试点击滚轮时,通常会滚动我所在的窗口。所以我想自动将顶部按钮(本例中为 #9)重新映射到中间按钮(#2)。我还想映射底部按钮(#8),以便它执行双击左键(#1)。
虽然我的目的很具体,但下面的解决方案可以推广到您想要在启动时自动重新映射鼠标按钮的任何情况。
将鼠标按钮映射到其他鼠标按钮
您需要安装 xinput
才能完成此任务。这可以完全在 .xsessionrc
文件中完成。首先,使用 xinput
来发现分配给鼠标的名称,然后将其与输入设备 ID 关联。以下是我的笔记本电脑的一些示例输出:
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ Logitech USB Laser Mouse id=11 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
我的鼠标自称 Logitech USB Laser Mouse
,显示为 id=11
。您的鼠标将具有不同的名称;弄清楚这一点留给读者作为练习。
当您仍然知道此会话中设备的 ID 时,请使用 xinput list
deviceID
找出输入处理程序认为您的鼠标有多少个按钮。这可能与设备上显示的按钮数量不同。
Logitech USB Laser Mouse id=11 [slave pointer (2)]
Reporting 7 classes:
Class originated from: 11. Type: XIButtonClass
Buttons supported: 16
Button labels: "Button Left" "Button Middle" "Button Right" "Button Wheel Up" "Button Wheel Down" "Button Horiz Wheel Left" "Button Horiz Wheel Right" "Button Side" "Button Extra" "Button Forward" "Button Back" "Button Task" "Button Unknown" "Button Unknown" "Button Unknown" "Button Unknown"
我的鼠标只有 9 个明显的物理按钮,但 xinput
报告有 16 个。
鉴于 USB 的特性,此 ID 每次重新启动时都会发生变化,因此仅编写静态键入您一次发现的 ID 的脚本是不够的。您必须在启动时动态解析它并根据当前 ID 执行您的 re-map。
现在您知道了它的名称,您可以使用 xinput test
deviceID
来确定要重新映射哪个键。按下要从其映射的鼠标按钮,以获取它们的索引。(作为参考,1、2 和 3 “always”(即通常)指的是 3 键鼠标的左键、中键和右键。常见的 re-map 将这些按钮反转,使鼠标成为 left-handed。)
button press 2
button release 2
button press 9
button release 9
在这种情况下,我发现我想将按钮#9(侧面,顶部)映射到按钮#2(中间)。
现在您知道了鼠标的名称以及要更改哪些按钮,您可以编写一个 ~/.xsessionrc
脚本,该脚本调用 xinput
在启动时执行按钮 re-mapping。以下是我的完整脚本。
# Map button 9 (top side button) to button 2 (middle button)
my_mouse_id=$(xinput | grep -m 1 "Logitech USB Laser Mouse" | sed 's/^.*id=\([0-9]*\)[ \t].*$/\1/')
echo $my_mouse_id > ~/temp/my_mouse_id
xinput set-button-map $my_mouse_id 1 2 3 4 5 6 7 8 2 10 11 12 13 14 15 16
此处的第一行设置了一个临时会话变量,该变量等于 xinput
报告的鼠标 ID。这是通过 grep
查找来自 xinput
的报告中鼠标的已知名称,然后使用 sed
从报告中的 id=xxx
标记中提取 ID 号来实现的。然后,此值用于 xinput set-button-map
指令,该指令执行 re-mapping。在上面的示例中,唯一的变化是按钮 #9 被 re-mapped 模仿按钮 #2。所有其他按钮均保持其默认设置。
更新:正如@Lokasenna 指出的 below ,如果您的设备将自己报告为鼠标和键盘,则可能需要使用 -m 1
来限制 grep
的结果计数。如果鼠标没有将自己报告为两者,这不会造成问题,因此它已包含在脚本中。
将鼠标按钮映射到任意功能
另请参阅 this answer 。
为此任务,您需要安装 xinput
、xbindkeys
和 xautomation
(包括 xte
)。
使用 xinput list
和 xinput test
来查找鼠标的设备 ID 和要分配的按钮编号。就我而言,我想将底部按钮 (#8) 映射到双击左键 (#1)。
创建或编辑 ~/.xbindkeysrc
。此文件的格式是一系列成对的行。第一行是针对事件执行的命令;第二行是事件描述。我们将使用 xautomation
的 xte
组件将事件直接发送到输入处理程序。
为了在释放按钮时创建双击事件,我添加了以下内容:
"/usr/bin/xte 'mouseclick 1' 'mouseclick 1' &"
b:8 + Release
此配置将鼠标单击按钮 #1 两次的序列映射到释放按钮 #8。(理论上,我猜你可以将任何命令映射到鼠标按钮,但这是最常见的情况。有关其他实际示例,请参阅 this answer。)
针对 16.04 Ubuntu 的更新
对于系统上连接了多个鼠标的用户,您还需要传入设备的 ID。这可能不适用于所有用户,并且是在使用 Unity 的 Ubuntu 16.04 上发现的。
xinput list
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ Kensington Kensington Expert Mouse id=9 [slave pointer (2)]
⎜ ↳ SynPS/2 Synaptics TouchPad id=13 [slave pointer (2)]
⎜ ↳ TPPS/2 IBM TrackPoint id=14 [slave pointer (2)]
然后通过引用命令输出中的 id= 值来修改 .xbindkeysrc 文件(此示例中为 id=9):
"/usr/bin/xte -i 9 'mouseclick 1' 'mouseclick 1' &"
b:8 + Release
次佳方法
简要步骤如下:
有一个名为 xinput
的实用程序。xinput list
或 xinput
将显示所有 X 输入设备及其 ID。在这里您可以找到要重新映射的鼠标的 ID。
我将使用我的 ID 作为示例,从我的设置来看,它是 21,然后 xinput --get-button-map 21
将输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
现在,如果你想交换左右按钮,只需运行
xinput --set-button-map 21 3 2 1
到这里,重新映射已经完成。
要在启动时运行它,只需将其放入文件中:
echo "xinput --set-button-map 21 3 2 1" > leftmouseremap.sh
赋予它可执行权限
chmod +x leftmouseremap.sh
最后,从 GUI 手动将其添加到 Statrtup Application,或者,如果您希望从 CLI 添加到 Statrtup Application,请将下面的文本(将路径更改为您的路径)放入 ~/.config/autostart
中的文件中,这是我的(less .config/autostart/leftmouseremap.sh.desktop
):
[Desktop Entry]
Type=Application
Exec=/home/ruslan/leftmouseremap.sh
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
Name[en_US]=/home/ruslan/leftmouseremap.sh
Name=/home/ruslan/leftmouseremap.sh
Comment[en_US]=
Comment=
请记住,对于 KDE,路径应该类似于 ~/.kde/Autosart
,对于其他桌面管理器,路径可能略有不同。或者,可以使用 /etc/rc.local
以常规方法进行启动运行。
第三种方法
使用 zerobandwidth’s great answer 时,某些设备(例如 Logitech 的 MX Ergo)会同时显示为指针和键盘设备:
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ Logitech MX Ergo id=10 [slave pointer (2)]
⎜ ↳ SynPS/2 Synaptics TouchPad id=14 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
↳ Power Button id=6 [slave keyboard (3)]
...
↳ Logitech MX Ergo id=15 [slave keyboard (3)]
因此,grep "Logitech MX Ergo"
最终返回两个值。后者最终被包含在映射字符串中作为第一项,并搞砸了所有鼠标按钮。
修复很简单 – 只需使用 grep
的 maximum-count 参数 -m 1
:
my_mouse_id=$(xinput | grep -m 1 "Logitech MX Ergo" | sed 's/^.*id=\([0-9]*\)[ \t].*$/\1/')
echo $my_mouse_id > ~/temp/my_mouse_id
xinput --set-button-map $my_mouse_id 1 2 3 4 5 6 7 8 2 10 11 12 13 14 15 16