Grey out LED zone rows when LED Control is off (0x8070)
The 0x8071 path already greys rgb_zone_* rows (and per-key) when rgb_control is off, so the user sees that those settings have no effect in Device mode. The 0x8070 zone settings had no such gate: led_zone_* rows stayed active even with led_control off, implying writes that go nowhere. Add the 0x8070 analog — led_zone_* rows gate on led_control, mirroring rgb_zone_* / rgb_control — wired into the same three points: initial _apply_rgb_gates, the toggle-time re-gate, and the async-read guard in _update_setting_item so a late read can't un-grey a blocked row.
This commit is contained in:
parent
3b76be9abb
commit
00a6a59f9e
|
|
@ -816,6 +816,8 @@ _icons_allowables = {v: k for k, v in _allowables_icons.items()}
|
|||
# the zone index (rgb_zone_1, rgb_zone_2, ...).
|
||||
_SW_CONTROL_DEPENDENT_NAMES = ("rgb_idle_timeout", "rgb_idle_effect", "rgb_sleep_timeout")
|
||||
_SW_CONTROL_DEPENDENT_PREFIXES = ("rgb_zone_",)
|
||||
# 0x8070 analog of rgb_control/rgb_zone_: led_zone_* rows need led_control on.
|
||||
_LED_CONTROL_DEPENDENT_PREFIXES = ("led_zone_",)
|
||||
# headset_led_control = whether Solaar holds the live-coloring claim (off lets
|
||||
# another app drive the LEDs). The 0x0620 per-zone painting and the 0x0621
|
||||
# onboard effect are both live LED control, so both need the claim; per-zone
|
||||
|
|
@ -846,6 +848,25 @@ def _sw_control_blocked(device):
|
|||
return value not in (True, 3)
|
||||
|
||||
|
||||
def _led_control_blocked(device):
|
||||
"""True when the 0x8070 LED Control is off (Device/firmware mode) — its
|
||||
led_zone_* rows have no effect. Reads setting._value first, then the
|
||||
persister; accepts the current bool or a legacy int 0/1."""
|
||||
persister = getattr(device, "persister", None)
|
||||
if persister is None:
|
||||
return False
|
||||
value = None
|
||||
for s in getattr(device, "settings", []) or []:
|
||||
if s.name == "led_control":
|
||||
value = s._value
|
||||
break
|
||||
if value is None:
|
||||
value = persister.get("led_control")
|
||||
if value is None:
|
||||
return False
|
||||
return value not in (True, 1)
|
||||
|
||||
|
||||
def _headset_led_blocked(device):
|
||||
"""True when the headset's LED Control is off (Device/firmware mode).
|
||||
Reads setting._value first, then the persister; accepts the current bool
|
||||
|
|
@ -919,6 +940,8 @@ def _gate_blocks(device, name):
|
|||
completions can't undo the grey-out when their callbacks land later."""
|
||||
if name in _SW_CONTROL_DEPENDENT_NAMES or any(name.startswith(p) for p in _SW_CONTROL_DEPENDENT_PREFIXES):
|
||||
return _sw_control_blocked(device)
|
||||
if any(name.startswith(p) for p in _LED_CONTROL_DEPENDENT_PREFIXES):
|
||||
return _led_control_blocked(device)
|
||||
if name == "per-key-lighting":
|
||||
return _sw_control_blocked(device) or _zone_effect_blocks_perkey(device)
|
||||
if name in _HEADSET_LED_DEPENDENT_NAMES:
|
||||
|
|
@ -943,6 +966,7 @@ def _apply_rgb_gates(device):
|
|||
if (
|
||||
name in _SW_CONTROL_DEPENDENT_NAMES
|
||||
or any(name.startswith(p) for p in _SW_CONTROL_DEPENDENT_PREFIXES)
|
||||
or any(name.startswith(p) for p in _LED_CONTROL_DEPENDENT_PREFIXES)
|
||||
or name == "per-key-lighting"
|
||||
or name in _HEADSET_LED_DEPENDENT_NAMES
|
||||
):
|
||||
|
|
@ -993,9 +1017,13 @@ def _change_click(button, sbox):
|
|||
# The lock icon on rgb_control, any zone, per-key, or headset_led_control
|
||||
# can change whether a dependent row is functional — re-evaluate the gate.
|
||||
name = sbox.setting.name
|
||||
if name in ("rgb_control", "per-key-lighting", "headset_led_control", "headset-onboard-effect") or name.startswith(
|
||||
"rgb_zone_"
|
||||
):
|
||||
if name in (
|
||||
"rgb_control",
|
||||
"led_control",
|
||||
"per-key-lighting",
|
||||
"headset_led_control",
|
||||
"headset-onboard-effect",
|
||||
) or name.startswith(("rgb_zone_", "led_zone_")):
|
||||
_apply_rgb_gates(sbox.setting._device)
|
||||
return True
|
||||
|
||||
|
|
@ -1099,9 +1127,13 @@ def _update_setting_item(sbox, value, is_online=True, sensitive=True, null_okay=
|
|||
logger.warning("%s: error setting control value (%s): %s", sbox.setting.name, sbox.setting._device, repr(e))
|
||||
sbox._control.set_sensitive(sensitive is True and can_function)
|
||||
_change_icon(sensitive, sbox._change_icon)
|
||||
# rgb_control / rgb_zone_* gate per-key; headset_led_control and the
|
||||
# headset-onboard-effect gate the per-zone row — re-evaluate on a change.
|
||||
if name in ("rgb_control", "headset_led_control", "headset-onboard-effect") or name.startswith("rgb_zone_"):
|
||||
# A control/zone/onboard-effect change can flip a dependent row's gate.
|
||||
if name in (
|
||||
"rgb_control",
|
||||
"led_control",
|
||||
"headset_led_control",
|
||||
"headset-onboard-effect",
|
||||
) or name.startswith(("rgb_zone_", "led_zone_")):
|
||||
_apply_rgb_gates(sbox.setting._device)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
from types import SimpleNamespace
|
||||
|
||||
from solaar.ui import config_panel
|
||||
|
||||
|
||||
def _device(settings, persister):
|
||||
return SimpleNamespace(settings=settings, persister=persister)
|
||||
|
||||
|
||||
def _setting(name, value):
|
||||
return SimpleNamespace(name=name, _value=value)
|
||||
|
||||
|
||||
def test_led_control_blocked_reads_setting_value_first():
|
||||
device = _device([_setting("led_control", False)], {"led_control": True})
|
||||
assert config_panel._led_control_blocked(device) is True
|
||||
|
||||
device = _device([_setting("led_control", True)], {"led_control": False})
|
||||
assert config_panel._led_control_blocked(device) is False
|
||||
|
||||
|
||||
def test_led_control_blocked_falls_back_to_persister():
|
||||
device = _device([_setting("led_control", None)], {"led_control": False})
|
||||
assert config_panel._led_control_blocked(device) is True
|
||||
|
||||
|
||||
def test_led_control_blocked_unknown_does_not_block():
|
||||
device = _device([], {})
|
||||
assert config_panel._led_control_blocked(device) is False
|
||||
|
||||
|
||||
def test_gate_blocks_led_zone_follows_led_control():
|
||||
off = _device([_setting("led_control", False), _setting("led_zone_1", None)], {})
|
||||
assert config_panel._gate_blocks(off, "led_zone_1") is True
|
||||
|
||||
on = _device([_setting("led_control", True), _setting("led_zone_1", None)], {})
|
||||
assert config_panel._gate_blocks(on, "led_zone_1") is False
|
||||
|
||||
|
||||
def test_gate_blocks_rgb_zone_unaffected_by_led_control():
|
||||
# rgb_zone_ still keys off rgb_control, not led_control
|
||||
device = _device([_setting("led_control", False), _setting("rgb_control", True), _setting("rgb_zone_1", None)], {})
|
||||
assert config_panel._gate_blocks(device, "rgb_zone_1") is False
|
||||
Loading…
Reference in New Issue