diff --git a/src/bar/bar.zig b/src/bar/bar.zig index f11a1a7..d16ac8b 100644 --- a/src/bar/bar.zig +++ b/src/bar/bar.zig @@ -110,6 +110,16 @@ pub const Bar = struct { } } + fn dispatch_click_event(self: *Bar, name: []const u8, event: MouseEvent) !void { + std.log.debug(.bar, "Dispatch! {} {}\n", .{ name, event }); + + for (self.widgets) |w| { + if (std.mem.eql(u8, w.name(), name)) { + try w.mouse_event(event); + } + } + } + inline fn terminal_input_process(self: *Bar) !void { // TODO: make work on other OSes other than xterm compatable terminals. @@ -150,16 +160,17 @@ pub const Bar = struct { if (y == null) { continue; } - const click_x_position = try std.fmt.parseInt(u64, x.?, 10); + const click_x_position = try std.fmt.parseInt(u16, x.?, 10); // This makes it so it only works on the end of a click not the start // preventing a single click pressing the button twice. if (y.?[y.?.len - 1] == 'm') continue; - var current_info_line_length: u64 = 0; + var current_info_line_length: u16 = 0; for (self.infos.items) |infoItem, index| { // Because the terminal output contains colour codes, we need to strip them. // To do this we only count the number of characters that are actually printed. var isEscape: bool = false; + const previous_length = current_info_line_length; for (infoItem.full_text) |char| { // Skip all of the escape codes. if (char == 0x1b) { @@ -177,12 +188,8 @@ pub const Bar = struct { current_info_line_length = current_info_line_length + 1; } // Get the first widget that the click is in. - if (click_x_position <= current_info_line_length) { - for (self.widgets) |w| { - if (std.mem.eql(u8, w.name(), infoItem.name)) { - w.mouse_event(.{ .button = .LeftClick }) catch {}; - } - } + if (click_x_position <= current_info_line_length) { + self.dispatch_click_event(infoItem.name, .{ .button = .LeftClick, .x = click_x_position, .y=0,.scale=1, .height=1, .relative_x = click_x_position - previous_length}) catch {}; break; } // Compensate for the | seporator on the terminal. @@ -195,9 +202,6 @@ pub const Bar = struct { inline fn i3bar_input_process(self: *Bar) !void { var line_buffer: [512]u8 = undefined; while (self.running) { - var arena = std.heap.ArenaAllocator.init(self.allocator); - defer arena.deinit(); - var allocator = &arena.allocator; const line_opt = try std.io.getStdIn().inStream().readUntilDelimiterOrEof(&line_buffer, '\n'); if (line_opt) |l| { var line = l; @@ -210,16 +214,11 @@ pub const Bar = struct { // instead of looping and getting it, maybe then it would make more sense? // Anyway this just strips off the prefix of ',' so I can parse the json. if (line[0] == ',') line = line[1..line.len]; - const parseOptions = std.json.ParseOptions{ .allocator = allocator }; + const parseOptions = std.json.ParseOptions{ .allocator = self.allocator }; const data = try std.json.parse(MouseEvent, &std.json.TokenStream.init(line), parseOptions); defer std.json.parseFree(MouseEvent, data, parseOptions); - // TODO: maybe make a function for getting the widget or widget index by name? - // We do use this patern a lot in this code. - for (self.widgets) |w| { - if (std.mem.eql(u8, w.name(), data.name)) { - try w.mouse_event(data); - } - } + + self.dispatch_click_event(data.name, data) catch {}; // If mouse_event needs to store the event for after the call is finished, // it should do it by itself, this just keeps the lifetime of the event to bare minimum. // Free the memory allocated by the MouseEvent struct. diff --git a/src/main.zig b/src/main.zig index cc16c8d..28e8706 100644 --- a/src/main.zig +++ b/src/main.zig @@ -66,8 +66,7 @@ pub fn main() !void { const widgets = [_]*Widget{ //&Widget.init(&textWidget.New("owo", "potato")), // 4KiB //&Widget.init(&textWidget.New("uwu", "tomato")), // 4KiB - &Widget.init(&networkWidget.New(allocator, &br)), // 4.08KiB - + &Widget.init(&networkWidget.New(allocator, &br)), // 24.01KiB &Widget.init(&cpuWidget.New(&br)), // 4.08KiB &Widget.init(&memoryWidget.New(&br)), // 4.08KiB &Widget.init(&weatherWidget.New(allocator, &br, @import("build_options").weather_location)), // 16.16KiB diff --git a/src/widgets/cpu/cpu.zig b/src/widgets/cpu/cpu.zig index ef9aa1b..02b7257 100644 --- a/src/widgets/cpu/cpu.zig +++ b/src/widgets/cpu/cpu.zig @@ -17,7 +17,6 @@ fn formatCPUPercent(allocator: *std.mem.Allocator, percent: f64) ![]const u8 { percentColour = "green"; } const percentString = try std.fmt.allocPrint(allocator, "{d:0<2.2}" ++ comptimeColour("accentdark", "%"), .{percent}); - return colour(allocator, percentColour, percentString); } diff --git a/src/widgets/memory/memory.zig b/src/widgets/memory/memory.zig index 6c24df4..81f088b 100644 --- a/src/widgets/memory/memory.zig +++ b/src/widgets/memory/memory.zig @@ -41,6 +41,7 @@ fn formatMemoryPercent(allocator: *std.mem.Allocator, percent: f64) ![]const u8 percentColour = "green"; } const percentString = try std.fmt.allocPrint(allocator, "{d:.2}" ++ comptimeColour("accentdark", "%"), .{percent}); + defer allocator.free(percentString); return colour(allocator, percentColour, percentString); } diff --git a/src/widgets/network/network.zig b/src/widgets/network/network.zig index 828ad0a..e935486 100644 --- a/src/widgets/network/network.zig +++ b/src/widgets/network/network.zig @@ -47,10 +47,17 @@ fn networkStatusToColour(s: NetworkStatus) []const u8 { pub const NetworkInfo = struct { network_type: NetworkType = .WiFi, network_status: NetworkStatus = .Connected, - network_info: [32]u8 = [32]u8{ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, - network_info_len: usize, + network_info: []const u8, }; +inline fn freeString(allocator: *std.mem.Allocator, string: []const u8) void { + allocator.free(string); +} + +inline fn dupeString(allocator: *std.mem.Allocator, string: []const u8) ![]const u8 { + return try allocator.dupe(u8, string); +} + pub const NetworkWidget = struct { bar: *Bar, allocator: *std.mem.Allocator, @@ -87,14 +94,15 @@ pub const NetworkWidget = struct { pub fn update_network_infos(self: *NetworkWidget) anyerror!void { const lock = self.update_mutex.acquire(); defer lock.release(); - self.network_infos.shrink(0); + for (self.network_infos.items) |info| { + freeString(self.allocator, info.network_info); + } self.num_interfaces = 0; - var arena = std.heap.ArenaAllocator.init(self.allocator); - defer arena.deinit(); - var allocator = &arena.allocator; - var proc = try std.ChildProcess.init(&[_][]const u8{ "nmcli", "-f", "common", "-c", "no", "d" }, allocator); + var proc = try std.ChildProcess.init(&[_][]const u8{ "nmcli", "-f", "common", "-c", "no", "d" }, self.allocator); + defer { _ = proc.kill() catch {}; proc.deinit(); } proc.stdout_behavior = .Pipe; try proc.spawn(); + var i: u8 = 0; if (proc.stdout) |stdout| { var line_buffer: [128]u8 = undefined; // Skip header. @@ -107,45 +115,52 @@ pub const NetworkWidget = struct { const status = it.next(); const description = it.next(); if (connection_type) |t| if (!(eql(u8, t, "wifi") or eql(u8, t, "ethernet"))) continue; - var net_info = NetworkInfo{ + try self.network_infos.resize(i+1); + self.network_infos.items[i] = NetworkInfo{ .network_type = toNetworkType(connection_type.?), .network_status = toNetworkStatus(status.?), - .network_info_len = description.?.len, + .network_info = try dupeString(self.allocator, description.?), }; - std.mem.copy(u8, net_info.network_info[0..description.?.len], description.?[0..description.?.len]); - - try self.network_infos.append(net_info); + //try self.network_infos.append(net_info); self.num_interfaces += 1; + i += 1; } } } pub fn update_bar(self: *NetworkWidget) anyerror!void { - var arena = std.heap.ArenaAllocator.init(self.allocator); - defer arena.deinit(); - var allocator = &arena.allocator; + var buffer: [512]u8 = undefined; + var fba = std.heap.FixedBufferAllocator.init(&buffer); + var allocator = &fba.allocator; for (self.network_infos.items) |info, i| { if (i != self.current_interface) continue; //std.log.debug(.network, "item! {} {}\n", .{ info, i }); + const inner_text = try std.fmt.allocPrint(allocator, "{} {}", .{ @tagName(info.network_type), info.network_info }); + const full_text = try colour(allocator, networkStatusToColour(info.network_status), inner_text); + defer allocator.free(full_text); + allocator.free(inner_text); try self.bar.add(Info{ .name = "network", - .full_text = try colour(allocator, networkStatusToColour(info.network_status), try std.fmt.allocPrint(allocator, "{} {}", .{ @tagName(info.network_type), info.network_info[0..info.network_info_len] })), + .full_text = full_text, .markup = "pango", }); } } pub fn start(self: *NetworkWidget) anyerror!void { - var arena = std.heap.ArenaAllocator.init(self.allocator); - defer arena.deinit(); - var allocator = &arena.allocator; - self.network_infos = std.ArrayList(NetworkInfo).init(allocator); + self.network_infos = std.ArrayList(NetworkInfo).init(self.allocator); + defer self.network_infos.deinit(); while (self.bar.keep_running()) { try self.update_network_infos(); try self.update_bar(); std.time.sleep(std.time.ns_per_s); } + const lock = self.update_mutex.acquire(); + defer lock.release(); + for (self.network_infos.items) |info| { + freeString(self.allocator, info.network_info); + } } }; diff --git a/src/widgets/time/time.zig b/src/widgets/time/time.zig index b936c71..807b540 100644 --- a/src/widgets/time/time.zig +++ b/src/widgets/time/time.zig @@ -25,12 +25,12 @@ pub const TimeWidget = struct { pub fn start(self: *TimeWidget) anyerror!void { // TODO: find a god damn decent time library thats better than this bullshit. - while (self.bar.keep_running()) { var arena = std.heap.ArenaAllocator.init(self.allocator); defer arena.deinit(); var allocator = &arena.allocator; var local = time.Location.getLocal(allocator); - var now = time.now(&local); + while (self.bar.keep_running()) { + var now = time.now(&local); var date = now.date(); var clock = now.clock();