Как отобразить модификаторы (например, CTRL) на кнопки большого пальца мыши, используя xbindkeys

13

Этот вопрос уже был задан, но так и не получил правильного ответа. После очистки с @Seth я теперь спрашиваю это снова. Это позволит мне ответить и, возможно, изменить вопрос намного проще. Оригинальный вопрос можно найти здесь:

Привязать Ctrl и Alt к кнопкам большого пальца мыши


Выпуск:

Хотя очень просто сопоставить любые нажатия клавиш с кнопкой мыши, используя их xbindkeysвместе xdotoolили xteкажется намного более проблематичным сопоставить клавишу-модификатор (например, ALT , CTRL , SHIFT и т. Д.) С ней.

Окончательный soloution должен позволять И.А. CTRL + щелчок (например , для выбора нескольких записей из списка) только с помощью мыши.

Несколько возможных подходов к решению этой проблемы можно найти здесь, на Stack Exchange, а также на других форумах, связанных с Linux. Но ни одна из этих работ не работает так, как ожидается, поскольку они приводят к другим проблемам и побочным эффектам.

Примечания:

В некоторых из приведенных ниже примеров используется синтаксис Guile with Scheme и .xbindkeysrc.scmфайл, в то время как другие полагаются на .xbindkeysrcфайл с соответствующим синтаксисом. Я знаю, что они не будут работать вместе.

Кроме того, приведенные ниже фрагменты основаны xdotoolтолько на том, но я открыт для подходов, связанных с другими приложениями, такими как, например, xteтакже - хотя, похоже, оба приводят к одним и тем же результатам, и поэтому я использую только xdotoolдействия здесь.

Подход А:

Обновление .xbindkeysrcфайла с помощью:

"xdotool keydown ctrl"
  b:8

"xdotool keyup ctrl"
  release + b:8

Это то, что я сначала попробовал, но у него есть побочный эффект, что модификатор удерживается и не может быть освобожден.

Подход Б:

Обновление .xbindkeysrc.scmфайла с помощью:

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

Находится по адресу http://www.linuxforums.org/forum/hardware-peripherals/169773-solved-map-mouse-button-modifier-key.html и пытается решить проблему, где хранится модификатор (как описано в подходе а).

Хотя это исправляет, что это работает только частично, поскольку невозможно выполнить другие щелчки мыши, пока нажата кнопка большого пальца.

Подход C:

Обновление .xbindkeysrcфайла с помощью:

"xdotool keydown ctrl"
  b:8

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

Опробовано OP связанного вопроса здесь, в askubuntu. Намного проще и надежнее, так как в нем нет состояний модификаторов. Тем не менее, вопрос остается, т.е. CTRL + щелчок не представляется возможным.

Кажется, что xbindkeysздесь проблема заключается в том, что он распознает щелчок, но не выполняет его. Это можно проверить с помощью xev | grep buttonи xbindkeys -v:

Обычный щелчок мыши, записанный пользователем, xevдолжен выглядеть следующим образом:

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

Как и для кнопки большого пальца:

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

Но при xbindkeysвключенной выше конфигурации он ничего не записывает. Хотя это имеет смысл для кнопки большого пальца, поскольку она отображается на CTRL и, следовательно, больше не является кнопкой мыши, странно, что кнопка 1 также не записывается. Это вероятно потому, xbindkeysчто не выполняет его, но само распознает:

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

Подход D:

Обновление .xbindkeysrcфайла с помощью:

"xdotool keydown ctrl"
  b:8

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

"xdotool click 1"
  b:1

Просто слишком просто ... но приводит к бесконечному циклу кликов.


ОБНОВИТЬ:

Тем временем я купил Logitech G502 и заметил, что однажды настроенный через драйвер в Windows не только сам профиль сохраняется в памяти устройства, но и фактическое нажатие клавиши осуществляется мышью. Это фактически решило мою проблему в Linux!

Единственная другая мышь, которую я помню, которая была способна сделать это, была Razer Copperhead в те времена. Но я думаю, сегодня есть и другие мыши, которые могут сделать то же самое.

conceptdeluxe
источник
1
Вот решение, использующее Easystroke: askubuntu.com/a/1010647/27202
atti

Ответы:

8

Я потратил много времени, пытаясь заставить эту обязательную работу работать. В конце концов я нашел решение, которое является сложным, но работает хорошо и не подразумевает стороннего программного обеспечения. Я делюсь этим здесь, надеясь, что это поможет людям. Кроме того, я знаю, что это не идеально с точки зрения безопасности, поэтому любая конструктивная обратная связь приветствуется.

Есть решения, которые действительно хороши, такие как предложенные здесь , но они всегда страдают от ограничений xbindkeys, которые захватывают всю мышь, делая неопределенными модификаторы + отображение щелчка мыши. Кроме того, решение на основе guile из вышеуказанной ссылки использует ctrl + plus / ctrl + minus, который, например, не распознается Gimp.

