How to map modifiers (e.g. CTRL) to mouse thumb buttons using xbindkeys












13















This question has already been asked but was never answered properly. After clearance with @Seth I am now asking it again. This will allow me to respond and possibly modify the question a lot easier. The original question can be found here:



Map Ctrl and Alt to mouse thumb buttons





Issue:



Though it is very simple to map any keystrokes to a mouse button using xbindkeys in conjunction with xdotool or xte it seems a lot more problematic to map a modifier key (e.g. ALT, CTRL, SHIFT etc.) to it.



The final soloution should allow i.a. a CTRL + click (e.g. for selecting multiple entries of a list) with just the mouse.



A couple of possible approaches to solve this can be found here at Stack Exchange as well as at other Linux related forums. But none of those work as expected as they lead to other issues and side effects.



Notes:



Some of the examples below involve Guile with Scheme syntax and rely on .xbindkeysrc.scm file whereas others rely on the .xbindkeysrc file with its respective syntax. I am aware that they won't work together.



Furthermore the below snippets rely on xdotool only but I am open to approaches involving other applications like e.g. xte as well - though it seems both lead to the same results and therefore I am using just xdotool actions here.



Approach A:



Updating the .xbindkeysrc file with:



"xdotool keydown ctrl"
b:8

"xdotool keyup ctrl"
release + b:8


That's what I initially tried but it has the side-effect that the modifier is being held and can not be released.



Approach B:



Updating the .xbindkeysrc.scm file with:



