headset RGB: re-overlay per-zone paint after onboard cluster writes
Writing the 0x0621 onboard cluster effect re-fills every LED uniformly, which the headset firmware treats as dropping the host per-zone buffer. HeadsetLEDControl.write already re-asserted the per-zone layer on re-claim, but HeadsetOnboardEffect.write did not — so changing the LEDs Primary color clobbered individually-painted zones with the flat base color and never restored them. Extract the re-assert logic into _headset_reassert_zone_layer (repaint every zone to LEDs Primary, then overlay the explicit per-zone overrides) and call it from both write paths. The helper is a no-op unless the onboard effect is Static, since a non-Static animation owns the LEDs and masks per-zone anyway.
This commit is contained in:
parent
e557c30ab2
commit
653f7aea18
|
|
@ -2378,6 +2378,26 @@ def _headset_per_zone_overrides(device):
|
||||||
return overrides
|
return overrides
|
||||||
|
|
||||||
|
|
||||||
|
def _headset_reassert_zone_layer(device):
|
||||||
|
"""Re-paint the per-zone layer: every zone to the LEDs Primary color,
|
||||||
|
then the explicit per-zone overrides on top.
|
||||||
|
|
||||||
|
The headset firmware drops the host-painted per-zone buffer whenever a
|
||||||
|
cluster layer is (re)written — so any path that re-asserts a cluster
|
||||||
|
layer (LED Control re-claim, onboard Static color change) must call this
|
||||||
|
to restore the per-zone paint. No-op unless the onboard effect is Fixed;
|
||||||
|
a non-Static animation owns the LEDs and masks per-zone anyway.
|
||||||
|
"""
|
||||||
|
if not _headset_cluster_effect_is_fixed(device):
|
||||||
|
return
|
||||||
|
zones = headset_rgb.discover_zones(device)
|
||||||
|
if not zones:
|
||||||
|
return
|
||||||
|
zone_map = {int(z): _headset_primary_color(device) for z in zones}
|
||||||
|
zone_map.update(_headset_per_zone_overrides(device) or {})
|
||||||
|
headset_rgb.write_zone_map(device, zone_map)
|
||||||
|
|
||||||
|
|
||||||
def _headset_led_control_on(device):
|
def _headset_led_control_on(device):
|
||||||
"""True when the headset LED Control is on (Solaar drives the LEDs).
|
"""True when the headset LED Control is on (Solaar drives the LEDs).
|
||||||
When off, the firmware owns the LEDs and host color writes are
|
When off, the firmware owns the LEDs and host color writes are
|
||||||
|
|
@ -2438,12 +2458,7 @@ class HeadsetLEDControl(settings.Setting):
|
||||||
result = super().write(value, save)
|
result = super().write(value, save)
|
||||||
if result is not None and value and self._device.online:
|
if result is not None and value and self._device.online:
|
||||||
if _headset_cluster_effect_is_fixed(self._device):
|
if _headset_cluster_effect_is_fixed(self._device):
|
||||||
primary = _headset_primary_color(self._device)
|
_headset_reassert_zone_layer(self._device)
|
||||||
zones = headset_rgb.discover_zones(self._device)
|
|
||||||
if zones:
|
|
||||||
zone_map = {int(z): primary for z in zones}
|
|
||||||
zone_map.update(_headset_per_zone_overrides(self._device) or {})
|
|
||||||
headset_rgb.write_zone_map(self._device, zone_map)
|
|
||||||
else:
|
else:
|
||||||
onboard = next((s for s in self._device.settings if s.name == "headset-onboard-effect"), None)
|
onboard = next((s for s in self._device.settings if s.name == "headset-onboard-effect"), None)
|
||||||
if onboard is not None and onboard._value is not None:
|
if onboard is not None and onboard._value is not None:
|
||||||
|
|
@ -2910,6 +2925,17 @@ class HeadsetOnboardEffect(settings.Setting):
|
||||||
setting.fields_map = {eid: (id_choices[eid], {field: 1 for field in cls._EFFECT_FIELDS[eid]}) for eid in supported}
|
setting.fields_map = {eid: (id_choices[eid], {field: 1 for field in cls._EFFECT_FIELDS[eid]}) for eid in supported}
|
||||||
return setting
|
return setting
|
||||||
|
|
||||||
|
def write(self, value, save=True):
|
||||||
|
# Writing the 0x0621 cluster effect re-fills every LED uniformly; the
|
||||||
|
# firmware treats that as dropping the host per-zone buffer. After a
|
||||||
|
# Static write, re-overlay the per-zone paint so individually-colored
|
||||||
|
# zones survive a LEDs Primary change. _headset_reassert_zone_layer is
|
||||||
|
# a no-op for non-Static effects (the animation masks per-zone).
|
||||||
|
result = super().write(value, save)
|
||||||
|
if result is not None and self._device.online and _headset_led_control_on(self._device):
|
||||||
|
_headset_reassert_zone_layer(self._device)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# LogiVoice (0x0900 + 0x0901..0x0907) — read-only presentation pass.
|
# LogiVoice (0x0900 + 0x0901..0x0907) — read-only presentation pass.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue