From 8a816dc5ef328472b443f22160dd1c902b1c623d Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 6 Jan 2024 12:30:44 -0800 Subject: [PATCH 1/2] os: mac app launched with bundle env var is treated as desktop launch --- src/os/desktop.zig | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/os/desktop.zig b/src/os/desktop.zig index ed4f977d9..6475c278e 100644 --- a/src/os/desktop.zig +++ b/src/os/desktop.zig @@ -19,7 +19,15 @@ pub fn launchedFromDesktop() bool { return switch (builtin.os.tag) { // macOS apps launched from finder or `open` always have the init // process as their parent. - .macos => c.getppid() == 1, + .macos => macos: { + // This special case is so that if we launch the app via the + // app bundle (i.e. via open) then we still treat it as if it + // was launched from the desktop. + if (build_config.artifact == .lib and + std.os.getenv("GHOSTTY_MAC_APP") != null) break :macos true; + + break :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 From d65fbba39e57f723fa6a93c393768b9c9dd2d60a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 6 Jan 2024 12:31:01 -0800 Subject: [PATCH 2/2] config: do not load command from SHELL when launched from desktop Fixes #139 From the issue: Looking into this now, I think I figured out the broken logic. When launching from open, the parent process of Ghostty is launchd which appears to set your SHELL env var to your configured shell when logging in. That's why a restart fixes it. However, I believe directory services (the macOS equivalent to /etc/passwd) is updated in real time. Ghostty does read directory services but at a lower priority than SHELL. This logic makes sense for CLI-launched terminals but not desktop-launched. From a CLI you want the terminal you're launching to probably inherit the shell from the CLI you launched it from. (Note that using open explicitly forces a launchd-style launch so it quacks as if it was double-clicked on the desktop). In conclusion, I believe the correct logic is to invert the priority on SHELL vs directory services when Ghostty detects it was launched from launchd. We already have this detection logic in Ghostty because we use it for a number of other things as well, so this should be easy to fix. I'll work on it later today. --- src/config/Config.zig | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/config/Config.zig b/src/config/Config.zig index 025d09412..9881580b9 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -1674,16 +1674,22 @@ pub fn finalize(self: *Config) !void { // set to /bin/sh. if (self.command) |cmd| log.info("shell src=config value={s}", .{cmd}) - else { - if (!internal_os.isFlatpak()) { - if (std.process.getEnvVarOwned(alloc, "SHELL")) |value| { - log.info("default shell source=env value={s}", .{value}); - self.command = value; + else shell_env: { + // Flatpak always gets its shell from outside the sandbox + if (internal_os.isFlatpak()) break :shell_env; - // If we don't need the working directory, then we can exit now. - if (!wd_home) break :command; - } else |_| {} - } + // If we were launched from the desktop, our SHELL env var + // will represent our SHELL at login time. We want to use the + // latest shell from /etc/passwd or directory services. + if (internal_os.launchedFromDesktop()) break :shell_env; + + if (std.process.getEnvVarOwned(alloc, "SHELL")) |value| { + log.info("default shell source=env value={s}", .{value}); + self.command = value; + + // If we don't need the working directory, then we can exit now. + if (!wd_home) break :command; + } else |_| {} } switch (builtin.os.tag) {