Skip to content

tapmap.autostart.macos_login_launch

tapmap.autostart.macos_login_launch

Detect macOS login-item launches from the kAEOpenApplication event.

The keyAELaunchedAsLogInItem ('lgit') value distinguishes login-item launches from manual launches.

logger = logging.getLogger(__name__) module-attribute

_K_CORE_EVENT_CLASS = 1634039412 module-attribute

_K_AE_OPEN_APPLICATION = 1868656752 module-attribute

_KEY_AE_PROP_DATA = 1886545012 module-attribute

_KEY_AE_LAUNCHED_AS_LOGIN_ITEM = 1818716532 module-attribute

_delegate = None module-attribute

_LoginLaunchDelegate

Bases: NSObject

Report the macOS login-launch decision once.

Source code in src/tapmap/autostart/macos_login_launch.py
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
class _LoginLaunchDelegate(NSObject):
    """Report the macOS login-launch decision once."""

    def initWithCallback_(self, callback: Callable[[bool], None]) -> _LoginLaunchDelegate | None:
        """Store the launch-decision callback."""
        self = objc.super(_LoginLaunchDelegate, self).init()
        if self is None:
            return None
        self._callback = callback
        self._decided = False
        return self

    def applicationWillFinishLaunching_(self, notification: object) -> None:
        """Register the kAEOpenApplication handler before AppKit's default handling."""
        NSAppleEventManager.sharedAppleEventManager().setEventHandler_andSelector_forEventClass_andEventID_(
            self,
            "handleAppleEvent:withReplyEvent:",
            _K_CORE_EVENT_CLASS,
            _K_AE_OPEN_APPLICATION,
        )

    def handleAppleEvent_withReplyEvent_(self, event: object, reply: object) -> None:
        """Report whether the launch event marks a login-item launch."""
        if self._decided:
            return
        self._decided = True

        is_login_launch = False
        prop_data = event.paramDescriptorForKeyword_(_KEY_AE_PROP_DATA)
        if prop_data is not None:
            is_login_launch = prop_data.enumCodeValue() == _KEY_AE_LAUNCHED_AS_LOGIN_ITEM

        try:
            self._callback(is_login_launch)
        except Exception:
            logger.exception("macOS login-launch callback failed.")

initWithCallback_(callback)

Store the launch-decision callback.

Source code in src/tapmap/autostart/macos_login_launch.py
32
33
34
35
36
37
38
39
def initWithCallback_(self, callback: Callable[[bool], None]) -> _LoginLaunchDelegate | None:
    """Store the launch-decision callback."""
    self = objc.super(_LoginLaunchDelegate, self).init()
    if self is None:
        return None
    self._callback = callback
    self._decided = False
    return self

applicationWillFinishLaunching_(notification)

Register the kAEOpenApplication handler before AppKit's default handling.

Source code in src/tapmap/autostart/macos_login_launch.py
41
42
43
44
45
46
47
48
def applicationWillFinishLaunching_(self, notification: object) -> None:
    """Register the kAEOpenApplication handler before AppKit's default handling."""
    NSAppleEventManager.sharedAppleEventManager().setEventHandler_andSelector_forEventClass_andEventID_(
        self,
        "handleAppleEvent:withReplyEvent:",
        _K_CORE_EVENT_CLASS,
        _K_AE_OPEN_APPLICATION,
    )

handleAppleEvent_withReplyEvent_(event, reply)

Report whether the launch event marks a login-item launch.

Source code in src/tapmap/autostart/macos_login_launch.py
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
def handleAppleEvent_withReplyEvent_(self, event: object, reply: object) -> None:
    """Report whether the launch event marks a login-item launch."""
    if self._decided:
        return
    self._decided = True

    is_login_launch = False
    prop_data = event.paramDescriptorForKeyword_(_KEY_AE_PROP_DATA)
    if prop_data is not None:
        is_login_launch = prop_data.enumCodeValue() == _KEY_AE_LAUNCHED_AS_LOGIN_ITEM

    try:
        self._callback(is_login_launch)
    except Exception:
        logger.exception("macOS login-launch callback failed.")

install(on_decision)

Install login-launch detection before NSApplication.run() starts.

Call on_decision once on the main thread with the detected launch type.

Source code in src/tapmap/autostart/macos_login_launch.py
67
68
69
70
71
72
73
74
75
def install(on_decision: Callable[[bool], None]) -> None:
    """Install login-launch detection before NSApplication.run() starts.

    Call on_decision once on the main thread with the detected launch type.
    """
    global _delegate
    app = NSApplication.sharedApplication()
    _delegate = _LoginLaunchDelegate.alloc().initWithCallback_(on_decision)
    app.setDelegate_(_delegate)