@@ -85,22 +85,68 @@ struct CGPoint
8585 public double Y ;
8686 }
8787
88- [ DllImport ( "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics" ) ]
88+ private const string CoreGraphicsLib =
89+ "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics" ;
90+
91+ [ DllImport ( CoreGraphicsLib ) ]
8992 static extern CGPoint CGEventGetLocation ( IntPtr eventRef ) ;
9093
91- [ DllImport ( "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics" ) ]
94+ [ DllImport ( CoreGraphicsLib ) ]
9295 static extern IntPtr CGEventCreate ( IntPtr source ) ;
9396
94- [ DllImport ( "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics" ) ]
97+ [ DllImport ( CoreGraphicsLib ) ]
9598 static extern IntPtr CFRelease ( IntPtr eventRef ) ;
9699
100+ private const string CoreFoundationLib =
101+ "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation" ;
102+
103+ // Options for window list
104+ private const uint kCGWindowListOptionIncludingWindow = 1 << 3 ;
105+
106+ [ DllImport ( CoreGraphicsLib ) ]
107+ private static extern IntPtr CGWindowListCopyWindowInfo ( uint option , uint relativeToWindow ) ;
108+
109+ [ DllImport ( CoreFoundationLib ) ]
110+ private static extern int CFArrayGetCount ( IntPtr theArray ) ;
111+
112+ [ DllImport ( CoreFoundationLib ) ]
113+ private static extern IntPtr CFArrayGetValueAtIndex ( IntPtr theArray , int idx ) ;
114+ [ DllImport ( CoreFoundationLib ) ]
115+ internal static extern IntPtr CFStringCreateWithCString (
116+ IntPtr alloc ,
117+ string str ,
118+ uint encoding
119+ ) ;
120+
121+ [ DllImport ( CoreFoundationLib ) ]
122+ internal static extern IntPtr CFDictionaryGetValue ( IntPtr theDict , IntPtr key ) ;
123+
124+ [ DllImport ( CoreGraphicsLib ) ]
125+ [ return : MarshalAs ( UnmanagedType . I1 ) ]
126+ internal static extern bool CGRectMakeWithDictionaryRepresentation (
127+ IntPtr dict ,
128+ out CGRect rect
129+ ) ;
130+ [ StructLayout ( LayoutKind . Sequential ) ]
131+ public struct CGRect
132+ {
133+ public double X ;
134+ public double Y ;
135+ public double Width ;
136+ public double Height ;
137+ }
138+
139+ // Standard UTF8 encoding ID for CFString
140+ internal const uint kCFStringEncodingUTF8 = 0x08000100 ;
141+
97142 public override Point GetCursorPosition ( )
98143 {
99144 var ev = CGEventCreate ( IntPtr . Zero ) ;
100145 var point = CGEventGetLocation ( ev ) ;
101146 CFRelease ( ev ) ;
102147 return new Point ( ( int ) point . X , ( int ) point . Y ) ;
103148 }
149+
104150 public void ShowWindow ( WindowInfo window )
105151 {
106152 if ( window . ProcessId == 0 )
@@ -121,6 +167,66 @@ public void ShowWindow(WindowInfo window)
121167 using var process = Process . Start ( psi ) ;
122168 process ? . WaitForExit ( ) ;
123169 }
170+ public override Rectangle GetWindowRectangle ( WindowInfo window )
171+ {
172+ return base . GetWindowRectangle ( window . Handle ) ;
173+ }
174+ public override Rectangle GetWindowRectangle ( IntPtr windowHandle )
175+ {
176+ uint windowId = ( uint ) windowHandle . ToInt32 ( ) ;
177+
178+ IntPtr arrayRef = CGWindowListCopyWindowInfo ( kCGWindowListOptionIncludingWindow , windowId ) ;
179+ if ( arrayRef == IntPtr . Zero )
180+ return Rectangle . Empty ;
181+
182+ try
183+ {
184+ int count = CFArrayGetCount ( arrayRef ) ;
185+ if ( count == 0 )
186+ return Rectangle . Empty ;
187+
188+ IntPtr dictRef = CFArrayGetValueAtIndex ( arrayRef , 0 ) ;
189+
190+ return ExtractCGRectFromDict ( dictRef ) ;
191+ }
192+ finally
193+ {
194+ CFRelease ( arrayRef ) ;
195+ }
196+ }
197+ private Rectangle ExtractCGRectFromDict ( IntPtr dictRef )
198+ {
199+ IntPtr key = CFStringCreateWithCString (
200+ IntPtr . Zero ,
201+ "kCGWindowBounds" ,
202+ kCFStringEncodingUTF8
203+ ) ;
204+
205+ try
206+ {
207+ IntPtr boundsDict = CFDictionaryGetValue ( dictRef , key ) ;
208+
209+ if (
210+ boundsDict != IntPtr . Zero
211+ && CGRectMakeWithDictionaryRepresentation ( boundsDict , out CGRect cgRect )
212+ )
213+ {
214+ return new Rectangle (
215+ ( int ) cgRect . X ,
216+ ( int ) cgRect . Y ,
217+ ( int ) cgRect . Width ,
218+ ( int ) cgRect . Height
219+ ) ;
220+ }
221+ }
222+ finally
223+ {
224+ if ( key != IntPtr . Zero )
225+ CFRelease ( key ) ;
226+ }
227+
228+ return Rectangle . Empty ;
229+ }
124230
125231 public override List < WindowInfo > GetWindowList ( )
126232 {
@@ -139,9 +245,7 @@ public override List<WindowInfo> GetWindowList()
139245 IsMinimized = raw . isMinimized ,
140246 IsVisible = ! raw . isMinimized ,
141247 IsActive = raw . isFocused ,
142-
143- // Not exposed
144- Handle = IntPtr . Zero ,
248+ Handle = ( nint ) ( nuint ) raw . hwnd ,
145249 } )
146250 . ToList ( ) ;
147251
0 commit comments