On the edge of posting a duplicate of this one (but the question slightly differs), the script below does what you describe, if you run it with the arguments
python3 /path/to/script.py 2 2
However, if there are more than four windows (or more than the cells of a grid, if you use other arguments than 2 2
), the script places only the four oldest windows in the grid.
What it does
When four windows are opened, randomly placed on the screen:

running the script will arrange them in a grid:

The script
#!/usr/bin/env python3
import subprocess
import sys
#--- set your preferences below: padding between windows, margin(s)
cols = int(sys.argv[1]); rows = int(sys.argv[2]); padding = 10; left_margin = 0; top_margin = 30
#---
get = lambda cmd: subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")
def get_res():
xr = get("xrandr").split(); pos = xr.index("current")
return [int(xr[pos+1]), int(xr[pos+3].replace(",", "") )]
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
# get resolution
res = get_res()
# define (calculate) the area to divide
area_h = res[0] - left_margin; area_v = res[1] - top_margin
# create a list of calculated coordinates
x_coords = [int(left_margin+area_h/cols*n) for n in range(cols)]
y_coords = [int(top_margin+area_v/rows*n) for n in range(rows)]
coords = sum([[(cx, cy) for cx in x_coords] for cy in y_coords], [])
# calculate the corresponding window size, given the padding, margins, columns and rows
w_size = [str(int(area_h/cols - padding)), str(int(area_v/rows - padding))]
# find windows of the application, identified by their pid
wlist = [w.split()[0] for w in get("wmctrl -lp").splitlines()]
w_list = [w for w in wlist if check_window(w) == True][:cols*rows]
print(w_list)
# remove possibly maximization, move the windows
for n, w in enumerate(w_list):
data = (",").join([str(item) for item in coords[n]])+","+(",").join(w_size)
cmd1 = "wmctrl -ir "+w+" -b remove,maximized_horz"
cmd2 = "wmctrl -ir "+w+" -b remove,maximized_vert"
cmd3 = "wmctrl -ir "+w+" -e 0,"+data
for cmd in [cmd1, cmd2, cmd3]:
subprocess.Popen(["/bin/bash", "-c", cmd])
How to use
The script needs both xdotool
and wmctrl
:
sudo apt-get install xdotool wmctrl
Copy the script into an empty file, save it as twobytwo.py
Test- run it by opening four windows (at least one terminal window to run the command), the run the command:
python3 /path/to/twobytwo.py 2 2
The windows should move into a grid of 4, as in the second image
If all works fine, add it to a shortcut key: choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command:
python3 /path/to/twobytwo.py 2 2
Note(s)
in the head section, there is a section:
left_margin = 0
I set this to zero, since gnome does not have the launcher on the left. For Unity, this should be (at least) 65
, depending on the set width of the launcher.
- As mentioned, the script, as it is, grids the four oldest windows. That means if you need more windows to be placed in the same grid, the script needs an edit. Please mention if so.