Xlib:在Java/JNI中,使用XAddToChangeSet向存储集添加窗口不起作用

Xlib:在Java/JNI中,使用XAddToChangeSet向存储集添加窗口不起作用,java,linux,x11,xlib,Java,Linux,X11,Xlib,我被卡住了,不知道该往哪里看 我有一个Java应用程序,它的一个功能是抓取一些特定的窗口(即第三方应用程序窗口),并将它们托管在自己的内部(带有一些额外的框架等) 除了我的Java应用程序死机(或崩溃)之外,整个过程都很顺利。发生这种情况时,托管的第三方窗口将被破坏,大多数情况下会使第三方应用程序完全崩溃 此功能设计为在Linux下工作 重新租赁的方式有点复杂: 创建一个专用Java线程并调用一个C共享库(A .so lib) 此共享库扫描所有当前窗口,并标识需要托管的窗口 当检测到这样的窗口

我被卡住了,不知道该往哪里看

我有一个Java应用程序,它的一个功能是抓取一些特定的窗口(即第三方应用程序窗口),并将它们托管在自己的内部(带有一些额外的框架等) 除了我的Java应用程序死机(或崩溃)之外,整个过程都很顺利。发生这种情况时,托管的第三方窗口将被破坏,大多数情况下会使第三方应用程序完全崩溃

此功能设计为在Linux下工作

重新租赁的方式有点复杂:

  • 创建一个专用Java线程并调用一个C共享库(A .so lib)
  • 此共享库扫描所有当前窗口,并标识需要托管的窗口
  • 当检测到这样的窗口时,使用XReparentWindow将其重新出租给主Java应用程序窗口
  • 共享库进入无限循环(由退出标志控制)并等待XEvent(使用XNextEvent),以防显示需要承载的窗口
我已经编写了一个虚拟C程序,它使用大部分库代码(没有JNI位)来调试这个问题,使用xclock作为我的托管测试应用程序。 我可以复制完全相同的行为:当杀死虚拟程序时,Xclock窗口消失,并且在Xclock崩溃后不久消失

然后我修改共享库例程以使用XAddToSaveSet函数。 这在我的示例程序中起到了很好的作用:Xclock窗口被正确地还原并重新租入根窗口。 现在,对Java应用程序做同样的事情是行不通的:托管的窗口没有被重新分配到根窗口

我已经使用gdb、xev和xmon监控了正在发生的事情。正确调用了XAddToChangeSet,我可以看到ChangeSet请求通过xmon(窗口ID是正确的),但是当Java应用程序崩溃时,事件DestroyWindow被发送到托管窗口,而我本来希望看到RemapWindow事件(如使用示例C程序时)

有没有人在Java世界玩过这种东西

Java应用程序相当大:多线程且使用OpenGL(可能很重要)。RHEL4和RHEL6上的行为相同。 没有运行窗口管理器,只有一个裸X服务器(XOrg X111.10.2)

还有其他的调试方法吗? 我们能否以某种方式观察存储集? XServer是否应该向变更集请求发送回复

我的下一步是编写一个示例Java应用程序,并以与主应用程序相同的方式使用JNI接口,但希望有一些明显的遗漏

谢谢

[编辑]

最后,我使用一个虚拟Java应用程序进行了测试:一个JPanel和将XClock重新租入面板。 当Java进程被终止时,XClock窗口被破坏

下面是带有示例C代码(使用Xlib)的XMON日志摘录:

对于Java代码,会发生相同的初始化序列,但在终止进程时不会发生ReparentNotify事件

根据Andrey的建议,我实现了xfixechangesaveset。 版本1似乎正好解决了这个问题(或者已经足够接近):

  • 存储集处理更改。核心存储集处理中断 嵌套的存在。此扩展使嵌入应用程序 更可靠
不幸的是,没有任何变化

所以我想我会放弃这一点,找其他的解决办法

[编辑2]

我不得不再次讨论这个问题,通过正确地重新编码xfixesapi,一切都正常

因此,最后,代码:

XReparentWindow(display, childWindowId, newParentWindowId, 0, 0);
XFixesChangeSaveSet(display, childWindowId, SetModeInsert, SaveSetRoot, SaveSertMap);
执行此操作。

“事件销毁窗口被发送到托管窗口”听起来像是java运行时在进行清理(而不考虑存储集)。从中的“连接关闭”第10节:

你能在崩溃前后几秒钟发布xmon(或xtruss或xtrace)通信转储吗


此外,对于“重新分配此窗口并添加到存储集”这样的简单操作,我会尝试使用低级客户端,如,并避免所有这些“额外的线程+ffi调用到.so(是xlib吗?)

谢谢heap Andrey。我会尽快用xmon的日志更新帖子。我确实可以用一个非常基本的Java应用程序重现这个问题,从而导致Java/X11问题。但是我没有得到的一件事是我杀死了Java进程-9。它怎么能负责清理呢?我希望X服务器能够检测到它的客户端和浏览存储集。是的,那就是xlib.Cheers.yep,如果你真的杀死了-9,那么java进程就没有办法执行额外的x请求。另一个建议是使用来自XFixes扩展的存储集——这有点不同,你可以知道哪个窗口需要重新访问代码部分,并用XFixes API.I正确地重做测试没用!!我不太确定我第一次尝试时做了什么,但同样的代码现在可以用了。非常感谢你的想法。嗨,丹尼斯。我正在做,你介意看一下吗?
XReparentWindow(display, childWindowId, newParentWindowId, 0, 0);
XFixesChangeSaveSet(display, childWindowId, SetModeInsert, SaveSetRoot, SaveSertMap);
When a client's resources are destroyed, for each window in the client's
save-set, if the window is an inferior of a window created by the client, the
save-set window is reparented to the closest ancestor such that the save-set
window is not an inferior of a window created by the client. If the save-set
window is unmapped, a MapWindow request is performed on it (even if it was not
an inferior of a window created by the client). The reparenting leaves
unchanged the absolute coordinates (with respect to the root window) of the
upper-left outer corner of the save-set window. After save-set processing, all
windows created by the client are destroyed. For each nonwindow resource
created by the client, the appropriate Free request is performed. All colors
and colormap entries allocated by the client are freed.