stevee

My wayland statusbar
git clone git://gtms.dev/stevee
Log | Files | Refs | README | LICENSE

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 }