~novakane/zelbar

46ebe1c426af25d5a6abe2e1c2328cf82762f60a — Hugo Machet 6 months ago d987148
Update to zig 0.11
M README.md => README.md +3 -3
@@ 6,10 6,10 @@ Wayland statusbar reading input from STDIN, inspired by [lemonbar].

Requirements:

-   [zig] 0.10
-   [zig] 0.11
-   wayland
-   wayland-protocols
-   [fcft] 3.0.1 (see fcft [requirements] if you want support for everything)
-   [fcft] 3.1.6 (see fcft [requirements] if you want support for everything)
-   pixman
-   pkg-config



@@ 19,7 19,7 @@ Init submodules:

Build, `e.g.`

    zig build -Drelease-safe --prefix ~/.local
    zig build -Doptimize=ReleaseSafe --prefix ~/.local

## Usage


M build.zig => build.zig +41 -48
@@ 4,7 4,7 @@ const Step = std.build.Step;
const assert = std.debug.assert;
const mem = std.mem;

const ScanProtocolsStep = @import("deps/zig-wayland/build.zig").ScanProtocolsStep;
const Scanner = @import("deps/zig-wayland/build.zig").Scanner;

/// While a zelbar release is in development, this string should contain
/// the version in development with the "-dev" suffix.  When a release is


@@ 15,19 15,19 @@ const version = "0.1.0-dev";