Я понял, что нам нужна кнопка мыши, которая действует как клавиатура, поэтому я использовал uinput, к которому можно получить доступ через python , написал скрипт, который отслеживает / dev / my-mouse для нажатия кнопки большого пальца и посылает клавишу ctrl на виртуальную клавиатуру. Вот подробные шаги:

1. Сделать правила Udev

Мы хотим, чтобы устройства были доступны (права и местоположение).

Для мыши:

/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 будет искать устройство, распознаваемое ядром, с такими именами, как event5, и я выбираю мышь с именем. Инструкция SYMLINK гарантирует, что я найду свою мышь в / dev / my_mx_mouse. Устройство будет доступно для чтения участнику группы «mxgrabber».

Чтобы найти информацию о вашем оборудовании, вы должны запустить что-то вроде

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

Для ввода:

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

Нет необходимости в символической ссылке, uinput всегда будет в $/dev/uinputили$/dev/input/uinput в зависимости от системы вы находитесь. Просто дайте ему группу и права читать и писать, конечно.

Вам нужно отключить - подключите мышь, и новая ссылка должна появиться в / dev. Вы можете заставить udev запускать ваши правила с помощью$udevadm trigger

2. Активируйте модуль UINPUT

sudo modprobe uinput

И сделать его загрузочным постоянным:

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

3. Создать новую группу

sudo groupadd mxgrabber

Или как вы называли свою группу доступа. Тогда вы должны добавить себя к этому:

sudo usermod -aG mxgrabber your_login

4. Python скрипт

Вам необходимо установить библиотеку python-uinput (очевидно) и библиотеку python-evdev . Используйте pip или ваш дистрибутив.

Сценарий довольно прост, вам просто нужно идентифицировать event.code вашей кнопки.

#!/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. Наслаждайтесь!

Все, что вам сейчас нужно, это сделать исполняемый файл Python и попросить менеджера рабочего стола загрузить файл при запуске. Возможно также стакан вина, чтобы праздновать хорошую работу!

6. Дополнительно бесплатно

Я использую xbindkeys для дополнительного поведения. Например, следующая конфигурация может быть полезна, если у вас есть мышь с щелчками по колесу:

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

Чтобы эта последняя комбинация работала, вы должны отключить кнопку, которую вы настроили для скрипта python , иначе она все равно будет захвачена xbindkeys. Должна остаться только клавиша 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

Перезагрузить с $ xmodmap ~/.Xmodmap

7. Заключение

Как я уже говорил в начале, я не совсем доволен тем, что мне нужно дать себе права писать в / dev / uinput, даже если это группа mxgrabber. Я уверен, что есть более безопасный способ сделать это, но я не знаю как.

С другой стороны, это работает очень, очень хорошо. Любая комбинация клавиатуры или клавиши мыши, которая работает с клавишей Ctrl на клавиатуре, теперь работает с мышью !!

Орелиен Сибрарио
источник
Большое спасибо за усилия и поделиться ими с нами! +1 ... хотя я еще не проверял. Кстати, я почти отказался от этого - было бы здорово, если бы это
работало,
Пожалуйста ! Для меня это работает без нареканий. Если у вас есть проблемы, дайте мне знать. Я пытаюсь завершить свой ответ, но поскольку я потратил почти два дня, пытаясь заставить его работать, возможно, я кое-что забыл. Будем рады помочь / отредактировать мой пост.
Орелиен Сибрарио
Я только что понял, что ctrl + click1 - очень плохой выбор, чтобы закрыть вкладку, так как она открывает ссылку в новой вкладке. Я отредактировал свой ответ, удалив последнюю часть скрипта Python и настроив его с помощью xbindkeys, более чистого решения
Aurélien Cibrario
просто хочу сообщить, что у меня еще не было времени проверить его - но я обязательно сделаю его приемлемым ответом, если он будет работать, как ожидалось - извините за ожидание - я немного занят
conceptdeluxe
Интересно, можем ли мы использовать приведенный выше скрипт, чтобы отменить неисправный переключатель мыши. У меня есть изношенная мышь. Я использую скрипт autohotkey, чтобы исправить это в Windows, но в Linux нет инструмента, чтобы исправить это. Вот скрипт Autohhotkey для исправления левой кнопки autohotkey.com/board/topic/63555-debounce-mouse-keys Я надеюсь, что кто-нибудь перенесет его на Linux, используя python3 - evdev
kenn
4

Я нашел решение с помощью PyUserInput . Это оказывается довольно простым и не требует прав администратора. С установленным Python 2 и PyUserInput я использовал следующий скрипт:

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

После предоставления прав на выполнение скрипта, я вызываю его ~/.xsessionrc, например, в строке

~ / path / to / script.py &

Примечание . это не предотвращает срабатывание события кнопки мыши. В моем случае я xinput set-button-mapменял отображение кнопок xinput и назначал номер интересующей меня кнопки тому, что не использовалось.

Например, если вы хотите использовать кнопку 8 на вашей мыши, но кнопка 8 уже имеет функцию (например, page-next), вы можете использовать следующее.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 &

