My script needs to know when user been idle for x seconds.
Hi cirno,
I think the only way to check idle time is to monitor application ScreenSaverEngine. You can’t find out how many seconds the computer has been idle at a certain time though. You can find out how many seconds of idle time from the time ScreenSaverEngine runs depending on the settings in the preferences.
What are you trying to do?
gl,
Hi cirno,
you can check the idle time with this line:
set idleTime to (do shell script "ioreg -c IOHIDSystem | perl -ane 'if (/Idle/) {$idle=(pop @F)/1000000000; print $idle,\"\";last}'")
Hi Stefan,
I ran this:
delay 60
set idleTime to (do shell script "ioreg -c IOHIDSystem | perl -ane 'if (/Idle/) {$idle=(pop @F)/1000000000; print $idle,\"\";last}'")
and still got zero. I didn’t touch the computer when running it. Is that suppose to be right? Maybe it’s my OS.
Thanks,
Hi kel,
strange, I tried this and it counts up
repeat
set idleTime to (do shell script "ioreg -c IOHIDSystem | perl -ane 'if (/Idle/) {$idle=(pop @F)/1000000000; print $idle,\"\";last}'")
display dialog idleTime as string giving up after 5
end repeat
I tried the repeat and still got zeros. Must be my system.
Thanks,
A few months back when this script example was first posted I also got a zero result.
I was watching a long QuickTime movie while I was scripting and experimenting with this script command. As long as the QuickTime movie was playing the result was zero, but once I quit the QuickTime player application I started getting the correct result. So I would have to assume some applications keep the idle time zeroed out while executing.
Hi.
I get kel’s results with my Jaguar system and Stefan’s with Tiger.
I’ve been looking at the “ioreg -c IOHIDSystem” results without the Perl modifications. With Tiger, the several “HIDIdleTime” entries are in decimal format; whereas with Jaguar, they’re in hexadecimal format and angle-bracketed: eg. “HIDIdleTime” = <00000000043e9207>.
The version of the repeat test below seems to work with Jaguar, but since I don’t understand Perl and don’t know which “HIDIdleTime” entry is the right one, I don’t know if the results are correct. I also don’t know if it works with Panther. The displayed idle times increment by nearly six seconds each time on my Jaguar machine, but this appears to be due to an inaccuracy in display dialog’s giving up after timing. If I use delay 5 instead and shunt the results into a list instead of displaying them, they’re more nearly five seconds apart.
on hexToNum(h)
set hexChrs to "0123456789abcdef"
set n to 0
set astid to AppleScript's text item delimiters
repeat with i from 1 to (count h)
set AppleScript's text item delimiters to character i of h
set n to n * 16 + (count text item 1 of hexChrs)
end repeat
set AppleScript's text item delimiters to astid
return n
end hexToNum
repeat
set idleTime to (do shell script "ioreg -c IOHIDSystem | perl -ane 'if (/Idle/) {$idle=(pop @F); print $idle,\"\";last}'")
if (idleTime begins with "<") then set idleTime to hexToNum(text 2 thru -2 of idleTime)
set idleTime to idleTime / 1.0E+9
display dialog idleTime as string giving up after 5
end repeat
No doubt some shell script expert here will be able to dispense with the hexToNum() handler.
May I help you
repeat
set idleTime to (do shell script "ioreg -c IOHIDSystem | perl -ane 'if (/Idle/) {$idle=(pop @F); print $idle,\"\";last}'")
if (idleTime begins with "<") then set idleTime to (do shell script "perl -e 'printf(hex(\"" & (text 2 thru -2 of idleTime) & "\"))'") as number
set idleTime to idleTime / 1.0E+9
display dialog idleTime as string giving up after 5
end repeat
Hi Nigel and Stefan,
It works! Now testing it in an idle handler.
Thanks,
I worked great predicting the screen saver.
I knew it.
But is there a way to combine all the code into one shell script? As it stands, it’s faster with my handler than with the second shell script.
To be fair, though, the handler’s tailored to the current situation and assumes that the input’s correct, that any letters are lower case, and that the hexadecimal string represents an unsigned number. Here’s a more robust “ though still fast “ HexToNum handler. (In fact, since the first shell script returns Unicode text, this handler’s even faster in the current situation than the original. )
on hexToNum from h given sign:sign
script o
property hexChrs : "0123456789abcdef" as Unicode text -- TIDs are case insensitive with Unicode.
on getHexVal(c)
set AppleScript's text item delimiters to c
set v to (count text item 1 of hexChrs)
if (v is 16) then error "Non-hex character(s)."
return v
end getHexVal
end script
set astid to AppleScript's text item delimiters
try
set h to h as Unicode text -- Speeds up use of TIDs with Unicode 'hexChrs' in o.
tell o to set n to getHexVal(character 1 of h)
if (sign) and (n > 7) then set n to n - 16
repeat with i from 2 to (count h)
tell o to set n to n * 16 + getHexVal(character i of h)
end repeat
on error msg number errNum
set AppleScript's text item delimiters to astid
error "hexToNum handler: " & msg number errNum
end try
set AppleScript's text item delimiters to astid
return n
end hexToNum
hexToNum from "00000000043e9207" without sign
--> 71209479
hexToNum from "FFFE" without sign
--> 65534
hexToNum from "FFFE" with sign
--> -2
Hi Nigel,
my knowledge about Perl is almost zero.
I found the conversion syntax accidently a few weeks ago.
So I investigated a bit and found out, that Perl natively doesn’t provide these kind of negative hex numbers.
e.g. in Perl hex(-FF) is decimal -255 not - 1
But it’s quite easy to calculate it in AppleScript
Here is my routine with correct negative hex numbers like in your routine.
The negative number is also calculated properly when entered a 3-digit hex number
on hexToDec from h given sign:sign
set n to (do shell script "perl -e 'printf(hex(\"" & h & "\"))'") as number
tell (((count h as string) + (count h as string) mod 2) ^ 8 as integer) to if sign and (n > it / 2 - 1) then set n to n - it
return n
end hexToDec
hexToDec from "00000000043e9207" without sign
--> 71209479
hexToDec from "FFFE" without sign
--> 65534
hexToDec from "FFFE" with sign
--> -2
PS: Your script is incredibly faster than this
Now I can start my screen saver when the machine has been inactive under 5 minutes.
property sse_start : 2 * minutes
--
on idle
set idleTime to (do shell script "ioreg -c IOHIDSystem | perl -ane 'if (/Idle/) {$idle=(pop @F); print $idle,\"\";last}'")
if (idleTime begins with "<") then
set idleTime to hexToNum from (text 2 thru -2 of idleTime) without sign
end if
set idleTime to idleTime / 1.0E+9
-- do something with idleTime
tell application "System Events" to set _e to exists process "ScreenSaverEngine"
if idleTime > sse_start and not _e then
tell application "ScreenSaverEngine" to activate
end if
return 2
end idle
--
on hexToNum from h given sign:sign
script o
property hexChrs : "0123456789abcdef" as Unicode text -- TIDs are case insensitive with Unicode.
--
on getHexVal(c)
set AppleScript's text item delimiters to c
set v to (count text item 1 of hexChrs)
if (v is 16) then error "Non-hex character(s)."
return v
end getHexVal
end script
--
set astid to AppleScript's text item delimiters
try
set h to h as Unicode text -- Speeds up use of TIDs with Unicode 'hexChrs' in o.
tell o to set n to getHexVal(character 1 of h)
if (sign) and (n > 7) then set n to n - 16
repeat with i from 2 to (count h)
tell o to set n to n * 16 + getHexVal(character i of h)
end repeat
on error msg number errNum
set AppleScript's text item delimiters to astid
error "hexToNum handler: " & msg number errNum
end try
set AppleScript's text item delimiters to astid
return n
end hexToNum
Thanks a lot,

