6

Enjoying multi-monitor setup at home and work, but wondering how to move focus between individual monitors (ie "screens") without a mouse?

Keyboards shortcuts are excellent for switching virtual desktops, and I looked at various options in ccsm but nothing came to mind.

I also look at other questions such as focus switch between separate X screens or links to dualscreenmouseutils and switchscreen but all of these seem to be concerned with separate screens per xorg.conf. These days, Unity "just works" with multiple monitors (via display port) so it is a bit of an embarrassment of riches.

But any hints how to navigate multiple (physical) screens within a single (virtual) Unity display would be very welcome.

  • All can be done, but I am not sure what you mean by "giving a screen focus"? Also: what is/are the screen's resolution(s) and how are they alligned? – Jacob Vlijm Jul 25 '15 at 14:18
  • I generally do focus follow mouse. But I need to get the mouse pointer from one screen (often with a maximized app) to another. Resolution differs between home and work, but is fixed either way. – Dirk Eddelbuettel Jul 25 '15 at 14:22
5

Toggle between screens and (optionally) set focus on the (full screen) window

The script below will toggle (and "focus") between the left and the right screen if both screens are more or less center- or top aligned, and more or less of the same vertical resolution.
I assume in practically all situations of a left/right screen setup it will work.

The script

#!/usr/bin/env python3
import subprocess
# just a helper function
get = lambda cmd: subprocess.check_output(cmd).decode("utf-8")
# get the current mouse position
current = [int(n) for n in [it.split(":")[1] for it in get(["xdotool", "getmouselocation"]).split()[:2]]]
# get the x/y size of the left screen
screendata = [(s.split("x")[0], s.split("x")[1].split("+")[0]) for s in get(["xrandr"]).split() if "+0+0" in s ][0]
xy = [int(n) for n in screendata]
# see if the mouse is on the left- or right screen
if current[0] < xy[0]:
    # if the mouse currently is on the left screen, move it to the right (from the middle of the left screen)
    command = ["xdotool", "mousemove", "--sync", str(current[0]+xy[0]), str(xy[1]/2)]
else:
    # if the mouse currently is on the left screen, move it to the right (from the middle of the left screen)
    command = ["xdotool", "mousemove", "--sync", str(current[0]-xy[0]), str(xy[1]/2)]

subprocess.Popen(command)
# optional: click after the mouse move: comment out if not needed / wanted
subprocess.Popen(["xdotool", "click", "1"])

How to use

  1. The script need xdotool to be installed (!)

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

  3. Test-run it by the command:

    python3 /path/to/toggle_screenloc.py
    
  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/toggle_screenloc.py
    

What it does exactly

If the script is run, it:

  1. derives the (left) screen's size (x/y) from the output of the xrandr command.
  2. it sees if the mouse is on the left- or right screen, by checking the (xdotool) command:

    xdotool getmouselocation
    

If the mouse pointer is located on the left screen:

  • it is moved to the middle (vertically) of the left screen, and horizontally moved to a position, equal to the current position + the width of the left screen.

If the mouse pointer is on the right screen:

  • actions are the opposite.

Subsequently, the mouse clicks a single time to set focus on the (possible) full screen application (optional).

  • Looks very promising, will definitely try this. But what would I do on the setup at work with (currently) three screen? How do I move left/right? I guess we could make it 'hop' on screen at a time, similarly to how Ctrl+Alt+Cursor moves one virtual desktop at a time? – Dirk Eddelbuettel Jul 25 '15 at 15:27
  • @DirkEddelbuettel Aha, I didn't understand you had more than two screens :) As it is, it toggles between screen 1 and 2. What would be the preferred behaviour? It should be no problem to edit, but I will have to edit it "blindly", since I only have two screens :) – Jacob Vlijm Jul 25 '15 at 15:32
  • I will have to acknowledge that I failed to mention that :) But I see now how the xdotool and xrandr binaries (knew about latter, not former) can help. I'll play with this some more and maybe come back with a question or two. "Worst case" I have enough idioms in your script to modify to move either 1/2 a total x-width, or 1/3 a total x-width with the choice between the two cases a function of the number of screens seen by xrandr. – Dirk Eddelbuettel Jul 25 '15 at 15:38
  • @DirkEddelbuettel Perfect :) Mind the nice --sync option to make one command wait for the last one to finish. – Jacob Vlijm Jul 25 '15 at 15:40
4

Jacob Vlijm's answer has the right idea, but there are other ways. Here's my take:

#!/bin/bash

eval $(xdotool getmouselocation --shell)

if [ $Y -gt 1080 ]
then
    theta=0
else
    theta=180
fi

xdotool mousemove_relative --polar $theta 1080

eval $(xdotool getmouselocation --shell)

xdotool windowfocus $WINDOW

The simplification comes from using xdotool getmouselocation --shell, which conveniently dumps the variables into the running script. This also lets us focus the window without clicking, which could have side effects we don't want.

Note that in my case, my displays are stacked vertically, so I move the mouse up (theta = 0) or down (theta = 180). I also choose 1080px as the dividing line.

  • Nice one too -- shall try that. Might work for my three-monitor setup at work too. – Dirk Eddelbuettel Nov 13 '15 at 20:54
  • I think the simplification is mostly setting the line at 1080, instead of letting the script read values automatically from xrandr. – Jacob Vlijm Nov 13 '15 at 21:09
  • Fair! I removed the opinionated text "can be improved". – chreekat Nov 13 '15 at 21:43
2

this repository may help you

https://github.com/Eitol/screen_focus_changer

You place the focus_changer.py left script in a fixed place (/ opt for example) And then add the keybinding / shortcut / hotkey in your settings

python3 /opt/focus_changer.py left # Focus to left

python3 /opt/focus_changer.py right # Focus to right

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.