diff --git a/lib/logitech_receiver/settings_templates.py b/lib/logitech_receiver/settings_templates.py index 58854ec1..0104d4b1 100644 --- a/lib/logitech_receiver/settings_templates.py +++ b/lib/logitech_receiver/settings_templates.py @@ -2265,10 +2265,9 @@ class HeadsetLEDsPrimary(settings.Setting): class HeadsetPerZoneLighting(settings.Settings): """Per-zone LED color overrides. - Mirrors `PerKeyLighting`'s `Settings` + `ChoicesMapValidator` style — - one dropdown per discovered zone with the `COLORSPLUS` palette. The - "No change" entry means "inherit the current `LEDs Primary` color", - so users can paint individual zones without losing the base setup. + Mirrors `PerKeyLighting` — keys are firmware zone IDs, values are + 24-bit RGB ints with the `-1` sentinel meaning "inherit the current + `LEDs Primary` color." Surfaces in the UI via the per-key painter. """ name = "headset_per_zone_lighting" @@ -2279,20 +2278,20 @@ class HeadsetPerZoneLighting(settings.Settings): ) feature = _F.HEADSET_RGB_HOSTMODE persist = True - choices_universe = special_keys.COLORSPLUS + editor_class = "solaar.ui.perkey.control:PerKeyControl" class rw_class(settings.FeatureRWMap): pass - class validator_class(settings_validator.ChoicesMapValidator): + class validator_class(settings_validator.MapRangeValidator): + _COLOR_RANGE = settings_validator.Range(min=0, max=0xFFFFFF, byte_count=3) + @classmethod def build(cls, setting_class, device): zones = headset_rgb.discover_zones(device) if not zones: return None - choices_map = { - common.NamedInt(int(z), _("Zone") + " " + str(int(z))): setting_class.choices_universe for z in zones - } + choices_map = {common.NamedInt(int(z), _("Zone") + " " + str(int(z))): cls._COLOR_RANGE for z in zones} return cls(choices_map) if choices_map else None def read(self, cached=True): diff --git a/lib/solaar/ui/perkey/layouts/__init__.py b/lib/solaar/ui/perkey/layouts/__init__.py index b2bde7e2..128b3e39 100644 --- a/lib/solaar/ui/perkey/layouts/__init__.py +++ b/lib/solaar/ui/perkey/layouts/__init__.py @@ -26,6 +26,7 @@ from __future__ import annotations from collections.abc import Callable from ..layout import Layout +from . import headset_g522 from . import keyboard_ansi from . import keyboard_iso_azerty from . import keyboard_iso_qwerty @@ -140,3 +141,5 @@ for _family, (_full, _tkl) in _FAMILY_LAYOUTS.items(): register_layout(0x8081, _keyboard_matcher(_family, full_size=False), _tkl) register_layout(0x8081, _name_contains("G502 X"), mouse_g502x.LAYOUT) +# HEADSET_RGB_HOSTMODE = 0x0620 +register_layout(0x0620, _name_contains("G522"), headset_g522.LAYOUT) diff --git a/lib/solaar/ui/perkey/layouts/headset_g522.py b/lib/solaar/ui/perkey/layouts/headset_g522.py new file mode 100644 index 00000000..de971bdf --- /dev/null +++ b/lib/solaar/ui/perkey/layouts/headset_g522.py @@ -0,0 +1,53 @@ +## Copyright (C) 2026 Solaar Contributors https://pwr-solaar.github.io/Solaar/ +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License along +## with this program; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +"""LED layout for the G522 LIGHTSPEED headset. + +Eight LEDs in two 2×2 grids — one per earcup, viewed from outside: + + Left earcup Right earcup + ┌─────┬─────┐ ┌─────┬─────┐ + │ 8 │ 7 │ │ 6 │ 5 │ + ├─────┼─────┤ ├─────┼─────┤ + │ 4 │ 3 │ │ 2 │ 1 │ + └─────┴─────┘ └─────┴─────┘ +""" + +from __future__ import annotations + +from ..layout import Cell +from ..layout import Layout + +_CELLS: tuple[Cell, ...] = ( + # Left earcup (cols 0-1, outer view): top-left=8, top-right=7, bottom-left=4, bottom-right=3 + Cell(zone_id=8, row=0, col=0, group="main", label="8"), + Cell(zone_id=7, row=0, col=1, group="main", label="7"), + Cell(zone_id=4, row=1, col=0, group="main", label="4"), + Cell(zone_id=3, row=1, col=1, group="main", label="3"), + # Right earcup (cols 3-4, outer view): top-left=6, top-right=5, bottom-left=2, bottom-right=1 + Cell(zone_id=6, row=0, col=3, group="main", label="6"), + Cell(zone_id=5, row=0, col=4, group="main", label="5"), + Cell(zone_id=2, row=1, col=3, group="main", label="2"), + Cell(zone_id=1, row=1, col=4, group="main", label="1"), +) + + +LAYOUT: Layout = Layout( + cells=_CELLS, + rows=2, + cols=5, + description="Logitech G522 LIGHTSPEED headset (8 LEDs, 4 per earcup)", +)