Here is my routine with correct negative hex numbers like in your routine.
The negative number is also calculated properly when entered a 3-digit hex number
Wow! That’s quite a one-liner in the middle!. Unfortunately, it doesn’t give the correct results for me when there are odd numbers of characters in the hex string. I’ve had more success with this version:
on hexToDec from h given sign:sign
set n to (do shell script "perl -e 'printf(hex(\"" & h & "\"))'") as number
tell 16 ^ (count h) to if (sign) and (n > it / 2 - 1) then set n to n - it
return n
end hexToDec
hexToDec from "00000000043e9207" without sign
--> 71209479
hexToDec from "FFFE" without sign
--> 65534
hexToDec from "FFE" with sign
--> -2
PS: Your script is incredibly faster than this
That’s the problem with shell scripts. The code they execute may be lightning fast, but there’s quite a time overhead in calling them.
But unless there are hundreds of hex-to-number conversions to do, there’s little practical time difference between your handler and mine. And yours is certainly shorter.

Thanks a lot,
More hours of harmless fun to take the mind off writing Christmas cards.
The code “set idleTime to (do shell script “ioreg -c IOHIDSystem | perl -ane ‘if (/Idle/) {$idle=(pop @F)/1000000000; print $idle,"";last}’”) as number” works well in the Script Editor or in an application with an idle handler. I never got it to work in Cronnix (/usr/bin/osascript /pathto script.scpt.) Any ideas?