settings: add setting for DPI CHANGE button to switch Sensitivity
This commit is contained in:
parent
2de79141e4
commit
14c1eac79c
|
@ -23,6 +23,7 @@ import math
|
||||||
|
|
||||||
from copy import copy as _copy
|
from copy import copy as _copy
|
||||||
from logging import DEBUG as _DEBUG
|
from logging import DEBUG as _DEBUG
|
||||||
|
from logging import WARNING as _WARNING
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
## use regular time instead of time_ns so as not to require Python 3.7
|
## use regular time instead of time_ns so as not to require Python 3.7
|
||||||
# from time import time_ns as _time_ns
|
# from time import time_ns as _time_ns
|
||||||
|
@ -1048,6 +1049,72 @@ class MultipleRangeValidator:
|
||||||
return w + b'\xFF'
|
return w + b'\xFF'
|
||||||
|
|
||||||
|
|
||||||
|
class ActionSettingRW(object):
|
||||||
|
"""Special RW class for settings that turn on and off special processing when a key or button is depressed"""
|
||||||
|
def __init__(self, name, divert_setting_name):
|
||||||
|
self.name = name
|
||||||
|
self.divert_setting_name = divert_setting_name
|
||||||
|
self.kind = FeatureRW.kind # pretend to be FeatureRW as required for HID++ 2.0 devices
|
||||||
|
self.device = None
|
||||||
|
self.key = None
|
||||||
|
self.active = False
|
||||||
|
self.pressed = False
|
||||||
|
|
||||||
|
def press_action(self): # action to take when key is pressed
|
||||||
|
pass
|
||||||
|
|
||||||
|
def release_action(self): # action to take when key is released
|
||||||
|
pass
|
||||||
|
|
||||||
|
def move_action(self, dx, dy): # action to take when mouse is moved while key is down
|
||||||
|
pass
|
||||||
|
|
||||||
|
def read(self, device): # need to return bytes, as if read from device
|
||||||
|
return _int2bytes(self.key, 2) if self.active else b'\x00\x00'
|
||||||
|
|
||||||
|
def write(self, device, data_bytes):
|
||||||
|
def handler(device, n): # Called on notification events from the device
|
||||||
|
if n.sub_id < 0x40 and device.features[n.sub_id] == _hidpp20.FEATURE.REPROG_CONTROLS_V4:
|
||||||
|
if n.address == 0x00:
|
||||||
|
cids = _unpack('!HHHH', n.data[:8])
|
||||||
|
if not self.pressed and int(self.key.key) in cids:
|
||||||
|
self.pressed = True
|
||||||
|
self.press_action()
|
||||||
|
elif self.pressed and int(self.key.key) not in cids:
|
||||||
|
self.pressed = False
|
||||||
|
self.release_action()
|
||||||
|
elif n.address == 0x10:
|
||||||
|
if self.pressed:
|
||||||
|
dx, dy = _unpack('!hh', n.data[:4])
|
||||||
|
self.move_action(dx, dy)
|
||||||
|
|
||||||
|
divertSetting = next(filter(lambda s: s.name == self.divert_setting_name, device.settings), None)
|
||||||
|
self.device = device
|
||||||
|
key = _bytes2int(data_bytes)
|
||||||
|
if key: # Enable
|
||||||
|
self.key = next((k for k in device.keys if k.key == key), None)
|
||||||
|
if self.key:
|
||||||
|
self.active = True
|
||||||
|
divertSetting.write_key_value(int(self.key.key), 1)
|
||||||
|
device.add_notification_handler(self.name, handler)
|
||||||
|
from solaar.ui import status_changed as _status_changed
|
||||||
|
_status_changed(device, refresh=True) # update main window
|
||||||
|
else:
|
||||||
|
_log.error('cannot enable %s on %s for key %s', self.name, device, key)
|
||||||
|
else: # Disable
|
||||||
|
if self.active:
|
||||||
|
self.active = False
|
||||||
|
divertSetting.write_key_value(int(self.key.key), 0)
|
||||||
|
from solaar.ui import status_changed as _status_changed
|
||||||
|
_status_changed(device, refresh=True) # update main window
|
||||||
|
try:
|
||||||
|
device.remove_notification_handler(self.name)
|
||||||
|
except Exception:
|
||||||
|
if _log.isEnabledFor(_WARNING):
|
||||||
|
_log.warn('cannot disable %s on %s', self.name, device)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
# Turn diverted mouse movement events into a mouse gesture
|
# Turn diverted mouse movement events into a mouse gesture
|
||||||
#
|
#
|
||||||
# Uses the following FSM.
|
# Uses the following FSM.
|
||||||
|
|
|
@ -35,6 +35,7 @@ from .common import bytes2int as _bytes2int
|
||||||
from .common import int2bytes as _int2bytes
|
from .common import int2bytes as _int2bytes
|
||||||
from .common import unpack as _unpack
|
from .common import unpack as _unpack
|
||||||
from .i18n import _
|
from .i18n import _
|
||||||
|
from .settings import ActionSettingRW as _ActionSettingRW
|
||||||
from .settings import BitFieldSetting as _BitFieldSetting
|
from .settings import BitFieldSetting as _BitFieldSetting
|
||||||
from .settings import BitFieldValidator as _BitFieldV
|
from .settings import BitFieldValidator as _BitFieldV
|
||||||
from .settings import BitFieldWithOffsetAndMaskSetting as _BitFieldOMSetting
|
from .settings import BitFieldWithOffsetAndMaskSetting as _BitFieldOMSetting
|
||||||
|
@ -118,6 +119,9 @@ _DIVERT_CROWN = ('divert-crown', _('Divert crown events'),
|
||||||
_('Make crown send CROWN HID++ notifications (which trigger Solaar rules but are otherwise ignored).'))
|
_('Make crown send CROWN HID++ notifications (which trigger Solaar rules but are otherwise ignored).'))
|
||||||
_DIVERT_GKEYS = ('divert-gkeys', _('Divert G Keys'),
|
_DIVERT_GKEYS = ('divert-gkeys', _('Divert G Keys'),
|
||||||
_('Make G keys send GKEY HID++ notifications (which trigger Solaar rules but are otherwise ignored).'))
|
_('Make G keys send GKEY HID++ notifications (which trigger Solaar rules but are otherwise ignored).'))
|
||||||
|
_SPEED_CHANGE = ('speed-change', _('Sensitivity Switching'),
|
||||||
|
_('Switch the current sensitivity and the remembered sensitivity when the key or button is pressed.\n'
|
||||||
|
'If there is no remembered sensitivity, just remember the current sensitivity'))
|
||||||
|
|
||||||
_GESTURE2_GESTURES_LABELS = {
|
_GESTURE2_GESTURES_LABELS = {
|
||||||
_GG['Tap1Finger']: (_('Single tap'), _('Performs a left click.')),
|
_GG['Tap1Finger']: (_('Single tap'), _('Performs a left click.')),
|
||||||
|
@ -524,6 +528,38 @@ def _feature_dpi_sliding():
|
||||||
return _Setting(_DPI_SLIDING, _DpiSlidingRW(), callback=_feature_dpi_sliding_callback, device_kind=(_DK.mouse, ))
|
return _Setting(_DPI_SLIDING, _DpiSlidingRW(), callback=_feature_dpi_sliding_callback, device_kind=(_DK.mouse, ))
|
||||||
|
|
||||||
|
|
||||||
|
def _feature_speed_change():
|
||||||
|
"""Implements the ability to switch Sensitivity by clicking on the DPI_Change button."""
|
||||||
|
class _SpeedChangeRW(_ActionSettingRW):
|
||||||
|
def press_action(self): # switch sensitivity
|
||||||
|
currentSpeed = self.device.persister.get('pointer_speed', None) if self.device.persister else None
|
||||||
|
newSpeed = self.device.persister.get('_speed-change', None) if self.device.persister else None
|
||||||
|
speed_setting = next(filter(lambda s: s.name == _POINTER_SPEED[0], self.device.settings), None)
|
||||||
|
if newSpeed is not None:
|
||||||
|
if speed_setting:
|
||||||
|
speed_setting.write(newSpeed)
|
||||||
|
else:
|
||||||
|
_log.error('cannot save sensitivity setting on %s', self.device)
|
||||||
|
from solaar.ui import status_changed as _status_changed
|
||||||
|
_status_changed(self.device, refresh=True) # update main window
|
||||||
|
if self.device.persister:
|
||||||
|
self.device.persister['_speed-change'] = currentSpeed
|
||||||
|
|
||||||
|
def callback(device):
|
||||||
|
key_index = device.keys.index(_special_keys.CONTROL.DPI_Change)
|
||||||
|
key = device.keys[key_index] if key_index is not None else None
|
||||||
|
if key is not None and 'divertable' in key.flags:
|
||||||
|
keys = [_NamedInt(0, _('Off')), key.key]
|
||||||
|
return _ChoicesV(_NamedInts.list(keys), byte_count=2)
|
||||||
|
|
||||||
|
return _Setting(
|
||||||
|
_SPEED_CHANGE,
|
||||||
|
_SpeedChangeRW('speed change', _DIVERT_KEYS[0]),
|
||||||
|
callback=callback,
|
||||||
|
device_kind=(_DK.mouse, _DK.trackball)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _feature_adjustable_dpi_callback(device):
|
def _feature_adjustable_dpi_callback(device):
|
||||||
# [1] getSensorDpiList(sensorIdx)
|
# [1] getSensorDpiList(sensorIdx)
|
||||||
reply = device.feature_request(_F.ADJUSTABLE_DPI, 0x10)
|
reply = device.feature_request(_F.ADJUSTABLE_DPI, 0x10)
|
||||||
|
@ -852,6 +888,7 @@ _SETTINGS_TABLE = [
|
||||||
_S(_DPI_SLIDING, _F.REPROG_CONTROLS_V4, _feature_dpi_sliding),
|
_S(_DPI_SLIDING, _F.REPROG_CONTROLS_V4, _feature_dpi_sliding),
|
||||||
_S(_MOUSE_GESTURES, _F.REPROG_CONTROLS_V4, _feature_mouse_gesture),
|
_S(_MOUSE_GESTURES, _F.REPROG_CONTROLS_V4, _feature_mouse_gesture),
|
||||||
_S(_POINTER_SPEED, _F.POINTER_SPEED, _feature_pointer_speed),
|
_S(_POINTER_SPEED, _F.POINTER_SPEED, _feature_pointer_speed),
|
||||||
|
_S(_SPEED_CHANGE, _F.POINTER_SPEED, _feature_speed_change),
|
||||||
_S(_BACKLIGHT, _F.BACKLIGHT2, _feature_backlight2),
|
_S(_BACKLIGHT, _F.BACKLIGHT2, _feature_backlight2),
|
||||||
_S(_FN_SWAP, _F.FN_INVERSION, _feature_fn_swap, registerFn=_register_fn_swap),
|
_S(_FN_SWAP, _F.FN_INVERSION, _feature_fn_swap, registerFn=_register_fn_swap),
|
||||||
_S(_FN_SWAP, _F.NEW_FN_INVERSION, _feature_new_fn_swap, identifier='new_fn_swap'),
|
_S(_FN_SWAP, _F.NEW_FN_INVERSION, _feature_new_fn_swap, identifier='new_fn_swap'),
|
||||||
|
|
Loading…
Reference in New Issue