Cómo asignar modificadores (p. Ej. CTRL) a los botones de pulgar del mouse usando xbindkeys

13

Esta pregunta ya se ha formulado, pero nunca se respondió correctamente. Después de la autorización con @Seth, ahora lo vuelvo a preguntar. Esto me permitirá responder y posiblemente modificar la pregunta mucho más fácilmente. La pregunta original se puede encontrar aquí:

Asigne Ctrl y Alt a los botones del mouse


Problema:

Aunque es muy simple asignar cualquier pulsación de tecla a un botón del mouse usando xbindkeysen conjunto xdotoolo xteparece mucho más problemático asignarle una tecla modificadora (por ejemplo , ALT , CTRL , SHIFT , etc.).

La solución final debe permitir, entre otras cosas, un CTRL + clic (por ejemplo, para seleccionar múltiples entradas de una lista) con solo el mouse.

Puede encontrar un par de enfoques posibles para resolver esto aquí en Stack Exchange, así como en otros foros relacionados con Linux. Pero ninguno de ellos funciona como se esperaba, ya que conducen a otros problemas y efectos secundarios.

Notas:

Algunos de los ejemplos a continuación involucran la sintaxis de Guile con Scheme y dependen del .xbindkeysrc.scmarchivo, mientras que otros dependen del .xbindkeysrcarchivo con su sintaxis respectiva. Soy consciente de que no trabajarán juntos.

Además, los fragmentos a continuación se basan xdotoolúnicamente, pero estoy abierto a enfoques que involucren otras aplicaciones como, por ejemplo xte, también, aunque parece que ambos conducen a los mismos resultados y, por lo tanto, estoy usando solo xdotoolacciones aquí.

Enfoque A:

Actualizando el .xbindkeysrcarchivo con:

"xdotool keydown ctrl"
  b:8

"xdotool keyup ctrl"
  release + b:8

Eso es lo que intenté inicialmente, pero tiene el efecto secundario de que el modificador se está reteniendo y no se puede liberar.

Enfoque B:

Actualizando el .xbindkeysrc.scmarchivo con:

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

Encontrado en http://www.linuxforums.org/forum/hardware-peripherals/169773-solved-map-mouse-button-modifier-key.html e intenta abordar el problema donde se mantiene el modificador (como se describe en el enfoque un).

Aunque corrige que solo funciona parcialmente, ya que no es posible realizar otros clics del mouse mientras se presiona el botón del pulgar.

Enfoque C:

Actualizando el .xbindkeysrcarchivo con:

"xdotool keydown ctrl"
  b:8

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

Probado por OP de la pregunta vinculada aquí en askubuntu. Mucho más simple y más sólido ya que no involucra estados modificadores. Sin embargo, el problema persiste, es decir, no se puede hacer clic CTRL + .

Parece que xbindkeysel problema es en sí mismo ya que reconoce el clic pero no lo ejecuta. Esto se puede probar usando xev | grep buttony xbindkeys -v:

Un clic normal del mouse según lo registrado xevdebería verse así:

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

Además del botón del pulgar:

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

Pero cuando tiene xbindkeyshabilitada la configuración anterior , no registra nada. Aunque tiene sentido para el botón del pulgar, ya que está asignado a CTRL y, por lo tanto, ya no es un botón del mouse, es extraño que el botón 1 no esté grabado también. Esto es probable porque xbindkeysno lo ejecuta pero sí lo reconoce:

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

Enfoque D:

Actualizando el .xbindkeysrcarchivo con:

"xdotool keydown ctrl"
  b:8

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

"xdotool click 1"
  b:1

Simplemente demasiado simple ... pero conduce a un bucle infinito de clics.


ACTUALIZAR:

Mientras tanto, compré un Logitech G502 y noté que una vez configurado a través del controlador en Windows, no solo el perfil en sí se almacena en la memoria del dispositivo, sino que la pulsación de tecla real se realiza con el mouse. ¡De hecho, eso resolvió mi problema en Linux!

El único otro mouse que recuerdo que pudo hacer eso fue el Razer Copperhead en aquellos días. Pero supongo que hay otros ratones disponibles hoy que pueden hacer lo mismo.

conceptdeluxe
fuente
1
He aquí una solución con Easystroke: askubuntu.com/a/1010647/27202
atti

Respuestas:

8

Pasé mucho tiempo tratando de hacer que ese enlace funcionara. Finalmente encontré una solución, que es complicada pero funciona bien y no implica software de terceros. Lo comparto aquí esperando que ayude a la gente. Además, sé que esto no es perfecto en términos de seguridad, por lo que cualquier comentario constructivo es más que bienvenido.

Hay soluciones que son realmente agradables, como la que se propone aquí , pero siempre sufre la limitación de xbindkeys que agarran todo el mouse, lo que hace que los modificadores + el mapeo del mouse sean inciertos. Además, la solución basada en el engaño del enlace anterior usa ctrl + más / ctrl + menos que Gimp no reconoce, por ejemplo.

Me di cuenta de que lo que queremos es un botón del mouse que actúe como teclado, así que usé uinput, a quien se puede acceder a través de Python , escribí un script que monitoriza / dev / my-mouse para hacer clic en el botón del pulgar y enviar la tecla Ctrl al teclado virtual. Aquí están los pasos detallados:

1. Hacer reglas de udev

Queremos que los dispositivos sean accesibles (derechos y ubicación).

Para el ratón:

/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 buscará un dispositivo reconocido por el kernel con nombres como event5, y selecciono mi mouse con el nombre. La instrucción SYMLINK asegura que encontraré mi mouse en / dev / my_mx_mouse. El dispositivo será legible por un miembro del grupo "mxgrabber".

Para encontrar información sobre su hardware, debe ejecutar algo como

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

Para entrada:

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

No es necesario el enlace simbólico, uinput siempre estará $/dev/uinputo $/dev/input/uinputdependerá del sistema en el que se encuentre. Solo dale el grupo y los derechos para leer Y escribir, por supuesto.

Debe desenchufar: conecte el mouse y el nuevo enlace debería aparecer en / dev. Puede obligar a udev a activar sus reglas con$udevadm trigger

2. Active el módulo UINPUT

sudo modprobe uinput

Y para hacerlo persistente:

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

3. Crear nuevo grupo

sudo groupadd mxgrabber

O como sea que haya llamado a su grupo de acceso. Entonces deberías sumarte:

sudo usermod -aG mxgrabber your_login

4. Script de Python

Necesita instalar la biblioteca python-uinput (obviamente) y la biblioteca python-evdev . Use pip o su paquete de distribución.

El script es bastante sencillo, solo tiene que identificar el código de evento del botón.

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

Todo lo que necesita ahora es hacer que su archivo de Python sea ejecutable y pedirle a su administrador de escritorio que cargue el archivo al inicio. ¡Quizás también una copa de vino para celebrar el buen trabajo!

6. Extra gratis

Yo uso xbindkeys para un comportamiento adicional. Por ejemplo, la siguiente configuración puede ser buena si tiene un mouse con clics en el lado de la rueda:

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

Para que esta última combinación funcione, debe deshabilitar el botón que configuró para el script python , de lo contrario, xbindkeys lo tomará. Solo debe permanecer la tecla Ctrl:

~/.Xmodmap
-------------------------------------------
! Disable button 13
! Is mapped to ctrl with uinput and python script
pointer = 1 2 3 4 5 6 7 8 9 10 11 12 0 14 15

Recargar con $ xmodmap ~/.Xmodmap

7. Conclusión

Como dije al principio, no estoy perfectamente contento con el hecho de que tengo que darme los derechos para escribir en / dev / uinput, incluso si se piensa que es el grupo "mxgrabber". Estoy seguro de que hay una forma más segura de hacerlo, pero no sé cómo.

En el lado positivo, funciona muy, muy bien. ¡Cualquier combinación de teclado o tecla del mouse que funcione con el botón Ctrl del teclado ahora funciona con la del mouse!

Aurélien Cibrario
fuente
¡Muchas gracias por el esfuerzo y por compartirlo con nosotros! +1 ... Aunque todavía no lo he probado. Por cierto, casi he renunciado a esto, sería genial si eso funciona como se espera :)
conceptdeluxe
De nada ! Para mí, funciona a la perfección. Si tienes problemas, házmelo saber. Intento completar mi respuesta, pero como pasé casi dos días tratando de que funcione, es posible que haya olvidado algo. Estaré encantado de ayudar / editar mi publicación.
Aurélien Cibrario
Me acabo de dar cuenta de que ctrl + click1 era una muy mala opción para cerrar una pestaña, ya que abre un enlace en una pestaña nueva. Edité mi respuesta eliminando la última parte del script de Python y ajustando con xbindkeys, una solución más limpia
Aurélien Cibrario
solo quiero hacerle saber que todavía no tuve tiempo de probarlo, pero seguro que lo haré la respuesta aceptada si funciona como se esperaba, perdón por la espera, estoy un poco ocupado atm
conceptdeluxe
Me pregunto si podemos usar el script anterior para eliminar el error de un interruptor de mouse defectuoso. Tengo un mouse desgastado. Utilizo un script de autohotkey para arreglarlo en Windows pero no hay ninguna herramienta para arreglarlo en Linux. Aquí está la secuencia de comandos Autohhotkey para la corrección del botón izquierdo autohotkey.com/board/topic/63555-debounce-mouse-keys Espero que alguien lo transfiera a Linux usando python3 - evdev
kenn
4

Encontré una solución con PyUserInput . Esto termina siendo bastante simple y no requiere derechos de administración. Con python 2 y PyUserInput instalados, utilicé el siguiente 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()

Después de otorgar derechos de ejecución al script, lo llamo con una línea ~/.xsessionrc, por ejemplo

~ / ruta / a / script.py &

Nota . Esto no impide que se active el evento del botón del mouse. En mi caso, solía xinput set-button-mapcambiar la asignación del botón xinput y asignar el número del botón que me interesaba a algo que no estaba en uso.

Por ejemplo, si desea usar el botón 8 en su mouse pero el botón 8 ya tiene una función (por ejemplo page-next), puede usar lo siguiente.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 &

