Ubuntu 14.10 Aero snap in two screen horizontal setup?

I tested the script below on Ubuntu (Gnome) Classic and Gnome Flashback (Metacity) 14.04. The "mixed" application of xdotool and wmctrl was necessary because of some peculiarities I ran into writing the script for Metacity.

The solution

As a result of the fact that I wanted the script to:

  • determine which is the left/right screen
  • calculate both monitor's resolutions
  • also work fine if the two screens are of different resolutions (and calculate both the positions and the targeted sizes of the windows)
  • work fine if either a second screen is connected or not

-- the script got a bit more extensive then I foresaw.

What it does:

If a second monitor is connected:
It works pretty much as you describe:

  • it divides the two screens in four areas, each area is half the size of the screen it is located on (as said, also with different resolutions)
  • running it with the option "left" or "right":
    • it moves the window to the area on the left/right of the window
    • re-sizes it horizontally to half the size of the targeted screen
    • maximizes the window vertically

If no second monitor is connected:
It works in the traditional way:

  • run with the option "left", it maximizes the front-most window vertically on the left half of the screen
  • run with the option "right", it maximizes the front-most window vertically on the right half of the screen

How to use it

  • Install both xdotool and wmctrl:

    sudo apt-get install wmctrl
    sudo apt-get install xdotool
    
  • Copy the script into an empty file, save it as aero.py run it by the command(s)

    python3 /path/to/aero.py left
    python3 /path/to/aero.py right
    

The script

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

move = sys.argv[1]

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

# screen resolutions ("raw")  
wds = [s for s in get("xrandr").split() if s.endswith("+0")]
# x-res left/right)
left = [scr.split("x")[0] for scr in wds if scr.endswith("+0+0")]
right = [scr.split("x")[0] for scr in wds if not scr.endswith("+0+0")]
# x-positions areas
left_pos = [0, int(int(left[0])/2), int(left[0])]
right_pos = [int(int(left[0])+int(right[0])/2)] if len(right) != 0 else []
x_positions = left_pos+right_pos
# frontmost window pos
frontmost =get("printf 0x%x "+get("xdotool getwindowfocus").strip())
frontmost = frontmost[:2]+"0"+frontmost[2:]
f_data = [l.split() for l in get("wmctrl -lG").splitlines() if frontmost in l][0][:6]
curr_pos = int(f_data[2])
area = len([x for x in x_positions if x <= curr_pos])
if move == "left":
    i = area-2; target_pos = x_positions[i] if i >= 0 else 0 
elif move == "right":
    i = area; target_pos = x_positions[area] if area < len(x_positions) else x_positions[-1]
if i >= 2:
    perc = int((100*(x_positions[-1]-x_positions[-2])/sum([int(it) for it in left+right])))
else:
    perc = int((100*(x_positions[1]-x_positions[0])/sum([int(it) for it in left+right])))
# execute actions
cmd1 = "wmctrl -r :ACTIVE: -b remove,maximized_vert,maximized_horz"
cmd2 = "wmctrl -ir "+f_data[0]+" -e 0,"+str(target_pos)+","+"30,300,300"
cmd3 = "xdotool windowsize $(xdotool getactivewindow) "+str(perc)+"% 100%"
for cmd in [cmd1, cmd2, cmd3]:
    execute(cmd)

Also posted on gist.gisthub (latest version)