@@ -2,6 +2,7 @@ import AppKit
22import AXExtension
33import AXNotificationStream
44import Foundation
5+ import Perception
56import SwiftUI
67import XcodeInspector
78
@@ -28,7 +29,7 @@ final class IDEWorkspaceWindowOverlayWindowController {
2829 let inspector : WorkspaceXcodeWindowInspector
2930 let contentProviders : [ any IDEWorkspaceWindowOverlayWindowControllerContentProvider ]
3031 private var isDestroyed : Bool = false
31- private let maskPanel : NSPanel
32+ private let maskPanel : OverlayPanel
3233 private var axNotificationTask : Task < Void , Never > ?
3334
3435 init (
@@ -46,11 +47,9 @@ final class IDEWorkspaceWindowOverlayWindowController {
4647 let panel = OverlayPanel (
4748 contentRect: . init( x: 0 , y: 0 , width: 200 , height: 200 )
4849 ) {
49- ContentWrapper {
50- ZStack {
51- ForEach ( 0 ..< contentProviders. count, id: \. self) { index in
52- contentProviders [ index] . contentBody
53- }
50+ ZStack {
51+ ForEach ( 0 ..< contentProviders. count, id: \. self) { index in
52+ contentProviders [ index] . contentBody
5453 }
5554 }
5655 }
@@ -69,31 +68,22 @@ final class IDEWorkspaceWindowOverlayWindowController {
6968 notificationNames: kAXMovedNotification, kAXResizedNotification
7069 )
7170
72- axNotificationTask = Task { [ weak panel ] in
71+ axNotificationTask = Task { [ weak self ] in
7372 for await notification in stream {
74- guard let panel else { return }
73+ guard let panel = self ? . maskPanel else { continue }
7574 if Task . isCancelled { return }
7675 switch notification. name {
7776 case kAXMovedNotification, kAXResizedNotification:
7877 if let rect = windowElement. rect {
79- let screen = NSScreen . screens
80- . first ( where: { $0. frame. intersects ( rect) } ) ?? NSScreen . main
81- let panelFrame = Self . convertAXRectToNSPanelFrame (
82- axRect: rect,
83- forScreen: screen
84- )
85- panel. setFrame ( panelFrame, display: false )
78+ panel. setTopLeftCoordinateFrame ( rect, display: true )
8679 }
8780 default : continue
8881 }
8982 }
9083 }
9184
9285 if let rect = windowElement. rect {
93- let screen = NSScreen . screens. first ( where: { $0. frame. intersects ( rect) } ) ?? NSScreen
94- . main
95- let panelFrame = Self . convertAXRectToNSPanelFrame ( axRect: rect, forScreen: screen)
96- panel. setFrame ( panelFrame, display: false )
86+ panel. setTopLeftCoordinateFrame ( rect, display: false )
9787 }
9888 }
9989
@@ -135,47 +125,3 @@ final class IDEWorkspaceWindowOverlayWindowController {
135125 }
136126}
137127
138- extension IDEWorkspaceWindowOverlayWindowController {
139- struct ContentWrapper < Content: View > : View {
140- @ViewBuilder let content : ( ) -> Content
141- @State var showOverlayArea : Bool = false
142-
143- var body : some View {
144- content ( )
145- . background {
146- if showOverlayArea {
147- Rectangle ( ) . fill ( . green. opacity ( 0.2 ) )
148- }
149- }
150- . overlay ( alignment: . topTrailing) {
151- #if DEBUG
152- HStack {
153- Button ( action: {
154- showOverlayArea. toggle ( )
155- } ) {
156- Image ( systemName: " eye " )
157- . foregroundColor ( showOverlayArea ? . green : . red)
158- }
159- . padding ( )
160- }
161- #else
162- EmptyView ( )
163- #endif
164- }
165- }
166- }
167-
168- static func convertAXRectToNSPanelFrame( axRect: CGRect , forScreen screen: NSScreen ? ) -> CGRect {
169- guard let screen = screen else { return . zero }
170- let screenFrame = screen. frame
171- let flippedY = screenFrame. origin. y + screenFrame. size
172- . height - ( axRect. origin. y + axRect. size. height)
173- return CGRect (
174- x: axRect. origin. x,
175- y: flippedY,
176- width: axRect. size. width,
177- height: axRect. size. height
178- )
179- }
180- }
181-
0 commit comments