Nó có thể được thực hiện rất tốt, nhưng bạn cần một số hiểu biết về Unity / viewports. Tôi hy vọng câu chuyện dưới đây là dễ hiểu, nếu không, xin vui lòng để lại nhận xét.
Các kịch bản dưới đây có thể được sử dụng để mở một cửa sổ của bất kỳ ứng dụng trên bất kỳ khung nhìn của bạn, vào vị trí bất kỳ, nếu bạn chạy nó với các đối số đúng. Kịch bản là một phiên bản chỉnh sửa của cái này , nhưng bây giờ đã chuẩn bị để đặt các cửa sổ trên màn hình ảo kéo dài .
1. Hiểu về khung nhìn và tọa độ cửa sổ
Không gian làm việc trong Unity
Trong Unity, không giống như các trình quản lý cửa sổ khác, bạn thực sự chỉ có một không gian làm việc kéo dài, được chia thành các khung nhìn. Trong trường hợp của bạn, không gian làm việc của bạn được chia thành tám khung nhìn.
Vị trí của các cửa sổ được xác định như thế nào
Vị trí cửa sổ, là đầu ra của lệnh:
wmctrl -lG
(you need to have wmctrl installed to run the command)
được mô tả là vị trí, liên quan đến góc trên bên trái của chế độ xem hiện tại :
Vì vậy, nếu bạn đang ở chế độ xem 1
:
một cửa sổ trên chế độ xem 2 có thể được định vị trên ví dụ: 1700 (x-khôn) x 500 (y-khôn)
(màn hình của tôi là 1680x1050)
Tuy nhiên, nếu bạn ở chế độ xem 6:
cùng một cửa sổ sẽ được định vị trên 20 (x), -550 (y)
Sử dụng các tọa độ này một cách chính xác là rất quan trọng để chạy tập lệnh với các đối số phù hợp, như được mô tả dưới đây:
2. Cách sử dụng tập lệnh
Kịch bản dưới đây có thể được sử dụng để đặt một cửa sổ mới của ứng dụng trên không gian làm việc (kéo dài) ảo của bạn.
Đảm bảo đã wmctrl
được cài đặt:
sudo apt-get install wmctrl
Sao chép tập lệnh bên dưới vào một tệp trống, lưu nó dưới dạng setwindow
(không có phần mở rộng) trong ~/bin
. Tạo thư mục nếu nó chưa tồn tại. Làm cho kịch bản thực thi .
- Nếu bạn vừa tạo
~/bin
, hãy chạy lệnh source ~/.profile
hoặc đăng xuất / đăng nhập để làm cho thư mục có sẵn $PATH
.
Chạy thử lệnh:
setwindow <application> <x_position> <y_position> <horizontal_size> <vertical_size>
ví dụ
setwindow gedit 100 100 200 200
Một cửa sổ gedit sẽ hiển thị trên khung nhìn hiện tại.
Ghi chú:
- Hãy nhớ rằng không phải tất cả các ứng dụng đều cho phép kích thước cửa sổ dưới một chiều rộng hoặc chiều cao nhất định. Chiều rộng tối thiểu của một
gedit
cửa sổ trên hệ thống của tôi là ví dụ như appr. 470 px.
- Kịch bản chỉ hoạt động tốt nếu toàn bộ cửa sổ vừa với khung nhìn được nhắm mục tiêu, chọn tọa độ / kích thước của bạn cho phù hợp. Cũng lưu ý rằng Unity Launcher và bảng điều khiển sử dụng một số khoảng trắng (!) Có thể ảnh hưởng đến vị trí của cửa sổ.
- Sử dụng phủ định
<x_position>
để đặt các cửa sổ ở bên trái của (các) chế độ xem hiện tại
- Sử dụng phủ định
<y_position>
để đặt các cửa sổ phía trên (các) chế độ xem hiện tại
Để mở các cửa sổ mới trên các chế độ xem khác nhau cùng một lúc, bạn có thể chỉ cần xâu chuỗi các lệnh. Nhìn vào thiết lập chế độ xem trong ví dụ "Câu chuyện dài", Nếu tôi ở chế độ xem 1, tôi có thể mở các cửa sổ gedit trên chế độ xem 1, 2, 3 và 4 bằng lệnh:
setwindow gedit 100 100 200 200&&setwindow gedit 1780 100 200 200&&setwindow gedit 3460 100 200 200&&setwindow gedit 5140 100 200 200
Kịch bản
#!/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: phiên bản lười biếng
Trong trường hợp bạn chỉ muốn nhập tọa độ và kích thước, đơn giản như thể bạn sẽ mở một cửa sổ trên chế độ xem hiện tại và đưa ra chế độ xem được nhắm mục tiêu làm đối số (không phải tính toán bất cứ điều gì), sau đó sử dụng phiên bản bên dưới ...
Nếu bạn thiết lập nó giống như phiên bản đầu tiên của tập lệnh, bạn có thể chạy nó bằng lệnh:
setwindow <application> <x_position> <y_position> <horizontal_size> <vertical_size> <targeted_viewport>
Một ví dụ: để mở một Google-Chrome
cửa sổ được định vị 20, 20
, kích thước 300x300
, trên khung nhìn 5
:
setwindow google-chrome 20 20 300 300 5
Thiết lập khá giống với phiên bản đầu tiên của tập lệnh.
Lưu ý rằng tập lệnh này chỉ hoạt động chính xác nếu cửa sổ được xác định (vị trí / kích thước) hoàn toàn phù hợp với chế độ xem được nhắm mục tiêu.
Kịch bản:
#!/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
Mở cửa sổ ứng dụng bằng các đối số
Để hoàn thành công việc, trả lời hoàn toàn câu hỏi của bạn:
Nếu bạn chạy tập lệnh như:
setwindow google-chrome 20 20 300 300 5
nó sẽ mở một cửa sổ mặc định trên (các) máy tính để bàn được nhắm mục tiêu.
Tuy nhiên, với phiên bản mới nhất của tập lệnh, bạn có thể thêm một đối số bổ sung để mở cửa sổ ứng dụng, ví dụ url
:
setwindow <application> <x_position> <y_position> <horizontal_size> <vertical_size> <targeted_viewport> <(optional)_argument>
ví dụ:
setwindow google-chrome 0 0 600 600 3 "--new-window http://askubuntu.com"
Nếu đối số (thêm) chứa khoảng trắng, hãy sử dụng dấu ngoặc kép. Ví dụ trên sẽ mở một google-chrome
cửa sổ trên khung nhìn 3, mở url
http://askubuntu.com
.
Bạn có thể xâu chuỗi các lệnh để mở nhiều cửa sổ / url trên các không gian làm việc khác nhau trong một lệnh, ví dụ:
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
, giống như một phần mềm để điều khiển các cửa sổ thông qua tập lệnh hoặc thiết bị đầu cuối. Nhưng đối với việc khởi động lại một cửa sổ, đó có thể là một thử thách lớn hơn một chút