Is there a way to automatically minimize a program after it hasn't had focus for a set amount of time?
-
1Nice questtion! Will answer tonight if no one did. Am on mobile currently, will be home late... – Jacob Vlijm Dec 15 '16 at 9:04
-
Hi L42, did you notice the answer? please let me know if all is clear. – Jacob Vlijm Dec 16 '16 at 11:24
-
Yes, thank you! I will test it as soon as I can :) There's a specific program I wish this behaviour for, but your solution implements the behaviour for all programs - is that right? – L42 Dec 16 '16 at 11:44
-
right, but I can easily make it application- specific. Will add it as a second option. – Jacob Vlijm Dec 16 '16 at 11:48
Got it working perfectly, pretty much exactly as you describe.
1. Script to minimize windows after x time without focus
The background script below will minimize windows after an arbitrary time without focus.
The script
#!/usr/bin/env python3
import subprocess
import sys
import time
def getwindowlist():
# get windowlist
try:
return [
l.split()[0] for l in \
subprocess.check_output(["wmctrl", "-l"]).decode("utf-8")\
.splitlines()
]
except subprocess.CalledProcessError:
pass
def getactive():
# get active window, convert to hex for compatibility with wmctrl
wid = str(hex(int(
subprocess.check_output(["xdotool", "getactivewindow"])\
.decode("utf-8"))))
return wid[:2]+str((10-len(wid))*"0")+wid[2:]
# round down on 2 seconds (match needs to be exact)
minitime = (int(sys.argv[1])/2)*2
wlist1 = []
timerlist = []
while True:
time.sleep(2)
wlist2 = getwindowlist()
if wlist2:
# clean up previous windowlist; remove non- existent windows
try:
timerlist = [
wcount for wcount in timerlist if wcount[0] in wlist2
]
except IndexError:
pass
for w in wlist2:
# add new windows, zero record
if not w in wlist1:
timerlist.append([w, 0])
# add two to account(s)
for item in timerlist:
item[1] += 2
active = getactive()
for w in timerlist:
# minimize windows that reach the threshold
if w[1] == minitime:
subprocess.Popen(["xdotool", "windowminimize", w[0]])
# set acoount of active window to zero
w[1] = 0 if w[0] == active else w[1]
wlist1 = wlist2
How to use
The script needs both
wmctrl
andxdotool
:sudo apt-get install wmctrl xdotool
Copy the script into an empty file, save it as
minimize_timer.py
Test- run it with the required time, in seconds (before minimizing), as argument, e.g.:
python3 /path/to/minimize_timer.py 300
...to minimize windows after 5 minutes without focus
If all works fine, add it to startup applications: Dash > Startup Applications > Add. Add the command:
/bin/bash -c "sleep 15 && python3 /path/to/minimize_timer.py 300"
Notes
- Running the script, I couldn't notice any additional burden to the processor.
- The script "rounds" time on two seconds. If a window has focus for e.g. only 0.5 seconds, it might not be noticed as being "focussed".
Explanation
- The script keeps record of all opened windows. Once per two seconds, the script adds two seconds to the windows' "account", unless the window has focus.
- If the window has focus, its account isa set to
0
- If the account reaches a certain threshold, set in the argument, the window is minimized by
xdotool
'swindowminimize
.
If a window no longer exists, it is removed from the record list.
2. Application specific version
The vesrion below will minimize all windows of an arbitrary application after x seconds.
The script
#!/usr/bin/env python3
import subprocess
import sys
import time
# --- set the application below
app = "gedit"
# ---
minitime = (int(sys.argv[1])/2)*2
def get(cmd):
# helper function
try:
return subprocess.check_output(cmd).decode("utf-8").strip()
except subprocess.CalledProcessError:
pass
t = 0
while True:
time.sleep(2)
# first check if app is runing at all (saves fuel if not)
pid = get(["pgrep", app])
if pid:
# if app is running, look up its windows
windows = get(["xdotool", "search", "--all", "--pid", pid]).splitlines()
if windows:
# ...and see if one of its windows is focussed
if get(["xdotool", "getactivewindow"]) in windows:
# if so, counter is set to 0
t = 0
else:
# if not, counter adds 2
t += 2
if t == minitime:
# if counter equals the threshold, minimize app's windows
for w in windows:
subprocess.Popen(["xdotool", "windowminimize", w])
else:
t = 0
How to use
The script needs
xdotool
:sudo apt-get install xdotool
Copy the script into an empty file, save it as
minimize_timer.py
- In the head section, set the application to minimize
Test- run it with the required time, in seconds (before minimizing), as argument, e.g.:
python3 /path/to/minimize_timer.py 300
...to minimize windows after 5 minutes without focus
If all works fine, add it to startup applications: Dash > Startup Applications > Add. Add the command:
/bin/bash -c "sleep 15 && python3 /path/to/minimize_timer.py 300"
-
Hiya. Made a couple of mods which make your code support multiple applications and custom PIDs. Repo is here: github.com/acenturyandabit/mini-miza but thanks for making the original answer :) – Thornkey Sep 3 '18 at 0:45
-
I find
minitime = (int(sys.argv[1])/2)*2
works in Python2(Got 4 if 5 is passed) but not in Python3 (Got 5.0 if 5 is passed). – leaf Mar 11 '20 at 13:11 -