2

How would one implement some kind of background process that constantly (or in short intervals) checks if the user is interacting with the system, that is, plain and simply, using the computer? The obvious way is to check for user-generated events of any kind, such as key presses, mouse moves and mouse clicks, etcetera. It is straightforward to capture events within a certain application because those are usually automatically supplied via the application's event loop, but how does one achieve this system-wide, i.e. irrespective of what application is in front/has focus? How is this done elegantly, so such a process does not consume too much system resources?

I'm interested in this in general, but obviously there is a different way for each platform – a cross-platform way (Java) would be ideal, but my platform of choice is Mac OS X (Cocoa).

Niels Heidenreich
  • 1,257
  • 1
  • 9
  • 20
  • Apparently, what I am looking for is "system idle time", which is something that is stored at system level and may be read through appropriate APIs/techniques… – Niels Heidenreich Aug 22 '11 at 20:06
  • The **X11** (e.g. Linux) version of this question at [detecting keyboard, mouse activity in linux](https://stackoverflow.com/questions/222606/detecting-keyboard-mouse-activity-in-linux) has a real answer while this question does not. – Adam Katz Apr 15 '15 at 20:47

3 Answers3

3

The idea by Thomas Langston to check out how pidgin (libpurple) does it was very helpful. I downloaded the source code and found this --

In pidgin-2.10.0/pidgin/gtkidle.c starting on line 46:

/*
* Get the number of seconds the user has been idle.  In Unix-world
* this is based on the X Windows usage.  In MS Windows this is
* based on keyboard/mouse usage information obtained from the OS.
* In MacOS X, this is based on keyboard/mouse usage information
* obtained from the OS, if configure detected IOKit.  Otherwise,
* MacOS X is handled as a case of X Windows.
*
* In Debian bug #271639, jwz says:
*
* Purple should simply ask xscreensaver how long the user has been idle:
*   % xscreensaver-command -time
*   XScreenSaver 4.18: screen blanked since Tue Sep 14 14:10:45 2004
*
* Or you can monitor the _SCREENSAVER_STATUS property on root window #0.
* Element 0 is the status (0, BLANK, LOCK), element 1 is the time_t since
* the last state change, and subsequent elements are which hack is running
* on the various screens:
*   % xprop -f _SCREENSAVER_STATUS 32ac -root _SCREENSAVER_STATUS
*   _SCREENSAVER_STATUS(INTEGER) = BLANK, 1095196626, 10, 237
*
* See watch() in xscreensaver/driver/xscreensaver-command.c.
*
* @return The number of seconds the user has been idle.
*/

That file contains the code to handle this for the different platforms.

Niels Heidenreich
  • 1,257
  • 1
  • 9
  • 20
  • On Mac OS X (10.4 and later), the easiest way seems to be this call: CGEventSourceSecondsSinceLastEventType() http://developer.apple.com/library/mac/#documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventSourceSecondsSinceLastEventType – Niels Heidenreich Aug 22 '11 at 20:43
  • **Nope!** Both of jwz's methods merely indicate when the screensaver last changed state (2004/09/14 == 1095196626) rather than when the system last saw user activity. _Pidgin doesn't actually use this method_. Instead, it uses [XScreenSaverQueryInfo](http://linux.die.net/man/3/xscreensaverqueryinfo) as [proposed](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=271639#20) by Luke Schierer, which jwz pooh-poohed as "extremely flaky" even though nobody has (modern) examples of it not working. – Adam Katz Apr 15 '15 at 17:05
1

I don't know the explicit answer, but I know where I'd go to look. Pidgin and other open source IM clients have to know if the user is idle. I'm sure you could use a similar method to determine user activity.

Thomas Langston
  • 3,743
  • 1
  • 25
  • 41
1

Capturing a system event like a key press or mouse movement is not the realm of any one language as such. This is basically what the OS manages, and because you want some mechanism which has to listen to system-wide events , you must depend on OS provided API in one or another way. For example , on Windows ,you get the Win API that can be used from within a Java program to listen to system wide events. But this will be specific to Win API, so for Mac OS , it will be a different version of API.

Bhaskar
  • 7,443
  • 5
  • 39
  • 51