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)) {
178 "Image r 0x%.6lx g 0x%.6lx b 0x%.6lx and depth %i\n",
182 image->bits_per_pixel);
186 switch (image->bits_per_pixel) {
191 if (image->red_mask == 0xf800 &&
192 image->green_mask == 0x07e0 &&
193 image->blue_mask == 0x001f) {
195 }
else if (image->red_mask == 0x7c00 &&
196 image->green_mask == 0x03e0 &&
197 image->blue_mask == 0x001f) {
202 if (image->red_mask == 0xff0000 &&
203 image->green_mask == 0x00ff00 &&
204 image->blue_mask == 0x0000ff) {
206 }
else if (image->red_mask == 0x0000ff &&
207 image->green_mask == 0x00ff00 &&
208 image->blue_mask == 0xff0000) {
213 if (image->red_mask == 0xff0000 &&
214 image->green_mask == 0x00ff00 &&
215 image->blue_mask == 0x0000ff ) {
222 "XImages with RGB mask 0x%.6lx 0x%.6lx 0x%.6lx and depth %i "
223 "are currently not supported.\n",
227 image->bits_per_pixel);
251 int x_off = 0, y_off = 0,
ret = 0,
screen, use_shm = 0;
261 offset = strchr(dpyname,
'+');
263 sscanf(offset,
"%d,%d", &x_off, &y_off);
264 if (strstr(offset,
"nomouse")) {
266 "'nomouse' specification in argument is deprecated: "
267 "use 'draw_mouse' option with value 0 instead\n");
274 "device: %s -> display: %s x: %d y: %d width: %d height: %d\n",
277 dpy = XOpenDisplay(dpyname);
292 screen = DefaultScreen(dpy);
295 int screen_w, screen_h;
298 screen_w = DisplayWidth(dpy,
screen);
299 screen_h = DisplayHeight(dpy,
screen);
300 XQueryPointer(dpy, RootWindow(dpy,
screen), &w, &w, &x_off, &y_off,
302 x_off -= x11grab->
width / 2;
303 y_off -= x11grab->
height / 2;
307 "followmouse is enabled, resetting grabbing region to x: %d y: %d\n",
312 use_shm = XShmQueryExtension(dpy);
314 "shared memory extension %sfound\n", use_shm ?
"" :
"not ");
317 if (use_shm &&
setup_shm(s1, dpy, &image) < 0) {
323 image = XGetImage(dpy, RootWindow(dpy,
screen),
333 x11grab->
x_off = x_off;
334 x11grab->
y_off = y_off;
335 x11grab->
image = image;
343 color_map = DefaultColormap(dpy,
screen);
344 for (i = 0; i < 256; ++i)
346 XQueryColors(dpy, color_map, color, 256);
347 for (i = 0; i < 256; ++i)
348 x11grab->
palette[i] = (color[i].red & 0xFF00) << 8 |
349 (color[i].green & 0xFF00) |
350 (color[i].blue & 0xFF00) >> 8;
377 int x_off = s->
x_off;
378 int y_off = s->
y_off;
381 Display *dpy = s->
dpy;
382 XFixesCursorImage *xcim;
385 int to_line, to_column;
386 int pixstride = image->bits_per_pixel >> 3;
393 XSetWindowAttributes attr;
394 Bool pointer_on_screen;
398 root = DefaultRootWindow(dpy);
399 pointer_on_screen = XQueryPointer(dpy, root, &w, &w, &_, &_, &_, &_, &_);
400 if (!pointer_on_screen)
404 if (image->bits_per_pixel != 24 && image->bits_per_pixel != 32)
408 s->
c = XCreateFontCursor(dpy, XC_left_ptr);
410 XChangeWindowAttributes(dpy, root, CWCursor, &attr);
412 xcim = XFixesGetCursorImage(dpy);
415 "XFixes extension not available, impossible to draw cursor\n");
420 x = xcim->x - xcim->xhot;
421 y = xcim->y - xcim->yhot;
423 to_line =
FFMIN((y + xcim->height), (height + y_off));
424 to_column =
FFMIN((x + xcim->width), (width + x_off));
426 for (line =
FFMAX(y, y_off); line < to_line; line++) {
427 for (column =
FFMAX(x, x_off); column < to_column; column++) {
428 int xcim_addr = (line -
y) * xcim->width + column - x;
429 int image_addr = ((line - y_off) * width + column - x_off) * pixstride;
430 int r = (
uint8_t)(xcim->pixels[xcim_addr] >> 0);
431 int g = (
uint8_t)(xcim->pixels[xcim_addr] >> 8);
432 int b = (
uint8_t)(xcim->pixels[xcim_addr] >> 16);
433 int a = (
uint8_t)(xcim->pixels[xcim_addr] >> 24);
436 pix[image_addr + 0] =
r;
437 pix[image_addr + 1] =
g;
438 pix[image_addr + 2] =
b;
441 pix[image_addr + 0] = r + (pix[image_addr + 0] * (255 -
a) + 255 / 2) / 255;
442 pix[image_addr + 1] = g + (pix[image_addr + 1] * (255 -
a) + 255 / 2) / 255;
443 pix[image_addr + 2] = b + (pix[image_addr + 2] * (255 -
a) + 255 / 2) / 255;
462 static int xget_zpixmap(Display *dpy, Drawable d, XImage *image,
int x,
int y)
472 GetReq(GetImage, req);
478 req->width = image->width;
479 req->height = image->height;
480 req->planeMask = (
unsigned int)AllPlanes;
481 req->format = ZPixmap;
483 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.length) {
489 nbytes = (long)rep.length << 2;
490 _XReadPad(dpy, image->data, nbytes);
507 Display *dpy = s->
dpy;
508 XImage *image = s->
image;
509 int x_off = s->
x_off;
510 int y_off = s->
y_off;
514 int64_t curtime, delay;
529 ts.tv_sec = delay / 1000000;
530 ts.tv_nsec = (delay % 1000000) * 1000;
531 nanosleep(&ts, NULL);
535 pkt->
data = image->data;
549 screen = DefaultScreen(dpy);
550 root = RootWindow(dpy, screen);
552 int screen_w, screen_h;
553 int pointer_x, pointer_y,
_;
556 screen_w = DisplayWidth(dpy, screen);
557 screen_h = DisplayHeight(dpy, screen);
558 XQueryPointer(dpy, root, &w, &w, &pointer_x, &pointer_y, &_, &_, &_);
559 if (follow_mouse == -1) {
561 x_off += pointer_x - s->
width / 2 - x_off;
562 y_off += pointer_y - s->
height / 2 - y_off;
566 if (pointer_x > x_off + s->
width - follow_mouse)
567 x_off += pointer_x - (x_off + s->
width - follow_mouse);
568 else if (pointer_x < x_off + follow_mouse)
569 x_off -= (x_off + follow_mouse) - pointer_x;
570 if (pointer_y > y_off + s->
height - follow_mouse)
571 y_off += pointer_y - (y_off + s->
height - follow_mouse);
572 else if (pointer_y < y_off + follow_mouse)
573 y_off -= (y_off + follow_mouse) - pointer_y;
587 XEvent evt = { .type = NoEventMask };
589 while (XCheckMaskEvent(dpy, ExposureMask | StructureNotifyMask,
600 if (!XShmGetImage(dpy, root, image, x_off, y_off, AllPlanes))
626 shmdt(x11grab->
shminfo.shmaddr);
627 shmctl(x11grab->
shminfo.shmid, IPC_RMID, NULL);
631 if (x11grab->
image) {
632 XDestroyImage(x11grab->
image);
633 x11grab->
image = NULL;
640 XCloseDisplay(x11grab->
dpy);
644 #define OFFSET(x) offsetof(X11GrabContext, x)
645 #define DEC AV_OPT_FLAG_DECODING_PARAM
649 {
"follow_mouse",
"move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region",
651 {
"centered",
"keep the mouse pointer at the center of grabbing region when following",
678 .priv_class = &x11_class,