Può essere fatto molto bene, ma è necessario un po 'di comprensione su Unity / viewport. Spero che la storia qui sotto sia comprensibile, in caso contrario, si prega di lasciare un commento.
Lo script seguente può essere utilizzato per aprire una finestra di qualsiasi applicazione su uno dei tuoi viewport, in qualsiasi posizione, se lo esegui con gli argomenti giusti. Lo script è una versione modificata di questo , ma ora è pronto per posizionare le finestre sul desktop virtuale di spanning .
1. Comprensione delle finestre e delle coordinate della finestra
Aree di lavoro in Unity
In Unity, a differenza di altri gestori di finestre, in realtà hai solo un'area di lavoro estesa, che è divisa in finestre. Nel tuo caso, l'area di lavoro è divisa in otto finestre.
Come viene definita la posizione delle finestre
La posizione della finestra, come output del comando:
wmctrl -lG
(you need to have wmctrl installed to run the command)
è descritta come la posizione, relativa all'angolo in alto a sinistra della finestra corrente :
Quindi, se sei su viewport 1
:
una finestra su viewport 2 potrebbe essere posizionata ad esempio su 1700 (x-saggio) x 500 (y-saggio)
(il mio schermo è 1680x1050)
Tuttavia, se sei su viewport 6:
la stessa finestra verrebbe posizionata su 20 (x), -550 (y)
L'uso corretto di queste coordinate è importante per eseguire lo script con gli argomenti giusti, come descritto di seguito:
2. Come usare lo script
Lo script seguente può essere utilizzato per posizionare una nuova finestra di un'applicazione nell'area di lavoro virtuale (spanning).
Assicurarsi che wmctrl
sia installato:
sudo apt-get install wmctrl
Copia lo script seguente in un file vuoto, salvalo come setwindow
(senza estensione) in ~/bin
. Crea la directory se non esiste ancora. Rendi eseguibile lo script .
- Se hai appena creato
~/bin
, esegui il comando source ~/.profile
o esci / accedi per rendere disponibile la directory $PATH
.
Test eseguire il comando:
setwindow <application> <x_position> <y_position> <horizontal_size> <vertical_size>
per esempio
setwindow gedit 100 100 200 200
Una finestra gedit dovrebbe apparire sulla finestra corrente.
Appunti:
- Tieni presente che non tutte le applicazioni consentono dimensioni di finestre inferiori a una determinata larghezza o altezza. La larghezza minima di una
gedit
finestra sul mio sistema è ad es. Appr. 470 px.
- Lo script funziona bene solo se l'intera finestra si adatta alla finestra di destinazione, scegli le coordinate / dimensioni di conseguenza. Ricorda inoltre che Unity Launcher e il pannello utilizzano dello spazio (!) Che può influenzare la posizione della finestra.
- Usa negativo
<x_position>
per posizionare le finestre a sinistra delle finestre correnti
- Usa negativo
<y_position>
per posizionare le finestre sopra le finestre correnti
Per aprire contemporaneamente nuove finestre su finestre diverse, puoi semplicemente concatenare i comandi. Osservando la configurazione della finestra nell'esempio "Storia lunga", Se sono su Viewport 1, posso aprire Windows gedit su Viewport 1, 2, 3 e 4 con il comando:
setwindow gedit 100 100 200 200&&setwindow gedit 1780 100 200 200&&setwindow gedit 3460 100 200 200&&setwindow gedit 5140 100 200 200
Il copione
#!/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: la versione pigra
Nel caso in cui preferissi inserire solo coordinate e dimensioni, semplicemente come se aprissi una finestra sulla finestra corrente e fornissi la finestra di destinazione come argomento (senza dover calcolare nulla), quindi utilizza la versione seguente ...
Se lo configuri come la prima versione dello script, puoi eseguirlo con il comando:
setwindow <application> <x_position> <y_position> <horizontal_size> <vertical_size> <targeted_viewport>
Un esempio: per aprire una Google-Chrome
finestra posizionata su 20, 20
, dimensioni 300x300
, su viewport 5
:
setwindow google-chrome 20 20 300 300 5
L'installazione è praticamente la stessa della prima versione dello script.
Si noti che anche questo script funziona correttamente solo se la finestra (posizione / dimensione) definita si adatta perfettamente alla vista di destinazione.
Il copione:
#!/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
Apertura di finestre dell'applicazione con argomenti
Per finire il lavoro, rispondendo completamente alla tua domanda:
Se esegui lo script come ad esempio:
setwindow google-chrome 20 20 300 300 5
si aprirà una finestra predefinita sui desktop target.
Con l'ultima versione dello script, tuttavia, è possibile aggiungere un argomento aggiuntivo per aprire la finestra dell'applicazione, ad esempio un url
:
setwindow <application> <x_position> <y_position> <horizontal_size> <vertical_size> <targeted_viewport> <(optional)_argument>
per esempio:
setwindow google-chrome 0 0 600 600 3 "--new-window http://askubuntu.com"
Se l'argomento (extra) contiene spazi, utilizzare le virgolette. L'esempio sopra aprirà una google-chrome
finestra su viewport 3, aprendo il url
http://askubuntu.com
.
È possibile concatenare i comandi per aprire più finestre / URL su diverse aree di lavoro in un solo comando, ad esempio:
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
, che è come un software per il controllo di Windows tramite script o terminale. Ma per quanto riguarda il riavvio di una finestra, questa potrebbe essere una sorta di sfida in più