Unityと15.4の仮想デスクトップで15.04を使用しています。
デスクトップ1でウィンドウを開いてデスクトップ2を表示しているとき(たとえば)、ビューをデスクトップ1に切り替えることなく、デスクトップ1からそのウィンドウをデスクトップ2に簡単に表示する方法はありますか?
したがって、非表示のデスクトップ(および最終的にはそのウィンドウで開いている他のウィンドウ)を表示せずに、現在非表示のデスクトップからアクティブなデスクトップにウィンドウを取得したいと考えています。
これを達成する簡単な方法はありますか?
以下のスクリプトが呼び出されると、すべてのワークスペースのすべてのウィンドウがリストされます。 1つを選択して押してください OK ウィンドウを現在のワークスペースに移動して引き上げます。デフォルトでは、ウィンドウを100
(x)、100
(y)の位置に移動します。
wmctrl
とxdotool
の両方を使用しているため、スクリプトは比較的単純です。 wmctrl
はすべてのウィンドウをリストするために使用されますが、xdotool
は、ウィンドウのサイズを「質問せずに」現在のワークスペースの事前定義された位置に移動します(wmctrl
とは異なります)。両方のワークスペースの相対的な位置。
元のワークスペースでの位置に応じて、ウィンドウをより正確に配置することは非常に可能ですが、必要なコードも乗算されます(例: here )。ほとんどの場合、これで十分だと思います。
例:
私はワークスペース8にいますが、ワークスペース1にはgedit
ウィンドウがあります。スクリプトを呼び出すと、ウィンドウが一覧表示されます。
geditウィンドウを選択すると、現在のワークスペースに移動します。
#!/usr/bin/env python3
import subprocess
import socket
import time
def get(command):
return subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")
def check_window(w_id):
w_type = get("xprop -id "+w_id)
if " _NET_WM_WINDOW_TYPE_NORMAL" in w_type:
return True
else:
return False
# split wmctrl output by machine name
wlist = [l.split(socket.gethostname()) for l in get("wmctrl -l").splitlines()]
# extract window -id from first section
wlist = [[wlist[i][0].split()[0], wlist[i][-1].strip()] for i, l in enumerate(wlist)]
# filter only "real, normal" windows
wlist = [w for w in wlist if check_window(w[0]) == True]
# create columns for zenity list
cols = (" ").join(['"'+w[1]+'" '+'"'+w[0]+'"' for w in wlist])
# calculate height and width for the zenity window, according to window names and list length
h = str(140+(len(wlist)*23))
w = str((max([len(w[-1]) for w in wlist])*8))
# define the zenity window
cmd = "zenity --list --hide-column=2 --print-column=2 "+\
"--title='Window list' --column='Current windowlist' "+\
"--column='wid' --height="+h+" --width="+w+" "+cols
try:
# call the window
w_id = get(cmd).split("|")[-1].strip()
# move the selected window to the current workspace
subprocess.Popen(["xdotool", "windowmove", "--sync", w_id, "100", "100"])
# raise it (the command below alone should do the job, but sometimes fails
# on firefox windows without first moving the window).
subprocess.Popen(["wmctrl", "-iR", w_id])
except subprocess.CalledProcessError:
pass
スクリプトにはwmctrl
とxdotool
の両方が必要です
Sudo apt-get install wmctrl xdotool
スクリプトを空のファイルにコピーし、move_windows.py
として保存します
次のコマンドでテスト実行します。
python3 /path/to/move_windows.py
ウィンドウが表示され、現在開いているウィンドウが一覧表示されます。
いずれかを選択して、現在のワークスペースに移動され、正しく上げられているかどうかを確認してください。
すべて正常に機能する場合は、ショートカットキーに広告を表示します。[システム設定]> [キーボード]> [ショートカット]> [カスタムショートカット]を選択します。 「+」をクリックして、コマンドを追加します。
python3 /path/to/move_windows.py
現在のウィンドウを一覧表示するzenity
ウィンドウのサイズは自動的に設定されます。スクリプトは、最長のウィンドウ名と行数(ウィンドウ)を探し、それに応じてサイズを設定します。
コメントで要求されているように、zenity
list-ウィンドウに詳細情報が含まれているバージョンの下:decurrentターゲットウィンドウのワークスペース(s)およびそれが属するアプリケーション。
上記のように、ワークスペースの相対的/絶対位置に関する情報は、より「相当な」量のコードにつながりますが、幸いにも私はこの以前の答えをベースとして使用できました。
使用方法はスクリプトの最初のバージョン(上記)とほとんど同じですが、コマンドには優先ソートオプションを含める必要があります。次のいずれかのコマンドで実行します。
python3 /path/to/move_windows.py -app
リストをアプリケーションでソートするには、
python3 /path/to/move_windows.py -ws
リストをワークスペースでソートし、
python3 /path/to/move_windows.py -win
リストをウィンドウ名でソートします。
#!/usr/bin/env python3
import subprocess
import socket
import sys
arg = sys.argv[1]
# list (column) header titles and their (data) position in the produced window data list
cols = [["Workspace", -1], ["Application name", -2] , ["Window name", -3]]
# rearrange columns, depending on the chosen option
if arg == "-app":
cols = [cols[1], cols[2], cols[0]]
Elif arg == "-ws":
cols = [cols[0], cols[2], cols[1]]
Elif arg == "-win":
cols = [cols[2], cols[1], cols[0]]
# extract headers, list positions, to be used in the zenity list
col1 = cols[0][0]; i1 = cols[0][1]
col2 = cols[1][0]; i2 = cols[1][1]
col3 = cols[2][0]; i3 = cols[2][1]
# just a helper function
get = lambda cmd: subprocess.check_output([
"/bin/bash", "-c", cmd
]).decode("utf-8")
# analyse viewport data, to be able to calculate relative/absolute position of windows
# and current viewport
def get_spandata():
xr = get("xrandr").split(); pos = xr.index("current")
res = [int(xr[pos+1]), int(xr[pos+3].replace(",", "") )]
spandata = get("wmctrl -d").split()
span = [int(n) for n in spandata[3].split("x")]
cols = int(span[0]/res[0]); rows = int(span[1]/res[1])
curr_vector = [int(n) for n in spandata[5].split(",")]
curr_viewport = int((curr_vector[1]/res[1])*cols + (curr_vector[0]/res[0])+1)
return {"resolution": res, "n_columns": cols, "vector": curr_vector, "current_viewport": curr_viewport}
posdata = get_spandata()
vector = posdata["vector"]; cols = posdata["n_columns"]
res = posdata["resolution"]; currvp = posdata["current_viewport"]
# function to distinguish "normal" windows from other types (like the desktop etc)
def check_window(w_id):
w_type = get("xprop -id "+w_id)
if " _NET_WM_WINDOW_TYPE_NORMAL" in w_type:
return True
else:
return False
# split windowdata by machine name
mach_name = socket.gethostname()
wlist = [[l.strip() for l in w.split(mach_name)] for w in get("wmctrl -lpG").splitlines()]
# split first section of window data
for i, w in enumerate(wlist):
wlist[i][0] = wlist[i][0].split()
# filter only "real" windows
real_wlist = [w for w in wlist if check_window(w[0][0]) == True]
# adding the viewport to the window's data
for w in real_wlist:
w.append(get("ps -p "+w[0][2]+" -o comm=").strip())
loc_rel = [int(n) for n in w[0][3:5]]
loc_abs = [loc_rel[0]+vector[0], loc_rel[1]+vector[1]]
abs_viewport = int((loc_abs[1]/res[1])*cols + (loc_abs[0]/res[0])+1)
abs_viewport = str(abs_viewport)+"*" if abs_viewport == currvp else str(abs_viewport)
w.append(abs_viewport)
# set sorting rules
if arg == "-app":
real_wlist.sort(key=lambda x: x[-2])
Elif arg == "-ws":
real_wlist.sort(key=lambda x: x[-1])
Elif arg == "-win":
real_wlist.sort(key=lambda x: x[-3])
# calculate width and height of the zenity window:
# height = 140px + 23px per line
h = str(140+(len(real_wlist)*23))
# width = 250px + 8px per character (of the longest window title)
w = str(250+(max([len(w[-3]) for w in real_wlist])*8))
# define the zenity window's content
cmd = "zenity --list --hide-column=4 --print-column=4 --title='Window list' "\
"--width="+w+" --height="+h+" --column='"+col1+"' --column='"+col2+"' --column='"+col3+\
"' --column='w_id' "+(" ").join([(" ").join([
'"'+w[i1]+'"','"'+w[i2]+'"','"'+w[i3]+'"','"'+w[0][0]+'"'
]) for w in real_wlist])
# finally, call the window list
try:
w_id = subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8").split("|")[0]
subprocess.Popen(["xdotool", "windowmove", "--sync", w_id, "100", "100"])
subprocess.Popen(["wmctrl", "-iR", w_id])
except subprocess.CalledProcessError:
pass
使用されたps
コマンドの出力は、15.04のgnome-terminal
で変更されたようです。したがって、15.04では、gnome-terminal
のアプリケーション名が上記のスクリプトで正しく表示されませんでした。以下のバージョンは、xprop
コマンドの出力のように、WM_CLASS
からアプリケーション名を派生させます。
使い方は上記の(2番目の)スクリプトとまったく同じです。
#!/usr/bin/env python3
import subprocess
import socket
import sys
arg = sys.argv[1]
# list (column) header titles and their (data) position in the produced window data list
cols = [["Workspace", -1], ["Application name", -2] , ["Window name", -3]]
# rearrange columns, depending on the chosen option
if arg == "-app":
cols = [cols[1], cols[2], cols[0]]
Elif arg == "-ws":
cols = [cols[0], cols[2], cols[1]]
Elif arg == "-win":
cols = [cols[2], cols[1], cols[0]]
# extract headers, list positions, to be used in the zenity list
col1 = cols[0][0]; i1 = cols[0][1]
col2 = cols[1][0]; i2 = cols[1][1]
col3 = cols[2][0]; i3 = cols[2][1]
# just a helper function
get = lambda cmd: subprocess.check_output([
"/bin/bash", "-c", cmd
]).decode("utf-8")
# analyse viewport data, to be able to calculate relative/absolute position of windows
# and current viewport
def get_spandata():
xr = get("xrandr").split(); pos = xr.index("current")
res = [int(xr[pos+1]), int(xr[pos+3].replace(",", "") )]
spandata = get("wmctrl -d").split()
span = [int(n) for n in spandata[3].split("x")]
cols = int(span[0]/res[0]); rows = int(span[1]/res[1])
curr_vector = [int(n) for n in spandata[5].split(",")]
curr_viewport = int((curr_vector[1]/res[1])*cols + (curr_vector[0]/res[0])+1)
return {"resolution": res, "n_columns": cols, "vector": curr_vector, "current_viewport": curr_viewport}
posdata = get_spandata()
vector = posdata["vector"]; cols = posdata["n_columns"]
res = posdata["resolution"]; currvp = posdata["current_viewport"]
# function to distinguish "normal" windows from other types (like the desktop etc)
def check_window(w_id):
w_type = get("xprop -id "+w_id)
if " _NET_WM_WINDOW_TYPE_NORMAL" in w_type:
cl = [l.replace('"', '').split(",")[-1].strip()\
for l in w_type.splitlines() if "WM_CLASS(STRING)" in l][0]
return (True, cl)
else:
return (False, "")
# split windowdata by machine name
mach_name = socket.gethostname()
wlist = [[l.strip() for l in w.split(mach_name)] for w in get("wmctrl -lpG").splitlines()]
# split first section of window data
for i, w in enumerate(wlist):
wlist[i][0] = wlist[i][0].split()
# filter only "real" windows
real_wlist = [w+[check_window(w[0][0])[1]] for w in wlist if check_window(w[0][0])[0] == True]
# adding the viewport to the window's data
for w in real_wlist:
loc_rel = [int(n) for n in w[0][3:5]]
loc_abs = [loc_rel[0]+vector[0], loc_rel[1]+vector[1]]
abs_viewport = int((loc_abs[1]/res[1])*cols + (loc_abs[0]/res[0])+1)
abs_viewport = str(abs_viewport)+"*" if abs_viewport == currvp else str(abs_viewport)
w.append(abs_viewport)
# set sorting rules
if arg == "-app":
real_wlist.sort(key=lambda x: x[-2])
Elif arg == "-ws":
real_wlist.sort(key=lambda x: x[-1])
Elif arg == "-win":
real_wlist.sort(key=lambda x: x[-3])
# calculate width and height of the zenity window:
# height = 140px + 23px per line
h = str(140+(len(real_wlist)*23))
# width = 250px + 8px per character (of the longest window title)
w = str(250+(max([len(w[-3]) for w in real_wlist])*8))
# define the zenity window's content
cmd = "zenity --list --hide-column=4 --print-column=4 --title='Window list' "\
"--width="+w+" --height="+h+" --column='"+col1+"' --column='"+col2+"' --column='"+col3+\
"' --column='w_id' "+(" ").join([(" ").join([
'"'+w[i1]+'"','"'+w[i2]+'"','"'+w[i3]+'"','"'+w[0][0]+'"'
]) for w in real_wlist])
# finally, call the window list
try:
w_id = subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8").split("|")[0]
subprocess.Popen(["xdotool", "windowmove", "--sync", w_id, "100", "100"])
subprocess.Popen(["wmctrl", "-iR", w_id])
except subprocess.CalledProcessError:
pass