From d03083c7f5ecb1ac8958382eeddba4a79861a5c7 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 29 Sep 2023 15:51:27 -0700 Subject: [PATCH] apprt/gtk: default working-directory to home if launched from desktop Fixes #573 --- src/config/Config.zig | 17 ++++++++++----- src/os/desktop.zig | 48 +++++++++++++++++++++++++++++++++++++++++++ src/os/main.zig | 1 + 3 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 src/os/desktop.zig diff --git a/src/config/Config.zig b/src/config/Config.zig index ba8544309..79a22c3d3 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -212,8 +212,10 @@ command: ?[]const u8 = null, /// The directory to change to after starting the command. /// /// The default is "inherit" except in special scenarios listed next. -/// If ghostty can detect it is launched on macOS from launchd -/// (double-clicked), then it defaults to "home". +/// On macOS, if Ghostty can detect it is launched from launchd +/// (double-clicked) or `open`, then it defaults to "home". +/// On Linux with GTK, if Ghostty can detect it was launched from +/// a desktop launcher, then it defaults to "home". /// /// The value of this must be an absolute value or one of the special /// values below: @@ -922,9 +924,14 @@ pub fn finalize(self: *Config) !void { } // The default for the working directory depends on the system. - const wd = self.@"working-directory" orelse switch (builtin.os.tag) { - .macos => if (c.getppid() == 1) "home" else "inherit", - else => "inherit", + const wd = self.@"working-directory" orelse wd: { + // If we have no working directory set, our default depends on + // whether we were launched from the desktop or CLI. + if (internal_os.launchedFromDesktop()) { + break :wd "home"; + } + + break :wd "inherit"; }; // If we are missing either a command or home directory, we need diff --git a/src/os/desktop.zig b/src/os/desktop.zig new file mode 100644 index 000000000..da78f454b --- /dev/null +++ b/src/os/desktop.zig @@ -0,0 +1,48 @@ +const std = @import("std"); +const builtin = @import("builtin"); +const build_config = @import("../build_config.zig"); + +const c = @cImport({ + @cInclude("unistd.h"); +}); + +/// Returns true if the program was launched from a desktop environment. +/// +/// On macOS, this returns true if the program was launched from Finder. +/// +/// On Linux GTK, this returns true if the program was launched using the +/// desktop file. This also includes when `gtk-launch` is used because I +/// can't find a way to distinguish the two scenarios. +/// +/// For other platforms and app runtimes, this returns false. +pub fn launchedFromDesktop() bool { + if (comptime build_config.artifact != .exe) return false; + + return switch (builtin.os.tag) { + // macOS apps launched from finder or `open` always have the init + // process as their parent. + .macos => c.getppid() == 1, + + // On Linux, GTK sets GIO_LAUNCHED_DESKTOP_FILE and + // GIO_LAUNCHED_DESKTOP_FILE_PID. We only check the latter to see if + // we match the PID and assume that if we do, we were launched from + // the desktop file. Pid comparing catches the scenario where + // another terminal was launched from a desktop file and then launches + // Ghostty and Ghostty inherits the env. + .linux => linux: { + const gio_pid_str = std.os.getenv("GIO_LAUNCHED_DESKTOP_FILE_PID") orelse + break :linux false; + + const pid = c.getpid(); + const gio_pid = std.fmt.parseInt( + @TypeOf(pid), + gio_pid_str, + 10, + ) catch break :linux false; + + break :linux gio_pid == pid; + }, + + else => @compileError("unsupported platform"), + }; +} diff --git a/src/os/main.zig b/src/os/main.zig index a9df1fca6..9b9b2d549 100644 --- a/src/os/main.zig +++ b/src/os/main.zig @@ -2,6 +2,7 @@ //! system. pub usingnamespace @import("env.zig"); +pub usingnamespace @import("desktop.zig"); pub usingnamespace @import("file.zig"); pub usingnamespace @import("flatpak.zig"); pub usingnamespace @import("homedir.zig");