const build_options = @import("build_options"); const c = @import("c.zig").c; const std = @import("std"); extern fn XDestroyImage(ximage: *c.XImage) c_int; const ShmInfo = if (build_options.use_xshm) c.XShmSegmentInfo else struct {}; pub const Screenshot = struct { image: *c.XImage, shm: ShmInfo = .{}, pub fn capture(display: *c.Display, window: c.Window) !Screenshot { var attrs: c.XWindowAttributes = undefined; _ = c.XGetWindowAttributes(display, window, &attrs); if (build_options.use_xshm) { const screen = c.XDefaultScreen(display); var ss = Screenshot{ .image = undefined, .shm = undefined }; ss.image = c.XShmCreateImage( display, c.XDefaultVisual(display, @intCast(screen)), @intCast(c.XDefaultDepthOfScreen(c.XScreenOfDisplay(display, @intCast(screen)))), c.ZPixmap, null, &ss.shm, @intCast(attrs.width), @intCast(attrs.height), ) orelse return error.ScreenshotFailed; ss.shm.shmid = c.shmget(c.IPC_PRIVATE, @intCast(ss.image.*.bytes_per_line * ss.image.*.height), c.IPC_CREAT | 0o777); ss.shm.shmaddr = @ptrCast(c.shmat(ss.shm.shmid, null, 0)); ss.image.*.data = @ptrCast(ss.shm.shmaddr); ss.shm.readOnly = c.False; _ = c.XShmAttach(display, &ss.shm); _ = c.XShmGetImage(display, window, ss.image, 0, 0, c.AllPlanes); return ss; } else { const image = c.XGetImage(display, window, 0, 0, @intCast(attrs.width), @intCast(attrs.height), c.AllPlanes, c.ZPixmap); if (image == null) return error.ScreenshotFailed; return .{ .image = image.? }; } } pub fn deinit(self: *Screenshot) void { if (build_options.use_xshm) { _ = XDestroyImage(self.image); _ = c.shmdt(self.shm.shmaddr); _ = c.shmctl(self.shm.shmid, c.IPC_RMID, null); } else { _ = XDestroyImage(self.image); } } };