~andreafeletto/levee

ref: a40cd1f35e815d58ac2b5bdf3968a611a8a0972e levee/src/Bar.zig -rw-r--r-- 3.5 KiB
a40cd1f3Andrea Feletto pulse: respect muted flag 5 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
const std = @import("std");
const mem = std.mem;

const wl = @import("wayland").client.wl;
const zwlr = @import("wayland").client.zwlr;

const Buffer = @import("Buffer.zig");
const Monitor = @import("wayland.zig").Monitor;
const render = @import("render.zig");
const State = @import("main.zig").State;
const Bar = @This();

monitor: *Monitor,

layerSurface: *zwlr.LayerSurfaceV1,
background: struct {
    surface: *wl.Surface,
    buffer: Buffer,
},

tags: Widget,
clock: Widget,
modules: Widget,

configured: bool,
width: u16,
height: u16,

pub const Widget = struct {
    surface: *wl.Surface,
    subsurface: *wl.Subsurface,
    buffers: [2]Buffer,

    pub fn init(state: *State, background: *wl.Surface) !Widget {
        const globals = &state.wayland.globals;

        const surface = try globals.compositor.createSurface();
        const subsurface = try globals.subcompositor.getSubsurface(
            surface,
            background,
        );

        return Widget{
            .surface = surface,
            .subsurface = subsurface,
            .buffers = mem.zeroes([2]Buffer),
        };
    }

    pub fn deinit(self: *Widget) void {
        self.surface.destroy();
        self.subsurface.destroy();
        self.buffers[0].deinit();
        self.buffers[1].deinit();
    }
};

pub fn create(monitor: *Monitor) !*Bar {
    const state = monitor.state;
    const globals = &state.wayland.globals;

    const self = try state.gpa.create(Bar);
    self.monitor = monitor;
    self.configured = false;

    self.background.surface = try globals.compositor.createSurface();
    self.layerSurface = try globals.layerShell.getLayerSurface(
        self.background.surface,
        monitor.output,
        .top,
        "levee",
    );
    self.background.buffer = mem.zeroes(Buffer);

    self.tags = try Widget.init(state, self.background.surface);
    self.clock = try Widget.init(state, self.background.surface);
    self.modules = try Widget.init(state, self.background.surface);

    // setup layer surface
    self.layerSurface.setSize(0, state.config.height);
    self.layerSurface.setAnchor(
        .{ .top = true, .left = true, .right = true, .bottom = false },
    );
    self.layerSurface.setExclusiveZone(state.config.height);
    self.layerSurface.setMargin(0, 0, 0, 0);
    self.layerSurface.setListener(*Bar, layerSurfaceListener, self);

    self.tags.surface.commit();
    self.clock.surface.commit();
    self.modules.surface.commit();
    self.background.surface.commit();

    return self;
}

pub fn destroy(self: *Bar) void {
    self.monitor.bar = null;

    self.background.surface.destroy();
    self.layerSurface.destroy();
    self.background.buffer.deinit();

    self.tags.deinit();
    self.clock.deinit();
    self.modules.deinit();

    self.monitor.state.gpa.destroy(self);
}

fn layerSurfaceListener(
    layerSurface: *zwlr.LayerSurfaceV1,
    event: zwlr.LayerSurfaceV1.Event,
    bar: *Bar,
) void {
    switch (event) {
        .configure => |data| {
            bar.configured = true;
            bar.width = @intCast(u16, data.width);
            bar.height = @intCast(u16, data.height);

            layerSurface.ackConfigure(data.serial);

            render.renderBackground(bar) catch return;
            render.renderTags(bar) catch return;
            render.renderClock(bar) catch return;
            render.renderModules(bar) catch return;

            bar.tags.surface.commit();
            bar.clock.surface.commit();
            bar.modules.surface.commit();
            bar.background.surface.commit();
        },
        .closed => bar.destroy(),
    }
}