1#![allow(clippy::module_name_repetitions)]
11
12#[cfg(target_os = "macos")]
13#[repr(C)]
14#[derive(Clone, Copy)]
15struct NsPoint {
16 x: f64,
17 y: f64,
18}
19
20#[cfg(target_os = "macos")]
21#[repr(C)]
22#[derive(Clone, Copy)]
23struct NsSize {
24 width: f64,
25 height: f64,
26}
27
28#[cfg(target_os = "macos")]
29#[repr(C)]
30#[derive(Clone, Copy)]
31struct NsRect {
32 origin: NsPoint,
33 size: NsSize,
34}
35
36#[cfg(target_os = "macos")]
53pub fn reanchor_to_superview_top(handle: raw_window_handle::RawWindowHandle) {
54 use objc::{msg_send, sel, sel_impl};
55
56 let view_ptr = match handle {
57 raw_window_handle::RawWindowHandle::AppKit(h) => h.ns_view,
58 _ => return,
59 };
60 if view_ptr.is_null() {
61 return;
62 }
63
64 unsafe {
65 let view = view_ptr.cast::<objc::runtime::Object>();
66 let superview: *mut objc::runtime::Object = msg_send![view, superview];
67 if superview.is_null() {
68 return;
69 }
70 let parent_frame: NsRect = msg_send![superview, frame];
71 let child_frame: NsRect = msg_send![view, frame];
72 let new_y = parent_frame.size.height - child_frame.size.height;
73 if (new_y - child_frame.origin.y).abs() < f64::EPSILON {
74 return;
75 }
76 let new_origin = NsPoint {
77 x: child_frame.origin.x,
78 y: new_y,
79 };
80 let _: () = msg_send![view, setFrameOrigin: new_origin];
81 }
82}
83
84#[cfg(not(target_os = "macos"))]
85pub fn reanchor_to_superview_top(_handle: raw_window_handle::RawWindowHandle) {}
86
87#[cfg(target_os = "macos")]
115#[must_use]
116pub fn should_skip_frame(handle: raw_window_handle::RawWindowHandle) -> bool {
117 use objc::{msg_send, sel, sel_impl};
118
119 let view_ptr = match handle {
120 raw_window_handle::RawWindowHandle::AppKit(h) => h.ns_view,
121 _ => return false,
122 };
123 if view_ptr.is_null() {
124 return true;
125 }
126
127 unsafe {
128 let view = view_ptr.cast::<objc::runtime::Object>();
129 let window: *mut objc::runtime::Object = msg_send![view, window];
130 if window.is_null() {
131 return true;
133 }
134 let state: u64 = msg_send![window, occlusionState];
137 state & (1 << 1) == 0
138 }
139}
140
141#[cfg(target_os = "windows")]
142#[must_use]
143pub fn should_skip_frame(handle: raw_window_handle::RawWindowHandle) -> bool {
144 unsafe extern "system" {
145 fn IsWindowVisible(hwnd: *mut std::ffi::c_void) -> i32;
146 fn IsIconic(hwnd: *mut std::ffi::c_void) -> i32;
147 }
148
149 let hwnd = match handle {
150 raw_window_handle::RawWindowHandle::Win32(h) => h.hwnd,
151 _ => return false,
152 };
153 if hwnd.is_null() {
154 return true;
155 }
156 unsafe { IsWindowVisible(hwnd) == 0 || IsIconic(hwnd) != 0 }
160}
161
162#[cfg(not(any(target_os = "macos", target_os = "windows")))]
163#[must_use]
164pub fn should_skip_frame(_handle: raw_window_handle::RawWindowHandle) -> bool {
165 false
166}
167
168#[cfg(target_os = "macos")]
175pub fn reanchor_all_children_to_top(parent: *mut std::ffi::c_void) {
176 use objc::runtime::Object;
177 use objc::{msg_send, sel, sel_impl};
178
179 if parent.is_null() {
180 return;
181 }
182 unsafe {
183 let parent_obj = parent.cast::<Object>();
184 let window: *mut Object = msg_send![parent_obj, window];
189 if window.is_null() {
190 return;
191 }
192 let parent_frame: NsRect = msg_send![parent_obj, frame];
193 let subviews: *mut Object = msg_send![parent_obj, subviews];
194 if subviews.is_null() {
195 return;
196 }
197 let count: usize = msg_send![subviews, count];
198 for i in 0..count {
199 let child: *mut Object = msg_send![subviews, objectAtIndex: i];
200 if child.is_null() {
201 continue;
202 }
203 let child_frame: NsRect = msg_send![child, frame];
204 let new_y = parent_frame.size.height - child_frame.size.height;
205 if (new_y - child_frame.origin.y).abs() < f64::EPSILON {
206 continue;
207 }
208 let new_origin = NsPoint {
209 x: child_frame.origin.x,
210 y: new_y,
211 };
212 let _: () = msg_send![child, setFrameOrigin: new_origin];
213 }
214 }
215}
216
217#[cfg(not(target_os = "macos"))]
218pub fn reanchor_all_children_to_top(_parent: *mut std::ffi::c_void) {}
219
220#[cfg(target_os = "windows")]
237#[must_use]
238#[allow(clippy::cast_possible_truncation, clippy::unnecessary_cast)]
241pub fn wgl_extensions_available() -> bool {
242 use windows_sys::Win32::Graphics::Gdi::{GetDC, ReleaseDC};
243 use windows_sys::Win32::Graphics::OpenGL::{
244 ChoosePixelFormat, PFD_DRAW_TO_WINDOW, PFD_MAIN_PLANE, PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA,
245 PIXELFORMATDESCRIPTOR, SetPixelFormat, wglCreateContext, wglDeleteContext,
246 wglGetProcAddress, wglMakeCurrent,
247 };
248 use windows_sys::Win32::System::LibraryLoader::GetModuleHandleW;
249 use windows_sys::Win32::UI::WindowsAndMessaging::{
250 CS_OWNDC, CreateWindowExW, DefWindowProcW, DestroyWindow, RegisterClassW, UnregisterClassW,
251 WNDCLASSW,
252 };
253 use windows_sys::core::s;
254
255 const CLASS_NAME: &[u16] = &[
257 0x74, 0x72, 0x75, 0x63, 0x65, 0x2d, 0x77, 0x67, 0x6c, 0x2d, 0x70, 0x72, 0x6f, 0x62, 0x65, 0,
258 ];
259
260 unsafe {
261 let hinstance = GetModuleHandleW(std::ptr::null());
262 let class = WNDCLASSW {
263 style: CS_OWNDC,
264 lpfnWndProc: Some(DefWindowProcW),
265 cbClsExtra: 0,
266 cbWndExtra: 0,
267 hInstance: hinstance,
268 hIcon: std::ptr::null_mut(),
269 hCursor: std::ptr::null_mut(),
270 hbrBackground: std::ptr::null_mut(),
271 lpszMenuName: std::ptr::null(),
272 lpszClassName: CLASS_NAME.as_ptr(),
273 };
274 let atom = RegisterClassW(&raw const class);
275 if atom == 0 {
276 return false;
277 }
278 let hwnd = CreateWindowExW(
279 0,
280 CLASS_NAME.as_ptr(),
281 CLASS_NAME.as_ptr(),
282 0,
283 0,
284 0,
285 1,
286 1,
287 std::ptr::null_mut(),
288 std::ptr::null_mut(),
289 hinstance,
290 std::ptr::null(),
291 );
292 if hwnd.is_null() {
293 UnregisterClassW(CLASS_NAME.as_ptr(), hinstance);
294 return false;
295 }
296
297 let mut available = false;
298 let hdc = GetDC(hwnd);
299 if !hdc.is_null() {
300 let pfd = PIXELFORMATDESCRIPTOR {
301 nSize: size_of::<PIXELFORMATDESCRIPTOR>() as u16,
302 nVersion: 1,
303 dwFlags: PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL,
304 iPixelType: PFD_TYPE_RGBA as u8,
305 cColorBits: 32,
306 cDepthBits: 24,
307 cStencilBits: 8,
308 iLayerType: PFD_MAIN_PLANE as u8,
309 ..std::mem::zeroed()
310 };
311 let format = ChoosePixelFormat(hdc, &raw const pfd);
312 if format != 0 && SetPixelFormat(hdc, format, &raw const pfd) != 0 {
313 let hglrc = wglCreateContext(hdc);
314 if !hglrc.is_null() {
315 wglMakeCurrent(hdc, hglrc);
316 available = wglGetProcAddress(s!("wglChoosePixelFormatARB")).is_some()
317 && wglGetProcAddress(s!("wglCreateContextAttribsARB")).is_some();
318 wglMakeCurrent(hdc, std::ptr::null_mut());
319 wglDeleteContext(hglrc);
320 }
321 }
322 ReleaseDC(hwnd, hdc);
323 }
324 DestroyWindow(hwnd);
325 UnregisterClassW(CLASS_NAME.as_ptr(), hinstance);
326 available
327 }
328}