stevee

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

hello.zig (3461B)


      1 const std = @import("std");
      2 const mem = std.mem;
      3 const posix = std.posix;
      4 
      5 const wayland = @import("wayland");
      6 const wl = wayland.client.wl;
      7 const xdg = wayland.client.xdg;
      8 
      9 const Context = struct {
     10     shm: ?*wl.Shm,
     11     compositor: ?*wl.Compositor,
     12     wm_base: ?*xdg.WmBase,
     13 };
     14 
     15 pub fn main() anyerror!void {
     16     const display = try wl.Display.connect(null);
     17     const registry = try display.getRegistry();
     18 
     19     var context = Context{
     20         .shm = null,
     21         .compositor = null,
     22         .wm_base = null,
     23     };
     24 
     25     registry.setListener(*Context, registryListener, &context);
     26     if (display.roundtrip() != .SUCCESS) return error.RoundtripFailed;
     27 
     28     const shm = context.shm orelse return error.NoWlShm;
     29     const compositor = context.compositor orelse return error.NoWlCompositor;
     30     const wm_base = context.wm_base orelse return error.NoXdgWmBase;
     31 
     32     const buffer = blk: {
     33         const width = 128;
     34         const height = 128;
     35         const stride = width * 4;
     36         const size = stride * height;
     37 
     38         const fd = try posix.memfd_create("hello-zig-wayland", 0);
     39         try posix.ftruncate(fd, size);
     40         const data = try posix.mmap(
     41             null,
     42             size,
     43             posix.PROT.READ | posix.PROT.WRITE,
     44             .{ .TYPE = .SHARED },
     45             fd,
     46             0,
     47         );
     48         @memcpy(data, @embedFile("cat.bgra"));
     49 
     50         const pool = try shm.createPool(fd, size);
     51         defer pool.destroy();
     52 
     53         break :blk try pool.createBuffer(0, width, height, stride, wl.Shm.Format.argb8888);
     54     };
     55     defer buffer.destroy();
     56 
     57     const surface = try compositor.createSurface();
     58     defer surface.destroy();
     59     const xdg_surface = try wm_base.getXdgSurface(surface);
     60     defer xdg_surface.destroy();
     61     const xdg_toplevel = try xdg_surface.getToplevel();
     62     defer xdg_toplevel.destroy();
     63 
     64     var running = true;
     65 
     66     xdg_surface.setListener(*wl.Surface, xdgSurfaceListener, surface);
     67     xdg_toplevel.setListener(*bool, xdgToplevelListener, &running);
     68 
     69     surface.commit();
     70     if (display.roundtrip() != .SUCCESS) return error.RoundtripFailed;
     71 
     72     surface.attach(buffer, 0, 0);
     73     surface.commit();
     74 
     75     while (running) {
     76         if (display.dispatch() != .SUCCESS) return error.DispatchFailed;
     77     }
     78 }
     79 
     80 fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, context: *Context) void {
     81     switch (event) {
     82         .global => |global| {
     83             if (mem.orderZ(u8, global.interface, wl.Compositor.interface.name) == .eq) {
     84                 context.compositor = registry.bind(global.name, wl.Compositor, 1) catch return;
     85             } else if (mem.orderZ(u8, global.interface, wl.Shm.interface.name) == .eq) {
     86                 context.shm = registry.bind(global.name, wl.Shm, 1) catch return;
     87             } else if (mem.orderZ(u8, global.interface, xdg.WmBase.interface.name) == .eq) {
     88                 context.wm_base = registry.bind(global.name, xdg.WmBase, 1) catch return;
     89             }
     90         },
     91         .global_remove => {},
     92     }
     93 }
     94 
     95 fn xdgSurfaceListener(xdg_surface: *xdg.Surface, event: xdg.Surface.Event, surface: *wl.Surface) void {
     96     switch (event) {
     97         .configure => |configure| {
     98             xdg_surface.ackConfigure(configure.serial);
     99             surface.commit();
    100         },
    101     }
    102 }
    103 
    104 fn xdgToplevelListener(_: *xdg.Toplevel, event: xdg.Toplevel.Event, running: *bool) void {
    105     switch (event) {
    106         .configure => {},
    107         .close => running.* = false,
    108     }
    109 }