diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index 6c506817b..9a9c2fb41 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -16,6 +16,7 @@ const builtin = @import("builtin"); const glfw = @import("glfw"); 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"); @@ -72,10 +73,16 @@ pub fn init(core_app: *CoreApp, opts: Options) !App { const cursor_none = c.gdk_cursor_new_from_name("none", null); errdefer if (cursor_none) |cursor| c.g_object_unref(cursor); + const single_instance = switch (config.@"gtk-single-instance") { + .true => true, + .false => false, + .desktop => internal_os.launchedFromDesktop(), + }; + // Setup the flags for our application. const app_flags: c.GApplicationFlags = app_flags: { var flags: c.GApplicationFlags = c.G_APPLICATION_DEFAULT_FLAGS; - if (!config.@"gtk-single-instance") flags |= c.G_APPLICATION_NON_UNIQUE; + if (!single_instance) flags |= c.G_APPLICATION_NON_UNIQUE; break :app_flags flags; }; @@ -88,6 +95,10 @@ pub fn init(core_app: *CoreApp, opts: Options) !App { }; // Create our GTK Application which encapsulates our process. + log.debug("creating GTK application id={s} single-instance={}", .{ + app_id, + single_instance, + }); const app = @as(?*c.GtkApplication, @ptrCast(c.gtk_application_new( app_id.ptr, app_flags, diff --git a/src/config/Config.zig b/src/config/Config.zig index 6d42516b6..1b6e8d84b 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -406,14 +406,19 @@ keybind: Keybinds = .{}, /// This does not work with GLFW builds. @"macos-option-as-alt": OptionAsAlt = .false, -/// If true (default), then the Ghostty GTK application will run in -/// single-instance mode: each new `ghostty` process launched will result -/// in a new window, if there is already a running process. +/// If true, the Ghostty GTK application will run in single-instance mode: +/// each new `ghostty` process launched will result in a new window if there +/// is already a running process. /// /// If false, each new ghostty process will launch a separate application. /// -/// Debug builds of Ghostty have a separate single-instance ID. -@"gtk-single-instance": bool = true, +/// The default value is "desktop" which will default to "true" if Ghostty +/// detects it was launched from the .desktop file such as an app launcher. +/// If Ghostty is launched from the command line, it will default to "false". +/// +/// Note that debug builds of Ghostty have a separate single-instance ID +/// so you can test single instance without conflicting with release builds. +@"gtk-single-instance": GtkSingleInstance = .desktop, /// If true (default), then the Ghostty GTK tabs will be "wide." Wide tabs /// are the new typical Gnome style where tabs fill their available space. @@ -1856,3 +1861,10 @@ pub const WindowTheme = enum { light, dark, }; + +/// See gtk-single-instance +pub const GtkSingleInstance = enum { + desktop, + false, + true, +};