Skip to content

Commit 3bdbeeb

Browse files
committed
Tweak real-time suggestion indicator update location logic
1 parent c3063bd commit 3bdbeeb

1 file changed

Lines changed: 55 additions & 8 deletions

File tree

Core/Sources/Service/GUI/RealtimeSuggestionIndicatorController.swift

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Environment
66
import QuartzCore
77
import SwiftUI
88
import XPCShared
9+
import AsyncAlgorithms
910

1011
/// Present a tiny dot next to mouse cursor if real-time suggestion is enabled.
1112
@MainActor
@@ -94,6 +95,7 @@ final class RealtimeSuggestionIndicatorController {
9495
private var userDefaultsObserver = UserDefaultsObserver()
9596
private var windowChangeObservationTask: Task<Void, Error>?
9697
private var activeApplicationMonitorTask: Task<Void, Error>?
98+
private var editorObservationTask: Task<Void, Error>?
9799
private var xcode: NSRunningApplication?
98100
var isObserving = false {
99101
didSet {
@@ -124,6 +126,7 @@ final class RealtimeSuggestionIndicatorController {
124126

125127
nonisolated init() {
126128
Task { @MainActor in
129+
observeEditorChangeIfNeeded()
127130
activeApplicationMonitorTask = Task { [weak self] in
128131
var previousApp: NSRunningApplication?
129132
for await app in ActiveApplicationMonitor.createStream() {
@@ -170,14 +173,61 @@ final class RealtimeSuggestionIndicatorController {
170173
notificationNames:
171174
kAXMovedNotification,
172175
kAXResizedNotification,
173-
kAXMainWindowChangedNotification,
174176
kAXFocusedWindowChangedNotification,
175-
kAXFocusedUIElementChangedNotification,
176-
kAXSelectedTextChangedNotification
177+
kAXFocusedUIElementChangedNotification
177178
)
178-
for await _ in notifications {
179+
for await notification in notifications {
179180
try Task.checkCancellation()
180181
updateIndicatorLocation()
182+
183+
switch notification.name {
184+
case kAXFocusedUIElementChangedNotification, kAXFocusedWindowChangedNotification:
185+
editorObservationTask?.cancel()
186+
editorObservationTask = nil
187+
observeEditorChangeIfNeeded()
188+
default:
189+
continue
190+
}
191+
}
192+
}
193+
}
194+
195+
private func observeEditorChangeIfNeeded() {
196+
guard editorObservationTask == nil,
197+
let activeXcode = ActiveApplicationMonitor.activeXcode
198+
else { return }
199+
let application = AXUIElementCreateApplication(activeXcode.processIdentifier)
200+
guard let focusElement: AXUIElement = try? application
201+
.copyValue(key: kAXFocusedUIElementAttribute),
202+
let focusElementType: String = try? focusElement
203+
.copyValue(key: kAXDescriptionAttribute),
204+
focusElementType == "Source Editor",
205+
let scrollView: AXUIElement = try? focusElement
206+
.copyValue(key: kAXParentAttribute),
207+
let scrollBar: AXUIElement = try? scrollView
208+
.copyValue(key: kAXVerticalScrollBarAttribute)
209+
else { return }
210+
211+
editorObservationTask = Task { [weak self] in
212+
let notificationsFromEditor = AXNotificationStream(
213+
app: activeXcode,
214+
element: focusElement,
215+
notificationNames:
216+
kAXResizedNotification,
217+
kAXMovedNotification,
218+
kAXLayoutChangedNotification,
219+
kAXSelectedTextChangedNotification
220+
)
221+
222+
let notificationsFromScrollBar = AXNotificationStream(
223+
app: activeXcode,
224+
element: scrollBar,
225+
notificationNames: kAXValueChangedNotification
226+
)
227+
228+
for await _ in merge(notificationsFromEditor, notificationsFromScrollBar) {
229+
try Task.checkCancellation()
230+
self?.updateIndicatorLocation()
181231
}
182232
}
183233
}
@@ -198,10 +248,7 @@ final class RealtimeSuggestionIndicatorController {
198248
return
199249
}
200250

201-
if let activeXcode = NSRunningApplication
202-
.runningApplications(withBundleIdentifier: "com.apple.dt.Xcode")
203-
.first(where: \.isActive)
204-
{
251+
if let activeXcode = ActiveApplicationMonitor.activeXcode {
205252
let application = AXUIElementCreateApplication(activeXcode.processIdentifier)
206253
if let focusElement: AXUIElement = try? application
207254
.copyValue(key: kAXFocusedUIElementAttribute),

0 commit comments

Comments
 (0)