fix(focus): détecter correctement l'unfocus sur les backends Wayland
Le suivi du focus laissait les injections app-controlled actives lors d'une perte de focus réelle (fermeture de la fenêtre courante, retour à un bureau vide). On corrige la détection sur toute la chaîne : - FocusService: un app_id vide est désormais traité comme un unfocus réel (et non un focus transitoire ignoré), ce qui stoppe les injections liées à l'application. - Sway: on ignore les events 'new' (pas un changement de focus) et on relit le focus courant sur un event 'title' non focused. - WlrForeignToplevelBackend: suit _current_handle, le clear sur stop() et émet un FocusEvent vide quand le toplevel actuellement focus se ferme. Tests: test_focus_service + test_focus_watcher (67) OK; lot feature historique (295) OK. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -233,11 +233,33 @@ class TestFocusService(unittest.TestCase):
|
||||
|
||||
# -- debounce / transient focus ---------------------------------------
|
||||
|
||||
def test_transient_empty_focus_is_ignored(self):
|
||||
def test_empty_focus_stops_app_controlled(self):
|
||||
service = self._make_service([self._binding("firefox", [("devX", "p1")])])
|
||||
service._reconcile(_event("firefox"))
|
||||
self.daemon.calls["start_injecting"].clear()
|
||||
|
||||
service._on_focus(_event(app_id=""))
|
||||
self.assertIsNone(service._pending_event)
|
||||
self.assertIsNone(service._debounce_id)
|
||||
service._flush()
|
||||
self.assertEqual(self.daemon.calls["stop_injecting"], ["devX"])
|
||||
self.assertEqual(service._app_controlled, {})
|
||||
self.assertEqual(self.daemon.calls["start_injecting"], [])
|
||||
|
||||
def test_focus_event_for_bound_app_starts_injecting(self):
|
||||
service = self._make_service([self._binding("firefox", [("devX", "p1")])])
|
||||
service._on_focus(_event("firefox"))
|
||||
service._flush()
|
||||
self.assertEqual(self.daemon.calls["start_injecting"], [("devX", "p1")])
|
||||
self.assertEqual(service._app_controlled, {"devX": "p1"})
|
||||
|
||||
def test_focus_event_for_unbound_app_stops_app_controlled(self):
|
||||
service = self._make_service([self._binding("firefox", [("devX", "p1")])])
|
||||
service._reconcile(_event("firefox"))
|
||||
self.daemon.calls["start_injecting"].clear()
|
||||
|
||||
service._on_focus(_event("code"))
|
||||
service._flush()
|
||||
self.assertEqual(self.daemon.calls["stop_injecting"], ["devX"])
|
||||
self.assertEqual(service._app_controlled, {})
|
||||
self.assertEqual(self.daemon.calls["start_injecting"], [])
|
||||
|
||||
def test_debounce_collapses_rapid_focus(self):
|
||||
|
||||
Reference in New Issue
Block a user