Botón proporcionado 12no tiene significado para el sistema operativo, y asignar una función personalizada para el botón 12de .xbuttonmodifier.py, la secuencia de comandos que he descrito anteriormente.

Máxima
fuente
Pero no impide que se dispare el evento original. Entonces, si mapeo el botón 8 para cambiar, y mantengo presionado el botón 8 en Firefox, también intenta volver a la página anterior, lo que no es deseable.
user23013
1
Cierto. Para abordar esto, cambié la identificación del botón que me interesaba a un botón usado xinput. Ver pregunta editada.
Maxim
2

Tengo una solución parcial No he descubierto cómo desasignar el botón existente, por lo que terminas haciendo clic en el botón y el modificador que deseas. Entonces, si ese botón del mouse tiene algún propósito existente, todavía se disparará. Por ejemplo, al reasignar el botón derecho del mouse a una tecla de control, se enviará un control + clic.

De todos modos, encontré una publicación en el foro que es similar a su pregunta para la cual la respuesta fue instalar btnx y configurar sus modificadores a través de eso. Parece que btnx ya no está disponible a través del repositorio. Hay un ppa, pero no funciona para el último ubuntu.

Publicación en el foro: publicación: http://ubuntuforums.org/showthread.php?t=1245930

Pero la fuente está disponible:

Puede compilarlo desde el origen, pero esto colocará archivos en su sistema que el administrador de paquetes no puede mantener.

A saber, los siguientes archivos:

/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

Los siguientes enlaces simbólicos:

/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

Entonces ... si no te importa construir desde la fuente ...

Obtenga las dependencias para btnx:

sudo apt-get install libdaemon-dev git

Si nunca ha construido nada desde la fuente, es posible que también necesite build-essential:

sudo apt-get install build-essential

Luego obtenga y compile btnx:

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

Tiene una herramienta de configuración GUI separada. Obtenga las dependencias para ello:

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

Ahora obtenga y compile la herramienta de configuración de GUI:

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

Ahora ejecuta la herramienta:

sudo btnx-config

Haga clic en Detectar botones del mouse Si desea poder leer las instrucciones mientras usa la herramienta, cambie el tamaño de la ventana que aparece, el texto del diálogo se recorta más tarde si no lo hace y si intenta cambiar el tamaño durante la detección, se cancelará La detección. Solo haz la ventana un poco más grande.

Haga clic en Presione para iniciar la detección del mouse, luego intente no mover el mouse hasta que el texto cambie ... Tarda unos 5-10 segundos. El texto cambiará. Cuando lo haga, ignore lo que dice y haga clic en Adelante.

Haga clic en el botón "Presione para iniciar la detección del botón"

Aquí hará clic en un botón de su mouse varias veces (hasta que la barra de estado se llene). Luego, establezca el nombre del botón en algo que reconocerá más adelante (por ejemplo: LeftButton) Haga clic en el botón Agregar.

Repita esto para cada botón del mouse (no olvide las ruedas de desplazamiento, los clics de desplazamiento, etc.). Probablemente pueda omitir cualquier botón que no quiera reasignar.

Cuando haya agregado todos los botones, haga clic en Aceptar.

En la GUI principal, haga clic en Botones, en el panel izquierdo, seleccione el botón que desea reasignar. Utilizará los nombres que ingresó en los pasos anteriores. Para sus propósitos, querrá seleccionar solo un modificador de clave en Combinación de teclas a la derecha.

No haga clic en Eliminar en esta pantalla, eliminará el botón. Tendrá que volver y detectar el botón nuevamente si lo hace.

Vuelva a la pantalla Conriguraciones y haga clic en reiniciar btnx.

Prueba el nuevo botón.

Si desea desinstalar las aplicaciones, detenga el programa btnx y luego vaya a los respectivos directorios desprotegidos de git y realice la desinstalación:

sudo /etc/init.d/btnx stop
cd btnx
sudo make uninstall
cd -
cd btnx-config
sudo make uninstall
cd -
Stephen
fuente
2
Muchas gracias por la respuesta detallada que publicaste en pastebin. Pero me temo que no puedo usar un ppa que no sea de confianza o crear una aplicación de origen desconocido sin revisarlo en detalle en mi dispositivo. Sin embargo, le daré un voto por el esfuerzo que ha realizado. Aparte de eso, le recomiendo que actualice su respuesta aquí y copie lo que ha escrito allí, ya que esta información puede ser útil para otros pero puede pasarse por alto. Finalmente, he leído que el paquete podría incluso no compilarse en Ubuntu o Debian, ¿lo has intentado realmente?
conceptdeluxe
Por cierto: puede ganar fácilmente 100 reputación adicionales al vincular su cuenta de askubuntu con otras cuentas de Stack Exchange como, por ejemplo, Linux y Unix.
conceptdeluxe
Sí, lo probé en Ubuntu 14.04. Hice que el botón derecho del mouse enviara una tecla de control y confirme que funcionaba antes de publicar. Y luego casi abandonó la publicación debido al requisito de reputación.
Stephen