我经常使用 wmctrl 在窗口之间切换,主要是为了避免多次输入 alt-tab。我一直使用一个工作区,但现在我想开始使用多个工作区。
我想知道是否可以修改 wmctrl 的上下文,以便当我键入时wmctrl -l
,只显示当前工作区的窗口,而不是所有工作区的所有窗口。
例如,假设我在工作区 1 中打开了一个 Firefox 窗口。我有一个键盘快捷键,ctrl+alt+f
执行wmctrl -a firefox
,它会切换到 Firefox。如果我在工作区 2 上打开一个新的 Firefox 窗口并输入ctrl+alt+f
,它会切换到工作区 1 的窗口,这不是我想要的。
关于如何解决这个问题有什么建议/想法吗?
编辑:我正在使用 compiz (Unity)
答案1
如果您使用的是 Compiz(wmctrl -m
如果不确定,请运行),wmctrl 只能看到 1 个桌面(wmctrl -l 的第二个字段,即 0),但您可以使用 geometry (-G) 选项来了解哪个窗口在哪个虚拟桌面上。当前桌面上的所有窗口的 x 位置都在 0 和屏幕宽度之间。y 位置在 0 和屏幕高度之间也是如此。因此,您可以使用类似的东西
#!/bin/bash
SCREEN_W=$(xwininfo -root | sed -n 's/^ Width: \(.*\)$/\1/p')
SCREEN_H=$(xwininfo -root | sed -n 's/^ Height: \(.*\)$/\1/p')
NAME='Navigator.Firefox'
wmctrl -xlG | awk -v W="$SCREEN_W" -v H="$SCREEN_H" -v NAME="$NAME" '$7==NAME && $3>=0 && $3<W && $4>=0 && $4<H {print $1}' | while read WINS; do wmctrl -ia "$WINS"; done
exit 0
您可以对屏幕的宽度和高度进行硬编码(如果您愿意的话),如果您想要一行代码,也可以对 NAME 进行硬编码。我不确定您想如何处理与 NAME 匹配的多个窗口。这将使它们全部聚焦。
对于 metacity,可以使用wmctrl -l
并 grep 第二个字段来找到桌面窗口的数量。
答案2
我有 2022 年的答案,它基于最新的 wmctrl 逻辑,非常强大,它模仿了 Windows 上的自动热键
因此,首先我们需要获取活动桌面/工作区
wmctrl -d | grep "*" | awk --field-separator=" " '{print $1}'
之后,你可以将其拼凑起来以获取该桌面上的唯一窗口列表
D=$(wmctrl -d | grep "*" | awk --field-separator=" " '{print $1}')
WINNAME="GVIM"
# Or you can get the full name as hex, more accurate for same window name
WIN=$(wmctrl -l | grep " $DESKTOP " | grep -i $WIN | awk '{print $1}')
# WIN will be filled with 0xYYYY ID in hex or use simple winname
IN=$(wmctrl -l | grep " $DESKTOP " | grep -i gvim | awk --field-separator="$(hostname) " '{print $2}')
# Get the number of window contain it's name
STATUS=$(wmctrl -l | grep " $DESKTOP " | grep -i $WINNAME | wc -l)
然后你可以像这样使用 if 检查它(对于 winname)
if [ $STATUS -gt 0 ]
then
activeWindow=$(xprop -id $(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) WM_NAME | cut -d '"' -f 2)
# zenity --notification --text="$activeWindow"
if [[ $activeWindow =~ "$WINNAME" ]]
then
wmctrl -r "$WIN" -b toggle,hidden
else
wmctrl -a "$WIN"
fi
else
/usr/bin/gvim # if the app hasn't started yet, start it
fi
或者
对于十六进制 ID
# ... output omitted
if [[ $activeWindow =~ "$WINNAME" ]]
then
wmctrl -i -r "$WIN" -b toggle,hidden
else
wmctrl -i -a "$WIN"
fi
# ... output omitted, see source before
所以如果你把它们拼凑在一起(对于使用窗口名称,这不是项目符号,因为如果工作区之间有相同的名字,那么它将遵循其他工作区)
#!/bin/bash
DESKTOP=$(wmctrl -d | grep "*" | awk --field-separator=" " '{print $1}')
STATUS=$(wmctrl -l | grep " $DESKTOP " | grep -i gvim | wc -l)
WIN=$(wmctrl -l | grep " $DESKTOP " | grep -i gvim | awk --field-separator="$(hostname) " '{print $4}')
# zenity --notification --text="$STATUS $DESKTOP $WIN"
if [ $STATUS -gt 0 ]
then
activeWindow=$(xprop -id $(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) WM_NAME | cut -d '"' -f 2)
# zenity --notification --text="$activeWindow"
if [[ $activeWindow =~ "GVIM" ]]
then
wmctrl -r $WIN -b toggle,hidden
else
wmctrl -a $WIN
fi
else
/usr/bin/gvim
fi
或使用十六进制 ID 进行 BULLET PROF
#!/bin/bash
DESKTOP=$(wmctrl -d | grep "*" | awk --field-separator=" " '{print $1}')
STATUS=$(wmctrl -l | grep " $DESKTOP " | grep -i gvim | wc -l)
WIN=$(wmctrl -l | grep " $DESKTOP " | grep -i gvim | awk '{print $1}')
#zenity --notification --text="$WIN"
if [ $STATUS -gt 0 ]
then
activeWindow=$(xprop -id $(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) WM_NAME | cut -d '"' -f 2)
#zenity --notification --text="$STATUS $DESKTOP \"$WIN\" $activeWindow"
if [[ $activeWindow =~ "GVIM" ]]
then
wmctrl -i -r "$WIN" -b toggle,hidden
else
wmctrl -i -a "$WIN"
fi
else
/usr/bin/gvim
fi
-iman wmctrl
表示:
-i 将窗口参数 () 解释为数值而不是窗口的字符串名称。如果数值以前缀“0x”开头,则假定为十六进制数
您可以获得类似 Windows 上的 AHK 脚本的窗口切换,但功能比它应有的更强大。
该脚本已在 XFCE 上测试,并且可在 Xubuntu 22.04 或 Fedora 36 上运行。