System Idle Time

  • Hello,

    How can I get the system idle time in Cocoa? I want to know how long the
    user has been away from computer. I tried using a timer called
    EventLoopIdleTimer in Carbon, which works fine, but it only gives me the
    idle time of my application. I also read something about HIDIdleTime in the
    archives, but couldn't find any source code examples on how to use it.

    Cheers,
    Mike

    _________________________________________________________________
    Express yourself instantly with MSN Messenger! Download today it's FREE!
    http://messenger.msn.com/
  • Mike Lewis, <partemagua...>, wrote:
    > How can I get the system idle time in Cocoa? I want to know how long the
    > user has been away from computer. I tried using a timer called
    > EventLoopIdleTimer in Carbon, which works fine, but it only gives me the
    > idle time of my application. I also read something about HIDIdleTime in the
    > archives, but couldn't find any source code examples on how to use it.

    I wrote the following a little while back. You'll have to massage it a
    little bit since it uses my JRFoundation, which is currently nonpublic.
    Try compiling it, and fix up the errors, and you should be good to go.

    ---- HIDIdleTime.h ----
    #import <Foundation/Foundation.h>
    @interface HIDIdleTime : NSObject {
    io_registry_entry_t _hidEntry;
    }
    - (uint64_t)idleTime;
    - (unsigned)idleTimeInSeconds;
    @end

    ---- HIDIdleTime ----
    #import "HIDIdleTime.h"
    #import <JRFoundation/JRFoundation.h>

    @implementation HIDIdleTime

    - (id)init {
    self = [super init];
    if( self ) {
      mach_port_t masterPort;
      kern_return_t err = IOMasterPort( MACH_PORT_NULL, &masterPort );
      [NSException raiseKernReturn:err];

      io_iterator_t  hidIter;
      err = IOServiceGetMatchingServices( masterPort,
    IOServiceMatching("IOHIDSystem"), &hidIter );
      [NSException raiseKernReturn:err];
      NSAssert0( hidIter != NULL );

      _hidEntry = IOIteratorNext( hidIter );
      NSAssert0( _hidEntry != NULL );
      IOObjectRelease(hidIter);
    }
    return self;
    }

    - (void)dealloc {
    if( _hidEntry ) {
      kern_return_t err = IOObjectRelease( _hidEntry );
      [NSException raiseKernReturn:err];
      _hidEntry = NULL;
    }
    [super dealloc];
    }

    - (uint64_t)idleTime {
    NSMutableDictionary *hidProperties;
    kern_return_t err = IORegistryEntryCreateCFProperties( _hidEntry,
    (CFMutableDictionaryRef*) &hidProperties, kCFAllocatorDefault, 0 );
    [NSException raiseKernReturn:err];
    NSAssert0( hidProperties != nil );
    [hidProperties autorelease];

    id hidIdleTimeObj = [hidProperties objectForKey:@"HIDIdleTime"];
    NSAssert0( [hidIdleTimeObj isKindOfClass:[NSData class]] ||
    [hidIdleTimeObj isKindOfClass:[NSNumber class]] );
    uint64_t result;
    if( [hidIdleTimeObj isKindOfClass:[NSData class]] ) {
      NSAssert0( [(NSData*)hidIdleTimeObj length] == sizeof( result ) );
      [hidIdleTimeObj getBytes:&result];
    } else {
      ASSERT_CAST( result, long long );
      result = [hidIdleTimeObj longLongValue];
    }

    return result;
    }

    - (unsigned)idleTimeInSeconds {
    #define NS_SECONDS 1000000000 // 10^9 -- number of ns in a second
    return [self idleTime] / NS_SECONDS;
    }

    @end

    | Jonathan 'Wolf' Rentzsch  http://rentzsch.com
    | Red Shed Software          http://redshed.net
    |    "better" necessarily means "different"
  • Here's some GPL code from Adium:

    //Returns the current # of seconds the user has been idle
    - (double)currentIdleTime
    {
        double idleTime = CGSSecondsSinceLastInputEvent(-1);

        //On MDD Powermacs, the above function will return a large value
    when the machine is active (-1?).
        //Here we check for that value and correctly return a 0 idle time.
        if(idleTime >= 18446744000.0) idleTime = 0.0; //18446744073.0

        return(idleTime);
    }

    On Oct 26, 2004, at 1:06 PM, Mike Lewis wrote:

    > Hello,
    >
    > How can I get the system idle time in Cocoa? I want to know how long
    > the user has been away from computer. I tried using a timer called
    > EventLoopIdleTimer in Carbon, which works fine, but it only gives me
    > the idle time of my application. I also read something about
    > HIDIdleTime in the archives, but couldn't find any source code
    > examples on how to use it.
    >
    > Cheers,
    > Mike
    >
    > _________________________________________________________________
    > Express yourself instantly with MSN Messenger! Download today it's
    > FREE! http://messenger.msn.com/
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/<evan.s...>
    >
    > This email sent to <evan.s...>
    >
  • Hmmmm... Not only is that undocumented SPI, but it's also used
    incorrectly.  The comment about MDD PowerMacs is also wildly
    misleading.

    Think about it.  Default C return type with no prototype is...  And you
    cast that to...  And suppose the real returned value is in another
    register...

    Using undocumented SPI is bad, m'kay?

    Mike Paquette

    On Oct 26, 2004, at 12:59 PM, Evan Schoenberg wrote:

    > Here's some GPL code from Adium:
    >
    > //Returns the current # of seconds the user has been idle
    > - (double)currentIdleTime
    > {
    > double idleTime = CGSSecondsSinceLastInputEvent(-1);
    >
    > //On MDD Powermacs, the above function will return a large value
    > when the machine is active (-1?).
    > //Here we check for that value and correctly return a 0 idle time.
    > if(idleTime >= 18446744000.0) idleTime = 0.0; //18446744073.0
    >
    > return(idleTime);
    > }
    >
    > On Oct 26, 2004, at 1:06 PM, Mike Lewis wrote:
    >
    >> Hello,
    >>
    >> How can I get the system idle time in Cocoa? I want to know how long
    >> the user has been away from computer. I tried using a timer called
    >> EventLoopIdleTimer in Carbon, which works fine, but it only gives me
    >> the idle time of my application. I also read something about
    >> HIDIdleTime in the archives, but couldn't find any source code
    >> examples on how to use it.
    >>
    >> Cheers,
    >> Mike
    >>
    >> _________________________________________________________________
    >> Express yourself instantly with MSN Messenger! Download today it's
    >> FREE! http://messenger.msn.com/
    >>
    >> _______________________________________________
    >> Do not post admin requests to the list. They will be ignored.
    >> Cocoa-dev mailing list      (<Cocoa-dev...>)
    >> Help/Unsubscribe/Update your Subscription:
    >> http://lists.apple.com/mailman/options/cocoa-dev/<evan.s...>
    >>
    >> This email sent to <evan.s...>
    >>
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/<mpaque...>
    >
    > This email sent to <mpaque...>
  • On Tue, 26 Oct 2004 18:06:38 +0000, Mike Lewis <partemagua...> wrote:
    > Hello,
    >
    > How can I get the system idle time in Cocoa? I want to know how long the
    > user has been away from computer. I tried using a timer called
    > EventLoopIdleTimer in Carbon, which works fine, but it only gives me the
    > idle time of my application. I also read something about HIDIdleTime in the
    > archives, but couldn't find any source code examples on how to use it.

    In Cocoa?  Beats me.  But it can be done with IOKit and Core
    Foundation.  There's some example code doing this at
    <http://archive.macosxlabs.org/tools_and_scripts/script_archive/scripts/idle
    /stanford_university/idler.html
    >.
    For some reason they've got a JPG of the source instead of text, but
    you'll get the idea.

    --
    Tom Harrington
    <atomicbird...>
  • What should I link to my application? I linked
    ApplicationServices.framework, but still got linker error, undefined symbols
    CGSSecondsSinceLastInputEvent ...

    If this is unofficial and undocumented way, so what is the official way of
    getting the system idle time?

    >
    > Here's some GPL code from Adium:
    >
    > //Returns the current # of seconds the user has been idle
    > - (double)currentIdleTime
    > {
    > double idleTime = CGSSecondsSinceLastInputEvent(-1);
    >
    > //On MDD Powermacs, the above function will return a large value when
    > the machine is active (-1?).
    > //Here we check for that value and correctly return a 0 idle time.
    > if(idleTime >= 18446744000.0) idleTime = 0.0; //18446744073.0
    >
    > return(idleTime);
    > }

    _________________________________________________________________
    Express yourself instantly with MSN Messenger! Download today it's FREE!
    http://messenger.msn.com/
  • On Oct 26, 2004, at 4:31 PM, Mike Paquette wrote:

    > Hmmmm... Not only is that undocumented SPI, but it's also used
    > incorrectly.  The comment about MDD PowerMacs is also wildly
    > misleading.
    >
    In what sense is it used incorrectly? And how is the comment about MDD
    PowerMacs misleading?  Not being combative; I honestly would like to
    understand where you're coming from there.

    > Think about it.  Default C return type with no prototype is...  And
    > you cast that to...  And suppose the real returned value is in
    > another register...
    >
    Sorry, I forgot to include the prototype in my reply:
    extern double CGSSecondsSinceLastInputEvent(unsigned long evType);

    -Evan

    >
    > On Oct 26, 2004, at 12:59 PM, Evan Schoenberg wrote:
    >
    >> Here's some GPL code from Adium:
    >>
    >> //Returns the current # of seconds the user has been idle
    >> - (double)currentIdleTime
    >> {
    >> double idleTime = CGSSecondsSinceLastInputEvent(-1);
    >>
    >> //On MDD Powermacs, the above function will return a large value
    >> when the machine is active (-1?).
    >> //Here we check for that value and correctly return a 0 idle time.
    >> if(idleTime >= 18446744000.0) idleTime = 0.0; //18446744073.0
    >>
    >> return(idleTime);
    >> }
    >>
    >> On Oct 26, 2004, at 1:06 PM, Mike Lewis wrote:
    >>
    >>> Hello,
    >>>
    >>> How can I get the system idle time in Cocoa? I want to know how long
    >>> the user has been away from computer. I tried using a timer called
    >>> EventLoopIdleTimer in Carbon, which works fine, but it only gives me
    >>> the idle time of my application. I also read something about
    >>> HIDIdleTime in the archives, but couldn't find any source code
    >>> examples on how to use it.
    >>>
    >>> Cheers,
    >>> Mike
    >>>
    >>> _________________________________________________________________
    >>> Express yourself instantly with MSN Messenger! Download today it's
    >>> FREE! http://messenger.msn.com/
    >>>
    >>> _______________________________________________
    >>> Do not post admin requests to the list. They will be ignored.
    >>> Cocoa-dev mailing list      (<Cocoa-dev...>)
    >>> Help/Unsubscribe/Update your Subscription:
    >>> http://lists.apple.com/mailman/options/cocoa-dev/<evan.s...>
    >>>
    >>> This email sent to <evan.s...>
    >>>
    >> _______________________________________________
    >> Do not post admin requests to the list. They will be ignored.
    >> Cocoa-dev mailing list      (<Cocoa-dev...>)
    >> Help/Unsubscribe/Update your Subscription:
    >> http://lists.apple.com/mailman/options/cocoa-dev/<mpaque...>
    >>
    >> This email sent to <mpaque...>
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/<evan.s...>
    >
    > This email sent to <evan.s...>
    >
  • Evan Schoenberg, <evan.s...>, wrote:
    >> Hmmmm... Not only is that undocumented SPI, but it's also used
    >> incorrectly.  The comment about MDD PowerMacs is also wildly
    >> misleading.
    >>
    > In what sense is it used incorrectly? And how is the comment about MDD
    > PowerMacs misleading?  Not being combative; I honestly would like to
    > understand where you're coming from there.
    >
    >> Think about it.  Default C return type with no prototype is...  And
    >> you cast that to...  And suppose the real returned value is in
    >> another register...
    >>
    > Sorry, I forgot to include the prototype in my reply:
    > extern double CGSSecondsSinceLastInputEvent(unsigned long evType);

    Reading between the lines, I deduce that maybe
    CGSSecondsSinceLastInputEvent() returns an integer, not a double.

    | Jonathan 'Wolf' Rentzsch  http://rentzsch.com
    | Red Shed Software          http://redshed.net
    |    "better" necessarily means "different"
  • While we are on this subject, is there any way to get the system idle
    time using Unix shell commands?

    Thanks,

    Don

    At 8:59 PM -0700 2004/10/26, <cocoa-dev-request...> wrote:
    > From: "Jonathan 'Wolf' Rentzsch" <nil...>
    > Subject:
    > To:
    > Message-ID: <20041027030427.F27273C45F8...>
    > Content-Type: text/plain; charset="US-ASCII"
    > Evan Schoenberg, <evan.s...>, wrote:
    >>> Hmmmm... Not only is that undocumented SPI, but it's also used
    >>> incorrectly.  The comment about MDD PowerMacs is also wildly
    > ...snip...
    >>>
    >> Sorry, I forgot to include the prototype in my reply:
    >> extern double CGSSecondsSinceLastInputEvent(unsigned long evType);
    >
    > Reading between the lines, I deduce that maybe
    > CGSSecondsSinceLastInputEvent() returns an integer, not a double.

    --
    Donald S. Hall, Ph.D.
    Apps & More Software Design, Inc.
    <don...>
    http://www.appsandmore.com
  • On Tue, 26 Oct 2004 21:16:29 -0500, Evan Schoenberg <evan.s...> wrote:
    >
    > On Oct 26, 2004, at 4:31 PM, Mike Paquette wrote:
    >
    >> Hmmmm... Not only is that undocumented SPI, but it's also used
    >> incorrectly.  The comment about MDD PowerMacs is also wildly
    >> misleading.
    >>
    > In what sense is it used incorrectly? And how is the comment about MDD
    > PowerMacs misleading?  Not being combative; I honestly would like to
    > understand where you're coming from there.

    I'm guessing that he is contractually obliged not to talk about the
    implementation details of the windowserver, and thus he has to be
    careful as to what he says? :-)

    >> Think about it.  Default C return type with no prototype is...  And
    >> you cast that to...  And suppose the real returned value is in
    >> another register...
    >>
    > Sorry, I forgot to include the prototype in my reply:
    > extern double CGSSecondsSinceLastInputEvent(unsigned long evType);

    Will HIDIdleTime work for you? Property of IOHIDSystem, quite easy to
    get -- seems to be in nanoseconds.

    -- Finlay
  • I found the following at Stanford about 6~7 months ago...

    --Jerry

    /*****************************************
      * idler.c
      *
      * Uses IOKit to figure out the idle time of the system. The idle time
      * is stored as a property of the IOHIDSystem class; the name is
      * HIDIdleTime. Stored as a 64-bit int, measured in ns.
      *
      * The program itself just prints to stdout the time that the computer
    has
      * been idle in seconds.
      *
      * Compile with gcc -Wall -framework IOKit -framework Carbon idler.c -o
      * idler
      *
      * Copyright (c) 2003, Stanford University
      * All rights reserved.
      *
      * Redistribution and use in source and binary forms, with or without
      * modification, are permitted provided that the following conditions
    are
      * met:
      * Redistributions of source code must retain the above copyright
    notice,
      * this list of conditions and the following disclaimer.
      *
      * Redistributions in binary form must reproduce the above copyright
    notice,
      * this list of conditions and the following disclaimer in the
    documentation
      * and/or other materials provided with the distribution.
      *
      * Neither the name of Stanford University nor the names of its
    contributors
      * may be used to endorse or promote products derived from this software
      * without specific prior written permission.
      *
      * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    "AS
      * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO,
      * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
    PARTICULAR
      * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
      * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
      * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
    OF
      * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
      * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
      * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      */

    #include <CoreFoundation/CoreFoundation.h>
    #include <CoreServices/CoreServices.h>
    #include <IOKit/IOKitLib.h>

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>

    /* 10^9 --  number of ns in a second */
    #define NS_SECONDS 1000000000

    int main(int argc, char **argv) {
      mach_port_t masterPort;
      io_iterator_t iter;
      io_registry_entry_t curObj;

      IOMasterPort(MACH_PORT_NULL, &masterPort);

      /* Get IOHIDSystem */
      IOServiceGetMatchingServices(masterPort,
                     IOServiceMatching("IOHIDSystem"),
                     &iter);
      if (iter == 0) {
        printf("Error accessing IOHIDSystem\n");
        exit(1);
      }

      curObj = IOIteratorNext(iter);

      if (curObj == 0) {
        printf("Iterator's empty!\n");
        exit(1);
      }

      CFMutableDictionaryRef properties = 0;
      CFTypeRef obj;

      if (IORegistryEntryCreateCFProperties(curObj, &properties,
        kCFAllocatorDefault, 0) ==
          KERN_SUCCESS && properties != NULL) {

        obj = CFDictionaryGetValue(properties, CFSTR("HIDIdleTime"));
        CFRetain(obj);
      } else {
        printf("Couldn't grab properties of system\n");
        obj = NULL;
      }

      if (obj) {
        uint64_t tHandle;

        CFTypeID type = CFGetTypeID(obj);

        if (type == CFDataGetTypeID()) {
          CFDataGetBytes((CFDataRef) obj,
               CFRangeMake(0, sizeof(tHandle)),
               (UInt8*) &tHandle);
        }  else if (type == CFNumberGetTypeID()) {
          CFNumberGetValue((CFNumberRef)obj,
                 kCFNumberSInt64Type,
                 &tHandle);
        } else {
          printf("%d: unsupported type\n", (int)type);
          exit(1);
        }

        CFRelease(obj);

        // essentially divides by 10^9
        tHandle >>= 30;
        printf("%qi\n", tHandle);
      } else {
        printf("Can't find idle time\n");
      }

      /* Release our resources */
      IOObjectRelease(curObj);
      IOObjectRelease(iter);
      CFRelease((CFTypeRef)properties);

      return 0;
    }
  • Yes, this is the same code Tom Harrington referred to. It works for me!
    Thanks for everybody who tried to help.

    Cheers,
    Mike

    >
    > I found the following at Stanford about 6~7 months ago...
    >
    > --Jerry
    >
    > /*****************************************
    >   * idler.c
    >   *
    >   * Uses IOKit to figure out the idle time of the system. The idle time
    >   * is stored as a property of the IOHIDSystem class; the name is
    >   * HIDIdleTime. Stored as a 64-bit int, measured in ns.
    >   *

    _________________________________________________________________
    Don't just search. Find. Check out the new MSN Search!
    http://search.msn.com/
previous month october 2004 next month
MTWTFSS
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Go to today