Split main() up by adding parseArgs() and run()
parseArgs() contains all of the argument parsing logic in a single fn. run() handles the event loop. To work with the bar, I had to re-write the loop to use polling similar to the loop in `beanclock` instead of just `while (true) dispatch`.
This commit is contained in:
parent
40088b4ab6
commit
5501ccbe26
3 changed files with 125 additions and 48 deletions
|
|
@ -114,7 +114,6 @@ pub fn layerSurfaceListener(
|
||||||
|
|
||||||
bar.configured = true;
|
bar.configured = true;
|
||||||
|
|
||||||
log.debug("bwbuhse before render", .{});
|
|
||||||
bar.render() catch |err| {
|
bar.render() catch |err| {
|
||||||
log.err("Bar render failed: {}", .{err});
|
log.err("Bar render failed: {}", .{err});
|
||||||
};
|
};
|
||||||
|
|
@ -125,7 +124,9 @@ pub fn layerSurfaceListener(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(bar: *Bar) !void {
|
// TODO: Configure number of visible tags
|
||||||
|
/// Renders the bar and its components
|
||||||
|
pub fn render(bar: *Bar) !void {
|
||||||
const buffer = try bar.context.buffer_pool.nextBuffer(bar.context.wl_shm, bar.width, bar.height);
|
const buffer = try bar.context.buffer_pool.nextBuffer(bar.context.wl_shm, bar.width, bar.height);
|
||||||
|
|
||||||
// Fill with a solid color (e.g., dark background)
|
// Fill with a solid color (e.g., dark background)
|
||||||
|
|
@ -138,7 +139,6 @@ fn render(bar: *Bar) !void {
|
||||||
wl_surface.attach(buffer.wl_buffer, 0, 0);
|
wl_surface.attach(buffer.wl_buffer, 0, 0);
|
||||||
wl_surface.damageBuffer(0, 0, bar.width, bar.height);
|
wl_surface.damageBuffer(0, 0, bar.width, bar.height);
|
||||||
wl_surface.commit();
|
wl_surface.commit();
|
||||||
log.debug("bwbuhse end of render", .{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Borrowed and modified from https://git.sr.ht/~novakane/zig-fcft-example
|
// Borrowed and modified from https://git.sr.ht/~novakane/zig-fcft-example
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,6 @@ pub fn destroy(libinput_device: *LibinputDevice) void {
|
||||||
fn riverLibinputDeviceV1Listener(river_libinput_device_v1: *river.LibinputDeviceV1, event: river.LibinputDeviceV1.Event, libinput_device: *LibinputDevice) void {
|
fn riverLibinputDeviceV1Listener(river_libinput_device_v1: *river.LibinputDeviceV1, event: river.LibinputDeviceV1.Event, libinput_device: *LibinputDevice) void {
|
||||||
assert(libinput_device.river_libinput_device_v1 == river_libinput_device_v1);
|
assert(libinput_device.river_libinput_device_v1 == river_libinput_device_v1);
|
||||||
const im = libinput_device.context.im;
|
const im = libinput_device.context.im;
|
||||||
log.debug("bwbuhse: {s} for {d}", .{ @tagName(event), river_libinput_device_v1.getId() });
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
.removed => {
|
.removed => {
|
||||||
river_libinput_device_v1.destroy();
|
river_libinput_device_v1.destroy();
|
||||||
|
|
|
||||||
166
src/main.zig
166
src/main.zig
|
|
@ -36,48 +36,8 @@ const usage: []const u8 =
|
||||||
\\
|
\\
|
||||||
;
|
;
|
||||||
|
|
||||||
// TODO: I'd like to clean this function up a bit and move some bits into helpers
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
const result = flags.parser([*:0]const u8, &.{
|
parseArgs();
|
||||||
.{ .name = "h", .kind = .boolean },
|
|
||||||
.{ .name = "version", .kind = .boolean },
|
|
||||||
.{ .name = "log-level", .kind = .arg },
|
|
||||||
}).parse(std.os.argv[1..]) catch {
|
|
||||||
try stderr.writeAll(usage);
|
|
||||||
try stderr.flush();
|
|
||||||
posix.exit(1);
|
|
||||||
};
|
|
||||||
if (result.flags.h) {
|
|
||||||
try stdout.writeAll(usage);
|
|
||||||
try stdout.flush();
|
|
||||||
posix.exit(0);
|
|
||||||
}
|
|
||||||
if (result.args.len != 0) {
|
|
||||||
log.err("unknown option '{s}'", .{result.args[0]});
|
|
||||||
try stderr.writeAll(usage);
|
|
||||||
try stderr.flush();
|
|
||||||
posix.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.flags.version) {
|
|
||||||
try stdout.writeAll(build_options.version ++ "\n");
|
|
||||||
try stdout.flush();
|
|
||||||
posix.exit(0);
|
|
||||||
}
|
|
||||||
if (result.flags.@"log-level") |level| {
|
|
||||||
if (mem.eql(u8, level, "error")) {
|
|
||||||
runtime_log_level = .err;
|
|
||||||
} else if (mem.eql(u8, level, "warning")) {
|
|
||||||
runtime_log_level = .warn;
|
|
||||||
} else if (mem.eql(u8, level, "info")) {
|
|
||||||
runtime_log_level = .info;
|
|
||||||
} else if (mem.eql(u8, level, "debug")) {
|
|
||||||
runtime_log_level = .debug;
|
|
||||||
} else {
|
|
||||||
log.err("invalid log level '{s}'", .{level});
|
|
||||||
posix.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize fcft
|
// Initialize fcft
|
||||||
const fcft_log_level: fcft.LogClass = switch (runtime_log_level) {
|
const fcft_log_level: fcft.LogClass = switch (runtime_log_level) {
|
||||||
|
|
@ -141,13 +101,130 @@ pub fn main() !void {
|
||||||
});
|
});
|
||||||
defer context.destroy();
|
defer context.destroy();
|
||||||
|
|
||||||
|
try run(wl_display, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Function to handle the main event loop
|
||||||
|
///
|
||||||
|
/// Since we've added a bar with a clock,we need
|
||||||
|
fn run(wl_display: *wl.Display, context: *Context) !void {
|
||||||
|
var mask = posix.sigemptyset();
|
||||||
|
|
||||||
|
posix.sigaddset(&mask, posix.SIG.INT);
|
||||||
|
posix.sigaddset(&mask, posix.SIG.QUIT);
|
||||||
|
|
||||||
|
posix.sigprocmask(posix.SIG.BLOCK, &mask, null);
|
||||||
|
|
||||||
|
const sig_fd = try posix.signalfd(-1, &mask, 0);
|
||||||
|
|
||||||
|
const poll_wayland = 0;
|
||||||
|
const poll_sig = 1;
|
||||||
|
|
||||||
|
var pollfds: [2]posix.pollfd = undefined;
|
||||||
|
|
||||||
|
pollfds[poll_wayland] = .{
|
||||||
|
.fd = wl_display.getFd(),
|
||||||
|
.events = posix.POLL.IN,
|
||||||
|
.revents = 0,
|
||||||
|
};
|
||||||
|
pollfds[poll_sig] = .{
|
||||||
|
.fd = sig_fd,
|
||||||
|
.events = posix.POLL.IN,
|
||||||
|
.revents = 0,
|
||||||
|
};
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (wl_display.dispatch() != .SUCCESS) {
|
const errno = wl_display.flush();
|
||||||
fatal("wayland display dispatch failed", .{});
|
if (errno != .SUCCESS) {
|
||||||
|
fatal("wl_display flush failed: E{s}", .{@tagName(errno)});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the number of milliseconds to the top of the next minute
|
||||||
|
const time = std.time.timestamp();
|
||||||
|
if (time < 0) {
|
||||||
|
log.err("Got a negative time ({d})", .{time});
|
||||||
|
return error.InvalidTime;
|
||||||
|
}
|
||||||
|
const timeout: i32 = @intCast((@divTrunc(time, 60) * 60 + 60 - time) * 1000);
|
||||||
|
|
||||||
|
const poll_rc = posix.poll(&pollfds, timeout) catch |err| {
|
||||||
|
fatal("Failed to poll {s}", .{@errorName(err)});
|
||||||
|
};
|
||||||
|
if (poll_rc == 0) {
|
||||||
|
// If poll returns 0, it timed out, meaning we hit the top of the minute
|
||||||
|
// and need to update the clock.
|
||||||
|
var it = context.wm.outputs.iterator(.forward);
|
||||||
|
while (it.next()) |output| {
|
||||||
|
if (output.bar) |*bar| {
|
||||||
|
bar.render() catch |err| {
|
||||||
|
log.err("Bar timer render failed: {}", .{err});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle fds that became ready
|
||||||
|
if (pollfds[poll_wayland].revents & posix.POLL.HUP != 0) {
|
||||||
|
log.info("Disconnected by compositor", .{});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pollfds[poll_wayland].revents & posix.POLL.IN != 0) {
|
||||||
|
if (wl_display.dispatch() != .SUCCESS) {
|
||||||
|
fatal("Wayland display dispatch failed", .{});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pollfds[poll_sig].revents & posix.POLL.HUP != 0) {
|
||||||
|
fatal("Signal fd hung up", .{});
|
||||||
|
}
|
||||||
|
if (pollfds[poll_sig].revents & posix.POLL.IN != 0) {
|
||||||
|
log.info("Exiting beansprout", .{});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.info("Exiting beansprout", .{});
|
fn parseArgs() void {
|
||||||
|
const result = flags.parser([*:0]const u8, &.{
|
||||||
|
.{ .name = "h", .kind = .boolean },
|
||||||
|
.{ .name = "version", .kind = .boolean },
|
||||||
|
.{ .name = "log-level", .kind = .arg },
|
||||||
|
}).parse(os.argv[1..]) catch {
|
||||||
|
stderr.writeAll(usage) catch {};
|
||||||
|
stderr.flush() catch {};
|
||||||
|
posix.exit(1);
|
||||||
|
};
|
||||||
|
if (result.flags.h) {
|
||||||
|
stdout.writeAll(usage) catch {};
|
||||||
|
stdout.flush() catch {};
|
||||||
|
posix.exit(0);
|
||||||
|
}
|
||||||
|
if (result.args.len != 0) {
|
||||||
|
log.err("unknown option '{s}'", .{result.args[0]});
|
||||||
|
stderr.writeAll(usage) catch {};
|
||||||
|
stderr.flush() catch {};
|
||||||
|
posix.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.flags.version) {
|
||||||
|
stdout.writeAll(build_options.version ++ "\n") catch {};
|
||||||
|
stdout.flush() catch {};
|
||||||
|
posix.exit(0);
|
||||||
|
}
|
||||||
|
if (result.flags.@"log-level") |level| {
|
||||||
|
if (mem.eql(u8, level, "error")) {
|
||||||
|
runtime_log_level = .err;
|
||||||
|
} else if (mem.eql(u8, level, "warning")) {
|
||||||
|
runtime_log_level = .warn;
|
||||||
|
} else if (mem.eql(u8, level, "info")) {
|
||||||
|
runtime_log_level = .info;
|
||||||
|
} else if (mem.eql(u8, level, "debug")) {
|
||||||
|
runtime_log_level = .debug;
|
||||||
|
} else {
|
||||||
|
log.err("invalid log level '{s}'", .{level});
|
||||||
|
posix.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, globals: *Globals) void {
|
fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, globals: *Globals) void {
|
||||||
|
|
@ -250,6 +327,7 @@ const std = @import("std");
|
||||||
const fatal = std.process.fatal;
|
const fatal = std.process.fatal;
|
||||||
const fs = std.fs;
|
const fs = std.fs;
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
|
const os = std.os;
|
||||||
const posix = std.posix;
|
const posix = std.posix;
|
||||||
const process = std.process;
|
const process = std.process;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue