Skip to content

Commit 56572dd

Browse files
committed
fix: reset layout state when device disconnects
1 parent 080db32 commit 56572dd

2 files changed

Lines changed: 46 additions & 3 deletions

File tree

tests/test_backend.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import copy
2+
import unittest
3+
from unittest.mock import patch
4+
5+
from core.config import DEFAULT_CONFIG
6+
7+
try:
8+
from ui.backend import Backend
9+
except ModuleNotFoundError:
10+
Backend = None
11+
12+
13+
@unittest.skipIf(Backend is None, "PySide6 not installed in test environment")
14+
class BackendDeviceLayoutTests(unittest.TestCase):
15+
def _make_backend(self):
16+
with (
17+
patch("ui.backend.load_config", return_value=copy.deepcopy(DEFAULT_CONFIG)),
18+
patch("ui.backend.save_config"),
19+
):
20+
return Backend(engine=None)
21+
22+
def test_defaults_to_generic_layout_without_connected_device(self):
23+
backend = self._make_backend()
24+
25+
self.assertEqual(backend.effectiveDeviceLayoutKey, "generic_mouse")
26+
self.assertFalse(backend.hasInteractiveDeviceLayout)
27+
28+
def test_disconnected_override_request_does_not_persist(self):
29+
backend = self._make_backend()
30+
backend._connected_device_key = "mx_master_3"
31+
backend.setDeviceLayoutOverride("mx_master")
32+
33+
overrides = backend._cfg.get("settings", {}).get("device_layout_overrides", {})
34+
self.assertEqual(overrides, {})
35+
36+
37+
if __name__ == "__main__":
38+
unittest.main()

ui/backend.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def __init__(self, engine=None, parent=None):
5656
self._device_display_name = "Logitech mouse"
5757
self._connected_device_key = ""
5858
self._device_layout_override_key = ""
59-
self._device_layout = get_device_layout("mx_master")
59+
self._device_layout = get_device_layout("generic_mouse")
6060
self._battery_level = -1
6161
self._debug_lines = []
6262
self._debug_events_enabled = bool(
@@ -475,7 +475,7 @@ def actionLabelFor(self, actionId):
475475
def setDeviceLayoutOverride(self, layoutKey):
476476
normalized = (layoutKey or "").strip()
477477
device_key = self._connected_device_key
478-
if not device_key:
478+
if not self._mouse_connected or not device_key:
479479
self.statusMessage.emit("Connect a device first")
480480
return
481481
valid_choices = {choice["key"] for choice in get_manual_layout_choices()}
@@ -549,6 +549,8 @@ def _handleConnectionChange(self, connected):
549549
device = getattr(self._engine, "connected_device", None) if self._engine else None
550550
if connected:
551551
self._apply_device_layout(device)
552+
else:
553+
self._apply_device_layout(None)
552554
if not connected and self._battery_level != -1:
553555
self._battery_level = -1
554556
self.batteryLevelChanged.emit()
@@ -571,8 +573,11 @@ def _apply_device_layout(self, device):
571573
self.deviceInfoChanged.emit()
572574

573575
overrides = self._cfg.get("settings", {}).get("device_layout_overrides", {})
576+
valid_override_keys = {choice["key"] for choice in get_manual_layout_choices()}
574577
override_key = overrides.get(device_key, "") if device_key else ""
575-
layout_key = override_key or getattr(device, "ui_layout", None) or "mx_master"
578+
if override_key not in valid_override_keys:
579+
override_key = ""
580+
layout_key = override_key or getattr(device, "ui_layout", None) or "generic_mouse"
576581
layout = get_device_layout(layout_key)
577582
layout_changed = False
578583
if override_key != self._device_layout_override_key:

0 commit comments

Comments
 (0)