我有一个小的 shell 脚本,每当我收到新电子邮件时,它就会播放一小段铃声并显示通知。
问题是这个 shell 脚本可以被调用任何时候- 包括当我在全屏模式下观看 DVD/视频时,声音会调高很多 - 这很烦人。
我想增强此脚本的功能,使其能够检测应用程序是否处于全屏模式。我知道这一定可以实现,因为在这种情况下不会显示通知。
我可以使用什么命令?
答案1
作为 shell 脚本来说,有点过度了,但是应该可以达到目的:
#!/bin/bash
WINDOW=$(echo $(xwininfo -id $(xdotool getactivewindow) -stats | \
egrep '(Width|Height):' | \
awk '{print $NF}') | \
sed -e 's/ /x/')
SCREEN=$(xdpyinfo | grep -m1 dimensions | awk '{print $2}')
if [ "$WINDOW" = "$SCREEN" ]; then
exit 0
else
exit 1
fi
然后你可以检查一下:
if is-full-screen ; then echo yup, full screen ; fi
如下所示,您需要先安装 xdotool:
sudo apt-get install xdotool
答案2
我感到有义务发表一些评论(简化):
上述 shell 代码使用了反模式
... | grep | awk
。每当您看到 时grep | awk
,都可以将其替换为 的单个调用awk
。我经常在在线帮助帖子/论坛中看到这种反模式。我的感觉是,大多数人都知道这一点,而在现实世界的代码中,大多数人知道得更多,但出于某种原因,以这种方式编写它(即 )在教学上被视为更优越grep | awk
。但看到它仍然让我很恼火。我认为上述想法可以简化为:
# Initializations section of your shell script: root_geo="$(xwininfo -root | grep geometry)" # In the loop: [ "$(xwininfo -id $(xdotool getactivewindow) | grep geometry)" = "$root_geo" ] && echo "Running fullscreen"
答案3
这是基于@JoeSchmoe 的答案的另一种选择,它不依赖于外部脚本,但工作方式也略有不同:它不关心全屏窗口是否获得焦点。
# Get screen size
root_geo=$(xwininfo -root | awk -F'[ +]' '$3 ~ /-geometry/ {print $4}')
# Check if any window fills the screen
xwininfo -root -tree | grep $root_geo | grep -qv "\(Desktop\|has no name\)"
如果有任何窗口覆盖整个屏幕,最后一个命令将返回退出代码 0,否则返回 1。请注意,这是在 KDE Plasma 上作为桌面设计的 - 您可能需要针对其他桌面环境进行调整,请参见下文。
解释
它首先获取屏幕的测量值并将其保存到root_geo
。对于单次使用,您还可以内联该调用。
多屏幕
对于多个屏幕,如果两个屏幕具有相同的分辨率,您可以对其进行硬编码或修改 awk 以自动执行此计算(假设它们是水平排列的):
xwininfo -root | awk -F'[ +x]' '$3 ~ /-geometry/ {printf "%dx%d",$4/2,$5}'
此外,这应该会获取您已连接的屏幕数量:
xrandr | grep ' connected ' | wc -l
因此,综合起来,这应该适用于任意数量的屏幕,只要它们水平排列并且中间没有空白并且具有相同的分辨率(如果您使用笔记本电脑并定期连接到外部屏幕,这非常有用):
root_geo=$(xwininfo -root | awk -F'[ +x]' '$3 ~ /-geometry/ {printf "%dx%d",$4/'"$(xrandr | grep ' connected ' | wc -l)"',$5}')
如果它们具有不同的分辨率或以不同的方式排列,您也可以使用 xrandr 获取每个分辨率并构建与其中任何一个匹配的正则表达式。请注意,这可能会错误地匹配与更大屏幕上另一个屏幕的精确尺寸匹配的窗口。您可以构建与相应屏幕匹配的内容来解决这个问题,但我不会在这里深入探讨。
检查全屏窗口
xwininfo -root -tree | grep $root_geo | grep -qv "\(Desktop\|has no name\)"
这里,你可能需要调整最后一个模式。
此命令的作用是列出全部以树状方式显示现有窗口(包括桌面)。因此,在筛选出覆盖整个屏幕的窗口后,您还必须筛选出本来就存在的窗口。最简单的检查方法是运行不带最后一个 grep 的命令,它为我生成了以下输出(使用 KDE Plasma 作为桌面):
❯ xwininfo -root -tree | grep $root_geo
0xe001cd (has no name): () 1920x1080+1920+0 +1920+0
0xe001ce (has no name): () 1920x1080+0+0 +1920+0
0x1e00180 "Desktop — Plasma": ("plasmashell" "plasmashell") 1920x1080+0+0 +1920+0
0xe0001e (has no name): () 1920x1080+0+0 +0+0
0xe0001f (has no name): () 1920x1080+0+0 +0+0
0x1e0000b "Desktop — Plasma": ("plasmashell" "plasmashell") 1920x1080+0+0 +0+0
因此,在这里 grep 出桌面和“没有名字”(似乎是一种分组)就足够了。
答案4
在 Ubuntu 的最新版本中,某些窗口(例如 gnome-terminal)受到保护,无法通过 xdotool、wmctrl 等进行访问,因此,除非您使用类似不安全模式菜单你能做的最好的就是检测一些窗口是全屏的,这对于 Chrome、VLC、Plex 等来说已经足够了。
考虑到这一点,我修改了接受的脚本,以便正常处理无法获取窗口信息的情况,因为它处于挂起状态:
#!/bin/bash
ACTIVE_WIN=$(xdotool getactivewindow 2>/dev/null)
if [ -z "$ACTIVE_WIN" ]; then
# protected window that can't be analyzed, e.g. gnome-terminal
echo "Failed to get active win"
exit 1
fi
WINDOW=$(echo $(xwininfo -id $ACTIVE_WIN -stats | \
egrep '(Width|Height):' | \
awk '{print $NF}') | \
sed -e 's/ /x/')
SCREEN=$(xdpyinfo | grep -m1 dimensions | awk '{print $2}')
if [ "$WINDOW" = "$SCREEN" ]; then
exit 0
else
exit 1
fi