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

如何在XWindows中捕获窗口最小化、最大化事件?

问题根因

你使用的Ubuntu 20.04默认搭载Mutter窗口管理器,这类现代X11窗口管理器已经不完全遵循旧版ICCCM规范的最小化逻辑,不会在最小化时unmap窗口,而是通过EWMH标准的_NET_WM_STATE窗口属性标记所有窗口状态,所以你收不到UnmapNotify属于正常现象。

原有代码核心错误

  1. 你把XCloseDisplay和return 0写在了事件循环内部,程序处理一次事件就会主动关闭X连接退出,自然收不到后续状态变化通知。
  2. 读取_NET_WM_STATE时只请求了1个单位长度的返回值,而该属性实际是Atom类型的数组,可能同时包含多个状态标识,只取第一个自然读不全所有状态。

修改方案

你需要先初始化所有需要用到的状态Atom,再遍历读取到的属性数组判断当前窗口状态:

步骤1:新增状态Atom定义

在main函数开头新增以下变量:

Atom net_wm_state;
Atom net_wm_state_hidden; // 对应最小化状态
Atom net_wm_state_max_vert; // 垂直最大化
Atom net_wm_state_max_horz; // 水平最大化
Atom net_wm_state_fullscreen; // 全屏状态

步骤2:初始化Atom

在XOpenDisplay调用成功后新增Atom初始化逻辑:

net_wm_state = XInternAtom(d, "_NET_WM_STATE", False);
net_wm_state_hidden = XInternAtom(d, "_NET_WM_STATE_HIDDEN", False);
net_wm_state_max_vert = XInternAtom(d, "_NET_WM_STATE_MAXIMIZED_VERT", False);
net_wm_state_max_horz = XInternAtom(d, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
net_wm_state_fullscreen = XInternAtom(d, "_NET_WM_STATE_FULLSCREEN", False);

步骤3:修改PropertyNotify事件处理逻辑

替换原有PropertyNotify分支的代码:

} else if (e.type == PropertyNotify) {
    // 直接匹配Atom,比转字符串比较效率更高
    if (e.xproperty.atom == net_wm_state) {
        status = XGetWindowProperty(d, w, net_wm_state,
                                    0L, 1024L, False, // 请求足够长的返回空间
                                    AnyPropertyType, &type, &format,
                                    &length, &after, &dp);
        if (status == Success && type == XA_ATOM && format == 32) {
            int is_minimized = 0;
            int is_maximized = 0;
            int is_fullscreen = 0;
            Atom *states = (Atom *)dp;
            // 遍历所有状态标识
            for (unsigned long i = 0; i < length; i++) {
                if (states[i] == net_wm_state_hidden) is_minimized = 1;
                if (states[i] == net_wm_state_max_vert) is_maximized += 1;
                if (states[i] == net_wm_state_max_horz) is_maximized += 1;
                if (states[i] == net_wm_state_fullscreen) is_fullscreen = 1;
            }
            // 同时存在水平+垂直最大化标识才是普通最大化
            is_maximized = (is_maximized == 2) ? 1 : 0;
            printf("状态更新:最小化=%d,最大化=%d,全屏=%d\n", is_minimized, is_maximized, is_fullscreen);
        }
        // 必须释放XGetWindowProperty返回的内存,避免泄漏
        if (dp) XFree(dp);
    }
}

步骤4:修正资源释放逻辑

把循环内的XCloseDisplay(d);和return 0;移到while循环外部,程序才能正常监听后续事件。

补充说明

不需要再额外监听StructureNotify等不需要的事件,只要保留PropertyChangeMask就能收到_NET_WM_STATE的变化通知,所有逻辑完全兼容GNOME、KDE等主流桌面环境的窗口管理器。


内容的提问来源于stack exchange,提问作者Scott Franco

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 05:54:00