3

My machine suspends after 5 minutes of inactivity, however I want to execute a command as well after 4 minutes and 30 seconds of inactivity. Is there a way to run a command after 4 minutes and 30 seconds of no full screen window and no keyboard- and mouse activity?

I am running Ubuntu GNOME 15.10 with GNOME 3.18. I have already looked at this question. However, xprintidle is not triggered by a full screen window, only by keyboard- and mouse activity.

11
  • 1
    Possible duplicate of How can a script detect a user's idle time? Dec 9, 2015 at 17:25
  • A 100% match (keyboard/mouse).That's where I got it in the first place. Dec 9, 2015 at 17:26
  • 1
    Ah, wait, you want the script to "pass" if any of your windows is maximized? What about the suspend then? Also: what is the context? Dec 9, 2015 at 17:43
  • 1
    So if an application is fullscreen don't trigger the script? Just to remove my close vote.
    – kos
    Dec 9, 2015 at 17:47
  • 1
    @kos: Yes, spot on! If an application is fullscreen, don't trigger the the script! Because this needs to be executed 30 seconds before a suspend, and a suspend won't take place if an application is not fullscreen.
    – user364819
    Dec 9, 2015 at 18:17

1 Answer 1

0

Running a command after idle time, triggered by both full screen and mouse/keyboard activity

Hi Paranoid Panda, the script below should do as you describe.

The issue was that both having a (any) window full screen, as well as mouse- or keyboard activities should reset the "real" idle time. Since xprintidle cannot be reset from command line, I solved it by subtracting the idle time from itself on the occasion of a full screen window:

  • In a loop, the scripts looks up the current idle time
  • if any window is maximized (checking if any window is as large as the screen's resolution, using both xrandr and wmctrl -lG), the current idle time is subtracted from the idle time, resulting in a correct "real" idle time, even when the window is not full screen any more.

The script

#!/usr/bin/env python3
import subprocess
import time
import sys

idletime = int(sys.argv[1])
command = sys.argv[2]

get = lambda cmd: subprocess.check_output(cmd).decode("utf-8").strip()

def get_res():
    xr = [s for s in get(["xrandr"]).split() \
          if "+0+0" in s][0].split("x"); xr[1] = xr[1].split("+")[0]
    return xr

res = get_res()

def check():
    front = [l for l in get(["xprop", "-root"]).splitlines() \
             if "_NET_ACTIVE_WINDOW(WINDOW):" in l][0].split("#")[-1].strip()
    front = front[:2]+(10-len(front))*"0"+front[2:]
    try:
        wdata = subprocess.check_output(
            ["wmctrl", "-lG"]
            ).decode("utf-8").splitlines()
        match = [l for l in wdata if front in l][0].split()[4:6]
        if match == res:
            return True
        else:
            return False
    except subprocess.CalledProcessError:
        pass

minus = 0; real_idle = 0; t1 = 0; due_1 = False
while True:
    time.sleep(1)
    fscreen = check()
    t2 = int(int(get(["xprintidle"]))/1000)
    if t2 < t1:
        minus = 0; real_idle = 0
    else:
        if fscreen == True:
            minus = t2
    real_idle = t2 - minus
    due_2 = [real_idle > idletime][0]
    if all([real_idle > idletime, due_1 != due_2]):
        subprocess.Popen(["/bin/bash", "-c", command])
    due_1 = due_2
    t1 = t2

To use

  • the script needs wmctrl and xprintidle:

    sudo apt-get install xdotool xprintidle
    
  • Copy the script into an empty file, save it as run_ontime.py

  • Run it by the command:

    python3 /path/to/run_ontime.py <seconds> <command>
    

    where the command needs to be between quotes if it contains spaces. I tested it for example with:

    python3 /path/to/run_ontime.py 10 "firefox askubuntu.com"
    

    which did the job :)

Note

The command is executed once every time the time passes idle time.

You must log in to answer this question.