如何在XCB + C中创建一个叠加层?
我找到了一个使用 xlib 的点击穿透窗口的示例。
xlib中的代码是这样的;
XRectangle rect;
XserverRegion region = XFixesCreateRegion(display, &rect, 1);
XFixesSetWindowShapeRegion(display, window, ShapeInput, 0, 0, region);
XFixesDestroyRegion(display, region);
于是我在xcb中写了如下代码:
xcb_rectangle_t rect [1] = {{0, 0, 0, 0}};
xcb_xfixes_region_t region;
xcb_xfixes_create_region(c, region, 1, rect);
xcb_xfixes_set_window_shape_region(c, window, 2, 0, 0, region);
(我在循环之后放置 xcb_xfixes_destroy_region(c, region);,因为我假设这是清理步骤)
我在Linux Mint上,编译参数: gcc -o pixel_xcb pixel_xcb.c -lxcb -lxcb-image -lxcb-shape -lxcb-xfixes
但问题是,它似乎无法让我对该窗口进行“点击穿透”。
完整代码:
// code adapted from here https://xorg.freedesktop.org/archive/X11R7.7/doc/libxcb/tutorial/index.html#intro
// extra info here https://xcb.freedesktop.org/manual/group__XCB____API.html
// comparisons here https://www.x.org/guide/xlib-and-xcb/#example:convertingxdpyinfoextensionqueriestoxcb
// so can i use this to save an image and then draw it to the screen?
// https://stackoverflow.com/questions/34176795/any-efficient-way-of-converting-ximage-data-to-pixel-map-e-g-array-of-rgb-quad
// maybe something useful for shm here http://metan.ucw.cz/blog/things-i-wanted-to-know-about-libxcb.html
#include <xcb/xcb.h>
#include <xcb/xcb_image.h>
#include <xcb/xproto.h>
#include <stdio.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <xcb/shape.h>
#include <xcb/xfixes.h>
//#include "/home/loki/Documents/libxcb-errors-master/src/xcb_errors.c"
// click through xcb https://shallowsky.com/blog/programming/translucent-window-click-thru.html
xcb_screen_t *screen_of_display (xcb_connection_t *c, int screen){
xcb_screen_iterator_t iter;
iter = xcb_setup_roots_iterator (xcb_get_setup (c));
for (; iter.rem; --screen, xcb_screen_next (&iter))
if (screen == 0)
return iter.data;
return NULL;
}
int main(){
// display and screen
int screen_default_nbr;
xcb_connection_t *c = xcb_connect (NULL, &screen_default_nbr);
// screen
xcb_screen_t* screen = screen_of_display (c, screen_default_nbr);
// root display (screen / root window with other screens as background)
xcb_window_t root_window = { 0 };
root_window = screen->root;
// gc (black)
uint32_t values[4];
uint32_t mask = 0;
xcb_gcontext_t gc;
gc = xcb_generate_id (c);
mask = XCB_GC_FUNCTION | XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_SUBWINDOW_MODE;
values[0] = XCB_GX_COPY;
values[1] = screen->black_pixel;
values[2] = screen->white_pixel;
values[3] = XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS;
xcb_create_gc (c, gc, root_window, mask, values);
// window
xcb_window_t window = xcb_generate_id (c);
xcb_create_window (c, /* Connection */
XCB_COPY_FROM_PARENT, /* depth (same as root)*/
window, /* window Id */
screen->root, /* parent window */
0, 0, /* x, y */
150, 150, /* width, height */
10, /* border_width */
XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */
screen->root_visual, /* visual */
0, NULL ); /* masks, not used yet */
const uint32_t valuess[] ={1};
//xcb_change_window_attributes (c, window, XCB_CW_OVERRIDE_REDIRECT, valuess);
uint32_t client_major_version = XCB_XFIXES_MAJOR_VERSION;
uint32_t client_minor_version = XCB_XFIXES_MINOR_VERSION;
xcb_xfixes_query_version_cookie_t cook = xcb_xfixes_query_version(c, client_major_version, client_minor_version);
//xcb_generic_error_t *err;
//printf("%d", err->major_code);
xcb_xfixes_query_version_reply_t* rep = xcb_xfixes_query_version_reply(c, cook, NULL);
xcb_rectangle_t rect [0] = {};
xcb_xfixes_region_t region = xcb_generate_id(c);
xcb_xfixes_create_region(c, region, 0, rect);
xcb_xfixes_set_window_shape_region(c, window, XCB_SHAPE_SK_BOUNDING, 0, 0, region);
/* Map the window on the screen */
xcb_map_window (c, window);
// https://stackoverflow.com/questions/16400937/click-through-transparent-xlib-windows
/*
XRectangle rect;
XserverRegion region = XFixesCreateRegion(display, &rect, 1);
XFixesSetWindowShapeRegion(display, window, ShapeInput, 0, 0, region);
XFixesDestroyRegion(display, region);*/
// pixmap
/*xcb_pixmap_t pix = xcb_generate_id (c);
xcb_create_pixmap (c, screen->root_depth,
pix, /* Id of the pixmap *
screen->root,
screen->width_in_pixels, /* Width of the window (in pixels) *
screen->height_in_pixels);
uint32_t vals [1];
vals[0] = 0xffffff80;
// image
xcb_get_image_reply_t* img = xcb_get_image_reply(
c,
xcb_get_image (
c,
XCB_IMAGE_FORMAT_Z_PIXMAP,
root_window,
0,
0,
100,
100,
0
),
NULL
);
//for (int x = 0; x < ){
xcb_point_t points [1];
points[0].x = 10;
points[0].y = 10;
uint32_t vales [1];
vals[0] = 0x394dfe;
xcb_change_gc (c, gc, XCB_GC_FOREGROUND, vales);
xcb_poly_point (c, XCB_COORD_MODE_ORIGIN, pix, gc, 1, points);
//}*/
while (1){
//XCopyArea(disp, pix, root, gc, 0, 0, width - 100, height - 100, 0, 0); // offset size position#
//xcb_copy_area (c, pix, window, gc, 0, 0, 0, 0, screen->width_in_pixels, 500);
//xcb_image_put(c, pix, gc, img, 0, 0, 0);
//xcb_copy_area (c, pix, win, gc, 0, 0, 0, 0, 100, 100);
//XFlush(disp);
xcb_flush(c);
usleep(1);
}
xcb_xfixes_destroy_region(c, region);
//xcb_free_pixmap (c, pix);
xcb_disconnect(c);
}
解决方案
必须先调用 xcb_xfixes_query_version,然后再用 xcb_xfixes_query_version_reply 获取回复。这将初始化该扩展。没有它,xfixes的请求似乎会被静默丢弃。
你还需要用 xcb_generate_id (c) 初始化 region(就像初始化一个窗口或任何其他资源一样)。如果开启编译器警告,你会看到 region 未被初始化。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。