Isso pode ser feito muito bem, mas você precisa de algum entendimento sobre Unity / viewports. Espero que a história abaixo seja compreensível, se não, por favor, deixe um comentário.
O script abaixo pode ser usado para abrir uma janela de qualquer aplicativo em qualquer uma das suas viewports, em qualquer posição, se você a executar com os argumentos corretos. O script é uma versão editada deste , mas agora preparado para colocar janelas na área de trabalho virtual de abrangência .
1. Compreendendo viewports e coordenadas de janela
Áreas de trabalho no Unity
No Unity, diferentemente de outros gerenciadores de janelas, na verdade você só possui um espaço de trabalho de abrangência, que é dividido em viewports. No seu caso, seu espaço de trabalho é dividido em oito viewports.
Como a posição das janelas é definida
A posição da janela, como a saída do comando:
wmctrl -lG
(you need to have wmctrl installed to run the command)
é descrita como a posição, relativa ao canto superior esquerdo da viewport atual :
Portanto, se você estiver na viewport 1
:
uma janela na viewport 2 poderá ser posicionada em, por exemplo, 1700 (x) X 500 (Y)
(minha tela é 1680x1050)
No entanto, se você estiver na viewport 6:
a mesma janela seria posicionada em 20 (x), -550 (y)
Usar essas coordenadas corretamente é importante para executar o script com os argumentos corretos, conforme descrito abaixo:
2. Como usar o script
O script abaixo pode ser usado para colocar uma nova janela de um aplicativo no seu espaço de trabalho virtual (estendido).
Verifique se wmctrl
está instalado:
sudo apt-get install wmctrl
Copie o script abaixo em um arquivo vazio, salve-o como setwindow
(sem extensão) em ~/bin
. Crie o diretório se ele ainda não existir. Torne o script executável .
- Se você acabou de criar
~/bin
, execute o comando source ~/.profile
ou efetue logout / logon para disponibilizar o diretório $PATH
.
Teste, execute o comando:
setwindow <application> <x_position> <y_position> <horizontal_size> <vertical_size>
por exemplo
setwindow gedit 100 100 200 200
Uma janela do gedit deve aparecer na viewport atual.
Notas:
- Lembre-se de que nem todos os aplicativos permitem tamanhos de janela abaixo de uma certa largura ou altura. A largura mínima de uma
gedit
janela no meu sistema é, por exemplo, appr. 470 px.
- O script só funciona bem se a janela inteira se encaixar na janela de exibição alvo, escolha suas coordenadas / tamanhos de acordo. Lembre-se também de que o Unity Launcher e o painel usam algum espaço (!) Que pode influenciar a posição da janela.
- Use negativo
<x_position>
para colocar janelas à esquerda das janelas de visualização atuais
- Use negativo
<y_position>
para colocar janelas acima da (s) janela (s) atual (is)
Para abrir novas janelas em diferentes viewports ao mesmo tempo, você pode simplesmente encadear comandos. Observando a configuração da viewport no exemplo "Long story", se eu estiver na viewport 1, posso abrir janelas do gedit nas viewport 1, 2, 3 e 4 com o 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
O script
#!/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: a versão preguiçosa
Caso prefira inserir coordenadas e tamanho, basta abrir uma janela na viewport atual e exibir a viewport direcionada como argumento (sem precisar calcular nada), e use a versão abaixo ...
Se você configurá-lo como a primeira versão do script, poderá executá-lo com o comando:
setwindow <application> <x_position> <y_position> <horizontal_size> <vertical_size> <targeted_viewport>
Um exemplo: para abrir uma Google-Chrome
janela posicionada em 20, 20
, tamanho 300x300
, na janela de exibição 5
:
setwindow google-chrome 20 20 300 300 5
A configuração é praticamente a mesma que a primeira versão do script.
Observe que também esse script funciona corretamente se a janela definida (posição / tamanho) se encaixar completamente na viewport de destino.
O script:
#!/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
Abrindo janelas de aplicativos com argumentos
Para finalizar o trabalho, responda sua pergunta completamente:
Se você executar o script como por exemplo:
setwindow google-chrome 20 20 300 300 5
ele abrirá uma janela padrão nos desktops direcionados.
No entanto, com a versão mais recente do script, você pode adicionar um argumento adicional para abrir a janela do aplicativo, por exemplo url
:
setwindow <application> <x_position> <y_position> <horizontal_size> <vertical_size> <targeted_viewport> <(optional)_argument>
por exemplo:
setwindow google-chrome 0 0 600 600 3 "--new-window http://askubuntu.com"
Se o argumento (extra) contiver espaços, use aspas. O exemplo acima abrirá uma google-chrome
janela na janela de visualização 3, abrindo o url
http://askubuntu.com
.
Você pode encadear comandos para abrir várias janelas / URLs em diferentes áreas de trabalho em um comando, por exemplo:
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
, que é como um software para controlar janelas através de script ou terminal. Mas, como para o reinício de uma janela, que pode ser algo de um pouco mais de desafio