【问题标题】:Cycle through windows of the same application using wmcrtl使用 wmcrtl 循环浏览同一应用程序的窗口
【发布时间】:2023-03-08 10:13:01
【问题描述】:

我正在配置 xbindkeys 以使用快捷方式更改窗口焦点。 例如,我设法创建了一个专注于应用程序窗口的快捷方式,比如说一个终结器窗口:

wmctrl -xa terminator

不幸的是,它总是聚焦在同一个终止符窗口,阻止我循环浏览终止符窗口。

您能否建议我一个集中在终止符窗口上的命令,如果再次按下,将在所有终止符窗口中循环,好吗?

2013 年 3 月 30 日更新

我修改了这个脚本 http://lars.st0ne.at/blog/switch%20between%20windows%20within%20the%20same%20application 制作一个这样的脚本

script.sh NAME

关注应用程序 NAME 或循环浏览 NAME 的所有窗口,如果它的一个窗口已经获得焦点,但它不能正常工作。

这是脚本

win_class=$1 # 'terminator' # $1

# get list of all windows matching with the class above
win_list=$(wmctrl -x -l | grep -i $win_class | awk '{print $1}' )

# get id of the focused window
active_win_id=$(xprop -root | grep '^_NET_ACTIVE_W' | awk -F'# 0x' '{print $2}')

