如何使用 xbindkeys 将修饰符(例如 CTRL)映射到鼠标拇指按钮

con*_*uxe 16 mouse xte xdotool xbindkeys

这个问题已经被问到,但从未得到正确回答。与@Seth 通关后,我现在再次询问。这将使我能够更轻松地回答并可能修改问题。原始问题可以在这里找到:

将 Ctrl 和 Alt 映射到鼠标拇指按钮


问题:

虽然这是非常简单的任何按键动作映射到使用鼠标按钮xbindkeys会同xdotoolxte似乎多了很多问题映射一个修改键(如ALTCTRLSHIFT等)给它。

最终的解决方案应该允许仅使用鼠标CTRL +单击(例如,用于选择列表的多个条目)。

可以在 Stack Exchange 以及其他 Linux 相关论坛上找到解决此问题的几种可能方法。但是这些都没有按预期工作,因为它们会导致其他问题和副作用。

笔记:

下面的一些示例涉及带有Scheme语法的Guile并依赖于文件,而其他示例则依赖于具有各自语法的文件。我知道他们不会一起工作。.xbindkeysrc.scm.xbindkeysrc

此外,下面的片段xdotool仅依赖于,但我对涉及其他应用程序的方法持开放态度,例如xte,尽管它似乎都导致相同的结果,因此我在xdotool这里只使用操作。

方法一:

使用以下内容更新.xbindkeysrc文件:

"xdotool keydown ctrl"
  b:8

"xdotool keyup ctrl"
  release + b:8
Run Code Online (Sandbox Code Playgroud)

这就是我最初尝试的,但它有一个副作用,即修饰符被保留并且无法释放。

方法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")
Run Code Online (Sandbox Code Playgroud)

位于http://www.linuxforums.org/forum/hardware-peripherals/169773-solved-map-mouse-button-modifier-key.html并尝试解决修改器被持有的问题(如方法中所述一种)。

虽然它修复了它只能部分工作的问题,因为在按下拇指按钮时无法执行其他鼠标点击。

方法 C:

使用以下内容更新.xbindkeysrc文件:

"xdotool keydown ctrl"
  b:8

"xdotool keyup ctrl"
  release + control + b:8
Run Code Online (Sandbox Code Playgroud)

由 OP 在 askubuntu 上对链接问题进行了尝试。更简单、更可靠,因为它不涉及修饰符状态。尽管如此,问题仍然存在,即无法CTRL +单击

似乎它xbindkeys本身就是这里的问题,因为它识别点击但不会执行它。这可以使用xev | grep button和进行测试xbindkeys -v

记录的正常鼠标单击xev应如下所示:

state 0x10, button 1, same_screen YES
state 0x110, button 1, same_screen YES
Run Code Online (Sandbox Code Playgroud)

以及拇指按钮:

state 0x10, button 8, same_screen YES
state 0x10, button 8, same_screen YES
Run Code Online (Sandbox Code Playgroud)

但是当xbindkeys启用上述配置时,它不会记录任何内容。虽然拇指按钮是有意义的,因为它被映射到CTRL并且因此不再是鼠标按钮,但奇怪的是按钮 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
Run Code Online (Sandbox Code Playgroud)

方法 D:

使用以下内容更新.xbindkeysrc文件:

"xdotool keydown ctrl"
  b:8

"xdotool keyup ctrl"
  release + control + b:8

"xdotool click 1"
  b:1
Run Code Online (Sandbox Code Playgroud)

太简单了……但会导致无限循环点击。


更新:

与此同时,我买了一台罗技 G502,并注意到一旦通过 Windows 上的驱动程序进行配置,不仅配置文件本身存储在设备内存中,而且实际的按键操作是由鼠标完成的。这实际上解决了我在 Linux 上的问题!

我记得唯一能够做到这一点的鼠标是当时的 Razer Copperhead。但我想今天还有其他鼠标可以做同样的事情。

Aur*_*rio 8

我花了很多时间试图使绑定工作。我最终找到了一个解决方案,它很复杂但效果很好,并不意味着第三方软件。我在这里分享它希望它会帮助人们。此外,我知道这在安全性方面并不完美,因此非常欢迎任何建设性的反馈。

有一些非常好的解决方案,就像这里提出的那样,但它总是受到 xbindkeys 抓取整个鼠标的限制,使得修改器+鼠标点击映射不确定。另外,来自上述链接的基于 guile 的解决方案使用 ctrl+plus/ctrl+minus,例如 Gimp 无法识别。

我发现我们想要的是一个充当键盘的鼠标按钮,所以我使用了可以通过 python访问的 uinput ,编写了一个脚本来监视 /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"
Run Code Online (Sandbox Code Playgroud)

Udev 将查找内核识别的设备,其名称类似于 event5,然后我选择带有该名称的鼠标。SYMLINK 指令确保我会在 /dev/my_mx_mouse 中找到我的鼠标。该设备将由“mxgrabber”组的成员读取。

要查找有关您的硬件的信息,您应该运行类似

udevadm info -a -n /dev/input/eventX
Run Code Online (Sandbox Code Playgroud)

对于 uinput :

/etc/udev/rules.d/94-mxkey.rules
----------------------------------------------------
KERNEL=="uinput", GROUP="mxgrabber", MODE="660"
Run Code Online (Sandbox Code Playgroud)

不需要符号链接,uinput 将始终在$/dev/uinput$/dev/input/uinput取决于您所在的系统。当然,只要给他小组和阅读和写作的权利。

您需要拔下 - 插入鼠标,新链接应出现在 /dev 中。您可以强制 udev 触发您的规则$udevadm trigger

