Como mapear modificadores (por exemplo, CTRL) para botões de polegar do mouse usando xbindkeys

10

Esta pergunta já foi feita, mas nunca foi respondida corretamente. Após a liberação com @Seth, estou perguntando novamente. Isso me permitirá responder e possivelmente modificar a questão muito mais fácil. A pergunta original pode ser encontrada aqui:

Mapeie Ctrl e Alt para os botões do polegar do mouse

Problema:

Embora seja muito simples mapear qualquer pressionamento de teclas a um botão do mouse usando xbindkeys em conjunto com xdotool ou xte , parece muito mais problemático mapear uma tecla modificadora (por exemplo, ALT , CTRL , SHIFT etc.) para ele.

A solução final deve permitir i.a. um CTRL + clique (por exemplo, para selecionar várias entradas de uma lista) apenas com o mouse.

Algumas abordagens possíveis para resolver isso podem ser encontradas aqui no Stack Exchange, bem como em outros fóruns relacionados ao Linux. Mas nenhum deles funciona como esperado, pois levam a outros problemas e efeitos colaterais.

Notas:

Alguns exemplos abaixo envolvem Guile com a sintaxe Scheme e dependem do arquivo .xbindkeysrc.scm enquanto outros contam com o arquivo .xbindkeysrc com sua respectiva sintaxe. Estou ciente de que eles não vão funcionar juntos.

Além disso, os snippets abaixo dependem apenas de xdotool , mas estou aberto a abordagens envolvendo outros aplicativos, como, por exemplo, xte também - embora pareça que ambos levam aos mesmos resultados e, portanto, estou usando apenas xdotool actions aqui.

Abordagem A:

Atualizando o arquivo .xbindkeysrc com:

"xdotool keydown ctrl"
  b:8

"xdotool keyup ctrl"
  release + b:8

Isso foi o que eu tentei inicialmente, mas tem o efeito colateral que o modificador está mantendo e não pode ser liberado.

Abordagem B:

Atualizando o arquivo .xbindkeysrc.scm com:

