我怎样才能让 wmctrl 提升应用程序最近聚焦的窗口?

我怎样才能让 wmctrl 提升应用程序最近聚焦的窗口?

我正在运行一个脚本wmctrl -x -a "$1"。它会弹出一个窗口,作为参数传递给脚本,例如:

wmctrl -x -a "Firefox" 

激活 Firefox。

然而,对于有多个窗口的应用程序,它不会调出最后的使用的窗口。假设我在 中打开了 3 个窗口LibreOffice Writer,分别名为“文档 1”、“文档 2”和“文档 3”,我现在在文档 3 上,然后转到另一个应用程序。执行脚本会显示“文档 1”,而不是上次使用的“文档 3”。

有没有什么标志可以解决这个问题wmctrl

答案1

根据要求,分离出另一个答案,并补充一个新的部分。

窗口的焦点历史记录

如何提升应用程序最近聚焦的窗口

正如我在评论中提到的,目前没有窗口的焦点历史记录。这意味着如果我们需要它,我们需要自己创建它。下面的第一个脚本正是这样做的;它跟踪当前聚焦的窗口,并将历史记录存储在一个小文件中,每秒刷新一次。行的顺序也是焦点的顺序;顶行代表最新的聚焦窗口,最后一行代表“最旧的”。

要使脚本调出应用程序最近聚焦的窗口,我们需要做的就是从上到下阅读这些行,找到应用程序窗口的第一个出现位置,然后调出它。如果您使用所WM_CLASS寻找窗口的 运行第二个脚本,那么它正是这样做的。

脚本

  1. 后台脚本,跟踪焦点历史记录。此脚本与第一个脚本完全相同这里

    #!/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
    

    注意:确保脚本启动其他窗口打开,否则窗口只有在获得第一个焦点后才会被记录(当然)。

  3. 使用命令调用第二个脚本(例如)

    python3 /path/to/raise_recent.py gedit
    

    ...调出最近聚焦的窗口gedit

  4. 如果一切正常,请将第一个脚本添加到启动应用程序。但请注意,您可能需要在脚本启动前添加一个中断,以防止wmctrl中断。(尽管脚本不应该这样做,因为它处理可能的异常)。

就是这样。

相关内容