Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 24 additions & 20 deletions GhosttyTabs.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@
7C135CU00000000000000002 /* ClosedTerminalUndoStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C135CU00000000000000001 /* ClosedTerminalUndoStore.swift */; };
NRSP0010A1B2C3D4E5F60719 /* ContentView+SidebarResizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = NRSP0009A1B2C3D4E5F60719 /* ContentView+SidebarResizer.swift */; };
NRSP0008A1B2C3D4E5F60719 /* ColorSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = NRSP0007A1B2C3D4E5F60719 /* ColorSupport.swift */; };
A5FF0005 /* ContentView+CommandPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5FF0015 /* ContentView+CommandPalette.swift */; };
A2CV0000000000000000000C /* ContentView+CommandPaletteCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2CV0000000000000000000D /* ContentView+CommandPaletteCommands.swift */; };
A2CV0000000000000000000A /* ContentView+CommandPaletteOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2CV0000000000000000000B /* ContentView+CommandPaletteOverlay.swift */; };
A2CV00000000000000000008 /* ContentView+CommandPaletteFlows.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2CV00000000000000000009 /* ContentView+CommandPaletteFlows.swift */; };
A2CV00000000000000000006 /* ContentView+CommandPaletteTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2CV00000000000000000007 /* ContentView+CommandPaletteTypes.swift */; };
A5FF0005 /* CommandPaletteView+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5FF0015 /* CommandPaletteView+Helpers.swift */; };
A2CV0000000000000000000C /* CommandPaletteView+Commands.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2CV0000000000000000000D /* CommandPaletteView+Commands.swift */; };
A2CV0000000000000000000A /* CommandPaletteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2CV0000000000000000000B /* CommandPaletteView.swift */; };
A2CV00000000000000000008 /* CommandPaletteView+Flows.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2CV00000000000000000009 /* CommandPaletteView+Flows.swift */; };
A2CV00000000000000000006 /* CommandPaletteView+Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2CV00000000000000000007 /* CommandPaletteView+Types.swift */; };
A2CV00000000000000000004 /* NotificationBurstCoalescer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2CV00000000000000000005 /* NotificationBurstCoalescer.swift */; };
A2CV00000000000000000002 /* TabManagerSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2CV00000000000000000003 /* TabManagerSettings.swift */; };
NRCV00000000000000000005 /* TabItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = NRCV00000000000000000006 /* TabItemView.swift */; };
Expand All @@ -87,6 +87,7 @@
NRCV00000000000000000007 /* SidebarDragDrop.swift in Sources */ = {isa = PBXBuildFile; fileRef = NRCV00000000000000000008 /* SidebarDragDrop.swift */; };
NRCV00000000000000000009 /* SidebarVisuals.swift in Sources */ = {isa = PBXBuildFile; fileRef = NRCV00000000000000000010 /* SidebarVisuals.swift */; };
NRCV00000000000000000011 /* CommandPaletteController.swift in Sources */ = {isa = PBXBuildFile; fileRef = NRCV00000000000000000012 /* CommandPaletteController.swift */; };
CPVW00000000000000000001 /* CommandPaletteController+Focus.swift in Sources */ = {isa = PBXBuildFile; fileRef = CPVW00000000000000000002 /* CommandPaletteController+Focus.swift */; };
E62155868BB29FEB5DAAAF25 /* SidebarSelectionState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AD52285508B1D6A9875E7B3 /* SidebarSelectionState.swift */; };
B9000018A1B2C3D4E5F60719 /* WindowDragHandleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9000017A1B2C3D4E5F60719 /* WindowDragHandleView.swift */; };
A5001003 /* TabManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001013 /* TabManager.swift */; };
Expand Down Expand Up @@ -481,11 +482,11 @@
7C135CU00000000000000001 /* ClosedTerminalUndoStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClosedTerminalUndoStore.swift; sourceTree = "<group>"; };
NRSP0009A1B2C3D4E5F60719 /* ContentView+SidebarResizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContentView+SidebarResizer.swift"; sourceTree = "<group>"; };
NRSP0007A1B2C3D4E5F60719 /* ColorSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorSupport.swift; sourceTree = "<group>"; };
A5FF0015 /* ContentView+CommandPalette.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContentView+CommandPalette.swift"; sourceTree = "<group>"; };
A2CV0000000000000000000D /* ContentView+CommandPaletteCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContentView+CommandPaletteCommands.swift"; sourceTree = "<group>"; };
A2CV0000000000000000000B /* ContentView+CommandPaletteOverlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContentView+CommandPaletteOverlay.swift"; sourceTree = "<group>"; };
A2CV00000000000000000009 /* ContentView+CommandPaletteFlows.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContentView+CommandPaletteFlows.swift"; sourceTree = "<group>"; };
A2CV00000000000000000007 /* ContentView+CommandPaletteTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContentView+CommandPaletteTypes.swift"; sourceTree = "<group>"; };
A5FF0015 /* CommandPaletteView+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CommandPaletteView+Helpers.swift"; sourceTree = "<group>"; };
A2CV0000000000000000000D /* CommandPaletteView+Commands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CommandPaletteView+Commands.swift"; sourceTree = "<group>"; };
A2CV0000000000000000000B /* CommandPaletteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandPaletteView.swift; sourceTree = "<group>"; };
A2CV00000000000000000009 /* CommandPaletteView+Flows.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CommandPaletteView+Flows.swift"; sourceTree = "<group>"; };
A2CV00000000000000000007 /* CommandPaletteView+Types.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CommandPaletteView+Types.swift"; sourceTree = "<group>"; };
A2CV00000000000000000005 /* NotificationBurstCoalescer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationBurstCoalescer.swift; sourceTree = "<group>"; };
A2CV00000000000000000003 /* TabManagerSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabManagerSettings.swift; sourceTree = "<group>"; };
NRCV00000000000000000006 /* TabItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabItemView.swift; sourceTree = "<group>"; };
Expand All @@ -494,6 +495,7 @@
NRCV00000000000000000008 /* SidebarDragDrop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarDragDrop.swift; sourceTree = "<group>"; };
NRCV00000000000000000010 /* SidebarVisuals.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarVisuals.swift; sourceTree = "<group>"; };
NRCV00000000000000000012 /* CommandPaletteController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandPaletteController.swift; sourceTree = "<group>"; };
CPVW00000000000000000002 /* CommandPaletteController+Focus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CommandPaletteController+Focus.swift"; sourceTree = "<group>"; };
9AD52285508B1D6A9875E7B3 /* SidebarSelectionState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarSelectionState.swift; sourceTree = "<group>"; };
B9000017A1B2C3D4E5F60719 /* WindowDragHandleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowDragHandleView.swift; sourceTree = "<group>"; };
A5001013 /* TabManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabManager.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -933,11 +935,11 @@
7C135CU00000000000000001 /* ClosedTerminalUndoStore.swift */,
NRSP0009A1B2C3D4E5F60719 /* ContentView+SidebarResizer.swift */,
NRSP0007A1B2C3D4E5F60719 /* ColorSupport.swift */,
A5FF0015 /* ContentView+CommandPalette.swift */,
A2CV0000000000000000000D /* ContentView+CommandPaletteCommands.swift */,
A2CV0000000000000000000B /* ContentView+CommandPaletteOverlay.swift */,
A2CV00000000000000000009 /* ContentView+CommandPaletteFlows.swift */,
A2CV00000000000000000007 /* ContentView+CommandPaletteTypes.swift */,
A5FF0015 /* CommandPaletteView+Helpers.swift */,
A2CV0000000000000000000D /* CommandPaletteView+Commands.swift */,
A2CV0000000000000000000B /* CommandPaletteView.swift */,
A2CV00000000000000000009 /* CommandPaletteView+Flows.swift */,
A2CV00000000000000000007 /* CommandPaletteView+Types.swift */,
A2CV00000000000000000005 /* NotificationBurstCoalescer.swift */,
A2CV00000000000000000003 /* TabManagerSettings.swift */,
NRCV00000000000000000006 /* TabItemView.swift */,
Expand All @@ -946,6 +948,7 @@
NRCV00000000000000000008 /* SidebarDragDrop.swift */,
NRCV00000000000000000010 /* SidebarVisuals.swift */,
NRCV00000000000000000012 /* CommandPaletteController.swift */,
CPVW00000000000000000002 /* CommandPaletteController+Focus.swift */,
9AD52285508B1D6A9875E7B3 /* SidebarSelectionState.swift */,
B9000017A1B2C3D4E5F60719 /* WindowDragHandleView.swift */,
A50012F0 /* Backport.swift */,
Expand Down Expand Up @@ -1481,11 +1484,11 @@
7C135CU00000000000000002 /* ClosedTerminalUndoStore.swift in Sources */,
NRSP0010A1B2C3D4E5F60719 /* ContentView+SidebarResizer.swift in Sources */,
NRSP0008A1B2C3D4E5F60719 /* ColorSupport.swift in Sources */,
A5FF0005 /* ContentView+CommandPalette.swift in Sources */,
A2CV0000000000000000000C /* ContentView+CommandPaletteCommands.swift in Sources */,
A2CV0000000000000000000A /* ContentView+CommandPaletteOverlay.swift in Sources */,
A2CV00000000000000000008 /* ContentView+CommandPaletteFlows.swift in Sources */,
A2CV00000000000000000006 /* ContentView+CommandPaletteTypes.swift in Sources */,
A5FF0005 /* CommandPaletteView+Helpers.swift in Sources */,
A2CV0000000000000000000C /* CommandPaletteView+Commands.swift in Sources */,
A2CV0000000000000000000A /* CommandPaletteView.swift in Sources */,
A2CV00000000000000000008 /* CommandPaletteView+Flows.swift in Sources */,
A2CV00000000000000000006 /* CommandPaletteView+Types.swift in Sources */,
A2CV00000000000000000004 /* NotificationBurstCoalescer.swift in Sources */,
A2CV00000000000000000002 /* TabManagerSettings.swift in Sources */,
NRCV00000000000000000005 /* TabItemView.swift in Sources */,
Expand All @@ -1494,6 +1497,7 @@
NRCV00000000000000000007 /* SidebarDragDrop.swift in Sources */,
NRCV00000000000000000009 /* SidebarVisuals.swift in Sources */,
NRCV00000000000000000011 /* CommandPaletteController.swift in Sources */,
CPVW00000000000000000001 /* CommandPaletteController+Focus.swift in Sources */,
E62155868BB29FEB5DAAAF25 /* SidebarSelectionState.swift in Sources */,
B9000018A1B2C3D4E5F60719 /* WindowDragHandleView.swift in Sources */,
A50012F1 /* Backport.swift in Sources */,
Expand Down
99 changes: 99 additions & 0 deletions Sources/CommandPaletteController+Focus.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Palette behavior that ContentView drives as well as CommandPaletteView:
// restoring terminal focus after a dismissal, and the per-window debug state
// AppDelegate exposes to the socket. Neither touches @FocusState, so both live
// on the model. ContentView calls them from inside its own surface-focus
// handlers so the restore runs after the workspace handoff in the same
// notification callback.

