settings: dpi sliding looks for suitable key
This commit is contained in:
parent
90bae7db84
commit
3969472dd3
|
@ -364,26 +364,19 @@ def _feature_smart_shift_enhanced():
|
||||||
def _feature_dpi_sliding():
|
def _feature_dpi_sliding():
|
||||||
"""Implements the ability to smoothly modify the DPI
|
"""Implements the ability to smoothly modify the DPI
|
||||||
by sliding a mouse horizontally while holding the DPI button."""
|
by sliding a mouse horizontally while holding the DPI button."""
|
||||||
def _feature_dpi_sliding_callback(device):
|
|
||||||
# need _F.REPROG_CONTROLS_V4 feature and a DPI Switch that can send raw XY
|
|
||||||
# and _F.ADJUSTABLE_DPI so that the DPI can be adjusted
|
|
||||||
if _F.ADJUSTABLE_DPI in device.features:
|
|
||||||
key_index = device.keys.index(_special_keys.CONTROL.DPI_Switch)
|
|
||||||
if key_index is not None and 'raw XY' in device.keys[key_index].flags:
|
|
||||||
return _BooleanV()
|
|
||||||
|
|
||||||
class _DpiSlidingRW(object):
|
class _DpiSlidingRW(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.kind = _FeatureRW.kind # pretend to be FeatureRW as required for HID++ 2.0 devices
|
self.kind = _FeatureRW.kind # pretend to be FeatureRW as required for HID++ 2.0 devices
|
||||||
|
self.key = None
|
||||||
def read(self, device): # need to return bytes, not a boolean
|
|
||||||
return b'0x01' if '_slidingDpiState' in device.__dict__ else b'0x00'
|
|
||||||
|
|
||||||
class MxVerticalDpiState(object):
|
class MxVerticalDpiState(object):
|
||||||
__slots__ = ('device', 'pressedCids', 'dpiSetting', 'dpiChoices', 'fsmState', 'otherDpiIdx', 'dx', 'movingDpiIdx')
|
__slots__ = (
|
||||||
|
'key', 'device', 'pressedCids', 'dpiSetting', 'dpiChoices', 'fsmState', 'otherDpiIdx', 'dx', 'movingDpiIdx'
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, device, dpiSetting):
|
def __init__(self, device, dpiSetting, key):
|
||||||
self.device = device
|
self.device = device
|
||||||
|
self.key = key
|
||||||
self.dpiSetting = dpiSetting
|
self.dpiSetting = dpiSetting
|
||||||
self.dpiChoices = list(self.dpiSetting.choices)
|
self.dpiChoices = list(self.dpiSetting.choices)
|
||||||
# Currently pressed/held control IDs
|
# Currently pressed/held control IDs
|
||||||
|
@ -407,17 +400,6 @@ def _feature_dpi_sliding():
|
||||||
we go into the `moved` state.
|
we go into the `moved` state.
|
||||||
When the button is released in this state
|
When the button is released in this state
|
||||||
the DPI is set according to the total displacement.
|
the DPI is set according to the total displacement.
|
||||||
|
|
||||||
release
|
|
||||||
+---------------------------------------------+
|
|
||||||
|set DPI in current slot |
|
|
||||||
v moved |
|
|
||||||
+------+ press +---------+ enough +-------+ |
|
|
||||||
| idle |------>| pressed |------->| moved |------+
|
|
||||||
+------+ +---------+ +-------+
|
|
||||||
^ release | ^ ^
|
|
||||||
+----------------+ accumulate
|
|
||||||
switch DPI slots displacement
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def setNewDpi(self, newDpiIdx):
|
def setNewDpi(self, newDpiIdx):
|
||||||
|
@ -436,11 +418,11 @@ def _feature_dpi_sliding():
|
||||||
|
|
||||||
def handle_keys_event(self, cids):
|
def handle_keys_event(self, cids):
|
||||||
if self.fsmState == 'idle':
|
if self.fsmState == 'idle':
|
||||||
if _special_keys.CONTROL.DPI_Switch in cids:
|
if self.key in cids:
|
||||||
self.fsmState = 'pressed'
|
self.fsmState = 'pressed'
|
||||||
self.dx = 0.
|
self.dx = 0.
|
||||||
elif self.fsmState == 'pressed':
|
elif self.fsmState == 'pressed':
|
||||||
if _special_keys.CONTROL.DPI_Switch not in cids:
|
if self.key not in cids:
|
||||||
# Swap with other DPI
|
# Swap with other DPI
|
||||||
thisIdx = self.dpiChoices.index(self.dpiSetting.read())
|
thisIdx = self.dpiChoices.index(self.dpiSetting.read())
|
||||||
newDpiIdx, self.otherDpiIdx = self.otherDpiIdx, thisIdx
|
newDpiIdx, self.otherDpiIdx = self.otherDpiIdx, thisIdx
|
||||||
|
@ -450,7 +432,7 @@ def _feature_dpi_sliding():
|
||||||
self.fsmState = 'idle'
|
self.fsmState = 'idle'
|
||||||
self.displayNewDpi(newDpiIdx)
|
self.displayNewDpi(newDpiIdx)
|
||||||
elif self.fsmState == 'moved':
|
elif self.fsmState == 'moved':
|
||||||
if _special_keys.CONTROL.DPI_Switch not in cids:
|
if self.key not in cids:
|
||||||
self.setNewDpi(self.movingDpiIdx)
|
self.setNewDpi(self.movingDpiIdx)
|
||||||
self.fsmState = 'idle'
|
self.fsmState = 'idle'
|
||||||
|
|
||||||
|
@ -471,6 +453,9 @@ def _feature_dpi_sliding():
|
||||||
self.movingDpiIdx = newMovingDpiIdx
|
self.movingDpiIdx = newMovingDpiIdx
|
||||||
self.displayNewDpi(newMovingDpiIdx)
|
self.displayNewDpi(newMovingDpiIdx)
|
||||||
|
|
||||||
|
def read(self, device): # need to return bytes, as if read from device
|
||||||
|
return _int2bytes(device._slidingDpiState.key, 2) if '_slidingDpiState' in device.__dict__ else b'\x00\x00'
|
||||||
|
|
||||||
def write(self, device, data_bytes):
|
def write(self, device, data_bytes):
|
||||||
def handler(device, n):
|
def handler(device, n):
|
||||||
"""Called on notification events from the mouse."""
|
"""Called on notification events from the mouse."""
|
||||||
|
@ -483,29 +468,59 @@ def _feature_dpi_sliding():
|
||||||
dx, dy = _unpack('!hh', n.data[:4])
|
dx, dy = _unpack('!hh', n.data[:4])
|
||||||
state.handle_move_event(dx, dy)
|
state.handle_move_event(dx, dy)
|
||||||
|
|
||||||
if bool(data_bytes): # Enable DPI sliding
|
key = _bytes2int(data_bytes)
|
||||||
|
if key: # Enable DPI sliding
|
||||||
# Enable HID++ events on sliding the mouse while DPI button held
|
# Enable HID++ events on sliding the mouse while DPI button held
|
||||||
dpiSetting = next(filter(lambda s: s.name == _DPI[0], device.settings), None)
|
self.key = next((k for k in device.keys if k.key == key), None)
|
||||||
DPI_key_index = device.keys.index(_special_keys.CONTROL.DPI_Switch)
|
if self.key:
|
||||||
DPI_key = device.keys[DPI_key_index] if DPI_key_index is not None else None
|
self.key.set_rawXY_reporting(True)
|
||||||
if dpiSetting and DPI_key and 'raw XY' in DPI_key.flags:
|
divertSetting = next(filter(lambda s: s.name == _DIVERT_KEYS[0], device.settings), None)
|
||||||
DPI_key.set_rawXY_reporting(True)
|
divertSetting.write_key_value(int(self.key.key), 1)
|
||||||
|
from solaar.ui import status_changed as _status_changed
|
||||||
|
_status_changed(device, refresh=True) # update main window
|
||||||
# Store our variables in the device object
|
# Store our variables in the device object
|
||||||
device._slidingDpiState = self.MxVerticalDpiState(device, dpiSetting)
|
dpiSetting = next(filter(lambda s: s.name == _DPI[0], device.settings), None)
|
||||||
|
device._slidingDpiState = self.MxVerticalDpiState(device, dpiSetting, self.key.key)
|
||||||
device.add_notification_handler('mx-vertical-dpi-handler', handler)
|
device.add_notification_handler('mx-vertical-dpi-handler', handler)
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
_log.error('cannot enable DPI sliding on %s', device)
|
_log.error('cannot enable DPI sliding on %s for key %s', device, key)
|
||||||
else: # Disable DPI sliding
|
else: # Disable DPI sliding
|
||||||
|
if self.key:
|
||||||
|
self.key.set_rawXY_reporting(False)
|
||||||
|
divertSetting = next(filter(lambda s: s.name == _DIVERT_KEYS[0], device.settings), None)
|
||||||
|
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:
|
try:
|
||||||
device.remove_notification_handler('mx-vertical-dpi-handler')
|
device.remove_notification_handler('mx-vertical-dpi-handler')
|
||||||
del device._slidingDpiState
|
|
||||||
DPI_key = device.keys[device.keys.index(_special_keys.CONTROL.DPI_Switch)]
|
|
||||||
DPI_key.set_rawXY_reporting(False)
|
|
||||||
except Exception:
|
except Exception:
|
||||||
if _log.isEnabledFor(_WARNING):
|
if _log.isEnabledFor(_WARNING):
|
||||||
_log.warn('cannot disable DPI sliding on %s', device)
|
_log.warn('cannot disable DPI sliding on %s', device)
|
||||||
|
if hasattr(device, '_slidingDpiState'):
|
||||||
|
del device._slidingDpiState
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
DPISlidingKeys = [_special_keys.CONTROL.DPI_Switch]
|
||||||
|
|
||||||
|
def _feature_dpi_sliding_callback(device):
|
||||||
|
# need _F.REPROG_CONTROLS_V4 feature and a DPI Switch that can send raw XY
|
||||||
|
# and _F.ADJUSTABLE_DPI so that the DPI can be adjusted
|
||||||
|
if device.kind == _DK.mouse and _F.ADJUSTABLE_DPI in device.features:
|
||||||
|
keys = []
|
||||||
|
for key in DPISlidingKeys:
|
||||||
|
key_index = device.keys.index(key)
|
||||||
|
dkey = device.keys[key_index] if key_index is not None else None
|
||||||
|
if dkey is not None and 'raw XY' in dkey.flags and 'divertable' in dkey.flags:
|
||||||
|
keys.append(dkey.key)
|
||||||
|
if not keys: # none of the keys designed for this, so look for any key with correct flags
|
||||||
|
for key in device.keys:
|
||||||
|
if 'raw XY' in key.flags and 'divertable' in key.flags and 'virtual' not in key.flags:
|
||||||
|
keys.append(key.key)
|
||||||
|
if keys:
|
||||||
|
keys.insert(0, _NamedInt(0, 'Off'))
|
||||||
|
return _ChoicesV(_NamedInts.list(keys), byte_count=2)
|
||||||
|
|
||||||
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, ))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -101,12 +101,13 @@ def _cleanup(d):
|
||||||
|
|
||||||
|
|
||||||
def _cleanup_load(d):
|
def _cleanup_load(d):
|
||||||
# remove boolean values for mouse-gestures
|
# remove boolean values for mouse-gesture and dpi-sliding
|
||||||
for device in d:
|
for device in d.values():
|
||||||
if isinstance(device, dict):
|
if isinstance(device, dict):
|
||||||
mg = device.get('mouse-gestures', None)
|
for setting in ['mouse-gestures', 'dpi-sliding']:
|
||||||
|
mg = device.get(setting, None)
|
||||||
if mg is True or mg is False:
|
if mg is True or mg is False:
|
||||||
del device['mouse-gestures']
|
del device[setting]
|
||||||
|
|
||||||
|
|
||||||
class _DeviceEntry(dict):
|
class _DeviceEntry(dict):
|
||||||
|
|
Loading…
Reference in New Issue