Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Only show notification if user is at computer

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.

like image 716
Jay Avatar asked Oct 10 '12 00:10

Jay


3 Answers

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;

like image 152
geowar Avatar answered Nov 13 '22 18:11

geowar


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.

like image 7
JanT Avatar answered Nov 13 '22 18:11

JanT


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;
}
like image 2
Technologeeks Avatar answered Nov 13 '22 18:11

Technologeeks