"""Run blocking work off the GTK main loop.""" from __future__ import annotations import threading from typing import Callable from gi.repository import GLib def run_async(work: Callable[[], object], done: Callable[[object, Exception | None], None]) -> None: """Execute `work` in a thread; call `done(result, error)` on the main loop.""" def target(): try: result, error = work(), None except Exception as e: # surfaced to the UI as a toast result, error = None, e GLib.idle_add(lambda: (done(result, error), False)[1]) threading.Thread(target=target, daemon=True).start()