これは キーボードのみを使用してウィンドウを別の画面にすばやく配置する に似ていますが、コマンドラインを使用できるようにしたいので(コマンドラインをリコールするだけです) bash履歴)。
たとえば、送信
eDP1
へのすべてのgnome端末ウィンドウ、VGA1
に、およびHDMI1
へ(そして、移動後に最大化する-しかし、クレイジーではない F11 方法、通常のウィンドウマネージャースタイルの最大化)。
実行可能ファイル名でウィンドウを指定したいと思います。
以下のスクリプトは、特定のWM_CLASS
(アプリケーション)に属するウィンドウを特定の画面に、画面のnameで送信します。それがどのように行われるかは、スクリプトで説明されています。
このスクリプトは、画面が水平に配置され、多少上下に揃えられることを想定しています(差は<100 PX)。
#!/usr/bin/env python3
import subprocess
import sys
# just a helper function, to reduce the amount of code
get = lambda cmd: subprocess.check_output(cmd).decode("utf-8")
# get the data on all currently connected screens, their x-resolution
screendata = [l.split() for l in get(["xrandr"]).splitlines() if " connected" in l]
screendata = sum([[(w[0], s.split("+")[-2]) for s in w if s.count("+") == 2] for w in screendata], [])
def get_class(classname):
# function to get all windows that belong to a specific window class (application)
w_list = [l.split()[0] for l in get(["wmctrl", "-l"]).splitlines()]
return [w for w in w_list if classname in get(["xprop", "-id", w])]
scr = sys.argv[2]
try:
# determine the left position of the targeted screen (x)
pos = [sc for sc in screendata if sc[0] == scr][0]
except IndexError:
# warning if the screen's name is incorrect (does not exist)
print(scr, "does not exist. Check the screen name")
else:
for w in get_class(sys.argv[1]):
# first move and resize the window, to make sure it fits completely inside the targeted screen
# else the next command will fail...
subprocess.Popen(["wmctrl", "-ir", w, "-e", "0,"+str(int(pos[1])+100)+",100,300,300"])
# maximize the window on its new screen
subprocess.Popen(["xdotool", "windowsize", "-sync", w, "100%", "100%"])
スクリプトには、wmctrl
とxdotool
の両方が必要です。
Sudo apt-get install xdotool wmctrl
以下のスクリプトを空のファイルにコピーし、move_wclass.py
として保存します
次のコマンドで実行します:
python3 /path/to/move_wclass.py <WM_CLASS> <targeted_screen>
例えば:
python3 /path/to/move_wclass.py gnome-terminal VGA-1
WM_CLASS
には、例のようにWM_CLASS
のpartを使用できます。画面の名前は、exactおよび完全な名前である必要があります。
説明は主にコンセプトに関するものであり、コーディングに関するものではありません。
Xrandrの出力には、接続されているすべての画面について、次のような文字列/行があります。
VGA-1 connected 1280x1024+1680+0
この行は、画面のpositionとそのnameに関する情報を提供します。説明 ここ 。
スクリプトは、すべての画面の情報をリストします。画面とウィンドウクラスを引数としてスクリプトを実行すると、画面の(x-)位置を検索し、特定のクラスのすべてのウィンドウ(-idの)を検索します(wmctrl -l
の助けを借りて)およびxprop -id <window_id>
の出力。
その後、スクリプトはすべてのウィンドウを1つずつターゲット画面上の位置に移動し(wmctrl -ir <window_id> -e 0,<x>,<y>,<width>,<height>
を使用)、最大化します(xdotool windowsize 100% 100%
を使用)。
スクリプトは、実行したテストで正常に機能しました。 Unityでwmctrl
、さらにはxdotool
を使用すると、頑固な特性を持つことがありますが、推論ではなく実験によって解決する必要がある場合があります。例外が発生する可能性がある場合は、言及してください。
@jacobs pythonコードを単純なbashに書き直して動作させました(ubuntu 16シナモンでこれをテストしました)。
ウィンドウが動かないままremove,maximized_vert, remove,maximized_horz
を追加する必要がありました。
#!/bin/bash
if [ ! -z "$1" ] || [ -z "$2" ]; then
command=$(wmctrl -l | grep $1 | cut -d" " -f1)
if [ ! -z "$command" ]; then
position=$(xrandr | grep "^$2" | cut -d"+" -f2)
if [ ! -z "$position" ]; then
for window in $command; do
wmctrl -ir $window -b remove,maximized_vert
wmctrl -ir $window -b remove,maximized_horz
wmctrl -ir $window -e 0,$position,0,1920,1080
wmctrl -ir $window -b add,maximized_vert
wmctrl -ir $window -b add,maximized_horz
done
else
echo -e "not found monitor with given name"
fi
else
echo -e "not found windows with given name"
fi
else
echo -e "specify window and monitor name;\nmove.sh window-name monitor-name"
fi
Sudo apt-get install xdotool wmctrl
/path/to/script.sh "window-name" "monitor-name"
記録のために、この質問と 複数のモニター設定を復元する の組み合わせに使用するものを以下に示します。
# configure multiplr displays and
# move the windows to their appropriate displays
import subprocess
import os
import wmctrl
import re
mydisplays = [("VGA1",0,"left"),
("eDP1",1080,"normal"),
("HDMI1",3000,"left")]
# https://askubuntu.com/questions/702002/restore-multiple-monitor-settings
def set_displays ():
subprocess.check_call(" && ".join([
"xrandr --output %s --pos %dx0 --rotate %s" % d for d in mydisplays]),
Shell=True)
# https://askubuntu.com/questions/702071/move-windows-to-specific-screens-using-the-command-line
mywindows = [("/emacs$","VGA1"),
("/chrome$","HDMI1"),
("gnome-terminal","eDP1")]
def max_windows ():
didi = dict([(d,x) for d,x,_ in mydisplays])
for w in wmctrl.Window.list():
try:
exe = os.readlink("/proc/%d/exe" % (w.pid))
for (r,d) in mywindows:
if re.search(r,exe):
x = didi[d]
print "%s(%s) --> %s (%d)" % (r,exe,d,x)
w.set_properties(("remove","maximized_vert","maximized_horz"))
w.resize_and_move(x,0,w.w,w.h)
w.set_properties(("add","maximized_vert","maximized_horz"))
break
except OSError:
continue
def cmdlines (cmd):
return subprocess.check_output(cmd).splitlines()
def show_displays ():
for l in cmdlines(["xrandr"]):
if " connected " in l:
print l
if __== '__main__':
show_displays()
set_displays()
show_displays()
max_windows()