(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")


Found at http://www.linuxforums.org/forum/hardware-peripherals/169773-solved-map-mouse-button-modifier-key.html and tries to address the issue where the modifier is being held (as described at approach a).



Though it fixes that it does only work partially as it is not possible to perform other mouse clicks while the thumb button is pressed.



Approach C:



Updating the .xbindkeysrc file with:



"xdotool keydown ctrl"
b:8

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


Tried out by OP of the linked question here at askubuntu. A lot simpler and more solid as it does not involve modifier states. Nevertheless the issue remains, i.e. a CTRL + click is not possible.



It seems that xbindkeys itself is the problem here as it recognizes the click but won't execute it. This can be tested using xev | grep button and xbindkeys -v:



A normal mouse click as recorded by xev should look like:



state 0x10, button 1, same_screen YES
state 0x110, button 1, same_screen YES


As well as for the thumb button:



state 0x10, button 8, same_screen YES
state 0x10, button 8, same_screen YES


But when having the above xbindkeys configuration enabled it does not record anything. Though it makes sense for the thumb button as it is mapped to CTRL and therefore is not a mouse button anymore it is strange that button 1 is not recorded as well. This is likely because xbindkeys does not execute it but itself is recognizing it:



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


Approach D:



Updating the .xbindkeysrc file with:



"xdotool keydown ctrl"
b:8

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

"xdotool click 1"
b:1


Just too simple ... but leads to an infinite loop of clicks.





UPDATE:



In the meantime I've bought a Logitech G502 and noticed that once configured via the driver on Windows not only the profile itself is stored on the device memory but the actual keypress is done by the mouse. That in fact solved my problem on Linux!



The only other mouse I remember that was able to do that was the Razer Copperhead back in the days. But I guess there are other mice available today which can do the same.










share|improve this question

























  • here's a solution using Easystroke: askubuntu.com/a/1010647/27202

    – atti
    Feb 28 '18 at 13:12
















13















This question has already been asked but was never answered properly. After clearance with @Seth I am now asking it again. This will allow me to respond and possibly modify the question a lot easier. The original question can be found here:



Map Ctrl and Alt to mouse thumb buttons





Issue:



Though it is very simple to map any keystrokes to a mouse button using xbindkeys in conjunction with xdotool or xte it seems a lot more problematic to map a modifier key (e.g. ALT, CTRL, SHIFT etc.) to it.



The final soloution should allow i.a. a CTRL + click (e.g. for selecting multiple entries of a list) with just the mouse.



A couple of possible approaches to solve this can be found here at Stack Exchange as well as at other Linux related forums. But none of those work as expected as they lead to other issues and side effects.



Notes:



Some of the examples below involve Guile with Scheme syntax and rely on .xbindkeysrc.scm file whereas others rely on the .xbindkeysrc file with its respective syntax. I am aware that they won't work together.



Furthermore the below snippets rely on xdotool only but I am open to approaches involving other applications like e.g. xte as well - though it seems both lead to the same results and therefore I am using just xdotool actions here.



Approach A:



Updating the .xbindkeysrc file with:



"xdotool keydown ctrl"
b:8

"xdotool keyup ctrl"
release + b:8


That's what I initially tried but it has the side-effect that the modifier is being held and can not be released.



Approach B:



Updating the .xbindkeysrc.scm file with:



(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")


Found at http://www.linuxforums.org/forum/hardware-peripherals/169773-solved-map-mouse-button-modifier-key.html and tries to address the issue where the modifier is being held (as described at approach a).



Though it fixes that it does only work partially as it is not possible to perform other mouse clicks while the thumb button is pressed.



Approach C:



Updating the .xbindkeysrc file with:



"xdotool keydown ctrl"
b:8

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


Tried out by OP of the linked question here at askubuntu. A lot simpler and more solid as it does not involve modifier states. Nevertheless the issue remains, i.e. a CTRL + click is not possible.



It seems that xbindkeys itself is the problem here as it recognizes the click but won't execute it. This can be tested using xev | grep button and xbindkeys -v:



A normal mouse click as recorded by xev should look like:



state 0x10, button 1, same_screen YES
state 0x110, button 1, same_screen YES


As well as for the thumb button:



state 0x10, button 8, same_screen YES
state 0x10, button 8, same_screen YES


But when having the above xbindkeys configuration enabled it does not record anything. Though it makes sense for the thumb button as it is mapped to CTRL and therefore is not a mouse button anymore it is strange that button 1 is not recorded as well. This is likely because xbindkeys does not execute it but itself is recognizing it:



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


Approach D:



Updating the .xbindkeysrc file with:



"xdotool keydown ctrl"
b:8

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

"xdotool click 1"
b:1


Just too simple ... but leads to an infinite loop of clicks.





UPDATE:



In the meantime I've bought a Logitech G502 and noticed that once configured via the driver on Windows not only the profile itself is stored on the device memory but the actual keypress is done by the mouse. That in fact solved my problem on Linux!



The only other mouse I remember that was able to do that was the Razer Copperhead back in the days. But I guess there are other mice available today which can do the same.










share|improve this question

























  • here's a solution using Easystroke: askubuntu.com/a/1010647/27202

    – atti
    Feb 28 '18 at 13:12














13












13








13


8






This question has already been asked but was never answered properly. After clearance with @Seth I am now asking it again. This will allow me to respond and possibly modify the question a lot easier. The original question can be found here:



Map Ctrl and Alt to mouse thumb buttons





Issue:



Though it is very simple to map any keystrokes to a mouse button using xbindkeys in conjunction with xdotool or xte it seems a lot more problematic to map a modifier key (e.g. ALT, CTRL, SHIFT etc.) to it.



The final soloution should allow i.a. a CTRL + click (e.g. for selecting multiple entries of a list) with just the mouse.



A couple of possible approaches to solve this can be found here at Stack Exchange as well as at other Linux related forums. But none of those work as expected as they lead to other issues and side effects.



Notes:



Some of the examples below involve Guile with Scheme syntax and rely on .xbindkeysrc.scm file whereas others rely on the .xbindkeysrc file with its respective syntax. I am aware that they won't work together.



Furthermore the below snippets rely on xdotool only but I am open to approaches involving other applications like e.g. xte as well - though it seems both lead to the same results and therefore I am using just xdotool actions here.



Approach A:



Updating the .xbindkeysrc file with:



"xdotool keydown ctrl"
b:8

"xdotool keyup ctrl"
release + b:8


That's what I initially tried but it has the side-effect that the modifier is being held and can not be released.



Approach B:



Updating the .xbindkeysrc.scm file with:



(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")


Found at http://www.linuxforums.org/forum/hardware-peripherals/169773-solved-map-mouse-button-modifier-key.html and tries to address the issue where the modifier is being held (as described at approach a).



Though it fixes that it does only work partially as it is not possible to perform other mouse clicks while the thumb button is pressed.



Approach C:



Updating the .xbindkeysrc file with:



"xdotool keydown ctrl"
b:8

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


Tried out by OP of the linked question here at askubuntu. A lot simpler and more solid as it does not involve modifier states. Nevertheless the issue remains, i.e. a CTRL + click is not possible.



It seems that xbindkeys itself is the problem here as it recognizes the click but won't execute it. This can be tested using xev | grep button and xbindkeys -v:



A normal mouse click as recorded by xev should look like:



state 0x10, button 1, same_screen YES
state 0x110, button 1, same_screen YES


As well as for the thumb button:



state 0x10, button 8, same_screen YES
state 0x10, button 8, same_screen YES


But when having the above xbindkeys configuration enabled it does not record anything. Though it makes sense for the thumb button as it is mapped to CTRL and therefore is not a mouse button anymore it is strange that button 1 is not recorded as well. This is likely because xbindkeys does not execute it but itself is recognizing it:



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


Approach D:



Updating the .xbindkeysrc file with:



"xdotool keydown ctrl"
b:8

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

"xdotool click 1"
b:1


Just too simple ... but leads to an infinite loop of clicks.





UPDATE:



In the meantime I've bought a Logitech G502 and noticed that once configured via the driver on Windows not only the profile itself is stored on the device memory but the actual keypress is done by the mouse. That in fact solved my problem on Linux!



The only other mouse I remember that was able to do that was the Razer Copperhead back in the days. But I guess there are other mice available today which can do the same.










share|improve this question
















This question has already been asked but was never answered properly. After clearance with @Seth I am now asking it again. This will allow me to respond and possibly modify the question a lot easier. The original question can be found here:



Map Ctrl and Alt to mouse thumb buttons





Issue:



Though it is very simple to map any keystrokes to a mouse button using xbindkeys in conjunction with xdotool or xte it seems a lot more problematic to map a modifier key (e.g. ALT, CTRL, SHIFT etc.) to it.



The final soloution should allow i.a. a CTRL + click (e.g. for selecting multiple entries of a list) with just the mouse.



A couple of possible approaches to solve this can be found here at Stack Exchange as well as at other Linux related forums. But none of those work as expected as they lead to other issues and side effects.



Notes:



Some of the examples below involve Guile with Scheme syntax and rely on .xbindkeysrc.scm file whereas others rely on the .xbindkeysrc file with its respective syntax. I am aware that they won't work together.



Furthermore the below snippets rely on xdotool only but I am open to approaches involving other applications like e.g. xte as well - though it seems both lead to the same results and therefore I am using just xdotool actions here.



Approach A:



Updating the .xbindkeysrc file with:



"xdotool keydown ctrl"
b:8

"xdotool keyup ctrl"
release + b:8


That's what I initially tried but it has the side-effect that the modifier is being held and can not be released.



Approach B:



Updating the .xbindkeysrc.scm file with:



(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")


Found at http://www.linuxforums.org/forum/hardware-peripherals/169773-solved-map-mouse-button-modifier-key.html and tries to address the issue where the modifier is being held (as described at approach a).



Though it fixes that it does only work partially as it is not possible to perform other mouse clicks while the thumb button is pressed.



Approach C:



Updating the .xbindkeysrc file with:



"xdotool keydown ctrl"
b:8

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


Tried out by OP of the linked question here at askubuntu. A lot simpler and more solid as it does not involve modifier states. Nevertheless the issue remains, i.e. a CTRL + click is not possible.



It seems that xbindkeys itself is the problem here as it recognizes the click but won't execute it. This can be tested using xev | grep button and xbindkeys -v:



A normal mouse click as recorded by xev should look like:



state 0x10, button 1, same_screen YES
state 0x110, button 1, same_screen YES


As well as for the thumb button:



state 0x10, button 8, same_screen YES
state 0x10, button 8, same_screen YES


But when having the above xbindkeys configuration enabled it does not record anything. Though it makes sense for the thumb button as it is mapped to CTRL and therefore is not a mouse button anymore it is strange that button 1 is not recorded as well. This is likely because xbindkeys does not execute it but itself is recognizing it:



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


Approach D:



Updating the .xbindkeysrc file with:



"xdotool keydown ctrl"
b:8

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

"xdotool click 1"
b:1


Just too simple ... but leads to an infinite loop of clicks.





UPDATE:



In the meantime I've bought a Logitech G502 and noticed that once configured via the driver on Windows not only the profile itself is stored on the device memory but the actual keypress is done by the mouse. That in fact solved my problem on Linux!



The only other mouse I remember that was able to do that was the Razer Copperhead back in the days. But I guess there are other mice available today which can do the same.







mouse xdotool xbindkeys xte






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Apr 13 '17 at 12:24









Community

1




1










asked May 24 '15 at 3:39









conceptdeluxeconceptdeluxe

20829




20829













  • here's a solution using Easystroke: askubuntu.com/a/1010647/27202

    – atti
    Feb 28 '18 at 13:12



















  • here's a solution using Easystroke: askubuntu.com/a/1010647/27202

    – atti
    Feb 28 '18 at 13:12

















here's a solution using Easystroke: askubuntu.com/a/1010647/27202

– atti
Feb 28 '18 at 13:12





here's a solution using Easystroke: askubuntu.com/a/1010647/27202

– atti
Feb 28 '18 at 13:12










3 Answers
3






active

oldest

votes


















7














I spent a lot of time trying to make that binding work. I eventually found a solution, which is complicated but works well and doesn't imply third party software.
I share it here hoping it will help people. Besides, I know this is not perfect in terms of security, so any constructive feedback is more than welcome.



There are solutions who are really nice, like the one proposed here, but It always suffer from the limitation of xbindkeys who grab the entire mouse, making modifers+mouse click mapping uncertain. Plus the guile based solution from the above link use ctrl+plus/ctrl+minus which isn't recognize by Gimp for example.



I figured out that what we want is a mouse button who act as a keyboard, so I used uinput, who can be accessed via python, wrote a script that monitor /dev/my-mouse for the thumb button click and send the ctrl key to the virtual keyboard. Here are the detailed steps :



1. Make udev rules



We want the devices to be accessible (rights and location).



For the mouse :



/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 will look for a device recognized by the kernel with names like event5, and I select my mouse with the name. The SYMLINK instruction assure I will find my mouse in /dev/my_mx_mouse. The device will be readable by a member of the group "mxgrabber".



To find information about your hardware, you should run something like



udevadm info -a -n /dev/input/eventX


For uinput :



/etc/udev/rules.d/94-mxkey.rules
----------------------------------------------------
KERNEL=="uinput", GROUP="mxgrabber", MODE="660"


No need for symlink, uinput will always be in $/dev/uinput or $/dev/input/uinput depending on the system you're on. Just give him the group and the rights to read AND write of course.



You need to unplug - plug your mouse, and the new link should appear in /dev. You can force udev to trigger your rules with $udevadm trigger



2. Activate UINPUT Module



sudo modprobe uinput


And to make it boot persistant :



/etc/modules-load.d/uinput.conf
-----------------------------------------------
uinput


3. Create new group



sudo groupadd mxgrabber


Or whatever you have called your access group. Then you should add yourself to it :



sudo usermod -aG mxgrabber your_login


4. Python script



You need to install the python-uinput library (obviously) and the python-evdev library. Use pip or your distribution package.



The script is quite straightforward, you just have to identify the event.code of you button.



#!/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. Enjoy !



All you need now is make your python file executable, and ask your desktop manager to load the file at startup. Maybe also a glass of wine to celebrate the good work !



6. Extra for free



I use xbindkeys for additional behavior. For instance, the following configuration may be nice if you have a mouse with wheel side clicks :



~/.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


For this last combinaison to work, you must disable the button you configured for the python script, otherwise it will still be grabed by xbindkeys. Only the Ctrl key must remain :



~/.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


Reload with $ xmodmap ~/.Xmodmap



7. Conclusion



As I said in the beginning, I'm not perfectly happy with the fact that I have to give myself the wrights to write to /dev/uinput, even if it's thought the "mxgrabber" group. I'm sure there is a safer way of doing that, but I don't know how.



On the bright side, it works really, really well. Any combinaison of keyboard or mouse key how works with the Ctrl button of the keyboard now works with the one of the mouse !!






share|improve this answer


























  • Thanks a lot for the effort and sharing it with us! +1 ... Though I have not tested it yet. BTW I have almost given up on this - would be great if that works as expected :)

    – conceptdeluxe
    Jan 6 '16 at 13:39











  • Your'e welcome ! For me, it works flawlessly. If you have trouble, let me know. I try to make my answer complete, but as I spent almost two days trying to make it work, I may have forget something. Will be glad to help / edit my post.

    – Aurélien Cibrario
    Jan 7 '16 at 7:37











  • I just realized that ctrl+click1 was a very bad choice to close a tab since it open a link in a new tab. I edited my answer removing last part of the python script and tweaking with xbindkeys, cleaner solution

    – Aurélien Cibrario
    Jan 7 '16 at 8:21











  • just want to let you know, that I had no time to test it yet - but I'll for sure make it the accepted answer if it works as expected - sorry for the wait - I am a bit busy atm

    – conceptdeluxe
    Jan 11 '16 at 17:14











  • I wonder if we can use above script to debounce a faulty mouse switch. I have a worn-out mouse. I use an autohotkey script to fix it in Windows but there is no tool to fix it in Linux. Here is Autohhotkey script for left button fix autohotkey.com/board/topic/63555-debounce-mouse-keys I hope somebody port it to Linux using python3--evdev

    – kenn
    Nov 20 '16 at 18:13



















3














I found a solution with PyUserInput. This ends up being quite simple and does not require administration rights. With python 2 and PyUserInput installed, I used the following script:



#!/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()


After giving execution rights to the script, I call it with a line in ~/.xsessionrc, for instance



~/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 &


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.






share|improve this answer


























  • But it doesn't prevent the original event from firing. So if I map button 8 to shift, and hold button 8 in Firefox, it also tries to go back to the previous page, which is undesirable.

    – user23013
    Aug 4 '17 at 13:24











  • True. To tackle this I used changed the id of the button I was interested in to an used button in xinput. See edited question.

    – Maxim
    Aug 4 '17 at 13:51



















2














I have a partial solution. I haven't figured out how to unmap the existing
button, so you end up with a button click and the modifier you want. So if
that mouse button has some existing purpose, it will still fire. For example,
remaping the right mouse button to a control key will result in a control+click
being sent.



Anyway, I found a forum post that is similar to your question for which the
answer was to install btnx and configure your modifiers through that. It seems
btnx is no longer available through the repo. There is a ppa, but it doesnt
work for the latest ubuntu.



Forum post: post: http://ubuntuforums.org/showthread.php?t=1245930



But the source is available:




  • https://github.com/cdobrich/btnx

  • https://github.com/cdobrich/btnx-config


You could compile it from source, but this will put files on your system that
the package manager cannot maintain.



Namely, the following files:



/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


The following symlinks:



/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


So... if you don't mind building from source...



Get the dependencies for btnx:



sudo apt-get install libdaemon-dev git


If you've never built anything from source, you might need build-essential, too:



sudo apt-get install build-essential


Then get and compile btnx:



git clone https://github.com/cdobrich/btnx
cd btnx
./configure
make
sudo make install
cd -


It has a separate GUI configuration tool. Get the dependencies for it:



sudo apt-get install libgtk2.0-dev libglade2-dev


Now get and compile the gui config tool:



git clone https://github.com/cdobrich/btnx-config
./configure
make
sudo make install


Now run the tool:



sudo btnx-config


Click on Detect Mouse Buttons
If you want to be able to read the directions while you use the tool, resize
the window that pops up, the dialog text gets clipped later if you don't and if
you try to resize during detection it will cancel the detection. Just make the
window a bit larger.



Click on Press to start mouse detection, then try not to move the mouse until
the text changes... Takes about 5-10 seconds. The text will change. When it
does, ignore what it says and click Forward.



Click the "Press to start button detection" button



Here you will click one button of your mouse several times (until the status bar fills up).
Then set the name of the button to something you will recognize later (ex: LeftButton)
Click the Add button.



Repeat this for each mouse button (don't forget scroll wheels, scroll clicks,
etc). You can probably skip any buttons you don't want to remap.



When you have added all the buttons, click on OK.



In the main GUI, click on Buttons, in the left pane select teh button you want to remap.
It will use the names you entered in the previous steps.
For your purposes, you'll want to select just a Key modifier under Key combination on the right.



Don't click delete on this screen, it will remove the button. You'll have to
go back and detect the button again if you do.



Go back to the Conrigurations screen and click restart btnx.



Try out the new button.



If you want to uninstall the applicaitons, stop the btnx program and then go
into the respective git checked out directories and make uninstall:



sudo /etc/init.d/btnx stop
cd btnx
sudo make uninstall
cd -
cd btnx-config
sudo make uninstall
cd -





share|improve this answer





















  • 2





    Thanks a lot for the detailed answer you posted at pastebin. But I am afraid that I am not allowed to use an untrusted ppa or build an application from unknown source without reviewing it in detail on my device. Nevertheless I'll give you a vote up for the effort you've put into it. Apart from that I recommend that you update your answer here and copy what you have written there as this information might be helpful for others but might be overlooked. Finally I have read that the package might even not compile under Ubuntu or Debian - have you tried that actually?

    – conceptdeluxe
    May 24 '15 at 15:47











  • Btw: You can gain additional 100 reputation easily by linking your askubuntu account with other Stack Exchange accounts like e.g. Linux & Unix.

    – conceptdeluxe
    May 24 '15 at 15:59











  • Yeah, I tested it under Ubuntu 14.04. I made the right mouse button send a control key and confirmed that it worked before posting. And then almost abandoned the post because of the reputation requirement.

    – Stephen
    May 24 '15 at 16:30












Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "89"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f627555%2fhow-to-map-modifiers-e-g-ctrl-to-mouse-thumb-buttons-using-xbindkeys%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









7














I spent a lot of time trying to make that binding work. I eventually found a solution, which is complicated but works well and doesn't imply third party software.
I share it here hoping it will help people. Besides, I know this is not perfect in terms of security, so any constructive feedback is more than welcome.



There are solutions who are really nice, like the one proposed here, but It always suffer from the limitation of xbindkeys who grab the entire mouse, making modifers+mouse click mapping uncertain. Plus the guile based solution from the above link use ctrl+plus/ctrl+minus which isn't recognize by Gimp for example.



I figured out that what we want is a mouse button who act as a keyboard, so I used uinput, who can be accessed via python, wrote a script that monitor /dev/my-mouse for the thumb button click and send the ctrl key to the virtual keyboard. Here are the detailed steps :



1. Make udev rules



We want the devices to be accessible (rights and location).



For the mouse :



/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 will look for a device recognized by the kernel with names like event5, and I select my mouse with the name. The SYMLINK instruction assure I will find my mouse in /dev/my_mx_mouse. The device will be readable by a member of the group "mxgrabber".



To find information about your hardware, you should run something like



udevadm info -a -n /dev/input/eventX


For uinput :



/etc/udev/rules.d/94-mxkey.rules
----------------------------------------------------
KERNEL=="uinput", GROUP="mxgrabber", MODE="660"


No need for symlink, uinput will always be in $/dev/uinput or $/dev/input/uinput depending on the system you're on. Just give him the group and the rights to read AND write of course.



You need to unplug - plug your mouse, and the new link should appear in /dev. You can force udev to trigger your rules with $udevadm trigger



2. Activate UINPUT Module



sudo modprobe uinput


And to make it boot persistant :



/etc/modules-load.d/uinput.conf
-----------------------------------------------
uinput


3. Create new group



sudo groupadd mxgrabber


Or whatever you have called your access group. Then you should add yourself to it :



sudo usermod -aG mxgrabber your_login


4. Python script



You need to install the python-uinput library (obviously) and the python-evdev library. Use pip or your distribution package.



The script is quite straightforward, you just have to identify the event.code of you button.



#!/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. Enjoy !



All you need now is make your python file executable, and ask your desktop manager to load the file at startup. Maybe also a glass of wine to celebrate the good work !



6. Extra for free



I use xbindkeys for additional behavior. For instance, the following configuration may be nice if you have a mouse with wheel side clicks :



~/.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


For this last combinaison to work, you must disable the button you configured for the python script, otherwise it will still be grabed by xbindkeys. Only the Ctrl key must remain :



~/.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


Reload with $ xmodmap ~/.Xmodmap



7. Conclusion



As I said in the beginning, I'm not perfectly happy with the fact that I have to give myself the wrights to write to /dev/uinput, even if it's thought the "mxgrabber" group. I'm sure there is a safer way of doing that, but I don't know how.



On the bright side, it works really, really well. Any combinaison of keyboard or mouse key how works with the Ctrl button of the keyboard now works with the one of the mouse !!






share|improve this answer


























  • Thanks a lot for the effort and sharing it with us! +1 ... Though I have not tested it yet. BTW I have almost given up on this - would be great if that works as expected :)

    – conceptdeluxe
    Jan 6 '16 at 13:39











  • Your'e welcome ! For me, it works flawlessly. If you have trouble, let me know. I try to make my answer complete, but as I spent almost two days trying to make it work, I may have forget something. Will be glad to help / edit my post.

    – Aurélien Cibrario
    Jan 7 '16 at 7:37











  • I just realized that ctrl+click1 was a very bad choice to close a tab since it open a link in a new tab. I edited my answer removing last part of the python script and tweaking with xbindkeys, cleaner solution

    – Aurélien Cibrario
    Jan 7 '16 at 8:21











  • just want to let you know, that I had no time to test it yet - but I'll for sure make it the accepted answer if it works as expected - sorry for the wait - I am a bit busy atm

    – conceptdeluxe
    Jan 11 '16 at 17:14











  • I wonder if we can use above script to debounce a faulty mouse switch. I have a worn-out mouse. I use an autohotkey script to fix it in Windows but there is no tool to fix it in Linux. Here is Autohhotkey script for left button fix autohotkey.com/board/topic/63555-debounce-mouse-keys I hope somebody port it to Linux using python3--evdev

    – kenn
    Nov 20 '16 at 18:13
















7














I spent a lot of time trying to make that binding work. I eventually found a solution, which is complicated but works well and doesn't imply third party software.
I share it here hoping it will help people. Besides, I know this is not perfect in terms of security, so any constructive feedback is more than welcome.



There are solutions who are really nice, like the one proposed here, but It always suffer from the limitation of xbindkeys who grab the entire mouse, making modifers+mouse click mapping uncertain. Plus the guile based solution from the above link use ctrl+plus/ctrl+minus which isn't recognize by Gimp for example.



I figured out that what we want is a mouse button who act as a keyboard, so I used uinput, who can be accessed via python, wrote a script that monitor /dev/my-mouse for the thumb button click and send the ctrl key to the virtual keyboard. Here are the detailed steps :



1. Make udev rules



We want the devices to be accessible (rights and location).



For the mouse :



/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 will look for a device recognized by the kernel with names like event5, and I select my mouse with the name. The SYMLINK instruction assure I will find my mouse in /dev/my_mx_mouse. The device will be readable by a member of the group "mxgrabber".



To find information about your hardware, you should run something like



udevadm info -a -n /dev/input/eventX


For uinput :



/etc/udev/rules.d/94-mxkey.rules
----------------------------------------------------
KERNEL=="uinput", GROUP="mxgrabber", MODE="660"


No need for symlink, uinput will always be in $/dev/uinput or $/dev/input/uinput depending on the system you're on. Just give him the group and the rights to read AND write of course.



You need to unplug - plug your mouse, and the new link should appear in /dev. You can force udev to trigger your rules with $udevadm trigger



2. Activate UINPUT Module



sudo modprobe uinput


And to make it boot persistant :



/etc/modules-load.d/uinput.conf
-----------------------------------------------
uinput


3. Create new group



sudo groupadd mxgrabber


Or whatever you have called your access group. Then you should add yourself to it :



sudo usermod -aG mxgrabber your_login


4. Python script



You need to install the python-uinput library (obviously) and the python-evdev library. Use pip or your distribution package.



The script is quite straightforward, you just have to identify the event.code of you button.



#!/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. Enjoy !



All you need now is make your python file executable, and ask your desktop manager to load the file at startup. Maybe also a glass of wine to celebrate the good work !



6. Extra for free



I use xbindkeys for additional behavior. For instance, the following configuration may be nice if you have a mouse with wheel side clicks :



~/.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


For this last combinaison to work, you must disable the button you configured for the python script, otherwise it will still be grabed by xbindkeys. Only the Ctrl key must remain :



~/.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


Reload with $ xmodmap ~/.Xmodmap



7. Conclusion



As I said in the beginning, I'm not perfectly happy with the fact that I have to give myself the wrights to write to /dev/uinput, even if it's thought the "mxgrabber" group. I'm sure there is a safer way of doing that, but I don't know how.



On the bright side, it works really, really well. Any combinaison of keyboard or mouse key how works with the Ctrl button of the keyboard now works with the one of the mouse !!






share|improve this answer


























  • Thanks a lot for the effort and sharing it with us! +1 ... Though I have not tested it yet. BTW I have almost given up on this - would be great if that works as expected :)

    – conceptdeluxe
    Jan 6 '16 at 13:39











  • Your'e welcome ! For me, it works flawlessly. If you have trouble, let me know. I try to make my answer complete, but as I spent almost two days trying to make it work, I may have forget something. Will be glad to help / edit my post.

    – Aurélien Cibrario
    Jan 7 '16 at 7:37











  • I just realized that ctrl+click1 was a very bad choice to close a tab since it open a link in a new tab. I edited my answer removing last part of the python script and tweaking with xbindkeys, cleaner solution

    – Aurélien Cibrario
    Jan 7 '16 at 8:21











  • just want to let you know, that I had no time to test it yet - but I'll for sure make it the accepted answer if it works as expected - sorry for the wait - I am a bit busy atm

    – conceptdeluxe
    Jan 11 '16 at 17:14











  • I wonder if we can use above script to debounce a faulty mouse switch. I have a worn-out mouse. I use an autohotkey script to fix it in Windows but there is no tool to fix it in Linux. Here is Autohhotkey script for left button fix autohotkey.com/board/topic/63555-debounce-mouse-keys I hope somebody port it to Linux using python3--evdev

    – kenn
    Nov 20 '16 at 18:13














7












7








7







I spent a lot of time trying to make that binding work. I eventually found a solution, which is complicated but works well and doesn't imply third party software.
I share it here hoping it will help people. Besides, I know this is not perfect in terms of security, so any constructive feedback is more than welcome.



There are solutions who are really nice, like the one proposed here, but It always suffer from the limitation of xbindkeys who grab the entire mouse, making modifers+mouse click mapping uncertain. Plus the guile based solution from the above link use ctrl+plus/ctrl+minus which isn't recognize by Gimp for example.



I figured out that what we want is a mouse button who act as a keyboard, so I used uinput, who can be accessed via python, wrote a script that monitor /dev/my-mouse for the thumb button click and send the ctrl key to the virtual keyboard. Here are the detailed steps :



1. Make udev rules



We want the devices to be accessible (rights and location).



For the mouse :



/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 will look for a device recognized by the kernel with names like event5, and I select my mouse with the name. The SYMLINK instruction assure I will find my mouse in /dev/my_mx_mouse. The device will be readable by a member of the group "mxgrabber".



To find information about your hardware, you should run something like



udevadm info -a -n /dev/input/eventX


For uinput :



/etc/udev/rules.d/94-mxkey.rules
----------------------------------------------------
KERNEL=="uinput", GROUP="mxgrabber", MODE="660"


No need for symlink, uinput will always be in $/dev/uinput or $/dev/input/uinput depending on the system you're on. Just give him the group and the rights to read AND write of course.



You need to unplug - plug your mouse, and the new link should appear in /dev. You can force udev to trigger your rules with $udevadm trigger



2. Activate UINPUT Module



sudo modprobe uinput


And to make it boot persistant :



/etc/modules-load.d/uinput.conf
-----------------------------------------------
uinput


3. Create new group



sudo groupadd mxgrabber


Or whatever you have called your access group. Then you should add yourself to it :



sudo usermod -aG mxgrabber your_login


4. Python script



You need to install the python-uinput library (obviously) and the python-evdev library. Use pip or your distribution package.



The script is quite straightforward, you just have to identify the event.code of you button.



#!/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. Enjoy !



All you need now is make your python file executable, and ask your desktop manager to load the file at startup. Maybe also a glass of wine to celebrate the good work !



6. Extra for free



I use xbindkeys for additional behavior. For instance, the following configuration may be nice if you have a mouse with wheel side clicks :



~/.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


For this last combinaison to work, you must disable the button you configured for the python script, otherwise it will still be grabed by xbindkeys. Only the Ctrl key must remain :



~/.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


Reload with $ xmodmap ~/.Xmodmap



7. Conclusion



As I said in the beginning, I'm not perfectly happy with the fact that I have to give myself the wrights to write to /dev/uinput, even if it's thought the "mxgrabber" group. I'm sure there is a safer way of doing that, but I don't know how.



On the bright side, it works really, really well. Any combinaison of keyboard or mouse key how works with the Ctrl button of the keyboard now works with the one of the mouse !!






share|improve this answer















I spent a lot of time trying to make that binding work. I eventually found a solution, which is complicated but works well and doesn't imply third party software.
I share it here hoping it will help people. Besides, I know this is not perfect in terms of security, so any constructive feedback is more than welcome.



There are solutions who are really nice, like the one proposed here, but It always suffer from the limitation of xbindkeys who grab the entire mouse, making modifers+mouse click mapping uncertain. Plus the guile based solution from the above link use ctrl+plus/ctrl+minus which isn't recognize by Gimp for example.



I figured out that what we want is a mouse button who act as a keyboard, so I used uinput, who can be accessed via python, wrote a script that monitor /dev/my-mouse for the thumb button click and send the ctrl key to the virtual keyboard. Here are the detailed steps :



1. Make udev rules



We want the devices to be accessible (rights and location).



For the mouse :



/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 will look for a device recognized by the kernel with names like event5, and I select my mouse with the name. The SYMLINK instruction assure I will find my mouse in /dev/my_mx_mouse. The device will be readable by a member of the group "mxgrabber".



To find information about your hardware, you should run something like



udevadm info -a -n /dev/input/eventX


For uinput :



/etc/udev/rules.d/94-mxkey.rules
----------------------------------------------------
KERNEL=="uinput", GROUP="mxgrabber", MODE="660"


No need for symlink, uinput will always be in $/dev/uinput or $/dev/input/uinput depending on the system you're on. Just give him the group and the rights to read AND write of course.



You need to unplug - plug your mouse, and the new link should appear in /dev. You can force udev to trigger your rules with $udevadm trigger



2. Activate UINPUT Module



sudo modprobe uinput


And to make it boot persistant :



/etc/modules-load.d/uinput.conf
-----------------------------------------------
uinput


3. Create new group



sudo groupadd mxgrabber


Or whatever you have called your access group. Then you should add yourself to it :



sudo usermod -aG mxgrabber your_login


4. Python script



You need to install the python-uinput library (obviously) and the python-evdev library. Use pip or your distribution package.



The script is quite straightforward, you just have to identify the event.code of you button.



#!/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. Enjoy !



All you need now is make your python file executable, and ask your desktop manager to load the file at startup. Maybe also a glass of wine to celebrate the good work !



6. Extra for free



I use xbindkeys for additional behavior. For instance, the following configuration may be nice if you have a mouse with wheel side clicks :



~/.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


For this last combinaison to work, you must disable the button you configured for the python script, otherwise it will still be grabed by xbindkeys. Only the Ctrl key must remain :



~/.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


Reload with $ xmodmap ~/.Xmodmap



7. Conclusion



As I said in the beginning, I'm not perfectly happy with the fact that I have to give myself the wrights to write to /dev/uinput, even if it's thought the "mxgrabber" group. I'm sure there is a safer way of doing that, but I don't know how.



On the bright side, it works really, really well. Any combinaison of keyboard or mouse key how works with the Ctrl button of the keyboard now works with the one of the mouse !!







share|improve this answer














share|improve this answer



share|improve this answer








edited May 26 '16 at 9:11

























answered Jan 6 '16 at 13:31









Aurélien CibrarioAurélien Cibrario

7113




7113













  • Thanks a lot for the effort and sharing it with us! +1 ... Though I have not tested it yet. BTW I have almost given up on this - would be great if that works as expected :)

    – conceptdeluxe
    Jan 6 '16 at 13:39











  • Your'e welcome ! For me, it works flawlessly. If you have trouble, let me know. I try to make my answer complete, but as I spent almost two days trying to make it work, I may have forget something. Will be glad to help / edit my post.

    – Aurélien Cibrario
    Jan 7 '16 at 7:37











  • I just realized that ctrl+click1 was a very bad choice to close a tab since it open a link in a new tab. I edited my answer removing last part of the python script and tweaking with xbindkeys, cleaner solution

    – Aurélien Cibrario
    Jan 7 '16 at 8:21











  • just want to let you know, that I had no time to test it yet - but I'll for sure make it the accepted answer if it works as expected - sorry for the wait - I am a bit busy atm

    – conceptdeluxe
    Jan 11 '16 at 17:14











  • I wonder if we can use above script to debounce a faulty mouse switch. I have a worn-out mouse. I use an autohotkey script to fix it in Windows but there is no tool to fix it in Linux. Here is Autohhotkey script for left button fix autohotkey.com/board/topic/63555-debounce-mouse-keys I hope somebody port it to Linux using python3--evdev

    – kenn
    Nov 20 '16 at 18:13



















  • Thanks a lot for the effort and sharing it with us! +1 ... Though I have not tested it yet. BTW I have almost given up on this - would be great if that works as expected :)

    – conceptdeluxe
    Jan 6 '16 at 13:39











  • Your'e welcome ! For me, it works flawlessly. If you have trouble, let me know. I try to make my answer complete, but as I spent almost two days trying to make it work, I may have forget something. Will be glad to help / edit my post.

    – Aurélien Cibrario
    Jan 7 '16 at 7:37











  • I just realized that ctrl+click1 was a very bad choice to close a tab since it open a link in a new tab. I edited my answer removing last part of the python script and tweaking with xbindkeys, cleaner solution

    – Aurélien Cibrario
    Jan 7 '16 at 8:21











  • just want to let you know, that I had no time to test it yet - but I'll for sure make it the accepted answer if it works as expected - sorry for the wait - I am a bit busy atm

    – conceptdeluxe
    Jan 11 '16 at 17:14











  • I wonder if we can use above script to debounce a faulty mouse switch. I have a worn-out mouse. I use an autohotkey script to fix it in Windows but there is no tool to fix it in Linux. Here is Autohhotkey script for left button fix autohotkey.com/board/topic/63555-debounce-mouse-keys I hope somebody port it to Linux using python3--evdev

    – kenn
    Nov 20 '16 at 18:13

















