XReparentWindow работает спорадически - PullRequest
0 голосов
/ 15 февраля 2019

Я экспериментирую с 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 ...

Что происходит?

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Решение для перебора, повторное получение окна:

#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.Работает на моей машине.Буду признателен за полное объяснение того, что на самом деле происходит.

0 голосов
/ 19 февраля 2019

Я никогда не пробовал с приложением OpenGL и у меня нет среды здесь.Может быть, попробуйте сначала с простым приложением X (например, xclock) и наблюдайте, получаете ли вы такое же поведение.Если да, то это ваш код, если нет, то, вероятно, взаимодействие OpenGL.

Из вашего сниппета два комментария:

В цикле 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);
...
...