Below a script that switches through application windows. It remembers the last used (= frontmost) window of all running applications, bypassing other windows of the same application.
The script is based on the same principle as the scripts here, but since the script only runs when a key combination is pressed, the last used window (per application) needs to be stored and read outside the script(-'s memory).
How to use
The script uses wmctrl
sudo apt-get install wmctrl
Copy the script below into an empty file, same it as alternative_switcher.py
Add it to a shortcut key combination: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts".
Click the "+" and add the command:
python3 /path/to/alternative_switcher.py
Use it as an alternative switcher with your key combination.
Note
The script switches among "normal" application windows, as defined as: "_NET_WM_WINDOW_TYPE_NORMAL" in the output of the xprop -id <window_id>
command. That means that dialogue windows will be excluded from the window list, as well as Idle
windows for example, which have pid 0.
The script
#!/usr/bin/env python3
import subprocess
import os
import getpass
home = os.environ["HOME"]
lastdir = home+"/.config/alternative_switcher"; wlist = lastdir+"/"+"wlist.txt"
def get(command):
return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")
def get_frontmost():
cmd = "xprop -root"
frontmost = [l for l in get(cmd).splitlines() if\
"ACTIVE_WINDOW(WINDOW)" in l][0].split()[-1]
return frontmost[:2]+"0"+frontmost[2:]
# read last used windowlist
if not os.path.exists(lastdir):
os.makedirs(lastdir)
try:
with open(wlist) as src:
windowlist = eval(src.read())
except (FileNotFoundError, SyntaxError):
windowlist = []
# creating window list: id, application name
w_data = [l.split()[0:7] for l in get("wmctrl -lpG").splitlines()]
[windowlist.remove(w) for w in windowlist if not w[1] in [data[0] for data in w_data]]
windows = [[get("ps -u "+getpass.getuser()+" | grep "+w[2]).split()[-1], w[0]]
for w in w_data if "_NET_WM_WINDOW_TYPE_NORMAL" in get("xprop -id "+w[0])]
# get frontmost window + application
frontmost = [data for data in windows if data[1] == get_frontmost()][0]
[windowlist.remove(item) for item in windowlist if item[0] == frontmost[0]]
# add frontmost to windowlist of last-used application windows
windowlist.insert(0, frontmost)
current_app = frontmost[0]
# determine next application
apps = sorted(set([w[0] for w in windows]))
next_app_i = apps.index(current_app)+1
if next_app_i == len(apps):
next_app_i = 0
next_app = apps[next_app_i]
# find matching window to raise
try:
next_w = [w[1] for w in windowlist if w[0] == next_app][0]
except IndexError:
next_w = [w[1] for w in windows if w[0] == next_app][0]
# write last- window list
with open(wlist, "wt") as out:
out.write(str(windowlist))
# raise next window
cmd = "wmctrl -ia "+next_w
subprocess.Popen(["/bin/bash", "-c", cmd])
File "./a.py", line 37, in <module> arg = apps[0] IndexError: list index out of range