Thanks a lot for the effort and sharing it with us! +1 ... Though I have not tested it yet. BTW I have almost given up on this - would be great if that works as expected :)

– conceptdeluxe
Jan 6 '16 at 13:39





Thanks a lot for the effort and sharing it with us! +1 ... Though I have not tested it yet. BTW I have almost given up on this - would be great if that works as expected :)

– conceptdeluxe
Jan 6 '16 at 13:39













Your'e welcome ! For me, it works flawlessly. If you have trouble, let me know. I try to make my answer complete, but as I spent almost two days trying to make it work, I may have forget something. Will be glad to help / edit my post.

– Aurélien Cibrario
Jan 7 '16 at 7:37





Your'e welcome ! For me, it works flawlessly. If you have trouble, let me know. I try to make my answer complete, but as I spent almost two days trying to make it work, I may have forget something. Will be glad to help / edit my post.

– Aurélien Cibrario
Jan 7 '16 at 7:37













I just realized that ctrl+click1 was a very bad choice to close a tab since it open a link in a new tab. I edited my answer removing last part of the python script and tweaking with xbindkeys, cleaner solution

– Aurélien Cibrario
Jan 7 '16 at 8:21





I just realized that ctrl+click1 was a very bad choice to close a tab since it open a link in a new tab. I edited my answer removing last part of the python script and tweaking with xbindkeys, cleaner solution