# get next window to focus on, removing id active
switch_to=$(echo $win_list | sed s/.*$active_win_id// | awk '{print $1}')

# if the current window is the last in the list ... take the first one
if [ "$switch_to" == '' ];then
   switch_to=$(echo $win_list | awk '{print $1}')
fi

# switch to window
wmctrl -i -a $switch_to

脚本确实专注于应用程序的一个窗口,并在它们之间循环,直到它到达一个窗口,我猜是最后创建的。到那时,骑自行车就行不通了。

【问题讨论】:

    标签: linux focus keyboard-shortcuts console-application window-managers


    【解决方案1】:

    我在脚本中发现了一个问题,如果没有窗口有焦点。

    您可以尝试以下修改后的脚本:

    #!/bin/bash
    win_class=$1 # 'terminator' # $1
    
    # get list of all windows matching with the class above
    win_list=$(wmctrl -x -l | grep -i $win_class | awk '{print $1}' )
    
    # get id of the focused window
    active_win_id=$(xprop -root | grep '^_NET_ACTIVE_W' | awk -F'# 0x' '{print $2}')
    if [ "$active_win_id" == "0" ]; then
        active_win_id=""
    fi
    
    # get next window to focus on, removing id active
    switch_to=$(echo $win_list | sed s/.*$active_win_id// | awk '{print $1}')
    
    # if the current window is the last in the list ... take the first one
    if [ "$switch_to" == '' ];then
       switch_to=$(echo $win_list | awk '{print $1}')
    fi
    
    # switch to window
    wmctrl -i -a $switch_to
    

    【讨论】:

    • 它有效,谢谢!实际上问题可能是另一个问题:我的文件不是以#!/bin/bash 开头的......对不起我的愚蠢。你知道为什么第一行在这种情况下会产生这种影响吗?
    • ...我猜“/bin/sh”指向“/b​​in/dash”而不是“/bin/bash”。上面的脚本不是独立于 shell 的。将脚本中的“==”替换为“=”,它也应该与破折号一起使用。
    【解决方案2】:

    脚本适合我。

    无论如何,在您的情况下,脚本似乎找不到活动窗口。因此,它设法切换到您的应用程序,但无法循环通过。它切换到 $win_list 中的第一个窗口,因为 sed 命令无法从 $win_list 中删除活动窗口(以及之前的所有列表条目)。

    尝试以下命令:

    xprop -root _NET_ACTIVE_WINDOW
    

    输出应该是这样的:

    _NET_ACTIVE_WINDOW(WINDOW): window id # 0x2400005
    

    属性“_NET_ACTIVE_WINDOW”是 EWMH 标准的一部分。见:http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html

    也许您正在使用不符合EWMH(扩展窗口管理器提示)的窗口管理器! 你用的是哪个WM?

    ...一些窗口管理器允许通过配置或插件启用 EWMH 兼容性。

    【讨论】:

    • 我正在使用 KDE+OpenBox。你的命令给了我正确的输出。 _NET_ACTIVE_WINDOW(WINDOW): window id # 0x7a0001d
    • 命令“wmctrl -x -l | grep -i terminator”是否显示多个窗口?
    • 你可以测试一下:打开 3 个 konsole 窗口;在第一个窗口中发出命令“script.sh konsole”-> 应该切换到第二个 konsole 窗口;在新的活动窗口中发出“script.sh konsole”...这应该在三个 konsole 窗口之间切换。
    • 我试过用我的终结器窗口进行测试,它可以工作......知道为什么它在 xbindkeys 中不能正常工作吗?
    • 我刚刚用 xbindkeys 测试了这个脚本,它就像一个魅力。 ……谢邦? ... chmod +x 脚本 ... 环境路径
    【解决方案3】:

    通过 st0ne 改编脚本后,我有了一个通用的版本(不需要指定 app_name)。希望这对某人有用。 :)

    #!/bin/bash
    active_win_id=`xprop -root | grep '^_NET_ACTIVE_W' | awk -F'# 0x' '{print $2}' | awk -F', ' '{print $1}'`
    if [ "$active_win_id" == "0" ]; then
        active_win_id=""
    fi
    
    app_name=`wmctrl -lx | grep $active_win_id | awk '{print $3}'`
    workspace_number=`wmctrl -d | grep '\*' | cut -d' ' -f 1`
    win_list=`wmctrl -lx | grep -ri $app_name | grep " $workspace_number " | awk '{print $1}'`
    
    # get next window to focus on, removing id active
    switch_to=`echo $win_list | sed s/.*$active_win_id// | awk '{print $1}'`
    # if the current window is the last in the list ... take the first one
    if [ "$switch_to" == "" ];then
        switch_to=`echo $win_list | awk '{print $1}'`
    fi
    
    
    if [[ -n "${switch_to}" ]]
        then
            (wmctrl -ia "$switch_to") &
        else
            if [[ -n "$2" ]]
                then
                    ($2) &
            fi
    fi
    
    
    exit 0
    

    【讨论】:

      【解决方案4】:

      我遇到了tkt028's answer 的一个小问题1,但我喜欢他们在处理任何通用应用程序方面所做的工作。但我也很喜欢st0ne's answer 如何处理在一个专门命名的应用程序的窗口中循环。所以我结合了这些方法。

      我的脚本采用可选的第一个参数来指定应循环其窗口的应用程序。如果没有找到这样的窗口,并且如果提供了可选的第二个参数,它将回退到启动第二个参数指定的命令。

      如果根本没有提供任何参数,那么它只会在当前活动应用程序的窗口中循环。

      #!/bin/bash
      
      if [[ "$1" == "-h" || "$1" == "--help" ]]; then
          echo "Cycle through windows of the active, or specified, application."
          echo ""
          echo "Usage: $(basename $0) [window_class_name [application_launcher]]"
          echo ""
          echo "  window_class_name:    regex string specifying an application's window name,"
          echo "                        as specified by the third column of"
          echo "                        'wmctrl -l -x'"
          echo "  application_launcher: application to optionally launch if no windows"
          echo "                        matching window_class_name are found"
          echo ""
          echo "If no arguments are specified, cycles through the windows of the active application."
          exit
      fi
      
      # get ID of active window
      active_win_id=`xprop -root | grep '^_NET_ACTIVE_W' | awk -F'# 0x' '{print $2}' | awk -F', ' '{print $1}'`
      if [ "$active_win_id" == "0" ]; then
          active_win_id=""
      fi
      
      if [[ -n "$1" ]]; then
          # get app name from input argument
          app_name="$1"
      else
          # get corresponding app name
          app_name="${app_name:-$(wmctrl -lx | grep $active_win_id | awk '{print $3}')}"
      fi
      
      # get active workspace number
      workspace_number=`wmctrl -d | grep '\*' | cut -d' ' -f 1`
      
      # get list of windows corresponding to the desired app
      win_list=`wmctrl -lx | grep -i $app_name | grep " $workspace_number " | awk '{print $1}'`
      
      # get next window of app to focus on
      #
      # (Parses $win_list as a single string, removing everything except the token
      # after the active ID. If active ID is sole token or last token, string will be
      # left unmodified, producing an array from which we'll extract the first element.)
      # Note: If active window was not of class app_name, then this will end up
      #       selecting the first window of app_name, if running. Otherwise, we'll fall
      #       through to launching a new instance of the app in the else of the next block.
      switch_to=($(echo $win_list | sed "s/.*\<\(0x0\+\)\?$active_win_id\>\s*\(\<0x[0-9a-f]\+\>\).*/\2/"))
      
      # if we have a valid window to switch to, do so
      if [[ -n "${switch_to}" ]]; then
          wmctrl -ia "${switch_to[0]}"
          exit $?
      else
          # if the user specified a fallback application to run if target window
          # was not found, try to launch it
          if [[ -n "$2" ]]; then
              $2 &
              # check whether process corresponding to PID of background
              # process we just launched is still running
              ps -p $! > /dev/null
              exit $?
          else
              exit $?
          fi
      fi
      

      1 tkt028 的答案中这一行的递归 grep 在我的环境中不起作用。也许这取决于您的 grep 版本。

      win_list=`wmctrl -lx | grep -ri $app_name | grep " $workspace_number " | awk '{print $1}'`
      

      我只是从grep 中删除了r 参数,然后他们的脚本就如宣传的那样工作了。

      win_list=`wmctrl -lx | grep -i $app_name | grep " $workspace_number " | awk '{print $1}'`
      

      【讨论】:

        猜你喜欢
        • 2010-10-18
        • 1970-01-01
        • 1970-01-01
        • 2011-05-29
        • 1970-01-01
        • 1970-01-01
        • 2016-11-03
        • 2014-03-09
        • 1970-01-01
        相关资源
        最近更新 更多