import AppKit

@MainActor
extension CommandPaletteController {
func requestFocusRestore(
target: CommandPaletteView.CommandPaletteRestoreFocusTarget,
tabManager: TabManager,
observedWindow: NSWindow?
) {
commandPalettePendingDismissFocusTarget = target
commandPaletteRestoreTimeoutWorkItem?.cancel()
let timeoutWork = DispatchWorkItem {
self.commandPalettePendingDismissFocusTarget = nil
self.commandPaletteRestoreTimeoutWorkItem = nil
}
commandPaletteRestoreTimeoutWorkItem = timeoutWork
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: timeoutWork)
attemptFocusRestoreIfNeeded(tabManager: tabManager, observedWindow: observedWindow)
}

func attemptFocusRestoreIfNeeded(tabManager: TabManager, observedWindow: NSWindow?) {
guard !isCommandPalettePresented else { return }
guard let target = commandPalettePendingDismissFocusTarget else { return }
if let window = observedWindow, !window.isVisible {
commandPalettePendingDismissFocusTarget = nil
commandPaletteRestoreTimeoutWorkItem?.cancel()
commandPaletteRestoreTimeoutWorkItem = nil
return
}
guard tabManager.tabs.contains(where: { $0.id == target.workspaceId }) else {
commandPalettePendingDismissFocusTarget = nil
commandPaletteRestoreTimeoutWorkItem?.cancel()
commandPaletteRestoreTimeoutWorkItem = nil
return
}

if let window = observedWindow, !window.isKeyWindow {
window.makeKeyAndOrderFront(nil)
}
tabManager.focusTab(target.workspaceId, surfaceId: target.panelId, suppressFlash: true)

guard let context = CommandPaletteView.focusedPanelContext(in: tabManager),
context.workspace.id == target.workspaceId,
context.panelId == target.panelId else {
return
}
guard context.panel.restoreFocusIntent(target.intent) else { return }
commandPalettePendingDismissFocusTarget = nil
commandPaletteRestoreTimeoutWorkItem?.cancel()
commandPaletteRestoreTimeoutWorkItem = nil
}