предоставленная кнопка не 12имеет никакого значения для ОС, и назначьте пользовательскую функцию кнопке 12в .xbuttonmodifier.pyсценарии, который я описал выше.

Максим
источник
Но это не мешает исходному событию сработать. Поэтому, если я сопоставлю кнопку 8 со сдвигом и удержу кнопку 8 в Firefox, он также попытается вернуться на предыдущую страницу, что нежелательно.
user23013
1
Правда. Чтобы справиться с этим, я использовал измененный идентификатор интересующей меня кнопки на используемую кнопку xinput. Смотрите отредактированный вопрос.
Максим
2

У меня есть частичное решение. Я не понял, как отменить отображение существующей кнопки, так что в итоге вы нажимаете кнопку и выбираете нужный вам модификатор. Так что, если эта кнопка мыши имеет какое-то существующее назначение, она все равно будет срабатывать. Например, переназначение правой кнопки мыши на управляющую клавишу приведет к отправке управляющего + щелчка.

Во всяком случае, я нашел сообщение на форуме, похожее на ваш вопрос, ответ на который должен был установить btnx и настроить ваши модификаторы через него. Похоже, btnx больше не доступен через репо. Существует ppa, но он не работает для последней версии Ubuntu.

Сообщение на форуме: post: http://ubuntuforums.org/showthread.php?t=1245930

Но источник доступен:

Вы можете скомпилировать его из исходного кода, но это поместит в вашу систему файлы, которые менеджер пакетов не сможет поддерживать.

А именно следующие файлы:

/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

Следующие символические ссылки:

/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

Так что ... если вы не возражаете против строительства из источника ...

Получите зависимости для btnx:

sudo apt-get install libdaemon-dev git

Если вы никогда не создавали ничего из исходного кода, вам также может понадобиться build-essential:

sudo apt-get install build-essential

Затем получите и скомпилируйте btnx:

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

У этого есть отдельный инструмент конфигурации GUI. Получить зависимости для этого:

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

Теперь получите и скомпилируйте инструмент конфигурации GUI:

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

Теперь запустите инструмент:

sudo btnx-config

Нажмите на кнопку «Определить мышь». Если вы хотите иметь возможность читать указания во время использования инструмента, измените размер всплывающего окна, текст диалога будет вырезан позже, если вы этого не сделаете, и если вы попытаетесь изменить размер во время обнаружения, он отменит обнаружение. Просто сделайте окно немного больше.

Нажмите на «Нажмите», чтобы начать обнаружение мыши, затем попытайтесь не перемещать мышь, пока текст не изменится ... Занимает около 5-10 секунд. Текст изменится. Когда это произойдет, проигнорируйте сказанное и нажмите «Вперед».

Нажмите кнопку «Нажмите, чтобы начать обнаружение кнопки»

Здесь вы будете нажимать одну кнопку мыши несколько раз (пока строка состояния не заполнится). Затем установите имя кнопки на то, что вы узнаете позже (например, LeftButton). Нажмите кнопку Добавить.

Повторите это для каждой кнопки мыши (не забывайте колесико прокрутки, щелчки прокрутки и т. Д.). Вы можете пропустить любые кнопки, которые вы не хотите переназначать.

Когда вы добавили все кнопки, нажмите кнопку ОК.

В главном графическом интерфейсе нажмите кнопку «Кнопки», на левой панели выберите кнопку, которую хотите переназначить. Он будет использовать имена, которые вы ввели в предыдущих шагах. Для ваших целей вы можете выбрать только модификатор Key под комбинацией клавиш справа.

Не нажимайте кнопку «Удалить» на этом экране, она удалит кнопку. Вам придется вернуться и снова обнаружить кнопку, если вы это сделаете.

Вернитесь к экрану Conrigurations и нажмите перезагрузить btnx.

Попробуйте новую кнопку.

Если вы хотите удалить приложения, остановите программу btnx, а затем перейдите в соответствующие каталоги git check out и выполните удаление:

sudo /etc/init.d/btnx stop
cd btnx
sudo make uninstall
cd -
cd btnx-config
sudo make uninstall
cd -
Стивен
источник
2
Большое спасибо за подробный ответ, который вы разместили на pastebin. Но я боюсь, что мне не разрешают использовать ненадежный ppa или создавать приложение из неизвестного источника, не просматривая его подробно на моем устройстве. Тем не менее, я проголосую за ваши усилия. Кроме того, я рекомендую вам обновить свой ответ здесь и скопировать то, что вы там написали, так как эта информация может быть полезна для других, но может быть упущена. Наконец я прочитал, что пакет может даже не скомпилироваться под Ubuntu или Debian - вы пробовали это на самом деле?
conceptdeluxe
Кстати: вы можете легко получить дополнительные 100 репутации, связав свою учетную запись askubuntu с другими учетными записями Stack Exchange, например, Linux и Unix.
conceptdeluxe
Да, я тестировал его под Ubuntu 14.04. Я заставил правую кнопку мыши отправить управляющую клавишу и подтвердил, что она работает, перед публикацией. А потом почти отказался от поста из-за требования к репутации.
Стивен