Come mappare i modificatori (ad es. CTRL) ai pulsanti del mouse usando xbindkeys


13

Questa domanda è già stata posta ma non è mai stata data una risposta adeguata. Dopo l'autorizzazione con @Seth ora lo sto chiedendo di nuovo. Questo mi permetterà di rispondere e, eventualmente, di modificare la domanda molto più facilmente. La domanda originale può essere trovata qui:

Mappa Ctrl e Alt per i pulsanti del pollice del mouse


Problema:

Sebbene sia molto semplice mappare qualsiasi sequenza di tasti a un pulsante del mouse usando xbindkeysinsieme xdotoolo xtesembra molto più problematico mappare un tasto modificatore (ad esempio ALT , CTRL , SHIFT ecc.) Su di esso.

L'assolo finale dovrebbe consentire tra l'altro un CTRL + clic (ad es. Per selezionare più voci di un elenco) con il solo mouse.

Un paio di possibili approcci per risolvere questo problema possono essere trovati qui su Stack Exchange e in altri forum relativi a Linux. Ma nessuno di questi funziona come previsto poiché porta ad altri problemi ed effetti collaterali.

Appunti:

Alcuni degli esempi seguenti riguardano Guile con la sintassi dello Schema e si basano sul .xbindkeysrc.scmfile, mentre altri si basano sul .xbindkeysrcfile con la relativa sintassi. Sono consapevole che non funzioneranno insieme.

Inoltre, i seguenti frammenti si basano xdotoolsolo su, ma sono aperto ad approcci che coinvolgono anche altre applicazioni come ad xteesempio, anche se sembra che conducano entrambi agli stessi risultati e quindi sto usando solo xdotoolazioni qui.

Approccio A:

Aggiornamento del .xbindkeysrcfile con:

"xdotool keydown ctrl"
  b:8

"xdotool keyup ctrl"
  release + b:8

Questo è quello che ho provato inizialmente, ma ha l'effetto collaterale che il modificatore viene trattenuto e non può essere rilasciato.

Approccio B:

Aggiornamento del .xbindkeysrc.scmfile 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")

Si trova su http://www.linuxforums.org/forum/hardware-peripherals/169773-solved-map-mouse-button-modifier-key.html e cerca di risolvere il problema in cui si tiene il modificatore (come descritto nell'approccio un).

Anche se risolve che funziona solo parzialmente in quanto non è possibile eseguire altri clic del mouse mentre si preme il pulsante del pollice.

Approccio C:

Aggiornamento del .xbindkeysrcfile con:

"xdotool keydown ctrl"
  b:8

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

Testato dall'OP della domanda collegata qui su askubuntu. Molto più semplice e più solido in quanto non coinvolge stati modificatori. Tuttavia, il problema persiste, ovvero un CTRL + non è possibile clic .

Sembra che questo xbindkeyssia il problema in quanto riconosce il clic ma non lo esegue. Questo può essere testato usando xev | grep buttonexbindkeys -v :

Un normale clic del mouse registrato da xevdovrebbe apparire come:

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

Oltre che per il pulsante pollice:

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

Ma quando la xbindkeysconfigurazione sopra abilitata non registra nulla. Sebbene abbia senso per il pulsante pollice in quanto è mappato su CTRL e quindi non è più un pulsante del mouse, è strano che anche il pulsante 1 non sia registrato. Ciò è probabilmente dovuto al fatto che xbindkeysnon lo esegue ma lo riconosce di per sé:

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

Approccio D:

Aggiornamento del .xbindkeysrcfile con:

"xdotool keydown ctrl"
  b:8

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

"xdotool click 1"
  b:1

Semplicemente troppo semplice ... ma porta a un ciclo infinito di clic.


AGGIORNARE:

Nel frattempo ho comprato un Logitech G502 e ho notato che una volta configurato tramite il driver su Windows non solo il profilo stesso è archiviato nella memoria del dispositivo, ma l'attuale pressione dei tasti viene eseguita dal mouse. Che in realtà ha risolto il mio problema su Linux!

