1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
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);
}
}
};
|