Это можно сделать очень хорошо, но вам нужно немного разбираться в Unity / viewports. Я надеюсь, что история ниже понятна, если нет, пожалуйста, оставьте комментарий.
Сценарий ниже может быть использован для открытия окна любого приложения в любом из ваших окон просмотра, в любой позиции, если вы запускаете его с правильными аргументами. Скрипт является отредактированной версией этого , но теперь он готов разместить окна на виртуальном рабочем столе .
1. Понимание области просмотра и координат окна
Рабочие пространства в Unity
В Unity, в отличие от других оконных менеджеров, у вас есть только одно рабочее пространство, которое разделено на области просмотра. В вашем случае ваше рабочее пространство разделено на восемь видов.
Как определяется положение окон
Положение окна, как вывод команды:
wmctrl -lG
(you need to have wmctrl installed to run the command)
описывается как позиция относительно левого верхнего угла текущего окна просмотра :
Поэтому, если вы находитесь в окне просмотра 1
:
окно в окне просмотра 2 может быть расположено, например, 1700 (по оси x) x 500 (по оси y)
(мой экран 1680x1050)
Однако, если вы находитесь в окне просмотра 6:
то же самое окно будет расположено на 20 (x), -550 (y)
Правильное использование этих координат важно для запуска сценария с правильными аргументами, как описано ниже:
2. Как использовать скрипт
Сценарий ниже может быть использован для размещения нового окна приложения в вашей виртуальной (охватывающей) рабочей области.
Убедитесь, что wmctrl
установлено:
sudo apt-get install wmctrl
Скопируйте приведенный ниже скрипт в пустой файл, сохраните его как setwindow
(без расширения) в ~/bin
. Создайте каталог, если он еще не существует. Сделайте скрипт исполняемым .
- Если вы только что создали
~/bin
, либо выполните команду, source ~/.profile
либо выйдите из системы, чтобы сделать каталог доступным в $PATH
.
Тестовый запуск команды:
setwindow <application> <x_position> <y_position> <horizontal_size> <vertical_size>
например
setwindow gedit 100 100 200 200
Окно Gedit должно отображаться в текущем окне просмотра.
Ноты:
- Имейте в виду, что не все приложения допускают размеры окон ниже определенной ширины или высоты. Минимальная ширина
gedit
окна в моей системе, например, ок. 470 пикселей
- Сценарий работает нормально только в том случае, если все окно помещается на целевой области просмотра, соответственно выберите ваши координаты / размеры. Также помните, что Unity Launcher и панель используют некоторое пространство (!), Которое может влиять на положение окна.
- Используйте негатив
<x_position>
для размещения окон слева от текущего видового экрана (ов)
- Используйте минус,
<y_position>
чтобы разместить окна над текущим окном просмотра
Чтобы одновременно открывать новые окна в разных окнах просмотра, вы можете просто объединять команды. Если посмотреть на настройки окна просмотра в примере «Длинная история», если я нахожусь в окне просмотра 1, я могу открыть окна gedit в окнах просмотра 1, 2, 3 и 4 с помощью команды:
setwindow gedit 100 100 200 200&&setwindow gedit 1780 100 200 200&&setwindow gedit 3460 100 200 200&&setwindow gedit 5140 100 200 200
Сценарий
#!/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
РЕДАКТИРОВАТЬ: ленивая версия
В случае, если вы предпочитаете просто ввести координаты и размер, просто, как если бы вы открыли окно в текущем окне просмотра и задали целевой порт просмотра в качестве аргумента (без необходимости что-либо вычислять), используйте версию ниже ...
Если вы установите его как первую версию скрипта, вы можете запустить его с помощью команды:
setwindow <application> <x_position> <y_position> <horizontal_size> <vertical_size> <targeted_viewport>
Пример: открыть Google-Chrome
окно, расположенное, по 20, 20
размеру 300x300
, в окне просмотра 5
:
setwindow google-chrome 20 20 300 300 5
Настройка почти такая же, как и в первой версии скрипта.
Обратите внимание, что этот скрипт также работает правильно, только если определенное окно (позиция / размер) полностью помещается в целевой области просмотра.
Сценарий:
#!/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
Открытие окна приложения с аргументами
Чтобы закончить работу, полностью отвечая на ваш вопрос:
Если вы запустите скрипт как, например:
setwindow google-chrome 20 20 300 300 5
это откроет окно по умолчанию на целевом рабочем столе (ах).
Однако в последней версии скрипта вы можете добавить дополнительный аргумент для открытия окна приложения, например url
:
setwindow <application> <x_position> <y_position> <horizontal_size> <vertical_size> <targeted_viewport> <(optional)_argument>
например:
setwindow google-chrome 0 0 600 600 3 "--new-window http://askubuntu.com"
Если (дополнительный) аргумент содержит пробелы, используйте кавычки. Приведенный выше пример откроет google-chrome
окно в окне просмотра 3, открывая url
http://askubuntu.com
.
Вы можете объединить команды, чтобы открыть несколько окон / URL-адресов в разных рабочих пространствах в одной команде, например:
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
, как программное обеспечение для управления окнами через скрипт или терминал. Но что касается перезапуска окна, это может быть чем-то более сложным