1#![crate_type = "lib"]
17#![crate_type = "rlib"]
18#![crate_type = "dylib"]
19#![crate_name = "glfw"]
20#![deny(
21 rust_2018_compatibility,
22 rust_2018_idioms,
23 nonstandard_style,
24 unused,
25 future_incompatible,
26 missing_copy_implementations,
27 missing_debug_implementations,
28 missing_abi,
29 clippy::doc_markdown
30)]
31#![allow(non_upper_case_globals)]
32
33pub mod ffi {
84 pub use glfw_sys::*;
85}
86macro_rules! make_user_callback_functions {
87 (
88 doc -> $doc:literal,
89 set -> $set:ident,
90 unset -> $unset:ident,
91 poll -> $poll:ident,
92 callback_field -> $callback_field:ident,
93 poll_field -> $poll_field:ident,
94 glfw -> $glfw:ident,
95 args -> ($($args:ty),*),
96 secret -> $secret:ident
97 ) => {
98
99 #[doc = $doc]
100 pub fn $set<T>(&mut self, callback: T)
101 where T: FnMut(&mut Window, $($args),*) + 'static {
102 unsafe {
103 let callbacks = WindowCallbacks::get_callbacks(self.ptr);
104 callbacks.$callback_field = Some(Box::new(callback));
105 ffi::$glfw(self.ptr, Some(Self::$secret));
106 }
107 }
108
109 #[doc = $doc]
110 pub fn $unset(&mut self) {
111 unsafe {
112 let callbacks = WindowCallbacks::get_callbacks(self.ptr);
113 callbacks.$callback_field = None;
114
115 if !callbacks.$poll_field {
117 ffi::$glfw(self.ptr, None);
118 }
119 }
120 }
121
122 #[doc = $doc]
123 pub fn $poll(&mut self, should_poll: bool) {
124 unsafe {
125 let callbacks = WindowCallbacks::get_callbacks(self.ptr);
126 callbacks.$poll_field = should_poll;
127
128 if should_poll {
130 ffi::$glfw(self.ptr, Some(Self::$secret));
131 } else if callbacks.$callback_field.is_none() {
132 ffi::$glfw(self.ptr, None);
133 }
134 }
135 }
136 }
137}
138
139macro_rules! new_callback {
140 (
141 doc -> $doc:literal,
142 set -> $set:ident,
143 unset -> $unset:ident,
144 poll -> $poll:ident,
145 callback_field -> $callback_field:ident,
146 poll_field -> $poll_field:ident,
147 window_event -> $window_event:ident ($($args:ty),+),
148 glfw -> $glfw:ident ($($glfw_arg_names:ident: $glfw_args:ty),*),
149 convert_args -> ($($convert_args:expr),*),
150 secret -> $secret:ident
151 ) => {
152
153 #[allow(unused_unsafe)]
154 extern "C" fn $secret(glfw_window: *mut GLFWwindow, $($glfw_arg_names: $glfw_args),*) {
155 unsafe {
156 let callbacks = WindowCallbacks::get_callbacks(glfw_window);
157 let window = &mut *callbacks.window_ptr;
158 if let Some(func) = &mut callbacks.$callback_field {
159 func(window, $($convert_args),*);
160 }
161 if callbacks.$poll_field {
162 let event = (ffi::glfwGetTime() as f64, WindowEvent::$window_event($($convert_args),*));
163 if let Some(event) = callbacks::unbuffered::handle(glfw_window as WindowId, event) {
164 callbacks.sender.send(event);
165 }
166 }
167 }
168 }
169
170 make_user_callback_functions!(
171 doc -> $doc,
172 set -> $set,
173 unset -> $unset,
174 poll -> $poll,
175 callback_field -> $callback_field,
176 poll_field -> $poll_field,
177 glfw -> $glfw,
178 args -> ($($args),*),
179 secret -> $secret
180 );
181 };
182 (
183 doc -> $doc:literal,
184 set -> $set:ident,
185 unset -> $unset:ident,
186 poll -> $poll:ident,
187 callback_field -> $callback_field:ident,
188 poll_field -> $poll_field:ident,
189 window_event -> $window_event:ident,
190 glfw -> $glfw:ident ($($glfw_arg_names:ident: $glfw_args:ty),*),
191 convert_args -> ($($convert_args:expr),*),
192 secret -> $secret:ident
193 ) => {
194
195 #[allow(unused_unsafe)]
196 extern "C" fn $secret(glfw_window: *mut GLFWwindow, $($glfw_arg_names: $glfw_args),*) {
197 unsafe {
198 let callbacks = WindowCallbacks::get_callbacks(glfw_window);
199 let window = &mut *callbacks.window_ptr;
200 if let Some(func) = &mut callbacks.$callback_field {
201 func(window);
202 }
203 if callbacks.$poll_field {
204 let event = (ffi::glfwGetTime() as f64, WindowEvent::$window_event);
205 if let Some(event) = callbacks::unbuffered::handle(glfw_window as WindowId, event) {
206 callbacks.sender.send(event);
207 }
208 }
209 }
210 }
211
212 make_user_callback_functions!(
213 doc -> $doc,
214 set -> $set,
215 unset -> $unset,
216 poll -> $poll,
217 callback_field -> $callback_field,
218 poll_field -> $poll_field,
219 glfw -> $glfw,
220 args -> (),
221 secret -> $secret
222 );
223 }
224}
225
226#[cfg(feature = "log")]
227#[macro_use]
228extern crate log;
229#[macro_use]
230extern crate bitflags;
231#[cfg(feature = "image")]
232#[allow(unused)]
233extern crate image;
234
235#[cfg(feature = "raw-window-handle-v0-6")]
236extern crate raw_window_handle_0_6 as raw_window_handle;
237
238#[cfg(feature = "raw-window-handle-v0-5")]
239extern crate raw_window_handle_0_5 as raw_window_handle;
240
241use std::collections::VecDeque;
242#[allow(unused)]
243use std::ffi::*;
244use std::ffi::{CStr, CString};
245use std::marker::Send;
246use std::ops::{Deref, DerefMut};
247#[cfg(not(target_os = "emscripten"))]
248use std::os::raw::c_void;
249use std::os::raw::{c_char, c_double, c_float, c_int, c_ushort};
250use std::path::PathBuf;
251use std::ptr::{null, null_mut};
252use std::sync::atomic::{AtomicUsize, Ordering};
253use std::sync::mpsc::{channel, Receiver, Sender};
254use std::sync::{Arc, Mutex};
255use std::{error, fmt, mem, ptr, slice};
256
257#[cfg(feature = "raw-window-handle-v0-6")]
258use raw_window_handle::{
259 DisplayHandle, HandleError, HasDisplayHandle, HasWindowHandle, WindowHandle,
260};
261#[cfg(feature = "raw-window-handle-v0-5")]
262use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
263use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
264#[cfg(feature = "serde")]
265use serde::{Deserialize, Serialize};
266
267pub use self::MouseButton::Button1 as MouseButtonLeft;
269pub use self::MouseButton::Button2 as MouseButtonRight;
271pub use self::MouseButton::Button3 as MouseButtonMiddle;
273use crate::ffi::GLFWwindow;
274
275mod callbacks;
276
277#[derive(Debug)]
278#[repr(transparent)]
279pub struct PWindow(Box<Window>);
280
281impl PWindow {
282 fn raw_ptr(&mut self) -> *mut Window {
283 self.0.deref_mut()
284 }
285}
286
287impl Deref for PWindow {
288 type Target = Window;
289 fn deref(&self) -> &Self::Target {
290 self.0.deref()
291 }
292}
293
294impl DerefMut for PWindow {
295 fn deref_mut(&mut self) -> &mut Self::Target {
296 self.0.deref_mut()
297 }
298}
299
300unsafe impl Send for PWindow {}
301
302unsafe impl Sync for PWindow {}
303
304#[cfg(feature = "raw-window-handle-v0-6")]
306impl HasWindowHandle for PWindow {
307 fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
308 self.0.window_handle()
309 }
310}
311
312#[cfg(feature = "raw-window-handle-v0-6")]
313impl HasDisplayHandle for PWindow {
314 fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
315 self.0.display_handle()
316 }
317}
318
319pub type WindowId = usize;
321
322#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
323#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
324pub struct Version {
325 pub major: u64,
326 pub minor: u64,
327 pub patch: u64,
328}
329
330#[repr(i32)]
332#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
333#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
334pub enum Action {
335 Release = ffi::GLFW_RELEASE,
336 Press = ffi::GLFW_PRESS,
337 Repeat = ffi::GLFW_REPEAT,
338}
339
340#[repr(i32)]
342#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
343#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
344pub enum Key {
345 Space = ffi::GLFW_KEY_SPACE,
346 Apostrophe = ffi::GLFW_KEY_APOSTROPHE,
347 Comma = ffi::GLFW_KEY_COMMA,
348 Minus = ffi::GLFW_KEY_MINUS,
349 Period = ffi::GLFW_KEY_PERIOD,
350 Slash = ffi::GLFW_KEY_SLASH,
351 Num0 = ffi::GLFW_KEY_0,
352 Num1 = ffi::GLFW_KEY_1,
353 Num2 = ffi::GLFW_KEY_2,
354 Num3 = ffi::GLFW_KEY_3,
355 Num4 = ffi::GLFW_KEY_4,
356 Num5 = ffi::GLFW_KEY_5,
357 Num6 = ffi::GLFW_KEY_6,
358 Num7 = ffi::GLFW_KEY_7,
359 Num8 = ffi::GLFW_KEY_8,
360 Num9 = ffi::GLFW_KEY_9,
361 Semicolon = ffi::GLFW_KEY_SEMICOLON,
362 Equal = ffi::GLFW_KEY_EQUAL,
363 A = ffi::GLFW_KEY_A,
364 B = ffi::GLFW_KEY_B,
365 C = ffi::GLFW_KEY_C,
366 D = ffi::GLFW_KEY_D,
367 E = ffi::GLFW_KEY_E,
368 F = ffi::GLFW_KEY_F,
369 G = ffi::GLFW_KEY_G,
370 H = ffi::GLFW_KEY_H,
371 I = ffi::GLFW_KEY_I,
372 J = ffi::GLFW_KEY_J,
373 K = ffi::GLFW_KEY_K,
374 L = ffi::GLFW_KEY_L,
375 M = ffi::GLFW_KEY_M,
376 N = ffi::GLFW_KEY_N,
377 O = ffi::GLFW_KEY_O,
378 P = ffi::GLFW_KEY_P,
379 Q = ffi::GLFW_KEY_Q,
380 R = ffi::GLFW_KEY_R,
381 S = ffi::GLFW_KEY_S,
382 T = ffi::GLFW_KEY_T,
383 U = ffi::GLFW_KEY_U,
384 V = ffi::GLFW_KEY_V,
385 W = ffi::GLFW_KEY_W,
386 X = ffi::GLFW_KEY_X,
387 Y = ffi::GLFW_KEY_Y,
388 Z = ffi::GLFW_KEY_Z,
389 LeftBracket = ffi::GLFW_KEY_LEFT_BRACKET,
390 Backslash = ffi::GLFW_KEY_BACKSLASH,
391 RightBracket = ffi::GLFW_KEY_RIGHT_BRACKET,
392 GraveAccent = ffi::GLFW_KEY_GRAVE_ACCENT,
393 World1 = ffi::GLFW_KEY_WORLD_1,
394 World2 = ffi::GLFW_KEY_WORLD_2,
395
396 Escape = ffi::GLFW_KEY_ESCAPE,
397 Enter = ffi::GLFW_KEY_ENTER,
398 Tab = ffi::GLFW_KEY_TAB,
399 Backspace = ffi::GLFW_KEY_BACKSPACE,
400 Insert = ffi::GLFW_KEY_INSERT,
401 Delete = ffi::GLFW_KEY_DELETE,
402 Right = ffi::GLFW_KEY_RIGHT,
403 Left = ffi::GLFW_KEY_LEFT,
404 Down = ffi::GLFW_KEY_DOWN,
405 Up = ffi::GLFW_KEY_UP,
406 PageUp = ffi::GLFW_KEY_PAGE_UP,
407 PageDown = ffi::GLFW_KEY_PAGE_DOWN,
408 Home = ffi::GLFW_KEY_HOME,
409 End = ffi::GLFW_KEY_END,
410 CapsLock = ffi::GLFW_KEY_CAPS_LOCK,
411 ScrollLock = ffi::GLFW_KEY_SCROLL_LOCK,
412 NumLock = ffi::GLFW_KEY_NUM_LOCK,
413 PrintScreen = ffi::GLFW_KEY_PRINT_SCREEN,
414 Pause = ffi::GLFW_KEY_PAUSE,
415 F1 = ffi::GLFW_KEY_F1,
416 F2 = ffi::GLFW_KEY_F2,
417 F3 = ffi::GLFW_KEY_F3,
418 F4 = ffi::GLFW_KEY_F4,
419 F5 = ffi::GLFW_KEY_F5,
420 F6 = ffi::GLFW_KEY_F6,
421 F7 = ffi::GLFW_KEY_F7,
422 F8 = ffi::GLFW_KEY_F8,
423 F9 = ffi::GLFW_KEY_F9,
424 F10 = ffi::GLFW_KEY_F10,
425 F11 = ffi::GLFW_KEY_F11,
426 F12 = ffi::GLFW_KEY_F12,
427 F13 = ffi::GLFW_KEY_F13,
428 F14 = ffi::GLFW_KEY_F14,
429 F15 = ffi::GLFW_KEY_F15,
430 F16 = ffi::GLFW_KEY_F16,
431 F17 = ffi::GLFW_KEY_F17,
432 F18 = ffi::GLFW_KEY_F18,
433 F19 = ffi::GLFW_KEY_F19,
434 F20 = ffi::GLFW_KEY_F20,
435 F21 = ffi::GLFW_KEY_F21,
436 F22 = ffi::GLFW_KEY_F22,
437 F23 = ffi::GLFW_KEY_F23,
438 F24 = ffi::GLFW_KEY_F24,
439 F25 = ffi::GLFW_KEY_F25,
440 Kp0 = ffi::GLFW_KEY_KP_0,
441 Kp1 = ffi::GLFW_KEY_KP_1,
442 Kp2 = ffi::GLFW_KEY_KP_2,
443 Kp3 = ffi::GLFW_KEY_KP_3,
444 Kp4 = ffi::GLFW_KEY_KP_4,
445 Kp5 = ffi::GLFW_KEY_KP_5,
446 Kp6 = ffi::GLFW_KEY_KP_6,
447 Kp7 = ffi::GLFW_KEY_KP_7,
448 Kp8 = ffi::GLFW_KEY_KP_8,
449 Kp9 = ffi::GLFW_KEY_KP_9,
450 KpDecimal = ffi::GLFW_KEY_KP_DECIMAL,
451 KpDivide = ffi::GLFW_KEY_KP_DIVIDE,
452 KpMultiply = ffi::GLFW_KEY_KP_MULTIPLY,
453 KpSubtract = ffi::GLFW_KEY_KP_SUBTRACT,
454 KpAdd = ffi::GLFW_KEY_KP_ADD,
455 KpEnter = ffi::GLFW_KEY_KP_ENTER,
456 KpEqual = ffi::GLFW_KEY_KP_EQUAL,
457 LeftShift = ffi::GLFW_KEY_LEFT_SHIFT,
458 LeftControl = ffi::GLFW_KEY_LEFT_CONTROL,
459 LeftAlt = ffi::GLFW_KEY_LEFT_ALT,
460 LeftSuper = ffi::GLFW_KEY_LEFT_SUPER,
461 RightShift = ffi::GLFW_KEY_RIGHT_SHIFT,
462 RightControl = ffi::GLFW_KEY_RIGHT_CONTROL,
463 RightAlt = ffi::GLFW_KEY_RIGHT_ALT,
464 RightSuper = ffi::GLFW_KEY_RIGHT_SUPER,
465 Menu = ffi::GLFW_KEY_MENU,
466 Unknown = ffi::GLFW_KEY_UNKNOWN,
467}
468
469pub fn get_key_name(key: Option<Key>, scancode: Option<Scancode>) -> Option<String> {
471 unsafe {
472 string_from_nullable_c_str(ffi::glfwGetKeyName(
473 match key {
474 Some(k) => k as c_int,
475 None => ffi::GLFW_KEY_UNKNOWN,
476 },
477 scancode.unwrap_or(ffi::GLFW_KEY_UNKNOWN),
478 ))
479 }
480}
481
482#[deprecated(
484 since = "0.16.0",
485 note = "'key_name' can cause a segfault, use 'get_key_name' instead"
486)]
487pub fn key_name(key: Option<Key>, scancode: Option<Scancode>) -> String {
488 unsafe {
489 string_from_c_str(ffi::glfwGetKeyName(
490 match key {
491 Some(k) => k as c_int,
492 None => ffi::GLFW_KEY_UNKNOWN,
493 },
494 scancode.unwrap_or(ffi::GLFW_KEY_UNKNOWN),
495 ))
496 }
497}
498
499pub fn get_key_scancode(key: Option<Key>) -> Option<Scancode> {
501 unsafe {
502 match ffi::glfwGetKeyScancode(match key {
503 Some(key) => key as c_int,
504 None => ffi::GLFW_KEY_UNKNOWN,
505 }) {
506 ffi::GLFW_KEY_UNKNOWN => None,
507 scancode => Some(scancode as Scancode),
508 }
509 }
510}
511
512impl Key {
513 #[deprecated(
515 since = "0.16.0",
516 note = "Key method 'name' can cause a segfault, use 'get_name' instead"
517 )]
518 pub fn name(&self) -> String {
519 #[allow(deprecated)]
520 key_name(Some(*self), None)
521 }
522
523 pub fn get_name(&self) -> Option<String> {
525 get_key_name(Some(*self), None)
526 }
527
528 pub fn get_scancode(&self) -> Option<Scancode> {
530 get_key_scancode(Some(*self))
531 }
532}
533
534#[repr(i32)]
537#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
538#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
539pub enum MouseButton {
540 Button1 = ffi::GLFW_MOUSE_BUTTON_1,
542 Button2 = ffi::GLFW_MOUSE_BUTTON_2,
544 Button3 = ffi::GLFW_MOUSE_BUTTON_3,
546 Button4 = ffi::GLFW_MOUSE_BUTTON_4,
547 Button5 = ffi::GLFW_MOUSE_BUTTON_5,
548 Button6 = ffi::GLFW_MOUSE_BUTTON_6,
549 Button7 = ffi::GLFW_MOUSE_BUTTON_7,
550 Button8 = ffi::GLFW_MOUSE_BUTTON_8,
551}
552
553impl MouseButton {
554 pub const Left: Self = MouseButton::Button1;
556 pub const Right: Self = MouseButton::Button2;
558 pub const Middle: Self = MouseButton::Button3;
560
561 pub fn from_i32(n: i32) -> Option<MouseButton> {
563 if (0..=ffi::GLFW_MOUSE_BUTTON_LAST).contains(&n) {
564 Some(unsafe { mem::transmute(n) })
565 } else {
566 None
567 }
568 }
569}
570
571pub struct DebugAliases<T>(pub T);
580
581impl fmt::Debug for DebugAliases<MouseButton> {
582 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
583 let DebugAliases(button) = *self;
584 match button {
585 MouseButtonLeft => write!(f, "MouseButtonLeft"),
586 MouseButtonRight => write!(f, "MouseButtonRight"),
587 MouseButtonMiddle => write!(f, "MouseButtonMiddle"),
588 button => button.fmt(f),
589 }
590 }
591}
592
593#[repr(i32)]
595#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
596#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
597pub enum Error {
598 NoError = ffi::GLFW_NO_ERROR,
599 NotInitialized = ffi::GLFW_NOT_INITIALIZED,
600 NoCurrentContext = ffi::GLFW_NO_CURRENT_CONTEXT,
601 InvalidEnum = ffi::GLFW_INVALID_ENUM,
602 InvalidValue = ffi::GLFW_INVALID_VALUE,
603 OutOfMemory = ffi::GLFW_OUT_OF_MEMORY,
604 ApiUnavailable = ffi::GLFW_API_UNAVAILABLE,
605 VersionUnavailable = ffi::GLFW_VERSION_UNAVAILABLE,
606 PlatformError = ffi::GLFW_PLATFORM_ERROR,
607 FormatUnavailable = ffi::GLFW_FORMAT_UNAVAILABLE,
608 NoWindowContext = ffi::GLFW_NO_WINDOW_CONTEXT,
609}
610
611impl fmt::Display for Error {
612 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
613 let description = match *self {
614 Error::NoError => "NoError",
615 Error::NotInitialized => "NotInitialized",
616 Error::NoCurrentContext => "NoCurrentContext",
617 Error::InvalidEnum => "InvalidEnum",
618 Error::InvalidValue => "InvalidValue",
619 Error::OutOfMemory => "OutOfMemory",
620 Error::ApiUnavailable => "ApiUnavailable",
621 Error::VersionUnavailable => "VersionUnavailable",
622 Error::PlatformError => "PlatformError",
623 Error::FormatUnavailable => "FormatUnavailable",
624 Error::NoWindowContext => "NoWindowContext",
625 };
626
627 f.write_str(description)
628 }
629}
630
631impl error::Error for Error {}
632
633pub fn fail_on_errors(e: Error, description: String) {
635 if e == Error::FormatUnavailable {
636 return;
642 }
643 panic!("GLFW Error: {}", description);
644}
645
646#[macro_export]
648macro_rules! fail_on_errors {
649 () => {{
650 |error, description| {
651 fail_on_errors(error, description);
652 }
653 }};
654}
655
656#[cfg(feature = "log")]
657pub fn log_errors(_: Error, description: String) {
659 error!("GLFW Error: {}", description);
660}
661
662#[cfg(not(feature = "log"))]
663pub fn log_errors(_: Error, description: String) {
665 eprintln!("GLFW Error: {}", description);
666}
667
668#[macro_export]
671macro_rules! log_errors {
672 () => {{
673 |error, description| {
674 log_errors(error, description);
675 }
676 }};
677}
678
679#[derive(Debug)]
682pub struct PixelImage {
683 pub width: u32,
685 pub height: u32,
687 pub pixels: Vec<u32>,
689}
690
691#[repr(i32)]
693#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
694#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
695pub enum CursorMode {
696 Normal = ffi::GLFW_CURSOR_NORMAL,
697 Hidden = ffi::GLFW_CURSOR_HIDDEN,
698 Disabled = ffi::GLFW_CURSOR_DISABLED,
699}
700
701#[repr(i32)]
703#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
704#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
705pub enum StandardCursor {
706 Arrow = ffi::GLFW_ARROW_CURSOR,
708 IBeam = ffi::GLFW_IBEAM_CURSOR,
710 Crosshair = ffi::GLFW_CROSSHAIR_CURSOR,
712 Hand = ffi::GLFW_HAND_CURSOR,
714 HResize = ffi::GLFW_HRESIZE_CURSOR,
716 VResize = ffi::GLFW_VRESIZE_CURSOR,
718}
719
720#[derive(Debug)]
726pub struct Cursor {
727 ptr: *mut ffi::GLFWcursor,
728}
729
730impl Drop for Cursor {
731 fn drop(&mut self) {
732 unsafe { ffi::glfwDestroyCursor(self.ptr) }
733 }
734}
735
736impl Cursor {
737 pub fn standard(cursor: StandardCursor) -> Cursor {
739 Cursor {
740 ptr: unsafe { ffi::glfwCreateStandardCursor(cursor as c_int) },
741 }
742 }
743
744 #[cfg(feature = "image")]
753 pub fn create(image: image::RgbaImage, x_hotspot: u32, y_hotspot: u32) -> Cursor {
754 let (width, height) = image.dimensions();
755
756 let image_data = image.into_vec();
757
758 let glfw_image = ffi::GLFWimage {
759 width: width as c_int,
760 height: height as c_int,
761 pixels: image_data.as_ptr() as _,
762 };
763
764 Cursor {
765 ptr: unsafe {
766 ffi::glfwCreateCursor(
767 &glfw_image as *const ffi::GLFWimage,
768 x_hotspot as c_int,
769 y_hotspot as c_int,
770 )
771 },
772 }
773 }
774
775 pub fn create_from_pixels(image: PixelImage, x_hotspot: u32, y_hotspot: u32) -> Cursor {
784 let glfw_image = ffi::GLFWimage {
785 width: image.width as c_int,
786 height: image.height as c_int,
787 pixels: image.pixels.as_ptr() as _,
788 };
789
790 Cursor {
791 ptr: unsafe {
792 ffi::glfwCreateCursor(
793 &glfw_image as *const ffi::GLFWimage,
794 x_hotspot as c_int,
795 y_hotspot as c_int,
796 )
797 },
798 }
799 }
800}
801
802#[derive(Copy, Clone)]
804#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
805pub struct VidMode {
806 pub width: u32,
807 pub height: u32,
808 pub red_bits: u32,
809 pub green_bits: u32,
810 pub blue_bits: u32,
811 pub refresh_rate: u32,
812}
813
814#[derive(Debug)]
816#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
817pub struct GammaRamp {
818 pub red: Vec<c_ushort>,
819 pub green: Vec<c_ushort>,
820 pub blue: Vec<c_ushort>,
821}
822
823#[repr(i32)]
825#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
826#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
827pub enum ContextReleaseBehavior {
828 Any = ffi::GLFW_ANY_RELEASE_BEHAVIOR,
829 Flush = ffi::GLFW_RELEASE_BEHAVIOR_FLUSH,
832 None = ffi::GLFW_RELEASE_BEHAVIOR_NONE,
834}
835
836#[repr(i32)]
838#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
839#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
840pub enum ContextCreationApi {
841 Native = ffi::GLFW_NATIVE_CONTEXT_API,
842 Egl = ffi::GLFW_EGL_CONTEXT_API,
843 OsMesa = ffi::GLFW_OSMESA_CONTEXT_API,
844}
845
846#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
852#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
853pub enum SwapInterval {
854 None,
856 Adaptive,
859 Sync(u32),
861}
862
863pub type GLProc = ffi::GLFWglproc;
865
866#[cfg(feature = "vulkan")]
868pub type VkProc = ffi::GLFWvkproc;
869
870static REF_COUNT_FOR_GLFW: AtomicUsize = AtomicUsize::new(0);
873
874#[derive(Debug)]
876pub struct ThreadSafeGlfw {
877 glfw: Glfw,
878}
879
880impl ThreadSafeGlfw {
881 pub fn from(glfw: &mut Glfw) -> Self {
883 Self { glfw: glfw.clone() }
884 }
885
886 pub fn set_swap_interval(&mut self, interval: SwapInterval) {
888 self.glfw.set_swap_interval(interval);
889 }
890
891 pub fn extension_supported(&self, extension: &str) -> bool {
893 self.glfw.extension_supported(extension)
894 }
895
896 pub fn get_time(&self) -> f64 {
898 self.glfw.get_time()
899 }
900
901 pub fn set_time(&mut self, time: f64) {
903 self.glfw.set_time(time);
904 }
905
906 #[cfg(feature = "vulkan")]
908 pub fn vulkan_supported(&self) -> bool {
909 self.glfw.vulkan_supported()
910 }
911
912 #[cfg(feature = "vulkan")]
914 pub fn get_required_instance_extensions(&self) -> Option<Vec<String>> {
915 self.glfw.get_required_instance_extensions()
916 }
917
918 #[cfg(feature = "vulkan")]
920 pub fn get_instance_proc_address_raw(
921 &self,
922 instance: ffi::VkInstance,
923 procname: &str,
924 ) -> VkProc {
925 self.glfw.get_instance_proc_address_raw(instance, procname)
926 }
927
928 #[cfg(feature = "vulkan")]
930 pub fn get_physical_device_presentation_support_raw(
931 &self,
932 instance: ffi::VkInstance,
933 device: ffi::VkPhysicalDevice,
934 queue_family: u32,
935 ) -> bool {
936 self.glfw
937 .get_physical_device_presentation_support_raw(instance, device, queue_family)
938 }
939
940 pub fn get_timer_value(&self) -> u64 {
942 self.glfw.get_timer_value()
943 }
944
945 pub fn get_timer_frequency(&self) -> u64 {
947 self.glfw.get_timer_frequency()
948 }
949
950 pub fn post_empty_event(&self) {
952 self.glfw.post_empty_event()
953 }
954}
955
956unsafe impl Send for ThreadSafeGlfw {}
957
958#[non_exhaustive]
964#[derive(Debug)]
965pub struct Glfw {
966 phantom: std::marker::PhantomData<*const ()>,
967}
968
969#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
971#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
972pub enum InitError {
973 AlreadyInitialized,
975 Internal,
977}
978
979impl fmt::Display for InitError {
980 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
981 let description = match *self {
982 InitError::AlreadyInitialized => "Already Initialized",
983 InitError::Internal => "Internal Initialization Error",
984 };
985
986 f.write_str(description)
987 }
988}
989
990impl error::Error for InitError {}
991
992#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
994#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
995pub enum InitHint {
996 Platform(Platform),
997 JoystickHatButtons(bool),
1000 CocoaChdirResources(bool),
1005 CocoaMenubar(bool),
1010}
1011
1012#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
1017#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1018#[repr(i32)]
1019pub enum Platform {
1020 X11 = ffi::GLFW_PLATFORM_X11,
1021 Wayland = ffi::GLFW_PLATFORM_WAYLAND,
1022 Win32 = ffi::GLFW_PLATFORM_WIN32,
1023 MacOS = ffi::GLFW_PLATFORM_COCOA,
1024 Null = ffi::GLFW_PLATFORM_NULL,
1026 Any = ffi::GLFW_ANY_PLATFORM,
1028}
1029impl Platform {
1030 pub fn is_supported(&self) -> bool {
1032 unsafe { ffi::glfwPlatformSupported(*self as c_int) == ffi::GLFW_TRUE }
1033 }
1034}
1035pub fn init_hint(hint: InitHint) {
1043 match hint {
1044 InitHint::Platform(platform) => unsafe {
1045 ffi::glfwInitHint(ffi::GLFW_PLATFORM, platform as c_int)
1046 },
1047 InitHint::JoystickHatButtons(joystick_hat_buttons) => unsafe {
1048 ffi::glfwInitHint(
1049 ffi::GLFW_JOYSTICK_HAT_BUTTONS,
1050 joystick_hat_buttons as c_int,
1051 )
1052 },
1053 InitHint::CocoaChdirResources(chdir) => unsafe {
1054 ffi::glfwInitHint(ffi::GLFW_COCOA_CHDIR_RESOURCES, chdir as c_int)
1055 },
1056 InitHint::CocoaMenubar(menubar) => unsafe {
1057 ffi::glfwInitHint(ffi::GLFW_COCOA_MENUBAR, menubar as c_int)
1058 },
1059 }
1060}
1061pub fn init<T>(callback: T) -> Result<Glfw, InitError>
1104where
1105 T: FnMut(Error, String) + 'static,
1106{
1107 callbacks::error::set(callback);
1111
1112 init_no_callbacks()
1113}
1114
1115pub fn init_no_callbacks() -> Result<Glfw, InitError> {
1116 if unsafe { ffi::glfwInit() } == ffi::GLFW_TRUE {
1120 REF_COUNT_FOR_GLFW.fetch_add(1, Ordering::SeqCst);
1121 Ok(Glfw {
1122 phantom: std::marker::PhantomData,
1123 })
1124 } else {
1125 Err(InitError::Internal)
1126 }
1127}
1128
1129impl Glfw {
1130 pub fn set_error_callback<T>(&mut self, callback: T)
1154 where
1155 T: FnMut(Error, String) + 'static,
1156 {
1157 callbacks::error::set(callback);
1158 }
1159
1160 pub fn unset_error_callback(&mut self) {
1162 callbacks::error::unset();
1163 }
1164
1165 pub fn set_monitor_callback<T>(&mut self, callback: T)
1167 where
1168 T: FnMut(Monitor, MonitorEvent) + 'static,
1169 {
1170 callbacks::monitor::set(callback);
1171 }
1172
1173 pub fn unset_monitor_callback(&mut self) {
1175 callbacks::monitor::unset();
1176 }
1177
1178 pub fn set_joystick_callback<T>(&mut self, callback: T)
1180 where
1181 T: FnMut(JoystickId, JoystickEvent) + 'static,
1182 {
1183 callbacks::joystick::set(callback);
1184 }
1185
1186 pub fn unset_joystick_callback(&mut self) {
1188 callbacks::joystick::unset();
1189 }
1190
1191 pub fn with_primary_monitor<T, F>(&mut self, f: F) -> T
1204 where
1205 F: FnOnce(&mut Self, Option<&mut Monitor>) -> T,
1206 {
1207 match unsafe { ffi::glfwGetPrimaryMonitor() } {
1208 ptr if ptr.is_null() => f(self, None),
1209 ptr => f(self, Some(&mut Monitor { ptr })),
1210 }
1211 }
1212
1213 pub fn with_window_monitor<T, F>(&mut self, window: &mut Window, f: F) -> T
1224 where
1225 F: FnOnce(&mut Self, Option<&mut Monitor>) -> T,
1226 {
1227 match unsafe { ffi::glfwGetWindowMonitor(window.ptr) } {
1228 ptr if ptr.is_null() => f(self, None),
1229 ptr => f(self, Some(&mut Monitor { ptr })),
1230 }
1231 }
1232
1233 pub fn with_connected_monitors<T, F>(&mut self, f: F) -> T
1246 where
1247 F: FnOnce(&mut Self, &[&mut Monitor]) -> T,
1248 {
1249 unsafe {
1250 let mut count = 0;
1251 let ptr = ffi::glfwGetMonitors(&mut count);
1252 let mut monitors = slice::from_raw_parts(ptr as *const _, count as usize)
1253 .iter()
1254 .map(|&ptr| Monitor { ptr })
1255 .collect::<Vec<Monitor>>();
1256
1257 let refs: Vec<&mut Monitor> = monitors.iter_mut().collect();
1258 f(self, &refs)
1259 }
1260 }
1261
1262 #[cfg(feature = "vulkan")]
1264 pub fn vulkan_supported(&self) -> bool {
1265 unsafe { ffi::glfwVulkanSupported() == ffi::GLFW_TRUE }
1266 }
1267
1268 pub fn window_hint(&mut self, hint: WindowHint) {
1298 #[inline(always)]
1303 unsafe fn dont_care_hint(hint: c_int, value: Option<u32>) {
1304 ffi::glfwWindowHint(hint, unwrap_dont_care(value))
1305 }
1306
1307 #[inline(always)]
1308 unsafe fn string_hint(hint: c_int, value: Option<String>) {
1309 let value = if let Some(value) = &value {
1310 value.as_str()
1311 } else {
1312 ""
1313 };
1314 with_c_str(value, |value| ffi::glfwWindowHintString(hint, value))
1315 }
1316
1317 match hint {
1318 WindowHint::MousePassthrough(value) => unsafe {
1319 ffi::glfwWindowHint(ffi::GLFW_MOUSE_PASSTHROUGH, value as c_int)
1320 },
1321 WindowHint::RedBits(bits) => unsafe { dont_care_hint(ffi::GLFW_RED_BITS, bits) },
1322 WindowHint::GreenBits(bits) => unsafe { dont_care_hint(ffi::GLFW_GREEN_BITS, bits) },
1323 WindowHint::BlueBits(bits) => unsafe { dont_care_hint(ffi::GLFW_BLUE_BITS, bits) },
1324 WindowHint::AlphaBits(bits) => unsafe { dont_care_hint(ffi::GLFW_ALPHA_BITS, bits) },
1325 WindowHint::DepthBits(bits) => unsafe { dont_care_hint(ffi::GLFW_DEPTH_BITS, bits) },
1326 WindowHint::StencilBits(bits) => unsafe {
1327 dont_care_hint(ffi::GLFW_STENCIL_BITS, bits)
1328 },
1329 WindowHint::AccumRedBits(bits) => unsafe {
1330 dont_care_hint(ffi::GLFW_ACCUM_RED_BITS, bits)
1331 },
1332 WindowHint::AccumGreenBits(bits) => unsafe {
1333 dont_care_hint(ffi::GLFW_ACCUM_GREEN_BITS, bits)
1334 },
1335 WindowHint::AccumBlueBits(bits) => unsafe {
1336 dont_care_hint(ffi::GLFW_ACCUM_BLUE_BITS, bits)
1337 },
1338 WindowHint::AccumAlphaBits(bits) => unsafe {
1339 dont_care_hint(ffi::GLFW_ACCUM_ALPHA_BITS, bits)
1340 },
1341 WindowHint::AuxBuffers(num_buffers) => unsafe {
1342 dont_care_hint(ffi::GLFW_AUX_BUFFERS, num_buffers)
1343 },
1344 WindowHint::Samples(num_samples) => unsafe {
1345 dont_care_hint(ffi::GLFW_SAMPLES, num_samples)
1346 },
1347 WindowHint::RefreshRate(rate) => unsafe {
1348 dont_care_hint(ffi::GLFW_REFRESH_RATE, rate)
1349 },
1350 WindowHint::Stereo(is_stereo) => unsafe {
1351 ffi::glfwWindowHint(ffi::GLFW_STEREO, is_stereo as c_int)
1352 },
1353 WindowHint::SRgbCapable(is_capable) => unsafe {
1354 ffi::glfwWindowHint(ffi::GLFW_SRGB_CAPABLE, is_capable as c_int)
1355 },
1356 WindowHint::ClientApi(api) => unsafe {
1357 ffi::glfwWindowHint(ffi::GLFW_CLIENT_API, api as c_int)
1358 },
1359 WindowHint::ContextVersionMajor(major) => unsafe {
1360 ffi::glfwWindowHint(ffi::GLFW_CONTEXT_VERSION_MAJOR, major as c_int)
1361 },
1362 WindowHint::ContextVersionMinor(minor) => unsafe {
1363 ffi::glfwWindowHint(ffi::GLFW_CONTEXT_VERSION_MINOR, minor as c_int)
1364 },
1365 WindowHint::ContextVersion(major, minor) => unsafe {
1366 ffi::glfwWindowHint(ffi::GLFW_CONTEXT_VERSION_MAJOR, major as c_int);
1367 ffi::glfwWindowHint(ffi::GLFW_CONTEXT_VERSION_MINOR, minor as c_int)
1368 },
1369 WindowHint::ContextRobustness(robustness) => unsafe {
1370 ffi::glfwWindowHint(ffi::GLFW_CONTEXT_ROBUSTNESS, robustness as c_int)
1371 },
1372 WindowHint::OpenGlForwardCompat(is_compat) => unsafe {
1373 ffi::glfwWindowHint(ffi::GLFW_OPENGL_FORWARD_COMPAT, is_compat as c_int)
1374 },
1375 WindowHint::OpenGlDebugContext(is_debug) => unsafe {
1376 ffi::glfwWindowHint(ffi::GLFW_OPENGL_DEBUG_CONTEXT, is_debug as c_int)
1377 },
1378 WindowHint::OpenGlProfile(profile) => unsafe {
1379 ffi::glfwWindowHint(ffi::GLFW_OPENGL_PROFILE, profile as c_int)
1380 },
1381 WindowHint::Resizable(is_resizable) => unsafe {
1382 ffi::glfwWindowHint(ffi::GLFW_RESIZABLE, is_resizable as c_int)
1383 },
1384 WindowHint::Visible(is_visible) => unsafe {
1385 ffi::glfwWindowHint(ffi::GLFW_VISIBLE, is_visible as c_int)
1386 },
1387 WindowHint::Decorated(is_decorated) => unsafe {
1388 ffi::glfwWindowHint(ffi::GLFW_DECORATED, is_decorated as c_int)
1389 },
1390 WindowHint::AutoIconify(auto_iconify) => unsafe {
1391 ffi::glfwWindowHint(ffi::GLFW_AUTO_ICONIFY, auto_iconify as c_int)
1392 },
1393 WindowHint::Floating(is_floating) => unsafe {
1394 ffi::glfwWindowHint(ffi::GLFW_FLOATING, is_floating as c_int)
1395 },
1396 WindowHint::Focused(is_focused) => unsafe {
1397 ffi::glfwWindowHint(ffi::GLFW_FOCUSED, is_focused as c_int)
1398 },
1399 WindowHint::Maximized(is_maximized) => unsafe {
1400 ffi::glfwWindowHint(ffi::GLFW_MAXIMIZED, is_maximized as c_int)
1401 },
1402 WindowHint::ContextNoError(is_no_error) => unsafe {
1403 ffi::glfwWindowHint(ffi::GLFW_CONTEXT_NO_ERROR, is_no_error as c_int)
1404 },
1405 WindowHint::ContextCreationApi(api) => unsafe {
1406 ffi::glfwWindowHint(ffi::GLFW_CONTEXT_CREATION_API, api as c_int)
1407 },
1408 WindowHint::ContextReleaseBehavior(behavior) => unsafe {
1409 ffi::glfwWindowHint(ffi::GLFW_CONTEXT_RELEASE_BEHAVIOR, behavior as c_int)
1410 },
1411 WindowHint::DoubleBuffer(is_dbuffered) => unsafe {
1412 ffi::glfwWindowHint(ffi::GLFW_DOUBLEBUFFER, is_dbuffered as c_int)
1413 },
1414 WindowHint::CenterCursor(center_cursor) => unsafe {
1415 ffi::glfwWindowHint(ffi::GLFW_CENTER_CURSOR, center_cursor as c_int)
1416 },
1417 WindowHint::TransparentFramebuffer(is_transparent) => unsafe {
1418 ffi::glfwWindowHint(ffi::GLFW_TRANSPARENT_FRAMEBUFFER, is_transparent as c_int)
1419 },
1420 WindowHint::FocusOnShow(focus) => unsafe {
1421 ffi::glfwWindowHint(ffi::GLFW_FOCUS_ON_SHOW, focus as c_int)
1422 },
1423 WindowHint::ScaleToMonitor(scale) => unsafe {
1424 ffi::glfwWindowHint(ffi::GLFW_SCALE_TO_MONITOR, scale as c_int)
1425 },
1426 WindowHint::CocoaRetinaFramebuffer(retina_fb) => unsafe {
1427 ffi::glfwWindowHint(ffi::GLFW_COCOA_RETINA_FRAMEBUFFER, retina_fb as c_int)
1428 },
1429 WindowHint::CocoaFrameName(name) => unsafe {
1430 string_hint(ffi::GLFW_COCOA_FRAME_NAME, name)
1431 },
1432 WindowHint::CocoaGraphicsSwitching(graphics_switching) => unsafe {
1433 ffi::glfwWindowHint(
1434 ffi::GLFW_COCOA_GRAPHICS_SWITCHING,
1435 graphics_switching as c_int,
1436 )
1437 },
1438 WindowHint::X11ClassName(class_name) => unsafe {
1439 string_hint(ffi::GLFW_X11_CLASS_NAME, class_name)
1440 },
1441 WindowHint::X11InstanceName(instance_name) => unsafe {
1442 string_hint(ffi::GLFW_X11_INSTANCE_NAME, instance_name)
1443 },
1444 }
1445 }
1446
1447 pub fn default_window_hints(&mut self) {
1452 unsafe {
1453 ffi::glfwDefaultWindowHints();
1454 }
1455 }
1456
1457 pub fn create_window(
1461 &mut self,
1462 width: u32,
1463 height: u32,
1464 title: &str,
1465 mode: WindowMode<'_>,
1466 ) -> Option<(PWindow, GlfwReceiver<(f64, WindowEvent)>)> {
1467 #[cfg(feature = "wayland")]
1468 {
1469 self.window_hint(WindowHint::Focused(false));
1471 }
1472 self.create_window_intern(width, height, title, mode, None)
1473 }
1474
1475 fn create_window_intern(
1477 &self,
1478 width: u32,
1479 height: u32,
1480 title: &str,
1481 mode: WindowMode<'_>,
1482 share: Option<&Window>,
1483 ) -> Option<(PWindow, GlfwReceiver<(f64, WindowEvent)>)> {
1484 let ptr = unsafe {
1485 with_c_str(title, |title| {
1486 ffi::glfwCreateWindow(
1487 width as c_int,
1488 height as c_int,
1489 title,
1490 mode.to_ptr(),
1491 match share {
1492 Some(w) => w.ptr,
1493 None => ptr::null_mut(),
1494 },
1495 )
1496 })
1497 };
1498 if ptr.is_null() {
1499 None
1500 } else {
1501 let (drop_sender, drop_receiver) = channel();
1502 let (sender, receiver) = glfw_channel(16, 256);
1503 let window = Window {
1504 ptr,
1505 glfw: self.clone(),
1506 is_shared: share.is_some(),
1507 drop_sender: Some(drop_sender),
1508 drop_receiver,
1509 current_cursor: None,
1510 };
1511 let mut callbacks = Box::new(WindowCallbacks::new(sender));
1512 let mut window = PWindow(Box::new(window));
1513
1514 unsafe {
1515 callbacks.window_ptr = window.raw_ptr();
1516 ffi::glfwSetWindowUserPointer(ptr, mem::transmute(callbacks));
1517 }
1518
1519 Some((window, receiver))
1520 }
1521 }
1522
1523 pub fn make_context_current(&mut self, context: Option<&Window>) {
1528 match context {
1529 Some(window) => unsafe { ffi::glfwMakeContextCurrent(window.ptr) },
1530 None => unsafe { ffi::glfwMakeContextCurrent(ptr::null_mut()) },
1531 }
1532 }
1533
1534 #[cfg(all(not(target_os = "windows"), not(target_os = "macos"), feature = "x11"))]
1536 pub fn get_x11_display(&self) -> *mut c_void {
1537 unsafe { ffi::glfwGetX11Display() }
1538 }
1539
1540 #[cfg(all(
1542 not(target_os = "windows"),
1543 not(target_os = "macos"),
1544 feature = "wayland"
1545 ))]
1546 pub fn get_wayland_display(&self) -> *mut c_void {
1547 unsafe { ffi::glfwGetWaylandDisplay().cast_mut() }
1548 }
1549 pub fn get_platform(&self) -> Platform {
1551 unsafe { mem::transmute(ffi::glfwGetPlatform()) }
1552 }
1553 pub fn poll_events(&mut self) {
1557 unsafe {
1558 ffi::glfwPollEvents();
1559 }
1560 }
1561
1562 pub fn poll_events_unbuffered<F>(&mut self, mut f: F)
1570 where
1571 F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>,
1572 {
1573 let _unset_handler_guard = unsafe { crate::callbacks::unbuffered::set_handler(&mut f) };
1574 self.poll_events();
1575 }
1576
1577 pub fn wait_events(&mut self) {
1582 unsafe {
1583 ffi::glfwWaitEvents();
1584 }
1585 }
1586
1587 pub fn wait_events_unbuffered<F>(&mut self, mut f: F)
1592 where
1593 F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>,
1594 {
1595 let _unset_handler_guard = unsafe { crate::callbacks::unbuffered::set_handler(&mut f) };
1596 self.wait_events();
1597 }
1598
1599 pub fn wait_events_timeout(&mut self, timeout: f64) {
1605 unsafe {
1606 ffi::glfwWaitEventsTimeout(timeout);
1607 }
1608 }
1609
1610 pub fn wait_events_timeout_unbuffered<F>(&mut self, timeout: f64, mut f: F)
1616 where
1617 F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>,
1618 {
1619 let _unset_handler_guard = unsafe { crate::callbacks::unbuffered::set_handler(&mut f) };
1620 self.wait_events_timeout(timeout);
1621 }
1622
1623 pub fn post_empty_event(&self) {
1629 unsafe {
1630 ffi::glfwPostEmptyEvent();
1631 }
1632 }
1633
1634 pub fn get_time(&self) -> f64 {
1640 unsafe { ffi::glfwGetTime() as f64 }
1641 }
1642
1643 pub fn set_time(&mut self, time: f64) {
1647 unsafe {
1648 ffi::glfwSetTime(time as c_double);
1649 }
1650 }
1651
1652 pub fn get_timer_value(&self) -> u64 {
1654 unsafe { ffi::glfwGetTimerValue() as u64 }
1655 }
1656
1657 pub fn get_timer_frequency(&self) -> u64 {
1659 unsafe { ffi::glfwGetTimerFrequency() as u64 }
1660 }
1661
1662 pub fn set_swap_interval(&mut self, interval: SwapInterval) {
1667 unsafe {
1668 ffi::glfwSwapInterval(match interval {
1669 SwapInterval::None => 0_i32,
1670 SwapInterval::Adaptive => -1_i32,
1671 SwapInterval::Sync(interval) => interval as c_int,
1672 })
1673 }
1674 }
1675
1676 pub fn extension_supported(&self, extension: &str) -> bool {
1681 unsafe {
1682 with_c_str(extension, |extension| {
1683 ffi::glfwExtensionSupported(extension) == ffi::GLFW_TRUE
1684 })
1685 }
1686 }
1687
1688 #[cfg(feature = "vulkan")]
1697 pub fn get_required_instance_extensions(&self) -> Option<Vec<String>> {
1698 let mut len: c_uint = 0;
1699
1700 unsafe {
1701 let raw_extensions: *const *const c_char =
1702 ffi::glfwGetRequiredInstanceExtensions(&mut len as *mut c_uint);
1703
1704 if !raw_extensions.is_null() {
1705 return Some(
1706 slice::from_raw_parts(raw_extensions, len as usize)
1707 .iter()
1708 .map(|extensions| string_from_c_str(*extensions))
1709 .collect(),
1710 );
1711 }
1712 }
1713
1714 None
1715 }
1716
1717 pub fn get_proc_address_raw(&self, procname: &str) -> GLProc {
1722 debug_assert!(unsafe { ffi::glfwGetCurrentContext() } != std::ptr::null_mut());
1723 with_c_str(procname, |procname| unsafe {
1724 ffi::glfwGetProcAddress(procname)
1725 })
1726 }
1727
1728 #[cfg(feature = "vulkan")]
1741 pub fn get_instance_proc_address_raw(
1742 &self,
1743 instance: ffi::VkInstance,
1744 procname: &str,
1745 ) -> VkProc {
1746 with_c_str(procname, |procname| unsafe {
1747 ffi::glfwGetInstanceProcAddress(instance, procname)
1748 })
1749 }
1750
1751 #[cfg(feature = "vulkan")]
1756 pub fn get_physical_device_presentation_support_raw(
1757 &self,
1758 instance: ffi::VkInstance,
1759 device: ffi::VkPhysicalDevice,
1760 queue_family: u32,
1761 ) -> bool {
1762 ffi::GLFW_TRUE
1763 == unsafe {
1764 ffi::glfwGetPhysicalDevicePresentationSupport(
1765 instance,
1766 device,
1767 queue_family as c_uint,
1768 )
1769 }
1770 }
1771
1772 pub fn get_joystick(&self, id: JoystickId) -> Joystick {
1774 Joystick {
1775 id,
1776 glfw: self.clone(),
1777 }
1778 }
1779
1780 pub fn supports_raw_motion(&self) -> bool {
1782 unsafe { ffi::glfwRawMouseMotionSupported() == ffi::GLFW_TRUE }
1783 }
1784
1785 pub fn update_gamepad_mappings(&self, mappings: &str) -> bool {
1796 unsafe {
1797 with_c_str(mappings, |mappings| {
1798 ffi::glfwUpdateGamepadMappings(mappings) == ffi::GLFW_TRUE
1799 })
1800 }
1801 }
1802}
1803
1804impl Clone for Glfw {
1805 fn clone(&self) -> Self {
1806 REF_COUNT_FOR_GLFW.fetch_add(1, Ordering::SeqCst);
1807 Glfw {
1808 phantom: std::marker::PhantomData,
1809 }
1810 }
1811}
1812
1813impl Drop for Glfw {
1814 fn drop(&mut self) {
1815 let old_diff = REF_COUNT_FOR_GLFW.fetch_sub(1, Ordering::SeqCst);
1816 if old_diff == 1 {
1817 unsafe {
1818 ffi::glfwTerminate();
1819 }
1820 }
1821 }
1822}
1823
1824fn glfw_channel<T>(initial_capacity: usize, max_len: usize) -> (GlfwSender<T>, GlfwReceiver<T>) {
1825 let shared = Arc::new(SharedTransmitter {
1826 queue: Mutex::new(VecDeque::with_capacity(initial_capacity)),
1827 max_len,
1828 });
1829 let (mpsc_sender, mpsc_receiver) = channel();
1830
1831 let sender = GlfwSender {
1832 transmitter: shared.clone(),
1833 sender: mpsc_sender,
1834 };
1835 let receiver = GlfwReceiver {
1836 transmitter: shared.clone(),
1837 receiver: mpsc_receiver,
1838 };
1839 (sender, receiver)
1840}
1841
1842#[derive(Debug)]
1843struct SharedTransmitter<T> {
1844 queue: Mutex<VecDeque<T>>,
1845 max_len: usize,
1846}
1847
1848#[derive(Debug, Clone)]
1849struct GlfwSender<T> {
1850 transmitter: Arc<SharedTransmitter<T>>,
1851 sender: Sender<T>,
1852}
1853
1854impl<T> GlfwSender<T> {
1855 fn send(&self, v: T) {
1856 let mut queue = self.transmitter.queue.lock().unwrap();
1857 if queue.len() >= self.transmitter.max_len {
1858 let _ = self.sender.send(v);
1859 } else {
1860 queue.push_back(v);
1861 }
1862 }
1863}
1864
1865#[derive(Debug)]
1866pub struct GlfwReceiver<T> {
1867 transmitter: Arc<SharedTransmitter<T>>,
1868 receiver: Receiver<T>,
1869}
1870
1871impl<T> GlfwReceiver<T> {
1872 pub fn receive(&self) -> Option<T> {
1873 let ret = self.transmitter.queue.lock().unwrap().pop_front();
1874 if ret.is_some() {
1875 ret
1876 } else {
1877 match self.receiver.try_recv() {
1878 Ok(ret) => Some(ret),
1879 Err(_) => None,
1880 }
1881 }
1882 }
1883}
1884
1885struct WindowCallbacks {
1886 window_ptr: *mut Window,
1887 sender: GlfwSender<(f64, WindowEvent)>,
1888 pos_callback: Option<Box<dyn FnMut(&mut Window, i32, i32)>>,
1889 size_callback: Option<Box<dyn FnMut(&mut Window, i32, i32)>>,
1890 close_callback: Option<Box<dyn FnMut(&mut Window)>>,
1891 refresh_callback: Option<Box<dyn FnMut(&mut Window)>>,
1892 focus_callback: Option<Box<dyn FnMut(&mut Window, bool)>>,
1893 iconify_callback: Option<Box<dyn FnMut(&mut Window, bool)>>,
1894 framebuffer_size_callback: Option<Box<dyn FnMut(&mut Window, i32, i32)>>,
1895 key_callback: Option<Box<dyn FnMut(&mut Window, Key, Scancode, Action, Modifiers)>>,
1896 char_callback: Option<Box<dyn FnMut(&mut Window, char)>>,
1897 char_mods_callback: Option<Box<dyn FnMut(&mut Window, char, Modifiers)>>,
1898 mouse_button_callback: Option<Box<dyn FnMut(&mut Window, MouseButton, Action, Modifiers)>>,
1899 cursor_pos_callback: Option<Box<dyn FnMut(&mut Window, f64, f64)>>,
1900 cursor_enter_callback: Option<Box<dyn FnMut(&mut Window, bool)>>,
1901 scroll_callback: Option<Box<dyn FnMut(&mut Window, f64, f64)>>,
1902 drag_and_drop_callback: Option<Box<dyn FnMut(&mut Window, Vec<PathBuf>)>>,
1903 maximize_callback: Option<Box<dyn FnMut(&mut Window, bool)>>,
1904 content_scale_callback: Option<Box<dyn FnMut(&mut Window, f32, f32)>>,
1905 pos_polling: bool,
1906 size_polling: bool,
1907 close_polling: bool,
1908 refresh_polling: bool,
1909 focus_polling: bool,
1910 iconify_polling: bool,
1911 framebuffer_size_polling: bool,
1912 key_polling: bool,
1913 char_polling: bool,
1914 char_mods_polling: bool,
1915 mouse_button_polling: bool,
1916 cursor_pos_polling: bool,
1917 cursor_enter_polling: bool,
1918 scroll_polling: bool,
1919 drag_and_drop_polling: bool,
1920 maximize_polling: bool,
1921 content_scale_polling: bool,
1922}
1923
1924impl WindowCallbacks {
1925 fn new(sender: GlfwSender<(f64, WindowEvent)>) -> Self {
1926 Self {
1927 window_ptr: std::ptr::null_mut(),
1928 sender,
1929 pos_callback: None,
1930 size_callback: None,
1931 close_callback: None,
1932 refresh_callback: None,
1933 focus_callback: None,
1934 iconify_callback: None,
1935 framebuffer_size_callback: None,
1936 key_callback: None,
1937 char_callback: None,
1938 char_mods_callback: None,
1939 mouse_button_callback: None,
1940 cursor_pos_callback: None,
1941 cursor_enter_callback: None,
1942 scroll_callback: None,
1943 drag_and_drop_callback: None,
1944 maximize_callback: None,
1945 content_scale_callback: None,
1946 pos_polling: false,
1947 size_polling: false,
1948 close_polling: false,
1949 refresh_polling: false,
1950 focus_polling: false,
1951 iconify_polling: false,
1952 framebuffer_size_polling: false,
1953 key_polling: false,
1954 char_polling: false,
1955 char_mods_polling: false,
1956 mouse_button_polling: false,
1957 cursor_pos_polling: false,
1958 cursor_enter_polling: false,
1959 scroll_polling: false,
1960 drag_and_drop_polling: false,
1961 maximize_polling: false,
1962 content_scale_polling: false,
1963 }
1964 }
1965
1966 fn get_callbacks<'a>(window: *mut GLFWwindow) -> &'a mut WindowCallbacks {
1967 unsafe { &mut *(ffi::glfwGetWindowUserPointer(window) as *mut WindowCallbacks) }
1968 }
1969}
1970
1971pub fn get_error() -> Error {
1973 unsafe { mem::transmute(ffi::glfwGetError(null_mut())) }
1974}
1975
1976pub fn get_error_string() -> (Error, String) {
1978 unsafe {
1979 let mut description: *const c_char = null();
1980 let error: Error = mem::transmute(ffi::glfwGetError(&mut description));
1981 (error, string_from_c_str(description))
1982 }
1983}
1984
1985pub fn get_version() -> Version {
1987 unsafe {
1988 let mut major = 0;
1989 let mut minor = 0;
1990 let mut patch = 0;
1991 ffi::glfwGetVersion(&mut major, &mut minor, &mut patch);
1992 Version {
1993 major: major as u64,
1994 minor: minor as u64,
1995 patch: patch as u64,
1996 }
1997 }
1998}
1999
2000pub unsafe fn string_from_c_str(c_str: *const c_char) -> String {
2002 String::from_utf8_lossy(CStr::from_ptr(c_str).to_bytes()).into_owned()
2003}
2004
2005pub unsafe fn string_from_nullable_c_str(c_str: *const c_char) -> Option<String> {
2007 if c_str.is_null() {
2008 None
2009 } else {
2010 Some(string_from_c_str(c_str))
2011 }
2012}
2013
2014pub fn with_c_str<F, T>(s: &str, f: F) -> T
2016where
2017 F: FnOnce(*const c_char) -> T,
2018{
2019 let c_str = CString::new(s.as_bytes());
2020 f(c_str.unwrap().as_bytes_with_nul().as_ptr() as *const _)
2021}
2022
2023pub fn get_version_string() -> String {
2025 unsafe { string_from_c_str(ffi::glfwGetVersionString()) }
2026}
2027
2028#[allow(missing_copy_implementations)]
2030pub struct Monitor {
2031 ptr: *mut ffi::GLFWmonitor,
2032}
2033
2034impl std::fmt::Debug for Monitor {
2035 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2036 write!(f, "Monitor({:p})", self.ptr)
2037 }
2038}
2039
2040impl Monitor {
2041 pub fn get_pos(&self) -> (i32, i32) {
2043 unsafe {
2044 let mut xpos = 0;
2045 let mut ypos = 0;
2046 ffi::glfwGetMonitorPos(self.ptr, &mut xpos, &mut ypos);
2047 (xpos as i32, ypos as i32)
2048 }
2049 }
2050
2051 pub fn get_physical_size(&self) -> (i32, i32) {
2053 unsafe {
2054 let mut width = 0;
2055 let mut height = 0;
2056 ffi::glfwGetMonitorPhysicalSize(self.ptr, &mut width, &mut height);
2057 (width as i32, height as i32)
2058 }
2059 }
2060
2061 pub fn get_name(&self) -> Option<String> {
2063 unsafe { string_from_nullable_c_str(ffi::glfwGetMonitorName(self.ptr)) }
2064 }
2065
2066 pub fn get_video_modes(&self) -> Vec<VidMode> {
2068 unsafe {
2069 let mut count = 0;
2070 let ptr = ffi::glfwGetVideoModes(self.ptr, &mut count);
2071 slice::from_raw_parts(ptr, count as usize)
2072 .iter()
2073 .map(VidMode::from_glfw_vid_mode)
2074 .collect()
2075 }
2076 }
2077
2078 pub fn get_video_mode(&self) -> Option<VidMode> {
2080 unsafe {
2081 let ptr = ffi::glfwGetVideoMode(self.ptr);
2084 if ptr.is_null() {
2085 None
2086 } else {
2087 Some(VidMode::from_glfw_vid_mode(&*ptr))
2088 }
2089 }
2090 }
2091
2092 pub fn set_gamma(&mut self, gamma: f32) {
2094 unsafe {
2095 ffi::glfwSetGamma(self.ptr, gamma as c_float);
2096 }
2097 }
2098
2099 pub fn get_gamma_ramp(&self) -> GammaRamp {
2101 unsafe {
2102 let llramp = *ffi::glfwGetGammaRamp(self.ptr);
2103 GammaRamp {
2104 red: slice::from_raw_parts(llramp.red as *const c_ushort, llramp.size as usize)
2105 .iter()
2106 .copied()
2107 .collect(),
2108 green: slice::from_raw_parts(llramp.green as *const c_ushort, llramp.size as usize)
2109 .iter()
2110 .copied()
2111 .collect(),
2112 blue: slice::from_raw_parts(llramp.blue as *const c_ushort, llramp.size as usize)
2113 .iter()
2114 .copied()
2115 .collect(),
2116 }
2117 }
2118 }
2119
2120 pub fn set_gamma_ramp(&mut self, ramp: &mut GammaRamp) {
2122 unsafe {
2123 ffi::glfwSetGammaRamp(
2124 self.ptr,
2125 &ffi::GLFWgammaramp {
2126 red: ramp.red.as_mut_ptr(),
2127 green: ramp.green.as_mut_ptr(),
2128 blue: ramp.blue.as_mut_ptr(),
2129 size: ramp.red.len() as u32,
2130 },
2131 );
2132 }
2133 }
2134
2135 pub fn get_content_scale(&self) -> (f32, f32) {
2137 unsafe {
2138 let mut xscale = 0.0_f32;
2139 let mut yscale = 0.0_f32;
2140 ffi::glfwGetMonitorContentScale(self.ptr, &mut xscale, &mut yscale);
2141 (xscale, yscale)
2142 }
2143 }
2144
2145 pub fn get_workarea(&self) -> (i32, i32, i32, i32) {
2147 unsafe {
2148 let mut xpos = 0;
2149 let mut ypos = 0;
2150 let mut width = 0;
2151 let mut height = 0;
2152 ffi::glfwGetMonitorWorkarea(self.ptr, &mut xpos, &mut ypos, &mut width, &mut height);
2153 (xpos, ypos, width, height)
2154 }
2155 }
2156}
2157
2158#[repr(i32)]
2160#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2161#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2162pub enum MonitorEvent {
2163 Connected = ffi::GLFW_CONNECTED,
2164 Disconnected = ffi::GLFW_DISCONNECTED,
2165}
2166
2167impl VidMode {
2168 fn from_glfw_vid_mode(mode: &ffi::GLFWvidmode) -> VidMode {
2169 VidMode {
2170 width: mode.width as u32,
2171 height: mode.height as u32,
2172 red_bits: mode.redBits as u32,
2173 green_bits: mode.greenBits as u32,
2174 blue_bits: mode.blueBits as u32,
2175 refresh_rate: mode.refreshRate as u32,
2176 }
2177 }
2178}
2179
2180impl fmt::Debug for VidMode {
2181 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2191 write!(
2192 f,
2193 "{} x {}, {} = {} + {} + {}, {} Hz",
2194 self.width,
2195 self.height,
2196 self.red_bits + self.green_bits + self.blue_bits,
2197 self.red_bits,
2198 self.green_bits,
2199 self.blue_bits,
2200 self.refresh_rate
2201 )
2202 }
2203}
2204
2205#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2207#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2208pub enum WindowHint {
2209 MousePassthrough(bool),
2210 RedBits(Option<u32>),
2212 GreenBits(Option<u32>),
2214 BlueBits(Option<u32>),
2216 AlphaBits(Option<u32>),
2218 DepthBits(Option<u32>),
2220 StencilBits(Option<u32>),
2222 AccumRedBits(Option<u32>),
2224 AccumGreenBits(Option<u32>),
2226 AccumBlueBits(Option<u32>),
2228 AccumAlphaBits(Option<u32>),
2230 AuxBuffers(Option<u32>),
2232 Stereo(bool),
2234 Samples(Option<u32>),
2237 SRgbCapable(bool),
2239 RefreshRate(Option<u32>),
2244 ClientApi(ClientApiHint),
2246 ContextVersionMajor(u32),
2252 ContextVersionMinor(u32),
2258 ContextVersion(u32, u32),
2268 ContextRobustness(ContextRobustnessHint),
2270 OpenGlForwardCompat(bool),
2277 OpenGlDebugContext(bool),
2282 OpenGlProfile(OpenGlProfileHint),
2287 Resizable(bool),
2293 Visible(bool),
2297 Decorated(bool),
2302 AutoIconify(bool),
2307 Floating(bool),
2312 Focused(bool),
2316 Maximized(bool),
2320 ContextNoError(bool),
2323 ContextCreationApi(ContextCreationApi),
2325 ContextReleaseBehavior(ContextReleaseBehavior),
2327 DoubleBuffer(bool),
2334 CenterCursor(bool),
2338 TransparentFramebuffer(bool),
2343 FocusOnShow(bool),
2345 ScaleToMonitor(bool),
2350 CocoaRetinaFramebuffer(bool),
2354 CocoaFrameName(Option<String>),
2359 CocoaGraphicsSwitching(bool),
2373 X11ClassName(Option<String>),
2375 X11InstanceName(Option<String>),
2377}
2378
2379#[repr(i32)]
2381#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2382#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2383pub enum ClientApiHint {
2384 NoApi = ffi::GLFW_NO_API,
2385 OpenGl = ffi::GLFW_OPENGL_API,
2386 OpenGlEs = ffi::GLFW_OPENGL_ES_API,
2387}
2388
2389#[repr(i32)]
2391#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2392#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2393pub enum ContextRobustnessHint {
2394 NoRobustness = ffi::GLFW_NO_ROBUSTNESS,
2395 NoResetNotification = ffi::GLFW_NO_RESET_NOTIFICATION,
2396 LoseContextOnReset = ffi::GLFW_LOSE_CONTEXT_ON_RESET,
2397}
2398
2399#[repr(i32)]
2401#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2402#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2403pub enum OpenGlProfileHint {
2404 Any = ffi::GLFW_OPENGL_ANY_PROFILE,
2405 Core = ffi::GLFW_OPENGL_CORE_PROFILE,
2406 Compat = ffi::GLFW_OPENGL_COMPAT_PROFILE,
2407}
2408
2409#[derive(Copy, Clone, Debug)]
2411pub enum WindowMode<'a> {
2412 FullScreen(&'a Monitor),
2414
2415 Windowed,
2417}
2418
2419impl<'a> WindowMode<'a> {
2421 fn to_ptr(&self) -> *mut ffi::GLFWmonitor {
2424 match *self {
2425 WindowMode::FullScreen(monitor) => monitor.ptr,
2426 WindowMode::Windowed => ptr::null_mut(),
2427 }
2428 }
2429}
2430
2431bitflags! {
2432 #[doc = "Key modifiers (e.g., Shift, Control, Alt, Super)"]
2433 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2434 pub struct Modifiers: ::std::os::raw::c_int {
2435 const Shift = crate::ffi::GLFW_MOD_SHIFT;
2436 const Control = crate::ffi::GLFW_MOD_CONTROL;
2437 const Alt = crate::ffi::GLFW_MOD_ALT;
2438 const Super = crate::ffi::GLFW_MOD_SUPER;
2439 const CapsLock = crate::ffi::GLFW_MOD_CAPS_LOCK;
2440 const NumLock = crate::ffi::GLFW_MOD_NUM_LOCK;
2441 }
2442}
2443
2444pub type Scancode = c_int;
2446
2447#[derive(Clone, PartialEq, PartialOrd, Debug)]
2449#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2450pub enum WindowEvent {
2451 Pos(i32, i32),
2452 Size(i32, i32),
2453 Close,
2454 Refresh,
2455 Focus(bool),
2456 Iconify(bool),
2457 FramebufferSize(i32, i32),
2458 MouseButton(MouseButton, Action, Modifiers),
2459 CursorPos(f64, f64),
2460 CursorEnter(bool),
2461 Scroll(f64, f64),
2462 Key(Key, Scancode, Action, Modifiers),
2463 Char(char),
2464 CharModifiers(char, Modifiers),
2465 FileDrop(Vec<PathBuf>),
2466 Maximize(bool),
2467 ContentScale(f32, f32),
2468}
2469
2470pub fn flush_messages<Message: Send>(
2482 receiver: &GlfwReceiver<Message>,
2483) -> FlushedMessages<'_, Message> {
2484 FlushedMessages(receiver)
2485}
2486
2487#[derive(Debug)]
2490pub struct FlushedMessages<'a, Message: Send>(&'a GlfwReceiver<Message>);
2491
2492unsafe impl<'a, Message: 'a + Send> Send for FlushedMessages<'a, Message> {}
2493
2494impl<'a, Message: 'static + Send> Iterator for FlushedMessages<'a, Message> {
2495 type Item = Message;
2496
2497 fn next(&mut self) -> Option<Message> {
2498 let FlushedMessages(receiver) = *self;
2499 receiver.receive()
2500 }
2501}
2502
2503#[derive(Debug)]
2505pub struct Window {
2506 ptr: *mut ffi::GLFWwindow,
2507 pub is_shared: bool,
2508 drop_sender: Option<Sender<()>>,
2510 #[allow(unused)]
2514 drop_receiver: Receiver<()>,
2515 current_cursor: Option<Cursor>,
2518 pub glfw: Glfw,
2519}
2520
2521impl Window {
2522 pub fn get_proc_address(&mut self, procname: &str) -> GLProc {
2528 if self.ptr != unsafe { ffi::glfwGetCurrentContext() } {
2529 self.make_current();
2530 }
2531
2532 self.glfw.get_proc_address_raw(procname)
2533 }
2534
2535 #[cfg(feature = "vulkan")]
2548 pub fn get_instance_proc_address(
2549 &mut self,
2550 instance: ffi::VkInstance,
2551 procname: &str,
2552 ) -> VkProc {
2553 self.glfw.get_instance_proc_address_raw(instance, procname)
2554 }
2555
2556 #[cfg(feature = "vulkan")]
2561 pub fn get_physical_device_presentation_support(
2562 &self,
2563 instance: ffi::VkInstance,
2564 device: ffi::VkPhysicalDevice,
2565 queue_family: u32,
2566 ) -> bool {
2567 self.glfw
2568 .get_physical_device_presentation_support_raw(instance, device, queue_family)
2569 }
2570
2571 #[cfg(feature = "vulkan")]
2573 pub unsafe fn create_window_surface(
2574 &self,
2575 instance: ffi::VkInstance,
2576 allocator: *const ffi::VkAllocationCallbacks,
2577 surface: *mut ffi::VkSurfaceKHR,
2578 ) -> ffi::VkResult {
2579 unsafe { ffi::glfwCreateWindowSurface(instance, self.ptr, allocator, surface) }
2580 }
2581
2582 pub fn create_shared(
2586 &self,
2587 width: u32,
2588 height: u32,
2589 title: &str,
2590 mode: WindowMode<'_>,
2591 ) -> Option<(PWindow, GlfwReceiver<(f64, WindowEvent)>)> {
2592 self.glfw
2593 .create_window_intern(width, height, title, mode, Some(self))
2594 }
2595
2596 pub fn close(self) {}
2599
2600 pub fn render_context(&mut self) -> PRenderContext {
2603 PRenderContext(Box::new(RenderContext {
2604 ptr: self.ptr,
2605 glfw: self.glfw.clone(),
2606 drop_sender: self.drop_sender.as_ref().unwrap().clone(),
2608 }))
2609 }
2610
2611 pub fn should_close(&self) -> bool {
2613 unsafe { ffi::glfwWindowShouldClose(self.ptr) == ffi::GLFW_TRUE }
2614 }
2615
2616 pub fn set_should_close(&mut self, value: bool) {
2618 unsafe { ffi::glfwSetWindowShouldClose(self.ptr, value as c_int) }
2619 }
2620
2621 pub fn set_title(&mut self, title: &str) {
2625 unsafe {
2626 with_c_str(title, |title| {
2627 ffi::glfwSetWindowTitle(self.ptr, title);
2628 });
2629 }
2630 }
2631
2632 pub fn get_pos(&self) -> (i32, i32) {
2634 unsafe {
2635 let mut xpos = 0;
2636 let mut ypos = 0;
2637 ffi::glfwGetWindowPos(self.ptr, &mut xpos, &mut ypos);
2638 (xpos as i32, ypos as i32)
2639 }
2640 }
2641
2642 pub fn set_pos(&mut self, xpos: i32, ypos: i32) {
2644 unsafe {
2645 ffi::glfwSetWindowPos(self.ptr, xpos as c_int, ypos as c_int);
2646 }
2647 }
2648
2649 pub fn get_size(&self) -> (i32, i32) {
2651 unsafe {
2652 let mut width = 0;
2653 let mut height = 0;
2654 ffi::glfwGetWindowSize(self.ptr, &mut width, &mut height);
2655 (width as i32, height as i32)
2656 }
2657 }
2658
2659 pub fn set_size(&mut self, width: i32, height: i32) {
2661 unsafe {
2662 ffi::glfwSetWindowSize(self.ptr, width as c_int, height as c_int);
2663 }
2664 }
2665
2666 pub fn get_frame_size(&self) -> (i32, i32, i32, i32) {
2670 let (mut left, mut top, mut right, mut bottom): (i32, i32, i32, i32) = (0, 0, 0, 0);
2671
2672 unsafe {
2673 ffi::glfwGetWindowFrameSize(
2674 self.ptr,
2675 &mut left as *mut c_int,
2676 &mut top as *mut c_int,
2677 &mut right as *mut c_int,
2678 &mut bottom as *mut c_int,
2679 );
2680 }
2681
2682 (left, top, right, bottom)
2683 }
2684
2685 pub fn get_framebuffer_size(&self) -> (i32, i32) {
2687 unsafe {
2688 let mut width = 0;
2689 let mut height = 0;
2690 ffi::glfwGetFramebufferSize(self.ptr, &mut width, &mut height);
2691 (width as i32, height as i32)
2692 }
2693 }
2694
2695 pub fn set_aspect_ratio(&mut self, numer: u32, denum: u32) {
2697 unsafe { ffi::glfwSetWindowAspectRatio(self.ptr, numer as c_int, denum as c_int) }
2698 }
2699
2700 pub fn set_size_limits(
2706 &mut self,
2707 minwidth: Option<u32>,
2708 minheight: Option<u32>,
2709 maxwidth: Option<u32>,
2710 maxheight: Option<u32>,
2711 ) {
2712 unsafe {
2713 ffi::glfwSetWindowSizeLimits(
2714 self.ptr,
2715 unwrap_dont_care(minwidth),
2716 unwrap_dont_care(minheight),
2717 unwrap_dont_care(maxwidth),
2718 unwrap_dont_care(maxheight),
2719 )
2720 }
2721 }
2722
2723 pub fn iconify(&mut self) {
2725 unsafe {
2726 ffi::glfwIconifyWindow(self.ptr);
2727 }
2728 }
2729
2730 pub fn restore(&mut self) {
2732 unsafe {
2733 ffi::glfwRestoreWindow(self.ptr);
2734 }
2735 }
2736
2737 pub fn maximize(&mut self) {
2739 unsafe { ffi::glfwMaximizeWindow(self.ptr) }
2740 }
2741
2742 pub fn show(&mut self) {
2744 unsafe {
2745 ffi::glfwShowWindow(self.ptr);
2746 }
2747 }
2748
2749 pub fn hide(&mut self) {
2751 unsafe {
2752 ffi::glfwHideWindow(self.ptr);
2753 }
2754 }
2755
2756 pub fn with_window_mode<T, F>(&self, f: F) -> T
2769 where
2770 F: FnOnce(WindowMode<'_>) -> T,
2771 {
2772 let ptr = unsafe { ffi::glfwGetWindowMonitor(self.ptr) };
2773 if ptr.is_null() {
2774 f(WindowMode::Windowed)
2775 } else {
2776 f(WindowMode::FullScreen(&Monitor { ptr }))
2777 }
2778 }
2779
2780 pub fn set_monitor(
2782 &mut self,
2783 mode: WindowMode<'_>,
2784 xpos: i32,
2785 ypos: i32,
2786 width: u32,
2787 height: u32,
2788 refresh_rate: Option<u32>,
2789 ) {
2790 let monitor_ptr = if let WindowMode::FullScreen(monitor) = mode {
2791 monitor.ptr
2792 } else {
2793 ptr::null_mut()
2794 };
2795
2796 unsafe {
2797 ffi::glfwSetWindowMonitor(
2798 self.ptr,
2799 monitor_ptr,
2800 xpos as c_int,
2801 ypos as c_int,
2802 width as c_int,
2803 height as c_int,
2804 unwrap_dont_care(refresh_rate),
2805 )
2806 }
2807 }
2808
2809 pub fn focus(&mut self) {
2814 unsafe { ffi::glfwFocusWindow(self.ptr) }
2815 }
2816
2817 pub fn is_focused(&self) -> bool {
2819 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_FOCUSED) == ffi::GLFW_TRUE }
2820 }
2821
2822 pub fn is_iconified(&self) -> bool {
2824 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_ICONIFIED) == ffi::GLFW_TRUE }
2825 }
2826
2827 pub fn is_maximized(&self) -> bool {
2829 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_MAXIMIZED) == ffi::GLFW_TRUE }
2830 }
2831
2832 pub fn get_client_api(&self) -> c_int {
2834 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_CLIENT_API) }
2835 }
2836
2837 pub fn get_context_version(&self) -> Version {
2844 unsafe {
2845 Version {
2846 major: ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_CONTEXT_VERSION_MAJOR) as u64,
2847 minor: ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_CONTEXT_VERSION_MINOR) as u64,
2848 patch: ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_CONTEXT_REVISION) as u64,
2849 }
2850 }
2851 }
2852
2853 pub fn get_context_robustness(&self) -> c_int {
2855 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_CONTEXT_ROBUSTNESS) }
2856 }
2857
2858 pub fn is_opengl_forward_compat(&self) -> bool {
2860 unsafe {
2861 ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_OPENGL_FORWARD_COMPAT) == ffi::GLFW_TRUE
2862 }
2863 }
2864
2865 pub fn is_opengl_debug_context(&self) -> bool {
2867 unsafe {
2868 ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_OPENGL_DEBUG_CONTEXT) == ffi::GLFW_TRUE
2869 }
2870 }
2871
2872 pub fn get_opengl_profile(&self) -> c_int {
2874 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_OPENGL_PROFILE) }
2875 }
2876
2877 pub fn is_resizable(&self) -> bool {
2879 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_RESIZABLE) == ffi::GLFW_TRUE }
2880 }
2881
2882 pub fn set_resizable(&mut self, resizable: bool) {
2884 unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::GLFW_RESIZABLE, resizable as c_int) }
2885 }
2886
2887 pub fn is_visible(&self) -> bool {
2889 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_VISIBLE) == ffi::GLFW_TRUE }
2890 }
2891
2892 pub fn is_decorated(&self) -> bool {
2894 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_DECORATED) == ffi::GLFW_TRUE }
2895 }
2896
2897 pub fn set_decorated(&mut self, decorated: bool) {
2899 unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::GLFW_DECORATED, decorated as c_int) }
2900 }
2901
2902 pub fn is_auto_iconify(&self) -> bool {
2904 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_AUTO_ICONIFY) == ffi::GLFW_TRUE }
2905 }
2906
2907 pub fn set_auto_iconify(&mut self, auto_iconify: bool) {
2909 unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::GLFW_AUTO_ICONIFY, auto_iconify as c_int) }
2910 }
2911
2912 pub fn is_floating(&self) -> bool {
2914 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_FLOATING) == ffi::GLFW_TRUE }
2915 }
2916
2917 pub fn set_floating(&mut self, floating: bool) {
2919 unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::GLFW_FLOATING, floating as c_int) }
2920 }
2921
2922 pub fn is_framebuffer_transparent(&self) -> bool {
2924 unsafe {
2925 ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_TRANSPARENT_FRAMEBUFFER) == ffi::GLFW_TRUE
2926 }
2927 }
2928
2929 pub fn is_mouse_passthrough(&self) -> bool {
2931 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_MOUSE_PASSTHROUGH) == ffi::GLFW_TRUE }
2932 }
2933
2934 pub fn set_mouse_passthrough(&mut self, passthrough: bool) {
2936 unsafe {
2937 ffi::glfwSetWindowAttrib(self.ptr, ffi::GLFW_MOUSE_PASSTHROUGH, passthrough as c_int);
2938 }
2939 }
2940
2941 pub fn is_focus_on_show(&self) -> bool {
2943 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_FOCUS_ON_SHOW) == ffi::GLFW_TRUE }
2944 }
2945
2946 pub fn set_focus_on_show(&mut self, focus_on_show: bool) {
2948 unsafe {
2949 ffi::glfwSetWindowAttrib(self.ptr, ffi::GLFW_FOCUS_ON_SHOW, focus_on_show as c_int)
2950 }
2951 }
2952
2953 pub fn is_hovered(&self) -> bool {
2955 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_HOVERED) == ffi::GLFW_TRUE }
2956 }
2957
2958 new_callback!(
2959 doc -> "Wrapper for `glfwSetWindowPosCallback`.",
2960 set -> set_pos_callback,
2961 unset -> unset_pos_callback,
2962 poll -> set_pos_polling,
2963 callback_field -> pos_callback,
2964 poll_field -> pos_polling,
2965 window_event -> Pos(i32, i32),
2966 glfw -> glfwSetWindowPosCallback(x: c_int, y: c_int),
2967 convert_args -> (x as i32, y as i32),
2968 secret -> _pos_callback
2969 );
2970
2971 new_callback!(
2972 doc -> "Wrapper for `glfwSetWindowSizeCallback`.",
2973 set -> set_size_callback,
2974 unset -> unset_size_callback,
2975 poll -> set_size_polling,
2976 callback_field -> size_callback,
2977 poll_field -> size_polling,
2978 window_event -> Size(i32, i32),
2979 glfw -> glfwSetWindowSizeCallback(width: c_int, height: c_int),
2980 convert_args -> (width as i32, height as i32),
2981 secret -> _size_callback
2982 );
2983
2984 new_callback!(
2985 doc -> "Wrapper for `glfwSetWindowCloseCallback`.",
2986 set -> set_close_callback,
2987 unset -> unset_close_callback,
2988 poll -> set_close_polling,
2989 callback_field -> close_callback,
2990 poll_field -> close_polling,
2991 window_event -> Close,
2992 glfw -> glfwSetWindowCloseCallback(),
2993 convert_args -> (),
2994 secret -> _close_callback
2995 );
2996
2997 new_callback!(
2998 doc -> "Wrapper for `glfwSetWindowRefreshCallback`.",
2999 set -> set_refresh_callback,
3000 unset -> unset_refresh_callback,
3001 poll -> set_refresh_polling,
3002 callback_field -> refresh_callback,
3003 poll_field -> refresh_polling,
3004 window_event -> Refresh,
3005 glfw -> glfwSetWindowRefreshCallback(),
3006 convert_args -> (),
3007 secret -> _refresh_callback
3008 );
3009
3010 new_callback!(
3011 doc -> "Wrapper for `glfwSetWindowFocusCallback`.",
3012 set -> set_focus_callback,
3013 unset -> unset_focus_callback,
3014 poll -> set_focus_polling,
3015 callback_field -> focus_callback,
3016 poll_field -> focus_polling,
3017 window_event -> Focus(bool),
3018 glfw -> glfwSetWindowFocusCallback(focused: c_int),
3019 convert_args -> (focused == ffi::GLFW_TRUE),
3020 secret -> _focus_callback
3021 );
3022
3023 new_callback!(
3024 doc -> "Wrapper for `glfwSetWindowIconifyCallback`.",
3025 set -> set_iconify_callback,
3026 unset -> unset_iconify_callback,
3027 poll -> set_iconify_polling,
3028 callback_field -> iconify_callback,
3029 poll_field -> iconify_polling,
3030 window_event -> Iconify(bool),
3031 glfw -> glfwSetWindowIconifyCallback(iconified: c_int),
3032 convert_args -> (iconified == ffi::GLFW_TRUE),
3033 secret -> _iconify_callback
3034 );
3035
3036 new_callback!(
3037 doc -> "Wrapper for `glfwSetFramebufferSizeCallback`.",
3038 set -> set_framebuffer_size_callback,
3039 unset -> unset_framebuffer_size_callback,
3040 poll -> set_framebuffer_size_polling,
3041 callback_field -> framebuffer_size_callback,
3042 poll_field -> framebuffer_size_polling,
3043 window_event -> FramebufferSize(i32, i32),
3044 glfw -> glfwSetFramebufferSizeCallback(width: c_int, height: c_int),
3045 convert_args -> (width as i32, height as i32),
3046 secret -> _framebuffer_size_callback
3047 );
3048
3049 new_callback!(
3050 doc -> "Wrapper for `glfwSetKeyCallback`.",
3051 set -> set_key_callback,
3052 unset -> unset_key_callback,
3053 poll -> set_key_polling,
3054 callback_field -> key_callback,
3055 poll_field -> key_polling,
3056 window_event -> Key(Key, Scancode, Action, Modifiers),
3057 glfw -> glfwSetKeyCallback(key: c_int, scancode: c_int, action: c_int, mods: c_int),
3058 convert_args -> (
3059 mem::transmute(key),
3060 scancode, mem::transmute(action),
3061 Modifiers::from_bits(mods).unwrap()
3062 ),
3063 secret -> _key_callback
3064 );
3065
3066 new_callback!(
3067 doc -> "Wrapper for `glfwSetCharCallback`.",
3068 set -> set_char_callback,
3069 unset -> unset_char_callback,
3070 poll -> set_char_polling,
3071 callback_field -> char_callback,
3072 poll_field -> char_polling,
3073 window_event -> Char(char),
3074 glfw -> glfwSetCharCallback(character: c_uint),
3075 convert_args -> (::std::char::from_u32(character).unwrap()),
3076 secret -> _char_callback
3077 );
3078
3079 new_callback!(
3080 doc -> "Wrapper for `glfwSetCharModsCallback`.",
3081 set -> set_char_mods_callback,
3082 unset -> unset_char_mods_callback,
3083 poll -> set_char_mods_polling,
3084 callback_field -> char_mods_callback,
3085 poll_field -> char_mods_polling,
3086 window_event -> CharModifiers(char, Modifiers),
3087 glfw -> glfwSetCharModsCallback(character: c_uint, mods: c_int),
3088 convert_args -> (
3089 ::std::char::from_u32(character).unwrap(),
3090 Modifiers::from_bits(mods).unwrap()
3091 ),
3092 secret -> _char_mods_callback
3093 );
3094
3095 new_callback!(
3096 doc -> "Wrapper for `glfwSetMouseButtonCallback`.",
3097 set -> set_mouse_button_callback,
3098 unset -> unset_mouse_button_callback,
3099 poll -> set_mouse_button_polling,
3100 callback_field -> mouse_button_callback,
3101 poll_field -> mouse_button_polling,
3102 window_event -> MouseButton(MouseButton, Action, Modifiers),
3103 glfw -> glfwSetMouseButtonCallback(button: c_int, action: c_int, mods: c_int),
3104 convert_args -> (
3105 mem::transmute(button),
3106 mem::transmute(action),
3107 Modifiers::from_bits(mods).unwrap()
3108 ),
3109 secret -> _mouse_button_callback
3110 );
3111
3112 new_callback!(
3113 doc -> "Wrapper for `glfwSetCursorPosCallback`.",
3114 set -> set_cursor_pos_callback,
3115 unset -> unset_cursor_pos_callback,
3116 poll -> set_cursor_pos_polling,
3117 callback_field -> cursor_pos_callback,
3118 poll_field -> cursor_pos_polling,
3119 window_event -> CursorPos(f64, f64),
3120 glfw -> glfwSetCursorPosCallback(x: c_double, y: c_double),
3121 convert_args -> (x as f64, y as f64),
3122 secret -> _cursor_pos_callback
3123 );
3124
3125 new_callback!(
3126 doc -> "Wrapper for `glfwSetCursorEnterCallback`.",
3127 set -> set_cursor_enter_callback,
3128 unset -> unset_cursor_enter_callback,
3129 poll -> set_cursor_enter_polling,
3130 callback_field -> cursor_enter_callback,
3131 poll_field -> cursor_enter_polling,
3132 window_event -> CursorEnter(bool),
3133 glfw -> glfwSetCursorEnterCallback(entered: c_int),
3134 convert_args -> (entered == ffi::GLFW_TRUE),
3135 secret -> _cursor_enter_callback
3136 );
3137
3138 new_callback!(
3139 doc -> "Wrapper for `glfwSetScrollCallback`.",
3140 set -> set_scroll_callback,
3141 unset -> unset_scroll_callback,
3142 poll -> set_scroll_polling,
3143 callback_field -> scroll_callback,
3144 poll_field -> scroll_polling,
3145 window_event -> Scroll(f64, f64),
3146 glfw -> glfwSetScrollCallback(x: c_double, y: c_double),
3147 convert_args -> (x as f64, y as f64),
3148 secret -> _scroll_callback
3149 );
3150
3151 new_callback!(
3152 doc -> "Wrapper for `glfwSetDropCallback`.",
3153 set -> set_drag_and_drop_callback,
3154 unset -> unset_drag_and_drop_callback,
3155 poll -> set_drag_and_drop_polling,
3156 callback_field -> drag_and_drop_callback,
3157 poll_field -> drag_and_drop_polling,
3158 window_event -> FileDrop(Vec<PathBuf>),
3159 glfw -> glfwSetDropCallback(num_paths: c_int, paths: *mut *const c_char),
3160 convert_args -> ({
3161 slice::from_raw_parts(paths, num_paths as usize)
3162 .iter()
3163 .map(|path| PathBuf::from(std::str::from_utf8({
3164 CStr::from_ptr(*path)
3165 .to_bytes()
3166 })
3167 .unwrap()
3168 .to_string()))
3169 .collect()
3170 }),
3171 secret -> _drag_and_drop_callback
3172 );
3173
3174 new_callback!(
3175 doc -> "Wrapper for `glfwSetWindowMaximizeCallback`.",
3176 set -> set_maximize_callback,
3177 unset -> unset_maximize_callback,
3178 poll -> set_maximize_polling,
3179 callback_field -> maximize_callback,
3180 poll_field -> maximize_polling,
3181 window_event -> Maximize(bool),
3182 glfw -> glfwSetWindowMaximizeCallback(maximized: c_int),
3183 convert_args -> (maximized == ffi::GLFW_TRUE),
3184 secret -> _maximize_callback
3185 );
3186
3187 new_callback!(
3188 doc -> "Wrapper for `glfwSetWindowContentScaleCallback`.",
3189 set -> set_content_scale_callback,
3190 unset -> unset_content_scale_callback,
3191 poll -> set_content_scale_polling,
3192 callback_field -> content_scale_callback,
3193 poll_field -> content_scale_polling,
3194 window_event -> ContentScale(f32, f32),
3195 glfw -> glfwSetWindowContentScaleCallback(xscale: c_float, yscale: c_float),
3196 convert_args -> (xscale as f32, yscale as f32),
3197 secret -> _content_scale_callback
3198 );
3199
3200 pub fn set_all_polling(&mut self, should_poll: bool) {
3202 self.set_pos_polling(should_poll);
3203 self.set_size_polling(should_poll);
3204 self.set_close_polling(should_poll);
3205 self.set_refresh_polling(should_poll);
3206 self.set_focus_polling(should_poll);
3207 self.set_iconify_polling(should_poll);
3208 self.set_framebuffer_size_polling(should_poll);
3209 self.set_key_polling(should_poll);
3210 self.set_char_polling(should_poll);
3211 self.set_char_mods_polling(should_poll);
3212 self.set_mouse_button_polling(should_poll);
3213 self.set_cursor_pos_polling(should_poll);
3214 self.set_cursor_enter_polling(should_poll);
3215 self.set_scroll_polling(should_poll);
3216 self.set_drag_and_drop_polling(should_poll);
3217 self.set_maximize_polling(should_poll);
3218 self.set_content_scale_polling(should_poll);
3219 }
3220
3221 pub fn get_cursor_mode(&self) -> CursorMode {
3223 unsafe { mem::transmute(ffi::glfwGetInputMode(self.ptr, ffi::GLFW_CURSOR)) }
3224 }
3225
3226 pub fn set_cursor_mode(&mut self, mode: CursorMode) {
3228 unsafe {
3229 ffi::glfwSetInputMode(self.ptr, ffi::GLFW_CURSOR, mode as c_int);
3230 }
3231 }
3232
3233 pub fn set_cursor(&mut self, cursor: Option<Cursor>) -> Option<Cursor> {
3240 let previous = mem::replace(&mut self.current_cursor, cursor);
3241
3242 unsafe {
3243 ffi::glfwSetCursor(
3244 self.ptr,
3245 match self.current_cursor {
3246 Some(ref cursor) => cursor.ptr,
3247 None => ptr::null_mut(),
3248 },
3249 )
3250 }
3251
3252 previous
3253 }
3254
3255 #[cfg(feature = "image")]
3272 pub fn set_icon(&mut self, images: Vec<image::RgbaImage>) {
3273 let image_data: Vec<(Vec<_>, u32, u32)> = images
3276 .into_iter()
3277 .map(|image| {
3278 let (width, height) = image.dimensions();
3279
3280 (image.into_vec(), width, height)
3281 })
3282 .collect();
3283
3284 let glfw_images: Vec<ffi::GLFWimage> = image_data
3285 .iter()
3286 .map(|data| ffi::GLFWimage {
3287 width: data.1 as c_int,
3288 height: data.2 as c_int,
3289 pixels: data.0.as_ptr() as _,
3290 })
3291 .collect();
3292
3293 unsafe {
3294 ffi::glfwSetWindowIcon(
3295 self.ptr,
3296 glfw_images.len() as c_int,
3297 glfw_images.as_ptr() as *const ffi::GLFWimage,
3298 )
3299 }
3300 }
3301
3302 pub fn set_icon_from_pixels(&mut self, images: Vec<PixelImage>) {
3305 let glfw_images: Vec<ffi::GLFWimage> = images
3306 .iter()
3307 .map(|image: &PixelImage| ffi::GLFWimage {
3308 width: image.width as c_int,
3309 height: image.height as c_int,
3310 pixels: image.pixels.as_ptr() as _,
3311 })
3312 .collect();
3313
3314 unsafe {
3315 ffi::glfwSetWindowIcon(
3316 self.ptr,
3317 glfw_images.len() as c_int,
3318 glfw_images.as_ptr() as *const ffi::GLFWimage,
3319 )
3320 }
3321 }
3322
3323 pub fn has_sticky_keys(&self) -> bool {
3325 unsafe { ffi::glfwGetInputMode(self.ptr, ffi::GLFW_STICKY_KEYS) == ffi::GLFW_TRUE }
3326 }
3327
3328 pub fn set_sticky_keys(&mut self, value: bool) {
3330 unsafe {
3331 ffi::glfwSetInputMode(self.ptr, ffi::GLFW_STICKY_KEYS, value as c_int);
3332 }
3333 }
3334
3335 pub fn has_sticky_mouse_buttons(&self) -> bool {
3337 unsafe { ffi::glfwGetInputMode(self.ptr, ffi::GLFW_STICKY_MOUSE_BUTTONS) == ffi::GLFW_TRUE }
3338 }
3339
3340 pub fn set_sticky_mouse_buttons(&mut self, value: bool) {
3342 unsafe {
3343 ffi::glfwSetInputMode(self.ptr, ffi::GLFW_STICKY_MOUSE_BUTTONS, value as c_int);
3344 }
3345 }
3346
3347 pub fn does_store_lock_key_mods(&self) -> bool {
3349 unsafe { ffi::glfwGetInputMode(self.ptr, ffi::GLFW_LOCK_KEY_MODS) == ffi::GLFW_TRUE }
3350 }
3351
3352 pub fn set_store_lock_key_mods(&mut self, value: bool) {
3354 unsafe { ffi::glfwSetInputMode(self.ptr, ffi::GLFW_LOCK_KEY_MODS, value as c_int) }
3355 }
3356
3357 pub fn uses_raw_mouse_motion(&self) -> bool {
3359 unsafe { ffi::glfwGetInputMode(self.ptr, ffi::GLFW_RAW_MOUSE_MOTION) == ffi::GLFW_TRUE }
3360 }
3361
3362 pub fn set_raw_mouse_motion(&mut self, value: bool) {
3364 unsafe { ffi::glfwSetInputMode(self.ptr, ffi::GLFW_RAW_MOUSE_MOTION, value as c_int) }
3365 }
3366
3367 pub fn get_key(&self, key: Key) -> Action {
3369 unsafe { mem::transmute(ffi::glfwGetKey(self.ptr, key as c_int)) }
3370 }
3371
3372 pub fn get_mouse_button(&self, button: MouseButton) -> Action {
3374 unsafe { mem::transmute(ffi::glfwGetMouseButton(self.ptr, button as c_int)) }
3375 }
3376
3377 pub fn get_cursor_pos(&self) -> (f64, f64) {
3379 unsafe {
3380 let mut xpos = 0.0;
3381 let mut ypos = 0.0;
3382 ffi::glfwGetCursorPos(self.ptr, &mut xpos, &mut ypos);
3383 (xpos as f64, ypos as f64)
3384 }
3385 }
3386
3387 pub fn set_cursor_pos(&mut self, xpos: f64, ypos: f64) {
3389 unsafe {
3390 ffi::glfwSetCursorPos(self.ptr, xpos as c_double, ypos as c_double);
3391 }
3392 }
3393
3394 pub fn set_clipboard_string(&mut self, string: &str) {
3396 unsafe {
3397 with_c_str(string, |string| {
3398 ffi::glfwSetClipboardString(self.ptr, string);
3399 });
3400 }
3401 }
3402
3403 pub fn get_clipboard_string(&self) -> Option<String> {
3405 unsafe { string_from_nullable_c_str(ffi::glfwGetClipboardString(self.ptr)) }
3406 }
3407
3408 pub fn get_opacity(&self) -> f32 {
3410 unsafe { ffi::glfwGetWindowOpacity(self.ptr) }
3411 }
3412
3413 pub fn set_opacity(&mut self, opacity: f32) {
3415 unsafe { ffi::glfwSetWindowOpacity(self.ptr, opacity) }
3416 }
3417
3418 pub fn request_attention(&mut self) {
3420 unsafe { ffi::glfwRequestWindowAttention(self.ptr) }
3421 }
3422
3423 pub fn get_content_scale(&self) -> (f32, f32) {
3425 unsafe {
3426 let mut xscale = 0.0_f32;
3427 let mut yscale = 0.0_f32;
3428 ffi::glfwGetWindowContentScale(self.ptr, &mut xscale, &mut yscale);
3429 (xscale, yscale)
3430 }
3431 }
3432
3433 #[cfg(target_os = "windows")]
3435 pub fn get_win32_window(&self) -> *mut c_void {
3436 unsafe { ffi::glfwGetWin32Window(self.ptr) }
3437 }
3438
3439 #[cfg(target_os = "windows")]
3441 pub fn get_wgl_context(&self) -> *mut c_void {
3442 unsafe { ffi::glfwGetWGLContext(self.ptr) }
3443 }
3444
3445 #[cfg(target_os = "macos")]
3447 pub fn get_cocoa_window(&self) -> *mut c_void {
3448 unsafe { ffi::glfwGetCocoaWindow(self.ptr) }
3449 }
3450
3451 #[cfg(target_os = "macos")]
3453 pub fn get_nsgl_context(&self) -> *mut c_void {
3454 unsafe { ffi::glfwGetNSGLContext(self.ptr) }
3455 }
3456
3457 #[cfg(all(not(target_os = "windows"), not(target_os = "macos"), feature = "x11"))]
3459 pub fn get_x11_window(&self) -> usize {
3460 unsafe { ffi::glfwGetX11Window(self.ptr) }
3461 }
3462
3463 #[cfg(all(
3465 not(target_os = "windows"),
3466 not(target_os = "macos"),
3467 feature = "wayland"
3468 ))]
3469 pub fn get_wayland_window(&self) -> *mut c_void {
3470 unsafe { ffi::glfwGetWaylandWindow(self.ptr) }
3471 }
3472
3473 #[cfg(all(not(target_os = "windows"), not(target_os = "macos"), feature = "x11"))]
3475 pub fn get_glx_context(&self) -> usize {
3476 unsafe { ffi::glfwGetGLXContext(self.ptr) }
3477 }
3478}
3479
3480impl Drop for Window {
3481 fn drop(&mut self) {
3487 drop(self.drop_sender.take());
3488
3489 #[cfg(feature = "log")]
3491 if self.drop_receiver.try_recv() != Err(std::sync::mpsc::TryRecvError::Disconnected) {
3492 debug!("Attempted to drop a Window before the `RenderContext` was dropped.");
3493 debug!("Blocking until the `RenderContext` was dropped.");
3494 let _ = self.drop_receiver.recv();
3495 }
3496
3497 if !self.ptr.is_null() {
3498 unsafe {
3499 let _: Box<WindowCallbacks> =
3500 mem::transmute(ffi::glfwGetWindowUserPointer(self.ptr));
3501 }
3502 }
3503
3504 if !self.is_shared {
3505 unsafe {
3506 ffi::glfwDestroyWindow(self.ptr);
3507 }
3508 }
3509 }
3510}
3511
3512#[derive(Debug)]
3513#[repr(transparent)]
3514pub struct PRenderContext(Box<RenderContext>);
3515
3516impl Deref for PRenderContext {
3517 type Target = RenderContext;
3518 fn deref(&self) -> &Self::Target {
3519 self.0.deref()
3520 }
3521}
3522
3523impl DerefMut for PRenderContext {
3524 fn deref_mut(&mut self) -> &mut Self::Target {
3525 self.0.deref_mut()
3526 }
3527}
3528
3529unsafe impl Send for PRenderContext {}
3530unsafe impl Sync for PRenderContext {}
3531
3532#[cfg(feature = "raw-window-handle-v0-6")]
3533impl HasWindowHandle for PRenderContext {
3534 fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
3535 self.0.window_handle()
3536 }
3537}
3538
3539#[cfg(feature = "raw-window-handle-v0-6")]
3540impl HasDisplayHandle for PRenderContext {
3541 fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
3542 self.0.display_handle()
3543 }
3544}
3545
3546#[derive(Debug)]
3548pub struct RenderContext {
3549 ptr: *mut ffi::GLFWwindow,
3550 glfw: Glfw,
3551 #[allow(dead_code)]
3554 drop_sender: Sender<()>,
3555}
3556
3557impl RenderContext {
3558 pub fn get_proc_address(&mut self, procname: &str) -> GLProc {
3560 if self.ptr != unsafe { ffi::glfwGetCurrentContext() } {
3561 self.make_current();
3562 }
3563
3564 self.glfw.get_proc_address_raw(procname)
3565 }
3566
3567 #[cfg(feature = "vulkan")]
3569 pub fn get_instance_proc_address(
3570 &mut self,
3571 instance: ffi::VkInstance,
3572 procname: &str,
3573 ) -> VkProc {
3574 self.glfw.get_instance_proc_address_raw(instance, procname)
3575 }
3576
3577 #[cfg(feature = "vulkan")]
3579 pub fn get_physical_device_presentation_support(
3580 &self,
3581 instance: ffi::VkInstance,
3582 device: ffi::VkPhysicalDevice,
3583 queue_family: u32,
3584 ) -> bool {
3585 self.glfw
3586 .get_physical_device_presentation_support_raw(instance, device, queue_family)
3587 }
3588
3589 #[cfg(feature = "vulkan")]
3591 pub unsafe fn create_window_surface(
3592 &self,
3593 instance: ffi::VkInstance,
3594 allocator: *const ffi::VkAllocationCallbacks,
3595 surface: *mut ffi::VkSurfaceKHR,
3596 ) -> ffi::VkResult {
3597 unsafe { ffi::glfwCreateWindowSurface(instance, self.ptr, allocator, surface) }
3598 }
3599}
3600
3601unsafe impl Send for RenderContext {}
3602
3603pub trait Context {
3605 fn window_ptr(&self) -> *mut ffi::GLFWwindow;
3607
3608 fn window_id(&self) -> WindowId {
3610 self.window_ptr() as WindowId
3611 }
3612
3613 fn swap_buffers(&mut self) {
3619 let ptr = self.window_ptr();
3620 unsafe {
3621 ffi::glfwSwapBuffers(ptr);
3622 }
3623 }
3624
3625 fn is_current(&self) -> bool {
3627 self.window_ptr() == unsafe { ffi::glfwGetCurrentContext() }
3628 }
3629
3630 fn make_current(&mut self) {
3632 let ptr = self.window_ptr();
3633 unsafe {
3634 ffi::glfwMakeContextCurrent(ptr);
3635 }
3636 }
3637
3638 fn should_close(&self) -> bool {
3640 let ptr = self.window_ptr();
3641 unsafe { ffi::glfwWindowShouldClose(ptr) == ffi::GLFW_TRUE }
3642 }
3643
3644 fn set_should_close(&mut self, value: bool) {
3646 let ptr = self.window_ptr();
3647 unsafe {
3648 ffi::glfwSetWindowShouldClose(ptr, value as c_int);
3649 }
3650 }
3651
3652 fn post_empty_event(&self) {
3654 unsafe { ffi::glfwPostEmptyEvent() }
3655 }
3656}
3657
3658impl Context for Window {
3659 fn window_ptr(&self) -> *mut ffi::GLFWwindow {
3660 self.ptr
3661 }
3662}
3663
3664impl Context for RenderContext {
3665 fn window_ptr(&self) -> *mut ffi::GLFWwindow {
3666 self.ptr
3667 }
3668}
3669
3670#[cfg(feature = "raw-window-handle-v0-6")]
3671impl HasWindowHandle for Window {
3672 fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
3673 Ok(unsafe { WindowHandle::borrow_raw(raw_window_handle(self)) })
3674 }
3675}
3676
3677#[cfg(feature = "raw-window-handle-v0-6")]
3678impl HasWindowHandle for RenderContext {
3679 fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
3680 Ok(unsafe { WindowHandle::borrow_raw(raw_window_handle(self)) })
3681 }
3682}
3683
3684#[cfg(feature = "raw-window-handle-v0-6")]
3685impl HasDisplayHandle for Window {
3686 fn display_handle(&'_ self) -> Result<DisplayHandle<'_>, HandleError> {
3687 Ok(unsafe { DisplayHandle::borrow_raw(raw_display_handle()) })
3688 }
3689}
3690
3691#[cfg(feature = "raw-window-handle-v0-6")]
3692impl HasDisplayHandle for RenderContext {
3693 fn display_handle(&'_ self) -> Result<DisplayHandle<'_>, HandleError> {
3694 Ok(unsafe { DisplayHandle::borrow_raw(raw_display_handle()) })
3695 }
3696}
3697
3698#[cfg(feature = "raw-window-handle-v0-5")]
3699unsafe impl HasRawWindowHandle for Window {
3700 fn raw_window_handle(&self) -> RawWindowHandle {
3701 raw_window_handle(self)
3702 }
3703}
3704
3705#[cfg(feature = "raw-window-handle-v0-5")]
3706unsafe impl HasRawWindowHandle for RenderContext {
3707 fn raw_window_handle(&self) -> RawWindowHandle {
3708 raw_window_handle(self)
3709 }
3710}
3711
3712#[cfg(feature = "raw-window-handle-v0-5")]
3713unsafe impl HasRawDisplayHandle for Window {
3714 fn raw_display_handle(&self) -> RawDisplayHandle {
3715 raw_display_handle()
3716 }
3717}
3718
3719#[cfg(feature = "raw-window-handle-v0-5")]
3720unsafe impl HasRawDisplayHandle for RenderContext {
3721 fn raw_display_handle(&self) -> RawDisplayHandle {
3722 raw_display_handle()
3723 }
3724}
3725
3726#[cfg(feature = "raw-window-handle-v0-6")]
3727fn raw_window_handle<C: Context>(context: &C) -> RawWindowHandle {
3728 #[cfg(target_family = "windows")]
3729 {
3730 use std::num::NonZeroIsize;
3731
3732 use raw_window_handle::Win32WindowHandle;
3733 let (hwnd, hinstance): (*mut std::ffi::c_void, *mut std::ffi::c_void) = unsafe {
3734 let hwnd = ffi::glfwGetWin32Window(context.window_ptr());
3735 let hinstance: *mut c_void =
3736 winapi::um::libloaderapi::GetModuleHandleW(std::ptr::null()) as _;
3737 (hwnd, hinstance as _)
3738 };
3739 let mut handle = Win32WindowHandle::new(NonZeroIsize::new(hwnd as isize).unwrap());
3740 handle.hinstance = NonZeroIsize::new(hinstance as isize);
3741 RawWindowHandle::Win32(handle)
3742 }
3743 #[cfg(all(
3744 any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3745 not(feature = "wayland")
3746 ))]
3747 {
3748 use raw_window_handle::XlibWindowHandle;
3749 let window =
3750 unsafe { ffi::glfwGetX11Window(context.window_ptr()) as std::os::raw::c_ulong };
3751 RawWindowHandle::Xlib(XlibWindowHandle::new(window))
3752 }
3753 #[cfg(all(
3754 any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3755 feature = "wayland"
3756 ))]
3757 {
3758 use std::ptr::NonNull;
3759
3760 use raw_window_handle::WaylandWindowHandle;
3761 let surface = unsafe { ffi::glfwGetWaylandWindow(context.window_ptr()) };
3762 let handle = WaylandWindowHandle::new(
3763 NonNull::new(surface).expect("wayland window surface is null"),
3764 );
3765 RawWindowHandle::Wayland(handle)
3766 }
3767 #[cfg(target_os = "macos")]
3768 {
3769 use std::ptr::NonNull;
3770
3771 use objc2::msg_send_id;
3772 use objc2::rc::Id;
3773 use objc2::runtime::NSObject;
3774 use raw_window_handle::AppKitWindowHandle;
3775 let ns_window: *mut NSObject =
3776 unsafe { ffi::glfwGetCocoaWindow(context.window_ptr()) as *mut _ };
3777 let ns_view: Option<Id<NSObject>> = unsafe { msg_send_id![ns_window, contentView] };
3778 let ns_view = ns_view.expect("failed to access contentView on GLFW NSWindow");
3779 let ns_view: NonNull<NSObject> = NonNull::from(&*ns_view);
3780 let handle = AppKitWindowHandle::new(ns_view.cast());
3781 RawWindowHandle::AppKit(handle)
3782 }
3783 #[cfg(target_os = "emscripten")]
3784 {
3785 let _ = context; let mut wh = raw_window_handle::WebWindowHandle::new(1);
3787 RawWindowHandle::Web(wh)
3791 }
3792}
3793
3794#[cfg(feature = "raw-window-handle-v0-6")]
3795fn raw_display_handle() -> RawDisplayHandle {
3796 #[cfg(target_family = "windows")]
3797 {
3798 use raw_window_handle::WindowsDisplayHandle;
3799 RawDisplayHandle::Windows(WindowsDisplayHandle::new())
3800 }
3801 #[cfg(all(
3802 any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3803 not(feature = "wayland")
3804 ))]
3805 {
3806 use std::ptr::NonNull;
3807
3808 use raw_window_handle::XlibDisplayHandle;
3809 let display = NonNull::new(unsafe { ffi::glfwGetX11Display() });
3810 let handle = XlibDisplayHandle::new(display, 0);
3811 RawDisplayHandle::Xlib(handle)
3812 }
3813 #[cfg(all(
3814 any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3815 feature = "wayland"
3816 ))]
3817 {
3818 use std::ptr::NonNull;
3819
3820 use raw_window_handle::WaylandDisplayHandle;
3821 let display = NonNull::new(unsafe { ffi::glfwGetWaylandDisplay().cast_mut() })
3822 .expect("wayland display is null");
3823 let handle = WaylandDisplayHandle::new(display);
3824 RawDisplayHandle::Wayland(handle)
3825 }
3826 #[cfg(target_os = "macos")]
3827 {
3828 use raw_window_handle::AppKitDisplayHandle;
3829 RawDisplayHandle::AppKit(AppKitDisplayHandle::new())
3830 }
3831 #[cfg(target_os = "emscripten")]
3832 {
3833 RawDisplayHandle::Web(raw_window_handle::WebDisplayHandle::new())
3834 }
3835}
3836
3837#[cfg(feature = "raw-window-handle-v0-5")]
3838fn raw_window_handle<C: Context>(context: &C) -> RawWindowHandle {
3839 #[cfg(target_family = "windows")]
3840 {
3841 use raw_window_handle::Win32WindowHandle;
3842 let (hwnd, hinstance) = unsafe {
3843 let hwnd = ffi::glfwGetWin32Window(context.window_ptr());
3844 let hinstance = winapi::um::libloaderapi::GetModuleHandleW(std::ptr::null());
3845 (hwnd, hinstance as _)
3846 };
3847 let mut handle = Win32WindowHandle::empty();
3848 handle.hwnd = hwnd;
3849 handle.hinstance = hinstance;
3850 RawWindowHandle::Win32(handle)
3851 }
3852 #[cfg(all(
3853 any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3854 not(feature = "wayland")
3855 ))]
3856 {
3857 use raw_window_handle::XlibWindowHandle;
3858 let mut handle = XlibWindowHandle::empty();
3859 handle.window =
3860 unsafe { ffi::glfwGetX11Window(context.window_ptr()) as std::os::raw::c_ulong };
3861 RawWindowHandle::Xlib(handle)
3862 }
3863 #[cfg(all(
3864 any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3865 feature = "wayland"
3866 ))]
3867 {
3868 use raw_window_handle::WaylandWindowHandle;
3869 let mut handle = WaylandWindowHandle::empty();
3870 handle.surface = unsafe { ffi::glfwGetWaylandWindow(context.window_ptr()) };
3871 RawWindowHandle::Wayland(handle)
3872 }
3873 #[cfg(target_os = "macos")]
3874 {
3875 use raw_window_handle::AppKitWindowHandle;
3876 let (ns_window, ns_view) = unsafe {
3877 let ns_window: *mut objc::runtime::Object =
3878 ffi::glfwGetCocoaWindow(context.window_ptr()) as *mut _;
3879 let ns_view: *mut objc::runtime::Object = objc::msg_send![ns_window, contentView];
3880 assert_ne!(ns_view, std::ptr::null_mut());
3881 (
3882 ns_window as *mut std::ffi::c_void,
3883 ns_view as *mut std::ffi::c_void,
3884 )
3885 };
3886 let mut handle = AppKitWindowHandle::empty();
3887 handle.ns_window = ns_window;
3888 handle.ns_view = ns_view;
3889 RawWindowHandle::AppKit(handle)
3890 }
3891 #[cfg(target_os = "emscripten")]
3892 {
3893 let _ = context; let mut wh = raw_window_handle::WebWindowHandle::empty();
3895 wh.id = 1;
3899 RawWindowHandle::Web(wh)
3900 }
3901}
3902
3903#[cfg(feature = "raw-window-handle-v0-5")]
3904fn raw_display_handle() -> RawDisplayHandle {
3905 #[cfg(target_family = "windows")]
3906 {
3907 use raw_window_handle::WindowsDisplayHandle;
3908 RawDisplayHandle::Windows(WindowsDisplayHandle::empty())
3909 }
3910 #[cfg(all(
3911 any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3912 not(feature = "wayland")
3913 ))]
3914 {
3915 use raw_window_handle::XlibDisplayHandle;
3916 let mut handle = XlibDisplayHandle::empty();
3917 handle.display = unsafe { ffi::glfwGetX11Display() };
3918 RawDisplayHandle::Xlib(handle)
3919 }
3920 #[cfg(all(
3921 any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3922 feature = "wayland"
3923 ))]
3924 {
3925 use raw_window_handle::WaylandDisplayHandle;
3926 let mut handle = WaylandDisplayHandle::empty();
3927 handle.display = unsafe { ffi::glfwGetWaylandDisplay() };
3928 RawDisplayHandle::Wayland(handle)
3929 }
3930 #[cfg(target_os = "macos")]
3931 {
3932 use raw_window_handle::AppKitDisplayHandle;
3933 RawDisplayHandle::AppKit(AppKitDisplayHandle::empty())
3934 }
3935 #[cfg(target_os = "emscripten")]
3936 {
3937 RawDisplayHandle::Web(raw_window_handle::WebDisplayHandle::empty())
3938 }
3939}
3940
3941pub fn make_context_current(context: Option<&dyn Context>) {
3943 match context {
3944 Some(ctx) => unsafe { ffi::glfwMakeContextCurrent(ctx.window_ptr()) },
3945 None => unsafe { ffi::glfwMakeContextCurrent(ptr::null_mut()) },
3946 }
3947}
3948
3949#[repr(i32)]
3951#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
3952#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3953pub enum JoystickId {
3954 Joystick1 = ffi::GLFW_JOYSTICK_1,
3955 Joystick2 = ffi::GLFW_JOYSTICK_2,
3956 Joystick3 = ffi::GLFW_JOYSTICK_3,
3957 Joystick4 = ffi::GLFW_JOYSTICK_4,
3958 Joystick5 = ffi::GLFW_JOYSTICK_5,
3959 Joystick6 = ffi::GLFW_JOYSTICK_6,
3960 Joystick7 = ffi::GLFW_JOYSTICK_7,
3961 Joystick8 = ffi::GLFW_JOYSTICK_8,
3962 Joystick9 = ffi::GLFW_JOYSTICK_9,
3963 Joystick10 = ffi::GLFW_JOYSTICK_10,
3964 Joystick11 = ffi::GLFW_JOYSTICK_11,
3965 Joystick12 = ffi::GLFW_JOYSTICK_12,
3966 Joystick13 = ffi::GLFW_JOYSTICK_13,
3967 Joystick14 = ffi::GLFW_JOYSTICK_14,
3968 Joystick15 = ffi::GLFW_JOYSTICK_15,
3969 Joystick16 = ffi::GLFW_JOYSTICK_16,
3970}
3971
3972impl JoystickId {
3973 pub fn from_i32(n: i32) -> Option<JoystickId> {
3975 if (0..=ffi::GLFW_JOYSTICK_LAST).contains(&n) {
3976 Some(unsafe { mem::transmute(n) })
3977 } else {
3978 None
3979 }
3980 }
3981}
3982
3983#[repr(i32)]
3985#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
3986#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3987pub enum GamepadButton {
3988 ButtonA = ffi::GLFW_GAMEPAD_BUTTON_A,
3989 ButtonB = ffi::GLFW_GAMEPAD_BUTTON_B,
3990 ButtonX = ffi::GLFW_GAMEPAD_BUTTON_X,
3991 ButtonY = ffi::GLFW_GAMEPAD_BUTTON_Y,
3992 ButtonLeftBumper = ffi::GLFW_GAMEPAD_BUTTON_LEFT_BUMPER,
3993 ButtonRightBumper = ffi::GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER,
3994 ButtonBack = ffi::GLFW_GAMEPAD_BUTTON_BACK,
3995 ButtonStart = ffi::GLFW_GAMEPAD_BUTTON_START,
3996 ButtonGuide = ffi::GLFW_GAMEPAD_BUTTON_GUIDE,
3997 ButtonLeftThumb = ffi::GLFW_GAMEPAD_BUTTON_LEFT_THUMB,
3998 ButtonRightThumb = ffi::GLFW_GAMEPAD_BUTTON_RIGHT_THUMB,
3999 ButtonDpadUp = ffi::GLFW_GAMEPAD_BUTTON_DPAD_UP,
4000 ButtonDpadRight = ffi::GLFW_GAMEPAD_BUTTON_DPAD_RIGHT,
4001 ButtonDpadDown = ffi::GLFW_GAMEPAD_BUTTON_DPAD_DOWN,
4002 ButtonDpadLeft = ffi::GLFW_GAMEPAD_BUTTON_DPAD_LEFT,
4003}
4004
4005impl GamepadButton {
4006 pub fn from_i32(n: i32) -> Option<GamepadButton> {
4008 if (0..=ffi::GLFW_GAMEPAD_BUTTON_LAST).contains(&n) {
4009 Some(unsafe { mem::transmute(n) })
4010 } else {
4011 None
4012 }
4013 }
4014}
4015
4016#[repr(i32)]
4018#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
4019#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4020pub enum GamepadAxis {
4021 AxisLeftX = ffi::GLFW_GAMEPAD_AXIS_LEFT_X,
4022 AxisLeftY = ffi::GLFW_GAMEPAD_AXIS_LEFT_Y,
4023 AxisRightX = ffi::GLFW_GAMEPAD_AXIS_RIGHT_X,
4024 AxisRightY = ffi::GLFW_GAMEPAD_AXIS_RIGHT_Y,
4025 AxisLeftTrigger = ffi::GLFW_GAMEPAD_AXIS_LEFT_TRIGGER,
4026 AxisRightTrigger = ffi::GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER,
4027}
4028
4029impl GamepadAxis {
4030 pub fn from_i32(n: i32) -> Option<GamepadAxis> {
4032 if (0..=ffi::GLFW_GAMEPAD_AXIS_LAST).contains(&n) {
4033 Some(unsafe { mem::transmute(n) })
4034 } else {
4035 None
4036 }
4037 }
4038}
4039
4040bitflags! {
4041 #[doc = "Joystick hats."]
4042 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4043 pub struct JoystickHats: ::std::os::raw::c_int {
4044 const Centered = crate::ffi::GLFW_HAT_CENTERED;
4045 const Up = crate::ffi::GLFW_HAT_UP;
4046 const Right = crate::ffi::GLFW_HAT_RIGHT;
4047 const Down = crate::ffi::GLFW_HAT_DOWN;
4048 const Left = crate::ffi::GLFW_HAT_LEFT;
4049 }
4050}
4051
4052#[derive(Clone, Debug)]
4054pub struct Joystick {
4055 pub id: JoystickId,
4056 pub glfw: Glfw,
4057}
4058
4059#[derive(Copy, Clone, Debug)]
4061#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4062pub struct GamepadState {
4063 buttons: [Action; (ffi::GLFW_GAMEPAD_BUTTON_LAST + 1) as usize],
4064 axes: [f32; (ffi::GLFW_GAMEPAD_AXIS_LAST + 1) as usize],
4065}
4066
4067#[repr(i32)]
4069#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
4070#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4071pub enum JoystickEvent {
4072 Connected = ffi::GLFW_CONNECTED,
4073 Disconnected = ffi::GLFW_DISCONNECTED,
4074}
4075
4076impl Joystick {
4077 pub fn is_present(&self) -> bool {
4079 unsafe { ffi::glfwJoystickPresent(self.id as c_int) == ffi::GLFW_TRUE }
4080 }
4081
4082 pub fn get_axes(&self) -> Vec<f32> {
4084 unsafe {
4085 let mut count = 0;
4086 let ptr = ffi::glfwGetJoystickAxes(self.id as c_int, &mut count);
4087 slice::from_raw_parts(ptr, count as usize)
4088 .iter()
4089 .map(|&a| a as f32)
4090 .collect()
4091 }
4092 }
4093
4094 pub fn get_buttons(&self) -> Vec<c_int> {
4096 unsafe {
4097 let mut count = 0;
4098 let ptr = ffi::glfwGetJoystickButtons(self.id as c_int, &mut count);
4099 slice::from_raw_parts(ptr, count as usize)
4100 .iter()
4101 .map(|&b| b as c_int)
4102 .collect()
4103 }
4104 }
4105
4106 pub fn get_hats(&self) -> Vec<JoystickHats> {
4108 unsafe {
4109 let mut count = 0;
4110 let ptr = ffi::glfwGetJoystickHats(self.id as c_int, &mut count);
4111 slice::from_raw_parts(ptr, count as usize)
4112 .iter()
4113 .map(|&b| mem::transmute(b as c_int))
4114 .collect()
4115 }
4116 }
4117
4118 pub fn get_name(&self) -> Option<String> {
4120 unsafe { string_from_nullable_c_str(ffi::glfwGetJoystickName(self.id as c_int)) }
4121 }
4122
4123 pub fn get_guid(&self) -> Option<String> {
4125 unsafe { string_from_nullable_c_str(ffi::glfwGetJoystickGUID(self.id as c_int)) }
4126 }
4127
4128 pub fn is_gamepad(&self) -> bool {
4130 unsafe { ffi::glfwJoystickIsGamepad(self.id as c_int) == ffi::GLFW_TRUE }
4131 }
4132
4133 pub fn get_gamepad_name(&self) -> Option<String> {
4135 unsafe { string_from_nullable_c_str(ffi::glfwGetGamepadName(self.id as c_int)) }
4136 }
4137
4138 pub fn get_gamepad_state(&self) -> Option<GamepadState> {
4140 unsafe {
4141 let mut state = ffi::GLFWgamepadstate {
4142 buttons: [0; (ffi::GLFW_GAMEPAD_BUTTON_LAST + 1) as usize],
4143 axes: [0_f32; (ffi::GLFW_GAMEPAD_AXIS_LAST + 1) as usize],
4144 };
4145 if ffi::glfwGetGamepadState(self.id as c_int, &mut state) == ffi::GLFW_TRUE {
4146 Some(state.into())
4147 } else {
4148 None
4149 }
4150 }
4151 }
4152}
4153
4154impl From<ffi::GLFWgamepadstate> for GamepadState {
4155 fn from(state: ffi::GLFWgamepadstate) -> Self {
4156 let mut buttons = [Action::Release; (ffi::GLFW_GAMEPAD_BUTTON_LAST + 1) as usize];
4157 let mut axes = [0_f32; (ffi::GLFW_GAMEPAD_AXIS_LAST + 1) as usize];
4158 unsafe {
4159 state
4160 .buttons
4161 .iter()
4162 .map(|&b| mem::transmute(b as c_int))
4163 .zip(buttons.iter_mut())
4164 .for_each(|(a, b)| *b = a);
4165 }
4166 state
4167 .axes
4168 .iter()
4169 .map(|&f| f as f32)
4170 .zip(axes.iter_mut())
4171 .for_each(|(a, b)| *b = a);
4172 Self { buttons, axes }
4173 }
4174}
4175
4176impl GamepadState {
4177 pub fn get_button_state(&self, button: GamepadButton) -> Action {
4178 self.buttons[button as usize]
4179 }
4180
4181 pub fn get_axis(&self, axis: GamepadAxis) -> f32 {
4182 self.axes[axis as usize]
4183 }
4184}
4185
4186#[inline(always)]
4187fn unwrap_dont_care(value: Option<u32>) -> c_int {
4188 match value {
4189 Some(v) => v as c_int,
4190 None => ffi::GLFW_DONT_CARE,
4191 }
4192}