44 #include <X11/cursorfont.h>
47 #include <X11/Xlibint.h>
48 #include <X11/Xproto.h>
49 #include <X11/Xutil.h>
51 #include <X11/extensions/shape.h>
52 #include <X11/extensions/Xfixes.h>
53 #include <X11/extensions/XShm.h>
91 #define REGION_WIN_BORDER 3
100 Display *dpy = s->
dpy;
102 int screen = DefaultScreen(dpy);
103 GC gc = XCreateGC(dpy, win, 0, 0);
105 XSetForeground(dpy, gc, WhitePixel(dpy, screen));
106 XSetBackground(dpy, gc, BlackPixel(dpy, screen));
108 XDrawRectangle(dpy, win, gc, 1, 1,
121 Display *dpy = s->
dpy;
123 XSetWindowAttributes attribs = { .override_redirect = True };
124 int screen = DefaultScreen(dpy);
126 s->
region_win = XCreateWindow(dpy, RootWindow(dpy, screen),
132 InputOutput, CopyFromParent,
133 CWOverrideRedirect, &attribs);
136 rect.width = s->
width;
140 &rect, 1, ShapeSubtract, 0);
142 XSelectInput(dpy, s->
region_win, ExposureMask | StructureNotifyMask);
149 int scr = XDefaultScreen(dpy);
150 XImage *
img = XShmCreateImage(dpy, DefaultVisual(dpy, scr),
151 DefaultDepth(dpy, scr), ZPixmap,
NULL,
154 g->
shminfo.shmid = shmget(IPC_PRIVATE, img->bytes_per_line * img->height,
165 if (!XShmAttach(dpy, &g->
shminfo)) {
179 if (XFixesQueryExtension(dpy, &ev_ret, &ev_err)) {
180 Window root = RootWindow(dpy, screen);
181 XFixesSelectCursorInput(dpy, root, XFixesDisplayCursorNotifyMask);
191 "Image r 0x%.6lx g 0x%.6lx b 0x%.6lx and depth %i\n",
195 image->bits_per_pixel);
199 switch (image->bits_per_pixel) {
204 if (image->red_mask == 0xf800 &&
205 image->green_mask == 0x07e0 &&
206 image->blue_mask == 0x001f) {
208 }
else if (image->red_mask == 0x7c00 &&
209 image->green_mask == 0x03e0 &&
210 image->blue_mask == 0x001f) {
215 if (image->red_mask == 0xff0000 &&
216 image->green_mask == 0x00ff00 &&
217 image->blue_mask == 0x0000ff) {
219 }
else if (image->red_mask == 0x0000ff &&
220 image->green_mask == 0x00ff00 &&
221 image->blue_mask == 0xff0000) {
226 if (image->red_mask == 0xff0000 &&
227 image->green_mask == 0x00ff00 &&
228 image->blue_mask == 0x0000ff ) {
235 "XImages with RGB mask 0x%.6lx 0x%.6lx 0x%.6lx and depth %i "
236 "are currently not supported.\n",
240 image->bits_per_pixel);
264 int x_off = 0, y_off = 0,
ret = 0,
screen, use_shm = 0;
274 offset = strchr(dpyname,
'+');
276 sscanf(offset,
"%d,%d", &x_off, &y_off);
277 if (strstr(offset,
"nomouse")) {
279 "'nomouse' specification in argument is deprecated: "
280 "use 'draw_mouse' option with value 0 instead\n");
287 "device: %s -> display: %s x: %d y: %d width: %d height: %d\n",
290 dpy = XOpenDisplay(dpyname);
305 screen = DefaultScreen(dpy);
308 int screen_w, screen_h;
311 screen_w = DisplayWidth(dpy,
screen);
312 screen_h = DisplayHeight(dpy,
screen);
313 XQueryPointer(dpy, RootWindow(dpy,
screen), &w, &w, &x_off, &y_off,
315 x_off -= x11grab->
width / 2;
316 y_off -= x11grab->
height / 2;
320 "followmouse is enabled, resetting grabbing region to x: %d y: %d\n",
325 use_shm = XShmQueryExtension(dpy);
327 "shared memory extension %sfound\n", use_shm ?
"" :
"not ");
330 if (use_shm &&
setup_shm(s1, dpy, &image) < 0) {
336 image = XGetImage(dpy, RootWindow(dpy,
screen),
344 "XFixes not available, cannot draw the mouse cursor\n");
352 x11grab->
x_off = x_off;
353 x11grab->
y_off = y_off;
354 x11grab->
image = image;
362 color_map = DefaultColormap(dpy,
screen);
363 for (i = 0; i < 256; ++i)
365 XQueryColors(dpy, color_map, color, 256);
366 for (i = 0; i < 256; ++i)
367 x11grab->
palette[i] = (color[i].red & 0xFF00) << 8 |
368 (color[i].green & 0xFF00) |
369 (color[i].blue & 0xFF00) >> 8;
396 int x_off = s->
x_off;
397 int y_off = s->
y_off;
400 Display *dpy = s->
dpy;
401 XFixesCursorImage *xcim;
404 int to_line, to_column;
405 int pixstride = image->bits_per_pixel >> 3;
412 XSetWindowAttributes attr;
415 if (image->bits_per_pixel != 24 && image->bits_per_pixel != 32)
419 s->
c = XCreateFontCursor(dpy, XC_left_ptr);
420 root = DefaultRootWindow(dpy);
422 XChangeWindowAttributes(dpy, root, CWCursor, &attr);
424 xcim = XFixesGetCursorImage(dpy);
427 "XFixesGetCursorImage failed\n");
431 x = xcim->x - xcim->xhot;
432 y = xcim->y - xcim->yhot;
434 to_line =
FFMIN((y + xcim->height), (height + y_off));
435 to_column =
FFMIN((x + xcim->width), (width + x_off));
437 for (line =
FFMAX(y, y_off); line < to_line; line++) {
438 for (column =
FFMAX(x, x_off); column < to_column; column++) {
439 int xcim_addr = (line -
y) * xcim->width + column - x;
440 int image_addr = ((line - y_off) * width + column - x_off) * pixstride;
441 int r = (
uint8_t)(xcim->pixels[xcim_addr] >> 0);
442 int g = (
uint8_t)(xcim->pixels[xcim_addr] >> 8);
443 int b = (
uint8_t)(xcim->pixels[xcim_addr] >> 16);
444 int a = (
uint8_t)(xcim->pixels[xcim_addr] >> 24);
447 pix[image_addr + 0] =
r;
448 pix[image_addr + 1] =
g;
449 pix[image_addr + 2] =
b;
452 pix[image_addr + 0] = r + (pix[image_addr + 0] * (255 -
a) + 255 / 2) / 255;
453 pix[image_addr + 1] = g + (pix[image_addr + 1] * (255 -
a) + 255 / 2) / 255;
454 pix[image_addr + 2] = b + (pix[image_addr + 2] * (255 -
a) + 255 / 2) / 255;
473 static int xget_zpixmap(Display *dpy, Drawable d, XImage *image,
int x,
int y)
483 GetReq(GetImage, req);
489 req->width = image->width;
490 req->height = image->height;
491 req->planeMask = (
unsigned int)AllPlanes;
492 req->format = ZPixmap;
494 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.length) {
500 nbytes = (long)rep.length << 2;
501 _XReadPad(dpy, image->data, nbytes);
518 Display *dpy = s->
dpy;
519 XImage *image = s->
image;
520 int x_off = s->
x_off;
521 int y_off = s->
y_off;
523 int screen, pointer_x, pointer_y,
_, same_screen = 1;
525 int64_t curtime, delay;
540 ts.tv_sec = delay / 1000000;
541 ts.tv_nsec = (delay % 1000000) * 1000;
542 nanosleep(&ts,
NULL);
546 pkt->
data = image->data;
560 screen = DefaultScreen(dpy);
561 root = RootWindow(dpy, screen);
564 same_screen = XQueryPointer(dpy, root, &w, &w,
565 &pointer_x, &pointer_y, &_, &_, &_);
567 if (follow_mouse && same_screen) {
568 int screen_w, screen_h;
570 screen_w = DisplayWidth(dpy, screen);
571 screen_h = DisplayHeight(dpy, screen);
572 if (follow_mouse == -1) {
574 x_off += pointer_x - s->
width / 2 - x_off;
575 y_off += pointer_y - s->
height / 2 - y_off;
579 if (pointer_x > x_off + s->
width - follow_mouse)
580 x_off += pointer_x - (x_off + s->
width - follow_mouse);
581 else if (pointer_x < x_off + follow_mouse)
582 x_off -= (x_off + follow_mouse) - pointer_x;
583 if (pointer_y > y_off + s->
height - follow_mouse)
584 y_off += pointer_y - (y_off + s->
height - follow_mouse);
585 else if (pointer_y < y_off + follow_mouse)
586 y_off -= (y_off + follow_mouse) - pointer_y;
600 XEvent evt = { .type = NoEventMask };
602 while (XCheckMaskEvent(dpy, ExposureMask | StructureNotifyMask,
613 if (!XShmGetImage(dpy, root, image, x_off, y_off, AllPlanes))
639 shmdt(x11grab->
shminfo.shmaddr);
644 if (x11grab->
image) {
645 XDestroyImage(x11grab->
image);
653 XCloseDisplay(x11grab->
dpy);
657 #define OFFSET(x) offsetof(X11GrabContext, x)
658 #define DEC AV_OPT_FLAG_DECODING_PARAM
664 {
"follow_mouse",
"move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region",
666 {
"centered",
"keep the mouse pointer at the center of grabbing region when following",
693 .priv_class = &x11_class,