L'unico altro topo che ricordo che fu in grado di fare fu il Razer Copperhead ai tempi. Ma immagino ci siano altri topi disponibili oggi che possono fare lo stesso.


1
ecco una soluzione che usa Easystroke: askubuntu.com/a/1010647/27202
atti

Risposte:


8

Ho trascorso molto tempo cercando di far funzionare quel legame. Alla fine ho trovato una soluzione, che è complicata ma funziona bene e non implica software di terze parti. Lo condivido qui sperando che possa aiutare le persone. Inoltre, so che questo non è perfetto in termini di sicurezza, quindi qualsiasi feedback costruttivo è più che benvenuto.

Ci sono soluzioni davvero carine, come quella qui proposta , ma soffre sempre della limitazione di xbindkeys che afferrano l'intero mouse, rendendo incerti modificatori + mappatura del clic del mouse. Inoltre la soluzione basata sull'astuzia dal link precedente usa ctrl + più / ctrl + meno che non è riconosciuto da Gimp, per esempio.

Ho capito che quello che vogliamo è un pulsante del mouse che funga da tastiera, quindi ho usato uinput, a cui è possibile accedere tramite Python , scritto uno script che monitora / dev / my-mouse per fare clic sul pulsante del pollice e invia il tasto ctrl alla tastiera virtuale. Ecco i passaggi dettagliati:

1. Crea regole udev

Vogliamo che i dispositivi siano accessibili (diritti e posizione).

Per il 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 cercherà un dispositivo riconosciuto dal kernel con nomi come event5 e selezionerò il mio mouse con il nome. Le istruzioni SYMLINK assicurano che troverò il mio mouse in / dev / my_mx_mouse. Il dispositivo sarà leggibile da un membro del gruppo "mxgrabber".

Per trovare informazioni sul tuo hardware, dovresti eseguire qualcosa del genere

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

Per uinput:

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

Non è necessario il collegamento simbolico, uinput sarà sempre in $/dev/uinputo$/dev/input/uinput base al sistema in cui ti trovi. Dagli semplicemente il gruppo e i diritti di leggere e scrivere ovviamente.

È necessario scollegare - collegare il mouse e il nuovo collegamento dovrebbe apparire in / dev. Puoi forzare udev a innescare le tue regole con$udevadm trigger

2. Attiva il modulo UINPUT

sudo modprobe uinput

E per renderlo permanente:

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

3. Crea un nuovo gruppo

sudo groupadd mxgrabber

O qualunque cosa tu abbia chiamato il tuo gruppo di accesso. Quindi dovresti aggiungerti ad esso:

sudo usermod -aG mxgrabber your_login

4. Script Python

Devi installare la libreria python-uinput (ovviamente) e la libreria python-evdev . Usa pip o il tuo pacchetto di distribuzione.

Lo script è piuttosto semplice, devi solo identificare il codice event.code del tuo pulsante.

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

Tutto ciò che serve ora è rendere eseguibile il file python e chiedere al desktop manager di caricare il file all'avvio. Forse anche un bicchiere di vino per festeggiare l'ottimo lavoro!

6. Extra gratis

Uso xbindkeys per un comportamento aggiuntivo. Ad esempio, la seguente configurazione può essere utile se si dispone di un mouse con clic sul lato ruota:

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

Perché quest'ultima combinazione funzioni, è necessario disabilitare il pulsante configurato per lo script Python , altrimenti verrà comunque bloccato da xbindkeys. Deve rimanere solo il tasto 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

Ricarica con $ xmodmap ~/.Xmodmap

7. Conclusione

Come ho detto all'inizio, non sono perfettamente soddisfatto del fatto che devo darmi i diritti per scrivere a / dev / uinput, anche se si pensa che il gruppo "mxgrabber". Sono sicuro che esiste un modo più sicuro per farlo, ma non so come.