pub fn build(b: *Builder) !void {
    const target = b.standardTargetOptions(.{});
    const mode = b.standardReleaseOptions();
    const optimize = b.standardOptimizeOption(.{});

    const full_version = blk: {
        if (mem.endsWith(u8, version, "-dev")) {
            var ret: u8 = undefined;

            const git_describe_long = b.execAllowFail(
                &[_][]const u8{ "git", "-C", b.build_root, "describe", "--long" },
                &[_][]const u8{ "git", "-C", b.build_root.path.?, "describe", "--long" },
                &ret,
                .Inherit,
            ) catch break :blk version;

            var it = mem.split(u8, mem.trim(u8, git_describe_long, &std.ascii.spaces), "-");
            var it = mem.split(u8, mem.trim(u8, git_describe_long, &std.ascii.whitespace), "-");
            _ = it.next().?; // previous tag
            const commit_count = it.next().?;
            const commit_hash = it.next().?;


@@ 44,21 44,20 @@ pub fn build(b: *Builder) !void {
        }
    };

    const scanner = ScanProtocolsStep.create(b);
    scanner.addSystemProtocol("stable/xdg-shell/xdg-shell.xml");
    scanner.addProtocolPath("protocol/wlr-layer-shell-unstable-v1.xml");

    const exe = b.addExecutable("zelbar", "src/main.zig");
    exe.setTarget(target);
    exe.setBuildMode(mode);

    const options = b.addOptions();
    options.addOption([]const u8, "version", full_version);
    exe.addOptions("build_options", options);
    const scanner = Scanner.create(b, .{});

    exe.step.dependOn(&scanner.step);
    const wayland = b.createModule(.{ .source_file = scanner.result });
    const flags = b.createModule(.{ .source_file = .{ .path = "common/flags.zig" } });
    const pixman = b.createModule(.{ .source_file = .{ .path = "deps/zig-pixman/pixman.zig" } });
    const fcft = b.createModule(.{
        .source_file = .{ .path = "deps/zig-fcft/fcft.zig" },
        .dependencies = &.{
            .{ .name = "pixman", .module = pixman },
        },
    });

    exe.addPackagePath("flags", "common/flags.zig");
    scanner.addSystemProtocol("stable/xdg-shell/xdg-shell.xml");
    scanner.addCustomProtocol("protocol/wlr-layer-shell-unstable-v1.xml");

    scanner.generate("wl_compositor", 4);
    scanner.generate("wl_shm", 1);


@@ 66,52 65,46 @@ pub fn build(b: *Builder) !void {
    scanner.generate("wl_seat", 5);
    scanner.generate("zwlr_layer_shell_v1", 3);

    const wayland = std.build.Pkg{
        .name = "wayland",
        .source = .{ .generated = &scanner.result },
    };
    exe.addPackage(wayland);
    const exe = b.addExecutable(.{
        .name = "zelbar",
        .root_source_file = .{ .path = "src/main.zig" },
        .target = target,
        .optimize = optimize,
    });

    exe.addModule("wayland", wayland);
    exe.addModule("flags", flags);
    exe.addModule("pixman", pixman);
    exe.addModule("fcft", fcft);

    const options = b.addOptions();
    options.addOption([]const u8, "version", full_version);
    exe.addOptions("build_options", options);

    exe.linkLibC();
    exe.linkSystemLibrary("wayland-client");
    exe.linkSystemLibrary("wayland-cursor");

    const pixman = std.build.Pkg{
        .name = "pixman",
        .source = .{ .path = "deps/zig-pixman/pixman.zig" },
    };
    exe.addPackage(pixman);
    exe.linkSystemLibrary("pixman-1");

    const fcft = std.build.Pkg{
        .name = "fcft",
        .source = .{ .path = "deps/zig-fcft/fcft.zig" },
        .dependencies = &[_]std.build.Pkg{pixman},
    };
    exe.addPackage(fcft);
    exe.linkSystemLibrary("fcft");

    // TODO: remove when https://github.com/ziglang/zig/issues/131 is implemented
    scanner.addCSource(exe);

    exe.install();
    b.installArtifact(exe);
    b.installFile("doc/zelbar.1", "share/man/man1/zelbar.1");

    {
        const tests = b.addTest("src/test_main.zig");
        tests.setTarget(target);
        tests.addPackage(wayland);
        tests.addPackage(pixman);
        const tests = b.addTest(.{
            .root_source_file = .{ .path = "src/test_main.zig" },
            .target = target,
            .optimize = optimize,
        });
        tests.addModule("wayland", wayland);
        tests.addModule("pixman", pixman);
        tests.addModule("fcft", fcft);
        tests.linkSystemLibrary("pixman-1");
        tests.addPackage(fcft);
        tests.linkSystemLibrary("fcft");
        tests.setBuildMode(mode);
        const test_step = b.step("test", "Run all tests");
        test_step.dependOn(&tests.step);
    }

    const run_cmd = exe.run();
    run_cmd.step.dependOn(b.getInstallStep());

    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);
}

M common/flags.zig => common/flags.zig +2 -2
@@ 41,14 41,14 @@ pub fn parser(comptime Arg: type, comptime flags: []const Flag) type {
                    const field: std.builtin.Type.StructField = switch (flag.kind) {
                        .boolean => .{
                            .name = flag.name,
                            .field_type = bool,
                            .type = bool,
                            .default_value = &false,
                            .is_comptime = false,
                            .alignment = @alignOf(bool),
                        },
                        .arg => .{
                            .name = flag.name,
                            .field_type = ?[:0]const u8,
                            .type = ?[:0]const u8,
                            .default_value = &@as(?[:0]const u8, null),
                            .is_comptime = false,
                            .alignment = @alignOf(?[:0]const u8),

M deps/zig-fcft => deps/zig-fcft +1 -1
@@ 1,1 1,1 @@
Subproject commit 5493496ecf0d2c780ecba4154717dd618089c0fd
Subproject commit 1091c57e3427a0dcc9945ba02b94a37221689ff3

M deps/zig-pixman => deps/zig-pixman +1 -1
@@ 1,1 1,1 @@
Subproject commit 4a49ba13eb9ebb0c0f991de924328e3d615bf283
Subproject commit b0a961079d80059ef56565e23c5f7a8b6a911196

M deps/zig-wayland => deps/zig-wayland +1 -1
@@ 1,1 1,1 @@
Subproject commit ace6aeebcf95930ce52bb277e1899f7c050378d4
Subproject commit 7f528883e057b282b1cb51db2899f9183b2e5a3b

M src/Backend.zig => src/Backend.zig +16 -16
@@ 199,10 199,10 @@ const Seat = struct {

    fn update_pointer(seat: *Seat, x: wl.Fixed, y: wl.Fixed, serial: ?u32) void {
        const X = x.toInt();
        seat.pointer_x = if (X > 0) @intCast(u31, X) else 0;
        seat.pointer_x = if (X > 0) @intCast(X) else 0;

        const Y = y.toInt();
        seat.pointer_y = if (Y > 0) @intCast(u31, Y) else 0;
        seat.pointer_y = if (Y > 0) @intCast(Y) else 0;

        if (serial) |s| seat.last_enter_serial = s;



@@ 259,8 259,8 @@ const Seat = struct {
        seat.wl_pointer.?.setCursor(
            seat.last_enter_serial,
            seat.cursor_surface.?,
            @intCast(i32, cursor_image.hotspot_x),
            @intCast(i32, cursor_image.hotspot_y),
            @intCast(cursor_image.hotspot_x),
            @intCast(cursor_image.hotspot_y),
        );
    }
};


@@ 343,7 343,7 @@ const Surface = struct {
        const buffer = try ctx.backend.pool.next_buffer(surface.width, surface.height);
        assert(!buffer.busy);

        try ctx.bar.render(buffer, @intCast(u16, surface.width), @intCast(u16, surface.height));
        try ctx.bar.render(buffer, @intCast(surface.width), @intCast(surface.height));

        // Attach the buffer to the surface.
        surface.wl_surface.attach(buffer.wl_buffer, 0, 0);


@@ 387,8 387,8 @@ const Surface = struct {
            .configure => |ev| {
                surface.layer_surface.ackConfigure(ev.serial);

                const w = @truncate(u31, ev.width);
                const h = @truncate(u31, ev.height);
                const w: u31 = @truncate(ev.width);
                const h: u31 = @truncate(ev.height);

                if (surface.configured and surface.width == w and surface.height == h) {
                    surface.wl_surface.commit();


@@ 556,10 556,10 @@ pub const Buffer = struct {
        // Create the pixman image.
        const pixman_image = pixman.Image.createBitsNoClear(
            .a8r8g8b8,
            @intCast(c_int, width),
            @intCast(c_int, height),
            @ptrCast([*c]u32, data),
            @intCast(c_int, stride),
            @intCast(width),
            @intCast(height),
            @ptrCast(data),
            @intCast(stride),
        );
        errdefer _ = pixman_image.unref();



@@ 733,13 733,13 @@ fn registry_listener(registry: *wl.Registry, event: wl.Registry.Event, backend: 
fn registry_event(backend: *Backend, registry: *wl.Registry, event: wl.Registry.Event) !void {
    switch (event) {
        .global => |ev| {
            if (std.cstr.cmp(ev.interface, wl.Compositor.getInterface().name) == 0) {
            if (mem.orderZ(u8, ev.interface, wl.Compositor.getInterface().name) == .eq) {
                // Version 4 required for wl_surface.damage_buffer.
                if (ev.version < 4) fatal_version(wl.Compositor, ev.version, 4);
                backend.compositor = try registry.bind(ev.name, wl.Compositor, 4);
            } else if (std.cstr.cmp(ev.interface, wl.Shm.getInterface().name) == 0) {
            } else if (mem.orderZ(u8, ev.interface, wl.Shm.getInterface().name) == .eq) {
                backend.shm = try registry.bind(ev.name, wl.Shm, 1);
            } else if (std.cstr.cmp(ev.interface, wl.Output.getInterface().name) == 0) {
            } else if (mem.orderZ(u8, ev.interface, wl.Output.getInterface().name) == .eq) {
                // Version 4 required for wl_output.name.
                if (ev.version < 4) fatal_version(wl.Output, ev.version, 4);



@@ 751,7 751,7 @@ fn registry_event(backend: *Backend, registry: *wl.Registry, event: wl.Registry.

                try node.data.init(wl_output, ev.name);
                backend.outputs.prepend(node);
            } else if (std.cstr.cmp(ev.interface, wl.Seat.getInterface().name) == 0) {
            } else if (mem.orderZ(u8, ev.interface, wl.Seat.getInterface().name) == .eq) {
                // Version 5 required for wl_seat.release.
                if (ev.version < 5) fatal_version(wl.Seat, ev.version, 5);



@@ 763,7 763,7 @@ fn registry_event(backend: *Backend, registry: *wl.Registry, event: wl.Registry.

                try node.data.init(wl_seat, ev.name);
                backend.seats.prepend(node);
            } else if (std.cstr.cmp(ev.interface, zwlr.LayerShellV1.getInterface().name) == 0) {
            } else if (mem.orderZ(u8, ev.interface, zwlr.LayerShellV1.getInterface().name) == .eq) {
                // Version 3 required for layer_shell.destroy();
                if (ev.version < 3) fatal_version(zwlr.LayerShellV1, ev.version, 3);
                backend.layer_shell = try registry.bind(ev.name, zwlr.LayerShellV1, 3);

M src/Bar.zig => src/Bar.zig +2 -2
@@ 102,8 102,8 @@ pub fn render(bar: *Bar, buffer: *Buffer, surface_w: u16, h: u16) !void {
    // Render the background and the borders of the bar.
    const pix = buffer.pixman_image orelse return error.PixmanImageEmpty;
    const bg = bar.config.colors.get(.bg).?;
    try decorations.draw_rectangle(pix, @intCast(i16, x), 0, w, h, bg);
    try bar.config.border.draw(pix, @intCast(i16, x), 0, w, h);
    try decorations.draw_rectangle(pix, @intCast(x), 0, w, h, bg);
    try bar.config.border.draw(pix, @intCast(x), 0, w, h);

    // Parse and render the raw input if any.
    if (bar.input.items.len > 0) try data.expose(bar.input.items[0..], pix, x, w);

M src/Text.zig => src/Text.zig +6 -6
@@ 85,7 85,7 @@ pub fn new(ally: mem.Allocator, bytes: []const u8, font: *fcft.Font) !Text {
                }
            }

            text_w += @intCast(i32, kerns[i] + glyphs[i].advance.x);
            text_w += @intCast(kerns[i] + glyphs[i].advance.x);
        }

        return Text{


@@ 124,7 124,7 @@ pub fn render_glyphs(

    var i: usize = 0;
    while (i < glyphs.len) : (i += 1) {
        if (text.mode == .glyphs) tmp_x += @intCast(i32, text.mode.glyphs.kerns[i]);
        if (text.mode == .glyphs) tmp_x += @intCast(text.mode.glyphs.kerns[i]);

        const c = pixman.Image.createSolidFill(&fg).?;
        defer _ = c.unref();


@@ 141,8 141,8 @@ pub fn render_glyphs(
                    0,
                    0,
                    0,
                    tmp_x + @intCast(i32, glyphs[i].x),
                    y - @intCast(i32, glyphs[i].y),
                    tmp_x + @as(i32, @intCast(glyphs[i].x)),
                    y - @as(i32, @intCast(glyphs[i].y)),
                    glyphs[i].width,
                    glyphs[i].height,
                );


@@ 158,8 158,8 @@ pub fn render_glyphs(
                    0,
                    0,
                    0,
                    tmp_x + @intCast(i32, glyphs[i].x),
                    y - @intCast(i32, glyphs[i].y),
                    tmp_x + @as(i32, @intCast(glyphs[i].x)),
                    y - @as(i32, @intCast(glyphs[i].y)),
                    glyphs[i].width,
                    glyphs[i].height,
                );

M src/data.zig => src/data.zig +9 -12
@@ 108,7 108,7 @@ fn parse_input(input: []const u8, height: u16) !Entries {
        switch (token.tag) {
            .text => {
                entry.text = try Text.new(ally, token.bytes, ctx.bar.font);
                entry.width = @intCast(u16, entry.text.width);
                entry.width = @intCast(entry.text.width);

                try entries.list.append(ally, entry);



@@ 179,7 179,7 @@ pub const Entries = struct {
    fn get_total_width(entries: Entries) [3]u16 {
        var ret: [3]u16 = .{ 0, 0, 0 };

        for (entries.list.items(.alignment)) |algn, index| {
        for (entries.list.items(.alignment), 0..) |algn, index| {
            const entry_w = entries.list.items(.width)[index] + entries.list.items(.offset)[index];
            switch (algn) {
                .left => ret[0] += entry_w,


@@ 230,16 230,13 @@ const Entry = struct {
    ///
    /// Return the total width of the entry to use as 'x' for the next one.
    pub fn render(entry: Entry, pix: *pixman.Image, prev_x: u16, height: u16) !u16 {
        var x = @intCast(i16, prev_x);
        var x: i16 = @intCast(prev_x);
        switch (entry.alignment) {
            .left, .center => x = x + entry.offset - @intCast(i16, entry.width) - entry.offset,
            .right => x = x - @intCast(i16, entry.width) - entry.offset,
            .left, .center => x = x + entry.offset - @as(i16, @intCast(entry.width)) - entry.offset,
            .right => x = x - @as(i16, @intCast(entry.width)) - entry.offset,
        }

        const y: i16 = @intCast(
            i16,
            if (ctx.bar.config.location == .bottom) ctx.bar.config.border.bottom else ctx.bar.config.border.top,
        );
        const y: i16 = @intCast(if (ctx.bar.config.location == .bottom) ctx.bar.config.border.bottom else ctx.bar.config.border.top);

        const bg = entry.colors.get(.bg) orelse ctx.bar.config.colors.get(.bg).?;
        try decorations.draw_rectangle(pix, x, y, entry.width, height, bg);


@@ 247,8 244,8 @@ const Entry = struct {
        if (entry.action) |action| {
            try ctx.backend.surface.?.hotspots.append(ctx.gpa, .{
                .action = action,
                .x = @intCast(u31, x),
                .y = @intCast(u31, y),
                .x = @intCast(x),
                .y = @intCast(y),
                .width = entry.width,
                .height = height,
            });


@@ 269,7 266,7 @@ const Entry = struct {
            try decorations.draw_rectangle(
                pix,
                x,
                y + @intCast(i16, height - line_u.height),
                y + @as(i16, @intCast(height - line_u.height)),
                entry.width,
                line_u.height,
                line_u.color,

M src/decorations.zig => src/decorations.zig +5 -5
@@ 67,15 67,15 @@ pub const Border = struct {
        const borders = [4]pixman.Rectangle16{
            // Top
            .{
                .x = x + @intCast(i16, border.left),
                .x = x + @as(i16, @intCast(border.left)),
                .y = 0,
                .width = width - border.left - border.right,
                .height = border.top,
            },
            // Bottom
            .{
                .x = x + @intCast(i16, border.left),
                .y = @intCast(i16, height - border.bottom),
                .x = x + @as(i16, @intCast(border.left)),
                .y = @intCast(height - border.bottom),
                .width = width - border.left - border.right,
                .height = border.bottom,
            },


@@ 88,7 88,7 @@ pub const Border = struct {
            },
            // Right
            .{
                .x = x + @intCast(i16, width - border.right),
                .x = x + @as(i16, @intCast(width - border.right)),
                .y = y,
                .width = border.right,
                .height = height,


@@ 126,7 126,7 @@ pub fn parse_rgba(s: []const u8) !pixman.Color {
        color |= 0xff;
    }

    const bytes = @bitCast([4]u8, color);
    const bytes = @as([4]u8, @bitCast(color));

    const r: u16 = bytes[3];
    const g: u16 = bytes[2];