Search code examples
objective-cmacososx-lionosx-mountain-lionpython-idle

Notification after user becomes idle on OS X?


What's the best way of detecting when a user has been idle for X amount of time, and then detect when the user becomes immediately active?

I know there's NSWorkspace which provides will/did sleep/wake notifications, but I can't rely on that because the sleep setting is usually about ~15 minutes to never. I need to be able to detect if the user's been idle for ~1-2 minutes.

This answer provides a way to get the idle time. I'd like to avoid polling if possible.


Solution

  • Polling is your only option, to my knowledge. As user1118321 points out, polling every O(minutes) is unlikely to cause any problems, performance or otherwise.

    If your app has a GUI and receives UI events anyway, you could install a handler via +[NSEvent addLocalMonitorForEventsMatchingMask:handler:] that resets your timer on each event. That'll help reduce if not eliminate polls when the user is consistently active, in your own app at least.

    Once you've determined that the user has been idle long enough, you could then install a global event tap to watch for the next event. See for example -[NSEvent addGlobalMonitorForEventsMatchingMask:handler:].

    Note: you should use CGEventSourceSecondsSinceLastEventType if at all possible rather than poking into the IO registry. It's a formal, supported API and may be more efficient. Not to mention it's way simpler. There's also UKIdleTimer though it relies on Carbon, so may not be applicable.