Il lato positivo è che funziona davvero molto bene. Qualsiasi combinazione di tastiera o mouse come funziona con il tasto Ctrl della tastiera ora funziona con quella del mouse !!


Grazie mille per lo sforzo e per averlo condiviso con noi! +1 ... Anche se non l'ho ancora testato. A proposito, ho quasi rinunciato a questo - sarebbe fantastico se funzionasse come previsto :)
conceptdeluxe

Prego ! Per me funziona perfettamente. Se hai problemi, fammi sapere. Cerco di completare la mia risposta, ma dato che ho trascorso quasi due giorni cercando di farlo funzionare, potrei aver dimenticato qualcosa. Saremo lieti di aiutare / modificare il mio post.
Aurélien Cibrario

Mi sono appena reso conto che ctrl + click1 era una pessima scelta per chiudere una scheda poiché apriva un collegamento in una nuova scheda. Ho modificato la mia risposta rimuovendo l'ultima parte dello script Python e modificando con xbindkeys, soluzione più pulita
Aurélien Cibrario

voglio solo farti sapere che non ho ancora avuto il tempo di testarlo - ma lo farò sicuramente la risposta accettata se funziona come previsto - scusami per l'attesa - Sono un po 'occupato atm
conceptdeluxe

Mi chiedo se possiamo usare lo script sopra per rimandare un interruttore del mouse difettoso. Ho un topo sfinito. Uso uno script autohotkey per risolverlo in Windows ma non esiste uno strumento per risolverlo in Linux. Ecco lo script Autohhotkey per la correzione del pulsante sinistro autohotkey.com/board/topic/63555-debounce-mouse-keys Spero che qualcuno lo porti su Linux usando python3 - evdev
kenn

4

Ho trovato una soluzione con PyUserInput . Questo finisce per essere abbastanza semplice e non richiede diritti di amministrazione. Con python 2 e PyUserInput installati, ho usato il seguente 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()

Dopo aver dato i diritti di esecuzione allo script, lo chiamo con una linea ~/.xsessionrc, per esempio

~ / path / to / script.py &

Nota . ciò non impedisce che l'evento del pulsante del mouse si attivi. Nel mio caso ho usato xinput set-button-mapper cambiare la mappatura del pulsante xinput e assegnare il numero del pulsante che mi interessava a qualcosa che non era in uso.

Ad esempio, se si desidera utilizzare il pulsante 8 sul mouse ma il pulsante 8 ha già una funzione (ad esempio, page-next), è possibile utilizzare quanto segue.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 &

il pulsante fornito 12non ha alcun significato per il sistema operativo e assegna una funzione personalizzata al pulsante 12in .xbuttonmodifier.py, lo script che ho descritto sopra.


Ma ciò non impedisce che l'evento originale venga generato. Quindi, se mappo il pulsante 8 per spostarmi e tengo premuto il pulsante 8 in Firefox, prova anche a tornare alla pagina precedente, il che è indesiderabile.
user23013

1
Vero. Per risolvere questo problema, ho usato l'ID del pulsante a cui ero interessato in un pulsante usato xinput. Vedi domanda modificata.
Massimo

2

Ho una soluzione parziale. Non ho capito come annullare l'associazione del pulsante esistente, quindi si finisce con un clic sul pulsante e il modificatore desiderato. Quindi, se quel pulsante del mouse ha uno scopo esistente, si attiverà comunque. Ad esempio, rimappando il tasto destro del mouse su un tasto di controllo, verrà inviato un controllo + clic.

Comunque, ho trovato un post sul forum simile alla tua domanda per la quale la risposta era installare btnx e configurare i tuoi modificatori attraverso quello. Sembra che btnx non sia più disponibile tramite il repository. C'è un ppa, ma non funziona con l'ultimo Ubuntu.

Post del forum: post: http://ubuntuforums.org/showthread.php?t=1245930

Ma la fonte è disponibile:

Potresti compilarlo dal sorgente, ma questo metterà sul tuo sistema file che il gestore pacchetti non può mantenere.

Vale a dire, i seguenti file:

/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

I seguenti link simbolici:

/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

Quindi ... se non ti dispiace costruire dalla fonte ...

Ottieni le dipendenze per btnx:

sudo apt-get install libdaemon-dev git

Se non hai mai creato nulla dalla fonte, potresti aver bisogno anche di build-essential:

sudo apt-get install build-essential

Quindi ottenere e compilare btnx:

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

Ha uno strumento di configurazione della GUI separato. Ottieni le dipendenze per questo:

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

Ora ottieni e compila lo strumento di configurazione della gui:

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

Ora esegui lo strumento:

sudo btnx-config

Fare clic su Rileva pulsanti del mouse Se si desidera essere in grado di leggere le indicazioni mentre si utilizza lo strumento, ridimensionare la finestra che si apre, il testo della finestra di dialogo viene ritagliato in seguito se non lo si fa e se si tenta di ridimensionare durante il rilevamento si annulla il rilevamento. Rendi la finestra un po 'più grande.

Fare clic su Premere per avviare il rilevamento del mouse, quindi provare a non spostare il mouse fino a quando il testo non cambia ... Impiega circa 5-10 secondi. Il testo cambierà. Quando lo fa, ignora ciò che dice e fai clic su Avanti.

Fai clic sul pulsante "Premi per avviare il rilevamento dei pulsanti"

Qui fai clic più volte su un pulsante del mouse (fino a quando la barra di stato non si riempie). Quindi imposta il nome del pulsante su qualcosa che riconoscerai in seguito (es: Pulsante Sinistra) Fai clic sul pulsante Aggiungi.

Ripeti l'operazione per ogni pulsante del mouse (non dimenticare le rotelle di scorrimento, i clic di scorrimento, ecc.). Probabilmente puoi saltare qualsiasi pulsante che non desideri rimappare.

Dopo aver aggiunto tutti i pulsanti, fare clic su OK.

Nella GUI principale, fai clic su Pulsanti, nel riquadro di sinistra seleziona il pulsante che desideri rimappare. Utilizzerà i nomi inseriti nei passaggi precedenti. Per i tuoi scopi, ti consigliamo di selezionare solo un modificatore di chiave in Combinazione di tasti sulla destra.

Non fare clic su Elimina in questa schermata, rimuoverà il pulsante. Dovrai tornare indietro e rilevare nuovamente il pulsante se lo fai.

Torna alla schermata delle Conrigurazioni e fai clic su riavvia btnx.

Prova il nuovo pulsante.

Se si desidera disinstallare le applicazioni, arrestare il programma btnx e quindi accedere alle rispettive directory estratte da git ed eseguire la disinstallazione:

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

2
Grazie mille per la risposta dettagliata che hai pubblicato su pastebin. Ma temo di non poter utilizzare un ppa non attendibile o creare un'applicazione da una fonte sconosciuta senza esaminarla in dettaglio sul mio dispositivo. Tuttavia, ti darò un voto per lo sforzo che ci hai messo. A parte ciò, ti consiglio di aggiornare qui la tua risposta e di copiare ciò che hai scritto in quanto queste informazioni potrebbero essere utili per gli altri ma potrebbero essere trascurate. Finalmente ho letto che il pacchetto potrebbe anche non essere compilato sotto Ubuntu o Debian - l'hai provato davvero?
conceptdeluxe

A proposito: puoi guadagnare facilmente 100 reputazione aggiuntiva collegando il tuo account askubuntu con altri account Stack Exchange come ad esempio Linux e Unix.
conceptdeluxe

Sì, l'ho provato con Ubuntu 14.04. Ho fatto in modo che il tasto destro del mouse inviasse un tasto di controllo e ho confermato che funzionava prima della pubblicazione. E poi quasi abbandonato il posto a causa del requisito di reputazione.
Stephen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.