How can I make programs open on a specific monitor? [duplicate]
I have Ubuntu 14.04 and two monitors. When I open applications I need some of them to be on the primary monitor and others On the secondary.
At the moment, apps always open in the primary monitor.
I have dash icons only on one (left) display, so I can't launch apps using the cursor or active window setting from Compiz.
The solution below works as follows:
- Press a key combination
- The first application that starts within 15 seconds will start on screen 1
or:
- Press a(nother) key combination
- The first application that starts within 15 seconds will start on screen 2
In other words: you'll need two key combinations to make sure a new application window appears on either the first or the second screen.
How to set up
The script uses both xdotool
and wmctrl
:
sudo apt-get install xdotool
sudo apt-get install wmctrl
Then:
- Copy the script below into an empty file, save it as
preferred_screen
(no extension) in~/bin
. Create the directory if necessary. - Make the script executable
- In the head section, set the horizontal resolution of the left screen (I already set it for you to 1600)
-
If you just created the directory
~bin
, run in a terminal:source ~/.profile
-
Test-run the script by running in a terminal window the command:
preferred_screen 1
Now open an (any) application, it should open on the first screen
Repeat the step with the command:
preferred_screen 2
now the application shoulod open on the second screen.
-
If all works fine, add both commands to two different key combinations: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the commands:
preferred_screen 1 preferred_screen 2
The script
#!/usr/bin/env python3
import subprocess
import time
import sys
#--- enter the horizontal resolution of the left screen below
left_width = 1600
#---
target_screen = int(sys.argv[1])
get = lambda cmd: subprocess.check_output(cmd).decode("utf-8")
def new_window(left_width):
w_list1 = get(["wmctrl", "-lG"]).splitlines()
while True:
time.sleep(1)
w_list2 = get(["wmctrl", "-lG"]).splitlines()
new = [w.split() for w in w_list2 if not w in w_list1]
if len(new) != 0:
data = new[0]
pos = 1 if int(data[2]) < left_width else 2
coords = data[2:4]
w_id = data[0]
return [w_id, pos, coords]
break
subject = new_window(left_width)
if not int(subject[1]) == target_screen:
move = -left_width if target_screen == 1 else left_width - int(subject[2][0])
subprocess.Popen(["xdotool", "windowmove", subject[0], str(int(subject[2][0])+move), subject[2][1]])
Explanation
Breaking into the startup process itself didn't seem a clean solutions to me in this situation, so the solution below works on an "incidental" base (only when you call it from a key combination).
If the script is called, it waits for 15 seconds for a new window to appear and moves it to either the right- or left screen (if it isn't already on the targeted screen) and subsequently terminates. After 15 seconds, it terminates anyway to prevent running infinitely if no window appears.
Note
The script assumes the screens are top-alligned. If there is a large difference, the script might need a little tweaking to prevent windows from "bumping" against the border of the other screen.
Here's an idea for a startup script or at least a script that can be bound to a shortcut to launch windows for the first time:
Step 1
Find out your root window width and height. This can be done with
xwininfo -root | awk '/Width/,/Height/ {print}'
or
xprop -root | awk '$1~/NET_DESKTOP_GEOMETRY/ {print }
Sample outputs are bellow
$ xwininfo -root | awk '/Width/,/Height/ {print}'
Width: 1366
Height: 768
$ xprop -root | awk '$1~/NET_DESKTOP_GEOMETRY/ {print}'
_NET_DESKTOP_GEOMETRY(CARDINAL) = 1366, 768
Step 2
Install wmctrl
with sudo apt-get install wmctrl
This tool allows for altering some of the windows properties by referring to their hex id or the window title. I've explained how it works on another question which i will link later here
Step 3
Create this script in your ~/bin
folder or somewhere that is part of your path. You can also bind the full path to this script to shortcut or create a .desktop
shortcut. Notice that since my screen is 1366 x 768, I use 1300 as my max right side x-offset. Adapt the script according to your specs in step 1. Notice that if you have duplicate windows, this might break, so this is good mostly for launching two program windows for the first time
#!/bin/sh
# Author: Serg Kolo
# Description: Send two different applications to different windows
set -x
LEFT=$(zenity --entry --text="What to put on the left?")
RIGHT=$(zenity --entry --text="What to put on the right?")
$LEFT &
$RIGHT &
sleep 1
if [ $? -eq 0 ]; then
# Get title of the left window
LEFT_TITLE="$(wmctrl -l | grep -i $LEFT | awk '{$1=$2=$3="";print}')"
# Get title of the right window
RIGHT_TITLE="$(wmctrl -l | grep -i $RIGHT | awk '{$1=$2=$3="";print }')"
printf "THIS IS A TEST %s",$LEFT_TITLE
printf "THIS IS A TEST 2 %s",$RIGHT_TITLE
wmctrl -r $LEFT_TITLE -e 0,0,0,600,600
sleep 0.5
wmctrl -r $RIGHT_TITLE -e 0,1300,0,600,600
fi
Now, you could adapt this script to behave as a launcher for just one window and specify if you want that to be on right side or left. I will work on this idea a little bit later in the day, but basic idea is to again, use two popups and if statement. Another idea that I have is to use awk to extract relevant info from single popup. I'll edit my answer once I complete the scripts
Edit
And here is the launcher for single window; type in programname,L
for left placement, and programname,R
for right placement
#!/bin/sh
# set -x
PROG=$(zenity --entry --text="Program,L or R ?")
NAME=$(echo $PROG | cut -d ',' -f1)
SIDE=$(echo $PROG | cut -d ',' -f2)
$NAME &
sleep 1
if [ $? -eq 0 ]
then
TITLE=$( wmctrl -l | grep -i $NAME| awk '{$1=$2=$3=""; print}' )
sleep 0.5
if [ $SIDE = "L" ];then
wmctrl -r $TITLE -e 0,0,0,600,600
else
wmctrl -r $TITLE -e 0,1300,0,600,600
fi
fi