From 0938835f87c88e2e2b07f9118879fa39d108c2a7 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Fri, 2 Feb 2024 21:10:58 -0600 Subject: [PATCH 1/2] Implement mode 2031 and DSR 996 for GTK --- src/apprt/gtk/App.zig | 105 ++++++++++++++++++++++++++++++++++++++ src/apprt/gtk/Surface.zig | 3 ++ 2 files changed, 108 insertions(+) diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index 0a33f0cc0..1396fd87f 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -19,6 +19,8 @@ const internal_os = @import("../../os/main.zig"); const Config = configpkg.Config; const CoreApp = @import("../../App.zig"); const CoreSurface = @import("../../Surface.zig"); +const ColorScheme = @import("../../apprt.zig").ColorScheme; + const build_options = @import("build_options"); const Surface = @import("Surface.zig"); @@ -223,6 +225,25 @@ pub fn init(core_app: *CoreApp, opts: Options) !App { // https://gitlab.gnome.org/GNOME/glib/-/blob/bd2ccc2f69ecfd78ca3f34ab59e42e2b462bad65/gio/gapplication.c#L2302 c.g_application_activate(gapp); + const dbus_connection = c.g_application_get_dbus_connection(gapp); + if (dbus_connection == null) { + log.err("unable to get dbus connection", .{}); + return error.NoDBusConnection; + } + + _ = c.g_dbus_connection_signal_subscribe( + dbus_connection, + null, + "org.freedesktop.portal.Settings", + "SettingChanged", + "/org/freedesktop/portal/desktop", + "org.freedesktop.appearance", + c.G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE, + >kNotifyColorScheme, + core_app, + null, + ); + return .{ .core_app = core_app, .app = app, @@ -488,6 +509,90 @@ fn gtkActivate(app: *c.GtkApplication, ud: ?*anyopaque) callconv(.C) void { }, .{ .forever = {} }); } +/// Call a D-Bus method to determine the current color scheme. +pub fn getColorScheme(self: *App) ColorScheme { + const dbus_connection = c.g_application_get_dbus_connection(@ptrCast(self.app)); + + var err: ?*c.GError = null; + defer if (err) |e| c.g_error_free(e); + + const value = c.g_dbus_connection_call_sync( + dbus_connection, + "org.freedesktop.portal.Desktop", + "/org/freedesktop/portal/desktop", + "org.freedesktop.portal.Settings", + "ReadOne", + c.g_variant_new("(ss)", "org.freedesktop.appearance", "color-scheme"), + c.G_VARIANT_TYPE("(v)"), + c.G_DBUS_CALL_FLAGS_NONE, + -1, + null, + &err, + ) orelse { + if (err) |e| log.err("unable to get current color scheme: {s}", .{e.message}); + return .light; + }; + defer c.g_variant_unref(value); + + if (c.g_variant_is_of_type(value, c.G_VARIANT_TYPE("(v)")) == 1) { + var inner: ?*c.GVariant = null; + c.g_variant_get(value, "(v)", &inner); + defer c.g_variant_unref(inner); + if (c.g_variant_is_of_type(inner, c.G_VARIANT_TYPE("u")) == 1) { + return if (c.g_variant_get_uint32(inner) == 1) .dark else .light; + } + } + + return .light; +} + +/// This will be called by D-Bus when the style changes between light & dark. +fn gtkNotifyColorScheme( + _: ?*c.GDBusConnection, + _: [*c]const u8, + _: [*c]const u8, + _: [*c]const u8, + _: [*c]const u8, + parameters: ?*c.GVariant, + user_data: ?*anyopaque, +) callconv(.C) void { + const core_app: *CoreApp = @ptrCast(@alignCast(user_data orelse { + log.err("style change notification: userdata is null", .{}); + return; + })); + + if (c.g_variant_is_of_type(parameters, c.G_VARIANT_TYPE("(ssv)")) != 1) { + log.err("unexpected parameter type: {s}", .{c.g_variant_get_type_string(parameters)}); + return; + } + + var namespace: [*c]u8 = undefined; + var setting: [*c]u8 = undefined; + var value: *c.GVariant = undefined; + + c.g_variant_get(parameters, "(ssv)", &namespace, &setting, &value); + + defer c.g_free(namespace); + defer c.g_free(setting); + defer c.g_variant_unref(value); + + // ignore any setting changes that we aren't interested in + if (!std.mem.eql(u8, "org.freedesktop.appearance", std.mem.span(namespace))) return; + if (!std.mem.eql(u8, "color-scheme", std.mem.span(setting))) return; + + if (c.g_variant_is_of_type(value, c.G_VARIANT_TYPE("u")) != 1) { + log.err("unexpected value type: {s}", .{c.g_variant_get_type_string(value)}); + return; + } + + const color_scheme: ColorScheme = if (c.g_variant_get_uint32(value) == 1) .dark else .light; + for (core_app.surfaces.items) |surface| { + surface.core_surface.colorSchemeCallback(color_scheme) catch |err| { + log.err("unable to tell surface about color scheme change: {}", .{err}); + }; + } +} + fn gtkActionOpenConfig( _: *c.GSimpleAction, _: *c.GVariant, diff --git a/src/apprt/gtk/Surface.zig b/src/apprt/gtk/Surface.zig index 5ba615f96..c715866a0 100644 --- a/src/apprt/gtk/Surface.zig +++ b/src/apprt/gtk/Surface.zig @@ -418,6 +418,9 @@ fn realize(self: *Surface) !void { self.core_surface.setFontSize(size); } + // set the intial color scheme + self.core_surface.color_scheme = self.app.getColorScheme(); + // Note we're realized self.realized = true; } From d315223423c3c6800824cbd0ccf27a07d101dd5b Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 2 Feb 2024 20:00:10 -0800 Subject: [PATCH 2/2] apprt/gtk: small stylistic edits --- src/apprt/gtk/App.zig | 46 +++++++++++++++++++-------------------- src/apprt/gtk/Surface.zig | 4 ++-- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index 1396fd87f..622764d14 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -13,13 +13,13 @@ const App = @This(); const std = @import("std"); const assert = std.debug.assert; const builtin = @import("builtin"); +const apprt = @import("../../apprt.zig"); const configpkg = @import("../../config.zig"); const input = @import("../../input.zig"); const internal_os = @import("../../os/main.zig"); const Config = configpkg.Config; const CoreApp = @import("../../App.zig"); const CoreSurface = @import("../../Surface.zig"); -const ColorScheme = @import("../../apprt.zig").ColorScheme; const build_options = @import("build_options"); @@ -225,25 +225,22 @@ pub fn init(core_app: *CoreApp, opts: Options) !App { // https://gitlab.gnome.org/GNOME/glib/-/blob/bd2ccc2f69ecfd78ca3f34ab59e42e2b462bad65/gio/gapplication.c#L2302 c.g_application_activate(gapp); - const dbus_connection = c.g_application_get_dbus_connection(gapp); - if (dbus_connection == null) { - log.err("unable to get dbus connection", .{}); - return error.NoDBusConnection; + // Register for dbus events + if (c.g_application_get_dbus_connection(gapp)) |dbus_connection| { + _ = c.g_dbus_connection_signal_subscribe( + dbus_connection, + null, + "org.freedesktop.portal.Settings", + "SettingChanged", + "/org/freedesktop/portal/desktop", + "org.freedesktop.appearance", + c.G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE, + >kNotifyColorScheme, + core_app, + null, + ); } - _ = c.g_dbus_connection_signal_subscribe( - dbus_connection, - null, - "org.freedesktop.portal.Settings", - "SettingChanged", - "/org/freedesktop/portal/desktop", - "org.freedesktop.appearance", - c.G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE, - >kNotifyColorScheme, - core_app, - null, - ); - return .{ .core_app = core_app, .app = app, @@ -509,8 +506,9 @@ fn gtkActivate(app: *c.GtkApplication, ud: ?*anyopaque) callconv(.C) void { }, .{ .forever = {} }); } -/// Call a D-Bus method to determine the current color scheme. -pub fn getColorScheme(self: *App) ColorScheme { +/// Call a D-Bus method to determine the current color scheme. If there +/// is any error at any point we'll log the error and return "light" +pub fn getColorScheme(self: *App) apprt.ColorScheme { const dbus_connection = c.g_application_get_dbus_connection(@ptrCast(self.app)); var err: ?*c.GError = null; @@ -569,9 +567,7 @@ fn gtkNotifyColorScheme( var namespace: [*c]u8 = undefined; var setting: [*c]u8 = undefined; var value: *c.GVariant = undefined; - c.g_variant_get(parameters, "(ssv)", &namespace, &setting, &value); - defer c.g_free(namespace); defer c.g_free(setting); defer c.g_variant_unref(value); @@ -585,7 +581,11 @@ fn gtkNotifyColorScheme( return; } - const color_scheme: ColorScheme = if (c.g_variant_get_uint32(value) == 1) .dark else .light; + const color_scheme: apprt.ColorScheme = if (c.g_variant_get_uint32(value) == 1) + .dark + else + .light; + for (core_app.surfaces.items) |surface| { surface.core_surface.colorSchemeCallback(color_scheme) catch |err| { log.err("unable to tell surface about color scheme change: {}", .{err}); diff --git a/src/apprt/gtk/Surface.zig b/src/apprt/gtk/Surface.zig index c715866a0..d2235e010 100644 --- a/src/apprt/gtk/Surface.zig +++ b/src/apprt/gtk/Surface.zig @@ -418,8 +418,8 @@ fn realize(self: *Surface) !void { self.core_surface.setFontSize(size); } - // set the intial color scheme - self.core_surface.color_scheme = self.app.getColorScheme(); + // Set the intial color scheme + try self.core_surface.colorSchemeCallback(self.app.getColorScheme()); // Note we're realized self.realized = true;