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

如何在GDK 3中使用C语言创建可穿透鼠标事件的透明窗口?

如何在GDK 3中使用C语言创建可穿透鼠标事件的透明窗口?

看起来你想要的是一个完全不接收鼠标事件、内容透明的窗口,这样点击它的时候事件会直接传递给下方的应用(比如文本编辑器)。你的现有代码里有两个主要问题:一是用cairo画了黑色填充导致窗口内容不透明,二是设置的输入形状区域不符合需求——你只把左半部分设为可接收输入,但我们需要的是整个窗口都不接收输入。

关键解决思路

要实现这个需求,需要做好三件事:

  • 让窗口支持RGBA透明度:必须给窗口设置带Alpha通道的视觉效果,否则透明设置不会生效。
  • 绘制透明内容:替换不透明的黑色填充,保持窗口背景透明(或按需绘制半透明元素)。
  • 禁用窗口的鼠标输入:告诉GDK这个窗口不接收任何鼠标事件,让事件直接穿透到下方窗口。

修改后的完整代码

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

static void on_destroy(GtkWidget *widget, gpointer data) {
    gtk_main_quit();
}

static void on_realize(GtkWidget *widget, gpointer data) {
    GdkWindow *gdk_window = gtk_widget_get_window(widget);

    if (gdk_window) {
        // 核心:传入NULL区域,让整个窗口不接收任何鼠标事件
        gdk_window_input_shape_combine_region(gdk_window, NULL, 0, 0);
    }
}

static gboolean on_draw(GtkWidget *widget, cairo_t *cr, gpointer data) {
    // 绘制完全透明的背景(alpha值0.0表示完全透明)
    cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
    cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
    cairo_paint(cr);

    // 可选:如果你需要半透明的元素,比如30%不透明的红色矩形,可以取消下面的注释
    // cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.3);
    // cairo_rectangle(cr, 50, 50, 300, 200);
    // cairo_fill(cr);

    return FALSE;
}

int main(int argc, char *argv[]) {
    GtkWidget *window;
    GdkVisual *visual;

    gtk_init(&argc, &argv);

    // 获取支持RGBA透明度的视觉效果
    visual = gdk_screen_get_rgba_visual(gdk_screen_get_default());

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    // 给窗口设置RGBA视觉效果,这是透明生效的前提
    if (visual != NULL) {
        gtk_widget_set_visual(window, visual);
    }

    // 设置窗口默认大小
    gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
    // 可选:如果需要窗口始终显示在最上层,可以开启下面的设置
    // gtk_window_set_keep_above(GTK_WINDOW(window), TRUE);

    g_signal_connect(window, "destroy", G_CALLBACK(on_destroy), NULL);
    g_signal_connect(window, "realize", G_CALLBACK(on_realize), NULL);
    g_signal_connect(window, "draw", G_CALLBACK(on_draw), NULL);

    gtk_widget_show_all(window);
    gtk_main();
    return 0;
}

关键修改点说明

  1. RGBA视觉效果:在main函数中获取并设置支持Alpha通道的视觉效果,这是窗口能显示透明内容的必要条件。
  2. 透明绘制:用draw信号替代你原来的cairo填充逻辑,通过cairo_set_source_rgba设置完全透明的背景,确保窗口本身是看不见的。
  3. 鼠标穿透设置:在on_realize中把输入形状区域设为NULL,这会让GDK完全跳过这个窗口的鼠标事件处理,所有点击、移动事件都会直接传递给下方的应用。
  4. 移除了原代码中的黑色填充逻辑:这是导致窗口不透明的直接原因,现在替换为透明绘制。

如果之后你需要部分区域可交互、部分区域穿透,只需要把gdk_window_input_shape_combine_region的NULL换成你需要的可交互区域(比如一个圆形或矩形的cairo_region_t)即可。

备注:内容来源于stack exchange,提问作者SilverCube

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 10:38:02