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;
152 xcb_generic_error_t *e =
NULL;
156 iq = xcb_get_image(c->
conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable,
159 img = xcb_get_image_reply(c->
conn, iq, &e);
163 "Cannot get the image data "
164 "event_error: response_type:%u error_code:%u "
165 "sequence:%u resource_id:%u minor_code:%u major_code:%u.\n",
166 e->response_type, e->error_code,
167 e->sequence, e->resource_id, e->minor_code, e->major_code);
174 data = xcb_get_image_data(img);
175 length = xcb_get_image_data_length(img);
180 memcpy(pkt->
data, data, length);
190 int64_t curtime, delay;
206 #if CONFIG_LIBXCB_SHM
207 static int check_shm(xcb_connection_t *conn)
209 xcb_shm_query_version_cookie_t cookie = xcb_shm_query_version(conn);
210 xcb_shm_query_version_reply_t *reply;
212 reply = xcb_shm_query_version_reply(conn, cookie,
NULL);
221 static void dealloc_shm(
void *unused,
uint8_t *
data)
229 xcb_shm_get_image_cookie_t iq;
230 xcb_shm_get_image_reply_t *
img;
231 xcb_drawable_t drawable = c->
screen->root;
234 int id = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777);
235 xcb_generic_error_t *e =
NULL;
246 xcb_shm_attach(c->
conn, c->segment,
id, 0);
248 iq = xcb_shm_get_image(c->
conn, drawable,
250 XCB_IMAGE_FORMAT_Z_PIXMAP, c->segment, 0);
252 xcb_shm_detach(c->
conn, c->segment);
254 img = xcb_shm_get_image_reply(c->
conn, iq, &e);
260 "Cannot get the image data "
261 "event_error: response_type:%u error_code:%u "
262 "sequence:%u resource_id:%u minor_code:%u major_code:%u.\n",
263 e->response_type, e->error_code,
264 e->sequence, e->resource_id, e->minor_code, e->major_code);
266 shmctl(
id, IPC_RMID, 0);
272 data = shmat(
id,
NULL, 0);
273 shmctl(
id, IPC_RMID, 0);
275 if ((intptr_t)data == -1)
291 #if CONFIG_LIBXCB_XFIXES
292 static int check_xfixes(xcb_connection_t *conn)
294 xcb_xfixes_query_version_cookie_t cookie;
295 xcb_xfixes_query_version_reply_t *reply;
297 cookie = xcb_xfixes_query_version(conn, XCB_XFIXES_MAJOR_VERSION,
298 XCB_XFIXES_MINOR_VERSION);
299 reply = xcb_xfixes_query_version_reply(conn, cookie,
NULL);
308 #define BLEND(target, source, alpha) \
309 (target) + ((source) * (255 - (alpha)) + 255 / 2) / 255
312 xcb_query_pointer_reply_t *p,
313 xcb_get_geometry_reply_t *geo)
319 xcb_xfixes_get_cursor_image_cookie_t cc;
320 xcb_xfixes_get_cursor_image_reply_t *ci;
321 int cx, cy, x,
y, w, h, c_off, i_off;
323 cc = xcb_xfixes_get_cursor_image(gr->
conn);
324 ci = xcb_xfixes_get_cursor_image_reply(gr->
conn, cc,
NULL);
328 cursor = xcb_xfixes_get_cursor_image_cursor_image(ci);
332 cx = ci->x - ci->xhot;
333 cy = ci->y - ci->yhot;
344 cursor += (y - cy) * ci->width;
345 image += (y - gr->
y) * gr->
width * stride;
347 for (y = 0; y < h; y++) {
349 image += i_off * stride;
350 for (x = 0; x < w; x++, cursor++, image += stride) {
354 g = (*cursor >> 8) & 0xff;
355 b = (*cursor >> 16) & 0xff;
356 a = (*cursor >> 24) & 0xff;
366 image[0] = BLEND(r, image[0], a);
367 image[1] = BLEND(g, image[1], a);
368 image[2] = BLEND(b, image[2], a);
372 cursor += ci->width - w - c_off;
373 image += (gr->
width - w - i_off) * stride;
386 xcb_configure_window(c->
conn,
388 XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
395 xcb_query_pointer_cookie_t pc;
396 xcb_get_geometry_cookie_t gc;
397 xcb_query_pointer_reply_t *p =
NULL;
398 xcb_get_geometry_reply_t *geo =
NULL;
404 pc = xcb_query_pointer(c->
conn, c->
screen->root);
405 gc = xcb_get_geometry(c->
conn, c->
screen->root);
406 p = xcb_query_pointer_reply(c->
conn, pc,
NULL);
407 geo = xcb_get_geometry_reply(c->
conn, gc,
NULL);
416 #if CONFIG_LIBXCB_SHM
417 if (c->
has_shm && xcbgrab_frame_shm(s, pkt) < 0)
423 #if CONFIG_LIBXCB_XFIXES
424 if (ret >= 0 && c->
draw_mouse && p->same_screen)
425 xcbgrab_draw_mouse(s, pkt, p, geo);
438 xcb_disconnect(ctx->
conn);
443 static xcb_screen_t *
get_screen(
const xcb_setup_t *setup,
int screen_num)
445 xcb_screen_iterator_t it = xcb_setup_roots_iterator(setup);
448 for (; it.rem > 0; xcb_screen_next (&it)) {
464 const xcb_setup_t *setup = xcb_get_setup(c->
conn);
465 const xcb_format_t *
fmt = xcb_setup_pixmap_formats(setup);
466 int length = xcb_setup_pixmap_formats_length(setup);
471 if (fmt->depth == depth) {
474 if (fmt->bits_per_pixel == 32)
478 if (fmt->bits_per_pixel == 32)
480 else if (fmt->bits_per_pixel == 24)
484 if (fmt->bits_per_pixel == 16)
488 if (fmt->bits_per_pixel == 16)
492 if (fmt->bits_per_pixel == 8)
499 c->
bpp = fmt->bits_per_pixel;
515 xcb_get_geometry_cookie_t gc;
516 xcb_get_geometry_reply_t *geo;
532 gc = xcb_get_geometry(c->
conn, c->
screen->root);
533 geo = xcb_get_geometry_reply(c->
conn, gc,
NULL);
535 if (c->
x + c->
width > geo->width ||
536 c->
y + c->
height > geo->height) {
538 "Capture area %dx%d at position %d.%d "
539 "outside the screen size %dx%d\n",
542 geo->width, geo->height);
566 xcb_gcontext_t gc = xcb_generate_id(c->
conn);
567 uint32_t
mask = XCB_GC_FOREGROUND |
572 uint32_t values[] = { c->
screen->black_pixel,
575 XCB_LINE_STYLE_DOUBLE_DASH,
576 XCB_FILL_STYLE_SOLID };
577 xcb_rectangle_t
r = { 1, 1,
581 xcb_create_gc(c->
conn, gc, c->
window, mask, values);
583 xcb_poly_rectangle(c->
conn, c->
window, gc, 1, &r);
589 uint32_t
mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
590 uint32_t values[] = { 1,
591 XCB_EVENT_MASK_EXPOSURE |
592 XCB_EVENT_MASK_STRUCTURE_NOTIFY };
597 xcb_create_window(c->
conn, XCB_COPY_FROM_PARENT,
605 XCB_WINDOW_CLASS_INPUT_OUTPUT,
606 XCB_COPY_FROM_PARENT,
609 #if CONFIG_LIBXCB_SHAPE
610 xcb_shape_rectangles(c->
conn, XCB_SHAPE_SO_SUBTRACT,
611 XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED,
626 const xcb_setup_t *setup;
632 if (!sscanf(s->
filename,
"%[^+]+%d,%d", display_name, &c->
x, &c->
y)) {
637 c->
conn = xcb_connect(display_name[0] ? display_name :
NULL, &screen_num);
640 if ((ret = xcb_connection_has_error(c->
conn))) {
645 setup = xcb_get_setup(c->
conn);
662 #if CONFIG_LIBXCB_SHM
664 c->segment = xcb_generate_id(c->
conn);
667 #if CONFIG_LIBXCB_XFIXES
671 "XFixes not available, cannot draw the mouse.\n");
695 .priv_class = &xcbgrab_class,