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

使用GTK检测Control键释放时gdk_window_get_pointer调用失败求助

问题分析与解决

你遇到的gdk_window_get_pointer failed错误,核心原因是你给这个函数传了NULL作为窗口参数。在GTK初始化完成后,如果你还没有创建任何应用窗口,NULL并不是一个有效的GDK窗口句柄,函数无法获取指针与按键状态。

修正后的代码

我们只需要把NULL替换为系统根窗口的句柄(通过gdk_get_default_root_window()获取),就能正常检测Ctrl键的状态了:

#include <stdlib.h>
#include <unistd.h>
#include <gtk/gtk.h>

int main (int argc, char* argv[]) {
    const unsigned int pause_microseconds = 100 * 1000;
    gtk_init(&argc, &argv);
    
    // 获取系统根窗口(全局有效)
    GdkWindow* root_window = gdk_get_default_root_window();
    if (!root_window) {
        puts("Failed to get root window");
        return EXIT_FAILURE;
    }

    GdkModifierType mask;
    while (1) {
        // 传入根窗口作为第一个参数
        if(gdk_window_get_pointer(root_window, NULL, NULL, &mask) == NULL){
            puts("gdk_window_get_pointer failed");
            return EXIT_FAILURE;
        }

        // 简化判断逻辑:当Ctrl键未被按下时,视为已释放
        unsigned control_has_been_released = !(mask & GDK_CONTROL_MASK);
        if (control_has_been_released) {
            puts("OK");
            return EXIT_SUCCESS;
        }

        if(usleep(pause_microseconds) != 0){
            puts("usleep failed");
            return EXIT_FAILURE;
        }
    }
}

关键修改说明

  1. 获取根窗口:gdk_get_default_root_window()会返回系统的根窗口句柄,这是一个全局有效的窗口,可以用来查询全系统的指针和按键状态,完美适配你的需求。
  2. 简化判断逻辑:把原有的(mask & GDK_CONTROL_MASK) != GDK_CONTROL_MASK改成!(mask & GDK_CONTROL_MASK),逻辑完全一致,但可读性更强。

额外优化提示

虽然上述代码可以正常工作,但用usleep加死循环的方式并不是GTK推荐的做法。更规范的方式是利用GTK的主循环,通过g_timeout_add()定时检查按键状态,避免阻塞主循环,也更符合GTK的设计模式:

#include <stdlib.h>
#include <gtk/gtk.h>

gboolean check_ctrl_release(gpointer data) {
    GdkModifierType mask;
    GdkWindow* root_window = gdk_get_default_root_window();
    
    if(gdk_window_get_pointer(root_window, NULL, NULL, &mask) == NULL){
        puts("gdk_window_get_pointer failed");
        exit(EXIT_FAILURE);
    }

    if (!(mask & GDK_CONTROL_MASK)) {
        puts("OK");
        gtk_main_quit();
        return FALSE; // 检测到后停止定时器
    }
    return TRUE; // 继续定时检查
}

int main (int argc, char* argv[]) {
    gtk_init(&argc, &argv);
    // 每100毫秒检查一次按键状态
    g_timeout_add(100, check_ctrl_release, NULL);
    gtk_main();
    return EXIT_SUCCESS;
}

这个版本依托GTK主循环处理定时任务,不会出现阻塞问题,代码风格也更贴合GTK生态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:13:47