Wayland.zig (5093B)
1 const std = @import("std"); 2 3 const wl = @import("wayland").client.wl; 4 const wp = @import("wayland").client.wp; 5 const zwlr = @import("wayland").client.zwlr; 6 const zriver = @import("wayland").client.zriver; 7 8 const Bar = @import("Bar.zig"); 9 const Event = @import("Loop.zig").Event; 10 const Input = @import("Input.zig"); 11 const Monitor = @import("Monitor.zig"); 12 const utils = @import("utils.zig"); 13 const Wayland = @This(); 14 15 const state = &@import("root").state; 16 17 display: *wl.Display, 18 fd: std.posix.fd_t, 19 20 compositor: ?*wl.Compositor = null, 21 subcompositor: ?*wl.Subcompositor = null, 22 shm: ?*wl.Shm = null, 23 single_pixel_buffer_manager: ?*wp.SinglePixelBufferManagerV1 = null, 24 viewporter: ?*wp.Viewporter = null, 25 layer_shell: ?*zwlr.LayerShellV1 = null, 26 status_manager: ?*zriver.StatusManagerV1 = null, 27 control: ?*zriver.ControlV1 = null, 28 29 monitors: std.ArrayList(*Monitor), 30 inputs: std.ArrayList(*Input), 31 32 pub fn init() !Wayland { 33 const display = try wl.Display.connect(null); 34 35 return Wayland{ 36 .display = display, 37 .fd = @intCast(display.getFd()), 38 .monitors = std.ArrayList(*Monitor).init(state.gpa), 39 .inputs = std.ArrayList(*Input).init(state.gpa), 40 }; 41 } 42 43 pub fn deinit(self: *Wayland) void { 44 for (self.monitors.items) |monitor| monitor.destroy(); 45 for (self.inputs.items) |input| input.destroy(); 46 47 self.monitors.deinit(); 48 self.inputs.deinit(); 49 50 if (self.compositor) |global| global.destroy(); 51 if (self.subcompositor) |global| global.destroy(); 52 if (self.shm) |global| global.destroy(); 53 if (self.viewporter) |global| global.destroy(); 54 if (self.single_pixel_buffer_manager) |global| global.destroy(); 55 if (self.layer_shell) |global| global.destroy(); 56 if (self.status_manager) |global| global.destroy(); 57 if (self.control) |global| global.destroy(); 58 59 self.display.disconnect(); 60 } 61 62 pub fn registerGlobals(self: *Wayland) !void { 63 const registry = try self.display.getRegistry(); 64 defer registry.destroy(); 65 66 registry.setListener(*Wayland, registryListener, self); 67 const errno = self.display.roundtrip(); 68 if (errno != .SUCCESS) return error.RoundtripFailed; 69 } 70 71 pub fn findBar(self: *Wayland, wlSurface: ?*wl.Surface) ?*Bar { 72 if (wlSurface == null) { 73 return null; 74 } 75 for (self.monitors.items) |monitor| { 76 if (monitor.bar) |bar| { 77 if (bar.background.surface == wlSurface or 78 bar.tags.surface == wlSurface or 79 bar.clock.surface == wlSurface or 80 bar.modules.surface == wlSurface) 81 { 82 return bar; 83 } 84 } 85 } 86 return null; 87 } 88 89 fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, self: *Wayland) void { 90 switch (event) { 91 .global => |g| { 92 self.bindGlobal(registry, g.name, g.interface) catch unreachable; 93 }, 94 .global_remove => |g| { 95 for (self.monitors.items, 0..) |monitor, i| { 96 if (monitor.globalName == g.name) { 97 self.monitors.swapRemove(i).destroy(); 98 break; 99 } 100 } 101 for (self.inputs.items, 0..) |input, i| { 102 if (input.globalName == g.name) { 103 self.inputs.swapRemove(i).destroy(); 104 break; 105 } 106 } 107 }, 108 } 109 } 110 111 fn bindGlobal(self: *Wayland, registry: *wl.Registry, name: u32, iface: [*:0]const u8) !void { 112 if (std.mem.orderZ(u8, iface, wl.Compositor.interface.name) == .eq) { 113 self.compositor = try registry.bind(name, wl.Compositor, 4); 114 } else if (std.mem.orderZ(u8, iface, wl.Subcompositor.interface.name) == .eq) { 115 self.subcompositor = try registry.bind(name, wl.Subcompositor, 1); 116 } else if (std.mem.orderZ(u8, iface, wl.Shm.interface.name) == .eq) { 117 self.shm = try registry.bind(name, wl.Shm, 1); 118 } else if (std.mem.orderZ(u8, iface, wp.Viewporter.interface.name) == .eq) { 119 self.viewporter = try registry.bind(name, wp.Viewporter, 1); 120 } else if (std.mem.orderZ(u8, iface, wp.SinglePixelBufferManagerV1.interface.name) == .eq) { 121 self.single_pixel_buffer_manager = try registry.bind(name, wp.SinglePixelBufferManagerV1, 1); 122 } else if (std.mem.orderZ(u8, iface, zwlr.LayerShellV1.interface.name) == .eq) { 123 self.layer_shell = try registry.bind(name, zwlr.LayerShellV1, 1); 124 } else if (std.mem.orderZ(u8, iface, zriver.StatusManagerV1.interface.name) == .eq) { 125 self.status_manager = try registry.bind(name, zriver.StatusManagerV1, 1); 126 } else if (std.mem.orderZ(u8, iface, zriver.ControlV1.interface.name) == .eq) { 127 self.control = try registry.bind(name, zriver.ControlV1, 1); 128 } else if (std.mem.orderZ(u8, iface, wl.Output.interface.name) == .eq) { 129 const monitor = try Monitor.create(registry, name); 130 try self.monitors.append(monitor); 131 } else if (std.mem.orderZ(u8, iface, wl.Seat.interface.name) == .eq) { 132 const input = try Input.create(registry, name); 133 try self.inputs.append(input); 134 } 135 }