Screensaver over loginwindow


Apple seems to have missed a bit of functionality with their screensaver: when a Mac is sitting at the loginwindow, the screen saver never comes on. If you have a Mac sitting at the loginwindow for many hours a day, and you do not have the Mac set to dim the screen after a short time, you could begin to burn-in the loginwindow's image into the screen!
There may be other reasons you need a screensaver to run at login. Whatever those might be, there's a fairly simple solution.

In Mac OS X 10.0-10.2.8, it was difficult if not impossible to run Apple's screensaver over the login window. Several applications were written to act as psuedo-screen savers: Andrew Mortenson's ScreenPreserver.app and Penn State's PSU Screen Saver are examples. Some people even used the University of Michigan's RSUG's iHook for this.

There were several disadvantages to these apps. Among them:

• After the psuedo-screen saver went away, the logonwindow was not restored as the active application, forcing the user to first click in the window to make in active before they could start entering their username/password.

• Most of these applications did not correctly handle multiple monitors: they would protect the main screen, but any additional monitors would maintain the default Aqua Blue image forever.

• One of these was too sensitive to events - when a Wacom tablet was attached to a machine, the psuedo-screensaver would kick in, then immediately abort, having received some event from the tablet driver. As it happened - the machines that had Wacom tablets were among those that most needed the screensaver to run over the login window!

• They did not behave exactly like the built-in Mac OS screensaver, leading to a small amount of user confusion.

Now with Mac OS X 10.3, it is possible to run Apple's screensaver over the loginwindow. It behaves exactly as one expects. You'll need to install a script that runs the screensaver, and you'll need cron to call it periodically. Here's the script I use (note that no lines should be wrapped - be careful with the line beginning "idleTime="):

#!/bin/sh

# define the path to the screen saver engine
launchPath="/System/Library/Frameworks/ScreenSaver.framework/Versions/A/Resources/ScreenSaverEngine.app"

# check to see if a user is logged into the console
loggedInUser=`/usr/bin/who | /usr/bin/grep console | /usr/bin/cut -d " " -f 1`

if [ "$loggedInUser" = "" ]; then
   # no one is logged in
   # but first check to see if the screen saver is already running!
   procList=`/bin/ps -auxwww | /usr/bin/grep -c "$launchPath"`

   if [ $procList -lt  2 ]; then
      # the screen saver is not already running, let's launch it,
      # but only if the system has been idle at least 5 minutes

      #get the system idle time in seconds
      idleTime=`/usr/sbin/ioreg -c IOHIDSystem | /usr/bin/perl -ane 'if (/Idle/) {$idle=int((pop @F)/1000000000); print $idle,"\n"; last}'`
                
      if [ $idleTime -gt 300 ]; then
         /usr/bin/open "$launchPath"
      fi
   fi
fi

exit 0

Make sure the script is executable.

I have a system cron task that calls this script every 15 minutes. So when a user logs out, the screen saver will start between 5 and 20 minutes after they log out; depending on when they log out.

The screensaver module that will run will be either the default store in the Engine Defaults.plist (see this entry) or the module saved as part of root's preferences (/var/root/Library/Preferences/ByHost/com.apple.screensaver.<mac layer address>.plist). Unless you are running another script to help you manage ByHost preferences, the easiest way to set this preference for all the machines you manage is to edit the "Engine Defaults.plist" (again see this for details) and make it part of your image, or use radmind to manage it.

Note that there is no need to enable the root account to set things up. Everything can be done with sudo from an admin account.

Thanks to this tip from Mac OS X Hints , and this discussion for the last pieces of the puzzle.

(Update 10/9/04)
I've been asked for a little more detail on adding this to cron, so here is one solution:

Login as an administrator, open /Applications/Utilities/Terminal.app, and type

sudo pico -w /etc/crontab

Add the three lines you see at the bottom of this example in red:

# /etc/crontab
SHELL=/bin/sh
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin
HOME=/var/log
#
#minute hour mday month wday who command
#
#*/5 * * * * root /usr/libexec/atrun
#
# Run daily/weekly/monthly jobs.
15 3 * * * root periodic daily
30 4 * * 6 root periodic weekly
30 5 1 * * root periodic monthly
#
# Check to see if we need to run the screen saver over the login window
*/15 * * * * root /path/to/run_screensaver.sh

Replace "/path/to/run_screensaver.sh" with the path to your script. (You should consider putting your management scripts in one location -- a folder named after your organization in the /Library folder would be a good choice.) Type Control-O to save, and Control-X to exit the pico editor.

Make sure the script has the executable bit set:

sudo chmod a+x /path/to/run_screensaver.sh

---

One more note:

This script uses the output of /usr/bin/who to determine if no-one is logged in via the GUI. If no-one, is we launch the screensaver. This arrangement is OK if "Fast User Switching" is off, but if it's on, the output of /usr/bin/who is different and the screensaver will never activate. Since Fast User Switching is off in our environment, I haven't had a need to figure out how to make it work if it's on. Email me if you need this functionality and I'll see if I can figure it out.

----

(Update 12/1/04)
Christian Pagé writes:

"For this to work with FUS, replace

loggedInUser=`/usr/bin/who | /usr/bin/grep console | /usr/bin/cut -d " " -f 1`

with

loggedInUser=`/bin/ls -l /dev/console | awk '{print $3}' | fgrep -v root`

This works only if you never login as root on the console."

I've done a little testing, and this seems to work. Basically, /dev/console is owned by the currently logged-in user, or by root if no user is logged in. (Thus Christian's caveat).
So if you need this to work in an environment with Fast User Switching on, give this modification a try.

Posted: Tue - June 15, 2004 at 07:36 PM      


©