Es kann sehr gut gemacht werden, aber Sie benötigen etwas Verständnis für Unity / Ansichtsfenster. Ich hoffe, die folgende Geschichte ist verständlich. Wenn nicht, hinterlassen Sie bitte einen Kommentar.
Das folgende Skript kann verwendet werden, um ein Fenster einer beliebigen Anwendung in einem Ihrer Ansichtsfenster an einer beliebigen Position zu öffnen, wenn Sie es mit den richtigen Argumenten ausführen. Das Skript ist eine bearbeitete Version dieses Skripts, ist jedoch jetzt darauf vorbereitet, Fenster auf dem übergreifenden virtuellen Desktop zu platzieren .
1. Grundlegendes zu Ansichtsfenstern und Fensterkoordinaten
Arbeitsbereiche in Einheit
In Unity haben Sie im Gegensatz zu anderen Fenstermanagern nur einen übergreifenden Arbeitsbereich, der in Ansichtsfenster unterteilt ist. In Ihrem Fall ist Ihr Arbeitsbereich in acht Ansichtsfenster unterteilt.
Wie die Position der Fenster definiert wird
Die Fensterposition als Ausgabe des Befehls:
wmctrl -lG
(you need to have wmctrl installed to run the command)
wird als Position relativ zur oberen linken Ecke des aktuellen Ansichtsfensters beschrieben :
Wenn Sie sich also im Ansichtsfenster befinden 1
:
Ein Fenster in Ansichtsfenster 2 kann beispielsweise auf 1700 (x-weise) x 500 (y-weise)
positioniert werden (mein Bildschirm ist 1680x1050).
Wenn Sie sich jedoch in Ansichtsfenster 6 befinden, wird
dasselbe Fenster auf 20 (x), -550 (y) positioniert.
Die korrekte Verwendung dieser Koordinaten ist wichtig, um das Skript mit den richtigen Argumenten auszuführen, wie unten beschrieben:
2. Verwendung des Skripts
Mit dem folgenden Skript können Sie ein neues Fenster einer Anwendung in Ihrem virtuellen (übergreifenden) Arbeitsbereich platzieren.
Stellen Sie sicher, dass wmctrl
installiert ist:
sudo apt-get install wmctrl
Kopieren Sie das folgende Skript in eine leere Datei und speichern Sie es als setwindow
(keine Erweiterung) in ~/bin
. Erstellen Sie das Verzeichnis, falls es noch nicht vorhanden ist. Machen Sie das Skript ausführbar .
- Wenn Sie gerade erstellt haben
~/bin
, führen Sie entweder den Befehl aus source ~/.profile
oder melden Sie sich ab, um das Verzeichnis in verfügbar zu machen $PATH
.
Testen Sie den Befehl:
setwindow <application> <x_position> <y_position> <horizontal_size> <vertical_size>
z.B
setwindow gedit 100 100 200 200
Im aktuellen Ansichtsfenster sollte ein gedit-Fenster angezeigt werden.
Anmerkungen:
- Beachten Sie, dass nicht alle Anwendungen Fenstergrößen unterhalb einer bestimmten Breite oder Höhe zulassen. Die Mindestbreite eines
gedit
Fensters auf meinem System beträgt z. 470 px.
- Das Skript funktioniert nur dann einwandfrei, wenn das gesamte Fenster auf das gewünschte Ansichtsfenster passt. Wählen Sie Ihre Koordinaten / Größen entsprechend aus. Beachten Sie auch, dass der Unity Launcher und das Bedienfeld etwas Platz (!) Verwenden, der die Position des Fensters beeinflussen kann.
- Verwenden Sie Negativ
<x_position>
, um Fenster links von den aktuellen Ansichtsfenstern zu platzieren.
- Verwenden Sie Negativ
<y_position>
, um Fenster über den aktuellen Ansichtsfenstern zu platzieren.
Um neue Fenster in verschiedenen Ansichtsfenstern gleichzeitig zu öffnen, können Sie einfach Befehle verketten. Wenn ich mich in Ansichtsfenster 1 befinde, kann ich gedit-Fenster in Ansichtsfenster 1, 2, 3 und 4 mit dem folgenden Befehl öffnen:
setwindow gedit 100 100 200 200&&setwindow gedit 1780 100 200 200&&setwindow gedit 3460 100 200 200&&setwindow gedit 5140 100 200 200
Das Skript
#!/usr/bin/env python3
import subprocess
import time
import sys
app = sys.argv[1]
get = lambda x: subprocess.check_output(["/bin/bash", "-c", x]).decode("utf-8")
ws1 = get("wmctrl -lp"); t = 0
subprocess.Popen(["/bin/bash", "-c", app])
# fix exception for Chrome (command = google-chrome-stable, but processname = chrome)
app = "chrome" if "chrome" in app else app
while t < 30:
ws2 = [w.split()[0:3] for w in get("wmctrl -lp").splitlines() if not w in ws1]
procs = [[(p, w[0]) for p in get("ps -e ww").splitlines() \
if app in p and w[2] in p] for w in ws2]
if len(procs) > 0:
w_id = procs[0][0][1]
cmd1 = "wmctrl -ir "+w_id+" -b remove,maximized_horz"
cmd2 = "wmctrl -ir "+w_id+" -b remove,maximized_vert"
cmd3 = "wmctrl -ir "+procs[0][0][1]+" -e 0,"+sys.argv[2]+","+sys.argv[3]+","+sys.argv[4]+","+sys.argv[5]
for cmd in [cmd1, cmd2, cmd3]:
subprocess.call(["/bin/bash", "-c", cmd])
break
time.sleep(0.5)
t = t+1
EDIT: die faule Version
Wenn Sie lieber nur Koordinaten und Größe eingeben möchten, als würden Sie ein Fenster im aktuellen Ansichtsfenster öffnen und das Zielansichtsfenster als Argument angeben (ohne etwas berechnen zu müssen), verwenden Sie die folgende Version ...
Wenn Sie es wie die erste Version des Skripts einrichten, können Sie es mit dem folgenden Befehl ausführen:
setwindow <application> <x_position> <y_position> <horizontal_size> <vertical_size> <targeted_viewport>
Ein Beispiel: ein zum Öffnen Google-Chrome
Fenster positioniert 20, 20
, Größe 300x300
, auf Darstellungsfeld 5
:
setwindow google-chrome 20 20 300 300 5
Das Setup entspricht weitgehend der ersten Version des Skripts.
Beachten Sie, dass auch dieses Skript nur dann ordnungsgemäß funktioniert, wenn das definierte Fenster (Position / Größe) vollständig in das Zielansichtsfenster passt.
Das Skript:
#!/usr/bin/env python3
import subprocess
import time
import sys
app = sys.argv[1]
target_vp = int(sys.argv[6])
def get_res():
# get resolution
xr = subprocess.check_output(["xrandr"]).decode("utf-8").split()
pos = xr.index("current")
return [int(xr[pos+1]), int(xr[pos+3].replace(",", "") )]
res = get_res()
def current(set_vp):
# get the current viewport
vp_data = subprocess.check_output(
["wmctrl", "-d"]
).decode("utf-8").split()
dt = [int(n) for n in vp_data[3].split("x")]
cols = int(dt[0]/res[0])
rows = int(dt[1]/res[1])
curr_vpdata = [int(n) for n in vp_data[5].split(",")]
curr_col = int(curr_vpdata[0]/res[0])
curr_row = int(curr_vpdata[1]/res[1])
curr_vp = curr_col+curr_row*cols+1
# calculate the vector to the origin from the current viewport (in resolution units)
vec_curr = vector(curr_vp, cols)
# calculate the vector to the origin from the targeted viewport
vec_set = vector(set_vp, cols)
# calculate the vector between current and targeted viewport
vec_relative = [vec_set[0] - vec_curr[0],
vec_set[1] - vec_curr[1]]
# calculate needed correction (absolute)
relative = [vec_relative[0]*res[0],
vec_relative[1]*res[1]]
return relative
def vector(vp, cols):
rem = vp%cols
vec_x = rem-1 if rem != 0 else cols-1
vec_y = int((vp-1)/cols)
return [vec_x, vec_y]
res = get_res() # nieuw
get = lambda x: subprocess.check_output(["/bin/bash", "-c", x]).decode("utf-8")
ws1 = get("wmctrl -lp"); t = 0
# check for additional arguments to run the application
try:
subprocess.Popen(["/bin/bash", "-c", app+" "+sys.argv[7]])
except IndexError:
subprocess.Popen(["/bin/bash", "-c", app])
# fix exception for Chrome (command = google-chrome-stable, but processname = chrome)
app = "chrome" if "chrome" in app else app
while t < 30:
ws2 = [w.split()[0:3] for w in get("wmctrl -lp").splitlines() if not w in ws1]
procs = [[(p, w[0]) for p in get("ps -e ww").splitlines() \
if app in p and w[2] in p] for w in ws2]
if len(procs) > 0:
w_id = procs[0][0][1]
cmd1 = "wmctrl -ir "+w_id+" -b remove,maximized_horz"
cmd2 = "wmctrl -ir "+w_id+" -b remove,maximized_vert"
# calculate the correction, related to the current workspace, marge for launcher and panel
pos_x = int(sys.argv[2]); pos_y = int(sys.argv[3]); x_marge = 65; y_marge = 35
pos_x = pos_x if pos_x > x_marge else x_marge; pos_y = pos_y if pos_y > y_marge else y_marge
x_relative = pos_x+current(target_vp)[0]
y_relative = pos_y+current(target_vp)[1]
# correct possible inaccurately set width / height
x_size = res[0]; y_size = res[1]
set_width = int(sys.argv[4]); set_height = int(sys.argv[5])
width = set_width if set_width+x_marge+pos_x < x_size else x_size - pos_x - x_marge
height = set_height if set_height+y_marge+pos_y < y_size else y_size - pos_y - y_marge
cmd3 = "wmctrl -ir "+w_id+" -e 0,"+str(x_relative)+","+str(y_relative)+","+str(width)+","+str(height)
for cmd in [cmd1, cmd2, cmd3]:
subprocess.call(["/bin/bash", "-c", cmd])
break
time.sleep(0.5)
t = t+1
Anwendungsfenster mit Argumenten öffnen
Um den Job zu beenden, beantworten Sie Ihre Frage vollständig:
Wenn Sie das Skript wie folgt ausführen:
setwindow google-chrome 20 20 300 300 5
Es wird ein Standardfenster auf den Ziel-Desktops geöffnet .
Mit der neuesten Version des Skripts können Sie jedoch ein zusätzliches Argument hinzufügen , um das Anwendungsfenster zu öffnen, z. B. a url
:
setwindow <application> <x_position> <y_position> <horizontal_size> <vertical_size> <targeted_viewport> <(optional)_argument>
z.B:
setwindow google-chrome 0 0 600 600 3 "--new-window http://askubuntu.com"
Wenn das (zusätzliche) Argument Leerzeichen enthält, verwenden Sie Anführungszeichen. Das obige Beispiel öffnet ein google-chrome
Fenster in Ansichtsfenster 3 und öffnet das url
http://askubuntu.com
.
Sie können Befehle verketten, um mehrere Fenster / URLs in verschiedenen Arbeitsbereichen in einem Befehl zu öffnen, z.
setwindow google-chrome 0 0 600 600 8 "--new-window http://askubuntu.com"&&setwindow google-chrome 0 0 600 600 7 "--new-window www.google.com"
wmctrl
eine Software zur Steuerung von Fenstern über ein Skript oder ein Terminal. Aber was den Neustart eines Fensters