Skip to content

Commit 93751c8

Browse files
committed
Throttle event handling
1 parent 81ca09d commit 93751c8

File tree

2 files changed

+60
-48
lines changed

2 files changed

+60
-48
lines changed

OverlayWindow/Sources/OverlayWindow/IDEWorkspaceWindowOverlayWindowController.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import AppKit
22
import AXExtension
33
import AXNotificationStream
4+
import DebounceFunction
45
import Foundation
56
import Perception
67
import SwiftUI
@@ -31,6 +32,7 @@ final class IDEWorkspaceWindowOverlayWindowController {
3132
let maskPanel: OverlayPanel
3233
var windowElement: AXUIElement
3334
private var axNotificationTask: Task<Void, Never>?
35+
let updateFrameThrottler = ThrottleRunner(duration: 0.2)
3436

3537
init(
3638
inspector: WorkspaceXcodeWindowInspector,
@@ -123,7 +125,9 @@ final class IDEWorkspaceWindowOverlayWindowController {
123125
if Task.isCancelled { return }
124126
switch notification.name {
125127
case kAXMovedNotification, kAXResizedNotification:
126-
self.updateFrame()
128+
await self.updateFrameThrottler.throttle { [weak self] in
129+
await self?.updateFrame()
130+
}
127131
case kAXWindowMiniaturizedNotification:
128132
self.hide()
129133
default: continue

OverlayWindow/Sources/OverlayWindow/OverlayWindowController.swift

Lines changed: 55 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import AppKit
2+
import DebounceFunction
23
import Foundation
34
import Perception
45
import XcodeInspector
@@ -18,6 +19,8 @@ public final class OverlayWindowController {
1819
[ObjectIdentifier: IDEWorkspaceWindowOverlayWindowController]()
1920
var updateWindowStateTask: Task<Void, Error>?
2021

22+
let windowUpdateThrottler = ThrottleRunner(duration: 0.2)
23+
2124
lazy var fullscreenDetector = {
2225
let it = NSWindow(
2326
contentRect: .zero,
@@ -95,53 +98,8 @@ private extension OverlayWindowController {
9598
guard let self else { return }
9699
Task { @MainActor in
97100
defer { self.observeWindowChange() }
98-
99-
guard XcodeInspector.shared.activeApplication?.isXcode ?? false else {
100-
var closedControllers: [ObjectIdentifier] = []
101-
for (id, controller) in self.ideWindowOverlayWindowControllers {
102-
if controller.isWindowClosed {
103-
controller.dim()
104-
closedControllers.append(id)
105-
} else {
106-
controller.dim()
107-
}
108-
}
109-
for id in closedControllers {
110-
self.removeIDEOverlayWindowController(for: id)
111-
}
112-
return
113-
}
114-
115-
guard let app = XcodeInspector.shared.activeXcode else {
116-
for (_, controller) in self.ideWindowOverlayWindowControllers {
117-
controller.hide()
118-
}
119-
return
120-
}
121-
122-
let windowInspector = XcodeInspector.shared.focusedWindow
123-
if let ideWindowInspector = windowInspector as? WorkspaceXcodeWindowInspector {
124-
let objectID = ObjectIdentifier(ideWindowInspector)
125-
// Workspace window is active
126-
// Hide all controllers first
127-
for (id, controller) in self.ideWindowOverlayWindowControllers {
128-
if id != objectID {
129-
controller.hide()
130-
}
131-
}
132-
if let controller = self.ideWindowOverlayWindowControllers[objectID] {
133-
controller.access()
134-
} else {
135-
self.createNewIDEOverlayWindowController(
136-
inspector: ideWindowInspector,
137-
application: app.runningApplication
138-
)
139-
}
140-
} else {
141-
// Not a workspace window, dim all controllers
142-
for (_, controller) in self.ideWindowOverlayWindowControllers {
143-
controller.dim()
144-
}
101+
await self.windowUpdateThrottler.throttle { [weak self] in
102+
await self?.handleOverlayStatusChange()
145103
}
146104
}
147105
}
@@ -194,5 +152,55 @@ private extension OverlayWindowController {
194152
activeWindowController.maskPanel.orderFrontRegardless()
195153
}
196154
}
155+
156+
func handleOverlayStatusChange() {
157+
guard XcodeInspector.shared.activeApplication?.isXcode ?? false else {
158+
var closedControllers: [ObjectIdentifier] = []
159+
for (id, controller) in ideWindowOverlayWindowControllers {
160+
if controller.isWindowClosed {
161+
controller.dim()
162+
closedControllers.append(id)
163+
} else {
164+
controller.dim()
165+
}
166+
}
167+
for id in closedControllers {
168+
removeIDEOverlayWindowController(for: id)
169+
}
170+
return
171+
}
172+
173+
guard let app = XcodeInspector.shared.activeXcode else {
174+
for (_, controller) in ideWindowOverlayWindowControllers {
175+
controller.hide()
176+
}
177+
return
178+
}
179+
180+
let windowInspector = XcodeInspector.shared.focusedWindow
181+
if let ideWindowInspector = windowInspector as? WorkspaceXcodeWindowInspector {
182+
let objectID = ObjectIdentifier(ideWindowInspector)
183+
// Workspace window is active
184+
// Hide all controllers first
185+
for (id, controller) in ideWindowOverlayWindowControllers {
186+
if id != objectID {
187+
controller.hide()
188+
}
189+
}
190+
if let controller = ideWindowOverlayWindowControllers[objectID] {
191+
controller.access()
192+
} else {
193+
createNewIDEOverlayWindowController(
194+
inspector: ideWindowInspector,
195+
application: app.runningApplication
196+
)
197+
}
198+
} else {
199+
// Not a workspace window, dim all controllers
200+
for (_, controller) in ideWindowOverlayWindowControllers {
201+
controller.dim()
202+
}
203+
}
204+
}
197205
}
198206

0 commit comments

Comments
 (0)