const std = @import("std"); const wayland = @import("../root.zig"); const wl = wayland.wl; const Self = @This(); pub const Requests = union(enum) { release: struct {}, }; pub const Events = wayland.EventSet(Self, .{ geometry, mode, done, scale, name, description, }); pub const Subpixel = enum(u32) { unkown = 0, none = 1, orizontal_rgb = 2, orizontal_bgr = 3, vertical_rgb = 4, vertical_bgr = 5, }; pub const Transform = enum(u32) { normal = 0, normal_90 = 1, normal_180 = 2, normal_270 = 3, flipped = 4, flipped_90 = 5, flipped_180 = 6, flipped_270 = 7, }; pub const Geometry = struct { x: u32, y: u32, physical_width: u32, physical_height: u32, subpixel: Subpixel, make: []const u8, model: []const u8, transform: Transform, }; pub const Mode = struct { pub const Kind = enum(u32) { current = 1, preferred = 2, }; kind: Kind, width: u32, height: u32, refresh: u32, }; pub const Info = struct { geometry: Geometry, mode: Mode, scale: u32, name: []const u8, description: []const u8, }; var outputs: std.ArrayListUnmanaged(*Self) = .empty; staging: Info = undefined, info: ?Info = null, interface: wayland.Object, pub fn init( self: *Self, allocator: std.mem.Allocator, display: *wl.Display, ) !void { self.* = .{ .interface = wayland.Object.from_self(self) }; try display.registry.add_object(allocator, &self.interface); } pub fn deinit(self: *Self, display: *wl.Display) !void { display.request(self, .{ .release = void{} }); } pub const handler: wl.Registry.GlobalHandler = .{ .interface = "wl_output", .version = 4, .handler = register, }; pub fn register(ctx: *wayland.Context) ?wayland.Object { const output = ctx.allocator.create(Self) catch return null; output.init(ctx.allocator, ctx.display) catch return null; outputs.append(ctx.allocator, output) catch return null; return output.interface; } fn geometry( self: *Self, ctx: *wayland.Context, x: u32, y: u32, physical_width: u32, physical_height: u32, subpixel: Subpixel, make: []const u8, model: []const u8, transform: Transform, ) void { _ = ctx; self.staging.geometry = .{ .x = x, .y = y, .physical_width = physical_width, .physical_height = physical_height, .subpixel = subpixel, .make = make, .model = model, .transform = transform, }; } fn mode( self: *Self, ctx: *wayland.Context, flags: Mode.Kind, width: u32, height: u32, refresh: u32, ) void { _ = ctx; self.staging.mode = .{ .kind = flags, .width = width, .height = height, .refresh = refresh, }; } fn done(self: *Self, ctx: *wayland.Context) void { if (self.info) |info| { ctx.allocator.free(info.name); ctx.allocator.free(info.description); } self.info = self.staging; } fn scale(self: *Self, ctx: *wayland.Context, factor: u32) void { _ = ctx; self.staging.scale = factor; } fn name(self: *Self, ctx: *wayland.Context, n: []const u8) !void { self.staging.name = try ctx.allocator.alloc(u8, n.len); @memcpy(@constCast(self.staging.name), n); } fn description(self: *Self, ctx: *wayland.Context, d: []const u8) !void { self.staging.description = try ctx.allocator.alloc(u8, d.len); @memcpy(@constCast(self.staging.description), d); } pub fn get(index: usize) *Self { return &outputs.items[index]; }