我可以通过各种方式更改我当前的工作区,例如通过单击某些切换器小部件、使用某些组合键或使用终端中的命令。
有没有办法检测工作区是否已经改变,并在那一刻启动 bash 脚本?
(例如,我认为 d-bus 上有一个可监控的信号,类似这样的东西。)
答案1
有一个更节能的 gnome-shell 扩展解决方案。它实际上会“在那一刻启动一个 bash 脚本”,而你无需事先启动任何东西。以下是安装过程:
- 创建要运行的脚本
~/script.sh
- 确保它是可执行的
- 将正确的版本粘贴到
~/.local/share/gnome-shell/extensions/[email protected]/metadata.json
- 将正确的版本粘贴到
~/.local/share/gnome-shell/extensions/[email protected]/extension.js
- 重新登录
- 跑步
gnome-extensions enable [email protected]
我使用script.sh
刚刚创建文件的 进行了测试。我测试了Ctrl++ /并确认脚本在那时运行,而不是在登录等其他时间运行。gnome-shell 不会将信号暴露给 DBus,并且AltDBus方法被锁定。但是,gnome-shell 扩展可以监听 gobject 信号←→org.gnome.Shell.Eval
WorkspaceManager::active-workspace-changed
。
侏儒壳 ≤ 42 (22.04)
metadata.json
{
"uuid": "[email protected]",
"name": "Workspace change detect script launcher",
"description": "Detect that the workspace has been changed, to launch a bash script at that moment",
"shell-version": [ "42" ],
"url": "https://askubuntu.com/q/1502368/1004020"
}
extension.js
const {GLib} = imports.gi;
let handlerId;
function enable() {
handlerId = global.workspaceManager.connect('active-workspace-changed', () => {
// Put the script to launch at ~/script.sh , or change the string on the next line:
GLib.spawn_command_line_async('./script.sh');
});
}
function disable() {
global.workspaceManager.disconnect(handlerId);
}
侏儒壳 ≥ 45 (23.10)
metadata.json
{
"uuid": "[email protected]",
"name": "Workspace change detect script launcher",
"description": "Detect that the workspace has been changed, to launch a bash script at that moment",
"shell-version": [ "45" ],
"url": "https://askubuntu.com/q/1502368/1004020"
}
extension.js
import GLib from 'gi://GLib';
import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js';
export default class WorkspaceChangeDetectExtension extends Extension {
enable() {
global.workspaceManager.connectObject('active-workspace-changed', () => {
// Put the script to launch at ~/script.sh , or change the string on the next line:
GLib.spawn_command_line_async('./script.sh');
}, this);
}
disable() {
global.workspaceManager.disconnectObject(this);
}
}
答案2
我确实研究过 D-Bus 和其他想到的 Gnome DE 特定方法,但找不到比下面描述的更可靠、可持续和便携的解决方案……
您可以使用xdotool
(这似乎也适用于 Wayland)在 shell 循环中如下:
#!/bin/sh
while sleep 0.2
do
v="$(xdotool get_desktop)"
if [ -z "$ws" ]
then
ws="$v"
elif [ "$ws" -ne "$v" ]
then
ws="$v"
echo "changed to $ws"
# Your command here
fi
done
...该工具仍可在 Wayland 上使用,因为它读取_NET_CURRENT_DESKTOP
的财产EWMH扩展窗口管理器提示其中许多窗口管理器/系统仍然支持并制定标准。
不用说,还有其他工具支持读取该属性以及内置的持续监视功能(如果你不喜欢不断循环sleep
通话) 喜欢xprop
你也可以像这样使用它:
#!/bin/bash
xprop -root -spy _NET_CURRENT_DESKTOP |
while IFS=" " read -r p s n
do
if ! [[ "$ws" =~ ^[0-9]+$ ]]
then
ws="$n"
elif [ "$n" -ne "$ws" ]
then
ws="$n"
echo "changed to $ws"
# Your command here
fi
done
... 甚至xev
像这样:
#!/bin/sh
xev -root -event property |
grep --line-buffered -o '_NET_CURRENT_DESKTOP' |
while read -r p
do
echo "Workspace changed."
# Your command here
done
...当然,如果您愿意,您也可以选择实现自己的应用程序,_NET_CURRENT_DESKTOP
用任何语言 C、Python...等读取属性,而不一定使用这些工具的 shell 脚本。
注意:
上面第一个循环
xdotool
和最后一个循环xev
不是 Bash 特有的,sh
例如可以与其他 POSIX shell 一起运行。在 Wayland 上使用时
xprop
,据报告@Daniel T(谢谢丹尼尔),那么在开始捕捉它之前必须至少切换工作区一次xprop
,因此您在工作区之间的第一次切换将超出脚本的范围......所以,如果这很关键,请使用xdotool
。
注意并且(不言而喻)这些循环需要在用户图形会话运行时运行,即在登录后和注销前...因此,最好的实现方式如下启动应用程序Command:无论它们是包含在脚本文件中还是甚至作为单个 shell 命令字符串布局在字段中,如下所示:
sh -c 'while sleep 0.2; do if [ -z "$ws" ]; then ws="$(xdotool get_desktop)"; elif [ "$ws" -ne "$(xdotool get_desktop)" ]; then ws="$(xdotool get_desktop)"; echo "changed to $ws"; fi done'
...或者像这样:
bash -c 'xprop -root -spy _NET_CURRENT_DESKTOP | while IFS=" " read -r p s n; do if ! [[ "$ws" =~ ^[0-9]+$ ]]; then ws="$n"; elif [ "$n" -ne "$ws" ]; then ws="$n"; echo "changet to $ws"; fi done'
...或者像这样:
sh -c 'xev -root -event property | grep --line-buffered -o '_NET_CURRENT_DESKTOP' | while read -r p; do echo "Workspace changed."; done'
... 这些命令字符串中的自定义命令应该代替该echo "..."
部分。