web-dev-qa-db-ja.com

wmctrlにアプリケーションの最近使用されたウィンドウを表示させるにはどうすればよいですか?

wmctrl -x -a "$1"を実行するスクリプトがあります。スクリプトに引数として渡されるウィンドウが表示されます。例:

wmctrl -x -a "Firefox" 

firefoxを起動します。

ただし、複数のウィンドウを持つアプリケーションでは、last使用済みウィンドウは表示されません。 「Doc 1」、「Doc 2」、「Doc 3」という名前の3つのウィンドウがLibreOffice Writerで開いていて、Doc 3を使用していて、別のアプリケーションに移動したとします。スクリプトを実行すると、最後に使用された「Doc 3」ではなく「Doc 1」が表示されます。

wmctrlでこの問題を修正するためのフラグはありますか?

1
Salil Surendran

リクエストに応じて、新しいセクションで補足された別の回答の分割。

ウィンドウのフォーカス履歴

アプリケーションの最近フォーカスされたウィンドウを上げる方法

私のコメントで述べたように、現在、ウィンドウのフォーカス履歴はありません。つまり、必要な場合は、自分で作成する必要があります。以下の最初のスクリプトは、まさにそれを行います。現在フォーカスされているウィンドウを追跡し、1秒に1回更新される小さなファイルに履歴を保存します。行の順序はフォーカスの順序でもあります。一番上の行は最新のフォーカスされたウィンドウを表し、最後の行は「最も古い」ウィンドウを表します。

スクリプトでアプリケーションの最も最近フォーカスされたウィンドウを発生させるには、行を上から下に読んで、アプリケーションのウィンドウの最初のオカレンスを見つけてそれを発生させるだけです。求めるウィンドウのWM_CLASSを指定して実行すると、2番目のスクリプトがまさにそれを行います。

スクリプト

  1. フォーカス履歴を追跡するバックグラウンドスクリプト。このスクリプトは、最初のスクリプトの正確なコピーです here

    #!/usr/bin/env python3
    import subprocess
    import time
    import os
    
    rootdata = os.environ["HOME"]+"/.focus_history"
    open(rootdata, "wt").write("This is an empty line")
    
    def current_windows():
        try:
            return subprocess.check_output(["wmctrl", "-lp"]).decode("utf-8")
        except subprocess.CalledProcessError:
            pass
    
    def convert_format(w_id):
        return w_id[:2]+(10-len(w_id))*"0"+w_id[2:]
    
    def read_data():
        return open(rootdata).read().splitlines()
    
    def get_top(wlist):
        try:
            top = convert_format(
                [l.split("#")[-1].strip() for l in subprocess.check_output(
                    ["xprop", "-root"]
                    ).decode("utf-8").splitlines() \
                   if "_NET_ACTIVE_WINDOW(WINDOW)" in l][0])
            return [l for l in wlist if top in l][0]
        except IndexError:
            pass
    
    if __name__ == "__main__":
        while True:
            time.sleep(1)
            wdata = current_windows()
            if wdata != None:
                wlist = wdata.splitlines()
                # get frontmost window (as in wmctrl -lG)
                top = get_top(wlist)
                oldlist = read_data()
                if not any([top == oldlist[0], top == None]):
                    # clean up closed windows
                    [oldlist.remove(l) for l in oldlist if not l.split()[0] in wdata]
                    # remove possible other mentions of the active window
                    [oldlist.remove(l) for l in oldlist if l.startswith(top.split()[0])]
                    open(rootdata, "wt").write(("\n").join([top]+oldlist))
    

    スクリプトを空のファイルにコピーし、focus_history.pyとして保存します

  2. アプリケーションの最新フォーカスウィンドウを発生させるスクリプト。

    #!/usr/bin/env python3
    import os
    import subprocess
    import sys
    
    lookfor = sys.argv[1]
    winhistory = os.environ["HOME"]+"/.focus_history"
    
    for l in open(winhistory):
        wid = l.split()[0]
        wmclass = subprocess.check_output(
            ["xprop", "-id", wid, "WM_CLASS"]
            ).decode("utf-8").strip()
        if lookfor in wmclass:
            subprocess.check_output(["wmctrl", "-ia", wid])
            break
    

    raise_recent.pyとして保存します。

使い方

  1. wmctrlがインストールされていることを確認してください:

    Sudo apt install wmctrl
    
  2. 次のコマンドを使用して、最初のスクリプトをバックグラウンドとしてテスト実行します。

    python3 /path/to/focus_history.py
    

    NBスクリプトが開始することを確認してくださいbeforeotherウィンドウが開いている場合、ウィンドウが記録されるのは(もちろん)最初のフォーカスを取得した後のみです。

  3. コマンドで2番目のスクリプトを呼び出します(例)

    python3 /path/to/raise_recent.py gedit
    

    ...最近フォーカスされたgeditのウィンドウを上げる。

  4. すべてが正常に機能する場合は、最初のスクリプトをスタートアップアプリケーションに追加します。ただし、wmctrlが壊れないようにするには、スクリプトを開始する前に区切りを追加する必要があることに注意してください。 (ただし、このスクリプトは、可能性のある例外を処理するため、すべきではありません)。

それでおしまい。

2
Jacob Vlijm