Merge pull request #2834 from ghostty-org/push-lzkskxmwylpx

apprt/gtk: update app color scheme state
This commit is contained in:
Mitchell Hashimoto
2024-11-26 20:04:32 -08:00
committed by GitHub

View File

@ -385,22 +385,6 @@ pub fn init(core_app: *CoreApp, opts: Options) !App {
if (config.@"initial-window") if (config.@"initial-window")
c.g_application_activate(gapp); c.g_application_activate(gapp);
// 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,
&gtkNotifyColorScheme,
core_app,
null,
);
}
// Internally, GTK ensures that only one instance of this provider exists in the provider list // Internally, GTK ensures that only one instance of this provider exists in the provider list
// for the display. // for the display.
const css_provider = c.gtk_css_provider_new(); const css_provider = c.gtk_css_provider_new();
@ -409,12 +393,6 @@ pub fn init(core_app: *CoreApp, opts: Options) !App {
@ptrCast(css_provider), @ptrCast(css_provider),
c.GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 3, c.GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 3,
); );
loadRuntimeCss(core_app.alloc, &config, css_provider) catch |err| switch (err) {
error.OutOfMemory => log.warn(
"out of memory loading runtime CSS, no runtime CSS applied",
.{},
),
};
return .{ return .{
.core_app = core_app, .core_app = core_app,
@ -831,14 +809,20 @@ fn configChange(
target: apprt.Target, target: apprt.Target,
new_config: *const Config, new_config: *const Config,
) void { ) void {
_ = new_config;
switch (target) { switch (target) {
// We don't do anything for surface config change events. There // We don't do anything for surface config change events. There
// is nothing to sync with regards to a surface today. // is nothing to sync with regards to a surface today.
.surface => {}, .surface => {},
.app => { .app => {
// We clone (to take ownership) and update our configuration.
if (new_config.clone(self.core_app.alloc)) |config_clone| {
self.config.deinit();
self.config = config_clone;
} else |err| {
log.warn("error cloning configuration err={}", .{err});
}
self.syncConfigChanges() catch |err| { self.syncConfigChanges() catch |err| {
log.warn("error handling configuration changes err={}", .{err}); log.warn("error handling configuration changes err={}", .{err});
}; };
@ -892,7 +876,7 @@ fn syncConfigChanges(self: *App) !void {
// Load our runtime CSS. If this fails then our window is just stuck // Load our runtime CSS. If this fails then our window is just stuck
// with the old CSS but we don't want to fail the entire sync operation. // with the old CSS but we don't want to fail the entire sync operation.
loadRuntimeCss(self.core_app.alloc, &self.config, self.css_provider) catch |err| switch (err) { self.loadRuntimeCss() catch |err| switch (err) {
error.OutOfMemory => log.warn( error.OutOfMemory => log.warn(
"out of memory loading runtime CSS, no runtime CSS applied", "out of memory loading runtime CSS, no runtime CSS applied",
.{}, .{},
@ -956,15 +940,14 @@ fn syncActionAccelerator(
} }
fn loadRuntimeCss( fn loadRuntimeCss(
alloc: Allocator, self: *const App,
config: *const Config,
provider: *c.GtkCssProvider,
) Allocator.Error!void { ) Allocator.Error!void {
var stack_alloc = std.heap.stackFallback(4096, alloc); var stack_alloc = std.heap.stackFallback(4096, self.core_app.alloc);
var buf = std.ArrayList(u8).init(stack_alloc.get()); var buf = std.ArrayList(u8).init(stack_alloc.get());
defer buf.deinit(); defer buf.deinit();
const writer = buf.writer(); const writer = buf.writer();
const config: *const Config = &self.config;
const window_theme = config.@"window-theme"; const window_theme = config.@"window-theme";
const unfocused_fill: Config.Color = config.@"unfocused-split-fill" orelse config.background; const unfocused_fill: Config.Color = config.@"unfocused-split-fill" orelse config.background;
const headerbar_background = config.background; const headerbar_background = config.background;
@ -1027,7 +1010,7 @@ fn loadRuntimeCss(
// Clears any previously loaded CSS from this provider // Clears any previously loaded CSS from this provider
c.gtk_css_provider_load_from_data( c.gtk_css_provider_load_from_data(
provider, self.css_provider,
buf.items.ptr, buf.items.ptr,
@intCast(buf.items.len), @intCast(buf.items.len),
); );
@ -1076,11 +1059,17 @@ pub fn run(self: *App) !void {
self.transient_cgroup_base = path; self.transient_cgroup_base = path;
} else log.debug("cgroup isolation disabled config={}", .{self.config.@"linux-cgroup"}); } else log.debug("cgroup isolation disabled config={}", .{self.config.@"linux-cgroup"});
// Setup our D-Bus connection for listening to settings changes.
self.initDbus();
// Setup our menu items // Setup our menu items
self.initActions(); self.initActions();
self.initMenu(); self.initMenu();
self.initContextMenu(); self.initContextMenu();
// Setup our initial color scheme
self.colorSchemeEvent(self.getColorScheme());
// On startup, we want to check for configuration errors right away // On startup, we want to check for configuration errors right away
// so we can show our error window. We also need to setup other initial // so we can show our error window. We also need to setup other initial
// state. // state.
@ -1114,6 +1103,26 @@ pub fn run(self: *App) !void {
} }
} }
fn initDbus(self: *App) void {
const dbus = c.g_application_get_dbus_connection(@ptrCast(self.app)) orelse {
log.warn("unable to get dbus connection, not setting up events", .{});
return;
};
_ = c.g_dbus_connection_signal_subscribe(
dbus,
null,
"org.freedesktop.portal.Settings",
"SettingChanged",
"/org/freedesktop/portal/desktop",
"org.freedesktop.appearance",
c.G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE,
&gtkNotifyColorScheme,
self,
null,
);
}
// This timeout function is started when no surfaces are open. It can be // This timeout function is started when no surfaces are open. It can be
// cancelled if a new surface is opened before the timer expires. // cancelled if a new surface is opened before the timer expires.
pub fn gtkQuitTimerExpired(ud: ?*anyopaque) callconv(.C) c.gboolean { pub fn gtkQuitTimerExpired(ud: ?*anyopaque) callconv(.C) c.gboolean {
@ -1394,7 +1403,7 @@ fn gtkNotifyColorScheme(
parameters: ?*c.GVariant, parameters: ?*c.GVariant,
user_data: ?*anyopaque, user_data: ?*anyopaque,
) callconv(.C) void { ) callconv(.C) void {
const core_app: *CoreApp = @ptrCast(@alignCast(user_data orelse { const self: *App = @ptrCast(@alignCast(user_data orelse {
log.err("style change notification: userdata is null", .{}); log.err("style change notification: userdata is null", .{});
return; return;
})); }));
@ -1426,9 +1435,20 @@ fn gtkNotifyColorScheme(
else else
.light; .light;
for (core_app.surfaces.items) |surface| { self.colorSchemeEvent(color_scheme);
surface.core_surface.colorSchemeCallback(color_scheme) catch |err| { }
log.err("unable to tell surface about color scheme change: {}", .{err});
fn colorSchemeEvent(
self: *App,
scheme: apprt.ColorScheme,
) void {
self.core_app.colorSchemeEvent(self, scheme) catch |err| {
log.err("error updating app color scheme err={}", .{err});
};
for (self.core_app.surfaces.items) |surface| {
surface.core_surface.colorSchemeCallback(scheme) catch |err| {
log.err("unable to tell surface about color scheme change err={}", .{err});
}; };
} }
} }