func syncDebugState(observedWindow: NSWindow?) {
guard let window = observedWindow ?? NSApp.keyWindow ?? NSApp.mainWindow else { return }
AppDelegate.shared?.setCommandPaletteVisible(isCommandPalettePresented, for: window)
let visibleResultCount = commandPaletteVisibleResults.count
let selectedIndex = isCommandPalettePresented ? selectedIndex(resultCount: visibleResultCount) : 0
AppDelegate.shared?.setCommandPaletteSelectionIndex(selectedIndex, for: window)
AppDelegate.shared?.setCommandPaletteSnapshot(debugSnapshot(), for: window)
}

private func debugSnapshot() -> CommandPaletteDebugSnapshot {
guard isCommandPalettePresented else { return .empty }

let listScope = CommandPaletteView.commandPaletteListScope(for: commandPaletteQuery)
let mode: String
switch commandPaletteMode {
case .commands:
mode = listScope.rawValue
case .renameInput:
mode = "rename_input"
case .workspaceDescriptionInput:
mode = "workspace_description_input"
}

let rows = Array(commandPaletteVisibleResults.prefix(100)).map { result in
CommandPaletteDebugResultRow(
commandId: result.command.id,
title: result.command.title,
shortcutHint: result.command.shortcutHint,
trailingLabel: CommandPaletteView.commandPaletteTrailingLabel(for: result.command)?.text,
score: result.score
)
}

return CommandPaletteDebugSnapshot(
query: CommandPaletteView.commandPaletteQueryForMatching(query: commandPaletteQuery, scope: listScope),
mode: mode,
results: rows
)
}
}
Loading
Loading