mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-06 07:38:21 +00:00
macOS: support injecting temporary defaults when testing
This commit is contained in:
@@ -27,6 +27,8 @@ class GhosttyCustomConfigCase: XCTestCase {
|
||||
true
|
||||
}
|
||||
|
||||
static let defaultsSuiteName: String = "GHOSTTY_UI_TESTS"
|
||||
|
||||
var configFile: URL?
|
||||
override func setUpWithError() throws {
|
||||
continueAfterFailure = false
|
||||
@@ -47,13 +49,14 @@ class GhosttyCustomConfigCase: XCTestCase {
|
||||
try newConfig.write(to: configFile!, atomically: true, encoding: .utf8)
|
||||
}
|
||||
|
||||
func ghosttyApplication() throws -> XCUIApplication {
|
||||
func ghosttyApplication(defaultsSuite: String = GhosttyCustomConfigCase.defaultsSuiteName) throws -> XCUIApplication {
|
||||
let app = XCUIApplication()
|
||||
app.launchArguments.append(contentsOf: ["-ApplePersistenceIgnoreState", "YES"])
|
||||
guard let configFile else {
|
||||
return app
|
||||
}
|
||||
app.launchEnvironment["GHOSTTY_CONFIG_PATH"] = configFile.path
|
||||
app.launchEnvironment["GHOSTTY_USER_DEFAULTS_SUITE"] = defaultsSuite
|
||||
return app
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +175,15 @@ class AppDelegate: NSObject,
|
||||
// MARK: - NSApplicationDelegate
|
||||
|
||||
func applicationWillFinishLaunching(_ notification: Notification) {
|
||||
UserDefaults.standard.register(defaults: [
|
||||
#if DEBUG
|
||||
if
|
||||
let suite = UserDefaults.ghosttySuite,
|
||||
let clear = ProcessInfo.processInfo.environment["GHOSTTY_CLEAR_USER_DEFAULTS"],
|
||||
(clear as NSString).boolValue {
|
||||
UserDefaults.ghostty.removePersistentDomain(forName: suite)
|
||||
}
|
||||
#endif
|
||||
UserDefaults.ghostty.register(defaults: [
|
||||
// Disable the automatic full screen menu item because we handle
|
||||
// it manually.
|
||||
"NSFullScreenMenuItemEverywhere": false,
|
||||
@@ -194,7 +202,7 @@ class AppDelegate: NSObject,
|
||||
|
||||
func applicationDidFinishLaunching(_ notification: Notification) {
|
||||
// System settings overrides
|
||||
UserDefaults.standard.register(defaults: [
|
||||
UserDefaults.ghostty.register(defaults: [
|
||||
// Disable this so that repeated key events make it through to our terminal views.
|
||||
"ApplePressAndHoldEnabled": false,
|
||||
])
|
||||
@@ -203,7 +211,7 @@ class AppDelegate: NSObject,
|
||||
applicationLaunchTime = ProcessInfo.processInfo.systemUptime
|
||||
|
||||
// Check if secure input was enabled when we last quit.
|
||||
if UserDefaults.standard.bool(forKey: "SecureInput") != SecureInput.shared.enabled {
|
||||
if UserDefaults.ghostty.bool(forKey: "SecureInput") != SecureInput.shared.enabled {
|
||||
toggleSecureInput(self)
|
||||
}
|
||||
|
||||
@@ -747,10 +755,10 @@ class AppDelegate: NSObject,
|
||||
// configuration. This is the only way to carefully control whether macOS invokes the
|
||||
// state restoration system.
|
||||
switch config.windowSaveState {
|
||||
case "never": UserDefaults.standard.setValue(false, forKey: "NSQuitAlwaysKeepsWindows")
|
||||
case "always": UserDefaults.standard.setValue(true, forKey: "NSQuitAlwaysKeepsWindows")
|
||||
case "never": UserDefaults.ghostty.setValue(false, forKey: "NSQuitAlwaysKeepsWindows")
|
||||
case "always": UserDefaults.ghostty.setValue(true, forKey: "NSQuitAlwaysKeepsWindows")
|
||||
case "default": fallthrough
|
||||
default: UserDefaults.standard.removeObject(forKey: "NSQuitAlwaysKeepsWindows")
|
||||
default: UserDefaults.ghostty.removeObject(forKey: "NSQuitAlwaysKeepsWindows")
|
||||
}
|
||||
|
||||
// Sync our auto-update settings. If SUEnableAutomaticChecks (in our Info.plist) is
|
||||
@@ -835,9 +843,9 @@ class AppDelegate: NSObject,
|
||||
private func updateAppIcon(from config: Ghostty.Config) {
|
||||
// Since this is called after `DockTilePlugin` has been running,
|
||||
// clean it up here to trigger a correct update of the current config.
|
||||
UserDefaults.standard.removeObject(forKey: "CustomGhosttyIcon")
|
||||
UserDefaults.ghostty.removeObject(forKey: "CustomGhosttyIcon")
|
||||
DispatchQueue.global().async {
|
||||
UserDefaults.standard.appIcon = AppIcon(config: config)
|
||||
UserDefaults.ghostty.appIcon = AppIcon(config: config)
|
||||
DistributedNotificationCenter.default()
|
||||
.postNotificationName(.ghosttyIconDidChange, object: nil, userInfo: nil, deliverImmediately: true)
|
||||
}
|
||||
@@ -927,7 +935,7 @@ class AppDelegate: NSObject,
|
||||
input.global.toggle()
|
||||
}
|
||||
self.menuSecureInput?.state = if input.global { .on } else { .off }
|
||||
UserDefaults.standard.set(input.global, forKey: "SecureInput")
|
||||
UserDefaults.ghostty.set(input.global, forKey: "SecureInput")
|
||||
}
|
||||
|
||||
// MARK: - IB Actions
|
||||
@@ -1321,7 +1329,7 @@ extension AppDelegate {
|
||||
}
|
||||
|
||||
@IBAction func useAsDefault(_ sender: NSMenuItem) {
|
||||
let ud = UserDefaults.standard
|
||||
let ud = UserDefaults.ghostty
|
||||
let key = TerminalWindow.defaultLevelKey
|
||||
if menuFloatOnTop?.state == .on {
|
||||
ud.set(NSWindow.Level.floating, forKey: key)
|
||||
|
||||
@@ -171,7 +171,7 @@ class TerminalWindow: NSWindow {
|
||||
tab.accessoryView = stackView
|
||||
|
||||
// Get our saved level
|
||||
level = UserDefaults.standard.value(forKey: Self.defaultLevelKey) as? NSWindow.Level ?? .normal
|
||||
level = UserDefaults.ghostty.value(forKey: Self.defaultLevelKey) as? NSWindow.Level ?? .normal
|
||||
}
|
||||
|
||||
// Both of these must be true for windows without decorations to be able to
|
||||
|
||||
@@ -1070,7 +1070,7 @@ extension Ghostty {
|
||||
|
||||
// If the user has force click enabled then we do a quick look. There
|
||||
// is no public API for this as far as I can tell.
|
||||
guard UserDefaults.standard.bool(forKey: "com.apple.trackpad.forceClick") else { return }
|
||||
guard UserDefaults.ghostty.bool(forKey: "com.apple.trackpad.forceClick") else { return }
|
||||
quickLook(with: event)
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ extension NSScreen {
|
||||
// AND present on this screen.
|
||||
var hasDock: Bool {
|
||||
// If the dock autohides then we don't have a dock ever.
|
||||
if let dockAutohide = UserDefaults.standard.persistentDomain(forName: "com.apple.dock")?["autohide"] as? Bool {
|
||||
if let dockAutohide = UserDefaults.ghostty.persistentDomain(forName: "com.apple.dock")?["autohide"] as? Bool {
|
||||
if dockAutohide { return false }
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import Foundation
|
||||
|
||||
extension UserDefaults {
|
||||
static var ghosttySuite: String? {
|
||||
#if DEBUG
|
||||
ProcessInfo.processInfo.environment["GHOSTTY_USER_DEFAULTS_SUITE"]
|
||||
#else
|
||||
nil
|
||||
#endif
|
||||
}
|
||||
|
||||
static var ghostty: UserDefaults {
|
||||
ghosttySuite.flatMap(UserDefaults.init(suiteName:)) ?? .standard
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ class LastWindowPosition {
|
||||
guard let window, window.isVisible else { return false }
|
||||
let frame = window.frame
|
||||
let rect = [frame.origin.x, frame.origin.y, frame.size.width, frame.size.height]
|
||||
UserDefaults.standard.set(rect, forKey: positionKey)
|
||||
UserDefaults.ghostty.set(rect, forKey: positionKey)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ class LastWindowPosition {
|
||||
func restore(_ window: NSWindow, origin restoreOrigin: Bool = true, size restoreSize: Bool = true) -> Bool {
|
||||
guard restoreOrigin || restoreSize else { return false }
|
||||
|
||||
guard let values = UserDefaults.standard.array(forKey: positionKey) as? [Double],
|
||||
guard let values = UserDefaults.ghostty.array(forKey: positionKey) as? [Double],
|
||||
values.count >= 2 else { return false }
|
||||
|
||||
let lastPosition = CGPoint(x: values[0], y: values[1])
|
||||
|
||||
@@ -126,7 +126,7 @@ class PermissionRequest {
|
||||
/// - Parameter key: The UserDefaults key to check
|
||||
/// - Returns: The cached decision, or nil if no valid cached decision exists
|
||||
private static func getStoredResult(for key: String) -> Bool? {
|
||||
let userDefaults = UserDefaults.standard
|
||||
let userDefaults = UserDefaults.ghostty
|
||||
guard let data = userDefaults.data(forKey: key),
|
||||
let storedPermission = try? NSKeyedUnarchiver.unarchivedObject(
|
||||
ofClass: StoredPermission.self, from: data) else {
|
||||
@@ -151,7 +151,7 @@ class PermissionRequest {
|
||||
let expiryDate = Date().addingTimeInterval(duration.timeInterval)
|
||||
let storedPermission = StoredPermission(result: result, expiry: expiryDate)
|
||||
if let data = try? NSKeyedArchiver.archivedData(withRootObject: storedPermission, requiringSecureCoding: true) {
|
||||
let userDefaults = UserDefaults.standard
|
||||
let userDefaults = UserDefaults.ghostty
|
||||
userDefaults.set(data, forKey: key)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user