mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-09-06 03:18:19 +00:00
macos: menu item symbols for Tahoe
This is recommended for macOS Tahoe and all standard menu items now have associated images. This makes our app look more polished and native for macOS Tahoe. For icon choice, I tried to copy other native macOS apps as much as possible, mostly from Xcode. It looks like a lot of apps aren't updated yet. I'm absolutely open to suggestions for better icons but I think these are a good starting point. One menu change is I moved "reset font size" above "increase font size" which better matches other apps (e.g. Terminal.app).
This commit is contained in:
@@ -93,6 +93,7 @@
|
|||||||
A5A6F72A2CC41B8900B232A5 /* AppInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A6F7292CC41B8700B232A5 /* AppInfo.swift */; };
|
A5A6F72A2CC41B8900B232A5 /* AppInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A6F7292CC41B8700B232A5 /* AppInfo.swift */; };
|
||||||
A5AEB1652D5BE7D000513529 /* LastWindowPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5AEB1642D5BE7BF00513529 /* LastWindowPosition.swift */; };
|
A5AEB1652D5BE7D000513529 /* LastWindowPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5AEB1642D5BE7BF00513529 /* LastWindowPosition.swift */; };
|
||||||
A5B30539299BEAAB0047F10C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A5B30538299BEAAB0047F10C /* Assets.xcassets */; };
|
A5B30539299BEAAB0047F10C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A5B30538299BEAAB0047F10C /* Assets.xcassets */; };
|
||||||
|
A5B4EA852DFE691B0022C3A2 /* NSMenuItem+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B4EA842DFE69140022C3A2 /* NSMenuItem+Extension.swift */; };
|
||||||
A5CA378C2D2A4DEB00931030 /* KeyboardLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CA378B2D2A4DE800931030 /* KeyboardLayout.swift */; };
|
A5CA378C2D2A4DEB00931030 /* KeyboardLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CA378B2D2A4DE800931030 /* KeyboardLayout.swift */; };
|
||||||
A5CA378E2D31D6C300931030 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CA378D2D31D6C100931030 /* Weak.swift */; };
|
A5CA378E2D31D6C300931030 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CA378D2D31D6C100931030 /* Weak.swift */; };
|
||||||
A5CBD0562C9E65B80017A1AE /* DraggableWindowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CBD0552C9E65A50017A1AE /* DraggableWindowView.swift */; };
|
A5CBD0562C9E65B80017A1AE /* DraggableWindowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CBD0552C9E65A50017A1AE /* DraggableWindowView.swift */; };
|
||||||
@@ -210,6 +211,7 @@
|
|||||||
A5B30531299BEAAA0047F10C /* Ghostty.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Ghostty.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
A5B30531299BEAAA0047F10C /* Ghostty.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Ghostty.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
A5B30538299BEAAB0047F10C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
A5B30538299BEAAB0047F10C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
A5B3053D299BEAAB0047F10C /* Ghostty.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Ghostty.entitlements; sourceTree = "<group>"; };
|
A5B3053D299BEAAB0047F10C /* Ghostty.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Ghostty.entitlements; sourceTree = "<group>"; };
|
||||||
|
A5B4EA842DFE69140022C3A2 /* NSMenuItem+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSMenuItem+Extension.swift"; sourceTree = "<group>"; };
|
||||||
A5CA378B2D2A4DE800931030 /* KeyboardLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardLayout.swift; sourceTree = "<group>"; };
|
A5CA378B2D2A4DE800931030 /* KeyboardLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardLayout.swift; sourceTree = "<group>"; };
|
||||||
A5CA378D2D31D6C100931030 /* Weak.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; };
|
A5CA378D2D31D6C100931030 /* Weak.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = "<group>"; };
|
||||||
A5CBD0552C9E65A50017A1AE /* DraggableWindowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraggableWindowView.swift; sourceTree = "<group>"; };
|
A5CBD0552C9E65A50017A1AE /* DraggableWindowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraggableWindowView.swift; sourceTree = "<group>"; };
|
||||||
@@ -478,6 +480,7 @@
|
|||||||
A599CDAF2CF103F20049FA26 /* NSAppearance+Extension.swift */,
|
A599CDAF2CF103F20049FA26 /* NSAppearance+Extension.swift */,
|
||||||
A5A2A3CB2D444AB80033CF96 /* NSApplication+Extension.swift */,
|
A5A2A3CB2D444AB80033CF96 /* NSApplication+Extension.swift */,
|
||||||
A54B0CEA2D0CFB4A00CBEFF8 /* NSImage+Extension.swift */,
|
A54B0CEA2D0CFB4A00CBEFF8 /* NSImage+Extension.swift */,
|
||||||
|
A5B4EA842DFE69140022C3A2 /* NSMenuItem+Extension.swift */,
|
||||||
A52FFF5C2CAB4D05000C6A5B /* NSScreen+Extension.swift */,
|
A52FFF5C2CAB4D05000C6A5B /* NSScreen+Extension.swift */,
|
||||||
AEE8B3442B9AA39600260C5E /* NSPasteboard+Extension.swift */,
|
AEE8B3442B9AA39600260C5E /* NSPasteboard+Extension.swift */,
|
||||||
C1F26EA62B738B9900404083 /* NSView+Extension.swift */,
|
C1F26EA62B738B9900404083 /* NSView+Extension.swift */,
|
||||||
@@ -763,6 +766,7 @@
|
|||||||
A5CDF1952AAFA19600513312 /* ConfigurationErrorsView.swift in Sources */,
|
A5CDF1952AAFA19600513312 /* ConfigurationErrorsView.swift in Sources */,
|
||||||
A55B7BBC29B6FC330055DE60 /* SurfaceView.swift in Sources */,
|
A55B7BBC29B6FC330055DE60 /* SurfaceView.swift in Sources */,
|
||||||
A5333E1C2B5A1CE3008AEFF7 /* CrossKit.swift in Sources */,
|
A5333E1C2B5A1CE3008AEFF7 /* CrossKit.swift in Sources */,
|
||||||
|
A5B4EA852DFE691B0022C3A2 /* NSMenuItem+Extension.swift in Sources */,
|
||||||
A5874D992DAD751B00E83852 /* CGS.swift in Sources */,
|
A5874D992DAD751B00E83852 /* CGS.swift in Sources */,
|
||||||
A586366B2DF0A98C00E04A10 /* Array+Extension.swift in Sources */,
|
A586366B2DF0A98C00E04A10 /* Array+Extension.swift in Sources */,
|
||||||
A51544FE2DFB111C009E85D8 /* TitlebarTabsTahoeTerminalWindow.swift in Sources */,
|
A51544FE2DFB111C009E85D8 /* TitlebarTabsTahoeTerminalWindow.swift in Sources */,
|
||||||
|
@@ -242,6 +242,9 @@ class AppDelegate: NSObject,
|
|||||||
|
|
||||||
ghostty_app_set_color_scheme(app, scheme)
|
ghostty_app_set_color_scheme(app, scheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup our menu
|
||||||
|
setupMenuImages()
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationDidBecomeActive(_ notification: Notification) {
|
func applicationDidBecomeActive(_ notification: Notification) {
|
||||||
@@ -392,6 +395,41 @@ class AppDelegate: NSObject,
|
|||||||
return dockMenu
|
return dockMenu
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Setup all the images for our menu items.
|
||||||
|
private func setupMenuImages() {
|
||||||
|
// Note: This COULD Be done all in the xib file, but I find it easier to
|
||||||
|
// modify this stuff as code.
|
||||||
|
self.menuNewWindow?.setImageIfDesired(systemSymbolName: "macwindow.badge.plus")
|
||||||
|
self.menuNewTab?.setImageIfDesired(systemSymbolName: "macwindow")
|
||||||
|
self.menuSplitRight?.setImageIfDesired(systemSymbolName: "rectangle.righthalf.inset.filled")
|
||||||
|
self.menuSplitLeft?.setImageIfDesired(systemSymbolName: "rectangle.leadinghalf.inset.filled")
|
||||||
|
self.menuSplitUp?.setImageIfDesired(systemSymbolName: "rectangle.tophalf.inset.filled")
|
||||||
|
self.menuSplitDown?.setImageIfDesired(systemSymbolName: "rectangle.bottomhalf.inset.filled")
|
||||||
|
self.menuClose?.setImageIfDesired(systemSymbolName: "xmark")
|
||||||
|
self.menuIncreaseFontSize?.setImageIfDesired(systemSymbolName: "textformat.size.larger")
|
||||||
|
self.menuResetFontSize?.setImageIfDesired(systemSymbolName: "textformat.size")
|
||||||
|
self.menuDecreaseFontSize?.setImageIfDesired(systemSymbolName: "textformat.size.smaller")
|
||||||
|
self.menuCommandPalette?.setImageIfDesired(systemSymbolName: "filemenu.and.selection")
|
||||||
|
self.menuQuickTerminal?.setImageIfDesired(systemSymbolName: "apple.terminal")
|
||||||
|
self.menuChangeTitle?.setImageIfDesired(systemSymbolName: "pencil.line")
|
||||||
|
self.menuTerminalInspector?.setImageIfDesired(systemSymbolName: "scope")
|
||||||
|
self.menuToggleFullScreen?.setImageIfDesired(systemSymbolName: "square.arrowtriangle.4.outward")
|
||||||
|
self.menuToggleVisibility?.setImageIfDesired(systemSymbolName: "eye")
|
||||||
|
self.menuZoomSplit?.setImageIfDesired(systemSymbolName: "arrow.up.left.and.arrow.down.right")
|
||||||
|
self.menuPreviousSplit?.setImageIfDesired(systemSymbolName: "chevron.backward.2")
|
||||||
|
self.menuNextSplit?.setImageIfDesired(systemSymbolName: "chevron.forward.2")
|
||||||
|
self.menuEqualizeSplits?.setImageIfDesired(systemSymbolName: "inset.filled.topleft.topright.bottomleft.bottomright.rectangle")
|
||||||
|
self.menuSelectSplitLeft?.setImageIfDesired(systemSymbolName: "arrow.left")
|
||||||
|
self.menuSelectSplitRight?.setImageIfDesired(systemSymbolName: "arrow.right")
|
||||||
|
self.menuSelectSplitAbove?.setImageIfDesired(systemSymbolName: "arrow.up")
|
||||||
|
self.menuSelectSplitBelow?.setImageIfDesired(systemSymbolName: "arrow.down")
|
||||||
|
self.menuMoveSplitDividerUp?.setImageIfDesired(systemSymbolName: "arrow.up.to.line")
|
||||||
|
self.menuMoveSplitDividerDown?.setImageIfDesired(systemSymbolName: "arrow.down.to.line")
|
||||||
|
self.menuMoveSplitDividerLeft?.setImageIfDesired(systemSymbolName: "arrow.left.to.line")
|
||||||
|
self.menuMoveSplitDividerRight?.setImageIfDesired(systemSymbolName: "arrow.right.to.line")
|
||||||
|
self.menuFloatOnTop?.setImageIfDesired(systemSymbolName: "square.3.layers.3d.top.filled")
|
||||||
|
}
|
||||||
|
|
||||||
/// Sync all of our menu item keyboard shortcuts with the Ghostty configuration.
|
/// Sync all of our menu item keyboard shortcuts with the Ghostty configuration.
|
||||||
private func syncMenuShortcuts(_ config: Ghostty.Config) {
|
private func syncMenuShortcuts(_ config: Ghostty.Config) {
|
||||||
guard ghostty.readiness == .ready else { return }
|
guard ghostty.readiness == .ready else { return }
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="23727" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="24093.7" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="macosx"/>
|
<deployment identifier="macosx"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23727"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="24093.7"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||||
@@ -251,18 +251,18 @@
|
|||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
<menu key="submenu" title="View" id="m6z-2H-VW7">
|
<menu key="submenu" title="View" id="m6z-2H-VW7">
|
||||||
<items>
|
<items>
|
||||||
<menuItem title="Increase Font Size" id="CIH-ey-Z6x" userLabel="Increase Font Size">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="increaseFontSize:" target="-1" id="361-5E-7PY"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Reset Font Size" id="Jah-MY-aLX">
|
<menuItem title="Reset Font Size" id="Jah-MY-aLX">
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="resetFontSize:" target="-1" id="3dh-T9-IkH"/>
|
<action selector="resetFontSize:" target="-1" id="3dh-T9-IkH"/>
|
||||||
</connections>
|
</connections>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
|
<menuItem title="Increase Font Size" id="CIH-ey-Z6x" userLabel="Increase Font Size">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="increaseFontSize:" target="-1" id="361-5E-7PY"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
<menuItem title="Decrease Font Size" id="kzb-SZ-dOA">
|
<menuItem title="Decrease Font Size" id="kzb-SZ-dOA">
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
<connections>
|
<connections>
|
||||||
|
@@ -1281,6 +1281,10 @@ extension Ghostty {
|
|||||||
|
|
||||||
let menu = NSMenu()
|
let menu = NSMenu()
|
||||||
|
|
||||||
|
// We just use a floating var so we can easily setup metadata on each item
|
||||||
|
// in a row without storing it all.
|
||||||
|
var item: NSMenuItem
|
||||||
|
|
||||||
// If we have a selection, add copy
|
// If we have a selection, add copy
|
||||||
if self.selectedRange().length > 0 {
|
if self.selectedRange().length > 0 {
|
||||||
menu.addItem(withTitle: "Copy", action: #selector(copy(_:)), keyEquivalent: "")
|
menu.addItem(withTitle: "Copy", action: #selector(copy(_:)), keyEquivalent: "")
|
||||||
@@ -1288,16 +1292,23 @@ extension Ghostty {
|
|||||||
menu.addItem(withTitle: "Paste", action: #selector(paste(_:)), keyEquivalent: "")
|
menu.addItem(withTitle: "Paste", action: #selector(paste(_:)), keyEquivalent: "")
|
||||||
|
|
||||||
menu.addItem(.separator())
|
menu.addItem(.separator())
|
||||||
menu.addItem(withTitle: "Split Right", action: #selector(splitRight(_:)), keyEquivalent: "")
|
item = menu.addItem(withTitle: "Split Right", action: #selector(splitRight(_:)), keyEquivalent: "")
|
||||||
menu.addItem(withTitle: "Split Left", action: #selector(splitLeft(_:)), keyEquivalent: "")
|
item.setImageIfDesired(systemSymbolName: "rectangle.righthalf.inset.filled")
|
||||||
menu.addItem(withTitle: "Split Down", action: #selector(splitDown(_:)), keyEquivalent: "")
|
item = menu.addItem(withTitle: "Split Left", action: #selector(splitLeft(_:)), keyEquivalent: "")
|
||||||
menu.addItem(withTitle: "Split Up", action: #selector(splitUp(_:)), keyEquivalent: "")
|
item.setImageIfDesired(systemSymbolName: "rectangle.leadinghalf.inset.filled")
|
||||||
|
item = menu.addItem(withTitle: "Split Down", action: #selector(splitDown(_:)), keyEquivalent: "")
|
||||||
|
item.setImageIfDesired(systemSymbolName: "rectangle.bottomhalf.inset.filled")
|
||||||
|
item = menu.addItem(withTitle: "Split Up", action: #selector(splitUp(_:)), keyEquivalent: "")
|
||||||
|
item.setImageIfDesired(systemSymbolName: "rectangle.tophalf.inset.filled")
|
||||||
|
|
||||||
menu.addItem(.separator())
|
menu.addItem(.separator())
|
||||||
menu.addItem(withTitle: "Reset Terminal", action: #selector(resetTerminal(_:)), keyEquivalent: "")
|
item = menu.addItem(withTitle: "Reset Terminal", action: #selector(resetTerminal(_:)), keyEquivalent: "")
|
||||||
menu.addItem(withTitle: "Toggle Terminal Inspector", action: #selector(toggleTerminalInspector(_:)), keyEquivalent: "")
|
item.setImageIfDesired(systemSymbolName: "arrow.trianglehead.2.clockwise")
|
||||||
|
item = menu.addItem(withTitle: "Toggle Terminal Inspector", action: #selector(toggleTerminalInspector(_:)), keyEquivalent: "")
|
||||||
|
item.setImageIfDesired(systemSymbolName: "scope")
|
||||||
menu.addItem(.separator())
|
menu.addItem(.separator())
|
||||||
menu.addItem(withTitle: "Change Title...", action: #selector(changeTitle(_:)), keyEquivalent: "")
|
item = menu.addItem(withTitle: "Change Title...", action: #selector(changeTitle(_:)), keyEquivalent: "")
|
||||||
|
item.setImageIfDesired(systemSymbolName: "pencil.line")
|
||||||
|
|
||||||
return menu
|
return menu
|
||||||
}
|
}
|
||||||
|
11
macos/Sources/Helpers/Extensions/NSMenuItem+Extension.swift
Normal file
11
macos/Sources/Helpers/Extensions/NSMenuItem+Extension.swift
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import AppKit
|
||||||
|
|
||||||
|
extension NSMenuItem {
|
||||||
|
/// Sets the image property from a symbol if we want images on our menu items.
|
||||||
|
func setImageIfDesired(systemSymbolName symbol: String) {
|
||||||
|
// We only set on macOS 26 when icons on menu items became the norm.
|
||||||
|
if #available(macOS 26, *) {
|
||||||
|
image = NSImage(systemSymbolName: symbol, accessibilityDescription: title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user