27 #if CONFIG_LIBXCB_XFIXES
28 #include <xcb/xfixes.h>
36 #if CONFIG_LIBXCB_SHAPE
37 #include <xcb/shape.h>
77 #define FOLLOW_CENTER -1
79 #define OFFSET(x) offsetof(XCBGrabContext, x)
80 #define D AV_OPT_FLAG_DECODING_PARAM
86 {
"video_size",
"A string describing frame size, such as 640x480 or hd720.",
OFFSET(video_size),
AV_OPT_TYPE_STRING, {.str =
"vga" }, 0, 0,
D },
89 {
"follow_mouse",
"Move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region.",
91 {
"centered",
"Keep the mouse pointer at the center of grabbing region when following.", 0,
AV_OPT_TYPE_CONST, { .i64 = -1 }, INT_MIN, INT_MAX,
D,
"follow_mouse" },
92 {
"show_region",
"Show the grabbing region.",
OFFSET(show_region),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1,
D },
93 {
"region_border",
"Set the region border thickness.",
OFFSET(region_border),
AV_OPT_TYPE_INT, { .i64 = 3 }, 1, 128,
D },
106 xcb_query_pointer_reply_t *p,
107 xcb_get_geometry_reply_t *geo)
110 int x = c->
x,
y = c->
y;
125 int right = x + w - f;
127 int bottom =
y + h + f;
130 }
else if (p_x < left) {
135 }
else if (p_y < top) {
149 xcb_get_image_cookie_t iq;
150 xcb_get_image_reply_t *
img;
151 xcb_drawable_t drawable = c->
screen->root;
155 iq = xcb_get_image(c->
conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable,
158 img = xcb_get_image_reply(c->
conn, iq,
NULL);
162 data = xcb_get_image_data(img);
163 length = xcb_get_image_data_length(img);
168 memcpy(pkt->
data, data, length);
178 int64_t curtime, delay;
194 #if CONFIG_LIBXCB_SHM
195 static int check_shm(xcb_connection_t *conn)
197 xcb_shm_query_version_cookie_t cookie = xcb_shm_query_version(conn);
198 xcb_shm_query_version_reply_t *reply;
200 reply = xcb_shm_query_version_reply(conn, cookie,
NULL);
209 static void dealloc_shm(
void *unused,
uint8_t *
data)
217 xcb_shm_get_image_cookie_t iq;
218 xcb_shm_get_image_reply_t *
img;
219 xcb_drawable_t drawable = c->
screen->root;
222 int id = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777);
223 xcb_generic_error_t *e =
NULL;
234 xcb_shm_attach(c->
conn, c->segment,
id, 0);
236 iq = xcb_shm_get_image(c->
conn, drawable,
238 XCB_IMAGE_FORMAT_Z_PIXMAP, c->segment, 0);
240 xcb_shm_detach(c->
conn, c->segment);
242 img = xcb_shm_get_image_reply(c->
conn, iq, &e);
248 "Cannot get the image data "
249 "event_error: response_type:%u error_code:%u "
250 "sequence:%u resource_id:%u minor_code:%u major_code:%u.\n",
251 e->response_type, e->error_code,
252 e->sequence, e->resource_id, e->minor_code, e->major_code);
254 shmctl(
id, IPC_RMID, 0);
260 data = shmat(
id,
NULL, 0);
261 shmctl(
id, IPC_RMID, 0);
263 if ((intptr_t)data == -1)
279 #if CONFIG_LIBXCB_XFIXES
280 static int check_xfixes(xcb_connection_t *conn)
282 xcb_xfixes_query_version_cookie_t cookie;
283 xcb_xfixes_query_version_reply_t *reply;
285 cookie = xcb_xfixes_query_version(conn, XCB_XFIXES_MAJOR_VERSION,
286 XCB_XFIXES_MINOR_VERSION);
287 reply = xcb_xfixes_query_version_reply(conn, cookie,
NULL);
296 #define BLEND(target, source, alpha) \
297 (target) + ((source) * (255 - (alpha)) + 255 / 2) / 255
300 xcb_query_pointer_reply_t *p,
301 xcb_get_geometry_reply_t *geo)
307 xcb_xfixes_get_cursor_image_cookie_t cc;
308 xcb_xfixes_get_cursor_image_reply_t *ci;
309 int cx, cy, x,
y, w, h, c_off, i_off;
311 cc = xcb_xfixes_get_cursor_image(gr->
conn);
312 ci = xcb_xfixes_get_cursor_image_reply(gr->
conn, cc,
NULL);
316 cursor = xcb_xfixes_get_cursor_image_cursor_image(ci);
320 cx = ci->x - ci->xhot;
321 cy = ci->y - ci->yhot;
332 cursor += (y - cy) * ci->width;
333 image += (y - gr->
y) * gr->
width * stride;
335 for (y = 0; y < h; y++) {
337 image += i_off * stride;
338 for (x = 0; x < w; x++, cursor++, image += stride) {
342 g = (*cursor >> 8) & 0xff;
343 b = (*cursor >> 16) & 0xff;
344 a = (*cursor >> 24) & 0xff;
354 image[0] = BLEND(r, image[0], a);
355 image[1] = BLEND(g, image[1], a);
356 image[2] = BLEND(b, image[2], a);
360 cursor += ci->width - w - c_off;
361 image += (gr->
width - w - i_off) * stride;
374 xcb_configure_window(c->
conn,
376 XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
383 xcb_query_pointer_cookie_t pc;
384 xcb_get_geometry_cookie_t gc;
385 xcb_query_pointer_reply_t *p =
NULL;
386 xcb_get_geometry_reply_t *geo =
NULL;
392 pc = xcb_query_pointer(c->
conn, c->
screen->root);
393 gc = xcb_get_geometry(c->
conn, c->
screen->root);
394 p = xcb_query_pointer_reply(c->
conn, pc,
NULL);
395 geo = xcb_get_geometry_reply(c->
conn, gc,
NULL);
404 #if CONFIG_LIBXCB_SHM
405 if (c->
has_shm && xcbgrab_frame_shm(s, pkt) < 0)
411 #if CONFIG_LIBXCB_XFIXES
413 xcbgrab_draw_mouse(s, pkt, p, geo);
426 xcb_disconnect(ctx->
conn);
431 static xcb_screen_t *
get_screen(
const xcb_setup_t *setup,
int screen_num)
433 xcb_screen_iterator_t it = xcb_setup_roots_iterator(setup);
436 for (; it.rem > 0; xcb_screen_next (&it)) {
452 const xcb_setup_t *setup = xcb_get_setup(c->
conn);
453 const xcb_format_t *
fmt = xcb_setup_pixmap_formats(setup);
454 int length = xcb_setup_pixmap_formats_length(setup);
459 if (fmt->depth == depth) {
462 if (fmt->bits_per_pixel == 32)
466 if (fmt->bits_per_pixel == 32)
468 else if (fmt->bits_per_pixel == 24)
472 if (fmt->bits_per_pixel == 16)
476 if (fmt->bits_per_pixel == 16)
480 if (fmt->bits_per_pixel == 8)
487 c->
bpp = fmt->bits_per_pixel;
503 xcb_get_geometry_cookie_t gc;
504 xcb_get_geometry_reply_t *geo;
520 gc = xcb_get_geometry(c->
conn, c->
screen->root);
521 geo = xcb_get_geometry_reply(c->
conn, gc,
NULL);
545 xcb_gcontext_t gc = xcb_generate_id(c->
conn);
546 uint32_t
mask = XCB_GC_FOREGROUND |
551 uint32_t values[] = { c->
screen->black_pixel,
554 XCB_LINE_STYLE_DOUBLE_DASH,
555 XCB_FILL_STYLE_SOLID };
556 xcb_rectangle_t
r = { 1, 1,
560 xcb_create_gc(c->
conn, gc, c->
window, mask, values);
562 xcb_poly_rectangle(c->
conn, c->
window, gc, 1, &r);
568 uint32_t
mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
569 uint32_t values[] = { 1,
570 XCB_EVENT_MASK_EXPOSURE |
571 XCB_EVENT_MASK_STRUCTURE_NOTIFY };
576 xcb_create_window(c->
conn, XCB_COPY_FROM_PARENT,
584 XCB_WINDOW_CLASS_INPUT_OUTPUT,
585 XCB_COPY_FROM_PARENT,
588 #if CONFIG_LIBXCB_SHAPE
589 xcb_shape_rectangles(c->
conn, XCB_SHAPE_SO_SUBTRACT,
590 XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED,
605 const xcb_setup_t *setup;
611 if (!sscanf(s->
filename,
"%[^+]+%d,%d", display_name, &c->
x, &c->
y)) {
616 c->
conn = xcb_connect(display_name[0] ? display_name :
NULL, &screen_num);
619 if ((ret = xcb_connection_has_error(c->
conn))) {
624 setup = xcb_get_setup(c->
conn);
641 #if CONFIG_LIBXCB_SHM
643 c->segment = xcb_generate_id(c->
conn);
646 #if CONFIG_LIBXCB_XFIXES
650 "XFixes not available, cannot draw the mouse.\n");
674 .priv_class = &xcbgrab_class,