可以做得很好,但是您需要对Unity /视口有一些了解。我希望下面的故事是可以理解的,如果不能理解,请发表评论。
如果您使用正确的参数运行以下脚本,则可以使用以下脚本在任何视口中的任何位置打开任何应用程序的窗口。剧本是经过编辑的版本这一个,但现在准备把窗户上的跨越虚拟桌面。
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
我的系统上窗口的最小宽度为例如appr。470像素
- 仅当整个窗口适合目标视口时,脚本才能正常工作,并相应地选择坐标/尺寸。另外请注意,Unity Launcher和面板使用的空格(!)可能会影响窗口的位置。
- 使用负片
<x_position>
将窗口放置在当前视口的左侧
- 使用负片
<y_position>
将窗口放置在当前视口上方
要一次在不同视口上打开新窗口,只需链接命令即可。在“ Long story”示例中查看视口设置,如果我在视口1上,则可以使用以下命令在视口1、2、3和4上打开gedit窗口:
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
,就像一个通过脚本或终端控制窗口的软件。但是对于重新启动窗口,这可能会带来更多挑战