![如何使用 xbindkeys 将修饰键(例如 CTRL)映射到鼠标拇指按钮](https://linux22.com/image/1085138/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%20xbindkeys%20%E5%B0%86%E4%BF%AE%E9%A5%B0%E9%94%AE%EF%BC%88%E4%BE%8B%E5%A6%82%20CTRL%EF%BC%89%E6%98%A0%E5%B0%84%E5%88%B0%E9%BC%A0%E6%A0%87%E6%8B%87%E6%8C%87%E6%8C%89%E9%92%AE.png)
这个问题已经有人问过了,但一直没有得到正确的回答。在得到@Seth的许可后,我现在再次提出这个问题。这将使我能够更轻松地回答并可能修改问题。原始问题可以在这里找到:
问题:
xbindkeys
尽管使用与鼠标键结合使用将任何按键映射到鼠标按钮非常简单,xdotool
但xte
映射修饰键似乎更加困难(例如谷氨酰胺,控制键,转移等等)。
最终的解决方案应该允许控制键+点击(例如,只需使用鼠标即可选择列表中的多个条目)。
在 Stack Exchange 以及其他 Linux 相关论坛上可以找到几种可能的解决方案。但这些方法都没有达到预期的效果,因为它们会导致其他问题和副作用。
笔记:
下面的一些例子涉及诡计和方案语法并依赖于.xbindkeysrc.scm
文件,而其他则依赖于.xbindkeysrc
具有其各自语法的文件。我知道它们不能一起工作。
此外,下面的代码片段xdotool
仅依赖于但我对涉及其他应用程序的方法持开放态度,例如xte
- 尽管它们似乎都导致相同的结果,因此我xdotool
在这里只使用操作。
方法A:
使用以下内容更新.xbindkeysrc
文件:
"xdotool keydown ctrl"
b:8
"xdotool keyup ctrl"
release + b:8
这是我最初尝试的,但它的副作用是修改器被保留并且无法释放。
方法 B:
使用以下内容更新.xbindkeysrc.scm
文件:
(xbindkey '("b:8") "xdotool keydown ctrl")
(xbindkey '(release "b:8") "xdotool keyup ctrl")
(xbindkey '("m:0x14" "b:8") "xdotool keydown ctrl")
(xbindkey '(release "m:0x14" "b:8") "xdotool keyup ctrl")
发现于http://www.linuxforums.org/forum/hardware-peripherals/169773-solved-map-mouse-button-modifier-key.html并尝试解决修饰符被保存的问题(如方法 a 所述)。
尽管它修复了仅部分起作用的问题,因为在按下拇指按钮时无法执行其他鼠标点击。
方法C:
使用以下内容更新.xbindkeysrc
文件:
"xdotool keydown ctrl"
b:8
"xdotool keyup ctrl"
release + control + b:8
由 askubuntu 上链接问题的 OP 尝试过。它更简单、更可靠,因为它不涉及修饰符状态。然而问题仍然存在,即控制键+点击不可能。
看来xbindkeys
问题本身就在这里,因为它识别点击但不会执行。可以使用xev | grep button
和进行测试xbindkeys -v
:
记录的正常鼠标点击xev
应如下所示:
state 0x10, button 1, same_screen YES
state 0x110, button 1, same_screen YES
以及拇指按钮:
state 0x10, button 8, same_screen YES
state 0x10, button 8, same_screen YES
但是,当启用上述xbindkeys
配置时,它不会记录任何内容。虽然这对拇指按钮来说是有意义的,因为它被映射到控制键因此不再是鼠标按钮,奇怪的是按钮 1也没有记录。这可能是因为xbindkeys
没有执行它,但它本身正在识别它:
Button press !
e.xbutton.button=8
e.xbutton.state=16
"xdotool keydown ctrl"
m:0x0 + b:8 (mouse)
got screen 0 for window 16d
Start program with fork+exec call
Button press !
e.xbutton.button=1
e.xbutton.state=20
Button release !
e.xbutton.button=1
e.xbutton.state=276
Button release !
e.xbutton.button=8
e.xbutton.state=20
"xdotool keyup ctrl"
Release + m:0x4 + b:8 (mouse)
got screen 0 for window 16d
Start program with fork+exec call
方法D:
使用以下内容更新.xbindkeysrc
文件:
"xdotool keydown ctrl"
b:8
"xdotool keyup ctrl"
release + control + b:8
"xdotool click 1"
b:1
太简单了...却导致无限循环点击。
更新:
与此同时,我买了一台 Logitech G502,发现一旦通过 Windows 上的驱动程序进行配置,不仅配置文件本身会存储在设备内存中,而且实际的按键也是通过鼠标完成的。这实际上解决了我在 Linux 上的问题!
我记得唯一一款能够做到这一点的鼠标是 Razer Copperhead。但我想现在还有其他鼠标可以做到这一点。
答案1
我花了很多时间尝试让这种绑定工作。我最终找到了一个解决方案,虽然很复杂,但效果很好,而且不需要第三方软件。我在这里分享它,希望它能帮助人们。此外,我知道这在安全性方面并不完美,所以任何建设性的反馈都是非常欢迎的。
有一些非常好的解决方案,就像这里提出的一样但它总是受到 xbindkeys 的限制,因为 xbindkeys 会抓取整个鼠标,导致修饰键 + 鼠标单击映射不确定。此外,上述链接中基于 guile 的解决方案使用 ctrl+plus/ctrl+minus,而 Gimp 无法识别。
我发现我们想要的是一个充当键盘的鼠标按钮,所以我使用了 uinput,它可以被访问通过python,编写了一个脚本,监控 /dev/my-mouse 上的拇指按钮点击并将 ctrl 键发送到虚拟键盘。以下是详细步骤:
1.制定udev规则
我们希望设备可以访问(权利和位置)。
对于鼠标:
/etc/udev/rules.d/93-mxmouse.conf.rules
------------------------------------------------------------
KERNEL=="event[0-9]*", SUBSYSTEM=="input", SUBSYSTEMS=="input",
ATTRS{name}=="Logitech Performance MX", SYMLINK+="my_mx_mouse",
GROUP="mxgrabber", MODE="640"
Udev 将查找内核识别的设备,其名称类似于 event5,然后我选择具有该名称的鼠标。SYMLINK 指令确保我将在 /dev/my_mx_mouse 中找到我的鼠标。该设备将可由“mxgrabber”组的成员读取。
要查找有关硬件的信息,你应该运行类似
udevadm info -a -n /dev/input/eventX
对于 uinput :
/etc/udev/rules.d/94-mxkey.rules
----------------------------------------------------
KERNEL=="uinput", GROUP="mxgrabber", MODE="660"
无需符号链接,uinput 始终处于$/dev/uinput
或$/dev/input/uinput
取决于您所使用的系统。当然,只需授予他组和读写权限即可。
您需要拔下 - 插入鼠标,新链接应出现在 /dev 中。您可以强制 udev 触发您的规则$udevadm trigger
2. 激活 UINPUT 模块
sudo modprobe uinput
并使其启动持久:
/etc/modules-load.d/uinput.conf
-----------------------------------------------
uinput
3. 创建新组
sudo groupadd mxgrabber
或者无论你如何称呼你的访问组。然后你应该将自己添加到其中:
sudo usermod -aG mxgrabber your_login
4.Python脚本
您需要安装python-uinput 库(显然)和python-evdev 库. 使用 pip 或您的分发包。
该脚本非常简单,您只需识别按钮的 event.code。
#!/usr/bin/python3.5
# -*- coding: utf-8 -*-
"""
Sort of mini driver.
Read a specific InputDevice (my_mx_mouse),
monitoring for special thumb button
Use uinput (virtual driver) to create a mini keyboard
Send ctrl keystroke on that keyboard
"""
from evdev import InputDevice, categorize, ecodes
import uinput
# Initialize keyboard, choosing used keys
ctrl_keyboard = uinput.Device([
uinput.KEY_KEYBOARD,
uinput.KEY_LEFTCTRL,
uinput.KEY_F4,
])
# Sort of initialization click (not sure if mandatory)
# ( "I'm-a-keyboard key" )
ctrl_keyboard.emit_click(uinput.KEY_KEYBOARD)
# Useful to list input devices
#for i in range(0,15):
# dev = InputDevice('/dev/input/event{}'.format(i))
# print(dev)
# Declare device patch.
# I made a udev rule to assure it's always the same name
dev = InputDevice('/dev/my_mx_mouse')
#print(dev)
ctrlkey_on = False
# Infinite monitoring loop
for event in dev.read_loop():
# My thumb button code (use "print(event)" to find)
if event.code == 280 :
# Button status, 1 is down, 0 is up
if event.value == 1:
ctrl_keyboard.emit(uinput.KEY_LEFTCTRL, 1)
ctrlkey_on = True
elif event.value == 0:
ctrl_keyboard.emit(uinput.KEY_LEFTCTRL, 0)
ctrlkey_on = False
5. 享受!
现在你需要做的就是让你的 Python 文件可执行,并让你的桌面管理器在启动时加载该文件。也许还可以喝一杯酒来庆祝你的出色工作!
6. 额外免费
我使用 xbindkeys 来实现其他行为。例如,如果您的鼠标带有滚轮侧点击功能,则以下配置可能很好:
~/.xbindkeysrc
---------------------------------------------
# Navigate between tabs with side wheel buttons
"xdotool key ctrl+Tab"
b:7
"xdotool key ctrl+shift+Tab"
b:6
# Close tab with ctrl + right click
# --clearmodifiers ensure that ctrl state will be
# restored if button is still pressed
"xdotool key --clearmodifiers ctrl+F4"
control+b:3
为了使最后一种组合发挥作用,您必须禁用为 Python 脚本配置的按钮,否则它仍将被 xbindkeys 抓取。只有 Ctrl 键必须保留:
~/.Xmodmap
-------------------------------------------
! Disable button 13
! Is mapped to ctrl with uinput and python script
pointer = 1 2 3 4 5 6 7 8 9 10 11 12 0 14 15
重新加载$ xmodmap ~/.Xmodmap
7. 结论
正如我在开头所说的,我不太满意我必须给自己授予写入 /dev/uinput 的权限,即使它被认为是“mxgrabber”组。我确信有更安全的方法可以做到这一点,但我不知道怎么做。
从好的方面来看,它确实非常有效。键盘或鼠标键的任何组合如何与键盘的 Ctrl 按钮配合使用现在都可以与鼠标的 Ctrl 按钮配合使用!
答案2
我找到了一个解决方案派用户输入。这最终变得非常简单,并且不需要管理权限。安装了 python 2 和 PyUserInput 后,我使用了以下脚本:
#!/usr/bin/python
from pymouse import PyMouseEvent
from pykeyboard import PyKeyboard
k = PyKeyboard()
class MouseToButton(PyMouseEvent):
def click(self, x, y, button, press):
if button == 8:
if press: # press
k.press_key(k.control_l_key)
else: # release
k.release_key(k.control_l_key)
C = MouseToButton()
C.run()
授予脚本执行权限后,我用一行来调用它~/.xsessionrc
,例如
〜/路径/到/script.py&
笔记. 这不会阻止鼠标按钮事件触发。就我而言,我曾经xinput set-button-map
更改 xinput 按钮映射,并将我感兴趣的按钮编号分配给未使用的内容。
例如,如果你想使用鼠标上的按钮 8,但按钮 8 已经有功能(例如page-next
),则可以使用以下命令.xsessionrc
logitech_mouse_id=$(xinput | grep "Logitech M705" | sed 's/^.*id=\([0-9]*\)[ \t].*$/\1/')
xinput set-button-map $logitech_mouse_id 1 2 3 4 5 6 7 12 9 10 11 12 13 14 15 16 17 18 19 20
./.xbuttonmodifier.py &
提供的按钮12
对操作系统没有任何意义,并为按钮分配一个自定义功能12
,.xbuttonmodifier.py
就像我上面描述的脚本一样。
答案3
我有一个部分解决方案。我还没有弄清楚如何取消映射现有按钮,所以你最终会得到一个按钮点击和你想要的修饰符。所以如果鼠标按钮有一些现有的用途,它仍然会触发。例如,将鼠标右键重新映射到控制键将导致发送控制+点击。
无论如何,我找到了一个与您的问题类似的论坛帖子,其答案是安装 btnx 并通过它配置您的修饰符。似乎 btnx 不再通过 repo 提供。有一个 ppa,但它不适用于最新的 ubuntu。
论坛帖子: 帖子:http://ubuntuforums.org/showthread.php?t=1245930
但源代码是可以找到的:
您可以从源代码进行编译,但这会将包管理器无法维护的文件放到您的系统中。
即以下文件:
/usr/local/sbin/btnx
/etc/init.d/btnx
/usr/share/pixmaps/btnx.png
/usr/share/btnx-config (directory, multiple files)
/usr/share/applications/btnx-config.desktop
/usr/share/omf/btnx-config/btnx-manual-C.omf
/usr/share/locale/de/LC_MESSAGES/btnx-config.mo
/usr/share/locale/fr/LC_MESSAGES/btnx-config.mo
/usr/share/locale/nl/LC_MESSAGES/btnx-config.mo
/usr/share/locale/ru/LC_MESSAGES/btnx-config.mo
以下符号链接:
/etc/rc0.d/K49btnx -> ../init.d/btnx
/etc/rc1.d/K49btnx -> ../init.d/btnx
/etc/rc6.d/K49btnx -> ../init.d/btnx
/etc/rc2.d/S49btnx -> ../init.d/btnx
/etc/rc3.d/S49btnx -> ../init.d/btnx
/etc/rc4.d/S49btnx -> ../init.d/btnx
/etc/rc5.d/S49btnx -> ../init.d/btnx
所以...如果您不介意从源代码构建...
获取 btnx 的依赖项:
sudo apt-get install libdaemon-dev git
如果您从未从源代码构建过任何东西,那么您可能也需要 build-essential:
sudo apt-get install build-essential
然后获取并编译btnx:
git clone https://github.com/cdobrich/btnx
cd btnx
./configure
make
sudo make install
cd -
它有一个单独的 GUI 配置工具。获取它的依赖项:
sudo apt-get install libgtk2.0-dev libglade2-dev
现在获取并编译 gui 配置工具:
git clone https://github.com/cdobrich/btnx-config
./configure
make
sudo make install
现在运行该工具:
sudo btnx-config
单击“检测鼠标按钮”如果您希望在使用该工具时能够阅读说明,请调整弹出窗口的大小,如果不这样做,对话框文本稍后会被剪切,如果您在检测期间尝试调整大小,它将取消检测。只需将窗口稍微放大一点即可。
单击“按下”开始鼠标检测,然后尝试不要移动鼠标,直到文本发生变化... 大约需要 5-10 秒。文本将会改变。当它改变时,忽略它的内容并单击“前进”。
点击“按下开始按钮检测”按钮
在这里,您将多次单击鼠标的一个按钮(直到状态栏填满)。然后将按钮的名称设置为您稍后会识别的名称(例如:LeftButton)单击“添加”按钮。
对每个鼠标按钮重复此操作(不要忘记滚轮、滚动点击等)。您可以跳过任何您不想重新映射的按钮。
添加完所有按钮后,单击“确定”。
在主 GUI 中,单击按钮,在左侧窗格中选择要重新映射的按钮。它将使用您在前面步骤中输入的名称。为了达到您的目的,您需要在右侧的组合键下选择一个键修饰符。
不要在此屏幕上单击删除,否则会删除该按钮。如果单击删除,则必须返回并再次检测该按钮。
返回配置屏幕并单击重新启动 btnx。
尝试一下新的按钮。
如果要卸载应用程序,请停止 btnx 程序,然后进入相应的 git 签出的目录并进行卸载:
sudo /etc/init.d/btnx stop
cd btnx
sudo make uninstall
cd -
cd btnx-config
sudo make uninstall
cd -
答案4
尽管已经很晚了,但这是我的解决方案。当然不是最优雅的,但它似乎有效(需要 xdotool)
我已将鼠标按钮更改为按住 ctrl 1 秒,并将我的 .xbindkeysrc 更改如下:
# Ctrl button pressed for 1 sec
"xdotool keydown ctrl;sleep 1;xdotool keyup ctrl"
b:10
# Show desktop
"wmctrl -k on"
b:11
# Restore desktop windows and release ctrl key
"wmctrl -k off;xdotool keyup ctrl"
control + b:11