如何从 shell 脚本检测我的终端是否在 GUI 中获得焦点?

Ale*_* P. 4 shell terminal-emulator shell-script focus

问题/目标描述

理想情况下,我想要一种从 shell 脚本中检测窗口是否具有焦点的方法。通过一个“好”的方式,我的意思是一些需要几个简单的步骤,最好不这样要求通过每个打开的窗口筛选盲目寻矿基于标题。

目的是在许多不同的脚本中控制通知——所以我只是在寻找一个可以适用于所有脚本的通用解决方案。

到目前为止,我想出的是迂回曲折的——如下:

  1. 将我的标题设置为独特的或机械相关的(在我的模型中,它是我的 PTS 路径,或者更可靠的 UUID)。迫切希望这个标题不会被某些东西覆盖。

  2. 按标题获取所有打开窗口的列表。

  3. 遍历列表以通过将它与标题元素匹配来识别我的窗口。(请注意,如果另一个窗口碰巧具有相同的标题元素,则此处可能会出错。)

  4. 检测所述窗口是否具有焦点与否。

应当指出的是,我根本想要实现这一点,只会做它作为最后的手段。所以我在这里要求的不是 this

妥协

这个解决方案显然很糟糕,所以我想知道是否有更好的方法。我更喜欢便携、优雅和完美的东西,但我意识到可能需要妥协。通过更好地我的意思是下列任何:

  1. 一种仅适用于特定终端仿真器的解决方案,例如通过让终端仿真器本身设置一个环境变量,允许脚本检测它所在的窗口。

  2. 一种不需要设置标题的解决方案,而是在窗口状态中使用其他一些不可见标记,该标记可从附加到所述窗口的 shell 脚本中访问和检测。

  3. 重新使用父进程阶梯以查找父终端模拟器 PID,并从那里开始工作(请注意,通过重新使用进程树来检测启动脚本的父进程的解决方案仅在脚本在本地运行时才有效,所以这个解决方案不完整但仍然很好!)

状况

我收到了关于我的首选解决方案应该在什么条件下运行的问题,答案是尽可能多。但至少,我想要一些有效的东西:

  1. 在本机运行的单选项卡终端会话中(默认方案)。

  2. 在像 tmux 这样的终端多路复用器中。(不同终端多路复用器之间的可移植性是首选,但实际上不是必需的。)

我非常欣赏的附加功能(按重要性排序)包括:

  1. 能够通过 telnet 和 SSH 进行远程连接。

  2. 能够区分哪个选项卡在多选项卡终端会话中打开。


概括

我想要一个很好的方法来找到我的 shell 脚本附加到哪个终端仿真器窗口,以便我可以检测它是否有焦点。

请注意,我已经知道的力学如何通过打开的窗口进行迭代,以及如何检测自己是否有焦点或不和他们有什么头衔。我知道and 这个问题的存在xdotoolxprop这些工具的基本机制无关(除非有一些隐藏的黑魔法功能我不知道这会回避我当前解决方案的内在技巧。)

我不想那样做的原因是因为它太可怕了。即完成同样的事情没有其他解决办法?

egm*_*ont 11

有一个FocusIn/FocusOut模式。启用:

echo -ne '\e[?1004h'
Run Code Online (Sandbox Code Playgroud)

要禁用:

echo -ne '\e[?1004l'
Run Code Online (Sandbox Code Playgroud)

上的每个焦点事件,收到任一\e[I(上)或\e[O从输入流(OUT)。

当您启用该模式GNOME终端(和其他基于VTE终端)也报告当前的状态。也就是说,您可以启用然后立即禁用它以查询一次值。

您可以结合read超时,或指定读取 3 个字符以获取响应。但是请注意,它受竞争条件的影响,例如,如果您预先输入了某些字符。


小智 2

if [ "$(xdotool getwindowfocus)" -eq "$WINDOWID" ]; then
   echo I have the focus
fi
Run Code Online (Sandbox Code Playgroud)

如果 screen/tmux 是从其他地方启动并且只是附加在当前窗口中,则这在 screen/tmux 内不起作用。