After fighting with trying to get the amount of time since a user has done something with the system, I’ve determined that CGEventSourceSecondsSinceLastEventType is broken. The documentation indicates that calling it like:
CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGAnyInputEventType)
will tell me how many seconds since the user last moved the mouse, touched the keyboard, etc. The docs say:
The various system and app defined events do not contribute to this event type’s time.
Unfortunately this just isn’t true. In one app I’m working on, I have a timer that fires every 5 seconds and prints the idle time. It starts going up, but then a notification comes in and it resets back to zero without me touching the keyboard. So, this call is almost useless as I need to know when things are idle in order to perform some tasks. While some of you are saying that I can use a Carbon Event Idle Timer, it turns out that they don’t work in background only apps. My only solution is to make the above call using something like:
+ (double) idleTimeInSeconds
{
double idleTime = 0;
double tempIdleTime = 0;
tempIdleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventLeftMouseDown);
if (idleTime == 0 || tempIdleTime < idleTime)
{
idleTime = tempIdleTime;
}
tempIdleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventLeftMouseUp);
if (idleTime == 0 || tempIdleTime < idleTime)
{
idleTime = tempIdleTime;
}
tempIdleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventRightMouseDown);
if (idleTime == 0 || tempIdleTime < idleTime)
{
idleTime = tempIdleTime;
}
tempIdleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventRightMouseUp);
if (idleTime == 0 || tempIdleTime < idleTime)
{
idleTime = tempIdleTime;
}
tempIdleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventMouseMoved);
if (idleTime == 0 || tempIdleTime < idleTime)
{
idleTime = tempIdleTime;
}
tempIdleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventLeftMouseDragged);
if (idleTime == 0 || tempIdleTime < idleTime)
{
idleTime = tempIdleTime;
}
tempIdleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventRightMouseDragged);
if (idleTime == 0 || tempIdleTime < idleTime)
{
idleTime = tempIdleTime;
}
tempIdleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventKeyDown);
if (idleTime == 0 || tempIdleTime < idleTime)
{
idleTime = tempIdleTime;
}
tempIdleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventKeyUp);
if (idleTime == 0 || tempIdleTime < idleTime)
{
idleTime = tempIdleTime;
}
tempIdleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventFlagsChanged);
if (idleTime == 0 || tempIdleTime < idleTime)
{
idleTime = tempIdleTime;
}
tempIdleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventScrollWheel);
if (idleTime == 0 || tempIdleTime < idleTime)
{
idleTime = tempIdleTime;
}
tempIdleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventTabletPointer);
if (idleTime == 0 || tempIdleTime < idleTime)
{
idleTime = tempIdleTime;
}
tempIdleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventTabletProximity);
if (idleTime == 0 || tempIdleTime < idleTime)
{
idleTime = tempIdleTime;
}
tempIdleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventOtherMouseDown);
if (idleTime == 0 || tempIdleTime < idleTime)
{
idleTime = tempIdleTime;
}
tempIdleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventOtherMouseUp);
if (idleTime == 0 || tempIdleTime < idleTime)
{
idleTime = tempIdleTime;
}
tempIdleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventOtherMouseDragged);
return idleTime;
}
Wow, that is freaking ugly, but at least I know exactly when a user event occurred. Feel free to use my code in any way you see fit. I've searched the web and found answers to a lot of my problems, so here's a small contribution back to the community.