Jak mapować modyfikatory (np. CTRL) na przyciski kciuka myszy za pomocą xbindkeys

13

To pytanie zostało już zadane, ale nigdy nie udzielono właściwej odpowiedzi. Po odprawie w @Seth pytam teraz ponownie. Pozwoli mi to odpowiedzieć i ewentualnie zmodyfikować pytanie o wiele łatwiej. Oryginalne pytanie można znaleźć tutaj:

Mapuj Ctrl i Alt na przyciskach myszy


Kwestia:

Chociaż bardzo proste jest przypisanie dowolnego naciśnięcia klawisza do przycisku myszy za pomocą xbindkeysw połączeniu z xdotoollub xtewydaje się o wiele bardziej problematyczne mapowanie klawisza modyfikującego (np. ALT , CTRL , SHIFT itp.).

Ostateczne rozwiązanie powinno pozwolić m.in. na CTRL + kliknięcie (np. W celu wybrania wielu pozycji listy) za pomocą myszy.

Kilka możliwych sposobów rozwiązania tego problemu można znaleźć tutaj na Stack Exchange oraz na innych forach związanych z Linuksem. Ale żaden z nich nie działa zgodnie z oczekiwaniami, ponieważ prowadzi do innych problemów i skutków ubocznych.

Uwagi:

Niektóre z poniższych przykładów dotyczą Guile ze składnią Scheme i polegają na .xbindkeysrc.scmpliku, podczas gdy inne polegają na .xbindkeysrcpliku z odpowiednią składnią. Wiem, że nie będą ze sobą współpracować.

Ponadto poniższe fragmenty polegają xdotooltylko na, ale jestem otwarty na podejścia obejmujące inne aplikacje, takie jak np xte. - chociaż wydaje się, że oba prowadzą do tych samych rezultatów i dlatego używam xdotooltutaj tylko akcji.

Podejście A:

Aktualizacja .xbindkeysrcpliku za pomocą:

"xdotool keydown ctrl"
  b:8

"xdotool keyup ctrl"
  release + b:8

Tak początkowo próbowałem, ale ma efekt uboczny, że modyfikator jest trzymany i nie można go zwolnić.

Podejście B:

Aktualizacja .xbindkeysrc.scmpliku za pomocą:

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

Znaleziony na http://www.linuxforums.org/forum/hardware-peripherals/169773-solved-map-mouse-button-modifier-key.html i próbuje rozwiązać problem związany z trzymaniem modyfikatora (zgodnie z opisem w podejściu za).

Chociaż naprawia to, że działa tylko częściowo, ponieważ nie można wykonywać innych kliknięć myszą, gdy przycisk kciuka jest wciśnięty.

Podejście C:

Aktualizacja .xbindkeysrcpliku za pomocą:

"xdotool keydown ctrl"
  b:8

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

Wypróbowane przez OP powiązanego pytania tutaj na askubuntu. O wiele prostsze i bardziej solidne, ponieważ nie obejmuje stanów modyfikatora. Niemniej jednak problem pozostaje, tzn. CTRL + kliknięcie nie jest możliwe.

Wygląda na to, że xbindkeyssam tutaj jest problem, ponieważ rozpoznaje kliknięcie, ale go nie wykonuje. Można to przetestować za pomocą xev | grep buttoni xbindkeys -v:

Zapisane normalne kliknięcie myszy xevpowinno wyglądać następująco:

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

Podobnie jak w przypadku przycisku kciuka:

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

Ale po włączeniu powyższej xbindkeyskonfiguracji nic nie nagrywa. Chociaż ma to sens dla przycisku kciuka, ponieważ jest odwzorowany na CTRL, a zatem nie jest już przyciskiem myszy, dziwne jest, że przycisk 1 również nie jest rejestrowany. Jest to prawdopodobne, ponieważ xbindkeysnie wykonuje go, ale sam je rozpoznaje:

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

Podejście D:

Aktualizacja .xbindkeysrcpliku za pomocą:

"xdotool keydown ctrl"
  b:8

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

"xdotool click 1"
  b:1

Po prostu zbyt proste ... ale prowadzi do nieskończonej pętli kliknięć.


AKTUALIZACJA:

W międzyczasie kupiłem Logitech G502 i zauważyłem, że po skonfigurowaniu za pomocą sterownika w systemie Windows nie tylko sam profil jest przechowywany w pamięci urządzenia, ale faktyczne naciśnięcie klawisza odbywa się za pomocą myszy. To faktycznie rozwiązało mój problem z Linuksem!

