I need to run a script after a period of user inactivity. For that I use the wonderful program xautolock.

Now, I also need to run another script when the activity is resumed (e.g. mouse is moved or a key is pressed).

How do I do that? Any sort of an anti-xautolock? An xautoUNlock?

Or, perhaps, any other easy way to catch the moment when the "idleness" stops?

  • 2
    Why would you want a screen locker that doesn't require unlocking? Just use a screensaver. – jasonwryan Nov 14 '13 at 1:33
  • 1
    xscreensaver will do just as you want, you don't need xautolock – number5 Nov 14 '13 at 1:35
  • 1
    I need to run a pair of custom scripts: the first is run after the idle timeout (i.e. in place of a regular screensaver) and the 2nd is run when activity is resumed. – Alexander Shcheblikin Nov 14 '13 at 1:38
  • 1
    OK, I figured I could configure xscreensaver to launch an arbitrary program (and have it killed on user activity) but how do I tell the xscreensaver not to blank the screen and have the screen updated as per normal? – Alexander Shcheblikin Nov 14 '13 at 15:07

I wrote the following script to check for idle and update the session idle status with systemd-logind accordingly. (Normally this would be done by the session manager, but I don't run one.) This lets systemd put the system to sleep automatically (based on IdleAction and IdleActionSec in /etc/systemd/logind.conf), with consideration of both X11 and ssh logins when determining whether the system is idle. Based partly on this and this.

You could modify the login1_idle class to run whatever scripts you want.


import ctypes
import os
import dbus
import time

# Timing parameters, in s
idle_threshold = 60 # Amount of idle time required to consider things truly idle
check_interval = 50 # How often to check the X server idle indication

class login1_idle:
  def __init__(self):
    self.flag = 0
    bus = dbus.SystemBus()
    seat = bus.get_object('org.freedesktop.login1',
                           + os.environ['XDG_SEAT'])
    active_session = seat.Get('org.freedesktop.login1.Seat',
    session_obj_path = active_session[1]
    self.session = bus.get_object('org.freedesktop.login1', session_obj_path);

  def on_busy(self):
    self.flag = 0

  def on_idle(self):
    self.flag = 1

class XScreenSaverInfo(ctypes.Structure):
  """ typedef struct { ... } XScreenSaverInfo; """
  _fields_ = [('window',      ctypes.c_ulong), # screen saver window
              ('state',       ctypes.c_int),   # off,on,disabled
              ('kind',        ctypes.c_int),   # blanked,internal,external
              ('since',       ctypes.c_ulong), # milliseconds
              ('idle',        ctypes.c_ulong), # milliseconds
              ('event_mask',  ctypes.c_ulong)] # events

xlib = ctypes.cdll.LoadLibrary('libX11.so')
display = xlib.XOpenDisplay(os.environ['DISPLAY'])
xss = ctypes.cdll.LoadLibrary('libXss.so.1')
xss.XScreenSaverAllocInfo.restype = ctypes.POINTER(XScreenSaverInfo)
xssinfo = xss.XScreenSaverAllocInfo()

idle = login1_idle()

while True:
  xss.XScreenSaverQueryInfo(display, xlib.XDefaultRootWindow(display), xssinfo)

  #print "idle: %d ms" % xssinfo.contents.idle

  if xssinfo.contents.idle > idle_threshold * 1000 and not idle.flag:
    print time.strftime('%c') + " doing on_idle"

  elif xssinfo.contents.idle < idle_threshold * 1000 and idle.flag:
    print time.strftime('%c') + " doing on_busy"

  #print idle.session.Get('org.freedesktop.login1.Session',
  #                       'IdleHint',
  #                       dbus_interface='org.freedesktop.DBus.Properties')


Another similar question with a C/bash implementation is Run a command when system is idle and when is active again.

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.