X11 / XCB / Xlib: копирование корневого окна в растровое изображение

Я могу скопировать содержимое корневого окна в xcb_image_t в клиентской (т.е. CPU) памяти, используя xcb_image_get() (независимо от его статуса map, хотя предположительно корневое окно всегда отображается ?). Например:

xcb_image_t* xcb_img = xcb_image_get(xcb_connection, xcb_screen->root, 0, 0, xcb_screen->width_in_pixels, xcb_screen->height_in_pixels, 0x00ffffff, XCB_IMAGE_FORMAT_Z_PIXMAP);

Теперь пиксели корневого окна находятся в xcb_img->data.

Но я пытаюсь скопировать содержимое корневого окна в xcb_pixmap_t (в памяти сервера), и оно не работает (вызов не завершается неудачно, но возвращает мусор, как если бы окно не было отображено):

  xcb_void_cookie_t    copy_cookie = xcb_copy_area_checked(xcb_connection, xcb_screen->root, xcb_pixmap, xcb_gc_null, 0, 0, 0, 0, xcb_screen->width_in_pixels, xcb_screen->height_in_pixels);
  xcb_generic_error_t* copy_error  = xcb_request_check(xcb_connection, copy_cookie);
  if(copy_error)
    exit(1);

Однако он работает для других окон, которые случайно отображаются (и не работает для подобластей тех окон, которые закрыты другими окнами, в том смысле, что копия возвращает мусор).

Я понимаю, что окно должно быть сопоставлено, чтобы иметь значимое содержимое. Это наводит меня на мысль, что корневое окно никогда не отображается (или что-то в этом роде).

Все, что я хочу, - это скопировать содержимое дисплея (т.е. пиксели, которые в настоящее время отображаются на физическом дисплее / мониторе) в xcb_pixmap_t (или, что то же самое, в Xlib Pixmap). Как я могу это сделать? (Это так легко работает для _9 _...)


person étale-cohomology    schedule 20.06.2018    source источник
comment
Как создается ваш xcb_gc_null? Какой у него режим подокна? Работает ли это, если вы установите для него значение IncludeInferiors, то есть от XCB_GC_SUBWINDOW_MODE до XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS (либо в xcb_create_gc, либо позже с xcb_change_gc)   -  person Uli Schlachter    schedule 22.08.2018
comment
Привет Ули! Ваша идея сработала! Большое спасибо за внимание к этому вне списка рассылки xcb =) Я думал, что не могу получить доступ к пикселям корневого окна, потому что оконный менеджер уже владел им! (Я думаю, что первый клиент, претендующий на владение корневым окном, получает полный контроль, а другие клиенты получают ошибку доступа или что-то в этом роде). Интересно, почему XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS имеет значение? xcb_gc_null - это просто (то, что я думаю) тривиальный gc, т.е. xcb_create_gc(connection, xcb_gc_null, window_xid, XCB_GC_GRAPHICS_EXPOSURES, (u32[]){XCB_EXPOSURES_NOT_ALLOWED})   -  person étale-cohomology    schedule 24.08.2018
comment
Единственное право собственности, которое принадлежит WM, - это выбор SubstructureRedirect в корневом окне. Только один клиент может делать это одновременно. Это не имеет ничего общего с рисованием, а участвует только в создании и отображении новых окон. См. Мой ответ для описания SubwindowMode.   -  person Uli Schlachter    schedule 27.08.2018


Ответы (1)


Вы хотите, чтобы в вашем GC для SubwindowMode было установлено значение IncludeInferiors (по умолчанию - ClipByChildren).

Из описания протокола X11:

Для ClipByChildren окна источника и назначения дополнительно обрезаются всеми видимыми дочерними элементами InputOutput. Для IncludeInferiors ни исходное, ни целевое окно не обрезаются подчиненными элементами. Это приведет к включению содержимого подокна в источник и прорисовке через границы подокна места назначения. Использование IncludeInferiors с исходным или конечным окном одной глубины с отображенными подчиненными с разной глубиной не является незаконным, но семантика не определена основным протоколом.

https://www.x.org/releases/X11R7.5/doc/x11proto/proto.html

Это означает, что с ClipByChildren вы копируете только из окна, которое вы использовали в качестве источника. Если в окне есть подокна, пиксели «там» не принадлежат окну, которое вы используете в качестве источника. Таким образом, X11 предполагает, что вам не нужны эти пиксели.

person Uli Schlachter    schedule 27.08.2018
comment
Большое спасибо! Что значит drawing through subwindow boundaries? - person étale-cohomology; 27.08.2018
comment
Представьте, что вы xcb_copy_area в корневое окно. С помощью ClipByChildren отрисовывается только та часть, где фактически видно корневое окно (подумайте: отрисовывается только к вашим обоям). С IncludeInferios это вместо этого будет рисовать по всем окнам. - person Uli Schlachter; 27.08.2018