Jedyna inna mysz, jaką pamiętam, która była w stanie to zrobić, to Razer Copperhead w tamtych czasach. Sądzę jednak, że dostępne są inne myszy, które mogą zrobić to samo.

conceptdeluxe
źródło
1
oto rozwiązanie wykorzystujące Easystroke
atti

Odpowiedzi:

8

Spędziłem dużo czasu, próbując sprawić, by to wiązanie zadziałało. W końcu znalazłem rozwiązanie, które jest skomplikowane, ale działa dobrze i nie oznacza oprogramowania innych firm. Podzielę się tutaj z nadzieją, że pomoże ludziom. Poza tym wiem, że nie jest to doskonałe pod względem bezpieczeństwa, więc wszelkie konstruktywne opinie są mile widziane.

Istnieją rozwiązania, które są naprawdę miłe, takie jak zaproponowane tutaj , ale zawsze cierpią z powodu ograniczenia klawiszy xbindkeys, które chwytają całą mysz, co powoduje, że modyfikatory + mapowanie kliknięcia myszy są niepewne. Dodatkowo oparte na podstępach rozwiązanie z powyższego linku używa ctrl + plus / ctrl + minus, co na przykład Gimp nie rozpoznaje.

Doszedłem do wniosku, że to, czego chcemy, to przycisk myszy, który działa jak klawiatura, więc użyłem uinput, do którego można uzyskać dostęp przez python , napisałem skrypt monitorujący / dev / my-mouse dla kliknięcia przycisku kciuka i wysłania klawisza Ctrl do wirtualnej klawiatury. Oto szczegółowe kroki:

1. Ustaw zasady udev

Chcemy, aby urządzenia były dostępne (prawa i lokalizacja).

Dla myszy:

/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 wyszuka urządzenie rozpoznawane przez jądro o nazwach takich jak event5, a ja wybieram mysz z tą nazwą. Instrukcja SYMLINK zapewnia, że ​​znajdę moją mysz w / dev / my_mx_mouse. Urządzenie będzie odczytywane przez członka grupy „mxgrabber”.

Aby znaleźć informacje o swoim sprzęcie, powinieneś uruchomić coś takiego

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

Dla wejścia:

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

Nie ma potrzeby tworzenia dowiązania symbolicznego, wejście zawsze będzie w $/dev/uinputlub w $/dev/input/uinputzależności od systemu, w którym się znajdujesz. Po prostu daj mu grupę i prawo do czytania ORAZ pisania oczywiście.

Musisz odłączyć - podłącz mysz, a nowy link powinien pojawić się w / dev. Możesz zmusić udev do uruchomienia reguł$udevadm trigger

2. Aktywuj moduł UINPUT

sudo modprobe uinput

Aby uczynić go odpornym na rozruch:

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

3. Utwórz nową grupę

sudo groupadd mxgrabber

Lub jakkolwiek nazwałeś swoją grupę dostępu. Następnie powinieneś się do tego dodać:

sudo usermod -aG mxgrabber your_login

4. Skrypt Python

Musisz zainstalować bibliotekę python-uinput (oczywiście) i bibliotekę python-evdev . Użyj pipa lub pakietu dystrybucyjnego.

Skrypt jest dość prosty, wystarczy zidentyfikować kod zdarzenia swojego przycisku.

#!/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. Ciesz się!

Wszystko, czego potrzebujesz teraz, to wykonanie pliku python i poproś swojego menedżera pulpitu, aby załadował plik podczas uruchamiania. Może także kieliszek wina z okazji dobrej pracy!

6. Dodatkowe za darmo

Używam xbindkeys do dodatkowego zachowania. Na przykład poniższa konfiguracja może być przydatna, jeśli masz mysz z kliknięciami kół:

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

Aby ta ostatnia kombinacja zadziałała, musisz wyłączyć przycisk skonfigurowany dla skryptu python , w przeciwnym razie nadal będzie on przechwytywany przez xbindkeys. Pozostaje tylko klawisz 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

Załaduj ponownie za pomocą $ xmodmap ~/.Xmodmap

7. Wnioski

Jak powiedziałem na początku, nie jestem całkowicie zadowolony z faktu, że muszę dać sobie prawo do pisania do / dev / uinput, nawet jeśli uważa się to za grupę „mxgrabber”. Jestem pewien, że jest to bezpieczniejszy sposób, ale nie wiem jak.

