tl;dr version:
* shell: xdotool or (probably better for your use case) wmctrl
* perl: X11::GUITest
https://metacpan.org/pod/X11::GUITest
* python: emwh
http://ewmh.readthedocs.io/en/latest/ewmh.html
or xdo
https://github.com/rshk/python-libxdo
or xlib
https://github.com/python-xlib/python-xlib
* devilspie2
http://www.nongnu.org/devilspie2/
I didn't know about devilspie2 when I started writing this reply, but it
sounds like it's ideal for automating tasks like this. It also seems to be a
tool I've been looking for for years.
With all of these tools the procedure will be similar but the exact details
will differ:
for each window you want to move:
get its window id
change the geometry of that windowid
Long, rambling, barely coherent version:
On Sun, Jul 22, 2018 at 09:54:25PM +1000, Kim Oldfield wrote:
Does anyone know how I can save (and later restore)
the positions of my
windows on my screens?
AFAIK, there isn't anything that can do exactly what you want. There
are tools you can use in shell scripts and libraries for various
programming/scripting languages. to do roughly what you want
There's also the sawfish window manager, which is very programmable (with a
lisp-like language). You can program it to react to all sorts of events - I
used to program it to redefine the window properties of certain always-on-top,
un-resizable dialog boxes so that they weren't always-on-top and were
re-sizeable (very useful for apps that assume that everyone uses the
developer's screen resolution and font size), and to force certain windows to
always open at a specific location and size. But I haven't used it for years,
not since I switched to openbox and then later to using XFCE. That was so
long ago that I think it was still called "sawmill" when I last used it. I
can't even remember why I stopped using it.
I've been looking for a standalone X event monitor that can be programmed to
perform the same kinds of actions for other window managers. Haven't found
one.
I don't know if it can detect a screen being attached or detached when you
dock and undock the laptop.
There are also things like xdotool which can send X events like key-strokes
or resizes etc to windows.
e.g. mupdf doesn't take a --geometry option, so I use the following wrapper
script to start mupdf with a window sized to fit an A4 PDF document on my
1440p monitor:
#!/bin/bash
# run mupdf in the background, then use xdotool to resize it
mupdf "$@" &
sleep 0.2
# find the window IDs with class "mupdf"
MUWIN=( $(xdotool search --class mupdf) )
# resize them and send a "Z" keystroke to them.
for w in "${MUWIN[@]}" ; do
xdotool windowsize --sync "$w" 1020 1320
xdotool key --window "$w" Z
done
You could write a script that you run manually when you re-dock your laptop
that used xdotool to search for particular windows and move & resize them.
BTW, xwininfo is useful for getting exact pixel sizes and locations of
current windows. just run it and then click on the window you want info on.
alternatively, you can use xdotool to find the window-id of a window and then
use 'xdotool getwindowgeometry' on it. From the xdotool man page:
getwindowgeometry [options] [window]
Output the geometry (location and position) of a window. The values
include: x, y, width, height, and screen number.
--shell
Output values suitable for 'eval' in a shell.
Note that window managers tend to treat multiple monitors as one big
desktop, so moving a window from one screen to another requires knowing the
co-ordinates for the start of the particular screen.
e.g. my system has a 28" 2560x1440 main monitor, with an old 21" 1680x1050
monitor to the right of that (and on its side so it's 1050 wide x 1680 high).
That means windows on the older 21" monitor are always going to be have an x
position >= 2560. e.g. if I maximise a mupdf window on it:
$ xdotool search --class mupdf
83886223
$ xdotool getwindowgeometry 83886223
Window 83886223
Position: 2560,35 (screen: 0)
Geometry: 1050x1610
The window starts at x=2560, y=35 (remember this is all zero-based so the
first screen's horizontal pixels are 0-2559, 2nd screen starts at 2560). The
window size (geometry) is 1050x1610 (not the full 1680 because there are xfce
panels at top and bottom of the screen).
wmctrl is another program with similar capabilities. I use both of them
for different tasks - they're both quite capable but some things are easier
to do with xdotool, and some are easier to do with wmctrl. Note that both
tools will take window and other IDs as either hexadecimal or decimal values.
xdotool displays them as decimal, while wmctrl displays them in hex.
$ wmctrl -l -p -G -x | grep -i mupdf
0x0500008f 0 0 2560 35 1050 1610 mupdf.MuPDF ganesh
debian-reference.en.pdf - 1/302 (96 dpi)
to extract the window-id for use in script, use awk:
$ wmctrl -l -p -G -x | awk '$8 ~ /mupdf/ {print $1}'
0x0500008f
$ xdotool getwindowgeometry 0x0500008f
Window 83886223
Position: 2560,35 (screen: 0)
Geometry: 1050x1610
Now that I think about it, wmctrl is probably better for your needs here. The
"-l" option to list all windows and their geometries will be useful and a lot
less hassle than getting each window's geometry individually.
You could run 'wmctrl -l -p -G -x' immediately before un-docking, save the
output to a file, and then run a script to parse and act on that file after
you've re-docked.
Note also that perl, python, and other languages have libraries for
manipulating window geometries and other attributes. If your script needs
to search for and reposition dozens or hundreds of windows, it will be much
faster to run and easier to write if you do it using one of these languages
than with a shell script repeatedly forking external programs and parsing
their output.
For perl, X11::GUITest seems quite capable (but I've never used it). It's
packaged in debian as libx11-guitest-perl
Here's an old perl-monks thread where someone wants to do exactly what you
want:
https://www.perlmonks.org/?node_id=803821
This thread mentions a program called devilspie which sounds like it can
do the kind of scripted window manipulation that i've been wanting since
i stopped using sawfish. I'd heard of this before but it seemed to be
abandonware.
After some brief googling I found that there's now a devilspie2 by a different
developer which last had an updated release in Sep 2017 so seems to be
actively maintained. devilspie2 replaces the original program's custom pattern
matching language with a LUA interpreter. Both are packaged for debian, and
the devilspie2 home page is at
http://www.nongnu.org/devilspie2/
You might be able to use devilspie2 to write a script that automatically moves
windows for you when your laptop is docked...depends on whether it can detect
the addition/removal of a screen or not. worth looking at, anyway.
For python, you'd use the ewmh library which will work with any reasonably
modern desktop or window manager. Alternatively, python-xdo. Both of these
are built-on top of python xlib. All are available packaged for debian for
both python2 & python3
python-ewmh-doc - Python interface to EWMH-compliant window managers (common
documentation)
python-ewmh - Python interface to EWMH-compliant window managers (Python 2)
python3-ewmh - Python interface to EWMH-compliant window managers (Python 3)
python-xdo - Python 2 library for simulating X11 keyboard/mouse input (libxdo bindings)
python3-xdo - Python 3 library for simulating X11 keyboard/mouse input (libxdo bindings)
python-xlib - interface for Python to the X11 protocol
python3-xlib - interface for Python 3 to the X11 protocol
craig
--
craig sanders <cas(a)taz.net.au>