git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit54e03a1a6bd4aca10ab8c32d04b85cfab13a07b9
parent4bb87624b5
authorIsaac Freund <[email protected]>
date2021-07-25 01:22
river: add custom wlroots log handler

This makes river's log output more consistent and will allow
filtering by the wlroots scope in the future.

 build.zig                   |  1 +
 river/main.zig              | 13 ++++++++++++-
 river/wlroots_log_wrapper.c | 41 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/build.zig b/build.zig
index 48b049a..0dfdca3 100644
--- a/build.zig
+++ b/build.zig
@@ -211,6 +211,7 @@ fn addServerDeps(exe: *zbs.LibExeObjStep, scanner: *ScanProtocolsStep) void {
     exe.linkSystemLibrary("wlroots");
 
     exe.addPackagePath("flags", "common/flags.zig");
+    exe.addCSourceFile("river/wlroots_log_wrapper.c", &[_][]const u8{ "-std=c99", "-O2" });
 
     // TODO: remove when zig issue #131 is implemented
     scanner.addCSource(exe);
diff --git a/river/main.zig b/river/main.zig
index 1482b9d..f1e75f2 100644
--- a/river/main.zig
+++ b/river/main.zig
@@ -87,7 +87,7 @@ pub fn main() anyerror!void {
         }
     };
 
-    wlr.log.init(switch (runtime_log_level) {
+    river_init_wlroots_log(switch (runtime_log_level) {
         .debug => .debug,
         .notice, .info => .info,
         .warn, .err, .crit, .alert, .emerg => .err,
@@ -181,3 +181,14 @@ pub fn log(
     const stderr = std.io.getStdErr().writer();
     stderr.print(@tagName(river_level) ++ scope_prefix ++ format ++ "\n", args) catch {};
 }
+
+/// See wlroots_log_wrapper.c
+extern fn river_init_wlroots_log(importance: wlr.log.Importance) void;
+export fn river_wlroots_log_callback(importance: wlr.log.Importance, ptr: [*:0]const u8, len: usize) void {
+    switch (importance) {
+        .err => log(.err, .wlroots, "{s}", .{ptr[0..len]}),
+        .info => log(.info, .wlroots, "{s}", .{ptr[0..len]}),
+        .debug => log(.debug, .wlroots, "{s}", .{ptr[0..len]}),
+        .silent, .last => unreachable,
+    }
+}
diff --git a/river/wlroots_log_wrapper.c b/river/wlroots_log_wrapper.c
new file mode 100644
index 0000000..7562ba8
--- /dev/null
+++ b/river/wlroots_log_wrapper.c
@@ -0,0 +1,41 @@
+#include <assert.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include <wlr/util/log.h>
+
+#define BUFFER_SIZE 1024
+
+void river_wlroots_log_callback(enum wlr_log_importance importance, const char *ptr, size_t len);
+
+static void callback(enum wlr_log_importance importance, const char *fmt, va_list args) {
+	char buffer[BUFFER_SIZE];
+
+	// Need to make a copy of the args in case our buffer isn't big
+	// enough and we need to use them again.
+	va_list args_copy;
+	va_copy(args_copy, args);
+
+	const int length = vsnprintf(buffer, BUFFER_SIZE, fmt, args);
+	// Need to add one for the terminating 0 byte
+	if (length + 1 <= BUFFER_SIZE) {
+		// The formatted string fit within our buffer, pass it on to river
+		river_wlroots_log_callback(importance, buffer, length);
+	} else {
+		// The formatted string did not fit in our buffer, we need
+		// to allocate enough memory to hold it.
+		char *allocated_buffer = malloc(length + 1);
+		if (allocated_buffer != NULL) {
+			const int length2 = vsnprintf(allocated_buffer, length + 1, fmt, args_copy);
+			assert(length2 == length);
+			river_wlroots_log_callback(importance, allocated_buffer, length);
+			free(allocated_buffer);
+		}
+	}
+
+	va_end(args_copy);
+}
+
+void river_init_wlroots_log(enum wlr_log_importance importance) {
+	wlr_log_init(importance, callback);
+}