Whats the best way to detect if a user is currently at their computer, ie using it in some way. We have an application that should only issue notifications (banner notifications with a close button) if the user is at their computer.
For example, imagine a stock trading application that alerts the user to various time sensitive information that might be relevant for only a few minutes. If the user is away from their computer, they don't want to find 20 un-actioned alerts to dismiss.
If linking against ApplicationServices or higher, try:
CFTimeInterval idleTime = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGAnyInputEventType);
Time since last event for an event source.
The kCGAnyInputEventType eventType will report the last timestamp for any input event, keyboard, mouse, or tablet. The various system and app defined events do not contribute to this event type's time.
Again, a program or application posting from within a login session should use the kCGEventSourceStateCombinedSessionState.
A user space device driver interpreting hardware state and generating events should use the kCGEventSourceStateHIDSystemState.
CG_EXTERN CFTimeInterval CGEventSourceSecondsSinceLastEventType( CGEventSourceStateID source, CGEventType eventType ) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
Technicaly I don't know how to watch for inactivity but I think you could use timeout for notifications to close themselves after a time interval and/or to limit displayed notifications to few, so the newest one would automaticaly close the oldest one.
From the apple documentation:
Note: It the user wakes more than 15 minutes after a scheduled notification is scheduled to fire, it is discarded. If the notification repeats with an interval less than 15 minutes, then it expires in 1 minute. Expired notifications are just discarded, unless they repeat, in which case, they stay in the scheduled list and just fire again later.
You could, instead, check the user's idle time. Assuming the user leaves her computer and walks away, IOKit will report idle time on the HID (Human Interface Devices). Code would look something like:
int64_t getIdleTime(void) {
io_iterator_t iter;
int64_t idle = 0;
// Step 1: Prepare a matching dictionary for "IOHIDSystem", which is the I/O Kit
// class which we will query
if (IOServiceGetMatchingServices
(kIOMasterPortDefault, IOServiceMatching("IOHIDSystem"), &iter) == KERN_SUCCESS)
{
io_registry_entry_t entry = IOIteratorNext(iter);
// Step 2: If we get the classes, get the property:
if (entry) {
CFMutableDictionaryRef dict;
// Query the HIDIdleTime property, if present.
if (IORegistryEntryCreateCFProperties(entry, &dict, kCFAllocatorDefault, 0) == KERN_SUCCESS)
{
CFNumberRef prop = (CFNumberRef) CFDictionaryGetValue(dict, CFSTR("HIDIdleTime"));
if (prop) {
int64_t nsIdle;
// Value is in Nanoseconds, you might want to convert
if (CFNumberGetValue(prop, kCFNumberSInt64Type, &nsIdle)) {
idle = (nsIdle / 1000000000);
}
}
CFRelease(dict); // Be nice. Clean up
}
IOObjectRelease(entry); // as well as here..
}
IOObjectRelease(iter); // and here..
}
return idle;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With