Add quick-terminal-space-behavior option

This commit is contained in:
Soh Satoh
2024-12-31 21:55:03 +09:00
committed by Mitchell Hashimoto
parent 2206c509be
commit e2523c25cb
5 changed files with 106 additions and 2 deletions

View File

@ -102,6 +102,7 @@
C159E89D2B69A2EF00FDFE9C /* OSColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */; };
C1F26EA72B738B9900404083 /* NSView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1F26EA62B738B9900404083 /* NSView+Extension.swift */; };
C1F26EE92B76CBFC00404083 /* VibrantLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = C1F26EE82B76CBFC00404083 /* VibrantLayer.m */; };
CFBB5FEA2D231E5000FD62EE /* QuickTerminalSpaceBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFBB5FE92D231E5000FD62EE /* QuickTerminalSpaceBehavior.swift */; };
FC5218FA2D10FFCE004C93E0 /* zsh in Resources */ = {isa = PBXBuildFile; fileRef = FC5218F92D10FFC7004C93E0 /* zsh */; };
FC9ABA9C2D0F53F80020D4C8 /* bash-completion in Resources */ = {isa = PBXBuildFile; fileRef = FC9ABA9B2D0F538D0020D4C8 /* bash-completion */; };
/* End PBXBuildFile section */
@ -198,6 +199,7 @@
C1F26EE72B76CBFC00404083 /* VibrantLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VibrantLayer.h; sourceTree = "<group>"; };
C1F26EE82B76CBFC00404083 /* VibrantLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VibrantLayer.m; sourceTree = "<group>"; };
C1F26EEA2B76CC2400404083 /* ghostty-bridging-header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ghostty-bridging-header.h"; sourceTree = "<group>"; };
CFBB5FE92D231E5000FD62EE /* QuickTerminalSpaceBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickTerminalSpaceBehavior.swift; sourceTree = "<group>"; };
FC5218F92D10FFC7004C93E0 /* zsh */ = {isa = PBXFileReference; lastKnownFileType = folder; name = zsh; path = "../zig-out/share/zsh"; sourceTree = "<group>"; };
FC9ABA9B2D0F538D0020D4C8 /* bash-completion */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "bash-completion"; path = "../zig-out/share/bash-completion"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -448,6 +450,7 @@
children = (
A5CBD05B2CA0C5C70017A1AE /* QuickTerminal.xib */,
A5CBD05D2CA0C5E70017A1AE /* QuickTerminalController.swift */,
CFBB5FE92D231E5000FD62EE /* QuickTerminalSpaceBehavior.swift */,
A5CBD0632CA122E70017A1AE /* QuickTerminalPosition.swift */,
A52FFF562CA90481000C6A5B /* QuickTerminalScreen.swift */,
A5CBD05F2CA0C9080017A1AE /* QuickTerminalWindow.swift */,
@ -616,6 +619,7 @@
A54B0CEB2D0CFB4C00CBEFF8 /* NSImage+Extension.swift in Sources */,
A54D786C2CA7978E001B19B1 /* BaseTerminalController.swift in Sources */,
A59FB5CF2AE0DB50009128F3 /* InspectorView.swift in Sources */,
CFBB5FEA2D231E5000FD62EE /* QuickTerminalSpaceBehavior.swift in Sources */,
A54B0CE92D0CECD100CBEFF8 /* ColorizedGhosttyIconView.swift in Sources */,
A5D0AF3D2B37804400D21823 /* CodableBridge.swift in Sources */,
A5D0AF3B2B36A1DE00D21823 /* TerminalRestorable.swift in Sources */,

View File

@ -3,6 +3,12 @@ import Cocoa
import SwiftUI
import GhosttyKit
// This is a Apple's private function that we need to call to get the active space.
@_silgen_name("CGSGetActiveSpace")
func CGSGetActiveSpace(_ cid: Int) -> size_t
@_silgen_name("CGSMainConnectionID")
func CGSMainConnectionID() -> Int
/// Controller for the "quick" terminal.
class QuickTerminalController: BaseTerminalController {
override var windowNibName: NSNib.Name? { "QuickTerminal" }
@ -18,6 +24,9 @@ class QuickTerminalController: BaseTerminalController {
/// application to the front.
private var previousApp: NSRunningApplication? = nil
// The active space when the quick terminal was last shown.
private var previousActiveSpace: size_t = 0
/// The configuration derived from the Ghostty config so we don't need to rely on references.
private var derivedConfig: DerivedConfig
@ -81,6 +90,9 @@ class QuickTerminalController: BaseTerminalController {
delegate: self
))
// Change the collection behavior of the window depending on the configuration.
window.collectionBehavior = derivedConfig.quickTerminalSpaceBehavior.collectionBehavior
// Animate the window in
animateIn()
}
@ -107,8 +119,27 @@ class QuickTerminalController: BaseTerminalController {
self.previousApp = nil
}
if (derivedConfig.quickTerminalAutoHide) {
animateOut()
if derivedConfig.quickTerminalAutoHide {
switch derivedConfig.quickTerminalSpaceBehavior {
case .remain:
if self.window?.isOnActiveSpace == true {
// If we lose focus on the active space, then we can animate out
animateOut()
}
case .move:
// Check if the reason for losing focus is due to an active space change
let currentActiveSpace = CGSGetActiveSpace(CGSMainConnectionID())
if previousActiveSpace == currentActiveSpace {
// If we lose focus on the active space, then we can animate out
animateOut()
} else {
// If we're from different space, then we bring the window back
DispatchQueue.main.async {
self.window?.makeKeyAndOrderFront(nil)
}
}
self.previousActiveSpace = currentActiveSpace
}
}
}
@ -163,6 +194,9 @@ class QuickTerminalController: BaseTerminalController {
}
}
// Set previous active space
self.previousActiveSpace = CGSGetActiveSpace(CGSMainConnectionID())
// Animate the window in
animateWindowIn(window: window, from: position)
@ -390,12 +424,16 @@ class QuickTerminalController: BaseTerminalController {
self.derivedConfig = DerivedConfig(config)
syncAppearance()
// Update window.collectionBehavior
self.window?.collectionBehavior = derivedConfig.quickTerminalSpaceBehavior.collectionBehavior
}
private struct DerivedConfig {
let quickTerminalScreen: QuickTerminalScreen
let quickTerminalAnimationDuration: Double
let quickTerminalAutoHide: Bool
let quickTerminalSpaceBehavior: QuickTerminalSpaceBehavior
let windowColorspace: String
let backgroundOpacity: Double
@ -403,6 +441,7 @@ class QuickTerminalController: BaseTerminalController {
self.quickTerminalScreen = .main
self.quickTerminalAnimationDuration = 0.2
self.quickTerminalAutoHide = true
self.quickTerminalSpaceBehavior = .move
self.windowColorspace = ""
self.backgroundOpacity = 1.0
}
@ -411,6 +450,7 @@ class QuickTerminalController: BaseTerminalController {
self.quickTerminalScreen = config.quickTerminalScreen
self.quickTerminalAnimationDuration = config.quickTerminalAnimationDuration
self.quickTerminalAutoHide = config.quickTerminalAutoHide
self.quickTerminalSpaceBehavior = config.quickTerminalSpaceBehavior
self.windowColorspace = config.windowColorspace
self.backgroundOpacity = config.backgroundOpacity
}

View File

@ -0,0 +1,36 @@
import Foundation
import Cocoa
enum QuickTerminalSpaceBehavior {
case remain
case move
init?(fromGhosttyConfig string: String) {
switch (string) {
case "move":
self = .move
case "remain":
self = .remain
default:
return nil
}
}
var collectionBehavior: NSWindow.CollectionBehavior {
let commonBehavior: [NSWindow.CollectionBehavior] = [
.ignoresCycle,
.fullScreenAuxiliary
]
switch (self) {
case .move:
// We want this to be part of every space because it is a singleton.
return NSWindow.CollectionBehavior([.canJoinAllSpaces] + commonBehavior)
case .remain:
// We want this to move the window to the active space.
return NSWindow.CollectionBehavior([.moveToActiveSpace] + commonBehavior)
}
}
}

View File

@ -431,6 +431,16 @@ extension Ghostty {
_ = ghostty_config_get(config, &v, key, UInt(key.count))
return v
}
var quickTerminalSpaceBehavior: QuickTerminalSpaceBehavior {
guard let config = self.config else { return .move }
var v: UnsafePointer<Int8>? = nil
let key = "quick-terminal-space-behavior"
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return .move }
guard let ptr = v else { return .move }
let str = String(cString: ptr)
return QuickTerminalSpaceBehavior(fromGhosttyConfig: str) ?? .move
}
#endif
var resizeOverlay: ResizeOverlay {

View File

@ -1567,6 +1567,14 @@ keybind: Keybinds = .{},
/// Set it to false for the quick terminal to remain open even when it loses focus.
@"quick-terminal-autohide": bool = true,
/// This configuration option determines the behavior of the quick terminal
/// when switching between spaces. If set to `move`, the quick terminal
/// will stay only in the space where it was originally opened and will not
/// follow when switching to another space. If set to `remain`, the quick terminal
/// will remain open and visible across all spaces, including after moving to
/// a different space.
@"quick-terminal-space-behavior": QuickTerminalSpaceBehavior = .move,
/// Whether to enable shell integration auto-injection or not. Shell integration
/// greatly enhances the terminal experience by enabling a number of features:
///
@ -5695,6 +5703,12 @@ pub const QuickTerminalScreen = enum {
@"macos-menu-bar",
};
// See quick-terminal-space-behavior
pub const QuickTerminalSpaceBehavior = enum {
remain,
move,
};
/// See grapheme-width-method
pub const GraphemeWidthMethod = enum {
legacy,