mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-25 13:16:11 +03:00
Merge pull request #2338 from rolandpeelen/main
Add an equivalent to iTerm's "show/hide all windows" hotkey (Fix for: #2205)
This commit is contained in:
@ -508,6 +508,7 @@ typedef enum {
|
|||||||
GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW,
|
GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW,
|
||||||
GHOSTTY_ACTION_TOGGLE_WINDOW_DECORATIONS,
|
GHOSTTY_ACTION_TOGGLE_WINDOW_DECORATIONS,
|
||||||
GHOSTTY_ACTION_TOGGLE_QUICK_TERMINAL,
|
GHOSTTY_ACTION_TOGGLE_QUICK_TERMINAL,
|
||||||
|
GHOSTTY_ACTION_TOGGLE_VISIBILITY,
|
||||||
GHOSTTY_ACTION_GOTO_TAB,
|
GHOSTTY_ACTION_GOTO_TAB,
|
||||||
GHOSTTY_ACTION_GOTO_SPLIT,
|
GHOSTTY_ACTION_GOTO_SPLIT,
|
||||||
GHOSTTY_ACTION_RESIZE_SPLIT,
|
GHOSTTY_ACTION_RESIZE_SPLIT,
|
||||||
|
@ -86,6 +86,11 @@ class AppDelegate: NSObject,
|
|||||||
return ProcessInfo.processInfo.systemUptime - applicationLaunchTime
|
return ProcessInfo.processInfo.systemUptime - applicationLaunchTime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tracks whether the application is currently visible. This can be gamed, i.e. if a user manually
|
||||||
|
/// brings each window one by one to the front. But at worst its off by one set of toggles and this
|
||||||
|
/// makes our logic very easy.
|
||||||
|
private var isVisible: Bool = true
|
||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
terminalManager = TerminalManager(ghostty)
|
terminalManager = TerminalManager(ghostty)
|
||||||
updaterController = SPUStandardUpdaterController(
|
updaterController = SPUStandardUpdaterController(
|
||||||
@ -251,6 +256,7 @@ class AppDelegate: NSObject,
|
|||||||
// Ghostty will validate as well but we can avoid creating an entirely new
|
// Ghostty will validate as well but we can avoid creating an entirely new
|
||||||
// surface by doing our own validation here. We can also show a useful error
|
// surface by doing our own validation here. We can also show a useful error
|
||||||
// this way.
|
// this way.
|
||||||
|
|
||||||
var isDirectory = ObjCBool(true)
|
var isDirectory = ObjCBool(true)
|
||||||
guard FileManager.default.fileExists(atPath: filename, isDirectory: &isDirectory) else { return false }
|
guard FileManager.default.fileExists(atPath: filename, isDirectory: &isDirectory) else { return false }
|
||||||
|
|
||||||
@ -315,6 +321,7 @@ class AppDelegate: NSObject,
|
|||||||
syncMenuShortcut(action: "decrease_font_size:1", menuItem: self.menuDecreaseFontSize)
|
syncMenuShortcut(action: "decrease_font_size:1", menuItem: self.menuDecreaseFontSize)
|
||||||
syncMenuShortcut(action: "reset_font_size", menuItem: self.menuResetFontSize)
|
syncMenuShortcut(action: "reset_font_size", menuItem: self.menuResetFontSize)
|
||||||
syncMenuShortcut(action: "toggle_quick_terminal", menuItem: self.menuQuickTerminal)
|
syncMenuShortcut(action: "toggle_quick_terminal", menuItem: self.menuQuickTerminal)
|
||||||
|
syncMenuShortcut(action: "toggle_visibility", menuItem: self.menuQuickTerminal)
|
||||||
syncMenuShortcut(action: "inspector:toggle", menuItem: self.menuTerminalInspector)
|
syncMenuShortcut(action: "inspector:toggle", menuItem: self.menuTerminalInspector)
|
||||||
|
|
||||||
syncMenuShortcut(action: "toggle_secure_input", menuItem: self.menuSecureInput)
|
syncMenuShortcut(action: "toggle_secure_input", menuItem: self.menuSecureInput)
|
||||||
@ -564,4 +571,23 @@ class AppDelegate: NSObject,
|
|||||||
|
|
||||||
self.menuQuickTerminal?.state = if (quickController.visible) { .on } else { .off }
|
self.menuQuickTerminal?.state = if (quickController.visible) { .on } else { .off }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Toggles visibility of all Ghosty Terminal windows. When hidden, activates Ghostty as the frontmost application
|
||||||
|
@IBAction func toggleVisibility(_ sender: Any) {
|
||||||
|
// We only care about terminal windows.
|
||||||
|
for window in NSApp.windows.filter({ $0.windowController is BaseTerminalController }) {
|
||||||
|
if isVisible {
|
||||||
|
window.orderOut(nil)
|
||||||
|
} else {
|
||||||
|
window.makeKeyAndOrderFront(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// After bringing them all to front we make sure our app is active too.
|
||||||
|
if !isVisible {
|
||||||
|
NSApp.activate(ignoringOtherApps: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
isVisible.toggle()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,10 +217,16 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
<menuItem isSeparatorItem="YES" id="L3L-I8-sqk"/>
|
<menuItem isSeparatorItem="YES" id="L3L-I8-sqk"/>
|
||||||
<menuItem title="Quick Terminal" id="kvF-d2-JsP">
|
<menuItem title="Toggle Visibility" id="kvF-d2-JsP">
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="toggleQuickTerminal:" target="bbz-4X-AYv" id="gm3-mk-l8N"/>
|
<action selector="toggleVisibility" target="bbz-4X-AYv" id="RhV-3i-Xjz"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
<menuItem title="Quick Terminal" id="1pv-LF-NBJ">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="toggleQuickTerminal:" target="bbz-4X-AYv" id="qDV-sz-Agc"/>
|
||||||
</connections>
|
</connections>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
<menuItem isSeparatorItem="YES" id="bC9-n9-RbJ"/>
|
<menuItem isSeparatorItem="YES" id="bC9-n9-RbJ"/>
|
||||||
|
@ -490,6 +490,9 @@ extension Ghostty {
|
|||||||
case GHOSTTY_ACTION_TOGGLE_QUICK_TERMINAL:
|
case GHOSTTY_ACTION_TOGGLE_QUICK_TERMINAL:
|
||||||
toggleQuickTerminal(app, target: target)
|
toggleQuickTerminal(app, target: target)
|
||||||
|
|
||||||
|
case GHOSTTY_ACTION_TOGGLE_VISIBILITY:
|
||||||
|
toggleVisibility(app, target: target)
|
||||||
|
|
||||||
case GHOSTTY_ACTION_CLOSE_ALL_WINDOWS:
|
case GHOSTTY_ACTION_CLOSE_ALL_WINDOWS:
|
||||||
fallthrough
|
fallthrough
|
||||||
case GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW:
|
case GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW:
|
||||||
@ -630,6 +633,14 @@ extension Ghostty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static func toggleVisibility(
|
||||||
|
_ app: ghostty_app_t,
|
||||||
|
target: ghostty_target_s
|
||||||
|
) {
|
||||||
|
guard let appDelegate = NSApplication.shared.delegate as? AppDelegate else { return }
|
||||||
|
appDelegate.toggleVisibility(self)
|
||||||
|
}
|
||||||
|
|
||||||
private static func gotoTab(
|
private static func gotoTab(
|
||||||
_ app: ghostty_app_t,
|
_ app: ghostty_app_t,
|
||||||
target: ghostty_target_s,
|
target: ghostty_target_s,
|
||||||
|
@ -325,6 +325,7 @@ pub fn performAction(
|
|||||||
.reload_config => try self.reloadConfig(rt_app),
|
.reload_config => try self.reloadConfig(rt_app),
|
||||||
.close_all_windows => try rt_app.performAction(.app, .close_all_windows, {}),
|
.close_all_windows => try rt_app.performAction(.app, .close_all_windows, {}),
|
||||||
.toggle_quick_terminal => try rt_app.performAction(.app, .toggle_quick_terminal, {}),
|
.toggle_quick_terminal => try rt_app.performAction(.app, .toggle_quick_terminal, {}),
|
||||||
|
.toggle_visibility => try rt_app.performAction(.app, .toggle_visibility, {}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +96,9 @@ pub const Action = union(Key) {
|
|||||||
/// Toggle the quick terminal in or out.
|
/// Toggle the quick terminal in or out.
|
||||||
toggle_quick_terminal,
|
toggle_quick_terminal,
|
||||||
|
|
||||||
|
/// Toggle the visibility of all Ghostty terminal windows.
|
||||||
|
toggle_visibility,
|
||||||
|
|
||||||
/// Jump to a specific tab. Must handle the scenario that the tab
|
/// Jump to a specific tab. Must handle the scenario that the tab
|
||||||
/// value is invalid.
|
/// value is invalid.
|
||||||
goto_tab: GotoTab,
|
goto_tab: GotoTab,
|
||||||
@ -180,6 +183,7 @@ pub const Action = union(Key) {
|
|||||||
toggle_tab_overview,
|
toggle_tab_overview,
|
||||||
toggle_window_decorations,
|
toggle_window_decorations,
|
||||||
toggle_quick_terminal,
|
toggle_quick_terminal,
|
||||||
|
toggle_visibility,
|
||||||
goto_tab,
|
goto_tab,
|
||||||
goto_split,
|
goto_split,
|
||||||
resize_split,
|
resize_split,
|
||||||
|
@ -197,6 +197,7 @@ pub const App = struct {
|
|||||||
.toggle_tab_overview,
|
.toggle_tab_overview,
|
||||||
.toggle_window_decorations,
|
.toggle_window_decorations,
|
||||||
.toggle_quick_terminal,
|
.toggle_quick_terminal,
|
||||||
|
.toggle_visibility,
|
||||||
.goto_tab,
|
.goto_tab,
|
||||||
.inspector,
|
.inspector,
|
||||||
.render_inspector,
|
.render_inspector,
|
||||||
|
@ -389,6 +389,7 @@ pub fn performAction(
|
|||||||
.close_all_windows,
|
.close_all_windows,
|
||||||
.toggle_split_zoom,
|
.toggle_split_zoom,
|
||||||
.toggle_quick_terminal,
|
.toggle_quick_terminal,
|
||||||
|
.toggle_visibility,
|
||||||
.size_limit,
|
.size_limit,
|
||||||
.cell_size,
|
.cell_size,
|
||||||
.secure_input,
|
.secure_input,
|
||||||
|
@ -387,6 +387,13 @@ pub const Action = union(enum) {
|
|||||||
/// configuration file to customize its behavior.
|
/// configuration file to customize its behavior.
|
||||||
toggle_quick_terminal: void,
|
toggle_quick_terminal: void,
|
||||||
|
|
||||||
|
/// Show/hide all windows. If all windows become shown, we also ensure
|
||||||
|
/// Ghostty is focused.
|
||||||
|
///
|
||||||
|
/// This currently only works on macOS. When hiding all windows, we do
|
||||||
|
/// not yield focus to the previous application.
|
||||||
|
toggle_visibility: void,
|
||||||
|
|
||||||
/// Quit ghostty.
|
/// Quit ghostty.
|
||||||
quit: void,
|
quit: void,
|
||||||
|
|
||||||
@ -588,6 +595,7 @@ pub const Action = union(enum) {
|
|||||||
.close_all_windows,
|
.close_all_windows,
|
||||||
.quit,
|
.quit,
|
||||||
.toggle_quick_terminal,
|
.toggle_quick_terminal,
|
||||||
|
.toggle_visibility,
|
||||||
=> .app,
|
=> .app,
|
||||||
|
|
||||||
// These are app but can be special-cased in a surface context.
|
// These are app but can be special-cased in a surface context.
|
||||||
|
Reference in New Issue
Block a user