Start the task switcher focused on its list

This commit is contained in:
Ian Gulliver
2026-10-21 10:50:13 -07:00
parent fab6ce5831
commit 761b9ced6a
2 changed files with 20 additions and 4 deletions
+7 -2
View File
@@ -143,7 +143,7 @@ final class Overlays {
guard let self, let window = self.window, win == ObjectIdentifier(window) else { guard let self, let window = self.window, win == ObjectIdentifier(window) else {
return false return false
} }
return self.key(code, flags, chars, ctrl) return self.key(event, code, flags, chars, ctrl)
} }
return taken ? nil : event return taken ? nil : event
} }
@@ -158,7 +158,7 @@ final class Overlays {
} }
} }
private func key(_ code: UInt16, _ flags: NSEvent.ModifierFlags, _ chars: String, _ ctrl: @MainActor (String) -> Bool) -> Bool { private func key(_ event: NSEvent, _ code: UInt16, _ flags: NSEvent.ModifierFlags, _ chars: String, _ ctrl: @MainActor (String) -> Bool) -> Bool {
if !dialogOpen && flags.contains(.control) && !flags.contains(.command) && goKeys.contains(chars) { if !dialogOpen && flags.contains(.control) && !flags.contains(.command) && goKeys.contains(chars) {
return ctrl(chars) return ctrl(chars)
} }
@@ -203,6 +203,11 @@ final class Overlays {
switcher.pick() switcher.pick()
return true return true
} }
if switcher.inList && (flags.isDisjoint(with: [.command, .control, .function]) || (flags.subtracting(.capsLock) == .command && chars.lowercased() == "v")) {
switcher.pending = event
switcher.inList = false
return true
}
} }
return false return false
} }
+13 -2
View File
@@ -79,6 +79,7 @@ private let shortcuts: [(String, [(String, String)])] = [
("Task switcher", [ ("Task switcher", [
("Tab", "Switch between the text and the list"), ("Tab", "Switch between the text and the list"),
("↑ ↓", "Move the highlight, in the list"), ("↑ ↓", "Move the highlight, in the list"),
("Typing, ⌘V", "Jump from the list to the text"),
("Enter", "Pick the highlighted row"), ("Enter", "Pick the highlighted row"),
("Shift+Enter", "New line in the first message"), ("Shift+Enter", "New line in the first message"),
("name: message", "Start the task in the project whose name starts with name"), ("name: message", "Start the task in the project whose name starts with name"),
@@ -154,7 +155,8 @@ final class SwitcherModel {
let imageKey = "switcher:\(UUID().uuidString)" let imageKey = "switcher:\(UUID().uuidString)"
var text = "" var text = ""
var selected = 0 var selected = 0
var inList = false var inList = true
@ObservationIgnored var pending: NSEvent?
var workflows: [WorkflowSummary] = [] var workflows: [WorkflowSummary] = []
init(store: Store, overlays: Overlays, anchor: CGRect) { init(store: Store, overlays: Overlays, anchor: CGRect) {
@@ -317,6 +319,7 @@ final class SwitcherModel {
} catch { } catch {
overlays.openSwitcher(store) overlays.openSwitcher(store)
if let s = overlays.switcher { if let s = overlays.switcher {
s.inList = false
s.setText(typed) s.setText(typed)
store.images.restore(s.imageKey, imgs) store.images.restore(s.imageKey, imgs)
} }
@@ -418,7 +421,11 @@ private struct SwitcherBox: View {
.onAppear { .onAppear {
DispatchQueue.main.async { DispatchQueue.main.async {
logFocus("switcher before focus") logFocus("switcher before focus")
focused = true if model.inList {
overlays.window?.makeFirstResponder(nil)
} else {
focused = true
}
DispatchQueue.main.async { DispatchQueue.main.async {
logFocus("switcher after focus focused=\(focused)") logFocus("switcher after focus focused=\(focused)")
} }
@@ -430,6 +437,10 @@ private struct SwitcherBox: View {
.onChange(of: focused) { .onChange(of: focused) {
if focused { if focused {
model.inList = false model.inList = false
if let event = model.pending {
model.pending = nil
NSApp.postEvent(event, atStart: true)
}
} }
} }
} }