To my own surprise, it works quite nicely, As long as you do not have too many other things on your desktop.
I worked with it for a while, and it seems a weird, but strangely enough nice alternative to frequent workspace switches. Refreshing for its simplicity.
The solution is actually pretty much what you describe:
Pressing a key combination will "box" the window on your desktop, from a window:
into an icon, with the application's appearance:
Double click the icon, and the window will re- appear and the icon will vanish.
How it works
The short story (explanation):
.desktop file will add a number of additional arguments arguments, such as the window id, the (file-) name of the
.desktop file is then made executable, to make it a double- clickable object.
.desktop file is double clicked, the window is (re-) mapped, the
.desktop file is removed from your desktop.
How to set up
Like practically always, when you want to play around with windows, the script needs both
sudo apt-get install xdotool wmctrl
- Create the directory
~ stands for your home directory)
Copy the script below into an empty file, save it as
windowbox (no extension) in
# --- On Unity, there is a (y-wise) deviation in window placement
# set to zero for other window managers
deviation = 28
args = sys.argv[1:]
get = lambda cmd: subprocess.check_output(cmd).decode("utf-8").strip()
# get the localized path to the Desktop folder
home = os.environ["HOME"]
dr_file = home+"/.config/user-dirs.dirs"
return [home+"/"+ l.split("/")[-1].strip() \
for l in open(dr_file).readlines() \
if l.startswith("XDG_DESKTOP_DIR=")].replace('"', "")
# check the type of window; only unmap "NORMAL" windows
return "_NET_WM_WINDOW_TYPE_NORMAL" in get(["xprop", "-id", w_id])
# get the name of the process, owning the window and window x/y position
w_list = get(["wmctrl", "-lpG"]).splitlines()
pid = [l for l in w_list if w_id in l].split()
proc = get(["ps", "-p", pid, "-o", "comm="])
xy = (" ").join(pid[3:5])
return (proc, xy)
def read_f(f, string, proc):
# search for a possible match in a targeted .desktop file
with open(f) as read:
for l in read:
if all([l.startswith(string), proc in l]):
in_f = True
in_f = False
in_f = False
def get_icon(proc, w_name):
# search appropriate icon in /usr/share/applications
exceptions = [item for item in [
] if item in proc]
if exceptions == [["soffice", "libreoffice-main"]]:
loffice = [
match = [m for m in loffice if m in w_name]
default = "/usr/share/applications"
dtfiles = [default+"/"+f for f in os.listdir(default)]
for f in dtfiles:
if read_f(f, "Exec=", proc) == True:
for l in open(f).readlines():
icon = l.replace("Icon=", "").strip()
# create unique (file-) name for boxed window
n = 1
name = dtop+"/"+"boxed_"+str(n)+".desktop"
n += 1
# convert window- id, xdotool format, into wmctrl format
w_id = hex(int(w_id))
def create_icon(w_id, w_name, icon, pos):
# create the launcher, representing the boxed window
boxedwindow = create_name()
"Exec=windowbox show "+w_id+" '"+boxedwindow+"' "+pos,
if icon == "generic":
with open(boxedwindow, "wt") as boxed:
for l in f_content:
command = "chmod +x "+"'"+boxedwindow+"'"
subprocess.call(["/bin/bash", "-c", command])
if args == "box":
dtop = find_dtop()
w_id = convert_wid(get(["xdotool", "getactivewindow"]))
w_name = get(["xdotool", "getwindowname", w_id])
if check_windowtype(w_id) == True:
procdata = get_process(w_id)
procname = procdata
icon = get_icon(procname, w_name); icon = icon if icon != None else "generic"
create_icon(w_id, w_name, icon, procdata)
subprocess.call(["xdotool", "windowunmap", w_id])
elif args == "show":
w_id = args
subprocess.call(["xdotool", "windowmap", w_id])
subprocess.call(["xdotool", "windowmove", "--sync", w_id, args, str(int(args)-deviation)])
Make the script executable
- To make the newly created directory "pop up" in
$PATH, either log out/in, or run
source ~/.profile (from a terminal window)
Test- run the script from a terminal window by the command:
The window should disappear, the "boxed" window should appear on your desktop.
If all works fine, add the following command to a shortcut key: choose the gear icon on the top right of your screen:
Go to System Settings → Keyboard → Shortcuts → Custom Shortcuts. Click the + and add the command:
That should do it.
The script uses
windowunmap to make the window invisible. The created "box" (icon) on your desktop is the only "gate" to the hidden window. In other words: don't remove the desktop file(s) manually. The window will be lost for good if you do.
Work to do [edit 20-12: done]
The script still could use some refinement:
- The window geometry is not restored by definition. Can be fixed very well, but I thought I'd show you the first result.
- In most cases, the boxed window has its correct icon. The function
get_process(w_id) could use some improvement however. If the process is not found as a command in
/usr/share/applications, the file has a generic icon.
Giving the boxed-window icons a different size than the other icons
The script names the created
.desktop files always
boxed_2.desktop etc, depending on the "available" name at the moment of creation (filenames, not the displayed name).
You can resize the files (in general), by right- click > icon size. The good news is that if you remove the file and recreate it, the size is remembered. Even if you create the file again after a restart. That means that if you ever resized the boxed windows (e.g.) 1-5, they will always have the same size when you (the script) create them again!