XReparentWindow偶尔工作

问题描述 投票:0回答:2

我正在尝试使用XReparentWindow,最终目标是将多个进程的窗口聚合成一个“驾驶舱”模拟过程。 XReparentWindow的实验偶尔进行 ;有时候窗口会成功地重新设置,有时候不会 。当没有成功重新制作时 (不) 抓住窗口闪烁一秒钟,然后照常进行,抓取器显示未定义的窗口内容。它每隔一段时间都是成功的(试图通过总是尝试两次来强行解决问题)。

编辑1:在XQueryTree显示抓取的窗口正确重新设置后检查XReparentWindow的输出,但看起来保持其帧原点从显示器抓取而不是移动到抓取器窗口。

抓取的窗口来自一个从源代码编译的实时OpenGL渲染应用程序。该应用程序不会以任何方式预期抓取(也许它应该?)。我也试过抓住glxgears和GNOME终端,结果相同。

实验代码,将窗口作为程序参数抓取(例如使用xwininfo | grep "Window id"):

#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;
}

(代码是从受限制的环境中手动导出的。对于导出期间发生的任何拼写错误,我们深表抱歉

期待下一步尝试的建议。

编辑2:使用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

我退出程序并再次尝试,继续输出的是:

UnmapNotify event ...
ReparentNotify event ... parent 0x4000001 (grabber window)
MapNotify event ...
VisibilityNotify event ...
Expose event ...

到底是怎么回事?

x11 gnome xlib
2个回答
0
投票

我从来没有尝试过使用OpenGL应用程序,也没有这里的环境。也许首先尝试一个简单的X应用程序(如xclock)并观察你是否得到相同的行为。如果是,那就是你的代码,如果没有,可能是OpenGL交互。

从你的snippset,两个评论:

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

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

然后XAddToSaveSet功能无法正常工作。您将需要使用XFix,以便在发生崩溃时正确恢复该窗口。

#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);
...

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后才能禁用该子句,才会发生这种情况。适用于我的机器。希望完全解释真正发生的事情。

© www.soinside.com 2019 - 2024. All rights reserved.