mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-05-05 23:43:00 +00:00
macos: add float on top feature for terminal windows (#7237)
Closes #5188 **See:** - https://github.com/ghostty-org/ghostty/discussions/5188#discussioncomment-12607781 - https://github.com/ghostty-org/ghostty/discussions/5188#discussioncomment-12984898
This commit is contained in:
commit
a6fd499019
@ -52,6 +52,8 @@ class AppDelegate: NSObject,
|
|||||||
@IBOutlet private var menuSelectSplitLeft: NSMenuItem?
|
@IBOutlet private var menuSelectSplitLeft: NSMenuItem?
|
||||||
@IBOutlet private var menuSelectSplitRight: NSMenuItem?
|
@IBOutlet private var menuSelectSplitRight: NSMenuItem?
|
||||||
@IBOutlet private var menuReturnToDefaultSize: NSMenuItem?
|
@IBOutlet private var menuReturnToDefaultSize: NSMenuItem?
|
||||||
|
@IBOutlet private var menuFloatOnTop: NSMenuItem?
|
||||||
|
@IBOutlet private var menuUseAsDefault: NSMenuItem?
|
||||||
|
|
||||||
@IBOutlet private var menuIncreaseFontSize: NSMenuItem?
|
@IBOutlet private var menuIncreaseFontSize: NSMenuItem?
|
||||||
@IBOutlet private var menuDecreaseFontSize: NSMenuItem?
|
@IBOutlet private var menuDecreaseFontSize: NSMenuItem?
|
||||||
@ -175,6 +177,12 @@ class AppDelegate: NSObject,
|
|||||||
handler: localEventHandler)
|
handler: localEventHandler)
|
||||||
|
|
||||||
// Notifications
|
// Notifications
|
||||||
|
NotificationCenter.default.addObserver(
|
||||||
|
self,
|
||||||
|
selector: #selector(windowDidBecomeKey),
|
||||||
|
name: NSWindow.didBecomeKeyNotification,
|
||||||
|
object: nil
|
||||||
|
)
|
||||||
NotificationCenter.default.addObserver(
|
NotificationCenter.default.addObserver(
|
||||||
self,
|
self,
|
||||||
selector: #selector(quickTerminalDidChangeVisibility),
|
selector: #selector(quickTerminalDidChangeVisibility),
|
||||||
@ -497,6 +505,16 @@ class AppDelegate: NSObject,
|
|||||||
return event
|
return event
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc private func windowDidBecomeKey(_ notification: Notification) {
|
||||||
|
guard let terminal = notification.object as? TerminalWindow else {
|
||||||
|
// If some other window became key we always turn this off
|
||||||
|
self.menuFloatOnTop?.state = .off
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.menuFloatOnTop?.state = terminal.level == .floating ? .on : .off
|
||||||
|
}
|
||||||
|
|
||||||
@objc private func quickTerminalDidChangeVisibility(_ notification: Notification) {
|
@objc private func quickTerminalDidChangeVisibility(_ notification: Notification) {
|
||||||
guard let quickController = notification.object as? QuickTerminalController else { return }
|
guard let quickController = notification.object as? QuickTerminalController else { return }
|
||||||
self.menuQuickTerminal?.state = if (quickController.visible) { .on } else { .off }
|
self.menuQuickTerminal?.state = if (quickController.visible) { .on } else { .off }
|
||||||
@ -844,6 +862,22 @@ class AppDelegate: NSObject,
|
|||||||
hiddenState = nil
|
hiddenState = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@IBAction func floatOnTop(_ menuItem: NSMenuItem) {
|
||||||
|
menuItem.state = menuItem.state == .on ? .off : .on
|
||||||
|
guard let window = NSApp.keyWindow else { return }
|
||||||
|
window.level = menuItem.state == .on ? .floating : .normal
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBAction func useAsDefault(_ sender: NSMenuItem) {
|
||||||
|
let ud = UserDefaults.standard
|
||||||
|
let key = TerminalWindow.defaultLevelKey
|
||||||
|
if (menuFloatOnTop?.state == .on) {
|
||||||
|
ud.set(NSWindow.Level.floating, forKey: key)
|
||||||
|
} else {
|
||||||
|
ud.removeObject(forKey: key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@IBAction func bringAllToFront(_ sender: Any) {
|
@IBAction func bringAllToFront(_ sender: Any) {
|
||||||
if !NSApp.isActive {
|
if !NSApp.isActive {
|
||||||
NSApp.activate(ignoringOtherApps: true)
|
NSApp.activate(ignoringOtherApps: true)
|
||||||
@ -899,3 +933,20 @@ class AppDelegate: NSObject,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: NSMenuItemValidation
|
||||||
|
|
||||||
|
extension AppDelegate: NSMenuItemValidation {
|
||||||
|
func validateMenuItem(_ item: NSMenuItem) -> Bool {
|
||||||
|
switch item.action {
|
||||||
|
case #selector(floatOnTop(_:)),
|
||||||
|
#selector(useAsDefault(_:)):
|
||||||
|
// Float on top items only active if the key window is a primary
|
||||||
|
// terminal window (not quick terminal).
|
||||||
|
return NSApp.keyWindow is TerminalWindow
|
||||||
|
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
<outlet property="menuCopy" destination="Jqf-pv-Zcu" id="bKd-1C-oy9"/>
|
<outlet property="menuCopy" destination="Jqf-pv-Zcu" id="bKd-1C-oy9"/>
|
||||||
<outlet property="menuDecreaseFontSize" destination="kzb-SZ-dOA" id="Y1B-Vh-6Z2"/>
|
<outlet property="menuDecreaseFontSize" destination="kzb-SZ-dOA" id="Y1B-Vh-6Z2"/>
|
||||||
<outlet property="menuEqualizeSplits" destination="3gH-VD-vL9" id="SiZ-ce-FOF"/>
|
<outlet property="menuEqualizeSplits" destination="3gH-VD-vL9" id="SiZ-ce-FOF"/>
|
||||||
|
<outlet property="menuFloatOnTop" destination="uRj-7z-1Nh" id="94n-o9-Jol"/>
|
||||||
<outlet property="menuIncreaseFontSize" destination="CIH-ey-Z6x" id="hkc-9C-80E"/>
|
<outlet property="menuIncreaseFontSize" destination="CIH-ey-Z6x" id="hkc-9C-80E"/>
|
||||||
<outlet property="menuMoveSplitDividerDown" destination="Zj7-2W-fdF" id="997-LL-nlN"/>
|
<outlet property="menuMoveSplitDividerDown" destination="Zj7-2W-fdF" id="997-LL-nlN"/>
|
||||||
<outlet property="menuMoveSplitDividerLeft" destination="wSR-ny-j1a" id="HCZ-CI-2ob"/>
|
<outlet property="menuMoveSplitDividerLeft" destination="wSR-ny-j1a" id="HCZ-CI-2ob"/>
|
||||||
@ -56,6 +57,7 @@
|
|||||||
<outlet property="menuTerminalInspector" destination="QwP-M5-fvh" id="wJi-Dh-S9f"/>
|
<outlet property="menuTerminalInspector" destination="QwP-M5-fvh" id="wJi-Dh-S9f"/>
|
||||||
<outlet property="menuToggleFullScreen" destination="8kY-Pi-KaY" id="yQg-6V-OO6"/>
|
<outlet property="menuToggleFullScreen" destination="8kY-Pi-KaY" id="yQg-6V-OO6"/>
|
||||||
<outlet property="menuToggleVisibility" destination="DOX-wA-ilh" id="iBj-Bc-2bq"/>
|
<outlet property="menuToggleVisibility" destination="DOX-wA-ilh" id="iBj-Bc-2bq"/>
|
||||||
|
<outlet property="menuUseAsDefault" destination="TrB-O8-g8H" id="af4-Jh-2HU"/>
|
||||||
<outlet property="menuZoomSplit" destination="oPd-mn-IEH" id="wTu-jK-egI"/>
|
<outlet property="menuZoomSplit" destination="oPd-mn-IEH" id="wTu-jK-egI"/>
|
||||||
</connections>
|
</connections>
|
||||||
</customObject>
|
</customObject>
|
||||||
@ -402,6 +404,19 @@
|
|||||||
<action selector="returnToDefaultSize:" target="-1" id="Bpt-GO-UU1"/>
|
<action selector="returnToDefaultSize:" target="-1" id="Bpt-GO-UU1"/>
|
||||||
</connections>
|
</connections>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
|
<menuItem isSeparatorItem="YES" id="Cm3-gn-vtj"/>
|
||||||
|
<menuItem title="Float on Top" id="uRj-7z-1Nh">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="floatOnTop:" target="bbz-4X-AYv" id="N58-PO-7pj"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
<menuItem title="Use as Default" id="TrB-O8-g8H">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="useAsDefault:" target="bbz-4X-AYv" id="RHA-Nl-L2U"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
<menuItem isSeparatorItem="YES" id="CpM-rI-Sc1"/>
|
<menuItem isSeparatorItem="YES" id="CpM-rI-Sc1"/>
|
||||||
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
|
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
class TerminalWindow: NSWindow {
|
class TerminalWindow: NSWindow {
|
||||||
|
/// This is the key in UserDefaults to use for the default `level` value.
|
||||||
|
static let defaultLevelKey: String = "TerminalDefaultLevel"
|
||||||
|
|
||||||
@objc dynamic var keyEquivalent: String = ""
|
@objc dynamic var keyEquivalent: String = ""
|
||||||
|
|
||||||
/// This is used to determine if certain elements should be drawn light or dark and should
|
/// This is used to determine if certain elements should be drawn light or dark and should
|
||||||
@ -63,6 +66,8 @@ class TerminalWindow: NSWindow {
|
|||||||
if titlebarTabs {
|
if titlebarTabs {
|
||||||
generateToolbar()
|
generateToolbar()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
level = UserDefaults.standard.value(forKey: Self.defaultLevelKey) as? NSWindow.Level ?? .normal
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user