– Aurélien Cibrario
Jan 7 '16 at 8:21













just want to let you know, that I had no time to test it yet - but I'll for sure make it the accepted answer if it works as expected - sorry for the wait - I am a bit busy atm

– conceptdeluxe
Jan 11 '16 at 17:14





just want to let you know, that I had no time to test it yet - but I'll for sure make it the accepted answer if it works as expected - sorry for the wait - I am a bit busy atm

– conceptdeluxe
Jan 11 '16 at 17:14













I wonder if we can use above script to debounce a faulty mouse switch. I have a worn-out mouse. I use an autohotkey script to fix it in Windows but there is no tool to fix it in Linux. Here is Autohhotkey script for left button fix autohotkey.com/board/topic/63555-debounce-mouse-keys I hope somebody port it to Linux using python3--evdev

– kenn
Nov 20 '16 at 18:13





I wonder if we can use above script to debounce a faulty mouse switch. I have a worn-out mouse. I use an autohotkey script to fix it in Windows but there is no tool to fix it in Linux. Here is Autohhotkey script for left button fix autohotkey.com/board/topic/63555-debounce-mouse-keys I hope somebody port it to Linux using python3--evdev

– kenn
Nov 20 '16 at 18:13













3














I found a solution with PyUserInput. This ends up being quite simple and does not require administration rights. With python 2 and PyUserInput installed, I used the following script:



#!/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()


After giving execution rights to the script, I call it with a line in ~/.xsessionrc, for instance



~/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 &


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.






share|improve this answer


























  • But it doesn't prevent the original event from firing. So if I map button 8 to shift, and hold button 8 in Firefox, it also tries to go back to the previous page, which is undesirable.

    – user23013
    Aug 4 '17 at 13:24











  • True. To tackle this I used changed the id of the button I was interested in to an used button in xinput. See edited question.

    – Maxim
    Aug 4 '17 at 13:51
















3














I found a solution with PyUserInput. This ends up being quite simple and does not require administration rights. With python 2 and PyUserInput installed, I used the following script:



#!/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()


After giving execution rights to the script, I call it with a line in ~/.xsessionrc, for instance



~/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 &


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.






share|improve this answer


























  • But it doesn't prevent the original event from firing. So if I map button 8 to shift, and hold button 8 in Firefox, it also tries to go back to the previous page, which is undesirable.

    – user23013
    Aug 4 '17 at 13:24











  • True. To tackle this I used changed the id of the button I was interested in to an used button in xinput. See edited question.

    – Maxim
    Aug 4 '17 at 13:51














3












3








3







I found a solution with PyUserInput. This ends up being quite simple and does not require administration rights. With python 2 and PyUserInput installed, I used the following script:



