diff --git a/lib/logitech_receiver/settings_templates.py b/lib/logitech_receiver/settings_templates.py index b9b4c298..f7fbbd21 100644 --- a/lib/logitech_receiver/settings_templates.py +++ b/lib/logitech_receiver/settings_templates.py @@ -25,6 +25,7 @@ from . import hidpp10 as _hidpp10 from . import hidpp20 as _hidpp20 from .common import ( bytes2int as _bytes2int, + int2bytes as _int2bytes, NamedInts as _NamedInts, unpack as _unpack, ) @@ -129,7 +130,9 @@ _FN_SWAP = ('fn-swap', _("Swap Fx function"), "and you must hold the FN key to activate their special function.")) _HAND_DETECTION = ('hand-detection', _("Hand Detection"), _("Turn on illumination when the hands hover over the keyboard.")) - +_SMART_SHIFT = ('smart-shift', _("Smart Shift"), + _("Automatically switch the mouse wheel between ratchet and freespin mode.\n" + "The mouse wheel is always free at 0, and always locked at 50")) # # # @@ -176,6 +179,42 @@ def _feature_smooth_scroll(): label=_SMOOTH_SCROLL[1], description=_SMOOTH_SCROLL[2], device_kind=_DK.mouse) +def _feature_smart_shift(): + _MIN_SMART_SHIFT_VALUE = 0 + _MAX_SMART_SHIFT_VALUE = 50 + class _SmartShiftRW(_FeatureRW): + def __init__(self, feature): + super(_SmartShiftRW, self).__init__(feature) + + def read(self, device): + value = super(_SmartShiftRW, self).read(device) + if _bytes2int(value[0:1]) == 1: + # Mode = Freespin, map to minimum + return _int2bytes(_MIN_SMART_SHIFT_VALUE, count=1) + else: + # Mode = smart shift, map to the value, capped at maximum + threshold = min(_bytes2int(value[1:2]), _MAX_SMART_SHIFT_VALUE) + return _int2bytes(threshold, count=1) + + def write(self, device, data_bytes): + threshold = _bytes2int(data_bytes) + # Freespin at minimum + mode = 1 if threshold == _MIN_SMART_SHIFT_VALUE else 2 + + # Ratchet at maximum + if threshold == _MAX_SMART_SHIFT_VALUE: + threshold = 255 + + data = _int2bytes(mode, count=1) + _int2bytes(threshold, count=1) * 2 + return super(_SmartShiftRW, self).write(device, data) + + return feature_range(_SMART_SHIFT[0], _F.SMART_SHIFT, + _MIN_SMART_SHIFT_VALUE, _MAX_SMART_SHIFT_VALUE, + bytes_count=1, + rw=_SmartShiftRW(_F.SMART_SHIFT), + label=_SMART_SHIFT[1], description=_SMART_SHIFT[2], + device_kind=_DK.mouse) + def _feature_adjustable_dpi_choices(device): # [1] getSensorDpiList(sensorIdx) reply = device.feature_request(_F.ADJUSTABLE_DPI, 0x10) @@ -224,6 +263,7 @@ _SETTINGS_LIST = namedtuple('_SETTINGS_LIST', [ 'dpi', 'hand_detection', 'typing_illumination', + 'smart_shift', ]) del namedtuple @@ -235,6 +275,7 @@ RegisterSettings = _SETTINGS_LIST( dpi=_register_dpi, hand_detection=_register_hand_detection, typing_illumination=None, + smart_shift=None, ) FeatureSettings = _SETTINGS_LIST( fn_swap=_feature_fn_swap, @@ -244,6 +285,7 @@ FeatureSettings = _SETTINGS_LIST( dpi=_feature_adjustable_dpi, hand_detection=None, typing_illumination=None, + smart_shift=_feature_smart_shift, ) del _SETTINGS_LIST @@ -278,6 +320,7 @@ def check_feature_settings(device, already_known): already_known.append(feature(device)) check_feature(_SMOOTH_SCROLL[0], _F.HI_RES_SCROLLING) - check_feature(_FN_SWAP[0], _F.FN_INVERSION) - check_feature(_FN_SWAP[0], _F.NEW_FN_INVERSION, 'new_fn_swap') - check_feature(_DPI[0], _F.ADJUSTABLE_DPI) + check_feature(_FN_SWAP[0], _F.FN_INVERSION) + check_feature(_FN_SWAP[0], _F.NEW_FN_INVERSION, 'new_fn_swap') + check_feature(_DPI[0], _F.ADJUSTABLE_DPI) + check_feature(_SMART_SHIFT[0], _F.SMART_SHIFT)