2. 激活 UINPUT 模块

sudo modprobe uinput
Run Code Online (Sandbox Code Playgroud)

并使其启动持久:

/etc/modules-load.d/uinput.conf
-----------------------------------------------
uinput
Run Code Online (Sandbox Code Playgroud)

3.新建组

sudo groupadd mxgrabber
Run Code Online (Sandbox Code Playgroud)

或任何您称为访问组的内容。那么你应该将自己添加到其中:

sudo usermod -aG mxgrabber your_login
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

要使最后一个组合起作用,您必须禁用为 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
Run Code Online (Sandbox Code Playgroud)

重新加载 $ xmodmap ~/.Xmodmap

7. 结论

正如我在开始时所说的,我对我必须给自己写信给 /dev/uinput 的事实并不完全满意,即使它被认为是“mxgrabber”组。我确信有一种更安全的方法可以做到这一点,但我不知道如何做到。

从好的方面来说,它的效果非常非常好。键盘或鼠标键的任何组合如何与键盘的 Ctrl 按钮一起使用现在可以与鼠标之一一起使用!


Max*_*xim 6

我找到了PyUserInput的解决方案。这最终非常简单,不需要管理权限。安装了 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()
Run Code Online (Sandbox Code Playgroud)

在赋予脚本执行权限后,我用一行 in 调用它~/.xsessionrc,例如

~/path/to/script.py &

Note. this does not prevent the mouse button event from firing. In my case I used xinput set-button-map to change the xinput button mapping and assign the number of the button I was interested in to something that was not in use.

For instance, if you want to use button 8 on your mouse but button 8 has already a function (for instance, page-next), you could use the following .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 &
Run Code Online (Sandbox Code Playgroud)

provided button 12 carries no meaning to the OS, and assign a custom function to button 12 in .xbuttonmodifier.py, the script I described above.


Ste*_*hen 2

我有一个部分解决方案。我还没有弄清楚如何取消映射现有按钮,因此您最终会单击按钮并获得所需的修改器。因此,如果该鼠标按钮有某种现有用途,它仍然会触发。例如,将鼠标右键重新映射到控制键将导致发送控制+单击。

不管怎样,我发现了一个与你的问题类似的论坛帖子,答案是安装 btnx 并通过它配置你的修改器。似乎 btnx 不再可以通过存储库获得。有一个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
Run Code Online (Sandbox Code Playgroud)

以下符号链接:

/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
Run Code Online (Sandbox Code Playgroud)

所以...如果你不介意从源代码构建...

获取 btnx 的依赖项:

sudo apt-get install libdaemon-dev git
Run Code Online (Sandbox Code Playgroud)

如果您从未从源代码构建过任何东西,那么您可能也需要 build-essential:

sudo apt-get install build-essential
Run Code Online (Sandbox Code Playgroud)

然后获取并编译btnx:

git clone https://github.com/cdobrich/btnx
cd btnx
./configure
make
sudo make install
cd -
Run Code Online (Sandbox Code Playgroud)

它有一个单独的 GUI 配置工具。获取它的依赖项:

sudo apt-get install libgtk2.0-dev libglade2-dev
Run Code Online (Sandbox Code Playgroud)

现在获取并编译 gui 配置工具:

git clone https://github.com/cdobrich/btnx-config
./configure
make
sudo make install
Run Code Online (Sandbox Code Playgroud)

现在运行该工具:

sudo btnx-config
Run Code Online (Sandbox Code Playgroud)

单击“检测鼠标按钮”如果您希望在使用该工具时能够阅读说明,请调整弹出窗口的大小,如果不这样做,对话框文本稍后会被剪切,如果您在检测期间尝试调整大小,它将取消检测。把窗户弄大一点就可以了。

单击“Press”开始鼠标检测,然后尝试不要移动鼠标,直到文本发生变化...大约需要 5-10 秒。文字将会改变。当出现这种情况时,请忽略它所说的内容并单击“前进”。

单击“按下开始按钮检测”按钮

在这里,您将多次单击鼠标的一个按钮(直到状态栏填满)。然后将按钮的名称设置为您稍后会识别的名称(例如:LeftButton) 单击“添加”按钮。

对每个鼠标按钮重复此操作(不要忘记滚轮、滚动点击等)。您可以跳过任何不想重新映射的按钮。

添加完所有按钮后,单击“确定”。

在主 GUI 中,单击“按钮”,在左侧窗格中选择要重新映射的按钮。它将使用您在前面步骤中输入的名称。出于您的目的,您只需选择右侧按键组合下的按键修饰符。

不要单击此屏幕上的“删除”,它会删除该按钮。如果这样做,您将必须返回并再次检测该按钮。

返回到配置屏幕并单击重新启动 btnx。

尝试一下新按钮。

如果要卸载应用程序,请停止 btnx 程序,然后进入相应的 git checkout 目录并进行卸载:

sudo /etc/init.d/btnx stop
cd btnx
sudo make uninstall
cd -
cd btnx-config
sudo make uninstall
cd -
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢您在pastebin 上发布的详细答案。但我担心我不允许使用不受信任的 ppa 或从未知来源构建应用程序而不在我的设备上详细检查它。尽管如此,我还是会为你所付出的努力投一票。除此之外,我建议您在这里更新您的答案并复制您在那里写的内容,因为这些信息可能对其他人有帮助,但可能会被忽视。最后我读到该软件包甚至可能无法在 Ubuntu 或 Debian 下编译 - 你实际上尝试过吗? (2认同)