stevee

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

commit 9dcaffc942929d1bd318ed6a1da8eb274261f5f8
parent 12d1b3d6ee59e2a5e7f09d1b6ef517b1b786333d
Author: Andrea Feletto <andrea@andreafeletto.com>
Date:   Sun, 18 Dec 2022 15:26:25 +0100

make state a global variable

Diffstat:
Msrc/Bar.zig | 11++++++-----
Msrc/Input.zig | 11+++++------
Msrc/Loop.zig | 12++++++------
Msrc/Modules.zig | 17+++++++----------
Msrc/Monitor.zig | 11+++++------
Msrc/Tags.zig | 8++++----
Msrc/Wayland.zig | 21++++++++-------------
Msrc/Widget.zig | 5+++--
Msrc/main.zig | 16++++++++++------
Msrc/modules/Backlight.zig | 13++++++-------
Msrc/modules/Battery.zig | 15+++++++--------
Msrc/modules/Pulse.zig | 11+++++------
Msrc/render.zig | 15++++++---------
13 files changed, 78 insertions(+), 88 deletions(-)

diff --git a/src/Bar.zig b/src/Bar.zig @@ -11,6 +11,8 @@ const render = @import("render.zig"); const Widget = @import("Widget.zig"); const Bar = @This(); +const state = &@import("root").state; + monitor: *Monitor, layerSurface: *zwlr.LayerSurfaceV1, @@ -29,7 +31,6 @@ width: u16, height: u16, pub fn create(monitor: *Monitor) !*Bar { - const state = monitor.state; const globals = &state.wayland.globals; const self = try state.gpa.create(Bar); @@ -48,9 +49,9 @@ pub fn create(monitor: *Monitor) !*Bar { "levee", ); - 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); + self.tags = try Widget.init(self.background.surface); + self.clock = try Widget.init(self.background.surface); + self.modules = try Widget.init(self.background.surface); // setup layer surface self.layerSurface.setSize(0, state.config.height); @@ -80,7 +81,7 @@ pub fn destroy(self: *Bar) void { self.clock.deinit(); self.modules.deinit(); - self.monitor.state.gpa.destroy(self); + state.gpa.destroy(self); } fn layerSurfaceListener( diff --git a/src/Input.zig b/src/Input.zig @@ -1,10 +1,10 @@ const wl = @import("wayland").client.wl; -const State = @import("main.zig").State; const Bar = @import("Bar.zig"); const Input = @This(); -state: *State, +const state = &@import("root").state; + seat: *wl.Seat, globalName: u32, @@ -16,9 +16,8 @@ pointer: struct { surface: ?*wl.Surface, }, -pub fn create(state: *State, registry: *wl.Registry, name: u32) !*Input { +pub fn create(registry: *wl.Registry, name: u32) !*Input { const self = try state.gpa.create(Input); - self.state = state; self.seat = try registry.bind(name, wl.Seat, 7); self.globalName = name; @@ -35,7 +34,7 @@ pub fn destroy(self: *Input) void { pointer.release(); } self.seat.release(); - self.state.gpa.destroy(self); + state.gpa.destroy(self); } fn listener(seat: *wl.Seat, event: wl.Seat.Event, input: *Input) void { @@ -67,7 +66,7 @@ fn pointerListener( .enter => |data| { input.pointer.x = data.surface_x.toInt(); input.pointer.y = data.surface_y.toInt(); - const bar = input.state.wayland.findBar(data.surface); + const bar = state.wayland.findBar(data.surface); input.pointer.bar = bar; input.pointer.surface = data.surface; }, diff --git a/src/Loop.zig b/src/Loop.zig @@ -3,14 +3,14 @@ const log = std.log; const mem = std.mem; const os = std.os; -const State = @import("main.zig").State; const utils = @import("utils.zig"); const Loop = @This(); -state: *State, +const state = &@import("root").state; + sfd: os.fd_t, -pub fn init(state: *State) !Loop { +pub fn init() !Loop { var mask = os.empty_sigset; os.linux.sigaddset(&mask, os.linux.SIG.INT); os.linux.sigaddset(&mask, os.linux.SIG.TERM); @@ -19,12 +19,12 @@ pub fn init(state: *State) !Loop { _ = os.linux.sigprocmask(os.linux.SIG.BLOCK, &mask, null); const sfd = os.linux.signalfd(-1, &mask, os.linux.SFD.NONBLOCK); - return Loop{ .state = state, .sfd = @intCast(os.fd_t, sfd) }; + return Loop{ .sfd = @intCast(os.fd_t, sfd) }; } pub fn run(self: *Loop) !void { - const wayland = &self.state.wayland; - const modules = &self.state.modules; + const wayland = &state.wayland; + const modules = &state.modules; var fds = [_]os.pollfd{ .{ diff --git a/src/Modules.zig b/src/Modules.zig @@ -2,26 +2,23 @@ const std = @import("std"); const mem = std.mem; const ArrayList = std.ArrayList; -const State = @import("main.zig").State; const Modules = @This(); const Backlight = @import("modules/Backlight.zig"); const Battery = @import("modules/Battery.zig"); const Pulse = @import("modules/Pulse.zig"); +var state = &@import("root").state; + const Tag = enum { backlight, battery, pulse }; -state: *State, backlight: ?Backlight = null, battery: ?Battery = null, pulse: ?Pulse = null, order: ArrayList(Tag), -pub fn init(state: *State) Modules { - return Modules{ - .state = state, - .order = ArrayList(Tag).init(state.gpa), - }; +pub fn init() Modules { + return Modules{ .order = ArrayList(Tag).init(state.gpa) }; } pub fn deinit(self: *Modules) void { @@ -33,13 +30,13 @@ pub fn deinit(self: *Modules) void { pub fn register(self: *Modules, name: []const u8) !void { if (mem.eql(u8, name, "backlight")) { - self.backlight = try Backlight.init(self.state); + self.backlight = try Backlight.init(); try self.order.append(.backlight); } else if (mem.eql(u8, name, "battery")) { - self.battery = try Battery.init(self.state); + self.battery = try Battery.init(); try self.order.append(.battery); } else if (mem.eql(u8, name, "pulse")) { - self.pulse = try Pulse.init(self.state); + self.pulse = try Pulse.init(); try self.pulse.?.start(); try self.order.append(.pulse); } else { diff --git a/src/Monitor.zig b/src/Monitor.zig @@ -1,11 +1,11 @@ const wl = @import("wayland").client.wl; -const State = @import("main.zig").State; const Bar = @import("Bar.zig"); const Tags = @import("Tags.zig"); const Monitor = @This(); -state: *State, +const state = &@import("root").state; + output: *wl.Output, globalName: u32, scale: i32, @@ -13,15 +13,14 @@ scale: i32, bar: ?*Bar, tags: *Tags, -pub fn create(state: *State, registry: *wl.Registry, name: u32) !*Monitor { +pub fn create(registry: *wl.Registry, name: u32) !*Monitor { const self = try state.gpa.create(Monitor); - self.state = state; self.output = try registry.bind(name, wl.Output, 4); self.globalName = name; self.scale = 1; self.bar = null; - self.tags = try Tags.create(state, self); + self.tags = try Tags.create(self); self.output.setListener(*Monitor, listener, self); return self; @@ -32,7 +31,7 @@ pub fn destroy(self: *Monitor) void { bar.destroy(); } self.tags.destroy(); - self.state.gpa.destroy(self); + state.gpa.destroy(self); } fn listener(_: *wl.Output, event: wl.Output.Event, monitor: *Monitor) void { diff --git a/src/Tags.zig b/src/Tags.zig @@ -5,9 +5,10 @@ const zriver = @import("wayland").client.zriver; const Monitor = @import("Monitor.zig"); const render = @import("render.zig"); const Input = @import("Input.zig"); -const State = @import("main.zig").State; const Tags = @This(); +const state = &@import("root").state; + monitor: *Monitor, outputStatus: *zriver.OutputStatusV1, tags: [9]Tag, @@ -18,7 +19,7 @@ pub const Tag = struct { occupied: bool = false, }; -pub fn create(state: *State, monitor: *Monitor) !*Tags { +pub fn create(monitor: *Monitor) !*Tags { const self = try state.gpa.create(Tags); const globals = &state.wayland.globals; @@ -36,7 +37,7 @@ pub fn create(state: *State, monitor: *Monitor) !*Tags { pub fn destroy(self: *Tags) void { self.outputStatus.destroy(); - self.monitor.state.gpa.destroy(self); + state.gpa.destroy(self); } fn outputStatusListener( @@ -73,7 +74,6 @@ fn outputStatusListener( } pub fn handleClick(self: *Tags, x: u32, input: *Input) !void { - const state = self.monitor.state; const control = state.wayland.globals.control; if (self.monitor.bar) |bar| { diff --git a/src/Wayland.zig b/src/Wayland.zig @@ -15,11 +15,11 @@ const Bar = @import("Bar.zig"); const Event = @import("Loop.zig").Event; const Input = @import("Input.zig"); const Monitor = @import("Monitor.zig"); -const State = @import("main.zig").State; const utils = @import("utils.zig"); const Wayland = @This(); -state: *State, +const state = &@import("root").state; + display: *wl.Display, fd: os.fd_t, @@ -39,15 +39,11 @@ const Globals = struct { }; const GlobalsMask = utils.Mask(Globals); -pub fn init(state: *State) !Wayland { +pub fn init() !Wayland { const display = try wl.Display.connect(null); - const wfd = wfd: { - const fd = display.getFd(); - break :wfd @intCast(os.fd_t, fd); - }; + const wfd = @intCast(os.fd_t, display.getFd()); return Wayland{ - .state = state, .display = display, .fd = wfd, .monitors = ArrayList(*Monitor).init(state.gpa), @@ -76,7 +72,7 @@ pub fn registerGlobals(self: *Wayland) !void { const registry = try self.display.getRegistry(); defer registry.destroy(); - registry.setListener(*State, registryListener, self.state); + registry.setListener(*Wayland, registryListener, self); const errno = self.display.roundtrip(); if (errno != .SUCCESS) return error.RoundtripFailed; for (self.globalsMask) |is_registered| if (!is_registered) { @@ -102,8 +98,7 @@ pub fn findBar(self: *Wayland, wlSurface: ?*wl.Surface) ?*Bar { return null; } -fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, state: *State) void { - const self = &state.wayland; +fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, self: *Wayland) void { switch (event) { .global => |g| { self.bindGlobal(registry, g.name, g.interface, g.version) catch |err| switch (err) { @@ -159,14 +154,14 @@ fn bindGlobal(self: *Wayland, registry: *wl.Registry, name: u32, iface: [*:0]con log.err("wl_output version 3 is required", .{}); return; } - const monitor = try Monitor.create(self.state, registry, name); + const monitor = try Monitor.create(registry, name); try self.monitors.append(monitor); } else if (strcmp(iface, wl.Seat.getInterface().name) == 0) { if (version < 5) { log.err("wl_seat version 5 is required", .{}); return; } - const input = try Input.create(self.state, registry, name); + const input = try Input.create(registry, name); try self.inputs.append(input); } } diff --git a/src/Widget.zig b/src/Widget.zig @@ -4,14 +4,15 @@ const mem = std.mem; const wl = @import("wayland").client.wl; const Buffer = @import("Buffer.zig"); -const State = @import("main.zig").State; const Widget = @This(); +const state = &@import("root").state; + surface: *wl.Surface, subsurface: *wl.Subsurface, buffers: [2]Buffer, -pub fn init(state: *State, background: *wl.Surface) !Widget { +pub fn init(background: *wl.Surface) !Widget { const globals = &state.wayland.globals; const surface = try globals.compositor.createSurface(); diff --git a/src/main.zig b/src/main.zig @@ -21,6 +21,8 @@ pub const State = struct { loop: Loop, }; +pub var state: State = undefined; + pub fn main() anyerror!void { var gpa: heap.GeneralPurposeAllocator(.{}) = .{}; defer _ = gpa.deinit(); @@ -28,14 +30,16 @@ pub fn main() anyerror!void { _ = fcft.init(.auto, false, .warning); // initialization - var state: State = undefined; state.gpa = gpa.allocator(); state.config = try Config.init(); - state.wayland = try Wayland.init(&state); - defer state.wayland.deinit(); - state.modules = Modules.init(&state); - defer state.modules.deinit(); - state.loop = try Loop.init(&state); + state.wayland = try Wayland.init(); + state.modules = Modules.init(); + state.loop = try Loop.init(); + + defer { + state.wayland.deinit(); + state.modules.deinit(); + } // modules var args = process.args(); diff --git a/src/modules/Backlight.zig b/src/modules/Backlight.zig @@ -7,11 +7,11 @@ const os = std.os; const udev = @import("udev"); const render = @import("../render.zig"); -const State = @import("../main.zig").State; const utils = @import("../utils.zig"); const Backlight = @This(); -state: *State, +const state = &@import("root").state; + context: *udev.Udev, monitor: *udev.Monitor, fd: os.fd_t, @@ -25,7 +25,7 @@ const Device = struct { const DeviceList = std.ArrayList(Device); -pub fn init(state: *State) !Backlight { +pub fn init() !Backlight { const context = try udev.Udev.new(); const monitor = try udev.Monitor.newFromNetlink(context, "udev"); @@ -37,7 +37,6 @@ pub fn init(state: *State) !Backlight { try updateDevices(state.gpa, context, &devices); return Backlight{ - .state = state, .context = context, .monitor = monitor, .fd = try monitor.getFd(), @@ -48,7 +47,7 @@ pub fn init(state: *State) !Backlight { pub fn deinit(self: *Backlight) void { _ = self.context.unref(); for (self.devices.items) |*device| { - self.state.gpa.free(device.name); + state.gpa.free(device.name); } self.devices.deinit(); } @@ -56,7 +55,7 @@ pub fn deinit(self: *Backlight) void { pub fn refresh(self: *Backlight) !void { _ = try self.monitor.receiveDevice(); - for (self.state.wayland.monitors.items) |monitor| { + for (state.wayland.monitors.items) |monitor| { if (monitor.bar) |bar| { if (bar.configured) { render.renderModules(bar) catch continue; @@ -68,7 +67,7 @@ pub fn refresh(self: *Backlight) !void { } pub fn print(self: *Backlight, writer: anytype) !void { - try updateDevices(self.state.gpa, self.context, &self.devices); + try updateDevices(state.gpa, self.context, &self.devices); const device = self.devices.items[0]; var percent = @intToFloat(f64, device.value) * 100.0; percent /= @intToFloat(f64, device.max); diff --git a/src/modules/Battery.zig b/src/modules/Battery.zig @@ -9,11 +9,11 @@ const udev = @import("udev"); const Module = @import("../Modules.zig").Module; const Event = @import("../Loop.zig").Event; const render = @import("../render.zig"); -const State = @import("../main.zig").State; const utils = @import("../utils.zig"); const Battery = @This(); -state: *State, +const state = &@import("root").state; + context: *udev.Udev, fd: os.fd_t, devices: DeviceList, @@ -26,7 +26,7 @@ const Device = struct { const DeviceList = std.ArrayList(Device); -pub fn init(state: *State) !Battery { +pub fn init() !Battery { const tfd = tfd: { const fd = os.linux.timerfd_create( os.CLOCK.MONOTONIC, @@ -46,7 +46,6 @@ pub fn init(state: *State) !Battery { try updateDevices(state.gpa, context, &devices); return Battery{ - .state = state, .context = context, .fd = tfd, .devices = devices, @@ -56,14 +55,14 @@ pub fn init(state: *State) !Battery { pub fn deinit(self: *Battery) void { _ = self.context.unref(); for (self.devices.items) |*device| { - self.state.gpa.free(device.name); - self.state.gpa.free(device.status); + state.gpa.free(device.name); + state.gpa.free(device.status); } self.devices.deinit(); } pub fn print(self: *Battery, writer: anytype) !void { - try updateDevices(self.state.gpa, self.context, &self.devices); + try updateDevices(state.gpa, self.context, &self.devices); const device = self.devices.items[0]; var icon: []const u8 = "❓"; @@ -82,7 +81,7 @@ pub fn refresh(self: *Battery) !void { var expirations = mem.zeroes([8]u8); _ = try os.read(self.fd, &expirations); - for (self.state.wayland.monitors.items) |monitor| { + for (state.wayland.monitors.items) |monitor| { if (monitor.bar) |bar| { if (bar.configured) { render.renderClock(bar) catch continue; diff --git a/src/modules/Pulse.zig b/src/modules/Pulse.zig @@ -8,11 +8,11 @@ const pulse = @cImport(@cInclude("pulse/pulseaudio.h")); const Module = @import("../Modules.zig").Module; const Event = @import("../Loop.zig").Event; const render = @import("../render.zig"); -const State = @import("../main.zig").State; const utils = @import("../utils.zig"); const Pulse = @This(); -state: *State, +const state = &@import("root").state; + fd: os.fd_t, mainloop: *pulse.pa_threaded_mainloop, api: *pulse.pa_mainloop_api, @@ -23,7 +23,7 @@ sink_is_running: bool, volume: u8, muted: bool, -pub fn init(state: *State) !Pulse { +pub fn init() !Pulse { // create descriptor for poll in Loop const efd = efd: { const fd = try os.eventfd(0, os.linux.EFD.NONBLOCK); @@ -42,7 +42,6 @@ pub fn init(state: *State) !Pulse { if (connected < 0) return error.InitFailed; return Pulse{ - .state = state, .fd = efd, .mainloop = mainloop, .api = api, @@ -74,7 +73,7 @@ pub fn refresh(self: *Pulse) !void { var data = mem.zeroes([8]u8); _ = try os.read(self.fd, &data); - for (self.state.wayland.monitors.items) |monitor| { + for (state.wayland.monitors.items) |monitor| { if (monitor.bar) |bar| { if (bar.configured) { render.renderClock(bar) catch continue; @@ -124,7 +123,7 @@ export fn contextStateCallback( pulse.PA_CONTEXT_TERMINATED, pulse.PA_CONTEXT_FAILED => { log.info("pulse: restarting", .{}); self.deinit(); - self.* = Pulse.init(self.state) catch return; + self.* = Pulse.init() catch return; log.info("pulse: restarted", .{}); }, else => {}, diff --git a/src/render.zig b/src/render.zig @@ -6,7 +6,6 @@ const pixman = @import("pixman"); const time = @cImport(@cInclude("time.h")); const Buffer = @import("Buffer.zig"); -const State = @import("main.zig").State; const Bar = @import("Bar.zig"); const Tag = @import("Tags.zig").Tag; const utils = @import("utils.zig"); @@ -15,17 +14,18 @@ const Backlight = @import("modules/Backlight.zig"); const Battery = @import("modules/Battery.zig"); const Pulse = @import("modules/Pulse.zig"); +const state = &@import("root").state; + pub const RenderFn = fn (*Bar) anyerror!void; pub fn renderTags(bar: *Bar) !void { - const state = bar.monitor.state; const surface = bar.tags.surface; const tags = bar.monitor.tags.tags; const width = bar.height * 9; const buffer = try Buffer.nextBuffer( &bar.tags.buffers, - bar.monitor.state.wayland.globals.shm, + state.wayland.globals.shm, width, bar.height, ); @@ -34,7 +34,7 @@ pub fn renderTags(bar: *Bar) !void { for (tags) |*tag, i| { const offset = @intCast(i16, bar.height * i); - try renderTag(buffer.pix.?, tag, bar.height, offset, state); + try renderTag(buffer.pix.?, tag, bar.height, offset); } surface.setBufferScale(bar.monitor.scale); @@ -43,12 +43,11 @@ pub fn renderTags(bar: *Bar) !void { } pub fn renderClock(bar: *Bar) !void { - const state = bar.monitor.state; const surface = bar.clock.surface; const shm = state.wayland.globals.shm; // utf8 datetime - const str = try formatDatetime(state); + const str = try formatDatetime(); defer state.gpa.free(str); const runes = try utils.toUtf8(state.gpa, str); defer state.gpa.free(runes); @@ -99,7 +98,6 @@ pub fn renderClock(bar: *Bar) !void { } pub fn renderModules(bar: *Bar) !void { - const state = bar.monitor.state; const surface = bar.modules.surface; const shm = state.wayland.globals.shm; @@ -171,7 +169,6 @@ fn renderTag( tag: *const Tag, height: u16, offset: i16, - state: *State, ) !void { const size = @intCast(u16, height); @@ -212,7 +209,7 @@ fn renderTag( pixman.Image.composite32(.over, char, glyph.pix, pix, 0, 0, 0, 0, x, y, glyph.width, glyph.height); } -fn formatDatetime(state: *State) ![]const u8 { +fn formatDatetime() ![]const u8 { var buf = try state.gpa.alloc(u8, 256); const now = time.time(null); const local = time.localtime(&now);