macos: wip

This commit is contained in:
Mitchell Hashimoto
2023-10-28 22:22:19 -07:00
parent 0ca69cbc98
commit 3018377389
5 changed files with 171 additions and 1 deletions

View File

@ -27,6 +27,9 @@
A571AB1D2A206FCF00248498 /* GhosttyKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5D495A1299BEC7E00DD1313 /* GhosttyKit.xcframework */; };
A59444F729A2ED5200725BBA /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59444F629A2ED5200725BBA /* SettingsView.swift */; };
A59630972AEE163600D64628 /* HostingWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59630962AEE163600D64628 /* HostingWindow.swift */; };
A596309A2AEE1C6400D64628 /* Terminal.xib in Resources */ = {isa = PBXBuildFile; fileRef = A59630992AEE1C6400D64628 /* Terminal.xib */; };
A596309C2AEE1C9E00D64628 /* TerminalController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A596309B2AEE1C9E00D64628 /* TerminalController.swift */; };
A596309E2AEE1D6C00D64628 /* TerminalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A596309D2AEE1D6C00D64628 /* TerminalView.swift */; };
A59FB5CF2AE0DB50009128F3 /* InspectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59FB5CE2AE0DB50009128F3 /* InspectorView.swift */; };
A59FB5D12AE0DEA7009128F3 /* MetalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59FB5D02AE0DEA7009128F3 /* MetalView.swift */; };
A5A1F8852A489D6800D1E8BC /* terminfo in Resources */ = {isa = PBXBuildFile; fileRef = A5A1F8842A489D6800D1E8BC /* terminfo */; };
@ -62,6 +65,9 @@
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>"; };
A59630962AEE163600D64628 /* HostingWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingWindow.swift; sourceTree = "<group>"; };
A59630992AEE1C6400D64628 /* Terminal.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = Terminal.xib; sourceTree = "<group>"; };
A596309B2AEE1C9E00D64628 /* TerminalController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalController.swift; sourceTree = "<group>"; };
A596309D2AEE1D6C00D64628 /* TerminalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalView.swift; sourceTree = "<group>"; };
A59FB5CE2AE0DB50009128F3 /* InspectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InspectorView.swift; sourceTree = "<group>"; };
A59FB5D02AE0DEA7009128F3 /* MetalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetalView.swift; sourceTree = "<group>"; };
A5A1F8842A489D6800D1E8BC /* terminfo */ = {isa = PBXFileReference; lastKnownFileType = folder; name = terminfo; path = "../zig-out/share/terminfo"; sourceTree = "<group>"; };
@ -97,6 +103,7 @@
children = (
A56D58872ACDE6BE00508D2C /* Services */,
A53426372A7DC53A00EBB7A2 /* Primary Window */,
A59630982AEE1C4400D64628 /* Terminal */,
A534263E2A7DCC5800EBB7A2 /* Settings */,
);
path = Features;
@ -173,6 +180,16 @@
path = Services;
sourceTree = "<group>";
};
A59630982AEE1C4400D64628 /* Terminal */ = {
isa = PBXGroup;
children = (
A59630992AEE1C6400D64628 /* Terminal.xib */,
A596309B2AEE1C9E00D64628 /* TerminalController.swift */,
A596309D2AEE1D6C00D64628 /* TerminalView.swift */,
);
path = Terminal;
sourceTree = "<group>";
};
A5A1F8862A489D7400D1E8BC /* Resources */ = {
isa = PBXGroup;
children = (
@ -280,6 +297,7 @@
buildActionMask = 2147483647;
files = (
A545D1A22A5772CE006E0AE4 /* shell-integration in Resources */,
A596309A2AEE1C6400D64628 /* Terminal.xib in Resources */,
A5A1F8852A489D6800D1E8BC /* terminfo in Resources */,
A5CDF1912AAF9A5800513312 /* ConfigurationErrors.xib in Resources */,
A5B30539299BEAAB0047F10C /* Assets.xcassets in Resources */,
@ -295,6 +313,7 @@
buildActionMask = 2147483647;
files = (
A59FB5CF2AE0DB50009128F3 /* InspectorView.swift in Sources */,
A596309C2AEE1C9E00D64628 /* TerminalController.swift in Sources */,
A53426392A7DC55C00EBB7A2 /* PrimaryWindowManager.swift in Sources */,
85DE1C922A6A3DCA00493853 /* PrimaryWindow.swift in Sources */,
A56D58892ACDE6CA00508D2C /* ServiceProvider.swift in Sources */,
@ -318,6 +337,7 @@
85102A1C2A6E32890084AB3E /* PrimaryWindowController.swift in Sources */,
A5CEAFFF29C2410700646FDA /* Backport.swift in Sources */,
8503D7C72A549C66006CFF3D /* FullScreenHandler.swift in Sources */,
A596309E2AEE1D6C00D64628 /* TerminalView.swift in Sources */,
A5CEAFDE29B8058B00646FDA /* SplitView.Divider.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -73,11 +73,15 @@ class AppDelegate: NSObject, ObservableObject, NSApplicationDelegate, GhosttyApp
// Let's launch our first window.
// TODO: we should detect if we restored windows and if so not launch a new window.
windowManager.addInitialWindow()
// TODO: remove when TerminalController is done
// windowManager.addInitialWindow()
// Initial config loading
configDidReload(ghostty)
let c = TerminalController(ghostty)
c.showWindow(self)
// Register our service provider. This must happen after everything
// else is initialized.
NSApp.servicesProvider = ServiceProvider()

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="TerminalController" customModule="Ghostty" customModuleProvider="target">
<connections>
<outlet property="window" destination="QvC-M9-y7g" id="cg9-Ep-qHg"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="👻 Ghostty" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="0.0" y="0.0" width="800" height="600"/>
<rect key="screenRect" x="0.0" y="0.0" width="3008" height="1667"/>
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="800" height="600"/>
<autoresizingMask key="autoresizingMask"/>
</view>
<connections>
<outlet property="delegate" destination="-2" id="tG2-b7-nb8"/>
</connections>
<point key="canvasLocation" x="132" y="-82"/>
</window>
</objects>
</document>

View File

@ -0,0 +1,50 @@
import Foundation
import Cocoa
import SwiftUI
import Combine
class TerminalController: NSWindowController, NSWindowDelegate {
override var windowNibName: NSNib.Name? { "Terminal" }
/// The app instance that this terminal view will represent.
let ghostty: Ghostty.AppState
init(_ ghostty: Ghostty.AppState) {
self.ghostty = ghostty
super.init(window: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) is not supported for this view")
}
//MARK: - NSWindowController
override func windowWillLoad() {
// We want every new terminal window to cascade so they don't directly overlap.
shouldCascadeWindows = true
}
override func windowDidLoad() {
guard let window = window else { return }
// Terminals typically operate in sRGB color space and macOS defaults
// to "native" which is typically P3. There is a lot more resources
// covered in thie GitHub issue: https://github.com/mitchellh/ghostty/pull/376
window.colorSpace = NSColorSpace.sRGB
// Center the window to start, we'll move the window frame automatically
// when cascading.
window.center()
// Initialize our content view to the SwiftUI root
window.contentView = NSHostingView(rootView: TerminalView(
ghostty: self.ghostty
))
}
//MARK: - NSWindowDelegate
func windowWillClose(_ notification: Notification) {
}
}

View File

@ -0,0 +1,65 @@
import SwiftUI
import GhosttyKit
struct TerminalView: View {
@ObservedObject var ghostty: Ghostty.AppState
// This seems like a crutch after switching from SwiftUI to AppKit lifecycle.
@FocusState private var focused: Bool
@FocusedValue(\.ghosttySurfaceView) private var focusedSurface
@FocusedValue(\.ghosttySurfaceTitle) private var surfaceTitle
@FocusedValue(\.ghosttySurfaceZoomed) private var zoomedSplit
@FocusedValue(\.ghosttySurfaceCellSize) private var cellSize
// The title for our window
private var title: String {
var title = "👻"
if let surfaceTitle = surfaceTitle {
if (surfaceTitle.count > 0) {
title = surfaceTitle
}
}
if let zoomedSplit = zoomedSplit {
if zoomedSplit {
title = "🔍 " + title
}
}
return title
}
var body: some View {
switch ghostty.readiness {
case .loading:
Text("Loading")
case .error:
ErrorView()
case .ready:
let center = NotificationCenter.default
let gotoTab = center.publisher(for: Ghostty.Notification.ghosttyGotoTab)
let toggleFullscreen = center.publisher(for: Ghostty.Notification.ghosttyToggleFullscreen)
VStack(spacing: 0) {
// If we're running in debug mode we show a warning so that users
// know that performance will be degraded.
if (ghostty.info.mode == GHOSTTY_BUILD_MODE_DEBUG) {
DebugBuildWarningView()
}
Ghostty.TerminalSplit(onClose: Self.closeWindow, baseConfig: nil)
.ghosttyApp(ghostty.app!)
.ghosttyConfig(ghostty.config!)
.focused($focused)
.onAppear { self.focused = true }
}
}
}
static func closeWindow() {
guard let currentWindow = NSApp.keyWindow else { return }
currentWindow.close()
}
}