Mac OS X user idle time in Python

I’m still on the quest for the perfect free kiosk app for Mac OS X. I’ve used Plainview to good effect in several exhibits. I’ve used Opera in one, and I’m using Firefox with R-Kiosk in another. Which program to use depends a lot on the nature of the web page(s) to be displayed in the kiosk and the way the user expects to interact with the kiosk.

For the Firefox kiosk, I needed a sure-fire way to reload the home page after a certain amount of idle time. The trouble is that Firefox doesn’t lend itself to be controlled via AppleScript. A lot of poking around led me to learn about AppleScript System Events being able to simulate a keypress, that Option-Home will make Firefox load the home page, and that there’s a really handy little application called Full Key Codes that tells you what the key code is for any key you press on a Mac.

That let me put together this handy little Python script that watches how long it’s been since a user has done something. First it waits until there’s been any user activity at all, then it waits until there’s been no activity for 90 seconds. Then it uses osascript to run a little bit of AppleScript that sends Option-Home (key code 115) to Firefox.

I suspect there’s a way to eliminate the osascript by using the Python objc module, but this is good enough for me…

#!/usr/bin/env python

#========================================================================
#
# idle.py - makes Firefox load home page after user inactivity
#
#       Set the value of 'timeout' to the number of seconds of idle
#       time you want to allow before reloading the home page
#
#       Comment out the calls to status() if you don't want to see any
#       messages
#
#========================================================================

from subprocess import Popen
from time import sleep
from Quartz.CoreGraphics import *

# From /System/Library/Frameworks/IOKit.framework/Versions/A/Headers/hidsystem/IOLLEvent.h
NX_ALLEVENTS = int(4294967295)  # 32-bits, all on.

# Set this value to the number of seconds of idle time before
# resetting Firefox
timeout = 90.0

def status(state, last, idle):
    """Print out some info about where we are """
    print "%10s %.1f %.1f" % (state, last, idle)

def getIdleTime():
    """Get number of seconds since last user input"""
    idle = CGEventSourceSecondsSinceLastEventType(1, NX_ALLEVENTS)
    return idle

def doReset():
    """Use osascript to tell Firefox to reload the home page"""
    reset = """/usr/bin/osascript \
        -e 'tell application "Firefox"' \
        -e ' activate' \
        -e 'end tell' \
        -e 'tell application "System Events"' \
        -e ' key code 115 using option down' \
        -e 'end tell' """
    Popen(reset, shell=True)
    sleep(1)                    # Prevent osascript keypress from triggering below

last = 0.0
idle = 0.0

while True:

    # These two lines can also be at the very end if you don't want to
    # load the home page once when the program starts
    status('--- RESET', last, idle)
    doReset()

    idle = getIdleTime()
    last = idle

    # Wait for user activity
    while idle >= last:
        status('wait', last, idle)
        sleep(1)
        idle = getIdleTime()

    # Wait for idle to become bigger than timeout
    while idle < timeout:
        status('triggered', last, idle)
        sleep(1)
        idle = getIdleTime()
Posted in kiosk, Mac, Museum
One comment on “Mac OS X user idle time in Python
  1. Smitty says:

    This looks great. I’ve got a mac mini running a WordPress site locally with MAMP for a kiosk, and have AppleScript that boots FireFox on start-up – but getting it to reset to home page is a mystery. Please pardon my ignorance, but how do you implement the scripts noted above? How/where does the script need to live? Is it a log-in item? Do I need to AppleScript to run the script above? Any insight/direction you can provide is most appreciated. Thanks.