สามารถทำได้ดีมาก แต่คุณต้องมีความเข้าใจเกี่ยวกับ Unity / วิวพอร์ต ฉันหวังว่าเรื่องราวด้านล่างนี้เป็นที่เข้าใจได้ถ้าไม่ใช่โปรดแสดงความคิดเห็น
สคริปต์ด้านล่างนี้สามารถใช้เพื่อเปิดหน้าต่างของแอปพลิเคชันใด ๆ ในวิวพอร์ตใด ๆ ของคุณในทุกตำแหน่งหากคุณเรียกใช้ด้วยอาร์กิวเมนต์ที่ถูกต้อง สคริปต์นี้เป็นเวอร์ชันที่ถูกแก้ไขของอันนี้แต่ตอนนี้ได้เตรียมที่จะวาง windows บนเดสก์ท็อปเสมือนที่ขยายออก
1. การทำความเข้าใจวิวพอร์ตและพิกัดหน้าต่าง
พื้นที่ทำงานใน Unity
ใน Unity ซึ่งแตกต่างจากตัวจัดการหน้าต่างอื่น ๆ จริง ๆ แล้วคุณมีพื้นที่ทำงานเพียงแห่งเดียวซึ่งแบ่งออกเป็นวิวพอร์ต ในกรณีของคุณเวิร์กสเปซของคุณแบ่งออกเป็นแปดวิวพอร์ต
วิธีการกำหนดตำแหน่งของหน้าต่าง
ตำแหน่งหน้าต่างเป็นผลลัพธ์ของคำสั่ง:
wmctrl -lG
(you need to have wmctrl installed to run the command)
ถูกอธิบายว่าเป็นตำแหน่งซึ่งสัมพันธ์กับมุมซ้ายบนของวิวพอร์ตปัจจุบัน :
ดังนั้นหากคุณอยู่ในวิวพอร์ต1
:
หน้าต่างในวิวพอร์ต 2 ที่สามารถวางตำแหน่งบนเช่น 1700 (x-wise) x 500 (y-wise)
(หน้าจอของฉันคือ 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 px
- สคริปต์จะทำงานได้ดีถ้าทั้งหน้าต่างพอดีกับวิวพอร์ตเป้าหมายให้เลือกพิกัด / ขนาดของคุณตามนั้น นอกจากนี้โปรดทราบว่าตัวเรียกใช้งาน Unity และแผงควบคุมนั้นใช้พื้นที่ (!) ซึ่งสามารถมีอิทธิพลต่อตำแหน่งของหน้าต่าง
- ใช้ค่าลบ
<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
เปิด
คุณสามารถโยงคำสั่งเพื่อเปิดหลาย windows / 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
ซึ่งเป็นเหมือนซอฟต์แวร์สำหรับควบคุมหน้าต่างผ่านสคริปต์หรือเทอร์มินัล แต่สำหรับการรีสตาร์ทหน้าต่างนั่นอาจเป็นเรื่องท้าทายอีกเล็กน้อย