mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
gtk: request initial color scheme asynchronously
Requesting the initial color scheme on systems where the D-Bus interface is nonexistent would delay Ghostty startup by 1-2 minutes. That's not acceptable. Our color scheme events are already async-friendly anyway. Fixes #4632
This commit is contained in:

committed by
Mitchell Hashimoto

parent
e39745113a
commit
956bb8f02b
@ -73,6 +73,11 @@ clipboard_confirmation_window: ?*ClipboardConfirmationWindow = null,
|
|||||||
/// This is set to false when the main loop should exit.
|
/// This is set to false when the main loop should exit.
|
||||||
running: bool = true,
|
running: bool = true,
|
||||||
|
|
||||||
|
/// If we should retry querying D-Bus for the color scheme with the deprecated
|
||||||
|
/// Read method, instead of the recommended ReadOne method. This is kind of
|
||||||
|
/// nasty to have as struct state but its just a byte...
|
||||||
|
dbus_color_scheme_retry: bool = true,
|
||||||
|
|
||||||
/// The base path of the transient cgroup used to put all surfaces
|
/// The base path of the transient cgroup used to put all surfaces
|
||||||
/// into their own cgroup. This is only set if cgroups are enabled
|
/// into their own cgroup. This is only set if cgroups are enabled
|
||||||
/// and initialization was successful.
|
/// and initialization was successful.
|
||||||
@ -1271,7 +1276,8 @@ 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.
|
// Setup our D-Bus connection for listening to settings changes,
|
||||||
|
// and asynchronously request the initial color scheme
|
||||||
self.initDbus();
|
self.initDbus();
|
||||||
|
|
||||||
// Setup our menu items
|
// Setup our menu items
|
||||||
@ -1279,9 +1285,6 @@ pub fn run(self: *App) !void {
|
|||||||
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.
|
||||||
@ -1329,6 +1332,22 @@ fn initDbus(self: *App) void {
|
|||||||
self,
|
self,
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Request the initial color scheme asynchronously.
|
||||||
|
c.g_dbus_connection_call(
|
||||||
|
dbus,
|
||||||
|
"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,
|
||||||
|
dbusColorSchemeCallback,
|
||||||
|
self,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
@ -1566,61 +1585,37 @@ fn gtkWindowIsActive(
|
|||||||
core_app.focusEvent(false);
|
core_app.focusEvent(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call a D-Bus method to determine the current color scheme. If there
|
fn dbusColorSchemeCallback(
|
||||||
/// is any error at any point we'll log the error and return "light"
|
source_object: [*c]c.GObject,
|
||||||
pub fn getColorScheme(self: *App) apprt.ColorScheme {
|
res: ?*c.GAsyncResult,
|
||||||
const dbus_connection = c.g_application_get_dbus_connection(@ptrCast(self.app));
|
ud: ?*anyopaque,
|
||||||
|
) callconv(.C) void {
|
||||||
|
const self: *App = @ptrCast(@alignCast(ud.?));
|
||||||
|
const dbus: *c.GDBusConnection = @ptrCast(source_object);
|
||||||
|
|
||||||
var err: ?*c.GError = null;
|
var err: ?*c.GError = null;
|
||||||
defer if (err) |e| c.g_error_free(e);
|
defer if (err) |e| c.g_error_free(e);
|
||||||
|
|
||||||
const value = c.g_dbus_connection_call_sync(
|
if (c.g_dbus_connection_call_finish(dbus, res, &err)) |value| {
|
||||||
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| {
|
|
||||||
// If ReadOne is not yet implemented, fall back to deprecated "Read" method
|
|
||||||
// Error code: GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: No such method “ReadOne”
|
|
||||||
if (e.code == 19) {
|
|
||||||
return self.getColorSchemeDeprecated();
|
|
||||||
}
|
|
||||||
// Otherwise, log the error and return .light
|
|
||||||
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) {
|
if (c.g_variant_is_of_type(value, c.G_VARIANT_TYPE("(v)")) == 1) {
|
||||||
var inner: ?*c.GVariant = null;
|
var inner: ?*c.GVariant = null;
|
||||||
c.g_variant_get(value, "(v)", &inner);
|
c.g_variant_get(value, "(v)", &inner);
|
||||||
defer c.g_variant_unref(inner);
|
defer c.g_variant_unref(inner);
|
||||||
if (c.g_variant_is_of_type(inner, c.G_VARIANT_TYPE("u")) == 1) {
|
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;
|
self.colorSchemeEvent(if (c.g_variant_get_uint32(inner) == 1)
|
||||||
|
.dark
|
||||||
|
else
|
||||||
|
.light);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (err) |e| {
|
||||||
return .light;
|
// If ReadOne is not yet implemented, fall back to deprecated "Read" method
|
||||||
}
|
// Error code: GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: No such method “ReadOne”
|
||||||
|
if (self.dbus_color_scheme_retry and e.code == 19) {
|
||||||
/// Call the deprecated D-Bus "Read" method to determine the current color scheme. If
|
self.dbus_color_scheme_retry = false;
|
||||||
/// there is any error at any point we'll log the error and return "light"
|
c.g_dbus_connection_call(
|
||||||
fn getColorSchemeDeprecated(self: *App) apprt.ColorScheme {
|
dbus,
|
||||||
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/desktop",
|
"/org/freedesktop/portal/desktop",
|
||||||
"org.freedesktop.portal.Settings",
|
"org.freedesktop.portal.Settings",
|
||||||
@ -1630,29 +1625,18 @@ fn getColorSchemeDeprecated(self: *App) apprt.ColorScheme {
|
|||||||
c.G_DBUS_CALL_FLAGS_NONE,
|
c.G_DBUS_CALL_FLAGS_NONE,
|
||||||
-1,
|
-1,
|
||||||
null,
|
null,
|
||||||
&err,
|
dbusColorSchemeCallback,
|
||||||
) orelse {
|
self,
|
||||||
if (err) |e| log.err("Read method failed: {s}", .{e.message});
|
);
|
||||||
return .light;
|
return;
|
||||||
};
|
|
||||||
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 if (inner) |i| c.g_variant_unref(i);
|
|
||||||
|
|
||||||
if (inner) |i| {
|
|
||||||
const child = c.g_variant_get_child_value(i, 0) orelse {
|
|
||||||
return .light;
|
|
||||||
};
|
|
||||||
defer c.g_variant_unref(child);
|
|
||||||
|
|
||||||
const val = c.g_variant_get_uint32(child);
|
|
||||||
return if (val == 1) .dark else .light;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Otherwise, log the error and return .light
|
||||||
|
log.warn("unable to get current color scheme: {s}", .{e.message});
|
||||||
}
|
}
|
||||||
return .light;
|
|
||||||
|
// Fall back
|
||||||
|
self.colorSchemeEvent(.light);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This will be called by D-Bus when the style changes between light & dark.
|
/// This will be called by D-Bus when the style changes between light & dark.
|
||||||
|
@ -633,9 +633,6 @@ fn realize(self: *Surface) !void {
|
|||||||
try self.core_surface.setFontSize(size);
|
try self.core_surface.setFontSize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the initial color scheme
|
|
||||||
try self.core_surface.colorSchemeCallback(self.app.getColorScheme());
|
|
||||||
|
|
||||||
// Note we're realized
|
// Note we're realized
|
||||||
self.realized = true;
|
self.realized = true;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user