设置Gtk窗口override redirect属性导致段错误该如何解决?
问题根因
你触发段错误的核心原因是刚创建的GtkWindow还未完成底层GdkWindow的初始化映射,此时调用gtk_widget_get_window()返回的是空指针,直接操作空指针就会触发段错误。
解决方法
需要做以下修改适配你的需求:
- 监听GtkWindow的
realize信号,在信号回调中获取已创建完成的GdkWindow再设置override redirect属性 - 额外添加窗口置顶、跳过任务栏/工作区显示、透明背景配置,匹配你要做顶层不可见透明绘制窗口的需求
修正后的完整代码
#include <gtk/gtk.h> // realize信号回调,此时底层GdkWindow已创建完成 void on_window_realized(GtkWidget *window, gpointer user_data) { GdkWindow *gdk_window = gtk_widget_get_window(window); // 设置override redirect,脱离窗口管理器管理 gdk_window_set_override_redirect(gdk_window, TRUE); // 窗口始终置顶 gdk_window_set_keep_above(gdk_window, TRUE); } void activate(GtkApplication *app) { GtkWidget *window = gtk_application_window_new(app); // 设置窗口默认大小,可按需调整 gtk_window_set_default_size(GTK_WINDOW(window), 400, 300); // 配置窗口透明背景 gtk_widget_set_app_paintable(window, TRUE); GdkScreen *screen = gtk_widget_get_screen(window); GdkVisual *visual = gdk_screen_get_rgba_visual(screen); if (visual != NULL && gdk_screen_is_composited(screen)) { gtk_widget_set_visual(window, visual); } // 设置窗口不显示在任务栏、工作区切换器中 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(window), TRUE); gtk_window_set_skip_pager_hint(GTK_WINDOW(window), TRUE); // 设置窗口类型为弹出式,更符合无装饰层的场景 gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_POPUP_MENU); // 绑定realize信号,等底层窗口创建完成再操作GdkWindow g_signal_connect(window, "realize", G_CALLBACK(on_window_realized), NULL); gtk_widget_show_all(window); } int main(int argc, char **argv) { GtkApplication *app = gtk_application_new("com.github.application.name", G_APPLICATION_FLAGS_NONE); g_signal_connect(app, "activate", G_CALLBACK (activate), NULL); int status = g_application_run(G_APPLICATION (app), argc, argv); g_object_unref(app); return status; }
编译方式
和你之前的编译指令完全一致即可:
gcc -o out main.c `pkg-config --cflags --libs gtk+-3.0`
注意事项
- 设置override redirect后窗口完全脱离窗口管理器控制,你需要自行处理窗口的移动、关闭、重绘等逻辑
- 如果要实现全屏幕覆盖,可以调用
gtk_window_fullscreen(GTK_WINDOW(window))将窗口全屏
内容的提问来源于stack exchange,提问作者phoney_badger
相关产品推荐
相关产品推荐

