GTKMM 4中XReparentWindow重设父窗口后子窗口装饰丢失求助
解决GTKMM 4中子窗口重设父窗口后装饰丢失的问题
问题背景
我尝试在GTKMM 4中模拟GTKMM 3里被废弃的「将窗口置于父窗口中央」功能,于是用XReparentWindow重设Gtk::Window子窗口的父窗口,还配合了XSetTransientForHint,但运行后子窗口的所有装饰都被移除了——直接显示对话框的话装饰是正常的。
我写的代码
void MyGtk::Window_Centre_Child_On_Parent( Gtk::Window *parent, Gtk::Window *child ) { int child_height; int child_width; int parent_height; int parent_width; int position_x; int position_y; // 参数校验 assert(parent); assert(child); // 获取子窗口大小 Widget_Get_Size( child, child_width, child_height ); assert(child_height > 0); assert(child_width > 0); // 获取父窗口大小 Widget_Get_Size( parent, parent_width, parent_height ); assert(parent_height > 0); assert(parent_width > 0); // 获取X11窗口ID auto child_window = Window_Get_X_Windows_ID(child); assert(child_window > 0); auto parent_window = Window_Get_X_Windows_ID(parent); assert(parent_window > 0); // 打开X11显示 auto display = XOpenDisplay(XDisplayName(nullptr)); assert(display); // 计算居中位置 position_x = abs( std::min( parent_width / 2, (parent_width - child_width) / 2 ) ); position_y = abs( std::min( parent_height / 2, (parent_height - child_height) / 2 ) ); // 设置transient hint XSetTransientForHint( display, child_window, parent_window ); // 重设父窗口 XReparentWindow( display, child_window, parent_window, position_x, position_y ); XFlush(display); XCloseDisplay(display); }
问题原因
直接调用XReparentWindow是核心问题:Gtk::Window本身是顶级窗口,重设父窗口后会变成父窗口的子部件,而GTK的子部件默认没有窗口装饰(窗口装饰是窗口管理器给顶级窗口的),所以装饰会直接消失。
解决方法
1. 用GTK原生API实现居中(推荐)
GTKMM 4虽然废弃了旧的居中接口,但可以用原生逻辑替代,完全不需要碰X11底层:
void Window_Centre_Child_On_Parent(Gtk::Window* parent, Gtk::Window* child) { g_return_if_fail(parent && child); // 让窗口管理器知道子窗口和父窗口的关联关系 child->set_transient_for(*parent); // 获取父窗口的位置与大小 int parent_x, parent_y; parent->get_position(parent_x, parent_y); int parent_w, parent_h; parent->get_size(parent_w, parent_h); // 获取子窗口的大小 int child_w, child_h; child->get_size(child_w, child_h); // 计算居中位置(基于父窗口左上角偏移) int x = parent_x + (parent_w - child_w) / 2; int y = parent_y + (parent_h - child_h) / 2; // 设置子窗口位置 child->move(x, y); }
2. 如果是对话框场景,直接用Gtk::Dialog
如果要显示的是对话框,Gtk::Dialog默认就会在父窗口居中,且自带完整装饰,完全不需要手动处理:
auto dialog = Gtk::Dialog::create("对话框标题", *parent, Gtk::DialogFlags::DIALOG_MODAL); // 添加对话框内容... dialog->show();
3. 非要用X11底层的话(不推荐)
别调用XReparentWindow,只保留XSetTransientForHint,然后用GTK的child->move(x,y)设置位置——这样子窗口还是顶级窗口,不会丢失装饰。
内容的提问来源于stack exchange,提问作者BRS
相关产品推荐
相关产品推荐

