mirror of
https://github.com/yusufipk/dikte.git
synced 2026-09-11 10:56:10 +00:00
Wait for macOS focus restoration to land
This commit is contained in:
+15
-3
@@ -637,12 +637,24 @@ class Dikte:
|
|||||||
# inactive: at forty the title bar visibly blinks, at ten it does not.
|
# inactive: at forty the title bar visibly blinks, at ten it does not.
|
||||||
# Two messages to AppKit per tick, for at most a second and a half.
|
# Two messages to AppKit per tick, for at most a second and a half.
|
||||||
watch.setInterval(10)
|
watch.setInterval(10)
|
||||||
|
# activateWithOptions: answers whether macOS accepted the request, not
|
||||||
|
# whether the other application is already back in front. Keep the
|
||||||
|
# watch alive until that asynchronous handoff is observable; on Intel
|
||||||
|
# Macs it can take hundreds of milliseconds after the call returned.
|
||||||
|
restore_requested = False
|
||||||
|
|
||||||
def look():
|
def look():
|
||||||
if mac_window.is_frontmost():
|
nonlocal restore_requested
|
||||||
mac_window.activate(was_in_front)
|
if time.monotonic() > deadline:
|
||||||
self._stop_watching_the_front()
|
self._stop_watching_the_front()
|
||||||
elif time.monotonic() > deadline:
|
return
|
||||||
|
if mac_window.is_frontmost():
|
||||||
|
if not restore_requested:
|
||||||
|
restore_requested = mac_window.activate(was_in_front)
|
||||||
|
elif restore_requested:
|
||||||
|
# The request has landed. Stop only now, rather than as soon
|
||||||
|
# as AppKit accepted it, so a delayed or failed handoff stays
|
||||||
|
# under observation until the deadline guard above.
|
||||||
self._stop_watching_the_front()
|
self._stop_watching_the_front()
|
||||||
|
|
||||||
watch.timeout.connect(look)
|
watch.timeout.connect(look)
|
||||||
|
|||||||
+35
-2
@@ -604,7 +604,7 @@ class GivingTheFrontBack(DikteTest):
|
|||||||
from dikte import mac_window
|
from dikte import mac_window
|
||||||
self.dikte = dikte_module
|
self.dikte = dikte_module
|
||||||
self.activated = []
|
self.activated = []
|
||||||
self.patch_attr(mac_window, "activate", self.activated.append)
|
self.patch_attr(mac_window, "activate", self.activate)
|
||||||
self.ticks = []
|
self.ticks = []
|
||||||
outer = self
|
outer = self
|
||||||
|
|
||||||
@@ -645,6 +645,10 @@ class GivingTheFrontBack(DikteTest):
|
|||||||
|
|
||||||
self.bare = BareDikte
|
self.bare = BareDikte
|
||||||
|
|
||||||
|
def activate(self, pid):
|
||||||
|
self.activated.append(pid)
|
||||||
|
return True
|
||||||
|
|
||||||
def watching(self, was_in_front, dikte_in_front, on=None):
|
def watching(self, was_in_front, dikte_in_front, on=None):
|
||||||
from dikte import mac_window
|
from dikte import mac_window
|
||||||
self.patch_attr(mac_window, "is_frontmost", lambda: dikte_in_front)
|
self.patch_attr(mac_window, "is_frontmost", lambda: dikte_in_front)
|
||||||
@@ -656,7 +660,36 @@ class GivingTheFrontBack(DikteTest):
|
|||||||
watch = self.watching(4242, dikte_in_front=True)
|
watch = self.watching(4242, dikte_in_front=True)
|
||||||
watch.tick()
|
watch.tick()
|
||||||
self.assertEqual(self.activated, [4242])
|
self.assertEqual(self.activated, [4242])
|
||||||
self.assertFalse(watch.running) # one is enough; it stops watching
|
self.assertTrue(watch.running) # accepted is not the same as landed
|
||||||
|
self.patch_attr(self.mac_window_module(), "is_frontmost", lambda: False)
|
||||||
|
watch.tick()
|
||||||
|
self.assertFalse(watch.running)
|
||||||
|
|
||||||
|
def test_an_accepted_restore_is_not_sent_again_while_it_is_landing(self):
|
||||||
|
watch = self.watching(4242, dikte_in_front=True)
|
||||||
|
watch.tick()
|
||||||
|
watch.tick()
|
||||||
|
self.assertEqual(self.activated, [4242])
|
||||||
|
self.assertTrue(watch.running)
|
||||||
|
|
||||||
|
def test_an_accepted_restore_that_never_lands_still_times_out(self):
|
||||||
|
watch = self.watching(4242, dikte_in_front=True)
|
||||||
|
watch.tick()
|
||||||
|
with mock.patch.object(self.dikte.time, "monotonic",
|
||||||
|
return_value=self.dikte.time.monotonic() + 60):
|
||||||
|
watch.tick()
|
||||||
|
self.assertFalse(watch.running)
|
||||||
|
self.assertEqual(self.activated, [4242])
|
||||||
|
|
||||||
|
def test_a_restore_the_system_refused_is_retried(self):
|
||||||
|
from dikte import mac_window
|
||||||
|
self.patch_attr(mac_window, "activate",
|
||||||
|
lambda pid: self.activated.append(pid) or False)
|
||||||
|
watch = self.watching(4242, dikte_in_front=True)
|
||||||
|
watch.tick()
|
||||||
|
watch.tick()
|
||||||
|
self.assertEqual(self.activated, [4242, 4242])
|
||||||
|
self.assertTrue(watch.running)
|
||||||
|
|
||||||
def test_a_front_that_was_never_taken_is_left_where_it_is(self):
|
def test_a_front_that_was_never_taken_is_left_where_it_is(self):
|
||||||
"""The microphone does not always take it, and pulling an application
|
"""The microphone does not always take it, and pulling an application
|
||||||
|
|||||||
Reference in New Issue
Block a user