From cadb960ef9b99b8c65af87eaed5fcdf6203dbf69 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 22 Sep 2024 21:57:17 -0700 Subject: [PATCH] core: slide terminal keybinding action --- macos/Sources/App/macOS/AppDelegate.swift | 21 +++++++++++++------ macos/Sources/App/macOS/MainMenu.xib | 8 +++++++ .../SlideTerminalController.swift | 9 ++++++++ src/Surface.zig | 6 ++++++ src/input/Binding.zig | 15 +++++++++++++ 5 files changed, 53 insertions(+), 6 deletions(-) diff --git a/macos/Sources/App/macOS/AppDelegate.swift b/macos/Sources/App/macOS/AppDelegate.swift index 1611541d1..47302f302 100644 --- a/macos/Sources/App/macOS/AppDelegate.swift +++ b/macos/Sources/App/macOS/AppDelegate.swift @@ -49,6 +49,7 @@ class AppDelegate: NSObject, @IBOutlet private var menuIncreaseFontSize: NSMenuItem? @IBOutlet private var menuDecreaseFontSize: NSMenuItem? @IBOutlet private var menuResetFontSize: NSMenuItem? + @IBOutlet private var menuSlideTerminal: NSMenuItem? @IBOutlet private var menuTerminalInspector: NSMenuItem? @IBOutlet private var menuEqualizeSplits: NSMenuItem? @@ -73,6 +74,9 @@ class AppDelegate: NSObject, /// Manages our terminal windows. let terminalManager: TerminalManager + /// Our slide terminal. This starts out uninitialized and only initializes if used. + private var slideController: SlideTerminalController? = nil + /// Manages updates let updaterController: SPUStandardUpdaterController let updaterDelegate: UpdaterDelegate = UpdaterDelegate() @@ -156,8 +160,6 @@ class AppDelegate: NSObject, center.delegate = self } - var foo: SlideTerminalController? = nil - func applicationDidBecomeActive(_ notification: Notification) { guard !applicationHasBecomeActive else { return } applicationHasBecomeActive = true @@ -167,11 +169,8 @@ class AppDelegate: NSObject, // - if we're opening a URL since `application(_:openFile:)` is called before this. // - if we're restoring from persisted state if terminalManager.windows.count == 0 { - //terminalManager.newWindow() + terminalManager.newWindow() } - - foo = SlideTerminalController(ghostty, baseConfig: nil) - foo?.showWindow(self) } func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { @@ -315,6 +314,7 @@ class AppDelegate: NSObject, syncMenuShortcut(action: "increase_font_size:1", menuItem: self.menuIncreaseFontSize) syncMenuShortcut(action: "decrease_font_size:1", menuItem: self.menuDecreaseFontSize) syncMenuShortcut(action: "reset_font_size", menuItem: self.menuResetFontSize) + syncMenuShortcut(action: "toggle_slide_terminal", menuItem: self.menuSlideTerminal) syncMenuShortcut(action: "inspector:toggle", menuItem: self.menuTerminalInspector) syncMenuShortcut(action: "toggle_secure_input", menuItem: self.menuSecureInput) @@ -550,4 +550,13 @@ class AppDelegate: NSObject, @IBAction func toggleSecureInput(_ sender: Any) { setSecureInput(.toggle) } + + @IBAction func toggleSlideTerminal(_ sender: Any) { + if slideController == nil { + slideController = SlideTerminalController(ghostty, baseConfig: nil) + } + + guard let slideController = self.slideController else { return } + slideController.slideToggle() + } } diff --git a/macos/Sources/App/macOS/MainMenu.xib b/macos/Sources/App/macOS/MainMenu.xib index beb411987..f19f9d1ed 100644 --- a/macos/Sources/App/macOS/MainMenu.xib +++ b/macos/Sources/App/macOS/MainMenu.xib @@ -42,6 +42,7 @@ + @@ -216,6 +217,13 @@ + + + + + + + diff --git a/macos/Sources/Features/SlideTerminal/SlideTerminalController.swift b/macos/Sources/Features/SlideTerminal/SlideTerminalController.swift index 12f785843..d1c4efc63 100644 --- a/macos/Sources/Features/SlideTerminal/SlideTerminalController.swift +++ b/macos/Sources/Features/SlideTerminal/SlideTerminalController.swift @@ -85,6 +85,15 @@ class SlideTerminalController: NSWindowController, NSWindowDelegate, TerminalVie // MARK: Slide Methods + func slideToggle() { + guard let window = self.window else { return } + if (window.alphaValue > 0) { + slideOut() + } else { + slideIn() + } + } + func slideIn() { guard let window = self.window else { return } slideWindowIn(window: window, from: position) diff --git a/src/Surface.zig b/src/Surface.zig index e8bbb885f..007f561e0 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -3856,6 +3856,12 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool .toggle, ), + .toggle_slide_terminal => { + if (@hasDecl(apprt.Surface, "toggleSlideTerminal")) { + self.rt_surface.toggleSlideTerminal(); + } else log.warn("runtime doesn't implement toggleSlideTerminal", .{}); + }, + .select_all => { const sel = self.io.terminal.screen.selectAll(); if (sel) |s| { diff --git a/src/input/Binding.zig b/src/input/Binding.zig index f9921a87e..73fb6aa47 100644 --- a/src/input/Binding.zig +++ b/src/input/Binding.zig @@ -363,6 +363,17 @@ pub const Action = union(enum) { /// This only works on macOS, since this is a system API on macOS. toggle_secure_input: void, + /// Toggle the "slide" terminal. The slide terminal is a terminal that + /// slides in from some screen edge, usually the top. This is useful for + /// quick access to a terminal without having to open a new window or tab. + /// + /// The slide terminal is a singleton; only one instance can exist at a + /// time. + /// + /// See the various configurations for the slide terminal in the + /// configuration file to customize its behavior. + toggle_slide_terminal: void, + /// Quit ghostty. quit: void, @@ -382,6 +393,10 @@ pub const Action = union(enum) { /// crash: CrashThread, + pub const SlideTerminalPosition = enum { + top, + }; + pub const CrashThread = enum { main, io,