#!/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()


After giving execution rights to the script, I call it with a line in ~/.xsessionrc, for instance



~/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 &


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.






share|improve this answer















I found a solution with PyUserInput. This ends up being quite simple and does not require administration rights. With python 2 and PyUserInput installed, I used the following script:



#!/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()


After giving execution rights to the script, I call it with a line in ~/.xsessionrc, for instance



~/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 &


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.







share|improve this answer














share|improve this answer



share|improve this answer








edited Aug 4 '17 at 13:49

























answered Apr 10 '17 at 23:59









MaximMaxim

29517




29517













  • But it doesn't prevent the original event from firing. So if I map button 8 to shift, and hold button 8 in Firefox, it also tries to go back to the previous page, which is undesirable.

    – user23013
    Aug 4 '17 at 13:24











  • True. To tackle this I used changed the id of the button I was interested in to an used button in xinput. See edited question.

    – Maxim
    Aug 4 '17 at 13:51



















  • But it doesn't prevent the original event from firing. So if I map button 8 to shift, and hold button 8 in Firefox, it also tries to go back to the previous page, which is undesirable.

    – user23013
    Aug 4 '17 at 13:24











  • True. To tackle this I used changed the id of the button I was interested in to an used button in xinput. See edited question.

    – Maxim
    Aug 4 '17 at 13:51

















But it doesn't prevent the original event from firing. So if I map button 8 to shift, and hold button 8 in Firefox, it also tries to go back to the previous page, which is undesirable.

– user23013
Aug 4 '17 at 13:24





But it doesn't prevent the original event from firing. So if I map button 8 to shift, and hold button 8 in Firefox, it also tries to go back to the previous page, which is undesirable.

– user23013
Aug 4 '17 at 13:24













True. To tackle this I used changed the id of the button I was interested in to an used button in xinput. See edited question.

– Maxim
Aug 4 '17 at 13:51





True. To tackle this I used changed the id of the button I was interested in to an used button in xinput. See edited question.

– Maxim
Aug 4 '17 at 13:51











2














I have a partial solution. I haven't figured out how to unmap the existing
button, so you end up with a button click and the modifier you want. So if
that mouse button has some existing purpose, it will still fire. For example,
remaping the right mouse button to a control key will result in a control+click
being sent.



Anyway, I found a forum post that is similar to your question for which the
answer was to install btnx and configure your modifiers through that. It seems
btnx is no longer available through the repo. There is a ppa, but it doesnt
work for the latest ubuntu.



Forum post: post: http://ubuntuforums.org/showthread.php?t=1245930



But the source is available:




  • https://github.com/cdobrich/btnx

  • https://github.com/cdobrich/btnx-config


You could compile it from source, but this will put files on your system that
the package manager cannot maintain.



Namely, the following files:



/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


The following symlinks:



/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


So... if you don't mind building from source...



Get the dependencies for btnx:



sudo apt-get install libdaemon-dev git


If you've never built anything from source, you might need build-essential, too:



sudo apt-get install build-essential


Then get and compile btnx:



git clone https://github.com/cdobrich/btnx
cd btnx
./configure
make
sudo make install
cd -


It has a separate GUI configuration tool. Get the dependencies for it:



sudo apt-get install libgtk2.0-dev libglade2-dev


Now get and compile the gui config tool:



git clone https://github.com/cdobrich/btnx-config
./configure
make
sudo make install


Now run the tool:



sudo btnx-config


Click on Detect Mouse Buttons
If you want to be able to read the directions while you use the tool, resize
the window that pops up, the dialog text gets clipped later if you don't and if
you try to resize during detection it will cancel the detection. Just make the
window a bit larger.



Click on Press to start mouse detection, then try not to move the mouse until
the text changes... Takes about 5-10 seconds. The text will change. When it
does, ignore what it says and click Forward.



Click the "Press to start button detection" button



Here you will click one button of your mouse several times (until the status bar fills up).
Then set the name of the button to something you will recognize later (ex: LeftButton)
Click the Add button.



Repeat this for each mouse button (don't forget scroll wheels, scroll clicks,
etc). You can probably skip any buttons you don't want to remap.



When you have added all the buttons, click on OK.



In the main GUI, click on Buttons, in the left pane select teh button you want to remap.
It will use the names you entered in the previous steps.
For your purposes, you'll want to select just a Key modifier under Key combination on the right.



Don't click delete on this screen, it will remove the button. You'll have to
go back and detect the button again if you do.



Go back to the Conrigurations screen and click restart btnx.



Try out the new button.



If you want to uninstall the applicaitons, stop the btnx program and then go
into the respective git checked out directories and make uninstall:



sudo /etc/init.d/btnx stop
cd btnx
sudo make uninstall
cd -
cd btnx-config
sudo make uninstall
cd -





share|improve this answer





















  • 2





    Thanks a lot for the detailed answer you posted at pastebin. But I am afraid that I am not allowed to use an untrusted ppa or build an application from unknown source without reviewing it in detail on my device. Nevertheless I'll give you a vote up for the effort you've put into it. Apart from that I recommend that you update your answer here and copy what you have written there as this information might be helpful for others but might be overlooked. Finally I have read that the package might even not compile under Ubuntu or Debian - have you tried that actually?

    – conceptdeluxe
    May 24 '15 at 15:47











  • Btw: You can gain additional 100 reputation easily by linking your askubuntu account with other Stack Exchange accounts like e.g. Linux & Unix.

    – conceptdeluxe
    May 24 '15 at 15:59











  • Yeah, I tested it under Ubuntu 14.04. I made the right mouse button send a control key and confirmed that it worked before posting. And then almost abandoned the post because of the reputation requirement.

    – Stephen
    May 24 '15 at 16:30
















2














I have a partial solution. I haven't figured out how to unmap the existing
button, so you end up with a button click and the modifier you want. So if
that mouse button has some existing purpose, it will still fire. For example,
remaping the right mouse button to a control key will result in a control+click
being sent.



Anyway, I found a forum post that is similar to your question for which the
answer was to install btnx and configure your modifiers through that. It seems
btnx is no longer available through the repo. There is a ppa, but it doesnt
work for the latest ubuntu.



Forum post: post: http://ubuntuforums.org/showthread.php?t=1245930



But the source is available:




  • https://github.com/cdobrich/btnx

  • https://github.com/cdobrich/btnx-config


You could compile it from source, but this will put files on your system that
the package manager cannot maintain.



Namely, the following files:



/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


The following symlinks:



/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


So... if you don't mind building from source...



Get the dependencies for btnx:



sudo apt-get install libdaemon-dev git


If you've never built anything from source, you might need build-essential, too:



sudo apt-get install build-essential


Then get and compile btnx:



git clone https://github.com/cdobrich/btnx
cd btnx
./configure
make
sudo make install
cd -


It has a separate GUI configuration tool. Get the dependencies for it:



sudo apt-get install libgtk2.0-dev libglade2-dev


Now get and compile the gui config tool:



git clone https://github.com/cdobrich/btnx-config
./configure
make
sudo make install


Now run the tool:



sudo btnx-config


Click on Detect Mouse Buttons
If you want to be able to read the directions while you use the tool, resize
the window that pops up, the dialog text gets clipped later if you don't and if
you try to resize during detection it will cancel the detection. Just make the
window a bit larger.



Click on Press to start mouse detection, then try not to move the mouse until
the text changes... Takes about 5-10 seconds. The text will change. When it
does, ignore what it says and click Forward.



Click the "Press to start button detection" button



Here you will click one button of your mouse several times (until the status bar fills up).
Then set the name of the button to something you will recognize later (ex: LeftButton)
Click the Add button.



Repeat this for each mouse button (don't forget scroll wheels, scroll clicks,
etc). You can probably skip any buttons you don't want to remap.



When you have added all the buttons, click on OK.



In the main GUI, click on Buttons, in the left pane select teh button you want to remap.
It will use the names you entered in the previous steps.
For your purposes, you'll want to select just a Key modifier under Key combination on the right.



Don't click delete on this screen, it will remove the button. You'll have to
go back and detect the button again if you do.



Go back to the Conrigurations screen and click restart btnx.



Try out the new button.



If you want to uninstall the applicaitons, stop the btnx program and then go
into the respective git checked out directories and make uninstall:



sudo /etc/init.d/btnx stop
cd btnx
sudo make uninstall
cd -
cd btnx-config
sudo make uninstall
cd -





share|improve this answer





















  • 2





    Thanks a lot for the detailed answer you posted at pastebin. But I am afraid that I am not allowed to use an untrusted ppa or build an application from unknown source without reviewing it in detail on my device. Nevertheless I'll give you a vote up for the effort you've put into it. Apart from that I recommend that you update your answer here and copy what you have written there as this information might be helpful for others but might be overlooked. Finally I have read that the package might even not compile under Ubuntu or Debian - have you tried that actually?

    – conceptdeluxe
    May 24 '15 at 15:47











  • Btw: You can gain additional 100 reputation easily by linking your askubuntu account with other Stack Exchange accounts like e.g. Linux & Unix.

    – conceptdeluxe
    May 24 '15 at 15:59











  • Yeah, I tested it under Ubuntu 14.04. I made the right mouse button send a control key and confirmed that it worked before posting. And then almost abandoned the post because of the reputation requirement.

    – Stephen
    May 24 '15 at 16:30














2












2








2







I have a partial solution. I haven't figured out how to unmap the existing
button, so you end up with a button click and the modifier you want. So if
that mouse button has some existing purpose, it will still fire. For example,
remaping the right mouse button to a control key will result in a control+click
being sent.



Anyway, I found a forum post that is similar to your question for which the
answer was to install btnx and configure your modifiers through that. It seems
btnx is no longer available through the repo. There is a ppa, but it doesnt
work for the latest ubuntu.



Forum post: post: http://ubuntuforums.org/showthread.php?t=1245930



But the source is available:




  • https://github.com/cdobrich/btnx

  • https://github.com/cdobrich/btnx-config


You could compile it from source, but this will put files on your system that
the package manager cannot maintain.



Namely, the following files:



/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


The following symlinks:



/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


So... if you don't mind building from source...



Get the dependencies for btnx:



sudo apt-get install libdaemon-dev git


If you've never built anything from source, you might need build-essential, too:



sudo apt-get install build-essential


Then get and compile btnx:



git clone https://github.com/cdobrich/btnx
cd btnx
./configure
make
sudo make install
cd -


It has a separate GUI configuration tool. Get the dependencies for it:



sudo apt-get install libgtk2.0-dev libglade2-dev


Now get and compile the gui config tool:



git clone https://github.com/cdobrich/btnx-config
./configure
make
sudo make install


Now run the tool:



sudo btnx-config


Click on Detect Mouse Buttons
If you want to be able to read the directions while you use the tool, resize
the window that pops up, the dialog text gets clipped later if you don't and if
you try to resize during detection it will cancel the detection. Just make the
window a bit larger.



Click on Press to start mouse detection, then try not to move the mouse until
the text changes... Takes about 5-10 seconds. The text will change. When it
does, ignore what it says and click Forward.



