Ubuntu – How to move from screen 1 to screen 3 by moving cursor to the left and vice versa

multiple-monitorsunity

If I have to move the mouse from the left screen all the way to the right screen, the distance is quite big.

Is there a way to virtually connect the sides of the screen as if they were arranged in a circle? I could then move from the left screen to the right screen, by simply moving the cursor to the left.

Best Answer

Script to connect screens "circular"

The script below will do as you describe; if the mouse touches the right edge of the right (-most) screen, the mouse re- appears on the left (-most) screen. If it touches the left side of the left screen, it re- appears on the right side of the right screen.

Built- in precautions

The script assumes the screens are arranged in a non- overlapping configuration, x-wise, but it has a built- in correction in case the screens are not top- aligned, or of a different y- resolution. Although you wouldn't run into problems in most cases, in the situation below you would, unless the script takes into account the possible differences in y- resolution and /or (un-) alignment of the screens:


enter image description here

If the top of the left screen is below the top of the right screen, the cursor moves from top- right to the top of the left screen. Possibly un- aligned bottom idem ditto


The script

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

def get_screendata():
    data = [s.split("+") for s in subprocess.check_output(["xrandr"]).decode("utf-8").split() \
            if s.count("+") == 2]
    # calculate total x-size of spanning screens
    x_span = sum([int(item[0].split("x")[0]) for item in data])
    # sort screens to find first/last screen (also for 2+ screens)
    data.sort(key=lambda x: x[1])
    # find (possible) screen offset of first/last screen and vertical area
    scr_first = data[0]; shiftl = int(scr_first[2])
    areal = [shiftl, shiftl+int(scr_first[0].split("x")[1])] 
    scr_last = data[-1]; shiftr = int(scr_last[2])
    arear = [shiftr, shiftr+int(scr_last[0].split("x")[1])]   
    return (x_span, areal, arear)

screendata = get_screendata()
x_span = screendata[0]; areal = screendata[1]; arear = screendata[2]
new_coords = []

while True:
    time.sleep(0.5)
    new_coords = []
    # read the current mouse position
    pos = [int(s.split(":")[-1]) for s in \
           subprocess.check_output(["xdotool", "getmouselocation"]).decode("utf-8").split()\
           if any(["x" in s, "y" in s])]
    # if the mouse is on the left of the first screen
    if pos[0] == 0:
        new_coords.append(x_span-2)
        if pos[1] <=  arear[0]:
            new_coords.append(arear[0]+2)
        elif pos[1] >= arear[1]:
            new_coords.append(arear[1]-2)
        else:
            new_coords.append(pos[1])
    # if the mouse is on the right of the last screen
    elif pos[0] > x_span-2:
        new_coords.append(2)
        if pos[1] <=  areal[0]:
            new_coords.append(areal[0]+2)
        elif pos[1] >= areal[1]:
            new_coords.append(areal[1]-2)
        else:
            new_coords.append(pos[1])
    # move the mouse
    if new_coords:
        subprocess.Popen(["xdotool", "mousemove", str(new_coords[0]), str(new_coords[1])])

How to use

  1. The script needs xdotool

    sudo apt-get install xdotool
    
  2. Copy the script into an empty file, save it as circular_mouse.py
  3. Test- run the script by running in a terminal:

    python3 /path/to/circular_mouse.py
    

    You should be able to make an infinite mouse movement to either right or left, circulation through your screens.

  4. If all works fine, add it to startup applications: Dash > Startup Applications > Add the command:

    /bin/bash -c "sleep 15 &&  python3 /path/to/circular_mouse.py" 
    
Related Question