Rust · 14845 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
110 // CF constants
111 pub const kCFNumberSInt32Type: i32 = 3;
112 pub const kCFNumberSInt64Type: i32 = 4;
113 pub const kCFNumberCFIndexType: i32 = 14;
114 pub const kCFBooleanFalse: *const c_void = std::ptr::null(); // placeholder
115
116 // --- SkyLight / CGS functions ---
117
118 unsafe extern "C" {
119 // Connection
120 pub fn SLSMainConnectionID() -> CGSConnectionID;
121 pub fn SLSNewConnection(zero: i32, cid: *mut CGSConnectionID) -> CGError;
122 pub fn SLSReleaseConnection(cid: CGSConnectionID) -> CGError;
123
124 // Event port
125 pub fn SLSGetEventPort(cid: CGSConnectionID, port_out: *mut u32) -> CGError;
126 pub fn SLEventCreateNextEvent(cid: CGSConnectionID) -> CGEventRef;
127 pub fn _CFMachPortSetOptions(mach_port: CFMachPortRef, options: i32);
128
129 // Event registration
130 pub fn SLSRegisterNotifyProc(
131 handler: *const c_void,
132 event: u32,
133 context: *mut c_void,
134 ) -> CGError;
135
136 pub fn SLSRequestNotificationsForWindows(
137 cid: CGSConnectionID,
138 window_list: *const u32,
139 window_count: i32,
140 ) -> CGError;
141
142 // Window queries
143 pub fn SLSGetWindowOwner(
144 cid: CGSConnectionID,
145 wid: u32,
146 out_cid: *mut CGSConnectionID,
147 ) -> CGError;
148 pub fn SLSConnectionGetPID(cid: CGSConnectionID, pid: *mut i32) -> CGError;
149 pub fn SLSGetWindowBounds(
150 cid: CGSConnectionID,
151 wid: u32,
152 frame: *mut CGRect,
153 ) -> CGError;
154 pub fn SLSWindowIsOrderedIn(
155 cid: CGSConnectionID,
156 wid: u32,
157 shown: *mut bool,
158 ) -> CGError;
159 pub fn SLSGetWindowLevel(
160 cid: CGSConnectionID,
161 wid: u32,
162 level_out: *mut i64,
163 ) -> CGError;
164
165 // Window iterator queries
166 pub fn SLSWindowQueryWindows(
167 cid: CGSConnectionID,
168 windows: CFArrayRef,
169 options: u32,
170 ) -> CFTypeRef;
171 pub fn SLSWindowQueryResultCopyWindows(window_query: CFTypeRef) -> CFTypeRef;
172 pub fn SLSWindowIteratorGetCount(iterator: CFTypeRef) -> i32;
173 pub fn SLSWindowIteratorAdvance(iterator: CFTypeRef) -> bool;
174 pub fn SLSWindowIteratorGetParentID(iterator: CFTypeRef) -> u32;
175 pub fn SLSWindowIteratorGetWindowID(iterator: CFTypeRef) -> u32;
176 pub fn SLSWindowIteratorGetTags(iterator: CFTypeRef) -> u64;
177 pub fn SLSWindowIteratorGetAttributes(iterator: CFTypeRef) -> u64;
178 pub fn SLSWindowIteratorGetLevel(iterator: CFTypeRef) -> i32;
179
180 // Window lifecycle
181 pub fn SLSNewWindow(
182 cid: CGSConnectionID,
183 window_type: i32,
184 x: f32,
185 y: f32,
186 region: CFTypeRef,
187 wid_out: *mut u32,
188 ) -> CGError;
189 pub fn SLSReleaseWindow(cid: CGSConnectionID, wid: u32) -> CGError;
190
191 // Window properties
192 pub fn SLSSetWindowTags(
193 cid: CGSConnectionID,
194 wid: u32,
195 tags: *const u64,
196 tag_size: i32,
197 ) -> CGError;
198 pub fn SLSClearWindowTags(
199 cid: CGSConnectionID,
200 wid: u32,
201 tags: *const u64,
202 tag_size: i32,
203 ) -> CGError;
204 pub fn SLSSetWindowShape(
205 cid: CGSConnectionID,
206 wid: u32,
207 x_offset: f32,
208 y_offset: f32,
209 shape: CFTypeRef,
210 ) -> CGError;
211 pub fn SLSSetWindowResolution(
212 cid: CGSConnectionID,
213 wid: u32,
214 res: f64,
215 ) -> CGError;
216 pub fn SLSSetWindowOpacity(
217 cid: CGSConnectionID,
218 wid: u32,
219 is_opaque: bool,
220 ) -> CGError;
221 pub fn SLSSetWindowAlpha(
222 cid: CGSConnectionID,
223 wid: u32,
224 alpha: f32,
225 ) -> CGError;
226 pub fn SLSSetWindowBackgroundBlurRadius(
227 cid: CGSConnectionID,
228 wid: u32,
229 radius: u32,
230 ) -> CGError;
231 pub fn SLSSetWindowLevel(
232 cid: CGSConnectionID,
233 wid: u32,
234 level: i32,
235 ) -> CGError;
236 pub fn SLSOrderWindow(
237 cid: CGSConnectionID,
238 wid: u32,
239 mode: i32,
240 relative_to: u32,
241 ) -> CGError;
242 pub fn SLSMoveWindow(
243 cid: CGSConnectionID,
244 wid: u32,
245 point: *const CGPoint,
246 ) -> CGError;
247
248 // Shadow
249 pub fn SLSWindowSetShadowProperties(
250 wid: u32,
251 properties: CFDictionaryRef,
252 ) -> CGError;
253
254 // Drawing context
255 pub fn SLWindowContextCreate(
256 cid: CGSConnectionID,
257 wid: u32,
258 options: CFDictionaryRef,
259 ) -> CGContextRef;
260
261 // Transactions
262 pub fn SLSTransactionCreate(cid: CGSConnectionID) -> CFTypeRef;
263 pub fn SLSTransactionSetWindowLevel(
264 transaction: CFTypeRef,
265 wid: u32,
266 level: i32,
267 ) -> CGError;
268 pub fn SLSTransactionMoveWindowWithGroup(
269 transaction: CFTypeRef,
270 wid: u32,
271 point: CGPoint,
272 ) -> CGError;
273 pub fn SLSTransactionOrderWindow(
274 transaction: CFTypeRef,
275 wid: u32,
276 order: i32,
277 rel_wid: u32,
278 ) -> CGError;
279 pub fn SLSTransactionSetWindowAlpha(
280 transaction: CFTypeRef,
281 wid: u32,
282 alpha: f32,
283 ) -> CGError;
284 pub fn SLSTransactionSetWindowTransform(
285 transaction: CFTypeRef,
286 wid: u32,
287 not: i32,
288 important: i32,
289 transform: CGAffineTransform,
290 ) -> CGError;
291 pub fn SLSTransactionCommit(transaction: CFTypeRef, synchronous: i32) -> CGError;
292 pub fn SLSTransactionSetWindowShape(
293 transaction: CFTypeRef,
294 wid: u32,
295 x_offset: f32,
296 y_offset: f32,
297 shape: CFTypeRef,
298 ) -> CGError;
299
300 // Flicker suppression
301 pub fn SLSDisableUpdate(cid: CGSConnectionID) -> CGError;
302 pub fn SLSReenableUpdate(cid: CGSConnectionID) -> CGError;
303 pub fn SLSFlushWindowContentRegion(
304 cid: CGSConnectionID,
305 wid: u32,
306 dirty: *const c_void,
307 ) -> CGError;
308
309 // Space management
310 pub fn SLSCopySpacesForWindows(
311 cid: CGSConnectionID,
312 selector: i32,
313 window_list: CFArrayRef,
314 ) -> CFArrayRef;
315 pub fn SLSCopyManagedDisplays(cid: CGSConnectionID) -> CFArrayRef;
316 pub fn SLSCopyManagedDisplaySpaces(cid: CGSConnectionID) -> CFArrayRef;
317 pub fn SLSCopyManagedDisplayForWindow(
318 cid: CGSConnectionID,
319 wid: u32,
320 ) -> CFStringRef;
321 pub fn SLSManagedDisplayGetCurrentSpace(
322 cid: CGSConnectionID,
323 uuid: CFStringRef,
324 ) -> u64;
325 pub fn SLSCopyActiveMenuBarDisplayIdentifier(cid: CGSConnectionID) -> CFStringRef;
326 pub fn SLSMoveWindowsToManagedSpace(
327 cid: CGSConnectionID,
328 window_list: CFArrayRef,
329 sid: u64,
330 ) -> CGError;
331
332 // Window enumeration
333 pub fn SLSCopyWindowsWithOptionsAndTags(
334 cid: CGSConnectionID,
335 owner: u32,
336 spaces: CFArrayRef,
337 options: u32,
338 set_tags: *const u64,
339 clear_tags: *const u64,
340 ) -> CFArrayRef;
341
342 // Front process detection
343 pub fn _SLPSGetFrontProcess(psn: *mut ProcessSerialNumber) -> i32;
344 pub fn SLSGetConnectionIDForPSN(
345 cid: CGSConnectionID,
346 psn: *mut ProcessSerialNumber,
347 psn_cid: *mut CGSConnectionID,
348 ) -> CGError;
349
350 // Region
351 pub fn CGSNewRegionWithRect(rect: *const CGRect, region: *mut CFTypeRef) -> CGError;
352 }
353
354 // --- CoreGraphics drawing ---
355
356 // --- CGWindowList (public CoreGraphics API) ---
357
358 pub const kCGWindowListOptionOnScreenOnly: u32 = 1 << 0;
359 pub const kCGWindowListOptionAll: u32 = 0;
360 pub const kCGNullWindowID: u32 = 0;
361
362 unsafe extern "C" {
363 pub fn CGWindowListCopyWindowInfo(option: u32, relative_to: u32) -> CFArrayRef;
364 pub fn CFDictionaryGetValueIfPresent(
365 dict: CFDictionaryRef,
366 key: CFTypeRef,
367 value_out: *mut CFTypeRef,
368 ) -> bool;
369 pub fn CFStringCreateWithCString(
370 alloc: CFAllocatorRef,
371 c_str: *const u8,
372 encoding: u32,
373 ) -> CFStringRef;
374 }
375
376 pub const kCFStringEncodingUTF8: u32 = 0x0800_0100;
377
378 // --- CoreGraphics drawing ---
379
380 unsafe extern "C" {
381 pub fn CGContextSetRGBStrokeColor(
382 ctx: CGContextRef,
383 r: f64,
384 g: f64,
385 b: f64,
386 a: f64,
387 );
388 pub fn CGContextSetRGBFillColor(
389 ctx: CGContextRef,
390 r: f64,
391 g: f64,
392 b: f64,
393 a: f64,
394 );
395 pub fn CGContextSetLineWidth(ctx: CGContextRef, width: f64);
396 pub fn CGContextClearRect(ctx: CGContextRef, rect: CGRect);
397 pub fn CGContextEOFillPath(ctx: CGContextRef);
398 pub fn CGContextAddPath(ctx: CGContextRef, path: CGPathRef);
399 pub fn CGContextStrokePath(ctx: CGContextRef);
400 pub fn CGContextFillPath(ctx: CGContextRef);
401 pub fn CGContextFlush(ctx: CGContextRef);
402 pub fn CGContextRelease(ctx: CGContextRef);
403 pub fn CGContextSaveGState(ctx: CGContextRef);
404 pub fn CGContextRestoreGState(ctx: CGContextRef);
405 pub fn CGContextSetInterpolationQuality(ctx: CGContextRef, quality: i32);
406 pub fn CGContextClip(ctx: CGContextRef);
407 pub fn CGContextEOClip(ctx: CGContextRef);
408 pub fn CGPathCreateWithRoundedRect(
409 rect: CGRect,
410 rx: f64,
411 ry: f64,
412 transform: *const CGAffineTransform,
413 ) -> CGPathRef;
414 pub fn CGPathCreateMutable() -> CGMutablePathRef;
415 pub fn CGPathAddRoundedRect(
416 path: CGMutablePathRef,
417 transform: *const CGAffineTransform,
418 rect: CGRect,
419 rx: f64,
420 ry: f64,
421 );
422 pub fn CGPathAddRect(
423 path: CGMutablePathRef,
424 transform: *const CGAffineTransform,
425 rect: CGRect,
426 );
427 pub fn CGPathAddPath(
428 path: CGMutablePathRef,
429 transform: *const CGAffineTransform,
430 other: CGPathRef,
431 );
432 pub fn CGPathRelease(path: CGPathRef);
433 }
434
435 // --- CoreFoundation ---
436
437 unsafe extern "C" {
438 pub fn CFRelease(cf: CFTypeRef);
439 pub fn CFRetain(cf: CFTypeRef) -> CFTypeRef;
440
441 pub fn CFArrayGetCount(array: CFArrayRef) -> i64;
442 pub fn CFArrayGetValueAtIndex(array: CFArrayRef, idx: i64) -> CFTypeRef;
443 pub fn CFArrayCreate(
444 allocator: CFAllocatorRef,
445 values: *const CFTypeRef,
446 count: i64,
447 callbacks: *const c_void,
448 ) -> CFArrayRef;
449
450 pub fn CFNumberCreate(
451 allocator: CFAllocatorRef,
452 the_type: i32,
453 value_ptr: *const c_void,
454 ) -> CFNumberRef;
455 pub fn CFNumberGetValue(
456 number: CFNumberRef,
457 the_type: i32,
458 value_ptr: *mut c_void,
459 ) -> bool;
460 pub fn CFNumberGetType(number: CFNumberRef) -> i32;
461
462 pub fn CFDictionaryCreate(
463 allocator: CFAllocatorRef,
464 keys: *const CFTypeRef,
465 values: *const CFTypeRef,
466 count: i64,
467 key_callbacks: *const c_void,
468 value_callbacks: *const c_void,
469 ) -> CFDictionaryRef;
470 pub fn CFDictionaryGetValue(dict: CFDictionaryRef, key: CFTypeRef) -> CFTypeRef;
471
472 pub fn CFMachPortCreateWithPort(
473 allocator: CFAllocatorRef,
474 port: u32,
475 callback: *const c_void,
476 context: *const c_void,
477 should_free: bool,
478 ) -> CFMachPortRef;
479
480 pub fn CFMachPortCreateRunLoopSource(
481 allocator: CFAllocatorRef,
482 port: CFMachPortRef,
483 order: i64,
484 ) -> CFRunLoopSourceRef;
485
486 pub fn CFRunLoopGetCurrent() -> CFRunLoopRef;
487 pub fn CFRunLoopGetMain() -> CFRunLoopRef;
488 pub fn CFRunLoopAddSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef);
489 pub fn CFRunLoopRun();
490 pub fn CFRunLoopStop(rl: CFRunLoopRef);
491
492 pub static kCFAllocatorDefault: CFAllocatorRef;
493 pub static kCFTypeDictionaryKeyCallBacks: c_void;
494 pub static kCFTypeDictionaryValueCallBacks: c_void;
495 pub static kCFTypeArrayCallBacks: c_void;
496 pub static kCFRunLoopDefaultMode: CFStringRef;
497 }
498
499 // --- macOS process ---
500
501 unsafe extern "C" {
502 pub fn getpid() -> i32;
503 pub fn pid_for_task(task: u32, pid: *mut i32) -> i32;
504 pub static mach_task_self_: u32;
505 }
506
507 pub fn mach_task_self() -> u32 {
508 unsafe { mach_task_self_ }
509 }
510
511 // --- Helper: create CFArray of CFNumbers ---
512
513 pub unsafe fn cfarray_of_cfnumbers(values: *const c_void, size: usize, count: i32, num_type: i32) -> CFArrayRef {
514 unsafe {
515 let mut temp: Vec<CFNumberRef> = Vec::with_capacity(count as usize);
516 for i in 0..count {
517 let ptr = (values as *const u8).add(size * i as usize) as *const c_void;
518 temp.push(CFNumberCreate(std::ptr::null(), num_type, ptr));
519 }
520 let array = CFArrayCreate(
521 std::ptr::null(),
522 temp.as_ptr() as *const CFTypeRef,
523 count as i64,
524 &kCFTypeArrayCallBacks as *const _ as *const c_void,
525 );
526 for n in &temp {
527 CFRelease(*n);
528 }
529 array
530 }
531 }
532