You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu 16.04无需轮询检测窗口打开事件并执行脚本或函数的方法

嘿,我之前在Ubuntu 16.04上折腾过类似的需求,太懂你不想用轮询的心情了——轮询不仅浪费系统资源,响应还不及时。下面给你几个事件驱动的靠谱方案,完美解决你的问题:

方案1:用libwnck(C/C++实现)

libwnck是GNOME生态下专门用于窗口管理的库,能直接监听窗口创建、关闭等事件,API非常友好,适合C/C++开发。

步骤:

  1. 先安装依赖库:
sudo apt-get install libwnck-3-dev
  1. 编写监听代码(示例):
#include <libwnck/libwnck.h>
#include <string.h>

// 窗口打开事件的回调函数
static void on_window_opened(WnckScreen *screen, WnckWindow *window, gpointer data) {
    // 获取窗口名称和窗口类名(类名更稳定,适合匹配目标窗口)
    const char *window_name = wnck_window_get_name(window);
    const char *window_class = wnck_window_get_class_group_name(window);

    // 替换成你的目标窗口标识(选名称或类名都可以)
    const char *TARGET_WINDOW_NAME = "你的目标窗口名";
    const char *TARGET_WINDOW_CLASS = "你的目标窗口类";

    if ((window_name && strcmp(window_name, TARGET_WINDOW_NAME) == 0) ||
        (window_class && strcmp(window_class, TARGET_WINDOW_CLASS) == 0)) {
        // 执行你的Bash脚本
        system("/path/to/your/script.sh");
        // 或者直接调用你的C/C++函数
        // your_custom_function();
    }
}

int main(int argc, char **argv) {
    // 初始化GDK(libwnck依赖GDK)
    gdk_init(&argc, &argv);
    // 获取默认屏幕
    WnckScreen *screen = wnck_screen_get_default();

    // 绑定窗口打开事件的回调
    g_signal_connect(screen, "window-opened", G_CALLBACK(on_window_opened), NULL);

    // 进入事件循环
    gdk_main();
    return 0;
}
  1. 编译代码:
gcc -o window_monitor window_monitor.c $(pkg-config --cflags --libs libwnck-3.0)
  1. 运行编译后的程序即可持续监听窗口事件。
方案2:用DBus监听(纯Bash脚本)

如果你不想写代码,纯Bash就能搞定——Ubuntu 16.04的桌面环境(比如Unity)会通过DBus广播窗口相关的信号,我们可以直接监听这些信号来实现事件驱动。

示例脚本:

#!/bin/bash

# 监听窗口添加事件(适配Unity/Compiz环境)
dbus-monitor "interface='org.compiz.WindowManager',member='WindowAdded'" | while read -r line; do
    # 当捕获到窗口添加信号时,获取最新打开的窗口信息
    if echo "$line" | grep -q "WindowAdded"; then
        # 用wmctrl获取最新窗口的名称(tail -n1取最后一行,即最新打开的窗口)
        latest_window_name=$(wmctrl -l | tail -n1 | awk '{sub(/^[^ ]+ [^ ]+ [^ ]+ /, ""); print}')
        # 替换成你的目标窗口名
        TARGET_WINDOW="你的目标窗口名"
        if [[ "$latest_window_name" == *"$TARGET_WINDOW"* ]]; then
            # 执行你的脚本
            /path/to/your/script.sh
        fi
    fi
done

注意:

  • 如果你的桌面是GNOME Shell,把监听的DBus接口改成"interface='org.gnome.Shell',member='WindowAdded'"即可。
  • 确保已经安装wmctrl和dbus-x11:sudo apt-get install wmctrl dbus-x11
方案3:用XCB底层接口(C实现)

如果你需要更底层的X窗口系统控制,XCB是个不错的选择——它是Xlib的替代方案,更轻量,不需要依赖GNOME的库。

步骤:

  1. 安装依赖:
sudo apt-get install libxcb1-dev
  1. 编写监听代码:
#include <xcb/xcb.h>
#include <string.h>
#include <stdlib.h>

int main() {
    // 连接到X服务器
    xcb_connection_t *conn = xcb_connect(NULL, NULL);
    if (xcb_connection_has_error(conn)) {
        fprintf(stderr, "无法连接到X服务器\n");
        return 1;
    }

    // 获取默认屏幕
    xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
    // 订阅根窗口的子结构通知事件(用于捕获窗口创建)
    uint32_t event_mask = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
    xcb_change_window_attributes(conn, screen->root, XCB_CW_EVENT_MASK, &event_mask);
    xcb_flush(conn);

    xcb_generic_event_t *event;
    while ((event = xcb_wait_for_event(conn))) {
        // 处理窗口创建事件
        if (event->response_type == XCB_CREATE_NOTIFY) {
            xcb_create_notify_event_t *create_event = (xcb_create_notify_event_t *)event;
            // 获取窗口名称属性
            xcb_get_property_cookie_t name_cookie = xcb_get_property(
                conn, 0, create_event->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 1024);
            xcb_get_property_reply_t *name_reply = xcb_get_property_reply(conn, name_cookie, NULL);
            if (name_reply && name_reply->value_len > 0) {
                char *window_name = xcb_get_property_value(name_reply);
                // 替换成你的目标窗口名
                if (strcmp(window_name, "你的目标窗口名") == 0) {
                    system("/path/to/your/script.sh");
                }
                free(name_reply);
            }
        }
        free(event);
    }

    xcb_disconnect(conn);
    return 0;
}
  1. 编译代码:
gcc -o xcb_window_monitor xcb_window_monitor.c -lxcb
  1. 运行程序即可监听窗口创建事件。

这些方案都是完全基于事件驱动的,不会像轮询那样一直占用CPU,你可以根据自己的技术栈选择最适合的方式。

内容的提问来源于stack exchange,提问作者Christian Eriksson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:36:46