rules: remove use of pynput
This commit is contained in:
parent
808a719823
commit
244d48d245
|
@ -30,7 +30,7 @@ in Fedora you need `gtk3` and `python3-gobject`;
|
||||||
if you're using another
|
if you're using another
|
||||||
distribution the required packages are most likely named something similar.
|
distribution the required packages are most likely named something similar.
|
||||||
The Solaar GUI also requires Python packages
|
The Solaar GUI also requires Python packages
|
||||||
`PyYAML` (>= 5.1), `python-xlib` (>= 0.27), `pynput` (>= 1.7.0), and `psutil` (>= 5.7.3).
|
`PyYAML` (>= 5.1), `python-xlib` (>= 0.27), and `psutil` (>= 5.7.3).
|
||||||
These are best installed using `pip` via `pip install --user <package>`
|
These are best installed using `pip` via `pip install --user <package>`
|
||||||
if they are not already available.
|
if they are not already available.
|
||||||
You may have to install the `gcc` and the Python development package (`python3-dev` or `python3-devel`,
|
You may have to install the `gcc` and the Python development package (`python3-dev` or `python3-devel`,
|
||||||
|
|
|
@ -27,8 +27,6 @@ import _thread
|
||||||
import psutil
|
import psutil
|
||||||
import Xlib
|
import Xlib
|
||||||
|
|
||||||
from pynput import keyboard as _keyboard
|
|
||||||
from pynput import mouse as _mouse
|
|
||||||
from Xlib import X
|
from Xlib import X
|
||||||
from Xlib.display import Display
|
from Xlib.display import Display
|
||||||
from Xlib.ext import record
|
from Xlib.ext import record
|
||||||
|
@ -125,9 +123,6 @@ _thread.start_new_thread(display.record_enable_context, (context, key_press_hand
|
||||||
|
|
||||||
# See docs/rules.md for documentation
|
# See docs/rules.md for documentation
|
||||||
|
|
||||||
keyboard = _keyboard.Controller()
|
|
||||||
mouse = _mouse.Controller()
|
|
||||||
|
|
||||||
keys_down = []
|
keys_down = []
|
||||||
key_down = None
|
key_down = None
|
||||||
|
|
||||||
|
@ -157,6 +152,8 @@ TESTS = {
|
||||||
|
|
||||||
COMPONENTS = {}
|
COMPONENTS = {}
|
||||||
|
|
||||||
|
displayt = Display()
|
||||||
|
|
||||||
|
|
||||||
class RuleComponent(object):
|
class RuleComponent(object):
|
||||||
def compile(self, c):
|
def compile(self, c):
|
||||||
|
@ -411,7 +408,7 @@ class KeyPress(Action):
|
||||||
if isinstance(keys, str):
|
if isinstance(keys, str):
|
||||||
keys = [keys]
|
keys = [keys]
|
||||||
self.key_symbols = keys
|
self.key_symbols = keys
|
||||||
key_from_string = lambda s: s if isinstance(s, str) and len(s) == 1 else _keyboard.KeyCode._from_symbol(s)
|
key_from_string = lambda s: displayt.keysym_to_keycode(Xlib.XK.string_to_keysym(s))
|
||||||
self.keys = [isinstance(k, str) and key_from_string(k) for k in keys]
|
self.keys = [isinstance(k, str) and key_from_string(k) for k in keys]
|
||||||
if not all(self.keys):
|
if not all(self.keys):
|
||||||
_log.warn('rule KeyPress argument not sequence of key names %s', keys)
|
_log.warn('rule KeyPress argument not sequence of key names %s', keys)
|
||||||
|
@ -421,30 +418,26 @@ class KeyPress(Action):
|
||||||
return 'KeyPress: ' + ' '.join(self.key_symbols)
|
return 'KeyPress: ' + ' '.join(self.key_symbols)
|
||||||
|
|
||||||
def needed(self, k, current_key_modifiers):
|
def needed(self, k, current_key_modifiers):
|
||||||
code = modifier_code(display.keysym_to_keycode(k.vk if isinstance(k, _keyboard.KeyCode) else k))
|
code = modifier_code(k)
|
||||||
return not (code and current_key_modifiers & (1 << code))
|
return not (code and current_key_modifiers & (1 << code))
|
||||||
|
|
||||||
def keyDown(self, keys, modifiers):
|
def keyDown(self, keys, modifiers):
|
||||||
for k in keys:
|
for k in keys:
|
||||||
if self.needed(k, modifiers):
|
if self.needed(k, modifiers):
|
||||||
keyboard.press(k)
|
Xlib.ext.xtest.fake_input(displayt, X.KeyPress, k)
|
||||||
|
|
||||||
def keyUp(self, keys, modifiers):
|
def keyUp(self, keys, modifiers):
|
||||||
for k in keys:
|
for k in keys:
|
||||||
if self.needed(k, modifiers):
|
if self.needed(k, modifiers):
|
||||||
keyboard.release(k)
|
Xlib.ext.xtest.fake_input(displayt, X.KeyRelease, k)
|
||||||
|
|
||||||
def evaluate(self, feature, notification, device, status, last_result):
|
def evaluate(self, feature, notification, device, status, last_result):
|
||||||
current = current_key_modifiers
|
current = current_key_modifiers
|
||||||
if _log.isEnabledFor(_INFO):
|
if _log.isEnabledFor(_INFO):
|
||||||
_log.info(
|
_log.info('KeyPress action: %s, modifiers %s %s', self.key_symbols, current, [hex(k) for k in self.keys])
|
||||||
'KeyPress action: %s, modifiers %s %s', self.key_symbols, current,
|
|
||||||
[(hex(k.vk) if isinstance(k, _keyboard.KeyCode) else k) for k in self.keys]
|
|
||||||
)
|
|
||||||
self.keyDown(self.keys, current)
|
self.keyDown(self.keys, current)
|
||||||
import time
|
|
||||||
time.sleep(0.1)
|
|
||||||
self.keyUp(reversed(self.keys), current)
|
self.keyUp(reversed(self.keys), current)
|
||||||
|
displayt.sync()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def data(self):
|
def data(self):
|
||||||
|
@ -459,6 +452,25 @@ class KeyPress(Action):
|
||||||
# def evaluate(self, feature, notification, device, status, last_result):
|
# def evaluate(self, feature, notification, device, status, last_result):
|
||||||
# super().keyUp(self.keys, current_key_modifiers)
|
# super().keyUp(self.keys, current_key_modifiers)
|
||||||
|
|
||||||
|
buttons = {
|
||||||
|
'unknown': None,
|
||||||
|
'left': 1,
|
||||||
|
'middle': 2,
|
||||||
|
'right': 3,
|
||||||
|
'scroll_up': 4,
|
||||||
|
'scroll_down': 5,
|
||||||
|
'scroll_left': 6,
|
||||||
|
'scroll_right': 7
|
||||||
|
}
|
||||||
|
for i in range(8, 31):
|
||||||
|
buttons['button%d' % i] = i
|
||||||
|
|
||||||
|
|
||||||
|
def click(button, count):
|
||||||
|
for _ in range(count):
|
||||||
|
Xlib.ext.xtest.fake_input(displayt, Xlib.X.ButtonPress, button)
|
||||||
|
Xlib.ext.xtest.fake_input(displayt, Xlib.X.ButtonRelease, button)
|
||||||
|
|
||||||
|
|
||||||
class MouseScroll(Action):
|
class MouseScroll(Action):
|
||||||
def __init__(self, amounts):
|
def __init__(self, amounts):
|
||||||
|
@ -481,7 +493,12 @@ class MouseScroll(Action):
|
||||||
amounts = [math.floor(last_result * a) for a in self.amounts]
|
amounts = [math.floor(last_result * a) for a in self.amounts]
|
||||||
if _log.isEnabledFor(_INFO):
|
if _log.isEnabledFor(_INFO):
|
||||||
_log.info('MouseScroll action: %s %s %s', self.amounts, last_result, amounts)
|
_log.info('MouseScroll action: %s %s %s', self.amounts, last_result, amounts)
|
||||||
mouse.scroll(*amounts)
|
dx, dy = amounts
|
||||||
|
if dx:
|
||||||
|
click(button=buttons['scroll_right'] if dx > 0 else buttons['scroll_left'], count=abs(dx))
|
||||||
|
if dy:
|
||||||
|
click(button=buttons['scroll_up'] if dy > 0 else buttons['scroll_down'], count=abs(dy))
|
||||||
|
displayt.sync()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def data(self):
|
def data(self):
|
||||||
|
@ -494,11 +511,11 @@ class MouseClick(Action):
|
||||||
args = args[0]
|
args = args[0]
|
||||||
if not isinstance(args, list):
|
if not isinstance(args, list):
|
||||||
args = [args]
|
args = [args]
|
||||||
self.button = str(args[0]) if len(args) >= 0 else 'unknown'
|
self.button = str(args[0]) if len(args) >= 0 else None
|
||||||
if not hasattr(_mouse.Button, self.button):
|
if self.button not in buttons:
|
||||||
_log.warn('rule MouseClick action: button %s not known', self.button)
|
_log.warn('rule MouseClick action: button %s not known', self.button)
|
||||||
self.button = 'unknown'
|
self.button = None
|
||||||
count = args[1] if len(args) >= 1 else 1
|
count = args[1] if len(args) >= 2 else 1
|
||||||
try:
|
try:
|
||||||
self.count = int(count)
|
self.count = int(count)
|
||||||
except ValueError | TypeError:
|
except ValueError | TypeError:
|
||||||
|
@ -511,7 +528,9 @@ class MouseClick(Action):
|
||||||
def evaluate(self, feature, notification, device, status, last_result):
|
def evaluate(self, feature, notification, device, status, last_result):
|
||||||
if _log.isEnabledFor(_INFO):
|
if _log.isEnabledFor(_INFO):
|
||||||
_log.info('MouseClick action: %d %s' % (self.count, self.button))
|
_log.info('MouseClick action: %d %s' % (self.count, self.button))
|
||||||
mouse.click(getattr(_mouse.Button, self.button), self.count)
|
if self.button and self.count:
|
||||||
|
click(buttons[self.button], self.count)
|
||||||
|
displayt.sync()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def data(self):
|
def data(self):
|
||||||
|
|
|
@ -28,9 +28,9 @@ import Xlib.XK
|
||||||
|
|
||||||
from gi.repository import Gdk, GObject, Gtk
|
from gi.repository import Gdk, GObject, Gtk
|
||||||
from logitech_receiver import diversion as _DIV
|
from logitech_receiver import diversion as _DIV
|
||||||
|
from logitech_receiver.diversion import buttons as _buttons
|
||||||
from logitech_receiver.hidpp20 import FEATURE as _ALL_FEATURES
|
from logitech_receiver.hidpp20 import FEATURE as _ALL_FEATURES
|
||||||
from logitech_receiver.special_keys import CONTROL as _CONTROL
|
from logitech_receiver.special_keys import CONTROL as _CONTROL
|
||||||
from pynput import mouse as _mouse
|
|
||||||
from solaar.i18n import _
|
from solaar.i18n import _
|
||||||
|
|
||||||
_log = getLogger(__name__)
|
_log = getLogger(__name__)
|
||||||
|
@ -1218,7 +1218,7 @@ class MouseClickUI(ActionUI):
|
||||||
CLASS = _DIV.MouseClick
|
CLASS = _DIV.MouseClick
|
||||||
MIN_VALUE = 1
|
MIN_VALUE = 1
|
||||||
MAX_VALUE = 9
|
MAX_VALUE = 9
|
||||||
BUTTONS = [b for b in dir(_mouse.Button) if not b.startswith('__')]
|
BUTTONS = list(_buttons.keys())
|
||||||
|
|
||||||
def create_widgets(self):
|
def create_widgets(self):
|
||||||
self.widgets = {}
|
self.widgets = {}
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -63,7 +63,6 @@ battery status, and show and modify some of the modifiable features of devices.
|
||||||
'pyudev (>= 0.13)',
|
'pyudev (>= 0.13)',
|
||||||
'PyYAML (>= 5.1)',
|
'PyYAML (>= 5.1)',
|
||||||
'python-xlib (>= 0.27)',
|
'python-xlib (>= 0.27)',
|
||||||
'pynput (>= 1.7.0)',
|
|
||||||
'psutil (>= 5.7.3)',
|
'psutil (>= 5.7.3)',
|
||||||
],
|
],
|
||||||
package_dir={'': 'lib'},
|
package_dir={'': 'lib'},
|
||||||
|
|
Loading…
Reference in New Issue