Open application window on the same screen as where It was launched
Unity uses Compiz as composing manager, and that has all sorts of plugins for this sort of stuff. To make it easy and long story short without messing in command line , install Compiz Config Settings Manager ( with sudo apt-get install compizconfig-settings-manager
or via Software Center ) , and look for Place Windows
, ensure it's checked
Under that plugin there will be several options for Multi Output Mode
. What you want is Use output device of focused window
. Thus it will place open file window wherever your file manager is
Redirecting the command to run an application
Most applications open their window on the screen they were initiated from (either from Dash or the launcher). Some applications however do not, but they can be forced to, by redirecting the command to run the application through the script below. To do that, you will need to edit the corresponding .desktop
file (launcher).
The setup seems a bit complicated, but if the procedure is followed ("How to use"), it should not be too difficult at all.
How it works
- The script reads the mouse position at the moment you click the launcher or choose the application from Dash, and determines on which screen that is (left/right).
- Subsquently, it waits for the new window to appear, owned by the application (pid) you started.
- Once the window appears, it checks if the window (screen-) position matches the mouse (screen-) initial position.
- If not, it moves the window to the screen you started the application from. In most cases, the action will be in a (very) early stage of the window's existance, so you even won't notice it.
Issue / solution
There is one downside: if you replace the .desktop
file's main command by the command to call this script, the right-click "open with " will not work properly. In the case of a webbrowser like Google Chrome, that will not be too big a problem. With other applications, a simple solution would be to add the option to open a new window on the current screen as a shortcut (see further below).
How to use:
-
The script uses both
wmctrl
andxautomation
:sudo apt-get install xautomation sudo apt-get install wmctrl
Create a directory
~/bin
if it does not exist yet.Copy the script into an empty file, save it as
open_oncurrent
(no extension) in~/bin
- Make it executable(!)
-
Copy the corresponding
.desktop
file from/usr/share/applications
to~/.local/share/applications
:cp /usr/share/applications/google-chrome.desktop ~/.local/share/applications/google-chrome.desktop
-
Open the local copy in
~/.local/share/applications
:gedit ~/.local/share/applications/google-chrome.desktop
-
Edit the file (two options):
-
To change the main command of the launcher:
-
find the line:
Exec=/usr/bin/google-chrome-stable %U
-
change it to
Exec=/bin/bash -c "open_oncurrent /usr/bin/google-chrome-stable"
-
-
To add the option as a shortcut (like in the image above):
-
find the line:
X-Ayatana-Desktop-Shortcuts=NewWindow;NewIncognito;
-
replace it by:
X-Ayatana-Desktop-Shortcuts=NewWindow;NewIncognito;New window on this screen;
-
Then add the following section to the very end of the file:
[New window on this screen Shortcut Group] Name=New window on this screen Exec=/bin/bash -c "open_oncurrent /usr/bin/google-chrome-stable" TargetEnvironment=Unity
-
-
How to use with other applications:
Similarly, you can apply the solution to other applications. The syntax of the command to use in the .desktop
fileis like the example:
Exec=/bin/bash -c "open_oncurrent <command>"
A small additional explanation on how to deal with exceptions is in the script.
The script
#!/usr/bin/env python3
import subprocess
import sys
import time
import getpass
t = 0; user = getpass.getuser(); application = sys.argv[1]
"""
In most cases, the command to run an application is the same as the process
name. There are however exceptions, to be listed below, if you use these appli-
cations i.c.w. this script. Just add an item to the list in the format:
["<command>", "<process_name>"],
"""
exceptions = [
["/usr/bin/google-chrome-stable", "chrome"],
]
try:
procname = [app[1] for app in exceptions if app[0] == application][0]
except IndexError:
procname = application
get = lambda cmd: subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")
# initial position of the mouse (click position)
start_pos = int(get("xmousepos").strip().split()[0])
# x- position of right side of the screen
x_res = [int(s.split("x")[0]) for s in get("xrandr").split() if s.endswith("+0+0")][0]
# current windows
start_windows = get("wmctrl -l")
# open application
subprocess.call(["/bin/bash", "-c", application+"&"])
while t < 30:
procs = get("ps -u "+user).splitlines()
new = [w for w in get("wmctrl -lpG").splitlines() if not w.split()[0] in start_windows]
match = sum([[line for line in procs if w.split()[2] in line and procname[:15] in line] for w in new], [])
if len(match) == 1:
data = new[0].split(); curr_pos = int(data[3]); compare = (start_pos > x_res, curr_pos > x_res)
if compare[0] == compare[1]:
pass
else:
if compare[0] == True:
data[3] = str(int(data[3])+x_res)
else:
data[3] = str(int(data[3])-x_res)
cmd1 = "wmctrl -r "+data[0]+" -b remove,maximized_vert,maximized_horz"
cmd2 = "wmctrl -ir "+data[0]+" -e 0,"+(",").join(data[3:7])
for cmd in [cmd1, cmd2]:
subprocess.Popen(["/bin/bash", "-c", cmd])
break
t = t + 1
time.sleep(0.5)