web-dev-qa-db-ja.com

wmctrlがスクリプト内でウィンドウのサイズ変更/移動に失敗する

たくさんのプログラムを開き、画面上のウィンドウを移動/サイズ変更するスクリプトを作成しようとしています。

例えば、

#!/bin/bash
zim
wmctrl -r Zim -b toggle,maximized_vert
wmctrl -r Zim -e 0,700,0,-1,-1

このスクリプトを実行すると、ウィンドウが最大化され、少し右に移動します。ただし、zimfirefoxまたはacroreadに置き換えると、ウィンドウの移動/サイズ変更に失敗します。

ターミナルでwmctrlと入力しても動作しますが、それが欲しいのですスクリプト内firefoxが画面上の位置を記憶する方法に関係しているに違いないと思います。

編集:配置しました

firefox
wmctrl -lG

スクリプト内で次の出力を取得します。

0x03800032  0 1168 347  750  731  briareos emacs@briareos
0x02a00002  0 -2020 -1180 1920 1080 briareos XdndCollectionWindowImp
0x02a00005  0 0    24   47   1056 briareos unity-launcher
0x02a00008  0 0    0    1920 24   briareos unity-panel
0x02a0000b  0 -420 -300 320  200  briareos unity-dash
0x02a0000c  0 -420 -300 320  200  briareos Hud
0x03c00011  0 59   52   900  1026 briareos Notes - Zim

これは、Firefoxが起動されたことをスクリプトが認識しないことを意味します。

2
Magicsowon

問題

問題は、使用するコマンドの組み合わせにおいて、wmctrlコマンドが成功するためには、アプリケーションのウィンドウを時間内に表示するために「幸運」である必要があるということです。
あなたのコマンドは、ほとんどの場合、軽度のアプリケーションで動作し、すぐに起動しますが、Inkscape、Firefox、Thunderbirdなどの他のアプリケーションでは動作しません。

can build-あなたがやったように5〜10秒の休憩で(コメントで言及)、必要以上に長く待たなければならないか、プロセッサが占有されている場合は結局壊れますまた、ウィンドウは「通常よりも後」です。

ソリューション

その場合の解決策は、スクリプトにプロシージャを含め、wmctrl -lpの出力にウィンドウが表示されるのを待ってから、コマンドを実行してウィンドウを最大化することです。

以下のpythonの例では、xdotoolを使用してウィンドウのサイズを変更しました。私の経験では、wmctrlを使用して作業を行うよりも堅牢です。

#!/usr/bin/env python3
import subprocess
import getpass
import time
import sys

app = sys.argv[1]

# to only list processes of the current user
user = getpass.getuser()
get = lambda x: subprocess.check_output(x).decode("utf-8")
# get the initial window list
ws1 = get(["wmctrl", "-lp"]); t = 0
# run the command to open the application
subprocess.Popen(app)

while t < 30:
    # fetch the updated window list, to see if the application's window appears
    ws2 = [(w.split()[2], w.split()[0]) for w in get(["wmctrl", "-lp"]).splitlines() if not w in ws1]
    # see if possible new windows belong to our application
    procs = sum([[(w[1], p) for p in get(["ps", "-u", user]).splitlines() \
              if app[:15].lower() in p.lower() and w[0] in p] for w in ws2], [])
    # in case of matches, move/resize the window
    if len(procs) > 0:
        subprocess.call(["xdotool", "windowsize", "-sync", procs[0][0] , "100%", "100%"])
        break
    time.sleep(0.5)
    t = t+1

使い方

  1. スクリプトにはwmctrlxdotoolの両方が必要です。

    Sudo apt-get install wmctrl xdotool
    
  2. スクリプトを空のファイルにコピーし、resize_window.pyとして保存します

  3. テストとして、アプリケーションを引数としてスクリプトを実行します。例:

    python3 /path/to/resize_window.py firefox
    

ノート

  • スタートアップアプリケーションでスクリプトとして使用する場合、ウィンドウリストを取得するwmctrlコマンドが実行されるのが少し早すぎる可能性があります。問題が発生した場合は、プロシージャ全体にtry/exceptを追加する必要があります。もしそうなら、私に知らせてください。
3
Jacob Vlijm