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;
1253 let refs: Vec<&mut Monitor> = if ptr.is_null() {
1254 Vec::new()
1255 } else {
1256 monitors = slice::from_raw_parts(ptr as *const _, count as usize)
1257 .iter()
1258 .map(|&ptr| Monitor { ptr })
1259 .collect::<Vec<Monitor>>();
1260 monitors.iter_mut().collect()
1261 };
1262 f(self, &refs)
1263 }
1264 }
1265
1266 #[cfg(feature = "vulkan")]
1268 pub fn vulkan_supported(&self) -> bool {
1269 unsafe { ffi::glfwVulkanSupported() == ffi::GLFW_TRUE }
1270 }
1271
1272 pub fn window_hint(&mut self, hint: WindowHint) {
1302 #[inline(always)]
1307 unsafe fn dont_care_hint(hint: c_int, value: Option<u32>) {
1308 ffi::glfwWindowHint(hint, unwrap_dont_care(value))
1309 }
1310
1311 #[inline(always)]
1312 unsafe fn string_hint(hint: c_int, value: Option<String>) {
1313 let value = if let Some(value) = &value {
1314 value.as_str()
1315 } else {
1316 ""
1317 };
1318 with_c_str(value, |value| ffi::glfwWindowHintString(hint, value))
1319 }
1320
1321 match hint {
1322 WindowHint::MousePassthrough(value) => unsafe {
1323 ffi::glfwWindowHint(ffi::GLFW_MOUSE_PASSTHROUGH, value as c_int)
1324 },
1325 WindowHint::RedBits(bits) => unsafe { dont_care_hint(ffi::GLFW_RED_BITS, bits) },
1326 WindowHint::GreenBits(bits) => unsafe { dont_care_hint(ffi::GLFW_GREEN_BITS, bits) },
1327 WindowHint::BlueBits(bits) => unsafe { dont_care_hint(ffi::GLFW_BLUE_BITS, bits) },
1328 WindowHint::AlphaBits(bits) => unsafe { dont_care_hint(ffi::GLFW_ALPHA_BITS, bits) },
1329 WindowHint::DepthBits(bits) => unsafe { dont_care_hint(ffi::GLFW_DEPTH_BITS, bits) },
1330 WindowHint::StencilBits(bits) => unsafe {
1331 dont_care_hint(ffi::GLFW_STENCIL_BITS, bits)
1332 },
1333 WindowHint::AccumRedBits(bits) => unsafe {
1334 dont_care_hint(ffi::GLFW_ACCUM_RED_BITS, bits)
1335 },
1336 WindowHint::AccumGreenBits(bits) => unsafe {
1337 dont_care_hint(ffi::GLFW_ACCUM_GREEN_BITS, bits)
1338 },
1339 WindowHint::AccumBlueBits(bits) => unsafe {
1340 dont_care_hint(ffi::GLFW_ACCUM_BLUE_BITS, bits)
1341 },
1342 WindowHint::AccumAlphaBits(bits) => unsafe {
1343 dont_care_hint(ffi::GLFW_ACCUM_ALPHA_BITS, bits)
1344 },
1345 WindowHint::AuxBuffers(num_buffers) => unsafe {
1346 dont_care_hint(ffi::GLFW_AUX_BUFFERS, num_buffers)
1347 },
1348 WindowHint::Samples(num_samples) => unsafe {
1349 dont_care_hint(ffi::GLFW_SAMPLES, num_samples)
1350 },
1351 WindowHint::RefreshRate(rate) => unsafe {
1352 dont_care_hint(ffi::GLFW_REFRESH_RATE, rate)
1353 },
1354 WindowHint::Stereo(is_stereo) => unsafe {
1355 ffi::glfwWindowHint(ffi::GLFW_STEREO, is_stereo as c_int)
1356 },
1357 WindowHint::SRgbCapable(is_capable) => unsafe {
1358 ffi::glfwWindowHint(ffi::GLFW_SRGB_CAPABLE, is_capable as c_int)
1359 },
1360 WindowHint::ClientApi(api) => unsafe {
1361 ffi::glfwWindowHint(ffi::GLFW_CLIENT_API, api as c_int)
1362 },
1363 WindowHint::ContextVersionMajor(major) => unsafe {
1364 ffi::glfwWindowHint(ffi::GLFW_CONTEXT_VERSION_MAJOR, major as c_int)
1365 },
1366 WindowHint::ContextVersionMinor(minor) => unsafe {
1367 ffi::glfwWindowHint(ffi::GLFW_CONTEXT_VERSION_MINOR, minor as c_int)
1368 },
1369 WindowHint::ContextVersion(major, minor) => unsafe {
1370 ffi::glfwWindowHint(ffi::GLFW_CONTEXT_VERSION_MAJOR, major as c_int);
1371 ffi::glfwWindowHint(ffi::GLFW_CONTEXT_VERSION_MINOR, minor as c_int)
1372 },
1373 WindowHint::ContextRobustness(robustness) => unsafe {
1374 ffi::glfwWindowHint(ffi::GLFW_CONTEXT_ROBUSTNESS, robustness as c_int)
1375 },
1376 WindowHint::OpenGlForwardCompat(is_compat) => unsafe {
1377 ffi::glfwWindowHint(ffi::GLFW_OPENGL_FORWARD_COMPAT, is_compat as c_int)
1378 },
1379 WindowHint::OpenGlDebugContext(is_debug) => unsafe {
1380 ffi::glfwWindowHint(ffi::GLFW_OPENGL_DEBUG_CONTEXT, is_debug as c_int)
1381 },
1382 WindowHint::OpenGlProfile(profile) => unsafe {
1383 ffi::glfwWindowHint(ffi::GLFW_OPENGL_PROFILE, profile as c_int)
1384 },
1385 WindowHint::Resizable(is_resizable) => unsafe {
1386 ffi::glfwWindowHint(ffi::GLFW_RESIZABLE, is_resizable as c_int)
1387 },
1388 WindowHint::Visible(is_visible) => unsafe {
1389 ffi::glfwWindowHint(ffi::GLFW_VISIBLE, is_visible as c_int)
1390 },
1391 WindowHint::Decorated(is_decorated) => unsafe {
1392 ffi::glfwWindowHint(ffi::GLFW_DECORATED, is_decorated as c_int)
1393 },
1394 WindowHint::AutoIconify(auto_iconify) => unsafe {
1395 ffi::glfwWindowHint(ffi::GLFW_AUTO_ICONIFY, auto_iconify as c_int)
1396 },
1397 WindowHint::Floating(is_floating) => unsafe {
1398 ffi::glfwWindowHint(ffi::GLFW_FLOATING, is_floating as c_int)
1399 },
1400 WindowHint::Focused(is_focused) => unsafe {
1401 ffi::glfwWindowHint(ffi::GLFW_FOCUSED, is_focused as c_int)
1402 },
1403 WindowHint::Maximized(is_maximized) => unsafe {
1404 ffi::glfwWindowHint(ffi::GLFW_MAXIMIZED, is_maximized as c_int)
1405 },
1406 WindowHint::ContextNoError(is_no_error) => unsafe {
1407 ffi::glfwWindowHint(ffi::GLFW_CONTEXT_NO_ERROR, is_no_error as c_int)
1408 },
1409 WindowHint::ContextCreationApi(api) => unsafe {
1410 ffi::glfwWindowHint(ffi::GLFW_CONTEXT_CREATION_API, api as c_int)
1411 },
1412 WindowHint::ContextReleaseBehavior(behavior) => unsafe {
1413 ffi::glfwWindowHint(ffi::GLFW_CONTEXT_RELEASE_BEHAVIOR, behavior as c_int)
1414 },
1415 WindowHint::DoubleBuffer(is_dbuffered) => unsafe {
1416 ffi::glfwWindowHint(ffi::GLFW_DOUBLEBUFFER, is_dbuffered as c_int)
1417 },
1418 WindowHint::CenterCursor(center_cursor) => unsafe {
1419 ffi::glfwWindowHint(ffi::GLFW_CENTER_CURSOR, center_cursor as c_int)
1420 },
1421 WindowHint::TransparentFramebuffer(is_transparent) => unsafe {
1422 ffi::glfwWindowHint(ffi::GLFW_TRANSPARENT_FRAMEBUFFER, is_transparent as c_int)
1423 },
1424 WindowHint::FocusOnShow(focus) => unsafe {
1425 ffi::glfwWindowHint(ffi::GLFW_FOCUS_ON_SHOW, focus as c_int)
1426 },
1427 WindowHint::ScaleToMonitor(scale) => unsafe {
1428 ffi::glfwWindowHint(ffi::GLFW_SCALE_TO_MONITOR, scale as c_int)
1429 },
1430 WindowHint::CocoaRetinaFramebuffer(retina_fb) => unsafe {
1431 ffi::glfwWindowHint(ffi::GLFW_COCOA_RETINA_FRAMEBUFFER, retina_fb as c_int)
1432 },
1433 WindowHint::CocoaFrameName(name) => unsafe {
1434 string_hint(ffi::GLFW_COCOA_FRAME_NAME, name)
1435 },
1436 WindowHint::CocoaGraphicsSwitching(graphics_switching) => unsafe {
1437 ffi::glfwWindowHint(
1438 ffi::GLFW_COCOA_GRAPHICS_SWITCHING,
1439 graphics_switching as c_int,
1440 )
1441 },
1442 WindowHint::X11ClassName(class_name) => unsafe {
1443 string_hint(ffi::GLFW_X11_CLASS_NAME, class_name)
1444 },
1445 WindowHint::X11InstanceName(instance_name) => unsafe {
1446 string_hint(ffi::GLFW_X11_INSTANCE_NAME, instance_name)
1447 },
1448 }
1449 }
1450
1451 pub fn default_window_hints(&mut self) {
1456 unsafe {
1457 ffi::glfwDefaultWindowHints();
1458 }
1459 }
1460
1461 pub fn create_window(
1465 &mut self,
1466 width: u32,
1467 height: u32,
1468 title: &str,
1469 mode: WindowMode<'_>,
1470 ) -> Option<(PWindow, GlfwReceiver<(f64, WindowEvent)>)> {
1471 #[cfg(feature = "wayland")]
1472 {
1473 self.window_hint(WindowHint::Focused(false));
1475 }
1476 self.create_window_intern(width, height, title, mode, None)
1477 }
1478
1479 fn create_window_intern(
1481 &self,
1482 width: u32,
1483 height: u32,
1484 title: &str,
1485 mode: WindowMode<'_>,
1486 share: Option<&Window>,
1487 ) -> Option<(PWindow, GlfwReceiver<(f64, WindowEvent)>)> {
1488 let ptr = unsafe {
1489 with_c_str(title, |title| {
1490 ffi::glfwCreateWindow(
1491 width as c_int,
1492 height as c_int,
1493 title,
1494 mode.to_ptr(),
1495 match share {
1496 Some(w) => w.ptr,
1497 None => ptr::null_mut(),
1498 },
1499 )
1500 })
1501 };
1502 if ptr.is_null() {
1503 None
1504 } else {
1505 let (drop_sender, drop_receiver) = channel();
1506 let (sender, receiver) = glfw_channel(16, 256);
1507 let window = Window {
1508 ptr,
1509 glfw: self.clone(),
1510 is_shared: share.is_some(),
1511 drop_sender: Some(drop_sender),
1512 drop_receiver,
1513 current_cursor: None,
1514 };
1515 let mut callbacks = Box::new(WindowCallbacks::new(sender));
1516 let mut window = PWindow(Box::new(window));
1517
1518 unsafe {
1519 callbacks.window_ptr = window.raw_ptr();
1520 ffi::glfwSetWindowUserPointer(ptr, mem::transmute(callbacks));
1521 }
1522
1523 Some((window, receiver))
1524 }
1525 }
1526
1527 pub fn make_context_current(&mut self, context: Option<&Window>) {
1532 match context {
1533 Some(window) => unsafe { ffi::glfwMakeContextCurrent(window.ptr) },
1534 None => unsafe { ffi::glfwMakeContextCurrent(ptr::null_mut()) },
1535 }
1536 }
1537
1538 #[cfg(all(not(target_os = "windows"), not(target_os = "macos"), feature = "x11"))]
1540 pub fn get_x11_display(&self) -> *mut c_void {
1541 unsafe { ffi::glfwGetX11Display() }
1542 }
1543
1544 #[cfg(all(
1546 not(target_os = "windows"),
1547 not(target_os = "macos"),
1548 feature = "wayland"
1549 ))]
1550 pub fn get_wayland_display(&self) -> *mut c_void {
1551 unsafe { ffi::glfwGetWaylandDisplay().cast_mut() }
1552 }
1553 pub fn get_platform(&self) -> Platform {
1555 unsafe { mem::transmute(ffi::glfwGetPlatform()) }
1556 }
1557 pub fn poll_events(&mut self) {
1561 unsafe {
1562 ffi::glfwPollEvents();
1563 }
1564 }
1565
1566 pub fn poll_events_unbuffered<F>(&mut self, mut f: F)
1574 where
1575 F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>,
1576 {
1577 let _unset_handler_guard = unsafe { crate::callbacks::unbuffered::set_handler(&mut f) };
1578 self.poll_events();
1579 }
1580
1581 pub fn wait_events(&mut self) {
1586 unsafe {
1587 ffi::glfwWaitEvents();
1588 }
1589 }
1590
1591 pub fn wait_events_unbuffered<F>(&mut self, mut f: F)
1596 where
1597 F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>,
1598 {
1599 let _unset_handler_guard = unsafe { crate::callbacks::unbuffered::set_handler(&mut f) };
1600 self.wait_events();
1601 }
1602
1603 pub fn wait_events_timeout(&mut self, timeout: f64) {
1609 unsafe {
1610 ffi::glfwWaitEventsTimeout(timeout);
1611 }
1612 }
1613
1614 pub fn wait_events_timeout_unbuffered<F>(&mut self, timeout: f64, mut f: F)
1620 where
1621 F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>,
1622 {
1623 let _unset_handler_guard = unsafe { crate::callbacks::unbuffered::set_handler(&mut f) };
1624 self.wait_events_timeout(timeout);
1625 }
1626
1627 pub fn post_empty_event(&self) {
1633 unsafe {
1634 ffi::glfwPostEmptyEvent();
1635 }
1636 }
1637
1638 pub fn get_time(&self) -> f64 {
1644 unsafe { ffi::glfwGetTime() as f64 }
1645 }
1646
1647 pub fn set_time(&mut self, time: f64) {
1651 unsafe {
1652 ffi::glfwSetTime(time as c_double);
1653 }
1654 }
1655
1656 pub fn get_timer_value(&self) -> u64 {
1658 unsafe { ffi::glfwGetTimerValue() as u64 }
1659 }
1660
1661 pub fn get_timer_frequency(&self) -> u64 {
1663 unsafe { ffi::glfwGetTimerFrequency() as u64 }
1664 }
1665
1666 pub fn set_swap_interval(&mut self, interval: SwapInterval) {
1671 unsafe {
1672 ffi::glfwSwapInterval(match interval {
1673 SwapInterval::None => 0_i32,
1674 SwapInterval::Adaptive => -1_i32,
1675 SwapInterval::Sync(interval) => interval as c_int,
1676 })
1677 }
1678 }
1679
1680 pub fn extension_supported(&self, extension: &str) -> bool {
1685 unsafe {
1686 with_c_str(extension, |extension| {
1687 ffi::glfwExtensionSupported(extension) == ffi::GLFW_TRUE
1688 })
1689 }
1690 }
1691
1692 #[cfg(feature = "vulkan")]
1701 pub fn get_required_instance_extensions(&self) -> Option<Vec<String>> {
1702 let mut len: c_uint = 0;
1703
1704 unsafe {
1705 let raw_extensions: *const *const c_char =
1706 ffi::glfwGetRequiredInstanceExtensions(&mut len as *mut c_uint);
1707
1708 if !raw_extensions.is_null() {
1709 return Some(
1710 slice::from_raw_parts(raw_extensions, len as usize)
1711 .iter()
1712 .map(|extensions| string_from_c_str(*extensions))
1713 .collect(),
1714 );
1715 }
1716 }
1717
1718 None
1719 }
1720
1721 pub fn get_proc_address_raw(&self, procname: &str) -> GLProc {
1726 debug_assert!(unsafe { ffi::glfwGetCurrentContext() } != std::ptr::null_mut());
1727 with_c_str(procname, |procname| unsafe {
1728 ffi::glfwGetProcAddress(procname)
1729 })
1730 }
1731
1732 #[cfg(feature = "vulkan")]
1745 pub fn get_instance_proc_address_raw(
1746 &self,
1747 instance: ffi::VkInstance,
1748 procname: &str,
1749 ) -> VkProc {
1750 with_c_str(procname, |procname| unsafe {
1751 ffi::glfwGetInstanceProcAddress(instance, procname)
1752 })
1753 }
1754
1755 #[cfg(feature = "vulkan")]
1760 pub fn get_physical_device_presentation_support_raw(
1761 &self,
1762 instance: ffi::VkInstance,
1763 device: ffi::VkPhysicalDevice,
1764 queue_family: u32,
1765 ) -> bool {
1766 ffi::GLFW_TRUE
1767 == unsafe {
1768 ffi::glfwGetPhysicalDevicePresentationSupport(
1769 instance,
1770 device,
1771 queue_family as c_uint,
1772 )
1773 }
1774 }
1775
1776 pub fn get_joystick(&self, id: JoystickId) -> Joystick {
1778 Joystick {
1779 id,
1780 glfw: self.clone(),
1781 }
1782 }
1783
1784 pub fn supports_raw_motion(&self) -> bool {
1786 unsafe { ffi::glfwRawMouseMotionSupported() == ffi::GLFW_TRUE }
1787 }
1788
1789 pub fn update_gamepad_mappings(&self, mappings: &str) -> bool {
1800 unsafe {
1801 with_c_str(mappings, |mappings| {
1802 ffi::glfwUpdateGamepadMappings(mappings) == ffi::GLFW_TRUE
1803 })
1804 }
1805 }
1806}
1807
1808impl Clone for Glfw {
1809 fn clone(&self) -> Self {
1810 REF_COUNT_FOR_GLFW.fetch_add(1, Ordering::SeqCst);
1811 Glfw {
1812 phantom: std::marker::PhantomData,
1813 }
1814 }
1815}
1816
1817impl Drop for Glfw {
1818 fn drop(&mut self) {
1819 let old_diff = REF_COUNT_FOR_GLFW.fetch_sub(1, Ordering::SeqCst);
1820 if old_diff == 1 {
1821 unsafe {
1822 ffi::glfwTerminate();
1823 }
1824 }
1825 }
1826}
1827
1828fn glfw_channel<T>(initial_capacity: usize, max_len: usize) -> (GlfwSender<T>, GlfwReceiver<T>) {
1829 let shared = Arc::new(SharedTransmitter {
1830 queue: Mutex::new(VecDeque::with_capacity(initial_capacity)),
1831 max_len,
1832 });
1833 let (mpsc_sender, mpsc_receiver) = channel();
1834
1835 let sender = GlfwSender {
1836 transmitter: shared.clone(),
1837 sender: mpsc_sender,
1838 };
1839 let receiver = GlfwReceiver {
1840 transmitter: shared.clone(),
1841 receiver: mpsc_receiver,
1842 };
1843 (sender, receiver)
1844}
1845
1846#[derive(Debug)]
1847struct SharedTransmitter<T> {
1848 queue: Mutex<VecDeque<T>>,
1849 max_len: usize,
1850}
1851
1852#[derive(Debug, Clone)]
1853struct GlfwSender<T> {
1854 transmitter: Arc<SharedTransmitter<T>>,
1855 sender: Sender<T>,
1856}
1857
1858impl<T> GlfwSender<T> {
1859 fn send(&self, v: T) {
1860 let mut queue = self.transmitter.queue.lock().unwrap();
1861 if queue.len() >= self.transmitter.max_len {
1862 let _ = self.sender.send(v);
1863 } else {
1864 queue.push_back(v);
1865 }
1866 }
1867}
1868
1869#[derive(Debug)]
1870pub struct GlfwReceiver<T> {
1871 transmitter: Arc<SharedTransmitter<T>>,
1872 receiver: Receiver<T>,
1873}
1874
1875impl<T> GlfwReceiver<T> {
1876 pub fn receive(&self) -> Option<T> {
1877 let ret = self.transmitter.queue.lock().unwrap().pop_front();
1878 if ret.is_some() {
1879 ret
1880 } else {
1881 match self.receiver.try_recv() {
1882 Ok(ret) => Some(ret),
1883 Err(_) => None,
1884 }
1885 }
1886 }
1887}
1888
1889struct WindowCallbacks {
1890 window_ptr: *mut Window,
1891 sender: GlfwSender<(f64, WindowEvent)>,
1892 pos_callback: Option<Box<dyn FnMut(&mut Window, i32, i32)>>,
1893 size_callback: Option<Box<dyn FnMut(&mut Window, i32, i32)>>,
1894 close_callback: Option<Box<dyn FnMut(&mut Window)>>,
1895 refresh_callback: Option<Box<dyn FnMut(&mut Window)>>,
1896 focus_callback: Option<Box<dyn FnMut(&mut Window, bool)>>,
1897 iconify_callback: Option<Box<dyn FnMut(&mut Window, bool)>>,
1898 framebuffer_size_callback: Option<Box<dyn FnMut(&mut Window, i32, i32)>>,
1899 key_callback: Option<Box<dyn FnMut(&mut Window, Key, Scancode, Action, Modifiers)>>,
1900 char_callback: Option<Box<dyn FnMut(&mut Window, char)>>,
1901 char_mods_callback: Option<Box<dyn FnMut(&mut Window, char, Modifiers)>>,
1902 mouse_button_callback: Option<Box<dyn FnMut(&mut Window, MouseButton, Action, Modifiers)>>,
1903 cursor_pos_callback: Option<Box<dyn FnMut(&mut Window, f64, f64)>>,
1904 cursor_enter_callback: Option<Box<dyn FnMut(&mut Window, bool)>>,
1905 scroll_callback: Option<Box<dyn FnMut(&mut Window, f64, f64)>>,
1906 drag_and_drop_callback: Option<Box<dyn FnMut(&mut Window, Vec<PathBuf>)>>,
1907 maximize_callback: Option<Box<dyn FnMut(&mut Window, bool)>>,
1908 content_scale_callback: Option<Box<dyn FnMut(&mut Window, f32, f32)>>,
1909 pos_polling: bool,
1910 size_polling: bool,
1911 close_polling: bool,
1912 refresh_polling: bool,
1913 focus_polling: bool,
1914 iconify_polling: bool,
1915 framebuffer_size_polling: bool,
1916 key_polling: bool,
1917 char_polling: bool,
1918 char_mods_polling: bool,
1919 mouse_button_polling: bool,
1920 cursor_pos_polling: bool,
1921 cursor_enter_polling: bool,
1922 scroll_polling: bool,
1923 drag_and_drop_polling: bool,
1924 maximize_polling: bool,
1925 content_scale_polling: bool,
1926}
1927
1928impl WindowCallbacks {
1929 fn new(sender: GlfwSender<(f64, WindowEvent)>) -> Self {
1930 Self {
1931 window_ptr: std::ptr::null_mut(),
1932 sender,
1933 pos_callback: None,
1934 size_callback: None,
1935 close_callback: None,
1936 refresh_callback: None,
1937 focus_callback: None,
1938 iconify_callback: None,
1939 framebuffer_size_callback: None,
1940 key_callback: None,
1941 char_callback: None,
1942 char_mods_callback: None,
1943 mouse_button_callback: None,
1944 cursor_pos_callback: None,
1945 cursor_enter_callback: None,
1946 scroll_callback: None,
1947 drag_and_drop_callback: None,
1948 maximize_callback: None,
1949 content_scale_callback: None,
1950 pos_polling: false,
1951 size_polling: false,
1952 close_polling: false,
1953 refresh_polling: false,
1954 focus_polling: false,
1955 iconify_polling: false,
1956 framebuffer_size_polling: false,
1957 key_polling: false,
1958 char_polling: false,
1959 char_mods_polling: false,
1960 mouse_button_polling: false,
1961 cursor_pos_polling: false,
1962 cursor_enter_polling: false,
1963 scroll_polling: false,
1964 drag_and_drop_polling: false,
1965 maximize_polling: false,
1966 content_scale_polling: false,
1967 }
1968 }
1969
1970 fn get_callbacks<'a>(window: *mut GLFWwindow) -> &'a mut WindowCallbacks {
1971 unsafe { &mut *(ffi::glfwGetWindowUserPointer(window) as *mut WindowCallbacks) }
1972 }
1973}
1974
1975pub fn get_error() -> Error {
1977 unsafe { mem::transmute(ffi::glfwGetError(null_mut())) }
1978}
1979
1980pub fn get_error_string() -> (Error, String) {
1982 unsafe {
1983 let mut description: *const c_char = null();
1984 let error: Error = mem::transmute(ffi::glfwGetError(&mut description));
1985 (error, string_from_c_str(description))
1986 }
1987}
1988
1989pub fn get_version() -> Version {
1991 unsafe {
1992 let mut major = 0;
1993 let mut minor = 0;
1994 let mut patch = 0;
1995 ffi::glfwGetVersion(&mut major, &mut minor, &mut patch);
1996 Version {
1997 major: major as u64,
1998 minor: minor as u64,
1999 patch: patch as u64,
2000 }
2001 }
2002}
2003
2004pub unsafe fn string_from_c_str(c_str: *const c_char) -> String {
2006 String::from_utf8_lossy(CStr::from_ptr(c_str).to_bytes()).into_owned()
2007}
2008
2009pub unsafe fn string_from_nullable_c_str(c_str: *const c_char) -> Option<String> {
2011 if c_str.is_null() {
2012 None
2013 } else {
2014 Some(string_from_c_str(c_str))
2015 }
2016}
2017
2018pub fn with_c_str<F, T>(s: &str, f: F) -> T
2020where
2021 F: FnOnce(*const c_char) -> T,
2022{
2023 let c_str = CString::new(s.as_bytes());
2024 f(c_str.unwrap().as_bytes_with_nul().as_ptr() as *const _)
2025}
2026
2027pub fn get_version_string() -> String {
2029 unsafe { string_from_c_str(ffi::glfwGetVersionString()) }
2030}
2031
2032#[allow(missing_copy_implementations)]
2034pub struct Monitor {
2035 ptr: *mut ffi::GLFWmonitor,
2036}
2037
2038impl std::fmt::Debug for Monitor {
2039 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2040 write!(f, "Monitor({:p})", self.ptr)
2041 }
2042}
2043
2044impl Monitor {
2045 pub fn get_pos(&self) -> (i32, i32) {
2047 unsafe {
2048 let mut xpos = 0;
2049 let mut ypos = 0;
2050 ffi::glfwGetMonitorPos(self.ptr, &mut xpos, &mut ypos);
2051 (xpos as i32, ypos as i32)
2052 }
2053 }
2054
2055 pub fn get_physical_size(&self) -> (i32, i32) {
2057 unsafe {
2058 let mut width = 0;
2059 let mut height = 0;
2060 ffi::glfwGetMonitorPhysicalSize(self.ptr, &mut width, &mut height);
2061 (width as i32, height as i32)
2062 }
2063 }
2064
2065 pub fn get_name(&self) -> Option<String> {
2067 unsafe { string_from_nullable_c_str(ffi::glfwGetMonitorName(self.ptr)) }
2068 }
2069
2070 pub fn get_video_modes(&self) -> Vec<VidMode> {
2072 unsafe {
2073 let mut count = 0;
2074 let ptr = ffi::glfwGetVideoModes(self.ptr, &mut count);
2075 if ptr.is_null() {
2076 return Vec::new();
2077 }
2078 slice::from_raw_parts(ptr, count as usize)
2079 .iter()
2080 .map(VidMode::from_glfw_vid_mode)
2081 .collect()
2082 }
2083 }
2084
2085 pub fn get_video_mode(&self) -> Option<VidMode> {
2087 unsafe {
2088 let ptr = ffi::glfwGetVideoMode(self.ptr);
2091 if ptr.is_null() {
2092 None
2093 } else {
2094 Some(VidMode::from_glfw_vid_mode(&*ptr))
2095 }
2096 }
2097 }
2098
2099 pub fn set_gamma(&mut self, gamma: f32) {
2101 unsafe {
2102 ffi::glfwSetGamma(self.ptr, gamma as c_float);
2103 }
2104 }
2105
2106 pub fn get_gamma_ramp(&self) -> GammaRamp {
2108 unsafe {
2109 let llramp = *ffi::glfwGetGammaRamp(self.ptr);
2110 GammaRamp {
2111 red: slice::from_raw_parts(llramp.red as *const c_ushort, llramp.size as usize)
2112 .iter()
2113 .copied()
2114 .collect(),
2115 green: slice::from_raw_parts(llramp.green as *const c_ushort, llramp.size as usize)
2116 .iter()
2117 .copied()
2118 .collect(),
2119 blue: slice::from_raw_parts(llramp.blue as *const c_ushort, llramp.size as usize)
2120 .iter()
2121 .copied()
2122 .collect(),
2123 }
2124 }
2125 }
2126
2127 pub fn set_gamma_ramp(&mut self, ramp: &mut GammaRamp) {
2129 unsafe {
2130 ffi::glfwSetGammaRamp(
2131 self.ptr,
2132 &ffi::GLFWgammaramp {
2133 red: ramp.red.as_mut_ptr(),
2134 green: ramp.green.as_mut_ptr(),
2135 blue: ramp.blue.as_mut_ptr(),
2136 size: ramp.red.len() as u32,
2137 },
2138 );
2139 }
2140 }
2141
2142 pub fn get_content_scale(&self) -> (f32, f32) {
2144 unsafe {
2145 let mut xscale = 0.0_f32;
2146 let mut yscale = 0.0_f32;
2147 ffi::glfwGetMonitorContentScale(self.ptr, &mut xscale, &mut yscale);
2148 (xscale, yscale)
2149 }
2150 }
2151
2152 pub fn get_workarea(&self) -> (i32, i32, i32, i32) {
2154 unsafe {
2155 let mut xpos = 0;
2156 let mut ypos = 0;
2157 let mut width = 0;
2158 let mut height = 0;
2159 ffi::glfwGetMonitorWorkarea(self.ptr, &mut xpos, &mut ypos, &mut width, &mut height);
2160 (xpos, ypos, width, height)
2161 }
2162 }
2163}
2164
2165#[repr(i32)]
2167#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2168#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2169pub enum MonitorEvent {
2170 Connected = ffi::GLFW_CONNECTED,
2171 Disconnected = ffi::GLFW_DISCONNECTED,
2172}
2173
2174impl VidMode {
2175 fn from_glfw_vid_mode(mode: &ffi::GLFWvidmode) -> VidMode {
2176 VidMode {
2177 width: mode.width as u32,
2178 height: mode.height as u32,
2179 red_bits: mode.redBits as u32,
2180 green_bits: mode.greenBits as u32,
2181 blue_bits: mode.blueBits as u32,
2182 refresh_rate: mode.refreshRate as u32,
2183 }
2184 }
2185}
2186
2187impl fmt::Debug for VidMode {
2188 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2198 write!(
2199 f,
2200 "{} x {}, {} = {} + {} + {}, {} Hz",
2201 self.width,
2202 self.height,
2203 self.red_bits + self.green_bits + self.blue_bits,
2204 self.red_bits,
2205 self.green_bits,
2206 self.blue_bits,
2207 self.refresh_rate
2208 )
2209 }
2210}
2211
2212#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2214#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2215pub enum WindowHint {
2216 MousePassthrough(bool),
2217 RedBits(Option<u32>),
2219 GreenBits(Option<u32>),
2221 BlueBits(Option<u32>),
2223 AlphaBits(Option<u32>),
2225 DepthBits(Option<u32>),
2227 StencilBits(Option<u32>),
2229 AccumRedBits(Option<u32>),
2231 AccumGreenBits(Option<u32>),
2233 AccumBlueBits(Option<u32>),
2235 AccumAlphaBits(Option<u32>),
2237 AuxBuffers(Option<u32>),
2239 Stereo(bool),
2241 Samples(Option<u32>),
2244 SRgbCapable(bool),
2246 RefreshRate(Option<u32>),
2251 ClientApi(ClientApiHint),
2253 ContextVersionMajor(u32),
2259 ContextVersionMinor(u32),
2265 ContextVersion(u32, u32),
2275 ContextRobustness(ContextRobustnessHint),
2277 OpenGlForwardCompat(bool),
2284 OpenGlDebugContext(bool),
2289 OpenGlProfile(OpenGlProfileHint),
2294 Resizable(bool),
2300 Visible(bool),
2304 Decorated(bool),
2309 AutoIconify(bool),
2314 Floating(bool),
2319 Focused(bool),
2323 Maximized(bool),
2327 ContextNoError(bool),
2330 ContextCreationApi(ContextCreationApi),
2332 ContextReleaseBehavior(ContextReleaseBehavior),
2334 DoubleBuffer(bool),
2341 CenterCursor(bool),
2345 TransparentFramebuffer(bool),
2350 FocusOnShow(bool),
2352 ScaleToMonitor(bool),
2357 CocoaRetinaFramebuffer(bool),
2361 CocoaFrameName(Option<String>),
2366 CocoaGraphicsSwitching(bool),
2380 X11ClassName(Option<String>),
2382 X11InstanceName(Option<String>),
2384}
2385
2386#[repr(i32)]
2388#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2389#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2390pub enum ClientApiHint {
2391 NoApi = ffi::GLFW_NO_API,
2392 OpenGl = ffi::GLFW_OPENGL_API,
2393 OpenGlEs = ffi::GLFW_OPENGL_ES_API,
2394}
2395
2396#[repr(i32)]
2398#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2399#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2400pub enum ContextRobustnessHint {
2401 NoRobustness = ffi::GLFW_NO_ROBUSTNESS,
2402 NoResetNotification = ffi::GLFW_NO_RESET_NOTIFICATION,
2403 LoseContextOnReset = ffi::GLFW_LOSE_CONTEXT_ON_RESET,
2404}
2405
2406#[repr(i32)]
2408#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2409#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2410pub enum OpenGlProfileHint {
2411 Any = ffi::GLFW_OPENGL_ANY_PROFILE,
2412 Core = ffi::GLFW_OPENGL_CORE_PROFILE,
2413 Compat = ffi::GLFW_OPENGL_COMPAT_PROFILE,
2414}
2415
2416#[derive(Copy, Clone, Debug)]
2418pub enum WindowMode<'a> {
2419 FullScreen(&'a Monitor),
2421
2422 Windowed,
2424}
2425
2426impl<'a> WindowMode<'a> {
2428 fn to_ptr(&self) -> *mut ffi::GLFWmonitor {
2431 match *self {
2432 WindowMode::FullScreen(monitor) => monitor.ptr,
2433 WindowMode::Windowed => ptr::null_mut(),
2434 }
2435 }
2436}
2437
2438bitflags! {
2439 #[doc = "Key modifiers (e.g., Shift, Control, Alt, Super)"]
2440 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2441 pub struct Modifiers: ::std::os::raw::c_int {
2442 const Shift = crate::ffi::GLFW_MOD_SHIFT;
2443 const Control = crate::ffi::GLFW_MOD_CONTROL;
2444 const Alt = crate::ffi::GLFW_MOD_ALT;
2445 const Super = crate::ffi::GLFW_MOD_SUPER;
2446 const CapsLock = crate::ffi::GLFW_MOD_CAPS_LOCK;
2447 const NumLock = crate::ffi::GLFW_MOD_NUM_LOCK;
2448 }
2449}
2450
2451pub type Scancode = c_int;
2453
2454#[derive(Clone, PartialEq, PartialOrd, Debug)]
2456#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2457pub enum WindowEvent {
2458 Pos(i32, i32),
2459 Size(i32, i32),
2460 Close,
2461 Refresh,
2462 Focus(bool),
2463 Iconify(bool),
2464 FramebufferSize(i32, i32),
2465 MouseButton(MouseButton, Action, Modifiers),
2466 CursorPos(f64, f64),
2467 CursorEnter(bool),
2468 Scroll(f64, f64),
2469 Key(Key, Scancode, Action, Modifiers),
2470 Char(char),
2471 CharModifiers(char, Modifiers),
2472 FileDrop(Vec<PathBuf>),
2473 Maximize(bool),
2474 ContentScale(f32, f32),
2475}
2476
2477pub fn flush_messages<Message: Send>(
2489 receiver: &GlfwReceiver<Message>,
2490) -> FlushedMessages<'_, Message> {
2491 FlushedMessages(receiver)
2492}
2493
2494#[derive(Debug)]
2497pub struct FlushedMessages<'a, Message: Send>(&'a GlfwReceiver<Message>);
2498
2499unsafe impl<'a, Message: 'a + Send> Send for FlushedMessages<'a, Message> {}
2500
2501impl<'a, Message: 'static + Send> Iterator for FlushedMessages<'a, Message> {
2502 type Item = Message;
2503
2504 fn next(&mut self) -> Option<Message> {
2505 let FlushedMessages(receiver) = *self;
2506 receiver.receive()
2507 }
2508}
2509
2510#[derive(Debug)]
2512pub struct Window {
2513 ptr: *mut ffi::GLFWwindow,
2514 pub is_shared: bool,
2515 drop_sender: Option<Sender<()>>,
2517 #[allow(unused)]
2521 drop_receiver: Receiver<()>,
2522 current_cursor: Option<Cursor>,
2525 pub glfw: Glfw,
2526}
2527
2528impl Window {
2529 pub fn get_proc_address(&mut self, procname: &str) -> GLProc {
2535 if self.ptr != unsafe { ffi::glfwGetCurrentContext() } {
2536 self.make_current();
2537 }
2538
2539 self.glfw.get_proc_address_raw(procname)
2540 }
2541
2542 #[cfg(feature = "vulkan")]
2555 pub fn get_instance_proc_address(
2556 &mut self,
2557 instance: ffi::VkInstance,
2558 procname: &str,
2559 ) -> VkProc {
2560 self.glfw.get_instance_proc_address_raw(instance, procname)
2561 }
2562
2563 #[cfg(feature = "vulkan")]
2568 pub fn get_physical_device_presentation_support(
2569 &self,
2570 instance: ffi::VkInstance,
2571 device: ffi::VkPhysicalDevice,
2572 queue_family: u32,
2573 ) -> bool {
2574 self.glfw
2575 .get_physical_device_presentation_support_raw(instance, device, queue_family)
2576 }
2577
2578 #[cfg(feature = "vulkan")]
2580 pub unsafe fn create_window_surface(
2581 &self,
2582 instance: ffi::VkInstance,
2583 allocator: *const ffi::VkAllocationCallbacks,
2584 surface: *mut ffi::VkSurfaceKHR,
2585 ) -> ffi::VkResult {
2586 unsafe { ffi::glfwCreateWindowSurface(instance, self.ptr, allocator, surface) }
2587 }
2588
2589 pub fn create_shared(
2593 &self,
2594 width: u32,
2595 height: u32,
2596 title: &str,
2597 mode: WindowMode<'_>,
2598 ) -> Option<(PWindow, GlfwReceiver<(f64, WindowEvent)>)> {
2599 self.glfw
2600 .create_window_intern(width, height, title, mode, Some(self))
2601 }
2602
2603 pub fn close(self) {}
2606
2607 pub fn render_context(&mut self) -> PRenderContext {
2610 PRenderContext(Box::new(RenderContext {
2611 ptr: self.ptr,
2612 glfw: self.glfw.clone(),
2613 drop_sender: self.drop_sender.as_ref().unwrap().clone(),
2615 }))
2616 }
2617
2618 pub fn should_close(&self) -> bool {
2620 unsafe { ffi::glfwWindowShouldClose(self.ptr) == ffi::GLFW_TRUE }
2621 }
2622
2623 pub fn set_should_close(&mut self, value: bool) {
2625 unsafe { ffi::glfwSetWindowShouldClose(self.ptr, value as c_int) }
2626 }
2627
2628 pub fn set_title(&mut self, title: &str) {
2632 unsafe {
2633 with_c_str(title, |title| {
2634 ffi::glfwSetWindowTitle(self.ptr, title);
2635 });
2636 }
2637 }
2638
2639 pub fn get_pos(&self) -> (i32, i32) {
2641 unsafe {
2642 let mut xpos = 0;
2643 let mut ypos = 0;
2644 ffi::glfwGetWindowPos(self.ptr, &mut xpos, &mut ypos);
2645 (xpos as i32, ypos as i32)
2646 }
2647 }
2648
2649 pub fn set_pos(&mut self, xpos: i32, ypos: i32) {
2651 unsafe {
2652 ffi::glfwSetWindowPos(self.ptr, xpos as c_int, ypos as c_int);
2653 }
2654 }
2655
2656 pub fn get_size(&self) -> (i32, i32) {
2658 unsafe {
2659 let mut width = 0;
2660 let mut height = 0;
2661 ffi::glfwGetWindowSize(self.ptr, &mut width, &mut height);
2662 (width as i32, height as i32)
2663 }
2664 }
2665
2666 pub fn set_size(&mut self, width: i32, height: i32) {
2668 unsafe {
2669 ffi::glfwSetWindowSize(self.ptr, width as c_int, height as c_int);
2670 }
2671 }
2672
2673 pub fn get_frame_size(&self) -> (i32, i32, i32, i32) {
2677 let (mut left, mut top, mut right, mut bottom): (i32, i32, i32, i32) = (0, 0, 0, 0);
2678
2679 unsafe {
2680 ffi::glfwGetWindowFrameSize(
2681 self.ptr,
2682 &mut left as *mut c_int,
2683 &mut top as *mut c_int,
2684 &mut right as *mut c_int,
2685 &mut bottom as *mut c_int,
2686 );
2687 }
2688
2689 (left, top, right, bottom)
2690 }
2691
2692 pub fn get_framebuffer_size(&self) -> (i32, i32) {
2694 unsafe {
2695 let mut width = 0;
2696 let mut height = 0;
2697 ffi::glfwGetFramebufferSize(self.ptr, &mut width, &mut height);
2698 (width as i32, height as i32)
2699 }
2700 }
2701
2702 pub fn set_aspect_ratio(&mut self, numer: u32, denum: u32) {
2704 unsafe { ffi::glfwSetWindowAspectRatio(self.ptr, numer as c_int, denum as c_int) }
2705 }
2706
2707 pub fn set_size_limits(
2713 &mut self,
2714 minwidth: Option<u32>,
2715 minheight: Option<u32>,
2716 maxwidth: Option<u32>,
2717 maxheight: Option<u32>,
2718 ) {
2719 unsafe {
2720 ffi::glfwSetWindowSizeLimits(
2721 self.ptr,
2722 unwrap_dont_care(minwidth),
2723 unwrap_dont_care(minheight),
2724 unwrap_dont_care(maxwidth),
2725 unwrap_dont_care(maxheight),
2726 )
2727 }
2728 }
2729
2730 pub fn iconify(&mut self) {
2732 unsafe {
2733 ffi::glfwIconifyWindow(self.ptr);
2734 }
2735 }
2736
2737 pub fn restore(&mut self) {
2739 unsafe {
2740 ffi::glfwRestoreWindow(self.ptr);
2741 }
2742 }
2743
2744 pub fn maximize(&mut self) {
2746 unsafe { ffi::glfwMaximizeWindow(self.ptr) }
2747 }
2748
2749 pub fn show(&mut self) {
2751 unsafe {
2752 ffi::glfwShowWindow(self.ptr);
2753 }
2754 }
2755
2756 pub fn hide(&mut self) {
2758 unsafe {
2759 ffi::glfwHideWindow(self.ptr);
2760 }
2761 }
2762
2763 pub fn with_window_mode<T, F>(&self, f: F) -> T
2776 where
2777 F: FnOnce(WindowMode<'_>) -> T,
2778 {
2779 let ptr = unsafe { ffi::glfwGetWindowMonitor(self.ptr) };
2780 if ptr.is_null() {
2781 f(WindowMode::Windowed)
2782 } else {
2783 f(WindowMode::FullScreen(&Monitor { ptr }))
2784 }
2785 }
2786
2787 pub fn set_monitor(
2789 &mut self,
2790 mode: WindowMode<'_>,
2791 xpos: i32,
2792 ypos: i32,
2793 width: u32,
2794 height: u32,
2795 refresh_rate: Option<u32>,
2796 ) {
2797 let monitor_ptr = if let WindowMode::FullScreen(monitor) = mode {
2798 monitor.ptr
2799 } else {
2800 ptr::null_mut()
2801 };
2802
2803 unsafe {
2804 ffi::glfwSetWindowMonitor(
2805 self.ptr,
2806 monitor_ptr,
2807 xpos as c_int,
2808 ypos as c_int,
2809 width as c_int,
2810 height as c_int,
2811 unwrap_dont_care(refresh_rate),
2812 )
2813 }
2814 }
2815
2816 pub fn focus(&mut self) {
2821 unsafe { ffi::glfwFocusWindow(self.ptr) }
2822 }
2823
2824 pub fn is_focused(&self) -> bool {
2826 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_FOCUSED) == ffi::GLFW_TRUE }
2827 }
2828
2829 pub fn is_iconified(&self) -> bool {
2831 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_ICONIFIED) == ffi::GLFW_TRUE }
2832 }
2833
2834 pub fn is_maximized(&self) -> bool {
2836 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_MAXIMIZED) == ffi::GLFW_TRUE }
2837 }
2838
2839 pub fn get_client_api(&self) -> c_int {
2841 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_CLIENT_API) }
2842 }
2843
2844 pub fn get_context_version(&self) -> Version {
2851 unsafe {
2852 Version {
2853 major: ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_CONTEXT_VERSION_MAJOR) as u64,
2854 minor: ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_CONTEXT_VERSION_MINOR) as u64,
2855 patch: ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_CONTEXT_REVISION) as u64,
2856 }
2857 }
2858 }
2859
2860 pub fn get_context_robustness(&self) -> c_int {
2862 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_CONTEXT_ROBUSTNESS) }
2863 }
2864
2865 pub fn is_opengl_forward_compat(&self) -> bool {
2867 unsafe {
2868 ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_OPENGL_FORWARD_COMPAT) == ffi::GLFW_TRUE
2869 }
2870 }
2871
2872 pub fn is_opengl_debug_context(&self) -> bool {
2874 unsafe {
2875 ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_OPENGL_DEBUG_CONTEXT) == ffi::GLFW_TRUE
2876 }
2877 }
2878
2879 pub fn get_opengl_profile(&self) -> c_int {
2881 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_OPENGL_PROFILE) }
2882 }
2883
2884 pub fn is_resizable(&self) -> bool {
2886 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_RESIZABLE) == ffi::GLFW_TRUE }
2887 }
2888
2889 pub fn set_resizable(&mut self, resizable: bool) {
2891 unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::GLFW_RESIZABLE, resizable as c_int) }
2892 }
2893
2894 pub fn is_visible(&self) -> bool {
2896 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_VISIBLE) == ffi::GLFW_TRUE }
2897 }
2898
2899 pub fn is_decorated(&self) -> bool {
2901 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_DECORATED) == ffi::GLFW_TRUE }
2902 }
2903
2904 pub fn set_decorated(&mut self, decorated: bool) {
2906 unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::GLFW_DECORATED, decorated as c_int) }
2907 }
2908
2909 pub fn is_auto_iconify(&self) -> bool {
2911 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_AUTO_ICONIFY) == ffi::GLFW_TRUE }
2912 }
2913
2914 pub fn set_auto_iconify(&mut self, auto_iconify: bool) {
2916 unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::GLFW_AUTO_ICONIFY, auto_iconify as c_int) }
2917 }
2918
2919 pub fn is_floating(&self) -> bool {
2921 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_FLOATING) == ffi::GLFW_TRUE }
2922 }
2923
2924 pub fn set_floating(&mut self, floating: bool) {
2926 unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::GLFW_FLOATING, floating as c_int) }
2927 }
2928
2929 pub fn is_framebuffer_transparent(&self) -> bool {
2931 unsafe {
2932 ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_TRANSPARENT_FRAMEBUFFER) == ffi::GLFW_TRUE
2933 }
2934 }
2935
2936 pub fn is_mouse_passthrough(&self) -> bool {
2938 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_MOUSE_PASSTHROUGH) == ffi::GLFW_TRUE }
2939 }
2940
2941 pub fn set_mouse_passthrough(&mut self, passthrough: bool) {
2943 unsafe {
2944 ffi::glfwSetWindowAttrib(self.ptr, ffi::GLFW_MOUSE_PASSTHROUGH, passthrough as c_int);
2945 }
2946 }
2947
2948 pub fn is_focus_on_show(&self) -> bool {
2950 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_FOCUS_ON_SHOW) == ffi::GLFW_TRUE }
2951 }
2952
2953 pub fn set_focus_on_show(&mut self, focus_on_show: bool) {
2955 unsafe {
2956 ffi::glfwSetWindowAttrib(self.ptr, ffi::GLFW_FOCUS_ON_SHOW, focus_on_show as c_int)
2957 }
2958 }
2959
2960 pub fn is_hovered(&self) -> bool {
2962 unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::GLFW_HOVERED) == ffi::GLFW_TRUE }
2963 }
2964
2965 new_callback!(
2966 doc -> "Wrapper for `glfwSetWindowPosCallback`.",
2967 set -> set_pos_callback,
2968 unset -> unset_pos_callback,
2969 poll -> set_pos_polling,
2970 callback_field -> pos_callback,
2971 poll_field -> pos_polling,
2972 window_event -> Pos(i32, i32),
2973 glfw -> glfwSetWindowPosCallback(x: c_int, y: c_int),
2974 convert_args -> (x as i32, y as i32),
2975 secret -> _pos_callback
2976 );
2977
2978 new_callback!(
2979 doc -> "Wrapper for `glfwSetWindowSizeCallback`.",
2980 set -> set_size_callback,
2981 unset -> unset_size_callback,
2982 poll -> set_size_polling,
2983 callback_field -> size_callback,
2984 poll_field -> size_polling,
2985 window_event -> Size(i32, i32),
2986 glfw -> glfwSetWindowSizeCallback(width: c_int, height: c_int),
2987 convert_args -> (width as i32, height as i32),
2988 secret -> _size_callback
2989 );
2990
2991 new_callback!(
2992 doc -> "Wrapper for `glfwSetWindowCloseCallback`.",
2993 set -> set_close_callback,
2994 unset -> unset_close_callback,
2995 poll -> set_close_polling,
2996 callback_field -> close_callback,
2997 poll_field -> close_polling,
2998 window_event -> Close,
2999 glfw -> glfwSetWindowCloseCallback(),
3000 convert_args -> (),
3001 secret -> _close_callback
3002 );
3003
3004 new_callback!(
3005 doc -> "Wrapper for `glfwSetWindowRefreshCallback`.",
3006 set -> set_refresh_callback,
3007 unset -> unset_refresh_callback,
3008 poll -> set_refresh_polling,
3009 callback_field -> refresh_callback,
3010 poll_field -> refresh_polling,
3011 window_event -> Refresh,
3012 glfw -> glfwSetWindowRefreshCallback(),
3013 convert_args -> (),
3014 secret -> _refresh_callback
3015 );
3016
3017 new_callback!(
3018 doc -> "Wrapper for `glfwSetWindowFocusCallback`.",
3019 set -> set_focus_callback,
3020 unset -> unset_focus_callback,
3021 poll -> set_focus_polling,
3022 callback_field -> focus_callback,
3023 poll_field -> focus_polling,
3024 window_event -> Focus(bool),
3025 glfw -> glfwSetWindowFocusCallback(focused: c_int),
3026 convert_args -> (focused == ffi::GLFW_TRUE),
3027 secret -> _focus_callback
3028 );
3029
3030 new_callback!(
3031 doc -> "Wrapper for `glfwSetWindowIconifyCallback`.",
3032 set -> set_iconify_callback,
3033 unset -> unset_iconify_callback,
3034 poll -> set_iconify_polling,
3035 callback_field -> iconify_callback,
3036 poll_field -> iconify_polling,
3037 window_event -> Iconify(bool),
3038 glfw -> glfwSetWindowIconifyCallback(iconified: c_int),
3039 convert_args -> (iconified == ffi::GLFW_TRUE),
3040 secret -> _iconify_callback
3041 );
3042
3043 new_callback!(
3044 doc -> "Wrapper for `glfwSetFramebufferSizeCallback`.",
3045 set -> set_framebuffer_size_callback,
3046 unset -> unset_framebuffer_size_callback,
3047 poll -> set_framebuffer_size_polling,
3048 callback_field -> framebuffer_size_callback,
3049 poll_field -> framebuffer_size_polling,
3050 window_event -> FramebufferSize(i32, i32),
3051 glfw -> glfwSetFramebufferSizeCallback(width: c_int, height: c_int),
3052 convert_args -> (width as i32, height as i32),
3053 secret -> _framebuffer_size_callback
3054 );
3055
3056 new_callback!(
3057 doc -> "Wrapper for `glfwSetKeyCallback`.",
3058 set -> set_key_callback,
3059 unset -> unset_key_callback,
3060 poll -> set_key_polling,
3061 callback_field -> key_callback,
3062 poll_field -> key_polling,
3063 window_event -> Key(Key, Scancode, Action, Modifiers),
3064 glfw -> glfwSetKeyCallback(key: c_int, scancode: c_int, action: c_int, mods: c_int),
3065 convert_args -> (
3066 mem::transmute(key),
3067 scancode, mem::transmute(action),
3068 Modifiers::from_bits(mods).unwrap()
3069 ),
3070 secret -> _key_callback
3071 );
3072
3073 new_callback!(
3074 doc -> "Wrapper for `glfwSetCharCallback`.",
3075 set -> set_char_callback,
3076 unset -> unset_char_callback,
3077 poll -> set_char_polling,
3078 callback_field -> char_callback,
3079 poll_field -> char_polling,
3080 window_event -> Char(char),
3081 glfw -> glfwSetCharCallback(character: c_uint),
3082 convert_args -> (::std::char::from_u32(character).unwrap()),
3083 secret -> _char_callback
3084 );
3085
3086 new_callback!(
3087 doc -> "Wrapper for `glfwSetCharModsCallback`.",
3088 set -> set_char_mods_callback,
3089 unset -> unset_char_mods_callback,
3090 poll -> set_char_mods_polling,
3091 callback_field -> char_mods_callback,
3092 poll_field -> char_mods_polling,
3093 window_event -> CharModifiers(char, Modifiers),
3094 glfw -> glfwSetCharModsCallback(character: c_uint, mods: c_int),
3095 convert_args -> (
3096 ::std::char::from_u32(character).unwrap(),
3097 Modifiers::from_bits(mods).unwrap()
3098 ),
3099 secret -> _char_mods_callback
3100 );
3101
3102 new_callback!(
3103 doc -> "Wrapper for `glfwSetMouseButtonCallback`.",
3104 set -> set_mouse_button_callback,
3105 unset -> unset_mouse_button_callback,
3106 poll -> set_mouse_button_polling,
3107 callback_field -> mouse_button_callback,
3108 poll_field -> mouse_button_polling,
3109 window_event -> MouseButton(MouseButton, Action, Modifiers),
3110 glfw -> glfwSetMouseButtonCallback(button: c_int, action: c_int, mods: c_int),
3111 convert_args -> (
3112 mem::transmute(button),
3113 mem::transmute(action),
3114 Modifiers::from_bits(mods).unwrap()
3115 ),
3116 secret -> _mouse_button_callback
3117 );
3118
3119 new_callback!(
3120 doc -> "Wrapper for `glfwSetCursorPosCallback`.",
3121 set -> set_cursor_pos_callback,
3122 unset -> unset_cursor_pos_callback,
3123 poll -> set_cursor_pos_polling,
3124 callback_field -> cursor_pos_callback,
3125 poll_field -> cursor_pos_polling,
3126 window_event -> CursorPos(f64, f64),
3127 glfw -> glfwSetCursorPosCallback(x: c_double, y: c_double),
3128 convert_args -> (x as f64, y as f64),
3129 secret -> _cursor_pos_callback
3130 );
3131
3132 new_callback!(
3133 doc -> "Wrapper for `glfwSetCursorEnterCallback`.",
3134 set -> set_cursor_enter_callback,
3135 unset -> unset_cursor_enter_callback,
3136 poll -> set_cursor_enter_polling,
3137 callback_field -> cursor_enter_callback,
3138 poll_field -> cursor_enter_polling,
3139 window_event -> CursorEnter(bool),
3140 glfw -> glfwSetCursorEnterCallback(entered: c_int),
3141 convert_args -> (entered == ffi::GLFW_TRUE),
3142 secret -> _cursor_enter_callback
3143 );
3144
3145 new_callback!(
3146 doc -> "Wrapper for `glfwSetScrollCallback`.",
3147 set -> set_scroll_callback,
3148 unset -> unset_scroll_callback,
3149 poll -> set_scroll_polling,
3150 callback_field -> scroll_callback,
3151 poll_field -> scroll_polling,
3152 window_event -> Scroll(f64, f64),
3153 glfw -> glfwSetScrollCallback(x: c_double, y: c_double),
3154 convert_args -> (x as f64, y as f64),
3155 secret -> _scroll_callback
3156 );
3157
3158 new_callback!(
3159 doc -> "Wrapper for `glfwSetDropCallback`.",
3160 set -> set_drag_and_drop_callback,
3161 unset -> unset_drag_and_drop_callback,
3162 poll -> set_drag_and_drop_polling,
3163 callback_field -> drag_and_drop_callback,
3164 poll_field -> drag_and_drop_polling,
3165 window_event -> FileDrop(Vec<PathBuf>),
3166 glfw -> glfwSetDropCallback(num_paths: c_int, paths: *mut *const c_char),
3167 convert_args -> ({
3168 slice::from_raw_parts(paths, num_paths as usize)
3169 .iter()
3170 .map(|path| PathBuf::from(std::str::from_utf8({
3171 CStr::from_ptr(*path)
3172 .to_bytes()
3173 })
3174 .unwrap()
3175 .to_string()))
3176 .collect()
3177 }),
3178 secret -> _drag_and_drop_callback
3179 );
3180
3181 new_callback!(
3182 doc -> "Wrapper for `glfwSetWindowMaximizeCallback`.",
3183 set -> set_maximize_callback,
3184 unset -> unset_maximize_callback,
3185 poll -> set_maximize_polling,
3186 callback_field -> maximize_callback,
3187 poll_field -> maximize_polling,
3188 window_event -> Maximize(bool),
3189 glfw -> glfwSetWindowMaximizeCallback(maximized: c_int),
3190 convert_args -> (maximized == ffi::GLFW_TRUE),
3191 secret -> _maximize_callback
3192 );
3193
3194 new_callback!(
3195 doc -> "Wrapper for `glfwSetWindowContentScaleCallback`.",
3196 set -> set_content_scale_callback,
3197 unset -> unset_content_scale_callback,
3198 poll -> set_content_scale_polling,
3199 callback_field -> content_scale_callback,
3200 poll_field -> content_scale_polling,
3201 window_event -> ContentScale(f32, f32),
3202 glfw -> glfwSetWindowContentScaleCallback(xscale: c_float, yscale: c_float),
3203 convert_args -> (xscale as f32, yscale as f32),
3204 secret -> _content_scale_callback
3205 );
3206
3207 pub fn set_all_polling(&mut self, should_poll: bool) {
3209 self.set_pos_polling(should_poll);
3210 self.set_size_polling(should_poll);
3211 self.set_close_polling(should_poll);
3212 self.set_refresh_polling(should_poll);
3213 self.set_focus_polling(should_poll);
3214 self.set_iconify_polling(should_poll);
3215 self.set_framebuffer_size_polling(should_poll);
3216 self.set_key_polling(should_poll);
3217 self.set_char_polling(should_poll);
3218 self.set_char_mods_polling(should_poll);
3219 self.set_mouse_button_polling(should_poll);
3220 self.set_cursor_pos_polling(should_poll);
3221 self.set_cursor_enter_polling(should_poll);
3222 self.set_scroll_polling(should_poll);
3223 self.set_drag_and_drop_polling(should_poll);
3224 self.set_maximize_polling(should_poll);
3225 self.set_content_scale_polling(should_poll);
3226 }
3227
3228 pub fn get_cursor_mode(&self) -> CursorMode {
3230 unsafe { mem::transmute(ffi::glfwGetInputMode(self.ptr, ffi::GLFW_CURSOR)) }
3231 }
3232
3233 pub fn set_cursor_mode(&mut self, mode: CursorMode) {
3235 unsafe {
3236 ffi::glfwSetInputMode(self.ptr, ffi::GLFW_CURSOR, mode as c_int);
3237 }
3238 }
3239
3240 pub fn set_cursor(&mut self, cursor: Option<Cursor>) -> Option<Cursor> {
3247 let previous = mem::replace(&mut self.current_cursor, cursor);
3248
3249 unsafe {
3250 ffi::glfwSetCursor(
3251 self.ptr,
3252 match self.current_cursor {
3253 Some(ref cursor) => cursor.ptr,
3254 None => ptr::null_mut(),
3255 },
3256 )
3257 }
3258
3259 previous
3260 }
3261
3262 #[cfg(feature = "image")]
3279 pub fn set_icon(&mut self, images: Vec<image::RgbaImage>) {
3280 let image_data: Vec<(Vec<_>, u32, u32)> = images
3283 .into_iter()
3284 .map(|image| {
3285 let (width, height) = image.dimensions();
3286
3287 (image.into_vec(), width, height)
3288 })
3289 .collect();
3290
3291 let glfw_images: Vec<ffi::GLFWimage> = image_data
3292 .iter()
3293 .map(|data| ffi::GLFWimage {
3294 width: data.1 as c_int,
3295 height: data.2 as c_int,
3296 pixels: data.0.as_ptr() as _,
3297 })
3298 .collect();
3299
3300 unsafe {
3301 ffi::glfwSetWindowIcon(
3302 self.ptr,
3303 glfw_images.len() as c_int,
3304 glfw_images.as_ptr() as *const ffi::GLFWimage,
3305 )
3306 }
3307 }
3308
3309 pub fn set_icon_from_pixels(&mut self, images: Vec<PixelImage>) {
3312 let glfw_images: Vec<ffi::GLFWimage> = images
3313 .iter()
3314 .map(|image: &PixelImage| ffi::GLFWimage {
3315 width: image.width as c_int,
3316 height: image.height as c_int,
3317 pixels: image.pixels.as_ptr() as _,
3318 })
3319 .collect();
3320
3321 unsafe {
3322 ffi::glfwSetWindowIcon(
3323 self.ptr,
3324 glfw_images.len() as c_int,
3325 glfw_images.as_ptr() as *const ffi::GLFWimage,
3326 )
3327 }
3328 }
3329
3330 pub fn has_sticky_keys(&self) -> bool {
3332 unsafe { ffi::glfwGetInputMode(self.ptr, ffi::GLFW_STICKY_KEYS) == ffi::GLFW_TRUE }
3333 }
3334
3335 pub fn set_sticky_keys(&mut self, value: bool) {
3337 unsafe {
3338 ffi::glfwSetInputMode(self.ptr, ffi::GLFW_STICKY_KEYS, value as c_int);
3339 }
3340 }
3341
3342 pub fn has_sticky_mouse_buttons(&self) -> bool {
3344 unsafe { ffi::glfwGetInputMode(self.ptr, ffi::GLFW_STICKY_MOUSE_BUTTONS) == ffi::GLFW_TRUE }
3345 }
3346
3347 pub fn set_sticky_mouse_buttons(&mut self, value: bool) {
3349 unsafe {
3350 ffi::glfwSetInputMode(self.ptr, ffi::GLFW_STICKY_MOUSE_BUTTONS, value as c_int);
3351 }
3352 }
3353
3354 pub fn does_store_lock_key_mods(&self) -> bool {
3356 unsafe { ffi::glfwGetInputMode(self.ptr, ffi::GLFW_LOCK_KEY_MODS) == ffi::GLFW_TRUE }
3357 }
3358
3359 pub fn set_store_lock_key_mods(&mut self, value: bool) {
3361 unsafe { ffi::glfwSetInputMode(self.ptr, ffi::GLFW_LOCK_KEY_MODS, value as c_int) }
3362 }
3363
3364 pub fn uses_raw_mouse_motion(&self) -> bool {
3366 unsafe { ffi::glfwGetInputMode(self.ptr, ffi::GLFW_RAW_MOUSE_MOTION) == ffi::GLFW_TRUE }
3367 }
3368
3369 pub fn set_raw_mouse_motion(&mut self, value: bool) {
3371 unsafe { ffi::glfwSetInputMode(self.ptr, ffi::GLFW_RAW_MOUSE_MOTION, value as c_int) }
3372 }
3373
3374 pub fn get_key(&self, key: Key) -> Action {
3376 unsafe { mem::transmute(ffi::glfwGetKey(self.ptr, key as c_int)) }
3377 }
3378
3379 pub fn get_mouse_button(&self, button: MouseButton) -> Action {
3381 unsafe { mem::transmute(ffi::glfwGetMouseButton(self.ptr, button as c_int)) }
3382 }
3383
3384 pub fn get_cursor_pos(&self) -> (f64, f64) {
3386 unsafe {
3387 let mut xpos = 0.0;
3388 let mut ypos = 0.0;
3389 ffi::glfwGetCursorPos(self.ptr, &mut xpos, &mut ypos);
3390 (xpos as f64, ypos as f64)
3391 }
3392 }
3393
3394 pub fn set_cursor_pos(&mut self, xpos: f64, ypos: f64) {
3396 unsafe {
3397 ffi::glfwSetCursorPos(self.ptr, xpos as c_double, ypos as c_double);
3398 }
3399 }
3400
3401 pub fn set_clipboard_string(&mut self, string: &str) {
3403 unsafe {
3404 with_c_str(string, |string| {
3405 ffi::glfwSetClipboardString(self.ptr, string);
3406 });
3407 }
3408 }
3409
3410 pub fn get_clipboard_string(&self) -> Option<String> {
3412 unsafe { string_from_nullable_c_str(ffi::glfwGetClipboardString(self.ptr)) }
3413 }
3414
3415 pub fn get_opacity(&self) -> f32 {
3417 unsafe { ffi::glfwGetWindowOpacity(self.ptr) }
3418 }
3419
3420 pub fn set_opacity(&mut self, opacity: f32) {
3422 unsafe { ffi::glfwSetWindowOpacity(self.ptr, opacity) }
3423 }
3424
3425 pub fn request_attention(&mut self) {
3427 unsafe { ffi::glfwRequestWindowAttention(self.ptr) }
3428 }
3429
3430 pub fn get_content_scale(&self) -> (f32, f32) {
3432 unsafe {
3433 let mut xscale = 0.0_f32;
3434 let mut yscale = 0.0_f32;
3435 ffi::glfwGetWindowContentScale(self.ptr, &mut xscale, &mut yscale);
3436 (xscale, yscale)
3437 }
3438 }
3439
3440 #[cfg(target_os = "windows")]
3442 pub fn get_win32_window(&self) -> *mut c_void {
3443 unsafe { ffi::glfwGetWin32Window(self.ptr) }
3444 }
3445
3446 #[cfg(target_os = "windows")]
3448 pub fn get_wgl_context(&self) -> *mut c_void {
3449 unsafe { ffi::glfwGetWGLContext(self.ptr) }
3450 }
3451
3452 #[cfg(target_os = "macos")]
3454 pub fn get_cocoa_window(&self) -> *mut c_void {
3455 unsafe { ffi::glfwGetCocoaWindow(self.ptr) }
3456 }
3457
3458 #[cfg(target_os = "macos")]
3460 pub fn get_nsgl_context(&self) -> *mut c_void {
3461 unsafe { ffi::glfwGetNSGLContext(self.ptr) }
3462 }
3463
3464 #[cfg(all(not(target_os = "windows"), not(target_os = "macos"), feature = "x11"))]
3466 pub fn get_x11_window(&self) -> usize {
3467 unsafe { ffi::glfwGetX11Window(self.ptr) }
3468 }
3469
3470 #[cfg(all(
3472 not(target_os = "windows"),
3473 not(target_os = "macos"),
3474 feature = "wayland"
3475 ))]
3476 pub fn get_wayland_window(&self) -> *mut c_void {
3477 unsafe { ffi::glfwGetWaylandWindow(self.ptr) }
3478 }
3479
3480 #[cfg(all(not(target_os = "windows"), not(target_os = "macos"), feature = "x11"))]
3482 pub fn get_glx_context(&self) -> usize {
3483 unsafe { ffi::glfwGetGLXContext(self.ptr) }
3484 }
3485}
3486
3487impl Drop for Window {
3488 fn drop(&mut self) {
3494 drop(self.drop_sender.take());
3495
3496 #[cfg(feature = "log")]
3498 if self.drop_receiver.try_recv() != Err(std::sync::mpsc::TryRecvError::Disconnected) {
3499 debug!("Attempted to drop a Window before the `RenderContext` was dropped.");
3500 debug!("Blocking until the `RenderContext` was dropped.");
3501 let _ = self.drop_receiver.recv();
3502 }
3503
3504 if !self.ptr.is_null() {
3505 unsafe {
3506 let _: Box<WindowCallbacks> =
3507 mem::transmute(ffi::glfwGetWindowUserPointer(self.ptr));
3508 }
3509 }
3510
3511 if !self.is_shared {
3512 unsafe {
3513 ffi::glfwDestroyWindow(self.ptr);
3514 }
3515 }
3516 }
3517}
3518
3519#[derive(Debug)]
3520#[repr(transparent)]
3521pub struct PRenderContext(Box<RenderContext>);
3522
3523impl Deref for PRenderContext {
3524 type Target = RenderContext;
3525 fn deref(&self) -> &Self::Target {
3526 self.0.deref()
3527 }
3528}
3529
3530impl DerefMut for PRenderContext {
3531 fn deref_mut(&mut self) -> &mut Self::Target {
3532 self.0.deref_mut()
3533 }
3534}
3535
3536unsafe impl Send for PRenderContext {}
3537unsafe impl Sync for PRenderContext {}
3538
3539#[cfg(feature = "raw-window-handle-v0-6")]
3540impl HasWindowHandle for PRenderContext {
3541 fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
3542 self.0.window_handle()
3543 }
3544}
3545
3546#[cfg(feature = "raw-window-handle-v0-6")]
3547impl HasDisplayHandle for PRenderContext {
3548 fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
3549 self.0.display_handle()
3550 }
3551}
3552
3553#[derive(Debug)]
3555pub struct RenderContext {
3556 ptr: *mut ffi::GLFWwindow,
3557 glfw: Glfw,
3558 #[allow(dead_code)]
3561 drop_sender: Sender<()>,
3562}
3563
3564impl RenderContext {
3565 pub fn get_proc_address(&mut self, procname: &str) -> GLProc {
3567 if self.ptr != unsafe { ffi::glfwGetCurrentContext() } {
3568 self.make_current();
3569 }
3570
3571 self.glfw.get_proc_address_raw(procname)
3572 }
3573
3574 #[cfg(feature = "vulkan")]
3576 pub fn get_instance_proc_address(
3577 &mut self,
3578 instance: ffi::VkInstance,
3579 procname: &str,
3580 ) -> VkProc {
3581 self.glfw.get_instance_proc_address_raw(instance, procname)
3582 }
3583
3584 #[cfg(feature = "vulkan")]
3586 pub fn get_physical_device_presentation_support(
3587 &self,
3588 instance: ffi::VkInstance,
3589 device: ffi::VkPhysicalDevice,
3590 queue_family: u32,
3591 ) -> bool {
3592 self.glfw
3593 .get_physical_device_presentation_support_raw(instance, device, queue_family)
3594 }
3595
3596 #[cfg(feature = "vulkan")]
3598 pub unsafe fn create_window_surface(
3599 &self,
3600 instance: ffi::VkInstance,
3601 allocator: *const ffi::VkAllocationCallbacks,
3602 surface: *mut ffi::VkSurfaceKHR,
3603 ) -> ffi::VkResult {
3604 unsafe { ffi::glfwCreateWindowSurface(instance, self.ptr, allocator, surface) }
3605 }
3606}
3607
3608unsafe impl Send for RenderContext {}
3609
3610pub trait Context {
3612 fn window_ptr(&self) -> *mut ffi::GLFWwindow;
3614
3615 fn window_id(&self) -> WindowId {
3617 self.window_ptr() as WindowId
3618 }
3619
3620 fn swap_buffers(&mut self) {
3626 let ptr = self.window_ptr();
3627 unsafe {
3628 ffi::glfwSwapBuffers(ptr);
3629 }
3630 }
3631
3632 fn is_current(&self) -> bool {
3634 self.window_ptr() == unsafe { ffi::glfwGetCurrentContext() }
3635 }
3636
3637 fn make_current(&mut self) {
3639 let ptr = self.window_ptr();
3640 unsafe {
3641 ffi::glfwMakeContextCurrent(ptr);
3642 }
3643 }
3644
3645 fn should_close(&self) -> bool {
3647 let ptr = self.window_ptr();
3648 unsafe { ffi::glfwWindowShouldClose(ptr) == ffi::GLFW_TRUE }
3649 }
3650
3651 fn set_should_close(&mut self, value: bool) {
3653 let ptr = self.window_ptr();
3654 unsafe {
3655 ffi::glfwSetWindowShouldClose(ptr, value as c_int);
3656 }
3657 }
3658
3659 fn post_empty_event(&self) {
3661 unsafe { ffi::glfwPostEmptyEvent() }
3662 }
3663}
3664
3665impl Context for Window {
3666 fn window_ptr(&self) -> *mut ffi::GLFWwindow {
3667 self.ptr
3668 }
3669}
3670
3671impl Context for RenderContext {
3672 fn window_ptr(&self) -> *mut ffi::GLFWwindow {
3673 self.ptr
3674 }
3675}
3676
3677#[cfg(feature = "raw-window-handle-v0-6")]
3678impl HasWindowHandle for Window {
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 HasWindowHandle for RenderContext {
3686 fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
3687 Ok(unsafe { WindowHandle::borrow_raw(raw_window_handle(self)) })
3688 }
3689}
3690
3691#[cfg(feature = "raw-window-handle-v0-6")]
3692impl HasDisplayHandle for Window {
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-6")]
3699impl HasDisplayHandle for RenderContext {
3700 fn display_handle(&'_ self) -> Result<DisplayHandle<'_>, HandleError> {
3701 Ok(unsafe { DisplayHandle::borrow_raw(raw_display_handle()) })
3702 }
3703}
3704
3705#[cfg(feature = "raw-window-handle-v0-5")]
3706unsafe impl HasRawWindowHandle for Window {
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 HasRawWindowHandle for RenderContext {
3714 fn raw_window_handle(&self) -> RawWindowHandle {
3715 raw_window_handle(self)
3716 }
3717}
3718
3719#[cfg(feature = "raw-window-handle-v0-5")]
3720unsafe impl HasRawDisplayHandle for Window {
3721 fn raw_display_handle(&self) -> RawDisplayHandle {
3722 raw_display_handle()
3723 }
3724}
3725
3726#[cfg(feature = "raw-window-handle-v0-5")]
3727unsafe impl HasRawDisplayHandle for RenderContext {
3728 fn raw_display_handle(&self) -> RawDisplayHandle {
3729 raw_display_handle()
3730 }
3731}
3732
3733#[cfg(feature = "raw-window-handle-v0-6")]
3734fn raw_window_handle<C: Context>(context: &C) -> RawWindowHandle {
3735 #[cfg(target_family = "windows")]
3736 {
3737 use std::num::NonZeroIsize;
3738
3739 use raw_window_handle::Win32WindowHandle;
3740 let (hwnd, hinstance): (*mut std::ffi::c_void, *mut std::ffi::c_void) = unsafe {
3741 let hwnd = ffi::glfwGetWin32Window(context.window_ptr());
3742 let hinstance: *mut c_void =
3743 winapi::um::libloaderapi::GetModuleHandleW(std::ptr::null()) as _;
3744 (hwnd, hinstance as _)
3745 };
3746 let mut handle = Win32WindowHandle::new(NonZeroIsize::new(hwnd as isize).unwrap());
3747 handle.hinstance = NonZeroIsize::new(hinstance as isize);
3748 RawWindowHandle::Win32(handle)
3749 }
3750 #[cfg(all(
3751 any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3752 not(feature = "wayland")
3753 ))]
3754 {
3755 use raw_window_handle::XlibWindowHandle;
3756 let window =
3757 unsafe { ffi::glfwGetX11Window(context.window_ptr()) as std::os::raw::c_ulong };
3758 RawWindowHandle::Xlib(XlibWindowHandle::new(window))
3759 }
3760 #[cfg(all(
3761 any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3762 feature = "wayland"
3763 ))]
3764 {
3765 use std::ptr::NonNull;
3766
3767 use raw_window_handle::WaylandWindowHandle;
3768 let surface = unsafe { ffi::glfwGetWaylandWindow(context.window_ptr()) };
3769 let handle = WaylandWindowHandle::new(
3770 NonNull::new(surface).expect("wayland window surface is null"),
3771 );
3772 RawWindowHandle::Wayland(handle)
3773 }
3774 #[cfg(target_os = "macos")]
3775 {
3776 use std::ptr::NonNull;
3777
3778 use objc2::msg_send_id;
3779 use objc2::rc::Id;
3780 use objc2::runtime::NSObject;
3781 use raw_window_handle::AppKitWindowHandle;
3782 let ns_window: *mut NSObject =
3783 unsafe { ffi::glfwGetCocoaWindow(context.window_ptr()) as *mut _ };
3784 let ns_view: Option<Id<NSObject>> = unsafe { msg_send_id![ns_window, contentView] };
3785 let ns_view = ns_view.expect("failed to access contentView on GLFW NSWindow");
3786 let ns_view: NonNull<NSObject> = NonNull::from(&*ns_view);
3787 let handle = AppKitWindowHandle::new(ns_view.cast());
3788 RawWindowHandle::AppKit(handle)
3789 }
3790 #[cfg(target_os = "emscripten")]
3791 {
3792 let _ = context; let mut wh = raw_window_handle::WebWindowHandle::new(1);
3794 RawWindowHandle::Web(wh)
3798 }
3799}
3800
3801#[cfg(feature = "raw-window-handle-v0-6")]
3802fn raw_display_handle() -> RawDisplayHandle {
3803 #[cfg(target_family = "windows")]
3804 {
3805 use raw_window_handle::WindowsDisplayHandle;
3806 RawDisplayHandle::Windows(WindowsDisplayHandle::new())
3807 }
3808 #[cfg(all(
3809 any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3810 not(feature = "wayland")
3811 ))]
3812 {
3813 use std::ptr::NonNull;
3814
3815 use raw_window_handle::XlibDisplayHandle;
3816 let display = NonNull::new(unsafe { ffi::glfwGetX11Display() });
3817 let handle = XlibDisplayHandle::new(display, 0);
3818 RawDisplayHandle::Xlib(handle)
3819 }
3820 #[cfg(all(
3821 any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3822 feature = "wayland"
3823 ))]
3824 {
3825 use std::ptr::NonNull;
3826
3827 use raw_window_handle::WaylandDisplayHandle;
3828 let display = NonNull::new(unsafe { ffi::glfwGetWaylandDisplay().cast_mut() })
3829 .expect("wayland display is null");
3830 let handle = WaylandDisplayHandle::new(display);
3831 RawDisplayHandle::Wayland(handle)
3832 }
3833 #[cfg(target_os = "macos")]
3834 {
3835 use raw_window_handle::AppKitDisplayHandle;
3836 RawDisplayHandle::AppKit(AppKitDisplayHandle::new())
3837 }
3838 #[cfg(target_os = "emscripten")]
3839 {
3840 RawDisplayHandle::Web(raw_window_handle::WebDisplayHandle::new())
3841 }
3842}
3843
3844#[cfg(feature = "raw-window-handle-v0-5")]
3845fn raw_window_handle<C: Context>(context: &C) -> RawWindowHandle {
3846 #[cfg(target_family = "windows")]
3847 {
3848 use raw_window_handle::Win32WindowHandle;
3849 let (hwnd, hinstance) = unsafe {
3850 let hwnd = ffi::glfwGetWin32Window(context.window_ptr());
3851 let hinstance = winapi::um::libloaderapi::GetModuleHandleW(std::ptr::null());
3852 (hwnd, hinstance as _)
3853 };
3854 let mut handle = Win32WindowHandle::empty();
3855 handle.hwnd = hwnd;
3856 handle.hinstance = hinstance;
3857 RawWindowHandle::Win32(handle)
3858 }
3859 #[cfg(all(
3860 any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3861 not(feature = "wayland")
3862 ))]
3863 {
3864 use raw_window_handle::XlibWindowHandle;
3865 let mut handle = XlibWindowHandle::empty();
3866 handle.window =
3867 unsafe { ffi::glfwGetX11Window(context.window_ptr()) as std::os::raw::c_ulong };
3868 RawWindowHandle::Xlib(handle)
3869 }
3870 #[cfg(all(
3871 any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3872 feature = "wayland"
3873 ))]
3874 {
3875 use raw_window_handle::WaylandWindowHandle;
3876 let mut handle = WaylandWindowHandle::empty();
3877 handle.surface = unsafe { ffi::glfwGetWaylandWindow(context.window_ptr()) };
3878 RawWindowHandle::Wayland(handle)
3879 }
3880 #[cfg(target_os = "macos")]
3881 {
3882 use raw_window_handle::AppKitWindowHandle;
3883 let (ns_window, ns_view) = unsafe {
3884 let ns_window: *mut objc::runtime::Object =
3885 ffi::glfwGetCocoaWindow(context.window_ptr()) as *mut _;
3886 let ns_view: *mut objc::runtime::Object = objc::msg_send![ns_window, contentView];
3887 assert_ne!(ns_view, std::ptr::null_mut());
3888 (
3889 ns_window as *mut std::ffi::c_void,
3890 ns_view as *mut std::ffi::c_void,
3891 )
3892 };
3893 let mut handle = AppKitWindowHandle::empty();
3894 handle.ns_window = ns_window;
3895 handle.ns_view = ns_view;
3896 RawWindowHandle::AppKit(handle)
3897 }
3898 #[cfg(target_os = "emscripten")]
3899 {
3900 let _ = context; let mut wh = raw_window_handle::WebWindowHandle::empty();
3902 wh.id = 1;
3906 RawWindowHandle::Web(wh)
3907 }
3908}
3909
3910#[cfg(feature = "raw-window-handle-v0-5")]
3911fn raw_display_handle() -> RawDisplayHandle {
3912 #[cfg(target_family = "windows")]
3913 {
3914 use raw_window_handle::WindowsDisplayHandle;
3915 RawDisplayHandle::Windows(WindowsDisplayHandle::empty())
3916 }
3917 #[cfg(all(
3918 any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3919 not(feature = "wayland")
3920 ))]
3921 {
3922 use raw_window_handle::XlibDisplayHandle;
3923 let mut handle = XlibDisplayHandle::empty();
3924 handle.display = unsafe { ffi::glfwGetX11Display() };
3925 RawDisplayHandle::Xlib(handle)
3926 }
3927 #[cfg(all(
3928 any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3929 feature = "wayland"
3930 ))]
3931 {
3932 use raw_window_handle::WaylandDisplayHandle;
3933 let mut handle = WaylandDisplayHandle::empty();
3934 handle.display = unsafe { ffi::glfwGetWaylandDisplay() };
3935 RawDisplayHandle::Wayland(handle)
3936 }
3937 #[cfg(target_os = "macos")]
3938 {
3939 use raw_window_handle::AppKitDisplayHandle;
3940 RawDisplayHandle::AppKit(AppKitDisplayHandle::empty())
3941 }
3942 #[cfg(target_os = "emscripten")]
3943 {
3944 RawDisplayHandle::Web(raw_window_handle::WebDisplayHandle::empty())
3945 }
3946}
3947
3948pub fn make_context_current(context: Option<&dyn Context>) {
3950 match context {
3951 Some(ctx) => unsafe { ffi::glfwMakeContextCurrent(ctx.window_ptr()) },
3952 None => unsafe { ffi::glfwMakeContextCurrent(ptr::null_mut()) },
3953 }
3954}
3955
3956#[repr(i32)]
3958#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
3959#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3960pub enum JoystickId {
3961 Joystick1 = ffi::GLFW_JOYSTICK_1,
3962 Joystick2 = ffi::GLFW_JOYSTICK_2,
3963 Joystick3 = ffi::GLFW_JOYSTICK_3,
3964 Joystick4 = ffi::GLFW_JOYSTICK_4,
3965 Joystick5 = ffi::GLFW_JOYSTICK_5,
3966 Joystick6 = ffi::GLFW_JOYSTICK_6,
3967 Joystick7 = ffi::GLFW_JOYSTICK_7,
3968 Joystick8 = ffi::GLFW_JOYSTICK_8,
3969 Joystick9 = ffi::GLFW_JOYSTICK_9,
3970 Joystick10 = ffi::GLFW_JOYSTICK_10,
3971 Joystick11 = ffi::GLFW_JOYSTICK_11,
3972 Joystick12 = ffi::GLFW_JOYSTICK_12,
3973 Joystick13 = ffi::GLFW_JOYSTICK_13,
3974 Joystick14 = ffi::GLFW_JOYSTICK_14,
3975 Joystick15 = ffi::GLFW_JOYSTICK_15,
3976 Joystick16 = ffi::GLFW_JOYSTICK_16,
3977}
3978
3979impl JoystickId {
3980 pub fn from_i32(n: i32) -> Option<JoystickId> {
3982 if (0..=ffi::GLFW_JOYSTICK_LAST).contains(&n) {
3983 Some(unsafe { mem::transmute(n) })
3984 } else {
3985 None
3986 }
3987 }
3988}
3989
3990#[repr(i32)]
3992#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
3993#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3994pub enum GamepadButton {
3995 ButtonA = ffi::GLFW_GAMEPAD_BUTTON_A,
3996 ButtonB = ffi::GLFW_GAMEPAD_BUTTON_B,
3997 ButtonX = ffi::GLFW_GAMEPAD_BUTTON_X,
3998 ButtonY = ffi::GLFW_GAMEPAD_BUTTON_Y,
3999 ButtonLeftBumper = ffi::GLFW_GAMEPAD_BUTTON_LEFT_BUMPER,
4000 ButtonRightBumper = ffi::GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER,
4001 ButtonBack = ffi::GLFW_GAMEPAD_BUTTON_BACK,
4002 ButtonStart = ffi::GLFW_GAMEPAD_BUTTON_START,
4003 ButtonGuide = ffi::GLFW_GAMEPAD_BUTTON_GUIDE,
4004 ButtonLeftThumb = ffi::GLFW_GAMEPAD_BUTTON_LEFT_THUMB,
4005 ButtonRightThumb = ffi::GLFW_GAMEPAD_BUTTON_RIGHT_THUMB,
4006 ButtonDpadUp = ffi::GLFW_GAMEPAD_BUTTON_DPAD_UP,
4007 ButtonDpadRight = ffi::GLFW_GAMEPAD_BUTTON_DPAD_RIGHT,
4008 ButtonDpadDown = ffi::GLFW_GAMEPAD_BUTTON_DPAD_DOWN,
4009 ButtonDpadLeft = ffi::GLFW_GAMEPAD_BUTTON_DPAD_LEFT,
4010}
4011
4012impl GamepadButton {
4013 pub fn from_i32(n: i32) -> Option<GamepadButton> {
4015 if (0..=ffi::GLFW_GAMEPAD_BUTTON_LAST).contains(&n) {
4016 Some(unsafe { mem::transmute(n) })
4017 } else {
4018 None
4019 }
4020 }
4021}
4022
4023#[repr(i32)]
4025#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
4026#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4027pub enum GamepadAxis {
4028 AxisLeftX = ffi::GLFW_GAMEPAD_AXIS_LEFT_X,
4029 AxisLeftY = ffi::GLFW_GAMEPAD_AXIS_LEFT_Y,
4030 AxisRightX = ffi::GLFW_GAMEPAD_AXIS_RIGHT_X,
4031 AxisRightY = ffi::GLFW_GAMEPAD_AXIS_RIGHT_Y,
4032 AxisLeftTrigger = ffi::GLFW_GAMEPAD_AXIS_LEFT_TRIGGER,
4033 AxisRightTrigger = ffi::GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER,
4034}
4035
4036impl GamepadAxis {
4037 pub fn from_i32(n: i32) -> Option<GamepadAxis> {
4039 if (0..=ffi::GLFW_GAMEPAD_AXIS_LAST).contains(&n) {
4040 Some(unsafe { mem::transmute(n) })
4041 } else {
4042 None
4043 }
4044 }
4045}
4046
4047bitflags! {
4048 #[doc = "Joystick hats."]
4049 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4050 pub struct JoystickHats: ::std::os::raw::c_int {
4051 const Centered = crate::ffi::GLFW_HAT_CENTERED;
4052 const Up = crate::ffi::GLFW_HAT_UP;
4053 const Right = crate::ffi::GLFW_HAT_RIGHT;
4054 const Down = crate::ffi::GLFW_HAT_DOWN;
4055 const Left = crate::ffi::GLFW_HAT_LEFT;
4056 }
4057}
4058
4059#[derive(Clone, Debug)]
4061pub struct Joystick {
4062 pub id: JoystickId,
4063 pub glfw: Glfw,
4064}
4065
4066#[derive(Copy, Clone, Debug)]
4068#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4069pub struct GamepadState {
4070 buttons: [Action; (ffi::GLFW_GAMEPAD_BUTTON_LAST + 1) as usize],
4071 axes: [f32; (ffi::GLFW_GAMEPAD_AXIS_LAST + 1) as usize],
4072}
4073
4074#[repr(i32)]
4076#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
4077#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4078pub enum JoystickEvent {
4079 Connected = ffi::GLFW_CONNECTED,
4080 Disconnected = ffi::GLFW_DISCONNECTED,
4081}
4082
4083impl Joystick {
4084 pub fn is_present(&self) -> bool {
4086 unsafe { ffi::glfwJoystickPresent(self.id as c_int) == ffi::GLFW_TRUE }
4087 }
4088
4089 pub fn get_axes(&self) -> Vec<f32> {
4091 unsafe {
4092 let mut count = 0;
4093 let ptr = ffi::glfwGetJoystickAxes(self.id as c_int, &mut count);
4094 if ptr.is_null() {
4095 return Vec::new();
4096 }
4097 slice::from_raw_parts(ptr, count as usize)
4098 .iter()
4099 .map(|&a| a as f32)
4100 .collect()
4101 }
4102 }
4103
4104 pub fn get_buttons(&self) -> Vec<c_int> {
4106 unsafe {
4107 let mut count = 0;
4108 let ptr = ffi::glfwGetJoystickButtons(self.id as c_int, &mut count);
4109 if ptr.is_null() {
4110 return Vec::new();
4111 }
4112 slice::from_raw_parts(ptr, count as usize)
4113 .iter()
4114 .map(|&b| b as c_int)
4115 .collect()
4116 }
4117 }
4118
4119 pub fn get_hats(&self) -> Vec<JoystickHats> {
4121 unsafe {
4122 let mut count = 0;
4123 let ptr = ffi::glfwGetJoystickHats(self.id as c_int, &mut count);
4124 if ptr.is_null() {
4125 return Vec::new();
4126 }
4127 slice::from_raw_parts(ptr, count as usize)
4128 .iter()
4129 .map(|&b| mem::transmute(b as c_int))
4130 .collect()
4131 }
4132 }
4133
4134 pub fn get_name(&self) -> Option<String> {
4136 unsafe { string_from_nullable_c_str(ffi::glfwGetJoystickName(self.id as c_int)) }
4137 }
4138
4139 pub fn get_guid(&self) -> Option<String> {
4141 unsafe { string_from_nullable_c_str(ffi::glfwGetJoystickGUID(self.id as c_int)) }
4142 }
4143
4144 pub fn is_gamepad(&self) -> bool {
4146 unsafe { ffi::glfwJoystickIsGamepad(self.id as c_int) == ffi::GLFW_TRUE }
4147 }
4148
4149 pub fn get_gamepad_name(&self) -> Option<String> {
4151 unsafe { string_from_nullable_c_str(ffi::glfwGetGamepadName(self.id as c_int)) }
4152 }
4153
4154 pub fn get_gamepad_state(&self) -> Option<GamepadState> {
4156 unsafe {
4157 let mut state = ffi::GLFWgamepadstate {
4158 buttons: [0; (ffi::GLFW_GAMEPAD_BUTTON_LAST + 1) as usize],
4159 axes: [0_f32; (ffi::GLFW_GAMEPAD_AXIS_LAST + 1) as usize],
4160 };
4161 if ffi::glfwGetGamepadState(self.id as c_int, &mut state) == ffi::GLFW_TRUE {
4162 Some(state.into())
4163 } else {
4164 None
4165 }
4166 }
4167 }
4168}
4169
4170impl From<ffi::GLFWgamepadstate> for GamepadState {
4171 fn from(state: ffi::GLFWgamepadstate) -> Self {
4172 let mut buttons = [Action::Release; (ffi::GLFW_GAMEPAD_BUTTON_LAST + 1) as usize];
4173 let mut axes = [0_f32; (ffi::GLFW_GAMEPAD_AXIS_LAST + 1) as usize];
4174 unsafe {
4175 state
4176 .buttons
4177 .iter()
4178 .map(|&b| mem::transmute(b as c_int))
4179 .zip(buttons.iter_mut())
4180 .for_each(|(a, b)| *b = a);
4181 }
4182 state
4183 .axes
4184 .iter()
4185 .map(|&f| f as f32)
4186 .zip(axes.iter_mut())
4187 .for_each(|(a, b)| *b = a);
4188 Self { buttons, axes }
4189 }
4190}
4191
4192impl GamepadState {
4193 pub fn get_button_state(&self, button: GamepadButton) -> Action {
4194 self.buttons[button as usize]
4195 }
4196
4197 pub fn get_axis(&self, axis: GamepadAxis) -> f32 {
4198 self.axes[axis as usize]
4199 }
4200}
4201
4202#[inline(always)]
4203fn unwrap_dont_care(value: Option<u32>) -> c_int {
4204 match value {
4205 Some(v) => v as c_int,
4206 None => ffi::GLFW_DONT_CARE,
4207 }
4208}