Saving and restoring window positions

5,846

Solution 1

Take a "snapshot" of the window arrangement and restore it

The script below can be used to get the current window positions of all "normal" windows (run with the argument -get), or restore the last window arrangement (run with the argument -restore).

As explained here, using wmctrl i.c.w. Unity has some issues. If it is satisfying in your situation is to decide.

How to use

The script uses wmctrl:

sudo apt-get install wmctrl

Then:

  1. Copy the script into an empty file, save it as window_arrange.py
  2. Run it by:

    python3 /path/to/window_arrange.py -get
    

    to "record" the current window arrangement, and

    python3 /path/to/window_arrange.py -restore
    

    to restore the last "recorded" window arrangement

The script:

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

wfile = os.environ["HOME"]+"/.windowlist"
arg = sys.argv[1]

def get(command):
    return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

def check_window(w_id):
    w_type = get("xprop -id "+w_id)
    if " _NET_WM_WINDOW_TYPE_NORMAL" in w_type:
        return True
    else:
        return False

def read_windows():
    w_list =  [l.split()[:6] for l in get("wmctrl -lG").splitlines()]
    relevant = [(" ").join(w) for w in w_list if check_window(w[0]) == True]
    with open(wfile, "wt") as out:
        for item in relevant:
            out.write(item+"\n")

def restore_windows():
    try:
        wlist = [l.split() for l in open(wfile).read().splitlines()]
    except FileNotFoundError:
        pass
    else:
        for w in wlist:
            try:
                cmd = "wmctrl -ir "+w[0]+" -e 0,"+(",").join(w[2:])
                subprocess.Popen(["/bin/bash", "-c", cmd])
            except:
                pass

if arg == "-restore":
    restore_windows()
elif arg == "-get":
    read_windows()

Solution 2

If you install wmctrl you can use "wmctrl -Gl" to get a listing of all windows with their current positions and sizes. You could then use this information in step 4 to call wmctrl with the -e option to restore the size and position. For example:

wmctrl -ir <id> -e 0,<x>,<y>,<w>,<h>

Solution 3

If you prefer NodeJs: I wrote a little library/command line tool which allow saving and restoring sessions and has support for different monitors setups as well as virtual desktops. You might want to check out the implementation of the window related features: https://github.com/johannesjo/linux-window-session-manager/blob/master/lib/x11-wrapper.js

You can find the whole thing here: https://github.com/johannesjo/linux-window-session-manager

Share:
5,846

Related videos on Youtube

Anthony Graham
Author by

Anthony Graham

Updated on September 18, 2022

Comments

  • Anthony Graham
    Anthony Graham over 1 year

    I'm experiencing a bug where when the machine comes back from standby a monitor connected via displayport (MST) does not come back on, however the windows are still in the area it cover if it did come on.

    The only way to recover from this short of a restart is to disable and reenable the display now I can do that via the command line just fine but when the display is disabled all the windows get rearranged onto the remaining screen.

    Is there a way to persist the window positions and restore them so my script could do this sequence:-

    1. enumerate windows, store positions
    2. display off (messing up positions)
    3. display on (making the display work again, yay!)
    4. restore position of the windows

    I can do step 2 and 3 just fine but I'm lost for step 1 and 4

    I know I can force a position per app but that's not what I want as I could be doing different things and have the same apps in different positions, I also have multiple terminals open, I need the current positions storing somehow and restoring.

    Any help would be appreciated!

    • Jacob Vlijm
      Jacob Vlijm almost 9 years
      Could be done very well (and interesting) , but in my case... it would be in python :) would that disturb you?
    • Anthony Graham
      Anthony Graham almost 9 years
      Python is absolutely fine, I guess it'd be good if saving and restoring could be called separately though then I can call the python scripts from my existing bash scripts
    • Jacob Vlijm
      Jacob Vlijm almost 9 years
      Posted my answer. Really curious if it is sufficient in your situation. You can also use it to store the arrangement before going on standby, and restore after wake up (but that may be what you meant:) ). You can even make two key shortcut keys to do that.
  • Anthony Graham
    Anthony Graham almost 9 years
    Sir, that is amazing work!
  • Jacob Vlijm
    Jacob Vlijm almost 9 years
    @AnthonyGraham Thanks. As mentioned, this is the kind of question that ineterests me a lot. Thanks for the nice question :)
  • ylluminate
    ylluminate about 8 years
    @JacobVlijm the follow up to this would be how to make a script that would execute all desired apps and then set the window positions. Thanks for the good work above.
  • Duncan Lock
    Duncan Lock about 7 years
    This is great, but it's got two problems: 1. It tries to restore windows by ID, which aren't stable across restarts - of the OS, or the App. 2. Doesn't tell the window which workspace to restore to.
  • Duncan Lock
    Duncan Lock about 7 years
    You can make this restore windows to the desktop/workspace they were on by changing line 38 to this: cmd = "wmctrl -ir " + w[0] + " -e 0," + (",").join(w[2:] + "-t " + w[1])
  • Jacob Vlijm
    Jacob Vlijm about 7 years
    @DuncanLock Thanks for mentioning, however, the question was on when the machine comes back from standby. Your suggestion does not work on Unity, Which is the tag on this question :). Unity has viewports on one big workspace.
  • Jake
    Jake almost 3 years
    work mostly. but all the windows positions slightly changed. don't know why,