~andreafeletto/levee

ae55230ec4895a224104a266195278ff23a8d44b — Andrea Feletto 3 months ago e0ba69e
correct rendering of clock
6 files changed, 44 insertions(+), 46 deletions(-)

M build.zig
M deps/zig-fcft
M src/clock.zig
M src/main.zig
M src/tags.zig
M src/wayland.zig
M build.zig => build.zig +1 -1
@@ 20,7 20,7 @@ pub fn build(b: *std.build.Builder) void {
    const fcft = Pkg{
        .name = "fcft",
        .path = "deps/zig-fcft/fcft.zig",
        .dependencies = &[_]Pkg{ pixman },
        .dependencies = &[_]Pkg{pixman},
    };
    const datetime = Pkg{
        .name = "datetime",

M deps/zig-fcft => deps/zig-fcft +1 -1
@@ 1,1 1,1 @@
Subproject commit 182fcc99f770ce6a8fe3080fa8ca21eecef3085f
Subproject commit 39f77836cfc6198e93a06b00563b0d0cfaef8e8f

M src/clock.zig => src/clock.zig +30 -27
@@ 1,4 1,5 @@
const std = @import("std");
const os = std.os;

const datetime = @import("datetime").datetime;
const pixman = @import("pixman");


@@ 12,44 13,46 @@ pub const Clock = struct {
    stop: bool = false,

    pub fn render(self: *const Clock, pix: *pixman.Image, state: *State) !void {
        const width: i16 = 100;
        const height = @intCast(i16, state.wayland.height);
        const offset = @divFloor(@intCast(i16, state.wayland.width) - width, 2);

        var now = datetime.Datetime.now();
        const str = try now.formatHttp(state.allocator);
        std.log.info("{s}", .{ str });

        // const outer = [_]pixman.Rectangle16{
        //     .{ .x = offset, .y = 0, .width = width, .height = height },
        // };
        // _ = pixman.Image.fillRectangles(.over, pix, state.foreground, 1, &outer);

        var x = offset;
        for (str) |char, i| {
            var color = pixman.Image.createSolidFill(state.foreground).?;
            const glyph = try fcft.Glyph.rasterize(state.font, char, .default);
            // x += @intCast(i16, glyph.advance.x);
            x += 14;
            //const y = @divFloor(height - @intCast(i16, glyph.height), 2);
            const y = 10;
            std.log.info("{d}, {d}", .{ x, y });
            pixman.Image.composite32(
                .over, color, glyph.pix, pix,
                0, 0, 0, 0, x, y,
                glyph.width, glyph.height
            );

        const cint = try state.allocator.alloc(c_int, str.len);
        for (str) |char, i| cint[i] = char;

        const run = try fcft.TextRun.rasterize(state.font, cint, .default);
        defer run.destroy();

        var i: usize = 0;
        var text_width: u32 = 0;
        while (i < run.count) : (i += 1) {
            text_width += @intCast(u32, run.glyphs[i].advance.x);
        }

        var x_offset = @intCast(i32, @divFloor(state.wayland.width - text_width, 2));
        var y_offset = @intCast(i32, @divFloor(state.wayland.height - @intCast(u32, state.font.height), 2));

        i = 0;
        var color = pixman.Image.createSolidFill(state.foreground).?;
        while (i < run.count) : (i += 1) {
            const glyph = run.glyphs[i];
            const x = x_offset + @intCast(i32, glyph.x);
            const y = y_offset + state.font.ascent - @intCast(i32, glyph.y);
            pixman.Image.composite32(.over, color, glyph.pix, pix, 0, 0, 0, 0, x, y, glyph.width, glyph.height);
            x_offset += glyph.advance.x;
        }
    }

    pub fn start(self: *Clock, state: *State) !void {
        self.thread = try std.Thread.spawn(repeatDraw, state);
        // self.thread = try std.Thread.spawn(repeatDraw, state);
        if ((try os.fork()) == 0) {
            repeatDraw(state);
        }
    }
};

fn repeatDraw(state: *State) void {
    while (!state.clock.stop) {
        state.draw(state);
        std.time.sleep(1 * std.time.ns_per_s);
        state.draw(state);
    }
}

M src/main.zig => src/main.zig +8 -10
@@ 28,11 28,12 @@ pub fn main() anyerror!void {

    const wayland = try Wayland.create(allocator);
    defer wayland.destroy();
    try wayland.setup(34);

    var tags = try Tags.init(wayland);
    var clock = Clock{};

    var font_names = [_][*:0]const u8{ "monospace:size=14" };
    var font_names = [_][*:0]const u8{"monospace:size=14"};
    const foreground = pixman.Color{
        .red = 0xffff,
        .green = 0xffff,


@@ 52,33 53,30 @@ pub fn main() anyerror!void {
        .clock = &clock,
        .allocator = allocator,
        .font = try fcft.Font.fromName(font_names[0..], null),

        .foreground = &foreground,
        .background = &background,
        .draw = draw,
    };

    try wayland.setup(34);
    try tags.listen(&state);
    try clock.start(&state);
    draw(&state);
    // draw(&state);
    wayland.loop();
}

fn draw(state: *State) void {
    const width = @intCast(i32, state.wayland.width);
    const height = @intCast(i32, state.wayland.height);
    const width = @intCast(u16, state.wayland.width);
    const height = @intCast(u16, state.wayland.height);
    const surface = state.wayland.wlSurface;

    const shm = state.wayland.shm.?;
    const buffer = Buffer.create(state.allocator, shm, width, height) catch return;
    defer buffer.destroy();

    const bg = pixman.Color{ .red = 0, .green = 0, .blue = 0, .alpha = 0xffff };
    const rects = [_]pixman.Rectangle16{
        .{ .x = 0, .y = 0, .width = @intCast(u16, width), .height = @intCast(u16, height) },
    const area = [_]pixman.Rectangle16{
        .{ .x = 0, .y = 0, .width = width, .height = height },
    };
    _ = pixman.Image.fillRectangles(.src, buffer.pix, &bg, 1, &rects);
    _ = pixman.Image.fillRectangles(.src, buffer.pix, state.background, 1, &area);

    state.tags.render(buffer.pix, state) catch return;
    state.clock.render(buffer.pix, state) catch return;

M src/tags.zig => src/tags.zig +3 -6
@@ 43,11 43,7 @@ pub const Tag = struct {
        const glyph = try fcft.Glyph.rasterize(state.font, self.label, .default);
        const x = offset + @divFloor(size - glyph.width, 2);
        const y = @divFloor(size - glyph.height, 2);
        pixman.Image.composite32(
            .over, char, glyph.pix, pix,
            0, 0, 0, 0, x, y,
            glyph.width, glyph.height
        );
        pixman.Image.composite32(.over, char, glyph.pix, pix, 0, 0, 0, 0, x, y, glyph.width, glyph.height);
    }
};



@@ 126,6 122,7 @@ fn outputStatusListener(status: *zriver.OutputStatusV1, event: zriver.OutputStat
                const mask = @as(u32, 1) << @intCast(u5, i);
                tag.focused = data.tags & mask != 0;
            }
            state.draw(state);
        },
        .view_tags => |data| {
            state.tags.resetOccupied();


@@ 137,5 134,5 @@ fn outputStatusListener(status: *zriver.OutputStatusV1, event: zriver.OutputStat
            }
        },
    }
    state.draw(state);
    // state.draw(state);
}

M src/wayland.zig => src/wayland.zig +1 -1
@@ 8,7 8,7 @@ const zwlr = wayland.zwlr;

const State = @import("main.zig").State;

pub const WaylandError = error {
pub const WaylandError = error{
    GlobalsUnavailable,
};