lib/windowing/src/surface.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const sys = @import("sys");
3
4 pub const Kind = enum {
5 wayland,
6 x11,
7 cocoa,
8 unsupported,
9 };
10
11 pub const Extent = struct {
12 width: u32,
13 height: u32,
14 framebuffer_width: u32,
15 framebuffer_height: u32,
16 scale_x: f32,
17 scale_y: f32,
18
19 pub fn pixelCount(self: Extent) ?usize {
20 return std.math.mul(usize, @as(usize, self.framebuffer_width), @as(usize, self.framebuffer_height)) catch null;
21 }
22 };
23
24 pub const Surface = union(Kind) {
25 wayland: Wayland,
26 x11: X11,
27 cocoa: Cocoa,
28 unsupported: Unsupported,
29
30 pub fn kind(self: Surface) Kind {
31 return switch (self) {
32 .wayland => .wayland,
33 .x11 => .x11,
34 .cocoa => .cocoa,
35 .unsupported => .unsupported,
36 };
37 }
38
39 pub fn extent(self: Surface) Extent {
40 return switch (self) {
41 .wayland => |value| value.extent,
42 .x11 => |value| value.extent,
43 .cocoa => |value| value.extent,
44 .unsupported => |value| value.extent,
45 };
46 }
47 };
48
49 pub const Wayland = struct {
50 descriptor: sys.fd.Descriptor,
51 surface_id: u32,
52 extent: Extent,
53 };
54
55 pub const X11 = struct {
56 connection: *sys.x11.Connection,
57 display: sys.x11.display.Target,
58 window: u32,
59 screen: u32,
60 root: u32,
61 visual: u32,
62 depth: u8,
63 red_mask: u32,
64 green_mask: u32,
65 blue_mask: u32,
66 extent: Extent,
67 };
68
69 pub const Cocoa = struct {
70 app: sys.apple.objc.Id,
71 window: sys.apple.objc.Id,
72 layer: sys.apple.objc.Id,
73 extent: Extent,
74 };
75
76 pub const Unsupported = struct {
77 extent: Extent,
78 };
79
80 pub fn extentFromSizes(
81 width: u32,
82 height: u32,
83 framebuffer_width: u32,
84 framebuffer_height: u32,
85 scale_x: f32,
86 scale_y: f32,
87 ) Extent {
88 return .{
89 .width = width,
90 .height = height,
91 .framebuffer_width = framebuffer_width,
92 .framebuffer_height = framebuffer_height,
93 .scale_x = usableScale(scale_x),
94 .scale_y = usableScale(scale_y),
95 };
96 }
97
98 fn usableScale(value: f32) f32 {
99 if (!std.math.isFinite(value) or value <= 0) return 1;
100 return value;
101 }
102
103 test "native surface extents sanitize scale and count framebuffer pixels" {
104 const extent = extentFromSizes(320, 200, 640, 400, 2, -1);
105 try std.testing.expectEqual(@as(u32, 320), extent.width);
106 try std.testing.expectEqual(@as(u32, 400), extent.framebuffer_height);
107 try std.testing.expectEqual(@as(f32, 2), extent.scale_x);
108 try std.testing.expectEqual(@as(f32, 1), extent.scale_y);
109 try std.testing.expectEqual(@as(usize, 640 * 400), extent.pixelCount().?);
110 }
111
112 test "native surface union exposes kind and extent" {
113 const extent = extentFromSizes(10, 20, 10, 20, 1, 1);
114 const native = Surface{ .unsupported = .{ .extent = extent } };
115 try std.testing.expectEqual(Kind.unsupported, native.kind());
116 try std.testing.expectEqual(extent, native.extent());
117 }