无法通过XReparentWindow让X11窗口永久重父至WinForms面板
X11窗口重父后自动恢复到根窗口的解决方案
我开发了一款基于WinForms Mono的远程连接管理应用,需求是将部分X11窗口重父到WinForms面板中。该功能在Windows下运行正常,但在Linux环境中遇到问题:使用XReparentWindow可以将Putty SSH终端窗口重父到WinForms面板,但几秒后窗口会自动回到根窗口,无法保持重父状态。
原重父实现代码
private static void ReparentWindow() { IntPtr display = XOpenDisplay(Environment.GetEnvironmentVariable("DISPLAY")); IntPtr puttyWindowHandle = [handle_of_putty_window]; // 通过窗口标题查找句柄的函数已实现 IntPtr panelHandle = panTestPanel.Handle; XReparentWindow(display, puttyWindowHandle, panelHandle, 0, 0); XMapWindow(display, puttyWindowHandle); XFlush(display); XSync(display, false); }
测试发现,计算器、gedit等程序可以正常完成重父,但终端类应用及glxgears均存在上述自动恢复的问题。
修复后的代码
private static void ReparentWindow() { IntPtr display = XOpenDisplay(Environment.GetEnvironmentVariable("DISPLAY")); IntPtr puttyWindowHandle = [handle_of_putty_window]; // 通过窗口标题查找句柄的函数已实现 IntPtr panelHandle = panTestPanel.Handle; // 设置目标窗口的override_redirect属性为true XSetWindowAttributes xSetWindowAttributes = new XSetWindowAttributes(); xSetWindowAttributes.override_redirect = true; IntPtr attr = Marshal.AllocHGlobal(Marshal.SizeOf(xSetWindowAttributes)); Marshal.StructureToPtr(xSetWindowAttributes, attr, false); XChangeWindowAttributes(display, puttyWindowHandle, XWindowAttributeFlags.CWOverrideRedirect, attr); Marshal.FreeHGlobal(attr); // 执行重父操作 XReparentWindow(display, puttyWindowHandle, panelHandle, 0, 0); XReparentWindow(display, puttyWindowHandle, panelHandle, 0, 0); XMapWindow(display, puttyWindowHandle); XFlush(display); XSync(display, false); }
核心解决方案说明
问题根源在于窗口管理器的干预:终端类等应用的窗口会被窗口管理器重新接管。通过设置目标窗口的override_redirect属性为true,可以让窗口绕过窗口管理器的控制,再重复调用XReparentWindow即可确保窗口保持重父状态。
内容的提问来源于stack exchange,提问作者djex
相关产品推荐
相关产品推荐

