Rust · 15460 bytes Raw Blame History
1 //! FFI bindings for SkyLight, CoreGraphics, and CoreFoundation.
2 //!
3 //! These are private/undocumented APIs used by the WindowServer compositor.
4 //! Signatures sourced from JankyBorders and yabai reverse engineering.
5
6 #![allow(non_snake_case, non_upper_case_globals, dead_code)]
7
8 use std::ffi::c_void;
9
10 // --- Core types ---
11
12 pub type CGError = i32;
13 pub type CGSConnectionID = i32;
14 pub const kCGErrorSuccess: CGError = 0;
15 pub const kCGBackingStoreBuffered: i32 = 2;
16
17 #[repr(C)]
18 #[derive(Debug, Clone, Copy, Default)]
19 pub struct CGPoint {
20 pub x: f64,
21 pub y: f64,
22 }
23
24 #[repr(C)]
25 #[derive(Debug, Clone, Copy, Default)]
26 pub struct CGSize {
27 pub width: f64,
28 pub height: f64,
29 }
30
31 #[repr(C)]
32 #[derive(Debug, Clone, Copy, Default)]
33 pub struct CGRect {
34 pub origin: CGPoint,
35 pub size: CGSize,
36 }
37
38 impl CGRect {
39 pub fn new(x: f64, y: f64, w: f64, h: f64) -> Self {
40 Self {
41 origin: CGPoint { x, y },
42 size: CGSize {
43 width: w,
44 height: h,
45 },
46 }
47 }
48
49 pub fn inset(&self, dx: f64, dy: f64) -> Self {
50 Self::new(
51 self.origin.x + dx,
52 self.origin.y + dy,
53 self.size.width - 2.0 * dx,
54 self.size.height - 2.0 * dy,
55 )
56 }
57 }
58
59 #[repr(C)]
60 #[derive(Debug, Clone, Copy)]
61 pub struct CGAffineTransform {
62 pub a: f64,
63 pub b: f64,
64 pub c: f64,
65 pub d: f64,
66 pub tx: f64,
67 pub ty: f64,
68 }
69
70 impl Default for CGAffineTransform {
71 fn default() -> Self {
72 Self::IDENTITY
73 }
74 }
75
76 impl CGAffineTransform {
77 pub const IDENTITY: Self = Self {
78 a: 1.0,
79 b: 0.0,
80 c: 0.0,
81 d: 1.0,
82 tx: 0.0,
83 ty: 0.0,
84 };
85 }
86
87 #[repr(C)]
88 #[derive(Debug, Clone, Copy)]
89 pub struct ProcessSerialNumber {
90 pub high: u32,
91 pub low: u32,
92 }
93
94 // --- Opaque CF types ---
95
96 pub type CFTypeRef = *const c_void;
97 pub type CFArrayRef = *const c_void;
98 pub type CFStringRef = *const c_void;
99 pub type CFDictionaryRef = *const c_void;
100 pub type CFNumberRef = *const c_void;
101 pub type CFMachPortRef = *const c_void;
102 pub type CFRunLoopSourceRef = *const c_void;
103 pub type CFRunLoopRef = *const c_void;
104 pub type CFAllocatorRef = *const c_void;
105 pub type CGContextRef = *mut c_void;
106 pub type CGPathRef = *const c_void;
107 pub type CGMutablePathRef = *mut c_void;
108 pub type CGEventRef = *const c_void;
109 pub type CGDisplayModeRef = *const c_void;
110
111 // CF constants
112 pub const kCFNumberSInt32Type: i32 = 3;
113 pub const kCFNumberSInt64Type: i32 = 4;
114 pub const kCFNumberCFIndexType: i32 = 14;
115 pub const kCFBooleanFalse: *const c_void = std::ptr::null(); // placeholder
116
117 // --- SkyLight / CGS functions ---
118
119 unsafe extern "C" {
120 // Connection
121 pub fn SLSMainConnectionID() -> CGSConnectionID;
122 pub fn SLSNewConnection(zero: i32, cid: *mut CGSConnectionID) -> CGError;
123 pub fn SLSReleaseConnection(cid: CGSConnectionID) -> CGError;
124
125 // Event port
126 pub fn SLSGetEventPort(cid: CGSConnectionID, port_out: *mut u32) -> CGError;
127 pub fn SLEventCreateNextEvent(cid: CGSConnectionID) -> CGEventRef;
128 pub fn _CFMachPortSetOptions(mach_port: CFMachPortRef, options: i32);
129
130 // Event registration
131 pub fn SLSRegisterNotifyProc(
132 handler: *const c_void,
133 event: u32,
134 context: *mut c_void,
135 ) -> CGError;
136
137 pub fn SLSRequestNotificationsForWindows(
138 cid: CGSConnectionID,
139 window_list: *const u32,
140 window_count: i32,
141 ) -> CGError;
142
143 // Window queries
144 pub fn SLSGetWindowOwner(
145 cid: CGSConnectionID,
146 wid: u32,
147 out_cid: *mut CGSConnectionID,
148 ) -> CGError;
149 pub fn SLSConnectionGetPID(cid: CGSConnectionID, pid: *mut i32) -> CGError;
150 pub fn SLSGetWindowBounds(cid: CGSConnectionID, wid: u32, frame: *mut CGRect) -> CGError;
151 pub fn SLSWindowIsOrderedIn(cid: CGSConnectionID, wid: u32, shown: *mut bool) -> CGError;
152 pub fn SLSGetWindowLevel(cid: CGSConnectionID, wid: u32, level_out: *mut i64) -> CGError;
153
154 // Window iterator queries
155 pub fn SLSWindowQueryWindows(
156 cid: CGSConnectionID,
157 windows: CFArrayRef,
158 options: u32,
159 ) -> CFTypeRef;
160 pub fn SLSWindowQueryResultCopyWindows(window_query: CFTypeRef) -> CFTypeRef;
161 pub fn SLSWindowIteratorGetCount(iterator: CFTypeRef) -> i32;
162 pub fn SLSWindowIteratorAdvance(iterator: CFTypeRef) -> bool;
163 pub fn SLSWindowIteratorGetParentID(iterator: CFTypeRef) -> u32;
164 pub fn SLSWindowIteratorGetWindowID(iterator: CFTypeRef) -> u32;
165 pub fn SLSWindowIteratorGetTags(iterator: CFTypeRef) -> u64;
166 pub fn SLSWindowIteratorGetAttributes(iterator: CFTypeRef) -> u64;
167 pub fn SLSWindowIteratorGetLevel(iterator: CFTypeRef) -> i32;
168
169 // Window lifecycle
170 pub fn SLSNewWindow(
171 cid: CGSConnectionID,
172 window_type: i32,
173 x: f32,
174 y: f32,
175 region: CFTypeRef,
176 wid_out: *mut u32,
177 ) -> CGError;
178 pub fn SLSReleaseWindow(cid: CGSConnectionID, wid: u32) -> CGError;
179
180 // Window properties
181 pub fn SLSSetWindowTags(
182 cid: CGSConnectionID,
183 wid: u32,
184 tags: *const u64,
185 tag_size: i32,
186 ) -> CGError;
187 pub fn SLSClearWindowTags(
188 cid: CGSConnectionID,
189 wid: u32,
190 tags: *const u64,
191 tag_size: i32,
192 ) -> CGError;
193 pub fn SLSSetWindowShape(
194 cid: CGSConnectionID,
195 wid: u32,
196 x_offset: f32,
197 y_offset: f32,
198 shape: CFTypeRef,
199 ) -> CGError;
200 pub fn SLSSetWindowResolution(cid: CGSConnectionID, wid: u32, res: f64) -> CGError;
201 pub fn SLSSetWindowOpacity(cid: CGSConnectionID, wid: u32, is_opaque: bool) -> CGError;
202 /// Mask of events the SLS window captures. Set to 0 to make the window
203 /// click-through (mouse events pass to the window beneath). Used by
204 /// border overlays so the user can still click/scroll the underlying
205 /// app window.
206 pub fn SLSSetWindowEventMask(cid: CGSConnectionID, wid: u32, mask: u32) -> CGError;
207 /// Hit-test/input shape. An empty region passes all mouse events
208 /// through to the window beneath. Equivalent to NSWindow's
209 /// `setIgnoresMouseEvents(true)` at the SLS layer.
210 pub fn SLSSetWindowEventShape(cid: CGSConnectionID, wid: u32, shape: CFTypeRef) -> CGError;
211 pub fn SLSSetWindowAlpha(cid: CGSConnectionID, wid: u32, alpha: f32) -> CGError;
212 pub fn SLSSetWindowBackgroundBlurRadius(cid: CGSConnectionID, wid: u32, radius: u32)
213 -> CGError;
214 pub fn SLSSetWindowLevel(cid: CGSConnectionID, wid: u32, level: i32) -> CGError;
215 pub fn SLSOrderWindow(cid: CGSConnectionID, wid: u32, mode: i32, relative_to: u32) -> CGError;
216 pub fn SLSMoveWindow(cid: CGSConnectionID, wid: u32, point: *const CGPoint) -> CGError;
217
218 // Shadow
219 pub fn SLSWindowSetShadowProperties(wid: u32, properties: CFDictionaryRef) -> CGError;
220
221 // Drawing context
222 pub fn SLWindowContextCreate(
223 cid: CGSConnectionID,
224 wid: u32,
225 options: CFDictionaryRef,
226 ) -> CGContextRef;
227
228 // Transactions
229 pub fn SLSTransactionCreate(cid: CGSConnectionID) -> CFTypeRef;
230 pub fn SLSTransactionSetWindowLevel(transaction: CFTypeRef, wid: u32, level: i32) -> CGError;
231 pub fn SLSTransactionMoveWindowWithGroup(
232 transaction: CFTypeRef,
233 wid: u32,
234 point: CGPoint,
235 ) -> CGError;
236 pub fn SLSTransactionOrderWindow(
237 transaction: CFTypeRef,
238 wid: u32,
239 order: i32,
240 rel_wid: u32,
241 ) -> CGError;
242 pub fn SLSTransactionSetWindowAlpha(transaction: CFTypeRef, wid: u32, alpha: f32) -> CGError;
243 pub fn SLSTransactionSetWindowTransform(
244 transaction: CFTypeRef,
245 wid: u32,
246 not: i32,
247 important: i32,
248 transform: CGAffineTransform,
249 ) -> CGError;
250 pub fn SLSTransactionCommit(transaction: CFTypeRef, synchronous: i32) -> CGError;
251 pub fn SLSTransactionSetWindowShape(
252 transaction: CFTypeRef,
253 wid: u32,
254 x_offset: f32,
255 y_offset: f32,
256 shape: CFTypeRef,
257 ) -> CGError;
258
259 // Flicker suppression
260 pub fn SLSDisableUpdate(cid: CGSConnectionID) -> CGError;
261 pub fn SLSReenableUpdate(cid: CGSConnectionID) -> CGError;
262 pub fn SLSFlushWindowContentRegion(
263 cid: CGSConnectionID,
264 wid: u32,
265 dirty: *const c_void,
266 ) -> CGError;
267
268 // Space management
269 pub fn SLSCopySpacesForWindows(
270 cid: CGSConnectionID,
271 selector: i32,
272 window_list: CFArrayRef,
273 ) -> CFArrayRef;
274 pub fn SLSCopyManagedDisplays(cid: CGSConnectionID) -> CFArrayRef;
275 pub fn SLSCopyManagedDisplaySpaces(cid: CGSConnectionID) -> CFArrayRef;
276 pub fn SLSCopyManagedDisplayForWindow(cid: CGSConnectionID, wid: u32) -> CFStringRef;
277 pub fn SLSManagedDisplayGetCurrentSpace(cid: CGSConnectionID, uuid: CFStringRef) -> u64;
278 pub fn SLSCopyActiveMenuBarDisplayIdentifier(cid: CGSConnectionID) -> CFStringRef;
279 pub fn SLSMoveWindowsToManagedSpace(
280 cid: CGSConnectionID,
281 window_list: CFArrayRef,
282 sid: u64,
283 ) -> CGError;
284
285 // Window enumeration
286 pub fn SLSCopyWindowsWithOptionsAndTags(
287 cid: CGSConnectionID,
288 owner: u32,
289 spaces: CFArrayRef,
290 options: u32,
291 set_tags: *const u64,
292 clear_tags: *const u64,
293 ) -> CFArrayRef;
294
295 // Front process detection
296 pub fn _SLPSGetFrontProcess(psn: *mut ProcessSerialNumber) -> i32;
297 pub fn SLSGetConnectionIDForPSN(
298 cid: CGSConnectionID,
299 psn: *mut ProcessSerialNumber,
300 psn_cid: *mut CGSConnectionID,
301 ) -> CGError;
302
303 // Region
304 pub fn CGSNewRegionWithRect(rect: *const CGRect, region: *mut CFTypeRef) -> CGError;
305 }
306
307 // --- CoreGraphics drawing ---
308
309 // --- CGWindowList (public CoreGraphics API) ---
310
311 pub const kCGWindowListOptionOnScreenOnly: u32 = 1 << 0;
312 pub const kCGWindowListOptionAll: u32 = 0;
313 pub const kCGNullWindowID: u32 = 0;
314
315 unsafe extern "C" {
316 pub fn CGWindowListCopyWindowInfo(option: u32, relative_to: u32) -> CFArrayRef;
317 pub fn CGGetDisplaysWithPoint(
318 point: CGPoint,
319 max_displays: u32,
320 displays: *mut u32,
321 count: *mut u32,
322 ) -> CGError;
323 pub fn CGDisplayCopyDisplayMode(display: u32) -> CGDisplayModeRef;
324 pub fn CGDisplayModeGetWidth(mode: CGDisplayModeRef) -> usize;
325 pub fn CGDisplayModeGetHeight(mode: CGDisplayModeRef) -> usize;
326 pub fn CGDisplayModeGetPixelWidth(mode: CGDisplayModeRef) -> usize;
327 pub fn CGDisplayModeGetPixelHeight(mode: CGDisplayModeRef) -> usize;
328 pub fn CFDictionaryGetValueIfPresent(
329 dict: CFDictionaryRef,
330 key: CFTypeRef,
331 value_out: *mut CFTypeRef,
332 ) -> bool;
333 pub fn CFStringCreateWithCString(
334 alloc: CFAllocatorRef,
335 c_str: *const u8,
336 encoding: u32,
337 ) -> CFStringRef;
338 }
339
340 pub const kCFStringEncodingUTF8: u32 = 0x0800_0100;
341
342 // --- CoreGraphics drawing ---
343
344 unsafe extern "C" {
345 pub fn CGContextSetRGBStrokeColor(ctx: CGContextRef, r: f64, g: f64, b: f64, a: f64);
346 pub fn CGContextSetRGBFillColor(ctx: CGContextRef, r: f64, g: f64, b: f64, a: f64);
347 pub fn CGContextSetLineWidth(ctx: CGContextRef, width: f64);
348 pub fn CGContextClearRect(ctx: CGContextRef, rect: CGRect);
349 pub fn CGContextEOFillPath(ctx: CGContextRef);
350 pub fn CGContextAddPath(ctx: CGContextRef, path: CGPathRef);
351 pub fn CGContextStrokePath(ctx: CGContextRef);
352 pub fn CGContextFillPath(ctx: CGContextRef);
353 pub fn CGContextFlush(ctx: CGContextRef);
354 pub fn CGContextRelease(ctx: CGContextRef);
355 pub fn CGContextSaveGState(ctx: CGContextRef);
356 pub fn CGContextRestoreGState(ctx: CGContextRef);
357 pub fn CGContextSetInterpolationQuality(ctx: CGContextRef, quality: i32);
358 pub fn CGContextClip(ctx: CGContextRef);
359 pub fn CGContextEOClip(ctx: CGContextRef);
360 pub fn CGPathCreateWithRoundedRect(
361 rect: CGRect,
362 rx: f64,
363 ry: f64,
364 transform: *const CGAffineTransform,
365 ) -> CGPathRef;
366 pub fn CGPathCreateMutable() -> CGMutablePathRef;
367 pub fn CGPathAddRoundedRect(
368 path: CGMutablePathRef,
369 transform: *const CGAffineTransform,
370 rect: CGRect,
371 rx: f64,
372 ry: f64,
373 );
374 pub fn CGPathAddRect(path: CGMutablePathRef, transform: *const CGAffineTransform, rect: CGRect);
375 pub fn CGPathAddPath(
376 path: CGMutablePathRef,
377 transform: *const CGAffineTransform,
378 other: CGPathRef,
379 );
380 pub fn CGPathRelease(path: CGPathRef);
381 }
382
383 // --- CoreFoundation ---
384
385 unsafe extern "C" {
386 pub fn CFRelease(cf: CFTypeRef);
387 pub fn CFRetain(cf: CFTypeRef) -> CFTypeRef;
388
389 pub fn CFArrayGetCount(array: CFArrayRef) -> i64;
390 pub fn CFArrayGetValueAtIndex(array: CFArrayRef, idx: i64) -> CFTypeRef;
391 pub fn CFArrayCreate(
392 allocator: CFAllocatorRef,
393 values: *const CFTypeRef,
394 count: i64,
395 callbacks: *const c_void,
396 ) -> CFArrayRef;
397
398 pub fn CFNumberCreate(
399 allocator: CFAllocatorRef,
400 the_type: i32,
401 value_ptr: *const c_void,
402 ) -> CFNumberRef;
403 pub fn CFNumberGetValue(number: CFNumberRef, the_type: i32, value_ptr: *mut c_void) -> bool;
404 pub fn CFNumberGetType(number: CFNumberRef) -> i32;
405
406 pub fn CFDictionaryCreate(
407 allocator: CFAllocatorRef,
408 keys: *const CFTypeRef,
409 values: *const CFTypeRef,
410 count: i64,
411 key_callbacks: *const c_void,
412 value_callbacks: *const c_void,
413 ) -> CFDictionaryRef;
414 pub fn CFDictionaryGetValue(dict: CFDictionaryRef, key: CFTypeRef) -> CFTypeRef;
415
416 pub fn CFMachPortCreateWithPort(
417 allocator: CFAllocatorRef,
418 port: u32,
419 callback: *const c_void,
420 context: *const c_void,
421 should_free: bool,
422 ) -> CFMachPortRef;
423
424 pub fn CFMachPortCreateRunLoopSource(
425 allocator: CFAllocatorRef,
426 port: CFMachPortRef,
427 order: i64,
428 ) -> CFRunLoopSourceRef;
429
430 pub fn CFRunLoopGetCurrent() -> CFRunLoopRef;
431 pub fn CFRunLoopGetMain() -> CFRunLoopRef;
432 pub fn CFRunLoopAddSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef);
433 pub fn CFRunLoopRun();
434 pub fn CFRunLoopStop(rl: CFRunLoopRef);
435 pub fn CFRunLoopWakeUp(rl: CFRunLoopRef);
436
437 pub static kCFAllocatorDefault: CFAllocatorRef;
438 pub static kCFTypeDictionaryKeyCallBacks: c_void;
439 pub static kCFTypeDictionaryValueCallBacks: c_void;
440 pub static kCFTypeArrayCallBacks: c_void;
441 pub static kCFRunLoopDefaultMode: CFStringRef;
442 }
443
444 // --- macOS process ---
445
446 unsafe extern "C" {
447 pub fn getpid() -> i32;
448 pub fn pid_for_task(task: u32, pid: *mut i32) -> i32;
449 pub static mach_task_self_: u32;
450 }
451
452 pub fn mach_task_self() -> u32 {
453 unsafe { mach_task_self_ }
454 }
455
456 // --- Helper: create CFArray of CFNumbers ---
457
458 pub unsafe fn cfarray_of_cfnumbers(
459 values: *const c_void,
460 size: usize,
461 count: i32,
462 num_type: i32,
463 ) -> CFArrayRef {
464 unsafe {
465 let mut temp: Vec<CFNumberRef> = Vec::with_capacity(count as usize);
466 for i in 0..count {
467 let ptr = (values as *const u8).add(size * i as usize) as *const c_void;
468 temp.push(CFNumberCreate(std::ptr::null(), num_type, ptr));
469 }
470 let array = CFArrayCreate(
471 std::ptr::null(),
472 temp.as_ptr() as *const CFTypeRef,
473 count as i64,
474 &kCFTypeArrayCallBacks as *const _,
475 );
476 for n in &temp {
477 CFRelease(*n);
478 }
479 array
480 }
481 }
482