Click the "Press to start button detection" button



Here you will click one button of your mouse several times (until the status bar fills up).
Then set the name of the button to something you will recognize later (ex: LeftButton)
Click the Add button.



Repeat this for each mouse button (don't forget scroll wheels, scroll clicks,
etc). You can probably skip any buttons you don't want to remap.



When you have added all the buttons, click on OK.



In the main GUI, click on Buttons, in the left pane select teh button you want to remap.
It will use the names you entered in the previous steps.
For your purposes, you'll want to select just a Key modifier under Key combination on the right.



Don't click delete on this screen, it will remove the button. You'll have to
go back and detect the button again if you do.



Go back to the Conrigurations screen and click restart btnx.



Try out the new button.



If you want to uninstall the applicaitons, stop the btnx program and then go
into the respective git checked out directories and make uninstall:



sudo /etc/init.d/btnx stop
cd btnx
sudo make uninstall
cd -
cd btnx-config
sudo make uninstall
cd -





share|improve this answer















I have a partial solution. I haven't figured out how to unmap the existing
button, so you end up with a button click and the modifier you want. So if
that mouse button has some existing purpose, it will still fire. For example,
remaping the right mouse button to a control key will result in a control+click
being sent.



Anyway, I found a forum post that is similar to your question for which the
answer was to install btnx and configure your modifiers through that. It seems
btnx is no longer available through the repo. There is a ppa, but it doesnt
work for the latest ubuntu.



Forum post: post: http://ubuntuforums.org/showthread.php?t=1245930



But the source is available:




  • https://github.com/cdobrich/btnx

  • https://github.com/cdobrich/btnx-config


You could compile it from source, but this will put files on your system that
the package manager cannot maintain.



Namely, the following files:



/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


The following symlinks:



/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


So... if you don't mind building from source...



Get the dependencies for btnx:



sudo apt-get install libdaemon-dev git


If you've never built anything from source, you might need build-essential, too:



sudo apt-get install build-essential


Then get and compile btnx:



git clone https://github.com/cdobrich/btnx
cd btnx
./configure
make
sudo make install
cd -


It has a separate GUI configuration tool. Get the dependencies for it:



sudo apt-get install libgtk2.0-dev libglade2-dev


Now get and compile the gui config tool:



git clone https://github.com/cdobrich/btnx-config
./configure
make
sudo make install


Now run the tool:



sudo btnx-config


Click on Detect Mouse Buttons
If you want to be able to read the directions while you use the tool, resize
the window that pops up, the dialog text gets clipped later if you don't and if
you try to resize during detection it will cancel the detection. Just make the
window a bit larger.



Click on Press to start mouse detection, then try not to move the mouse until
the text changes... Takes about 5-10 seconds. The text will change. When it
does, ignore what it says and click Forward.



Click the "Press to start button detection" button



Here you will click one button of your mouse several times (until the status bar fills up).
Then set the name of the button to something you will recognize later (ex: LeftButton)
Click the Add button.



Repeat this for each mouse button (don't forget scroll wheels, scroll clicks,
etc). You can probably skip any buttons you don't want to remap.



When you have added all the buttons, click on OK.



In the main GUI, click on Buttons, in the left pane select teh button you want to remap.
It will use the names you entered in the previous steps.
For your purposes, you'll want to select just a Key modifier under Key combination on the right.



Don't click delete on this screen, it will remove the button. You'll have to
go back and detect the button again if you do.



Go back to the Conrigurations screen and click restart btnx.



Try out the new button.



If you want to uninstall the applicaitons, stop the btnx program and then go
into the respective git checked out directories and make uninstall:



sudo /etc/init.d/btnx stop
cd btnx
sudo make uninstall
cd -
cd btnx-config
sudo make uninstall
cd -






share|improve this answer














share|improve this answer



share|improve this answer








edited May 24 '15 at 20:16

























answered May 24 '15 at 14:24









StephenStephen

1,657711




1,657711








  • 2





    Thanks a lot for the detailed answer you posted at pastebin. But I am afraid that I am not allowed to use an untrusted ppa or build an application from unknown source without reviewing it in detail on my device. Nevertheless I'll give you a vote up for the effort you've put into it. Apart from that I recommend that you update your answer here and copy what you have written there as this information might be helpful for others but might be overlooked. Finally I have read that the package might even not compile under Ubuntu or Debian - have you tried that actually?

    – conceptdeluxe
    May 24 '15 at 15:47











  • Btw: You can gain additional 100 reputation easily by linking your askubuntu account with other Stack Exchange accounts like e.g. Linux & Unix.

    – conceptdeluxe
    May 24 '15 at 15:59











  • Yeah, I tested it under Ubuntu 14.04. I made the right mouse button send a control key and confirmed that it worked before posting. And then almost abandoned the post because of the reputation requirement.

    – Stephen
    May 24 '15 at 16:30














  • 2





    Thanks a lot for the detailed answer you posted at pastebin. But I am afraid that I am not allowed to use an untrusted ppa or build an application from unknown source without reviewing it in detail on my device. Nevertheless I'll give you a vote up for the effort you've put into it. Apart from that I recommend that you update your answer here and copy what you have written there as this information might be helpful for others but might be overlooked. Finally I have read that the package might even not compile under Ubuntu or Debian - have you tried that actually?

    – conceptdeluxe
    May 24 '15 at 15:47











  • Btw: You can gain additional 100 reputation easily by linking your askubuntu account with other Stack Exchange accounts like e.g. Linux & Unix.

    – conceptdeluxe
    May 24 '15 at 15:59











  • Yeah, I tested it under Ubuntu 14.04. I made the right mouse button send a control key and confirmed that it worked before posting. And then almost abandoned the post because of the reputation requirement.

    – Stephen
    May 24 '15 at 16:30








2




2





Thanks a lot for the detailed answer you posted at pastebin. But I am afraid that I am not allowed to use an untrusted ppa or build an application from unknown source without reviewing it in detail on my device. Nevertheless I'll give you a vote up for the effort you've put into it. Apart from that I recommend that you update your answer here and copy what you have written there as this information might be helpful for others but might be overlooked. Finally I have read that the package might even not compile under Ubuntu or Debian - have you tried that actually?

– conceptdeluxe
May 24 '15 at 15:47





Thanks a lot for the detailed answer you posted at pastebin. But I am afraid that I am not allowed to use an untrusted ppa or build an application from unknown source without reviewing it in detail on my device. Nevertheless I'll give you a vote up for the effort you've put into it. Apart from that I recommend that you update your answer here and copy what you have written there as this information might be helpful for others but might be overlooked. Finally I have read that the package might even not compile under Ubuntu or Debian - have you tried that actually?

– conceptdeluxe
May 24 '15 at 15:47













Btw: You can gain additional 100 reputation easily by linking your askubuntu account with other Stack Exchange accounts like e.g. Linux & Unix.

– conceptdeluxe
May 24 '15 at 15:59





Btw: You can gain additional 100 reputation easily by linking your askubuntu account with other Stack Exchange accounts like e.g. Linux & Unix.

– conceptdeluxe
May 24 '15 at 15:59













Yeah, I tested it under Ubuntu 14.04. I made the right mouse button send a control key and confirmed that it worked before posting. And then almost abandoned the post because of the reputation requirement.

– Stephen
May 24 '15 at 16:30





Yeah, I tested it under Ubuntu 14.04. I made the right mouse button send a control key and confirmed that it worked before posting. And then almost abandoned the post because of the reputation requirement.

– Stephen
May 24 '15 at 16:30


















draft saved

draft discarded




















































Thanks for contributing an answer to Ask Ubuntu!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f627555%2fhow-to-map-modifiers-e-g-ctrl-to-mouse-thumb-buttons-using-xbindkeys%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Human spaceflight

Can not write log (Is /dev/pts mounted?) - openpty in Ubuntu-on-Windows?

張江高科駅