XReparentWindow偶尔起作用

时间:2019-02-15 09:30:31

标签: x11 gnome xlib

我正在试验XReparentWindow,最终目的是将多个进程的窗口聚合到一个“座舱”模拟进程中。 XReparentWindow的实验偶尔会起作用。有时窗口重新设置成功,有时没有成功。如果未成功重新设置父级,则(非)抓取的窗口闪烁一秒钟,然后照常进行,抓取器将显示未定义的窗口内容。每隔两次就成功了一次(总是尝试两次就试图强行解决问题)。

编辑1:在socket.on('run', async options => { try { user = await User.findById(jwt.verify(options.token, config.get('jwtPrivateKey'))._id); options.userId = user._id.toString(); return true; } catch (err) { throw err; }}); 显示所抓取的窗口已正确重新设置后立即检查XQueryTree的输出,但似乎将其帧原点保留在显示的抓取位置,而不是移至抓取器窗口

抓取的窗口来自实时OpenGL渲染应用程序,该应用程序是从源代码编译的。该应用程序不会以任何方式预期抢夺(也许应该吗?)。我也尝试过抢XReparentWindow和GNOME Terminal,结果相同。

实验代码,以窗口作为程序参数(例如,使用glxgears):

xwininfo | grep "Window id"

(代码是从受限环境中手动导出的。对于导出过程中出现的任何错字,我们深表歉意。)

期待有关下一步尝试的建议。

编辑2:使用#include <X11/Xlib.h> #include <stdio.h> #include <assert.h> #include <unistd.h> // usleep int main(int argc, char** argv) { assert(argc==2); Window window, extwin; sscanf(argv[1], "%p", &extwin); Display* display = XOpenDisplay(0); window = XCreateWindow(display, RootWindow(display, 0), 0, 0, 500, 500, 0, DefaultDepth(display, 0), InputOutput, DefaultVisual(display, 0), 0, 0); XMapWindow(display, window); XReparentWindow(display, extwin, window, 0, 0); while(1) { XFlush(display); usleep(3e5); } return 0; } 捕获抓取窗口的事件流后,我发现有些奇怪;重新设置到采集卡窗口后,它会在不到一秒钟的时间内重新将自己重新绑定到根窗口(受限制的环境,键入在其他窗口上看到的具有预期意义的内容):

xev

我退出程序,然后再次尝试,然后继续输出:

UnmapNotify event ...
ReparentNotify event ... parent 0x4000001 (grabber window)
MapNotify event ...
ConfigureNotify event ... synthetic YES (what is this?)
UnmapNotify event ...
ReparentNotify event ... parent 0xed (reparenting back to parent window, but why?)
MapNotify event ...
VisibilityNotify event ...
Expose event ...
PropertyNotify event ... _NET_WM_DESKTOP state PropertyDelete
PropertyNotify event ... _NET_WM_STATE state PropertyDelete
PropertyNotify event ... WM_STATE state PropertyNewValue

这是怎么回事?

2 个答案:

答案 0 :(得分:0)

我从未尝试过使用OpenGL应用程序,并且这里没有环境。 也许首先尝试使用简单的X应用程序(例如xclock),然后观察您是否获得相同的行为。 如果是,那是您的代码,如果不是,那可能是OpenGL交互。

在您的摘要中,有两个评论:

while循环中,您应该使用X个事件

XEvent e;    
while(1) {
     XNextEvent(d, &e);
}

然后XAddToSaveSet函数无法正常工作。 您需要使用XFixes才能在崩溃时正确还原该窗口。

#include <X11/extensions/Xfixes.h>

...

// The Xorg API is buggy in certain areas.
// Need to use the XFixes extensions to address them
// Initializes these extensions
int event_base_return = 0;
int error_base_return = 0;
Bool result = XFixesQueryExtension(display, &event_base_return);
printf("XFixesQueryExtension result: %d. eventbase: %d - errorbase: %d\n", result, event_base_return, error_base_return);

// We actually only need version 1.0. But if 4.0 is not there then something is really wrong
int major = 4;
int minor = 0;
result = XFixesQueryVersion(display, &major, &minor);
printf("XFixesQueryVersion result: %d - version: %d.%d\n", result, major, minor);

...
XReparentWindow(display, childWindowId, parentWindowId, 0, 0);
XFixesChangeSaveSet(display, childWindowId, SetModeInsert, SaveSetRoot, SaveSetUnmap);
...

答案 1 :(得分:0)

强力解决方案,反复抓住窗户:

#include <X11/Xlib.h>
#include <stdio.h>
#include <assert.h>
#include <unistd.h> // usleep

int main(int argc, char** argv) {
  assert(argc==2);
  Window window, extwin;
  sscanf(argv[1], "%p", &extwin);
  Display* display = XOpenDisplay(0);
  window = XCreateWindow(display, RootWindow(display, 0), 0, 0, 500, 500, 0, DefaultDepth(display, 0), InputOutput, DefaultVisual(display, 0), 0, 0);
  XMapWindow(display, window);
  while(1) {
    Window root, parent, *ch;
    unsigned int nch;
    XQueryTree(display, extwin, &root, &parent, &ch, &nch);
    if(parent!=window) {
      XReparentWindow(display, extwin, window, 0, 0);
    }
    if(nch>0) { XFree(ch); }
    XFlush(display);
    usleep(3e5);
  }
  return 0;
}

假定仅在两次调用reparent之后可以禁用该子句的情况下才会发生这种情况。在我的机器上工作。希望对真正发生的事情有充分的解释。