Rust · 15358 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).
204 pub fn SLSSetWindowEventMask(cid: CGSConnectionID, wid: u32, mask: u32) -> CGError;
205 /// Hit-test/input shape. An empty region passes all mouse events
206 /// through to the window beneath. Equivalent to NSWindow's
207 /// `setIgnoresMouseEvents(true)` at the SLS layer.
208 pub fn SLSSetWindowEventShape(cid: CGSConnectionID, wid: u32, shape: CFTypeRef) -> CGError;
209 pub fn SLSSetWindowAlpha(cid: CGSConnectionID, wid: u32, alpha: f32) -> CGError;
210 pub fn SLSSetWindowBackgroundBlurRadius(cid: CGSConnectionID, wid: u32, radius: u32)
211 -> CGError;
212 pub fn SLSSetWindowLevel(cid: CGSConnectionID, wid: u32, level: i32) -> CGError;
213 pub fn SLSOrderWindow(cid: CGSConnectionID, wid: u32, mode: i32, relative_to: u32) -> CGError;
214 pub fn SLSMoveWindow(cid: CGSConnectionID, wid: u32, point: *const CGPoint) -> CGError;
215
216 // Shadow
217 pub fn SLSWindowSetShadowProperties(wid: u32, properties: CFDictionaryRef) -> CGError;
218
219 // Drawing context
220 pub fn SLWindowContextCreate(
221 cid: CGSConnectionID,
222 wid: u32,
223 options: CFDictionaryRef,
224 ) -> CGContextRef;
225
226 // Transactions
227 pub fn SLSTransactionCreate(cid: CGSConnectionID) -> CFTypeRef;
228 pub fn SLSTransactionSetWindowLevel(transaction: CFTypeRef, wid: u32, level: i32) -> CGError;
229 pub fn SLSTransactionMoveWindowWithGroup(
230 transaction: CFTypeRef,
231 wid: u32,
232 point: CGPoint,
233 ) -> CGError;
234 pub fn SLSTransactionOrderWindow(
235 transaction: CFTypeRef,
236 wid: u32,
237 order: i32,
238 rel_wid: u32,
239 ) -> CGError;
240 pub fn SLSTransactionSetWindowAlpha(transaction: CFTypeRef, wid: u32, alpha: f32) -> CGError;
241 pub fn SLSTransactionSetWindowTransform(
242 transaction: CFTypeRef,
243 wid: u32,
244 not: i32,
245 important: i32,
246 transform: CGAffineTransform,
247 ) -> CGError;
248 pub fn SLSTransactionCommit(transaction: CFTypeRef, synchronous: i32) -> CGError;
249 pub fn SLSTransactionSetWindowShape(
250 transaction: CFTypeRef,
251 wid: u32,
252 x_offset: f32,
253 y_offset: f32,
254 shape: CFTypeRef,
255 ) -> CGError;
256
257 // Flicker suppression
258 pub fn SLSDisableUpdate(cid: CGSConnectionID) -> CGError;
259 pub fn SLSReenableUpdate(cid: CGSConnectionID) -> CGError;
260 pub fn SLSFlushWindowContentRegion(
261 cid: CGSConnectionID,
262 wid: u32,
263 dirty: *const c_void,
264 ) -> CGError;
265
266 // Space management
267 pub fn SLSCopySpacesForWindows(
268 cid: CGSConnectionID,
269 selector: i32,
270 window_list: CFArrayRef,
271 ) -> CFArrayRef;
272 pub fn SLSCopyManagedDisplays(cid: CGSConnectionID) -> CFArrayRef;
273 pub fn SLSCopyManagedDisplaySpaces(cid: CGSConnectionID) -> CFArrayRef;
274 pub fn SLSCopyManagedDisplayForWindow(cid: CGSConnectionID, wid: u32) -> CFStringRef;
275 pub fn SLSManagedDisplayGetCurrentSpace(cid: CGSConnectionID, uuid: CFStringRef) -> u64;
276 pub fn SLSCopyActiveMenuBarDisplayIdentifier(cid: CGSConnectionID) -> CFStringRef;
277 pub fn SLSMoveWindowsToManagedSpace(
278 cid: CGSConnectionID,
279 window_list: CFArrayRef,
280 sid: u64,
281 ) -> CGError;
282
283 // Window enumeration
284 pub fn SLSCopyWindowsWithOptionsAndTags(
285 cid: CGSConnectionID,
286 owner: u32,
287 spaces: CFArrayRef,
288 options: u32,
289 set_tags: *const u64,
290 clear_tags: *const u64,
291 ) -> CFArrayRef;
292
293 // Front process detection
294 pub fn _SLPSGetFrontProcess(psn: *mut ProcessSerialNumber) -> i32;
295 pub fn SLSGetConnectionIDForPSN(
296 cid: CGSConnectionID,
297 psn: *mut ProcessSerialNumber,
298 psn_cid: *mut CGSConnectionID,
299 ) -> CGError;
300
301 // Region
302 pub fn CGSNewRegionWithRect(rect: *const CGRect, region: *mut CFTypeRef) -> CGError;
303 }
304
305 // --- CoreGraphics drawing ---
306
307 // --- CGWindowList (public CoreGraphics API) ---
308
309 pub const kCGWindowListOptionOnScreenOnly: u32 = 1 << 0;
310 pub const kCGWindowListOptionAll: u32 = 0;
311 pub const kCGNullWindowID: u32 = 0;
312
313 unsafe extern "C" {
314 pub fn CGWindowListCopyWindowInfo(option: u32, relative_to: u32) -> CFArrayRef;
315 pub fn CGGetDisplaysWithPoint(
316 point: CGPoint,
317 max_displays: u32,
318 displays: *mut u32,
319 count: *mut u32,
320 ) -> CGError;
321 pub fn CGDisplayCopyDisplayMode(display: u32) -> CGDisplayModeRef;
322 pub fn CGDisplayModeGetWidth(mode: CGDisplayModeRef) -> usize;
323 pub fn CGDisplayModeGetHeight(mode: CGDisplayModeRef) -> usize;
324 pub fn CGDisplayModeGetPixelWidth(mode: CGDisplayModeRef) -> usize;
325 pub fn CGDisplayModeGetPixelHeight(mode: CGDisplayModeRef) -> usize;
326 pub fn CFDictionaryGetValueIfPresent(
327 dict: CFDictionaryRef,
328 key: CFTypeRef,
329 value_out: *mut CFTypeRef,
330 ) -> bool;
331 pub fn CFStringCreateWithCString(
332 alloc: CFAllocatorRef,
333 c_str: *const u8,
334 encoding: u32,
335 ) -> CFStringRef;
336 }
337
338 pub const kCFStringEncodingUTF8: u32 = 0x0800_0100;
339
340 // --- CoreGraphics drawing ---
341
342 unsafe extern "C" {
343 pub fn CGContextSetRGBStrokeColor(ctx: CGContextRef, r: f64, g: f64, b: f64, a: f64);
344 pub fn CGContextSetRGBFillColor(ctx: CGContextRef, r: f64, g: f64, b: f64, a: f64);
345 pub fn CGContextSetLineWidth(ctx: CGContextRef, width: f64);
346 pub fn CGContextClearRect(ctx: CGContextRef, rect: CGRect);
347 pub fn CGContextEOFillPath(ctx: CGContextRef);
348 pub fn CGContextAddPath(ctx: CGContextRef, path: CGPathRef);
349 pub fn CGContextStrokePath(ctx: CGContextRef);
350 pub fn CGContextFillPath(ctx: CGContextRef);
351 pub fn CGContextFlush(ctx: CGContextRef);
352 pub fn CGContextRelease(ctx: CGContextRef);
353 pub fn CGContextSaveGState(ctx: CGContextRef);
354 pub fn CGContextRestoreGState(ctx: CGContextRef);
355 pub fn CGContextSetInterpolationQuality(ctx: CGContextRef, quality: i32);
356 pub fn CGContextClip(ctx: CGContextRef);
357 pub fn CGContextEOClip(ctx: CGContextRef);
358 pub fn CGPathCreateWithRoundedRect(
359 rect: CGRect,
360 rx: f64,
361 ry: f64,
362 transform: *const CGAffineTransform,
363 ) -> CGPathRef;
364 pub fn CGPathCreateMutable() -> CGMutablePathRef;
365 pub fn CGPathAddRoundedRect(
366 path: CGMutablePathRef,
367 transform: *const CGAffineTransform,
368 rect: CGRect,
369 rx: f64,
370 ry: f64,
371 );
372 pub fn CGPathAddRect(path: CGMutablePathRef, transform: *const CGAffineTransform, rect: CGRect);
373 pub fn CGPathAddPath(
374 path: CGMutablePathRef,
375 transform: *const CGAffineTransform,
376 other: CGPathRef,
377 );
378 pub fn CGPathRelease(path: CGPathRef);
379 }
380
381 // --- CoreFoundation ---
382
383 unsafe extern "C" {
384 pub fn CFRelease(cf: CFTypeRef);
385 pub fn CFRetain(cf: CFTypeRef) -> CFTypeRef;
386
387 pub fn CFArrayGetCount(array: CFArrayRef) -> i64;
388 pub fn CFArrayGetValueAtIndex(array: CFArrayRef, idx: i64) -> CFTypeRef;
389 pub fn CFArrayCreate(
390 allocator: CFAllocatorRef,
391 values: *const CFTypeRef,
392 count: i64,
393 callbacks: *const c_void,
394 ) -> CFArrayRef;
395
396 pub fn CFNumberCreate(
397 allocator: CFAllocatorRef,
398 the_type: i32,
399 value_ptr: *const c_void,
400 ) -> CFNumberRef;
401 pub fn CFNumberGetValue(number: CFNumberRef, the_type: i32, value_ptr: *mut c_void) -> bool;
402 pub fn CFNumberGetType(number: CFNumberRef) -> i32;
403
404 pub fn CFDictionaryCreate(
405 allocator: CFAllocatorRef,
406 keys: *const CFTypeRef,
407 values: *const CFTypeRef,
408 count: i64,
409 key_callbacks: *const c_void,
410 value_callbacks: *const c_void,
411 ) -> CFDictionaryRef;
412 pub fn CFDictionaryGetValue(dict: CFDictionaryRef, key: CFTypeRef) -> CFTypeRef;
413
414 pub fn CFMachPortCreateWithPort(
415 allocator: CFAllocatorRef,
416 port: u32,
417 callback: *const c_void,
418 context: *const c_void,
419 should_free: bool,
420 ) -> CFMachPortRef;
421
422 pub fn CFMachPortCreateRunLoopSource(
423 allocator: CFAllocatorRef,
424 port: CFMachPortRef,
425 order: i64,
426 ) -> CFRunLoopSourceRef;
427
428 pub fn CFRunLoopGetCurrent() -> CFRunLoopRef;
429 pub fn CFRunLoopGetMain() -> CFRunLoopRef;
430 pub fn CFRunLoopAddSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef);
431 pub fn CFRunLoopRun();
432 pub fn CFRunLoopStop(rl: CFRunLoopRef);
433 pub fn CFRunLoopWakeUp(rl: CFRunLoopRef);
434
435 pub static kCFAllocatorDefault: CFAllocatorRef;
436 pub static kCFTypeDictionaryKeyCallBacks: c_void;
437 pub static kCFTypeDictionaryValueCallBacks: c_void;
438 pub static kCFTypeArrayCallBacks: c_void;
439 pub static kCFRunLoopDefaultMode: CFStringRef;
440 }
441
442 // --- macOS process ---
443
444 unsafe extern "C" {
445 pub fn getpid() -> i32;
446 pub fn pid_for_task(task: u32, pid: *mut i32) -> i32;
447 pub static mach_task_self_: u32;
448 }
449
450 pub fn mach_task_self() -> u32 {
451 unsafe { mach_task_self_ }
452 }
453
454 // --- Helper: create CFArray of CFNumbers ---
455
456 pub unsafe fn cfarray_of_cfnumbers(
457 values: *const c_void,
458 size: usize,
459 count: i32,
460 num_type: i32,
461 ) -> CFArrayRef {
462 unsafe {
463 let mut temp: Vec<CFNumberRef> = Vec::with_capacity(count as usize);
464 for i in 0..count {
465 let ptr = (values as *const u8).add(size * i as usize) as *const c_void;
466 temp.push(CFNumberCreate(std::ptr::null(), num_type, ptr));
467 }
468 let array = CFArrayCreate(
469 std::ptr::null(),
470 temp.as_ptr() as *const CFTypeRef,
471 count as i64,
472 &kCFTypeArrayCallBacks as *const _,
473 );
474 for n in &temp {
475 CFRelease(*n);
476 }
477 array
478 }
479 }
480