From 781c1aa6dce63a6c351bdf35ef6dea78805d5b5d Mon Sep 17 00:00:00 2001 From: Roxis Date: Fri, 27 Nov 2009 17:58:48 +0000 Subject: Real cursor support in x11grab. Patch by Roxis /// roxis list dot ru Slight changes by me to update the patch to current svn. Originally committed as revision 20631 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavdevice/x11grab.c | 116 +++++++++++++------------------------------------- 1 file changed, 29 insertions(+), 87 deletions(-) (limited to 'libavdevice/x11grab.c') diff --git a/libavdevice/x11grab.c b/libavdevice/x11grab.c index a9fdce4271..c564d66692 100644 --- a/libavdevice/x11grab.c +++ b/libavdevice/x11grab.c @@ -45,6 +45,7 @@ #include #include #include +#include /** * X11 Device Demuxer context @@ -234,35 +235,6 @@ x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) return 0; } -/** - * Get pointer coordinates from X11. - * - * @param x Integer where horizontal coordinate will be returned - * @param y Integer where vertical coordinate will be returned - * @param dpy X11 display from where pointer coordinates are retrieved - * @param s1 Context used for logging errors if necessary - */ -static void -get_pointer_coordinates(int *x, int *y, Display *dpy, AVFormatContext *s1) -{ - Window mrootwindow, childwindow; - int dummy; - - mrootwindow = DefaultRootWindow(dpy); - - if (XQueryPointer(dpy, mrootwindow, &mrootwindow, &childwindow, - x, y, &dummy, &dummy, (unsigned int*)&dummy)) { - } else { - struct x11_grab *s = s1->priv_data; - if (!s->mouse_warning_shown) { - av_log(s1, AV_LOG_INFO, "couldn't find mouse pointer\n"); - s->mouse_warning_shown = 1; - } - *x = -1; - *y = -1; - } -} - /** * Mouse painting helper function that applies an 'and' and 'or' mask pair to * '*dst' pixel. It actually draws a mouse pointer pixel to grabbed frame. @@ -300,71 +272,43 @@ apply_masks(uint8_t *dst, int and, int or, int bits_per_pixel) * @param y Mouse pointer coordinate */ static void -paint_mouse_pointer(XImage *image, struct x11_grab *s, int x, int y) +paint_mouse_pointer(XImage *image, struct x11_grab *s) { - /* 16x20x1bpp bitmap for the black channel of the mouse pointer */ - static const uint16_t const mousePointerBlack[] = - { - 0x0000, 0x0003, 0x0005, 0x0009, 0x0011, - 0x0021, 0x0041, 0x0081, 0x0101, 0x0201, - 0x03c1, 0x0049, 0x0095, 0x0093, 0x0120, - 0x0120, 0x0240, 0x0240, 0x0380, 0x0000 - }; - - /* 16x20x1bpp bitmap for the white channel of the mouse pointer */ - static const uint16_t const mousePointerWhite[] = - { - 0x0000, 0x0000, 0x0002, 0x0006, 0x000e, - 0x001e, 0x003e, 0x007e, 0x00fe, 0x01fe, - 0x003e, 0x0036, 0x0062, 0x0060, 0x00c0, - 0x00c0, 0x0180, 0x0180, 0x0000, 0x0000 - }; - int x_off = s->x_off; int y_off = s->y_off; int width = s->width; int height = s->height; + Display *dpy = s->dpy; + XFixesCursorImage *xcim; + int x, y; + int line, column; + int to_line, to_column; + int image_addr, xcim_addr; - if ( x - x_off >= 0 && x < width + x_off - && y - y_off >= 0 && y < height + y_off) { - uint8_t *im_data = (uint8_t*)image->data; - int bytes_per_pixel; - int line; - int masks; + xcim = XFixesGetCursorImage(dpy);; - /* Select correct masks and pixel size */ - if (image->bits_per_pixel == 8) { - masks = 1; - } else { - masks = (image->red_mask|image->green_mask|image->blue_mask); - } - bytes_per_pixel = image->bits_per_pixel>>3; - - /* Shift to right line */ - im_data += image->bytes_per_line * (y - y_off); - /* Shift to right pixel in the line */ - im_data += bytes_per_pixel * (x - x_off); - - /* Draw the cursor - proper loop */ - for (line = 0; line < FFMIN(20, (y_off + height) - y); line++) { - uint8_t *cursor = im_data; - int column; - uint16_t bm_b; - uint16_t bm_w; - - bm_b = mousePointerBlack[line]; - bm_w = mousePointerWhite[line]; - - for (column = 0; column < FFMIN(16, (x_off + width) - x); column++) { - apply_masks(cursor, ~(masks*(bm_b&1)), masks*(bm_w&1), - image->bits_per_pixel); - cursor += bytes_per_pixel; - bm_b >>= 1; - bm_w >>= 1; + x = xcim->x - xcim->xhot; + y = xcim->y - xcim->yhot; + + to_line = FFMIN((y + xcim->height), (height + y_off)); + to_column = FFMIN((x + xcim->width), (width + x_off)); + + for (line = FFMAX(y, y_off); line < to_line; line++) { + for (column = FFMAX(x, x_off); column < to_column; column++) { + xcim_addr = (line - y) * xcim->width + column - x; + + if ((unsigned char)(xcim->pixels[xcim_addr] >> 24) != 0) { // skip fully transparent pixel + image_addr = ((line - y_off) * width + column - x_off) * 4; + + image->data[image_addr] = (unsigned char)(xcim->pixels[xcim_addr] >> 0); + image->data[image_addr+1] = (unsigned char)(xcim->pixels[xcim_addr] >> 8); + image->data[image_addr+2] = (unsigned char)(xcim->pixels[xcim_addr] >> 16); } - im_data += image->bytes_per_line; } } + + XFree(xcim); + xcim = NULL; } @@ -469,9 +413,7 @@ x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt) } { - int pointer_x, pointer_y; - get_pointer_coordinates(&pointer_x, &pointer_y, dpy, s1); - paint_mouse_pointer(image, s, pointer_x, pointer_y); + paint_mouse_pointer(image, s); } -- cgit v1.2.3