macOS: Add macos-dock-drop-folder-behavior (new tab or window) configuration option (#8114)

This PR adds a new configuration option
`macos-dock-drop-folder-behavior` that controls whether folders dropped
onto the Ghostty dock icon open in a new tab (default) or a new window.

## Changes

### Configuration Option Added
- **Option name**: `macos-dock-drop-folder-behavior`
- **Valid values**: 
  - `tab` (default) - Opens folders in a new tab in the main window
  - `window` - Opens folders in a new window
- **Platform**: macOS only

### Files Modified

1. **`src/config/Config.zig`**
- Added `MacOSDockDropFolderBehavior` enum with `tab` and `window`
values
   - Added configuration field with default value of `.tab`
   - Added documentation explaining the option

2. **`macos/Sources/Ghostty/Package.swift`**
   - Added `MacOSDockDropFolderBehavior` enum to match the Zig enum

3. **`macos/Sources/Ghostty/Ghostty.Config.swift`**
- Added `macosDockDropFolderBehavior` computed property to access the
configuration value from Swift

4. **`macos/Sources/App/macOS/AppDelegate.swift`**
- Modified `application(_:openFile:)` method to check the configuration
- When a folder is dropped on the dock icon, it now respects the user's
preference

## Usage

Add to your Ghostty configuration file:
```
macos-dock-drop-folder-behavior = window
```

## Motivation

This feature is useful for users (like me!) who prefer window-based
workflows over tab-based workflows when opening folders via drag and
drop on macOS.
push-lvtrmyqqqpkn
Mitchell Hashimoto 2025-08-21 10:55:04 -07:00 committed by GitHub
commit d725f2346f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 46 additions and 6 deletions

View File

@ -402,11 +402,9 @@ class AppDelegate: NSObject,
var config = Ghostty.SurfaceConfiguration()
if (isDirectory.boolValue) {
// When opening a directory, create a new tab in the main
// window with that as the working directory.
// If no windows exist, a new one will be created.
// When opening a directory, check the configuration to decide
// whether to open in a new tab or new window.
config.workingDirectory = filename
_ = TerminalController.newTab(ghostty, withBaseConfig: config)
} else {
// When opening a file, we want to execute the file. To do this, we
// don't override the command directly, because it won't load the
@ -418,8 +416,11 @@ class AppDelegate: NSObject,
// Set the parent directory to our working directory so that relative
// paths in scripts work.
config.workingDirectory = (filename as NSString).deletingLastPathComponent
_ = TerminalController.newWindow(ghostty, withBaseConfig: config)
}
switch ghostty.config.macosDockDropBehavior {
case .new_tab: _ = TerminalController.newTab(ghostty, withBaseConfig: config)
case .new_window: _ = TerminalController.newWindow(ghostty, withBaseConfig: config)
}
return true

View File

@ -282,6 +282,17 @@ extension Ghostty {
return MacOSTitlebarProxyIcon(rawValue: str) ?? defaultValue
}
var macosDockDropBehavior: MacDockDropBehavior {
let defaultValue = MacDockDropBehavior.new_tab
guard let config = self.config else { return defaultValue }
var v: UnsafePointer<Int8>? = nil
let key = "macos-dock-drop-behavior"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue }
guard let ptr = v else { return defaultValue }
let str = String(cString: ptr)
return MacDockDropBehavior(rawValue: str) ?? defaultValue
}
var macosWindowShadow: Bool {
guard let config = self.config else { return false }
var v = false;
@ -607,6 +618,11 @@ extension Ghostty.Config {
static let attention = BellFeatures(rawValue: 1 << 2)
static let title = BellFeatures(rawValue: 1 << 3)
}
enum MacDockDropBehavior: String {
case new_tab = "new-tab"
case new_window = "new-window"
}
enum MacHidden : String {
case never

View File

@ -2631,6 +2631,21 @@ keybind: Keybinds = .{},
/// editor, etc.
@"macos-titlebar-proxy-icon": MacTitlebarProxyIcon = .visible,
/// Controls the windowing behavior when dropping a file or folder
/// onto the Ghostty icon in the macOS dock.
///
/// Valid values are:
///
/// * `new-tab` - Create a new tab in the current window, or open
/// a new window if none exist.
/// * `new-window` - Create a new window unconditionally.
///
/// The default value is `new-tab`.
///
/// This setting is only supported on macOS and has no effect on other
/// platforms.
@"macos-dock-drop-behavior": MacOSDockDropBehavior = .@"new-tab",
/// macOS doesn't have a distinct "alt" key and instead has the "option"
/// key which behaves slightly differently. On macOS by default, the
/// option key plus a character will sometimes produce a Unicode character.
@ -7082,6 +7097,12 @@ pub const WindowNewTabPosition = enum {
end,
};
/// See macos-dock-drop-behavior
pub const MacOSDockDropBehavior = enum {
@"new-tab",
window,
};
/// See window-show-tab-bar
pub const WindowShowTabBar = enum {
always,

View File

@ -147,6 +147,8 @@ pub const FileFormatter = struct {
opts: std.fmt.FormatOptions,
writer: anytype,
) !void {
@setEvalBranchQuota(10_000);
_ = layout;
_ = opts;