mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
macos: implement service provider
This commit is contained in:
@ -22,6 +22,47 @@
|
||||
<key>GHOSTTY_MAC_APP</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
<key>NSServices</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSMenuItem</key>
|
||||
<dict>
|
||||
<key>default</key>
|
||||
<string>New Ghostty Tab Here</string>
|
||||
</dict>
|
||||
<key>NSMessage</key>
|
||||
<string>openTab</string>
|
||||
<key>NSRequiredContext</key>
|
||||
<dict>
|
||||
<key>NSTextContent</key>
|
||||
<string>FilePath</string>
|
||||
</dict>
|
||||
<key>NSSendTypes</key>
|
||||
<array>
|
||||
<string>NSFilenamesPboardType</string>
|
||||
<string>public.plain-text</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSMenuItem</key>
|
||||
<dict>
|
||||
<key>default</key>
|
||||
<string>New Ghostty Window Here</string>
|
||||
</dict>
|
||||
<key>NSMessage</key>
|
||||
<string>openWindow</string>
|
||||
<key>NSRequiredContext</key>
|
||||
<dict>
|
||||
<key>NSTextContent</key>
|
||||
<string>FilePath</string>
|
||||
</dict>
|
||||
<key>NSSendTypes</key>
|
||||
<array>
|
||||
<string>NSFilenamesPboardType</string>
|
||||
<string>public.plain-text</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
<key>NSAppleEventsUsageDescription</key>
|
||||
|
@ -23,6 +23,7 @@
|
||||
A55B7BBE29B701360055DE60 /* Ghostty.SplitView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A55B7BBD29B701360055DE60 /* Ghostty.SplitView.swift */; };
|
||||
A56B880B2A840447007A0E29 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A56B880A2A840447007A0E29 /* Carbon.framework */; };
|
||||
A56D58862ACDDB4100508D2C /* Ghostty.Shell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A56D58852ACDDB4100508D2C /* Ghostty.Shell.swift */; };
|
||||
A56D58892ACDE6CA00508D2C /* ServiceProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A56D58882ACDE6CA00508D2C /* ServiceProvider.swift */; };
|
||||
A571AB1D2A206FCF00248498 /* GhosttyKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5D495A1299BEC7E00DD1313 /* GhosttyKit.xcframework */; };
|
||||
A59444F729A2ED5200725BBA /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59444F629A2ED5200725BBA /* SettingsView.swift */; };
|
||||
A5A1F8852A489D6800D1E8BC /* terminfo in Resources */ = {isa = PBXBuildFile; fileRef = A5A1F8842A489D6800D1E8BC /* terminfo */; };
|
||||
@ -55,6 +56,7 @@
|
||||
A55B7BBD29B701360055DE60 /* Ghostty.SplitView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ghostty.SplitView.swift; sourceTree = "<group>"; };
|
||||
A56B880A2A840447007A0E29 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
|
||||
A56D58852ACDDB4100508D2C /* Ghostty.Shell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ghostty.Shell.swift; sourceTree = "<group>"; };
|
||||
A56D58882ACDE6CA00508D2C /* ServiceProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceProvider.swift; sourceTree = "<group>"; };
|
||||
A571AB1C2A206FC600248498 /* Ghostty-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Ghostty-Info.plist"; sourceTree = "<group>"; };
|
||||
A59444F629A2ED5200725BBA /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
|
||||
A5A1F8842A489D6800D1E8BC /* terminfo */ = {isa = PBXFileReference; lastKnownFileType = folder; name = terminfo; path = "../zig-out/share/terminfo"; sourceTree = "<group>"; };
|
||||
@ -89,6 +91,7 @@
|
||||
A53426362A7DC53000EBB7A2 /* Features */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A56D58872ACDE6BE00508D2C /* Services */,
|
||||
A53426372A7DC53A00EBB7A2 /* Primary Window */,
|
||||
A534263E2A7DCC5800EBB7A2 /* Settings */,
|
||||
);
|
||||
@ -156,6 +159,14 @@
|
||||
path = Ghostty;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A56D58872ACDE6BE00508D2C /* Services */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A56D58882ACDE6CA00508D2C /* ServiceProvider.swift */,
|
||||
);
|
||||
path = Services;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A5A1F8862A489D7400D1E8BC /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -279,6 +290,7 @@
|
||||
files = (
|
||||
A53426392A7DC55C00EBB7A2 /* PrimaryWindowManager.swift in Sources */,
|
||||
85DE1C922A6A3DCA00493853 /* PrimaryWindow.swift in Sources */,
|
||||
A56D58892ACDE6CA00508D2C /* ServiceProvider.swift in Sources */,
|
||||
A5278A9B2AA05B2600CD3039 /* Ghostty.Input.swift in Sources */,
|
||||
A53426352A7DA53D00EBB7A2 /* AppDelegate.swift in Sources */,
|
||||
A5CDF1952AAFA19600513312 /* ConfigurationErrorsView.swift in Sources */,
|
||||
|
@ -40,7 +40,7 @@ class AppDelegate: NSObject, ObservableObject, NSApplicationDelegate, GhosttyApp
|
||||
private var ghostty: Ghostty.AppState = Ghostty.AppState()
|
||||
|
||||
/// Manages windows and tabs, ensuring they're allocated/deallocated correctly
|
||||
private var windowManager: PrimaryWindowManager!
|
||||
var windowManager: PrimaryWindowManager!
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
@ -72,6 +72,10 @@ class AppDelegate: NSObject, ObservableObject, NSApplicationDelegate, GhosttyApp
|
||||
|
||||
// Initial config loading
|
||||
configDidReload(ghostty)
|
||||
|
||||
// Register our service provider. This must happen after everything
|
||||
// else is initialized.
|
||||
NSApp.servicesProvider = ServiceProvider()
|
||||
}
|
||||
|
||||
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
|
||||
|
68
macos/Sources/Features/Services/ServiceProvider.swift
Normal file
68
macos/Sources/Features/Services/ServiceProvider.swift
Normal file
@ -0,0 +1,68 @@
|
||||
import Foundation
|
||||
import AppKit
|
||||
|
||||
class ServiceProvider: NSObject {
|
||||
static private let errorNoString = NSString(string: "Could not load any text from the clipboard.")
|
||||
|
||||
/// The target for an open operation
|
||||
enum OpenTarget {
|
||||
case tab
|
||||
case window
|
||||
}
|
||||
|
||||
@objc func openTab(
|
||||
_ pasteboard: NSPasteboard,
|
||||
userData: String?,
|
||||
error: AutoreleasingUnsafeMutablePointer<NSString>
|
||||
) {
|
||||
guard let str = pasteboard.string(forType: .string) else {
|
||||
error.pointee = Self.errorNoString
|
||||
return
|
||||
}
|
||||
|
||||
openTerminal(str, target: .tab)
|
||||
}
|
||||
|
||||
@objc func openWindow(
|
||||
_ pasteboard: NSPasteboard,
|
||||
userData: String?,
|
||||
error: AutoreleasingUnsafeMutablePointer<NSString>
|
||||
) {
|
||||
guard let str = pasteboard.string(forType: .string) else {
|
||||
error.pointee = Self.errorNoString
|
||||
return
|
||||
}
|
||||
|
||||
openTerminal(str, target: .window)
|
||||
}
|
||||
|
||||
private func openTerminal(_ path: String, target: OpenTarget) {
|
||||
guard let delegateRaw = NSApp.delegate else { return }
|
||||
guard let delegate = delegateRaw as? AppDelegate else { return }
|
||||
guard let windowManager = delegate.windowManager else { return }
|
||||
|
||||
// We only open in directories.
|
||||
var isDirectory = ObjCBool(true)
|
||||
guard FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory) else { return }
|
||||
guard isDirectory.boolValue else { return }
|
||||
|
||||
// Build our config
|
||||
var config = Ghostty.SurfaceConfiguration()
|
||||
config.workingDirectory = path
|
||||
|
||||
// If we don't have a window open through the window manager, we launch
|
||||
// a new window even if they requested a tab.
|
||||
guard let mainWindow = windowManager.mainWindow else {
|
||||
windowManager.addNewWindow(withBaseConfig: config)
|
||||
return
|
||||
}
|
||||
|
||||
switch (target) {
|
||||
case .window:
|
||||
windowManager.addNewWindow(withBaseConfig: config)
|
||||
|
||||
case .tab:
|
||||
windowManager.addNewTab(to: mainWindow, withBaseConfig: config)
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user