Change to a notification based approach to getting the focused app's name

This commit is contained in:
2026-03-23 19:30:57 -07:00
parent 80b93bdb1c
commit bec64b4291

View File

@@ -1,6 +1,6 @@
import signal, sys import signal, sys, objc
from AppKit import NSWorkspace from AppKit import NSWorkspace
from Foundation import NSRunLoop, NSDate from Foundation import NSRunLoop, NSDate, NSObject
import hid import hid
VID, PID = 0x3384, 0x0009 VID, PID = 0x3384, 0x0009
@@ -20,47 +20,60 @@ def send_app_name(dev, name):
dev.write(data) dev.write(data)
dev.read(32, timeout=1000) dev.read(32, timeout=1000)
class AppObserver(NSObject):
def init(self):
self = objc.super(AppObserver, self).init()
self.dev = None
self.last_app = None
self.current_app = NSWorkspace.sharedWorkspace().frontmostApplication().localizedName()
return self
def appChanged_(self, notification):
app = notification.userInfo()["NSWorkspaceApplicationKey"].localizedName()
self.current_app = app
if self.dev is not None:
self.last_app = app
print(f"App: {app}")
try:
send_app_name(self.dev, app)
except Exception:
print("Keyboard disconnected")
self.dev = None
self.last_app = None
def main(): def main():
signal.signal(signal.SIGINT, lambda *_: sys.exit(0)) signal.signal(signal.SIGINT, lambda *_: sys.exit(0))
ws = NSWorkspace.sharedWorkspace() ws = NSWorkspace.sharedWorkspace()
dev = None
last_app = None observer = AppObserver.alloc().init()
ws.notificationCenter().addObserver_selector_name_object_(
observer, "appChanged:", "NSWorkspaceDidActivateApplicationNotification", None
)
while True: while True:
connected = find_keyboard_path() is not None connected = find_keyboard_path() is not None
# Detect disconnect # Detect disconnect
if dev is not None and not connected: if observer.dev is not None and not connected:
print("Keyboard disconnected") print("Keyboard disconnected")
dev = None observer.dev = None
last_app = None observer.last_app = None
# Connect and send current app # Connect and send current app
if dev is None and connected: if observer.dev is None and connected:
try: try:
dev = hid.Device(path=find_keyboard_path()) observer.dev = hid.Device(path=find_keyboard_path())
print("Keyboard connected") print("Keyboard connected")
last_app = ws.frontmostApplication().localizedName() observer.last_app = observer.current_app
print(f"App: {last_app}") print(f"App: {observer.current_app}")
send_app_name(dev, last_app) send_app_name(observer.dev, observer.current_app)
except Exception: except Exception:
dev = None observer.dev = None
# App change
if dev is not None:
app = ws.frontmostApplication().localizedName()
if app != last_app:
print(f"App: {app}")
last_app = app
try:
send_app_name(dev, app)
except Exception:
print("Keyboard disconnected")
dev = None
last_app = None
# Pump run loop — notifications fire here and send immediately;
# 2s is enough for connect/disconnect detection
NSRunLoop.currentRunLoop().runUntilDate_( NSRunLoop.currentRunLoop().runUntilDate_(
NSDate.dateWithTimeIntervalSinceNow_(0.25) NSDate.dateWithTimeIntervalSinceNow_(2.0)
) )
if __name__ == "__main__": if __name__ == "__main__":