linux 无法使用XReparentWindow使窗口永久重新成为父窗口

jjhzyzn0  于 2023-03-29  发布在  Linux
关注(0)|答案(1)|浏览(424)

我正在开发一个管理远程连接的个人使用的WinForms mono应用程序。我一直试图找出一种方法来将某些X11窗口重新父化到我的WinForms应用程序中。我在Windows上完美地运行了此功能,但Linux中的X11 API给了我问题。
我明白这可能是浪费时间,因为有更好的解决方案,但我现在深入研究,至少想知道为什么这不起作用,也许如果有一个解决方案。
我想将Putty SSH终端窗口重新父化到WinForms面板(WinForms程序在mono中运行)。我可以使用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);
}

我已经尝试过这与其他程序以及并已发现,一些将家长只是发现(calculator,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);
}
af7jpaap

af7jpaap1#

好吧,我找到了我的问题的解决方案。很可能是Cinnamon和它的窗口管理器在我重新父化窗口时导致了问题。为了阻止Cinnamon取消父化,我必须在我想要重新父化的窗口上将覆盖重定向标志设置为True。奇怪的是,在设置标志之后,我需要执行XReparentWindow两次,以便使窗口正确地重新父化。不知道为什么,但它的工作原理。然而,在窗口reparents它不再更新图形。我仍然在这个问题上的工作。
我已经用修改后的代码更新了原始文章。

相关问题