27 #if CONFIG_LIBXCB_XFIXES
28 #include <xcb/xfixes.h>
36 #if CONFIG_LIBXCB_SHAPE
37 #include <xcb/shape.h>
78 #define FOLLOW_CENTER -1
80 #define OFFSET(x) offsetof(XCBGrabContext, x)
81 #define D AV_OPT_FLAG_DECODING_PARAM
85 {
"video_size",
"A string describing frame size, such as 640x480 or hd720.",
OFFSET(video_size),
AV_OPT_TYPE_STRING, {.str =
"vga" }, 0, 0,
D },
88 {
"follow_mouse",
"Move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region.",
90 {
"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" },
91 {
"show_region",
"Show the grabbing region.",
OFFSET(show_region),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1,
D },
92 {
"region_border",
"Set the region border thickness.",
OFFSET(region_border),
AV_OPT_TYPE_INT, { .i64 = 3 }, 1, 128,
D },
105 xcb_query_pointer_reply_t *p,
106 xcb_get_geometry_reply_t *geo)
109 int x = c->
x,
y = c->
y, p_x = p->win_x, p_y = p->win_y;
120 int right = x + w - f;
122 int bottom =
y + h + f;
125 }
else if (p_x < left) {
130 }
else if (p_y < top) {
144 xcb_get_image_cookie_t iq;
145 xcb_get_image_reply_t *
img;
146 xcb_drawable_t drawable = c->
screen->root;
150 iq = xcb_get_image(c->
conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable,
153 img = xcb_get_image_reply(c->
conn, iq, NULL);
157 data = xcb_get_image_data(img);
158 length = xcb_get_image_data_length(img);
163 memcpy(pkt->
data, data, length);
173 int64_t curtime, delay;
189 #if CONFIG_LIBXCB_SHM
190 static int check_shm(xcb_connection_t *conn)
192 xcb_shm_query_version_cookie_t cookie = xcb_shm_query_version(conn);
193 xcb_shm_query_version_reply_t *reply;
195 reply = xcb_shm_query_version_reply(conn, cookie, NULL);
204 static void dealloc_shm(
void *unused,
uint8_t *
data)
212 xcb_shm_get_image_cookie_t iq;
213 xcb_shm_get_image_reply_t *
img;
214 xcb_drawable_t drawable = c->
screen->root;
217 int id = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777);
218 xcb_generic_error_t *e = NULL;
229 xcb_shm_attach(c->
conn, c->segment,
id, 0);
231 iq = xcb_shm_get_image(c->
conn, drawable,
233 XCB_IMAGE_FORMAT_Z_PIXMAP, c->segment, 0);
235 xcb_shm_detach(c->
conn, c->segment);
237 img = xcb_shm_get_image_reply(c->
conn, iq, &e);
243 "Cannot get the image data "
244 "event_error: response_type:%u error_code:%u "
245 "sequence:%u resource_id:%u minor_code:%u major_code:%u.\n",
246 e->response_type, e->error_code,
247 e->sequence, e->resource_id, e->minor_code, e->major_code);
249 shmctl(
id, IPC_RMID, 0);
255 data = shmat(
id, NULL, 0);
256 shmctl(
id, IPC_RMID, 0);
258 if ((intptr_t)data == -1)
274 #if CONFIG_LIBXCB_XFIXES
275 static int check_xfixes(xcb_connection_t *conn)
277 xcb_xfixes_query_version_cookie_t cookie;
278 xcb_xfixes_query_version_reply_t *reply;
280 cookie = xcb_xfixes_query_version(conn, XCB_XFIXES_MAJOR_VERSION,
281 XCB_XFIXES_MINOR_VERSION);
282 reply = xcb_xfixes_query_version_reply(conn, cookie, NULL);
291 #define BLEND(target, source, alpha) \
292 (target) + ((source) * (255 - (alpha)) + 255 / 2) / 255
295 xcb_query_pointer_reply_t *p,
296 xcb_get_geometry_reply_t *geo)
302 xcb_xfixes_get_cursor_image_cookie_t cc;
303 xcb_xfixes_get_cursor_image_reply_t *ci;
304 int cx, cy, x,
y, w, h, c_off, i_off;
306 cc = xcb_xfixes_get_cursor_image(gr->
conn);
307 ci = xcb_xfixes_get_cursor_image_reply(gr->
conn, cc, NULL);
311 cursor = xcb_xfixes_get_cursor_image_cursor_image(ci);
315 cx = ci->x - ci->xhot;
316 cy = ci->y - ci->yhot;
327 cursor += (y - cy) * ci->width;
328 image += (y - gr->
y) * gr->
width * stride;
330 for (y = 0; y < h; y++) {
332 image += i_off * stride;
333 for (x = 0; x < w; x++, cursor++, image += stride) {
337 g = (*cursor >> 8) & 0xff;
338 b = (*cursor >> 16) & 0xff;
339 a = (*cursor >> 24) & 0xff;
349 image[0] = BLEND(r, image[0], a);
350 image[1] = BLEND(g, image[1], a);
351 image[2] = BLEND(b, image[2], a);
355 cursor += ci->width - w - c_off;
356 image += (gr->
width - w - i_off) * stride;
369 xcb_configure_window(c->
conn,
371 XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
378 xcb_query_pointer_cookie_t pc;
379 xcb_get_geometry_cookie_t gc;
380 xcb_query_pointer_reply_t *p = NULL;
381 xcb_get_geometry_reply_t *geo = NULL;
387 pc = xcb_query_pointer(c->
conn, c->
screen->root);
388 gc = xcb_get_geometry(c->
conn, c->
screen->root);
389 p = xcb_query_pointer_reply(c->
conn, pc, NULL);
390 geo = xcb_get_geometry_reply(c->
conn, gc, NULL);
399 #if CONFIG_LIBXCB_SHM
400 if (c->
has_shm && xcbgrab_frame_shm(s, pkt) < 0)
406 #if CONFIG_LIBXCB_XFIXES
408 xcbgrab_draw_mouse(s, pkt, p, geo);
421 xcb_disconnect(ctx->
conn);
426 static xcb_screen_t *
get_screen(
const xcb_setup_t *setup,
int screen_num)
428 xcb_screen_iterator_t it = xcb_setup_roots_iterator(setup);
429 xcb_screen_t *
screen = NULL;
431 for (; it.rem > 0; xcb_screen_next (&it)) {
447 const xcb_setup_t *setup = xcb_get_setup(c->
conn);
448 const xcb_format_t *
fmt = xcb_setup_pixmap_formats(setup);
449 int length = xcb_setup_pixmap_formats_length(setup);
454 if (fmt->depth == depth) {
457 if (fmt->bits_per_pixel == 32)
461 if (fmt->bits_per_pixel == 32)
463 else if (fmt->bits_per_pixel == 24)
467 if (fmt->bits_per_pixel == 16)
471 if (fmt->bits_per_pixel == 16)
475 if (fmt->bits_per_pixel == 8)
482 c->
bpp = fmt->bits_per_pixel;
498 xcb_get_geometry_cookie_t gc;
499 xcb_get_geometry_reply_t *geo;
515 gc = xcb_get_geometry(c->
conn, c->
screen->root);
516 geo = xcb_get_geometry_reply(c->
conn, gc, NULL);
540 xcb_gcontext_t gc = xcb_generate_id(c->
conn);
541 uint32_t
mask = XCB_GC_FOREGROUND |
546 uint32_t values[] = { c->
screen->black_pixel,
549 XCB_LINE_STYLE_DOUBLE_DASH,
550 XCB_FILL_STYLE_SOLID };
551 xcb_rectangle_t
r = { 1, 1,
555 xcb_create_gc(c->
conn, gc, c->
window, mask, values);
557 xcb_poly_rectangle(c->
conn, c->
window, gc, 1, &r);
563 uint32_t
mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
564 uint32_t values[] = { 1,
565 XCB_EVENT_MASK_EXPOSURE |
566 XCB_EVENT_MASK_STRUCTURE_NOTIFY };
571 xcb_create_window(c->
conn, XCB_COPY_FROM_PARENT,
579 XCB_WINDOW_CLASS_INPUT_OUTPUT,
580 XCB_COPY_FROM_PARENT,
583 #if CONFIG_LIBXCB_SHAPE
584 xcb_shape_rectangles(c->
conn, XCB_SHAPE_SO_SUBTRACT,
585 XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED,
600 const xcb_setup_t *setup;
606 if (!sscanf(s->
filename,
"%[^+]+%d,%d", display_name, &c->
x, &c->
y)) {
611 c->
conn = xcb_connect(display_name, &screen_num);
613 if ((ret = xcb_connection_has_error(c->
conn))) {
618 setup = xcb_get_setup(c->
conn);
628 #if CONFIG_LIBXCB_SHM
629 c->segment = xcb_generate_id(c->
conn);
639 #if CONFIG_LIBXCB_SHM
643 #if CONFIG_LIBXCB_XFIXES
647 "XFixes not available, cannot draw the mouse.\n");
671 .priv_class = &xcbgrab_class,