3

I recently saw this answer to a great question, and I wondered, is this also possible on Ubuntu GNOME 15.10 with GNOME 3.18 and GDM, as well as on Compiz as the answer to that question shows?

But the keyboard shortcuts aren't so important for me, I just really want to be able to drag windows into the corners and have them automatically resize into those corners rather than on the sides when I release my mouse.

Jacob Vlijm
  • 83,767
  • @kos: How is this a duplicate of that? They are using compiz, I am using GDM, so why would I try to configure compiz to get this working on GDM when I don't have compiz? –  Nov 24 '15 at 21:49
  • Sorry, my bad. But is it even needed to use CCSM in the other answer? I remember that windows resize automatically using the keyboard shortcuts. I may very well be wrong on this though. – kos Nov 24 '15 at 21:53
  • @ParanoidPanda The question was, but the answer was universal, should work on most windowmanagers. It is however definitely not what your latest edit mentions. I removed the comment :) – Jacob Vlijm Nov 24 '15 at 22:12
  • @JacobVlijm: You mentioned (I think in one of your deleted comments) that you have a very similar script which you can just tweak a little in order for it to work for me. Now as the current answer only works properly without trouble on 3.16, and the extension does not currently support 3.18, it still doesn't work absolutely properly when using the workaround. So I was wondering if you could also post your script as an answer? :) –  Dec 15 '15 at 13:03
  • @ParanoidPanda sure! I'll look it up... – Jacob Vlijm Dec 15 '15 at 13:04

2 Answers2

5

Gnome Shell can be changed using Gnome Extensions - I think this extension will work for you:

This is done by dragging and dropping the windows into position, it will show a orange highlight (doesn't seem to match the theme :/ ). You can change the gap between windows in the settings:

enter image description here

Though currently this extension is not available for GNOME 3.18, so you will have to give this workaround a go.

Wilf
  • 30,194
  • 17
  • 108
  • 164
1

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:

enter image description here

running the script will arrange them in a grid:

enter image description here

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

  1. The script needs both xdotool and wmctrl:

    sudo apt-get install xdotool wmctrl
    
  2. Copy the script into an empty file, save it as twobytwo.py

  3. 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

  4. 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.
Jacob Vlijm
  • 83,767