Move windows between screens in dual screen mode
Solution 1:
1. Script to swap all windows from screen 1 --> screen 2 and vice versa
The script assumes the screens are of the same vertical resolution, and the left screen is the primary one. The horizontal resolutions of both screens is searched by the script.
How to set up
The script needs wmctrl
to be installed:
sudo apt-get install wmctrl
- Copy the script below into an empty file, save it as
swap_windows
(no extension) in~/.bin
. Create the directory if it doesn't exist already, and make the script executable. - If you just created the directory
~/bin
(it didn't exist yet), either log out/in or run in a terminal:source ~/.profile
. -
test run the script with the command:
swap_windows
If all works as expected, add shortut key; choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command
The script
#!/usr/bin/env python3
import subprocess
import sys
def get(cmd):
return subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")
def get_shiftright(xr_output):
lines = [l for l in xr_output.splitlines() if "+0+0" in l][0].split()
return int([it for it in lines if "x" in it][0].split("x")[0])
def get_shiftleft(xr_output):
lines = [l for l in xr_output.splitlines() if "+0" in l and not "+0+0" in l][0].split()
return -int([it for it in lines if "x" in it][0].split("x")[0])
def swap_windows():
xr_output = get("xrandr")
shift_r = get_shiftright(xr_output)
shift_l = get_shiftleft(xr_output)
w_data = [l.split() for l in get("wmctrl -lG").splitlines()]
for w in w_data:
props = get("xprop -id "+w[0])
if any(["_TYPE_NORMAL" in props, "TYPE_DIALOG" in props]):
if 0 < int(w[2]) < shift_r:
shift = shift_r
elif shift_r-shift_l > int(w[2]) >= shift_r:
shift = -shift_r
else:
shift = 0
command = "wmctrl -ir "+w[0]+" -e 0,"+(",").join([str(int(w[2])+shift), str(int(w[3])-28), w[4], w[5]])
subprocess.Popen(["/bin/bash", "-c", command])
swap_windows()
2. Script to move (all) windows from one monitor to the other
The script below moves windows in a dual monitor setup from one screen to another, either:
-
from the left to the right monitor -->
or
from the right to the left monitor <--
Depending on the argument you run it with (left
or right
)
The script (again) assumes the screens are of the same vertical resolution, and the left screen is the primary one. The horizontal resolutions of both screens is searched by the script.
How to set up
The script needs wmctrl
to be installed:
sudo apt-get install wmctrl
- Copy the script below into an empty file, save it as
shift_windows
(no extension) in~/.bin
. Create the directory if it doesn't exist already, and make the script executable. - If you just created the directory
~/bin
(it didn't exist yet), either log out/in or run in a terminal:source ~/.profile
. -
test run the script with the commands
shift_windows right
and: shift_windows left
In the first case, windows on your left screen should move to the right screen and in the second case vice versa.
- If all works as expected, add the script to two shortcut combinations: choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the commands as explained above.
The script
#!/usr/bin/env python3
import subprocess
import sys
vec = sys.argv[1]
def get(cmd):
return subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")
def get_shiftright(xr_output):
lines = [l for l in xr_output.splitlines() if "+0+0" in l][0].split()
return int([it for it in lines if "x" in it][0].split("x")[0])
def get_shiftleft(xr_output):
lines = [l for l in xr_output.splitlines() if "+0" in l and not "+0+0" in l][0].split()
return -int([it for it in lines if "x" in it][0].split("x")[0])
def shift_windows():
xr_output = get("xrandr")
shift_r = get_shiftright(xr_output)
shift_l = get_shiftleft(xr_output)
w_data = [l.split() for l in get("wmctrl -lG").splitlines()]
for w in w_data:
props = get("xprop -id "+w[0])
if vec == "right":
check = (0 < int(w[2]) < shift_r, "_TYPE_NORMAL" in props, "TYPE_DIALOG" in props).count(True)
shift = shift_r
if vec == "left":
check = (shift_r-shift_l > int(w[2]) >= shift_r , "_TYPE_NORMAL" in props, "TYPE_DIALOG" in props).count(True)
shift = -shift_r
if check == 2:
command = "wmctrl -ir "+w[0]+" -e 0,"+(",").join([str(int(w[2])+shift), str(int(w[3])-28), w[4], w[5]])
subprocess.Popen(["/bin/bash", "-c", command])
shift_windows()
3. Move a single window from one screen to another
Although not literally your question, with just a few lines more, you can either move all windows from one screen to the other, but also a single one (the frontmost) with a key combination.
With the script below, you can move all windows with the command:
shift_windows right
or move a single window with the command:
shift_windows right s
The setup is pretty much the same as the script above (don't forget to install wmctrl
)
The script
#!/usr/bin/env python3
import subprocess
import sys
vec = sys.argv[1]
try:
n = sys.argv[2]
except IndexError:
n = "a"
def get(cmd):
return subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")
def get_shiftright(xr_output):
lines = [l for l in xr_output.splitlines() if "+0+0" in l][0].split()
return int([it for it in lines if "x" in it][0].split("x")[0])
def get_shiftleft(xr_output):
lines = [l for l in xr_output.splitlines() if "+0" in l and not "+0+0" in l][0].split()
return -int([it for it in lines if "x" in it][0].split("x")[0])
def shift_windows():
xr_output = get("xrandr")
shift_r = get_shiftright(xr_output)
shift_l = get_shiftleft(xr_output)
w_data = [l.split() for l in get("wmctrl -lG").splitlines()]
if n == "s":
frontmost = [l for l in get("xprop -root").splitlines() if "_NET_ACTIVE_WINDOW(WINDOW)" in l][0].split()[-1]
frontmost = frontmost[:2]+"0"+frontmost[2:]
w_data = [l for l in w_data if frontmost in l]
for w in w_data:
props = get("xprop -id "+w[0])
if vec == "right":
check = (0 < int(w[2]) < shift_r, "_TYPE_NORMAL" in props, "TYPE_DIALOG" in props).count(True)
shift = shift_r
if vec == "left":
check = (shift_r-shift_l > int(w[2]) >= shift_r , "_TYPE_NORMAL" in props, "TYPE_DIALOG" in props).count(True)
shift = -shift_r
if check == 2:
command = "wmctrl -ir "+w[0]+" -e 0,"+(",").join([str(int(w[2])+shift), str(int(w[3])-28), w[4], w[5]])
subprocess.Popen(["/bin/bash", "-c", command])
shift_windows()