Not literally what you asked for, but if you have a key combination that would automatically recognize both the gnome-terminal
-window and the window directly below it, you could switch (toggle) between the two quickly without further effort.
The setup does exactly that: If (and only if) either the active window or the window directly below it is a gnome-terminal
window, the script makes them switch places, as shown in the images. I left a few irrelevant windows to illustrate they don't take part in the toggle:
Having a gnome-terminal
window on top of a gedit
window:
Pressing the shortcut:
Press it again:
And so on. As mentioned, this will only happen if either one of the topmost windows belongs to gnome-terminal
.
How to set up
The script(s) need wmctrl
sudo apt-get install wmctrl
Save both scripts below in one and the same directory, since one of the scripts imports functions from the other:
Script 1
to be saved as (exactly) z_list.py
:
This is actually a background script, keeping track of the z-order of windows. The z-order cannot be determined by the "normal" tools like wmctrl
or xdotool
. Running a simple script to keep track of the currently active window, will give us the z-order however.
#!/usr/bin/env python3
import subprocess
import time
import os
rootdata = os.environ["HOME"]+"/.focus_history"
def current_windows():
try:
return subprocess.check_output(["wmctrl", "-lp"]).decode("utf-8")
except subprocess.CalledProcessError:
pass
def convert_format(w_id):
return w_id[:2]+(10-len(w_id))*"0"+w_id[2:]
def read_data():
return open(rootdata).read().splitlines()
def get_top(wlist):
try:
top = convert_format([l.split("#")[-1].strip() for l in \
subprocess.check_output(["xprop", "-root"]).decode("utf-8").splitlines() \
if "_NET_ACTIVE_WINDOW(WINDOW)" in l][0])
return [l for l in wlist if top in l][0]
except IndexError:
pass
if __name__ == "__main__":
open(rootdata, "wt").write("This is an empty line")
while True:
time.sleep(0.5)
wdata = current_windows()
if wdata != None:
wlist = wdata.splitlines()
# get frontmost window (as in wmctrl -lG)
top = get_top(wlist)
oldlist = read_data()
if not any([top == oldlist[0], top == None]):
# clean up closed windows
[oldlist.remove(l) for l in oldlist if not l.split()[0] in wdata]
# remove possible other mentions of the active window
[oldlist.remove(l) for l in oldlist if l.startswith(top.split()[0])]
open(rootdata, "wt").write(("\n").join([top]+oldlist))
Script 2
to be saved as toggle_terminal.py
:
As mentioned, save this script in one and the same directory, together with z_list.py
.
#!/usr/bin/env python3
import subprocess
import z_list
try:
termpid = subprocess.check_output(["pidof", "gnome-terminal"]).decode("utf-8").strip()
wlist = z_list.read_data(); top = wlist[0]; second = wlist[1]
if any([termpid in top, termpid in second]):
subprocess.Popen(["wmctrl", "-ia", second.split()[0]])
except subprocess.calledProcessError:
pass
How to use
Since the background script keeps track of active windows and creates the z-order that way, it needs to run before you open (at least) the windows you'd like to toggle, preferably as a Startup Application.
To test:
Open a terminal window, run the background script by the command:
python3 /path/to/z_list.py
Open a new terminal window and (e.g.) a gedit
window. Focus the gedit
window and open a new terminal window on top of it. Then run in the terminal window the command:
python3 /path/to/toggle_terminal.py
The windows should change places (order). Unfortunately you won't be able to run the command again (in the terminal) to bring the terminal window to top again, since the gedit
window is now active :). You may assume however it will work from a shortcut key.
If all works fine, make the setup permanent:
Add z_list.py
to Startup Applications: Dash > Startup Applications > Add the command:
/bin/bash -c "sleep 15 && python3 /path/to/z_list.py"
Add script 2 to a shortcut key combination: choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command:
python3 /path/to/toggle_terminal.py