aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/screenshot.h96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/screenshot.h b/src/screenshot.h
new file mode 100644
index 0000000..96cee42
--- /dev/null
+++ b/src/screenshot.h
@@ -0,0 +1,96 @@
+#ifndef SCREENSHOT_H
+#define SCREENSHOT_H
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#ifdef USE_XSHM
+#include <X11/extensions/XShm.h>
+#endif
+
+typedef struct {
+ XImage *image;
+#ifdef USE_XSHM
+ XShmSegmentInfo *shminfo;
+#endif
+} Screenshot;
+
+Screenshot *new_screenshot(Display *display, Window window);
+void destroy_screenshot(Display *display, Screenshot *screenshot);
+
+// TODO(20260315T135543): maybe add error checking
+
+#ifdef SCREENSHOT_IMPL
+
+#include <stdlib.h>
+
+#ifdef USE_XSHM
+#include <sys/shm.h>
+#endif
+
+#define UNUSED(x) (void)(x)
+
+Screenshot *new_screenshot(Display *d, Window w) {
+ Screenshot *result = malloc(sizeof(Screenshot));
+
+ XWindowAttributes attributes;
+ XGetWindowAttributes(d, w, &attributes);
+
+#ifdef USE_XSHM
+ result->shminfo = malloc(sizeof(XShmSegmentInfo));
+
+ int screen = DefaultScreen(d);
+
+ result->image = XShmCreateImage(
+ d,
+ DefaultVisual(d, screen),
+ DefaultDepthOfScreen(ScreenOfDisplay(d, screen)),
+ ZPixmap,
+ NULL,
+ result->shminfo,
+ attributes.width,
+ attributes.height
+ );
+
+ result->shminfo->shmid = shmget(
+ IPC_PRIVATE,
+ result->image->bytes_per_line * result->image->height,
+ IPC_CREAT | 0777
+ );
+
+ result->shminfo->shmaddr = (char*)shmat(result->shminfo->shmid, 0, 0);
+ result->image->data = result->shminfo->shmaddr;
+ result->shminfo->readOnly = False;
+
+ XShmAttach(d, result->shminfo);
+
+ XShmGetImage(d, w, result->image, 0, 0, AllPlanes);
+#else // USE_XSHM
+ result->image = XGetImage(d, w, 0, 0,
+ attributes.width, attributes.height,
+ AllPlanes, ZPixmap);
+#endif // USE_XSHM
+
+ return result;
+}
+
+void destroy_screenshot(Display *d, Screenshot *s) {
+ if (!s) return;
+
+#ifdef USE_XSHM
+ XSync(d, False);
+ XShmDetach(d, s->shminfo);
+ XDestroyImage(s->image);
+ shmdt(s->shminfo->shmaddr);
+ shmctl(s->shminfo->shmid, IPC_RMID, 0);
+ free(s->shminfo);
+#else
+ UNUSED(d);
+ XDestroyImage(s->image);
+#endif
+ free(s);
+}
+
+#endif // SCREENSHOT_IMPL
+
+#endif // SCREENSHOT_H