1

There's an question that is asking in how to move a window around using keyboard shortcuts.

Yet the provided answer of using

  • Ctrl + Alt + NUMPAD 4 (left edge)
  • Ctrl + Alt + NUMPAD 6 (right edge)

doesn't work for a three monitor setup, as the jump omits the middle screens and goes to the most left or most right screen.

Another answer recommended the Puts Windows extension, yet its keybinding doesn't seem to work for me, as it is active but the shortcuts are not working at all.

How to be able to move windows to a specific screen using more than two monitors using gnome-shell?


My output of xrandr:

Screen 0: minimum 8 x 8, current 5760 x 1080, maximum 32767 x 32767
eDP1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 309mm x 174mm
   1920x1080      60.0*+   59.9     48.0  
   1680x1050      60.0     59.9  
   1600x1024      60.2  
   1400x1050      60.0  
   1600x900       60.0  
   1280x1024      60.0  
   1440x900       59.9  
   1280x960       60.0  
   1368x768       60.0  
   1360x768       59.8     60.0  
   1152x864       60.0  
   1280x720       60.0  
   1024x768       60.0  
   1024x576       60.0  
   960x540        60.0  
   800x600        60.3     56.2  
   864x486        60.0  
   640x480        59.9  
   720x405        60.0  
   640x360        60.0  
DP1 disconnected (normal left inverted right x axis y axis)
DP1-1 connected 1920x1080+1920+0 (normal left inverted right x axis y axis) 477mm x 268mm
   1920x1080      60.0*+
   1680x1050      59.9  
   1600x900       60.0  
   1280x1024      75.0     60.0  
   1280x800       59.9  
   1152x864       75.0  
   1280x720       60.0  
   1024x768       75.1     60.0  
   832x624        74.6  
   800x600        75.0     60.3  
   640x480        75.0     60.0  
   720x400        70.1  
DP1-2 connected 1920x1080+3840+0 (normal left inverted right x axis y axis) 477mm x 268mm
   1920x1080      60.0*+
   1680x1050      59.9  
   1600x900       60.0  
   1280x1024      75.0     60.0  
   1280x800       59.9  
   1152x864       75.0  
   1280x720       60.0  
   1024x768       75.1     60.0  
   832x624        74.6  
   800x600        75.0     60.3  
   640x480        75.0     60.0  
   720x400        70.1  
DP1-3 disconnected (normal left inverted right x axis y axis)
HDMI1 disconnected (normal left inverted right x axis y axis)
HDMI2 disconnected (normal left inverted right x axis y axis)
VIRTUAL1 disconnected (normal left inverted right x axis y axis)
k0pernikus
  • 6,115

1 Answers1

1

The good news is that the y- resolution of all screens is the same, and the screens are vertically alligned, so we do not need to take care of possible y- position clashes, like here.

Moving windows across multiple screens, using the screen as an argument

Below a script to make available under three (for three screens) shortcut keys. By pressing the keys, you can move the windows to either screen 1, 2 or 3. The script calculates on what screen the window is on, and the distance the window has to be moved.

The script

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

target = int(sys.argv[1])

# --- for Unity, there is a deviation in the y coordinate of the wmctrl -command
# --- for Unity, set: deviation = -28
deviation = 0
# ---

# get the (sorted) x resolution of the screens as a list
screens = [int(s.split("+")[-2]) for s in subprocess.check_output(
    ["xrandr"]).decode("utf-8").split() if (s).count("+") == 2]
screens.sort()
# get the frontmost window and its coordinates
frontmost = [l.split("#")[-1].strip() for l in subprocess.check_output([
    "xprop", "-root"]).decode("utf-8").splitlines() if "_NET_ACTIVE_WINDOW(WINDOW)" in l][0]
active = frontmost[:2]+(10-len(frontmost))*"0"+frontmost[2:]
windata = [l.split() for l in subprocess.check_output(
    ["wmctrl", "-lG"]).decode("utf-8").splitlines() if active in l][0]
# get the current screen the window is on, and (thus) the x-position (of the screen)
currscreen = len([cr for cr in screens if cr <= int(windata[2])]) 
currpos = sum([item for item in screens[:currscreen]])
# calculate the target position/the distance to move the window
target_pos = screens[target-1]
move = target_pos-currpos
command = ["wmctrl", "-ir", active, "-e", "0,"+(",").join(
    [str(int(windata[2])+move), str(int(windata[3])-28), windata[4], windata[5]])]
# move the window to the targeted screen
subprocess.Popen(command)

How to use

  1. The script needs wmctrl:

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

  3. Test- run the script by running it in a terminal window, with the commands:

    python3 /path/to/move_window.py 1
    

    To move the active window to screen 1,

    python3 /path/to/move_window.py 2
    

    To move the active window to screen 2,

    python3 /path/to/move_window.py 3
    

    To move the active window to screen 3

    enter image description here

    Since the terminal is your active window, it should move across your screens on the commands.

  4. Add it to three different shortcut keys, e.g. Ctrl+Alt+1, 2 and 3: choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command(s)

Notes

  • The question was on Gnome, but the script should work on (at least) Unity as well. There is however a deviation when used on Unity, as explained in the head section of the script and here.
  • Since the script gets the screen information from xrandr, it should work as well with 2, 3, 4 or any number of screens.
Jacob Vlijm
  • 83,767
  • This does not work quite as excpected. Some index numbers do not seem to identfy a specific window, but toggle between two monitors. Furthermore, there is no difference between running with index 2 and 3, the monitor stays on the same monitor. – k0pernikus Nov 10 '15 at 15:08
  • @k0pernikus Hmm, I cannot test with 3 monitors, only with 2, but I will look into the script with fake (screen-) data. Will get back later. – Jacob Vlijm Nov 10 '15 at 15:18
  • Here's a gif showcasing the weird behavior: http://i.giphy.com/3oEduLfcFhxWBTRvCE.gif – k0pernikus Nov 10 '15 at 15:20
  • @k0pernikus Thanks, very usefull! – Jacob Vlijm Nov 10 '15 at 15:23
  • @k0pernikus I Think I know, on Gnome, the screen actually is on the very left of the screen, I think I need to change < by <=. Wait a minute... – Jacob Vlijm Nov 10 '15 at 15:25
  • You got all the time in the world ;) Thanks alot! – k0pernikus Nov 10 '15 at 15:27
  • @k0pernikus I have good hopes this solves it (see edit). If not, I need to look into it more seriously :) – Jacob Vlijm Nov 10 '15 at 15:28
  • Yes, it solves it, only difference is that the monitors are now 0-indexed instead of starting by 1. – k0pernikus Nov 10 '15 at 15:34
  • Wait a second, it just switched back to 1 based 0.o Is the way the index is determined realiable? – k0pernikus Nov 10 '15 at 15:38
  • @k0pernikus it should be. I'll run some test with fake-screendata and fake- windowpositions. – Jacob Vlijm Nov 10 '15 at 15:38
  • When using it from command line it works pretty well, yet when assigning shortcuts there is still some glitchy behaviour. I have mapped the indexes the super+1, super+2, super+3; yet it jumps not consistently, and repeating the shortcut toggles the movement between to screens. Have not yet discovered a pattern – k0pernikus Nov 10 '15 at 15:41
  • Did you find the time to fix the little quirks the script was having in gnome-shell? – k0pernikus Nov 27 '15 at 18:40
  • @k0pernikus I must install Gnome. I will probably after the weekend. In the meantime, curious if this one works on your system: http://askubuntu.com/a/702302/72216 almost a dupe, and it seems to work on gnome as well. – Jacob Vlijm Nov 27 '15 at 18:45