Z drugiej strony działa naprawdę bardzo dobrze. Każde połączenie klawisza lub klawisza myszy, jak działa z klawiszem Ctrl na klawiaturze, teraz działa z jednym z myszy !!

Aurélien Cibrario
źródło
Bardzo dziękuję za wysiłek i udostępnienie go nam! +1 ... Chociaż jeszcze tego nie przetestowałem. BTW Prawie się
poddałem
Nie ma za co ! Dla mnie działa bezbłędnie. Jeśli masz problemy, daj mi znać. Staram się, aby moja odpowiedź była kompletna, ale ponieważ prawie dwa dni starałem się, aby zadziałała, być może coś zapomniałem. Z przyjemnością pomogę / edytuję mój post.
Aurélien Cibrario
Właśnie zdałem sobie sprawę, że ctrl + kliknięcie 1 było bardzo złym wyborem do zamknięcia karty, ponieważ otwiera ona link w nowej karcie. Zredagowałem swoją odpowiedź, usuwając ostatnią część skryptu python i poprawiając za pomocą xbindkeys, czystsze rozwiązanie
Aurélien Cibrario
chcę tylko poinformować, że nie miałem jeszcze czasu, aby go przetestować - ale na pewno zrobię to zaakceptowaną odpowiedź, jeśli będzie
działać
Zastanawiam się, czy możemy użyć powyższego skryptu, aby ogłosić wadliwy przełącznik myszy. Mam zużytą mysz. Używam skryptu autohotkey, aby naprawić to w systemie Windows, ale nie ma narzędzia do naprawy w systemie Linux. Oto skrypt Autohhotkey dla naprawy lewego przycisku autohotkey.com/board/topic/63555-debounce-mouse-keys Mam nadzieję, że ktoś przeniesie go do Linuksa za pomocą python3 - evdev
kenn
4

Znalazłem rozwiązanie z PyUserInput . W rezultacie jest to dość proste i nie wymaga uprawnień administracyjnych. Po zainstalowaniu Python 2 i PyUserInput użyłem następującego skryptu:

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

Po udzieleniu skryptu praw do wykonywania wywołuję go ~/.xsessionrcna przykład z wejściem liniowym

~ / path / to / script.py &

Uwaga . nie uniemożliwia to uruchomienia zdarzenia przycisku myszy. W moim przypadku xinput set-button-mapzmieniłem mapowanie przycisków xinput i przypisałem numer interesującego mnie przycisku do czegoś, co nie było używane.

Na przykład, jeśli chcesz użyć przycisku 8 na myszy, ale przycisk 8 ma już funkcję (na przykład page-next), możesz użyć następujących.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 &

pod warunkiem przycisk 12niesie żadnego znaczenia dla systemu operacyjnego i przypisać funkcję niestandardowego przycisku 12w .xbuttonmodifier.pyskrypt opisałem powyżej.

Maksyma
źródło
Ale to nie zapobiega uruchomieniu pierwotnego zdarzenia. Jeśli więc zmapuję przycisk 8, aby przesunąć, i przytrzymam przycisk 8 w przeglądarce Firefox, spróbuje również wrócić do poprzedniej strony, co jest niepożądane.
user23013,
1
Prawdziwe. Aby temu zaradzić, zmieniłem identyfikator przycisku, który mnie interesował, na używany przycisk w xinput. Zobacz edytowane pytanie.
Maxim
2

Mam częściowe rozwiązanie. Nie wymyśliłem, jak usunąć mapowanie istniejącego przycisku, więc kończysz kliknięciem przycisku i pożądanym modyfikatorem. Więc jeśli ten przycisk myszy ma jakiś istniejący cel, nadal będzie strzelał. Na przykład ponowne przypisanie prawego przycisku myszy do klawisza sterującego spowoduje wysłanie kontroli + kliknięcia.

W każdym razie znalazłem post na forum podobny do twojego pytania, na który odpowiedzią było zainstalowanie btnx i skonfigurowanie przez to twoich modyfikatorów. Wygląda na to, że btnx nie jest już dostępny w repozytorium. Istnieje ppa, ale nie działa na najnowszym Ubuntu.

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

Ale źródło jest dostępne:

Możesz skompilować go ze źródła, ale spowoduje to umieszczenie w systemie plików, których menedżer pakietów nie będzie w stanie utrzymać.

Mianowicie następujące pliki:

/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

Następujące dowiązania symboliczne:

/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

Więc ... jeśli nie masz nic przeciwko budowaniu ze źródła ...

Uzyskaj zależności dla btnx:

sudo apt-get install libdaemon-dev git

Jeśli nigdy nie budowałeś niczego ze źródła, być może potrzebujesz też niezbędnych do kompilacji:

sudo apt-get install build-essential

Następnie pobierz i skompiluj btnx:

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

Ma osobne narzędzie do konfiguracji GUI. Uzyskaj zależności:

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

Teraz pobierz i skompiluj narzędzie do konfiguracji GUI:

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

Teraz uruchom narzędzie:

sudo btnx-config

Kliknij Wykryj przyciski myszy Jeśli chcesz móc odczytać wskazówki podczas korzystania z narzędzia, zmień rozmiar okna, które się pojawi, tekst okna dialogowego zostanie przycięty później, jeśli tego nie zrobisz, a jeśli spróbujesz zmienić rozmiar podczas wykrywania, anuluje wykrycie. Po prostu powiększ okno.

Kliknij przycisk Naciśnij, aby rozpocząć wykrywanie myszy, a następnie spróbuj nie poruszać myszą, dopóki tekst się nie zmieni ... Zajmie to około 5–10 sekund. Tekst się zmieni. Gdy to zrobisz, zignoruj ​​to, co mówi, i kliknij przycisk Przekaż.

Kliknij przycisk „Naciśnij, aby rozpocząć wykrywanie przycisku”

W tym miejscu klikasz kilka razy przycisk myszy (aż pasek stanu się zapełni). Następnie ustaw nazwę przycisku na coś, co rozpoznasz później (np. LeftButton) Kliknij przycisk Dodaj.

Powtórz to dla każdego przycisku myszy (nie zapomnij o kółkach przewijania, kliknięciach przewijania itp.). Prawdopodobnie możesz pominąć wszystkie przyciski, których nie chcesz ponownie mapować.

Po dodaniu wszystkich przycisków kliknij przycisk OK.

W głównym GUI kliknij przycisk Przyciski, w lewym okienku wybierz przycisk, który chcesz ponownie przypisać. Użyje nazw wprowadzonych w poprzednich krokach. Do swoich celów będziesz chciał wybrać tylko modyfikator klucza w kombinacji klawiszy po prawej stronie.

Nie klikaj przycisku Usuń na tym ekranie, spowoduje to usunięcie przycisku. Jeśli to zrobisz, musisz wrócić i ponownie wykryć przycisk.

Wróć do ekranu Konfiguracje i kliknij ponownie uruchom btnx.

Wypróbuj nowy przycisk.

Jeśli chcesz odinstalować aplikacje, zatrzymaj program btnx, a następnie przejdź do odpowiednich katalogów sprawdzonych przez git i wykonaj odinstalowanie:

sudo /etc/init.d/btnx stop
cd btnx
sudo make uninstall
cd -
cd btnx-config
sudo make uninstall
cd -
Stephen
źródło
2
Bardzo dziękuję za szczegółową odpowiedź, którą zamieściłeś na pastebin. Ale obawiam się, że nie wolno mi używać niezaufanego ppa ani tworzyć aplikacji z nieznanego źródła bez szczegółowego przeglądania jej na moim urządzeniu. Niemniej jednak dam ci głos za wysiłek włożony w to. Poza tym zalecamy zaktualizowanie tutaj odpowiedzi i skopiowanie tego, co tam napisałeś, ponieważ informacje te mogą być pomocne dla innych, ale mogą zostać przeoczone. W końcu przeczytałem, że pakiet może nawet nie skompilować się pod Ubuntu lub Debianem - czy rzeczywiście próbowałeś tego?
conceptdeluxe
Btw: Możesz łatwo zyskać dodatkowe 100 reputacji, łącząc swoje konto askubuntu z innymi kontami Stack Exchange, takimi jak np. Linux i Unix.
conceptdeluxe
Tak, przetestowałem to pod Ubuntu 14.04. Sprawiłem, że prawy przycisk myszy wysłał klawisz kontrolny i potwierdziłem, że zadziałał przed wysłaniem. A potem prawie porzucił stanowisko z powodu wymogu reputacji.
Stephen