(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 no link e tenta para resolver o problema em que o modificador está sendo realizado (conforme descrito na abordagem a).

Embora conserte que funcione apenas parcialmente, pois não é possível executar outros cliques do mouse enquanto o botão miniatura é pressionado.

Abordagem C:

Atualizando o arquivo .xbindkeysrc com:

"xdotool keydown ctrl"
  b:8

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

Tentei por OP da pergunta vinculada aqui no askubuntu. Muito mais simples e mais sólido, pois não envolve estados modificadores. No entanto, o problema permanece, ou seja, um clique CTRL + não é possível.

Parece que xbindkeys é o problema aqui, pois reconhece o clique, mas não o executa. Isso pode ser testado usando xev | grep button e xbindkeys -v :

Um clique normal do mouse, como registrado por xev , deve se parecer com:

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

Além do botão de polegar:

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

Mas quando a configuração xbindkeys acima está ativada, ela não registra nada. Embora faça sentido para o botão thumb como ele é mapeado para CTRL e, portanto, não é mais um botão do mouse, é estranho que botão 1 não seja gravado também. Isso é provável porque xbindkeys não o executa, mas está reconhecendo-o:

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

Abordagem D:

Atualizando o arquivo .xbindkeysrc com:

"xdotool keydown ctrl"
  b:8

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

"xdotool click 1"
  b:1

Simples demais ... mas leva a um loop infinito de cliques.

ATUALIZAÇÃO:

Entretanto, comprei um Logitech G502 e notei que, uma vez configurado através do driver no Windows, não apenas o próprio perfil é armazenado na memória do dispositivo, mas o pressionamento de tecla real é feito pelo mouse. Isso de fato resolveu meu problema no Linux!

O único outro rato que me lembro que foi capaz de fazer isso foi o Razer Copperhead nos dias de hoje. Mas eu acho que existem outros mouses disponíveis hoje que podem fazer o mesmo.

    
por conceptdeluxe 24.05.2015 / 05:39

3 respostas

6

Passei muito tempo tentando fazer esse trabalho de encadernação. Eu finalmente encontrei uma solução, que é complicada, mas funciona bem e não implica software de terceiros. Eu compartilho aqui esperando que isso ajude as pessoas. Além disso, sei que isso não é perfeito em termos de segurança, portanto, qualquer feedback construtivo é mais do que bem-vindo.

Existem soluções que são realmente legais, como a proposta aqui , mas sempre sofrem com a limitação de xbindkeys que pegam o mouse inteiro, tornando os modificadores + mapeamento de cliques do mouse incertos. Além disso, a solução baseada em guile do link acima usa ctrl + plus / ctrl + minus que não é reconhecido pelo Gimp, por exemplo.

Eu descobri que o que queremos é um botão do mouse que funcione como um teclado, então usei o uinput, que pode ser acessado via python , escreveu um script que monitora / dev / my-mouse para o botão do polegar e envia a tecla ctrl para o teclado virtual. Aqui estão os passos detalhados:

1. Faça as regras do udev

Queremos que os dispositivos sejam acessíveis (direitos e localização).

Para o 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"

O Udev irá procurar por um dispositivo reconhecido pelo kernel com nomes como event5, e eu seleciono meu mouse com o nome. A instrução SYMLINK assegura que eu localizarei meu mouse em / dev / my_mx_mouse. O dispositivo será legível por um membro do grupo "mxgrabber".

Para encontrar informações sobre seu hardware, você deve executar algo como

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

Para entrada de dados:

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

Não há necessidade de symlink, o uinput sempre estará em $/dev/uinput ou $/dev/input/uinput , dependendo do sistema em que você está. Apenas dê a ele o grupo e os direitos de ler E escrever, é claro.

Você precisa desconectar - conecte o mouse e o novo link deve aparecer em / dev. Você pode forçar o udev a acionar suas regras com $udevadm trigger

2. Ativar o módulo UINPUT

sudo modprobe uinput

E para que o boot seja persistente:

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

3. Criar novo grupo

sudo groupadd mxgrabber

Ou o que você chamou de seu grupo de acesso. Então você deve se adicionar a ele:

sudo usermod -aG mxgrabber your_login

4. Script Python

Você precisa instalar a biblioteca python-uinput (obviamente) e a biblioteca python-evdev . Use pip ou seu pacote de distribuição.

O script é bastante simples, você só precisa identificar o código event.code de você.

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

Tudo o que você precisa agora é tornar seu arquivo python executável e pedir ao seu gerenciador de área de trabalho para carregar o arquivo na inicialização. Talvez também um copo de vinho para celebrar o bom trabalho!

6. Extra grátis

Eu uso xbindkeys para comportamento adicional. Por exemplo, a seguinte configuração pode ser interessante se você tiver um mouse com cliques no lado da roda:

~/.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 combinação funcione, você deve desativar o botão que você configurou para o script python , caso contrário, ele ainda será capturado por xbindkeys. Apenas a tecla Ctrl deve permanecer:

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

Recarregue com $ xmodmap ~/.Xmodmap

7. Conclusão

Como eu disse no começo, eu não estou perfeitamente feliz com o fato de que eu tenho que me dar os cuidados para escrever em / dev / uinput, mesmo que se pense no grupo "mxgrabber". Tenho certeza de que há uma maneira mais segura de fazer isso, mas não sei como.

No lado positivo, funciona muito bem. Qualquer combinação de teclas de teclado ou mouse como funciona com o botão Ctrl do teclado agora funciona com o mouse !! p>     

por Aurélien Cibrario 06.01.2016 / 14:31
2

Eu tenho uma solução parcial. Eu não descobri como desmapear o existente botão, então você acaba com um clique no botão e o modificador que você quer. Então se Se o botão do mouse tiver alguma finalidade, ele ainda será disparado. Por exemplo, remaping o botão direito do mouse para uma tecla de controle irá resultar em um controle + clique sendo enviado.

De qualquer forma, encontrei uma postagem no fórum semelhante à sua pergunta para a qual A resposta foi instalar o btnx e configurar seus modificadores através disso. Parece O btnx não está mais disponível através do repo. Há um ppa, mas não trabalhar para o ubuntu mais recente.

Post no fórum: post: link

Mas a fonte está disponível:

Você pode compilá-lo a partir do código-fonte, mas isso colocará arquivos no sistema que o gerenciador de pacotes não pode manter.

Ou seja, os seguintes arquivos:

/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

Os seguintes links 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

Então ... se você não se importar em construir a partir do código-fonte ...

Obtenha as dependências para o btnx:

sudo apt-get install libdaemon-dev git

Se você nunca criou nada a partir do código-fonte, também poderá precisar do essencial:

sudo apt-get install build-essential

Então pegue e compile btnx:

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

Tem uma ferramenta de configuração GUI separada. Obtenha as dependências para isso:

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

Agora pegue e compile a ferramenta de configuração de gui:

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

Agora, execute a ferramenta:

sudo btnx-config

Clique em Detectar botões do mouse Se você quiser ler as instruções enquanto usa a ferramenta, redimensione a janela que aparece, o texto da caixa de diálogo é cortado mais tarde se você não o fizer e se você tenta redimensionar durante a detecção, ele cancelará a detecção. Basta fazer o janela um pouco maior.

Clique em Pressione para iniciar a detecção do mouse e tente não mover o mouse até o texto muda ... Leva cerca de 5-10 segundos. O texto vai mudar. Quando ignora o que diz e clica em Avançar.

Clique no botão "Pressione para iniciar a detecção do botão"

Aqui você clicará em um botão do mouse várias vezes (até que a barra de status fique cheia). Em seguida, defina o nome do botão para algo que você reconhecerá mais tarde (ex: LeftButton) Clique no botão Adicionar.

Repita isso para cada botão do mouse (não se esqueça das rodas de rolagem, cliques de rolagem, etc). Você provavelmente pode pular todos os botões que você não deseja remapear.

Quando você tiver adicionado todos os botões, clique em OK.

Na interface principal, clique em Botões, no painel esquerdo, selecione o botão que você deseja remapear. Ele usará os nomes digitados nas etapas anteriores. Para seus objetivos, você desejará selecionar apenas um modificador de chave na combinação de teclas à direita.

Não clique em excluir nesta tela, ele removerá o botão. Você terá que volte e detecte o botão novamente se você fizer isso.

Volte para a tela Conrigurations e clique em restart btnx.

Experimente o novo botão.

Se você quiser desinstalar os aplicativos, pare o programa btnx e vá no respectivo git check out diretórios e faça a desinstalação:

sudo /etc/init.d/btnx stop
cd btnx
sudo make uninstall
cd -
cd btnx-config
sudo make uninstall
cd -
    
por Stephen 24.05.2015 / 16:24
2

Eu encontrei uma solução com PyUserInput . Isso acaba sendo bastante simples e não requer direitos de administração. Com o python 2 e o PyUserInput instalados, usei o seguinte 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()

Depois de dar direitos de execução ao script, eu o chamo com uma linha em ~/.xsessionrc , por exemplo

~ / caminho / para / script.py & amp;

Nota . isso não impede que o evento do botão do mouse seja disparado. No meu caso usei xinput set-button-map para alterar o mapeamento do botão xinput e atribuir o número do botão em que eu estava interessado para algo que não estava em uso.

Por exemplo, se você quiser usar o botão 8 do mouse, mas o botão 8 já tiver uma função (por exemplo, page-next ), você pode usar o seguinte .xsessionrc

logitech_mouse_id=$(xinput | grep "Logitech M705" | sed 's/^.*id=\([0-9]*\)[ \t].*$//')
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 &
O botão

fornecido 12 não tem significado para o sistema operacional e atribui uma função personalizada ao botão 12 in .xbuttonmodifier.py , o script que descrevi acima.

    
por Maxim 11.04.2017 / 01:59