我正在开发一个 WinForms mono 应用程序供个人使用,用于管理远程连接。我一直在尝试找出一种方法将某些 X11 窗口重新设置为我的 WinForms 应用程序。我有这个功能在 Windows 上完美运行,但是 Linux 中的 X11 API 给我带来了问题。
我知道这可能是浪费时间,因为有更好的解决方案,但是我现在已经深入了解它,并且至少想知道为什么这不起作用,也许是否有解决方案。
我想将 Putty SSH 终端窗口重新设置为 WinForms 面板(WinForms 程序以单声道运行)。我可以使用 XReparentWindow 完成此操作,但是一秒钟后 Putty 窗口将取消父级返回到根窗口。它不会停留在 WinForms 面板上。
这些是我用来重新设置 Putty 窗口父级的 API 调用:
private static void ReparentWindow()
{
IntPtr display = XOpenDisplay(Environment.GetEnvironmentVariable("DISPLAY"));
IntPtr puttyWindowHandle = [handle_of_putty_window]; //I have a function here that finds a window by title and returns the handle
IntPtr panelHandle = panTestPanel.Handle;
XReparentWindow(display, puttyWindowHandle, panelHandle, 0, 0);
XMapWindow(display, puttyWindowHandle);
XFlush(display);
XSync(display, false);
}
我也用其他程序尝试过这个,发现有些程序只会找到(计算器,gedit)而其他程序,特别是终端应用程序,根本不会保持父级。我对 X11 的了解不够,无法理解这是为什么以及是否有解决方案。我怀疑它与等待输入的终端应用程序有关,尽管我也尝试重新设置 gxlgears 作为测试,它有同样的问题,所以我不确定。
如有任何帮助或建议,我们将不胜感激。
更新的解决方案:
private static void ReparentWindow()
{
IntPtr display = XOpenDisplay(Environment.GetEnvironmentVariable("DISPLAY"));
IntPtr puttyWindowHandle = [handle_of_putty_window]; //I have a function here that finds a window by title and returns the handle
IntPtr panelHandle = panTestPanel.Handle;
//Set the override redirect flag on the window we want to reparent
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);
//Reparent the window
XReparentWindow(display, puttyWindowHandle, panelHandle, 0, 0);
XReparentWindow(display, puttyWindowHandle, panelHandle, 0, 0);
XMapWindow(display, puttyWindowHandle);
XFlush(display);
XSync(display, false);
}
好吧,我找到了问题的解决方案。很可能是 Cinnamon 和它的窗口管理器在我重新设置窗口时引起了问题。为了阻止 Cinnamon 取消父级设置,我必须在我想要重新设置父级的窗口上将覆盖重定向标志设置为 True。奇怪的是,我需要在设置标志后执行两次 XReparentWindow 以使窗口正确重新设置父级。不知道为什么会这样,但它有效。但是,在窗口重新设置父级后,它不再以图形方式更新。我还在研究这个问题。
我已经用修改后的代码更新了原始帖子。