[go: up one dir, main page]

glfw/
lib.rs

1// Copyright 2013-2016 The GLFW-RS Developers. For a full listing of the authors,
2// refer to the AUTHORS file at the top-level directory of this distribution.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16#![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
33//! An idiomatic wrapper for the GLFW library.
34//!
35//! # Example
36//!
37//! ~~~no_run
38//! extern crate glfw;
39//!
40//! use glfw::{Action, Context, Key};
41//!
42//! fn main() {
43//!    use glfw::fail_on_errors;
44//! let mut glfw = glfw::init(fail_on_errors!()).unwrap();
45//!
46//!     // Create a windowed mode window and its OpenGL context
47//!     let (mut window, events) = glfw.create_window(300, 300, "Hello this is window",
48//! glfw::WindowMode::Windowed)         .expect("Failed to create GLFW window.");
49//!
50//!     // Make the window's context current
51//!     window.make_current();
52//!     window.set_key_polling(true);
53//!
54//!     // Loop until the user closes the window
55//!     while !window.should_close() {
56//!         // Swap front and back buffers
57//!         window.swap_buffers();
58//!
59//!         // Poll for and process events
60//!         glfw.poll_events();
61//!         for (_, event) in glfw::flush_messages(&events) {
62//!             println!("{:?}", event);
63//!             match event {
64//!                 glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
65//!                     window.set_should_close(true)
66//!                 },
67//!                 _ => {},
68//!             }
69//!         }
70//!     }
71//! }
72//! ~~~
73//!
74//! # Cargo Features
75//!
76//! Use the `vulkan` feature flag to enable all Vulkan functions and types.
77//!
78//! Use the `image` feature flag to enable use of the [`image`](https://github.com/PistonDevelopers/image) library for cursors and icons.
79//!
80//! Use the `all` feature flag to enable both at the same time.
81
82// TODO: Document differences between GLFW and glfw-rs
83
84macro_rules! make_user_callback_functions {
85    (
86        doc -> $doc:literal,
87        set -> $set:ident,
88        unset -> $unset:ident,
89        poll -> $poll:ident,
90        callback_field -> $callback_field:ident,
91        poll_field -> $poll_field:ident,
92        glfw -> $glfw:ident,
93        args -> ($($args:ty),*),
94        secret -> $secret:ident
95    ) => {
96
97        #[doc = $doc]
98        pub fn $set<T>(&mut self, callback: T)
99        where T: FnMut(&mut Window, $($args),*) + 'static {
100            unsafe {
101                let callbacks = WindowCallbacks::get_callbacks(self.ptr);
102                callbacks.$callback_field = Some(Box::new(callback));
103                ffi::$glfw(self.ptr, Some(Self::$secret));
104            }
105        }
106
107        #[doc = $doc]
108        pub fn $unset(&mut self) {
109            unsafe {
110                let callbacks = WindowCallbacks::get_callbacks(self.ptr);
111                callbacks.$callback_field = None;
112
113                // We're removing the callback, if theres no polling either, set to null
114                if !callbacks.$poll_field {
115                    ffi::$glfw(self.ptr, None);
116                }
117            }
118        }
119
120        #[doc = $doc]
121        pub fn $poll(&mut self, should_poll: bool) {
122            unsafe {
123                let callbacks = WindowCallbacks::get_callbacks(self.ptr);
124                callbacks.$poll_field = should_poll;
125
126                // If no polling and not custom callback, set glfw callback to null
127                if should_poll {
128                    ffi::$glfw(self.ptr, Some(Self::$secret));
129                } else if callbacks.$callback_field.is_none() {
130                    ffi::$glfw(self.ptr, None);
131                }
132            }
133        }
134    }
135}
136
137macro_rules! new_callback {
138    (
139        doc -> $doc:literal,
140        set -> $set:ident,
141        unset -> $unset:ident,
142        poll -> $poll:ident,
143        callback_field -> $callback_field:ident,
144        poll_field -> $poll_field:ident,
145        window_event -> $window_event:ident ($($args:ty),+),
146        glfw -> $glfw:ident ($($glfw_arg_names:ident: $glfw_args:ty),*),
147        convert_args -> ($($convert_args:expr),*),
148        secret -> $secret:ident
149    ) => {
150
151        #[allow(unused_unsafe)]
152        extern "C" fn $secret(glfw_window: *mut GLFWwindow, $($glfw_arg_names: $glfw_args),*) {
153            unsafe {
154                let callbacks = WindowCallbacks::get_callbacks(glfw_window);
155                let window = &mut *callbacks.window_ptr;
156                if let Some(func) = &mut callbacks.$callback_field {
157                    func(window, $($convert_args),*);
158                }
159                if callbacks.$poll_field {
160                    let event = (ffi::glfwGetTime() as f64, WindowEvent::$window_event($($convert_args),*));
161                    if let Some(event) = callbacks::unbuffered::handle(glfw_window as WindowId, event) {
162                        callbacks.sender.send(event);
163                    }
164                }
165            }
166        }
167
168        make_user_callback_functions!(
169            doc -> $doc,
170            set -> $set,
171            unset -> $unset,
172            poll -> $poll,
173            callback_field -> $callback_field,
174            poll_field -> $poll_field,
175            glfw -> $glfw,
176            args -> ($($args),*),
177            secret -> $secret
178        );
179    };
180    (
181        doc -> $doc:literal,
182        set -> $set:ident,
183        unset -> $unset:ident,
184        poll -> $poll:ident,
185        callback_field -> $callback_field:ident,
186        poll_field -> $poll_field:ident,
187        window_event -> $window_event:ident,
188        glfw -> $glfw:ident ($($glfw_arg_names:ident: $glfw_args:ty),*),
189        convert_args -> ($($convert_args:expr),*),
190        secret -> $secret:ident
191    ) => {
192
193        #[allow(unused_unsafe)]
194        extern "C" fn $secret(glfw_window: *mut GLFWwindow, $($glfw_arg_names: $glfw_args),*) {
195            unsafe {
196                let callbacks = WindowCallbacks::get_callbacks(glfw_window);
197                let window = &mut *callbacks.window_ptr;
198                if let Some(func) = &mut callbacks.$callback_field {
199                    func(window);
200                }
201                if callbacks.$poll_field {
202                    let event = (ffi::glfwGetTime() as f64, WindowEvent::$window_event);
203                    if let Some(event) = callbacks::unbuffered::handle(glfw_window as WindowId, event) {
204                        callbacks.sender.send(event);
205                    }
206                }
207            }
208        }
209
210        make_user_callback_functions!(
211            doc -> $doc,
212            set -> $set,
213            unset -> $unset,
214            poll -> $poll,
215            callback_field -> $callback_field,
216            poll_field -> $poll_field,
217            glfw -> $glfw,
218            args -> (),
219            secret -> $secret
220        );
221    }
222}
223
224#[cfg(feature = "log")]
225#[macro_use]
226extern crate log;
227#[macro_use]
228extern crate bitflags;
229#[cfg(feature = "image")]
230extern crate image;
231
232#[cfg(feature = "raw-window-handle-v0-6")]
233extern crate raw_window_handle_0_6 as raw_window_handle;
234
235#[cfg(feature = "raw-window-handle-v0-5")]
236extern crate raw_window_handle_0_5 as raw_window_handle;
237
238use std::collections::VecDeque;
239#[allow(unused)]
240use std::ffi::*;
241use std::ffi::{CStr, CString};
242use std::marker::Send;
243use std::ops::{Deref, DerefMut};
244#[cfg(feature = "vulkan")]
245use std::os::raw::c_uint;
246#[cfg(not(target_os = "emscripten"))]
247use std::os::raw::c_void;
248use std::os::raw::{c_char, c_double, c_float, c_int, c_uchar, c_ushort};
249use std::path::PathBuf;
250use std::ptr::{null, null_mut};
251use std::sync::atomic::{AtomicUsize, Ordering};
252use std::sync::mpsc::{channel, Receiver, Sender};
253use std::sync::{Arc, Mutex};
254use std::{error, fmt, mem, ptr, slice};
255
256#[cfg(feature = "vulkan")]
257use ash::vk;
258#[cfg(feature = "raw-window-handle-v0-6")]
259use raw_window_handle::{
260    DisplayHandle, HandleError, HasDisplayHandle, HasWindowHandle, WindowHandle,
261};
262#[cfg(feature = "raw-window-handle-v0-5")]
263use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
264use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
265#[cfg(feature = "serde")]
266use serde::{Deserialize, Serialize};
267
268/// Alias to `MouseButton1`, supplied for improved clarity.
269pub use self::MouseButton::Button1 as MouseButtonLeft;
270/// Alias to `MouseButton2`, supplied for improved clarity.
271pub use self::MouseButton::Button2 as MouseButtonRight;
272/// Alias to `MouseButton3`, supplied for improved clarity.
273pub use self::MouseButton::Button3 as MouseButtonMiddle;
274use crate::ffi::GLFWwindow;
275
276mod callbacks;
277pub mod ffi;
278
279#[derive(Debug)]
280#[repr(transparent)]
281pub struct PWindow(Box<Window>);
282
283impl PWindow {
284    fn raw_ptr(&mut self) -> *mut Window {
285        self.0.deref_mut()
286    }
287}
288
289impl Deref for PWindow {
290    type Target = Window;
291    fn deref(&self) -> &Self::Target {
292        self.0.deref()
293    }
294}
295
296impl DerefMut for PWindow {
297    fn deref_mut(&mut self) -> &mut Self::Target {
298        self.0.deref_mut()
299    }
300}
301
302unsafe impl Send for PWindow {}
303
304unsafe impl Sync for PWindow {}
305
306// these are technically already implemented, but somehow this fixed a error in wgpu
307#[cfg(feature = "raw-window-handle-v0-6")]
308impl HasWindowHandle for PWindow {
309    fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
310        self.0.window_handle()
311    }
312}
313
314#[cfg(feature = "raw-window-handle-v0-6")]
315impl HasDisplayHandle for PWindow {
316    fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
317        self.0.display_handle()
318    }
319}
320
321/// Unique identifier for a `Window`.
322pub type WindowId = usize;
323
324#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
325#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
326pub struct Version {
327    pub major: u64,
328    pub minor: u64,
329    pub patch: u64,
330}
331
332/// Input actions.
333#[repr(i32)]
334#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
335#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
336pub enum Action {
337    Release = ffi::RELEASE,
338    Press = ffi::PRESS,
339    Repeat = ffi::REPEAT,
340}
341
342/// Input keys.
343#[repr(i32)]
344#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
345#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
346pub enum Key {
347    Space = ffi::KEY_SPACE,
348    Apostrophe = ffi::KEY_APOSTROPHE,
349    Comma = ffi::KEY_COMMA,
350    Minus = ffi::KEY_MINUS,
351    Period = ffi::KEY_PERIOD,
352    Slash = ffi::KEY_SLASH,
353    Num0 = ffi::KEY_0,
354    Num1 = ffi::KEY_1,
355    Num2 = ffi::KEY_2,
356    Num3 = ffi::KEY_3,
357    Num4 = ffi::KEY_4,
358    Num5 = ffi::KEY_5,
359    Num6 = ffi::KEY_6,
360    Num7 = ffi::KEY_7,
361    Num8 = ffi::KEY_8,
362    Num9 = ffi::KEY_9,
363    Semicolon = ffi::KEY_SEMICOLON,
364    Equal = ffi::KEY_EQUAL,
365    A = ffi::KEY_A,
366    B = ffi::KEY_B,
367    C = ffi::KEY_C,
368    D = ffi::KEY_D,
369    E = ffi::KEY_E,
370    F = ffi::KEY_F,
371    G = ffi::KEY_G,
372    H = ffi::KEY_H,
373    I = ffi::KEY_I,
374    J = ffi::KEY_J,
375    K = ffi::KEY_K,
376    L = ffi::KEY_L,
377    M = ffi::KEY_M,
378    N = ffi::KEY_N,
379    O = ffi::KEY_O,
380    P = ffi::KEY_P,
381    Q = ffi::KEY_Q,
382    R = ffi::KEY_R,
383    S = ffi::KEY_S,
384    T = ffi::KEY_T,
385    U = ffi::KEY_U,
386    V = ffi::KEY_V,
387    W = ffi::KEY_W,
388    X = ffi::KEY_X,
389    Y = ffi::KEY_Y,
390    Z = ffi::KEY_Z,
391    LeftBracket = ffi::KEY_LEFT_BRACKET,
392    Backslash = ffi::KEY_BACKSLASH,
393    RightBracket = ffi::KEY_RIGHT_BRACKET,
394    GraveAccent = ffi::KEY_GRAVE_ACCENT,
395    World1 = ffi::KEY_WORLD_1,
396    World2 = ffi::KEY_WORLD_2,
397
398    Escape = ffi::KEY_ESCAPE,
399    Enter = ffi::KEY_ENTER,
400    Tab = ffi::KEY_TAB,
401    Backspace = ffi::KEY_BACKSPACE,
402    Insert = ffi::KEY_INSERT,
403    Delete = ffi::KEY_DELETE,
404    Right = ffi::KEY_RIGHT,
405    Left = ffi::KEY_LEFT,
406    Down = ffi::KEY_DOWN,
407    Up = ffi::KEY_UP,
408    PageUp = ffi::KEY_PAGE_UP,
409    PageDown = ffi::KEY_PAGE_DOWN,
410    Home = ffi::KEY_HOME,
411    End = ffi::KEY_END,
412    CapsLock = ffi::KEY_CAPS_LOCK,
413    ScrollLock = ffi::KEY_SCROLL_LOCK,
414    NumLock = ffi::KEY_NUM_LOCK,
415    PrintScreen = ffi::KEY_PRINT_SCREEN,
416    Pause = ffi::KEY_PAUSE,
417    F1 = ffi::KEY_F1,
418    F2 = ffi::KEY_F2,
419    F3 = ffi::KEY_F3,
420    F4 = ffi::KEY_F4,
421    F5 = ffi::KEY_F5,
422    F6 = ffi::KEY_F6,
423    F7 = ffi::KEY_F7,
424    F8 = ffi::KEY_F8,
425    F9 = ffi::KEY_F9,
426    F10 = ffi::KEY_F10,
427    F11 = ffi::KEY_F11,
428    F12 = ffi::KEY_F12,
429    F13 = ffi::KEY_F13,
430    F14 = ffi::KEY_F14,
431    F15 = ffi::KEY_F15,
432    F16 = ffi::KEY_F16,
433    F17 = ffi::KEY_F17,
434    F18 = ffi::KEY_F18,
435    F19 = ffi::KEY_F19,
436    F20 = ffi::KEY_F20,
437    F21 = ffi::KEY_F21,
438    F22 = ffi::KEY_F22,
439    F23 = ffi::KEY_F23,
440    F24 = ffi::KEY_F24,
441    F25 = ffi::KEY_F25,
442    Kp0 = ffi::KEY_KP_0,
443    Kp1 = ffi::KEY_KP_1,
444    Kp2 = ffi::KEY_KP_2,
445    Kp3 = ffi::KEY_KP_3,
446    Kp4 = ffi::KEY_KP_4,
447    Kp5 = ffi::KEY_KP_5,
448    Kp6 = ffi::KEY_KP_6,
449    Kp7 = ffi::KEY_KP_7,
450    Kp8 = ffi::KEY_KP_8,
451    Kp9 = ffi::KEY_KP_9,
452    KpDecimal = ffi::KEY_KP_DECIMAL,
453    KpDivide = ffi::KEY_KP_DIVIDE,
454    KpMultiply = ffi::KEY_KP_MULTIPLY,
455    KpSubtract = ffi::KEY_KP_SUBTRACT,
456    KpAdd = ffi::KEY_KP_ADD,
457    KpEnter = ffi::KEY_KP_ENTER,
458    KpEqual = ffi::KEY_KP_EQUAL,
459    LeftShift = ffi::KEY_LEFT_SHIFT,
460    LeftControl = ffi::KEY_LEFT_CONTROL,
461    LeftAlt = ffi::KEY_LEFT_ALT,
462    LeftSuper = ffi::KEY_LEFT_SUPER,
463    RightShift = ffi::KEY_RIGHT_SHIFT,
464    RightControl = ffi::KEY_RIGHT_CONTROL,
465    RightAlt = ffi::KEY_RIGHT_ALT,
466    RightSuper = ffi::KEY_RIGHT_SUPER,
467    Menu = ffi::KEY_MENU,
468    Unknown = ffi::KEY_UNKNOWN,
469}
470
471/// Wrapper around `glfwGetKeyName`
472pub fn get_key_name(key: Option<Key>, scancode: Option<Scancode>) -> Option<String> {
473    unsafe {
474        string_from_nullable_c_str(ffi::glfwGetKeyName(
475            match key {
476                Some(k) => k as c_int,
477                None => ffi::KEY_UNKNOWN,
478            },
479            scancode.unwrap_or(ffi::KEY_UNKNOWN),
480        ))
481    }
482}
483
484/// Wrapper around `glfwGetKeyName`
485#[deprecated(
486    since = "0.16.0",
487    note = "'key_name' can cause a segfault, use 'get_key_name' instead"
488)]
489pub fn key_name(key: Option<Key>, scancode: Option<Scancode>) -> String {
490    unsafe {
491        string_from_c_str(ffi::glfwGetKeyName(
492            match key {
493                Some(k) => k as c_int,
494                None => ffi::KEY_UNKNOWN,
495            },
496            scancode.unwrap_or(ffi::KEY_UNKNOWN),
497        ))
498    }
499}
500
501/// Wrapper around `glfwGetKeyScancode`.
502pub fn get_key_scancode(key: Option<Key>) -> Option<Scancode> {
503    unsafe {
504        match ffi::glfwGetKeyScancode(match key {
505            Some(key) => key as c_int,
506            None => ffi::KEY_UNKNOWN,
507        }) {
508            ffi::KEY_UNKNOWN => None,
509            scancode => Some(scancode as Scancode),
510        }
511    }
512}
513
514impl Key {
515    /// Wrapper around `glfwGetKeyName` without scancode
516    #[deprecated(
517        since = "0.16.0",
518        note = "Key method 'name' can cause a segfault, use 'get_name' instead"
519    )]
520    pub fn name(&self) -> String {
521        #[allow(deprecated)]
522        key_name(Some(*self), None)
523    }
524
525    /// Wrapper around `glfwGetKeyName` without scancode
526    pub fn get_name(&self) -> Option<String> {
527        get_key_name(Some(*self), None)
528    }
529
530    /// Wrapper around `glfwGetKeyScancode`.
531    pub fn get_scancode(&self) -> Option<Scancode> {
532        get_key_scancode(Some(*self))
533    }
534}
535
536/// Mouse buttons. The `MouseButtonLeft`, `MouseButtonRight`, and
537/// `MouseButtonMiddle` aliases are supplied for convenience.
538#[repr(i32)]
539#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
540#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
541pub enum MouseButton {
542    /// The left mouse button. A `MouseButtonLeft` alias is provided to improve clarity.
543    Button1 = ffi::MOUSE_BUTTON_1,
544    /// The right mouse button. A `MouseButtonRight` alias is provided to improve clarity.
545    Button2 = ffi::MOUSE_BUTTON_2,
546    /// The middle mouse button. A `MouseButtonMiddle` alias is provided to improve clarity.
547    Button3 = ffi::MOUSE_BUTTON_3,
548    Button4 = ffi::MOUSE_BUTTON_4,
549    Button5 = ffi::MOUSE_BUTTON_5,
550    Button6 = ffi::MOUSE_BUTTON_6,
551    Button7 = ffi::MOUSE_BUTTON_7,
552    Button8 = ffi::MOUSE_BUTTON_8,
553}
554
555impl MouseButton {
556    /// Alias to `MouseButton1`, supplied for improved clarity.
557    pub const Left: Self = MouseButton::Button1;
558    /// Alias to `MouseButton2`, supplied for improved clarity.
559    pub const Right: Self = MouseButton::Button2;
560    /// Alias to `MouseButton3`, supplied for improved clarity.
561    pub const Middle: Self = MouseButton::Button3;
562
563    /// Converts from `i32`.
564    pub fn from_i32(n: i32) -> Option<MouseButton> {
565        if (0..=ffi::MOUSE_BUTTON_LAST).contains(&n) {
566            Some(unsafe { mem::transmute(n) })
567        } else {
568            None
569        }
570    }
571}
572
573/// Formats the type using aliases rather than the default variant names.
574///
575/// # Example
576///
577/// ~~~ignore
578/// assert_eq(format!("{}", glfw::MouseButtonLeft), "MouseButton1");
579/// assert_eq(format!("{}", glfw::DebugAliases(glfw::MouseButtonLeft)), "MouseButtonLeft");
580/// ~~~
581pub struct DebugAliases<T>(pub T);
582
583impl fmt::Debug for DebugAliases<MouseButton> {
584    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
585        let DebugAliases(button) = *self;
586        match button {
587            MouseButtonLeft => write!(f, "MouseButtonLeft"),
588            MouseButtonRight => write!(f, "MouseButtonRight"),
589            MouseButtonMiddle => write!(f, "MouseButtonMiddle"),
590            button => button.fmt(f),
591        }
592    }
593}
594
595/// Tokens corresponding to various error types.
596#[repr(i32)]
597#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
598#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
599pub enum Error {
600    NoError = ffi::NO_ERROR,
601    NotInitialized = ffi::NOT_INITIALIZED,
602    NoCurrentContext = ffi::NO_CURRENT_CONTEXT,
603    InvalidEnum = ffi::INVALID_ENUM,
604    InvalidValue = ffi::INVALID_VALUE,
605    OutOfMemory = ffi::OUT_OF_MEMORY,
606    ApiUnavailable = ffi::API_UNAVAILABLE,
607    VersionUnavailable = ffi::VERSION_UNAVAILABLE,
608    PlatformError = ffi::PLATFORM_ERROR,
609    FormatUnavailable = ffi::FORMAT_UNAVAILABLE,
610    NoWindowContext = ffi::NO_WINDOW_CONTEXT,
611}
612
613impl fmt::Display for Error {
614    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
615        let description = match *self {
616            Error::NoError => "NoError",
617            Error::NotInitialized => "NotInitialized",
618            Error::NoCurrentContext => "NoCurrentContext",
619            Error::InvalidEnum => "InvalidEnum",
620            Error::InvalidValue => "InvalidValue",
621            Error::OutOfMemory => "OutOfMemory",
622            Error::ApiUnavailable => "ApiUnavailable",
623            Error::VersionUnavailable => "VersionUnavailable",
624            Error::PlatformError => "PlatformError",
625            Error::FormatUnavailable => "FormatUnavailable",
626            Error::NoWindowContext => "NoWindowContext",
627        };
628
629        f.write_str(description)
630    }
631}
632
633impl error::Error for Error {}
634
635/// The function to be used with the `fail_on_errors!()` callback.
636pub fn fail_on_errors(_: Error, description: String) {
637    panic!("GLFW Error: {}", description);
638}
639
640/// A callback that triggers a task failure when an error is encountered.
641#[macro_export]
642macro_rules! fail_on_errors {
643    () => {{
644        |error, description| {
645            fail_on_errors(error, description);
646        }
647    }};
648}
649
650#[cfg(feature = "log")]
651/// The function to be used with the `LOG_ERRORS` callback.
652pub fn log_errors(_: Error, description: String) {
653    error!("GLFW Error: {}", description);
654}
655
656#[cfg(not(feature = "log"))]
657/// The function to be used with the `LOG_ERRORS` callback.
658pub fn log_errors(_: Error, description: String) {
659    eprintln!("GLFW Error: {}", description);
660}
661
662/// A callback that logs each error as it is encountered without triggering a
663/// task failure
664#[macro_export]
665macro_rules! log_errors {
666    () => {{
667        |error, description| {
668            log_errors(error, description);
669        }
670    }};
671}
672
673/// When not using the `image` library, or if you just want to,
674/// you can specify an image from its raw pixel data using this structure.
675#[derive(Debug)]
676pub struct PixelImage {
677    /// Width of the image in pixels
678    pub width: u32,
679    /// Height of the image in pixels
680    pub height: u32,
681    /// Pixels are 4 bytes each, one byte for each RGBA subpixel.
682    pub pixels: Vec<u32>,
683}
684
685/// Cursor modes.
686#[repr(i32)]
687#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
688#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
689pub enum CursorMode {
690    Normal = ffi::CURSOR_NORMAL,
691    Hidden = ffi::CURSOR_HIDDEN,
692    Disabled = ffi::CURSOR_DISABLED,
693}
694
695/// Standard cursors provided by GLFW
696#[repr(i32)]
697#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
698#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
699pub enum StandardCursor {
700    /// The regular arrow cursor shape.
701    Arrow = ffi::ARROW_CURSOR,
702    /// The text input I-beam cursor shape.
703    IBeam = ffi::IBEAM_CURSOR,
704    /// The crosshair shape.
705    Crosshair = ffi::CROSSHAIR_CURSOR,
706    /// The hand shape.
707    Hand = ffi::HAND_CURSOR,
708    /// The horizontal resize arrow shape.
709    HResize = ffi::HRESIZE_CURSOR,
710    /// The vertical resize arrow shape.
711    VResize = ffi::VRESIZE_CURSOR,
712}
713
714/// Represents a window cursor that can be used to display any
715/// of the standard cursors or load a custom cursor from an image.
716///
717/// Note that the cursor object has a lifetime and will not display
718/// correctly after it has been dropped.
719#[derive(Debug)]
720pub struct Cursor {
721    ptr: *mut ffi::GLFWcursor,
722}
723
724impl Drop for Cursor {
725    fn drop(&mut self) {
726        unsafe { ffi::glfwDestroyCursor(self.ptr) }
727    }
728}
729
730impl Cursor {
731    /// Create a new cursor using `glfwCreateStandardCursor`
732    pub fn standard(cursor: StandardCursor) -> Cursor {
733        Cursor {
734            ptr: unsafe { ffi::glfwCreateStandardCursor(cursor as c_int) },
735        }
736    }
737
738    /// Creates a new cursor from the image provided via `glfwCreateCursor`
739    ///
740    /// Note that the cursor image will be the same size as the image provided,
741    /// so scaling it beforehand may be required.
742    ///
743    /// The cursor hotspot is specified in pixels, relative to the upper-left
744    /// corner of the cursor image. Like all other coordinate systems in GLFW,
745    /// the X-axis points to the right and the Y-axis points down.
746    #[cfg(feature = "image")]
747    pub fn create(image: image::RgbaImage, x_hotspot: u32, y_hotspot: u32) -> Cursor {
748        let (width, height) = image.dimensions();
749
750        let image_data = image.into_vec();
751
752        let glfw_image = ffi::GLFWimage {
753            width: width as c_int,
754            height: height as c_int,
755            pixels: image_data.as_ptr() as *const c_uchar,
756        };
757
758        Cursor {
759            ptr: unsafe {
760                ffi::glfwCreateCursor(
761                    &glfw_image as *const ffi::GLFWimage,
762                    x_hotspot as c_int,
763                    y_hotspot as c_int,
764                )
765            },
766        }
767    }
768
769    /// Creates a new cursor from the `PixelImage` provided via `glfwCreateCursor`
770    ///
771    /// Note that the cursor image will be the same size as the image provided,
772    /// so scaling it beforehand may be required.
773    ///
774    /// The cursor hotspot is specified in pixels, relative to the upper-left
775    /// corner of the cursor image. Like all other coordinate systems in GLFW,
776    /// the X-axis points to the right and the Y-axis points down.
777    pub fn create_from_pixels(image: PixelImage, x_hotspot: u32, y_hotspot: u32) -> Cursor {
778        let glfw_image = ffi::GLFWimage {
779            width: image.width as c_int,
780            height: image.height as c_int,
781            pixels: image.pixels.as_ptr() as *const c_uchar,
782        };
783
784        Cursor {
785            ptr: unsafe {
786                ffi::glfwCreateCursor(
787                    &glfw_image as *const ffi::GLFWimage,
788                    x_hotspot as c_int,
789                    y_hotspot as c_int,
790                )
791            },
792        }
793    }
794}
795
796/// Describes a single video mode.
797#[derive(Copy, Clone)]
798#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
799pub struct VidMode {
800    pub width: u32,
801    pub height: u32,
802    pub red_bits: u32,
803    pub green_bits: u32,
804    pub blue_bits: u32,
805    pub refresh_rate: u32,
806}
807
808/// Describes the gamma ramp of a monitor.
809#[derive(Debug)]
810#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
811pub struct GammaRamp {
812    pub red: Vec<c_ushort>,
813    pub green: Vec<c_ushort>,
814    pub blue: Vec<c_ushort>,
815}
816
817/// `ContextReleaseBehavior` specifies the release behavior to be used by the context.
818#[repr(i32)]
819#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
820#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
821pub enum ContextReleaseBehavior {
822    Any = ffi::ANY_RELEASE_BEHAVIOR,
823    /// `Flush` tells the context to flush the pipeline whenever the context is released from being
824    /// the current one.
825    Flush = ffi::RELEASE_BEHAVIOR_FLUSH,
826    /// `None` tells the context to NOT flush the pipeline on release
827    None = ffi::RELEASE_BEHAVIOR_NONE,
828}
829
830/// Specifies the API to use to create the context
831#[repr(i32)]
832#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
833#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
834pub enum ContextCreationApi {
835    Native = ffi::NATIVE_CONTEXT_API,
836    Egl = ffi::EGL_CONTEXT_API,
837    OsMesa = ffi::OSMESA_CONTEXT_API,
838}
839
840/// Specifies how the context should handle swapping the buffers.
841///
842/// i.e. the number of screen updates to wait from the time
843/// `glfwSwapBuffers`/`context.swap_buffers`
844/// was called before swapping the buffers and returning.
845#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
846#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
847pub enum SwapInterval {
848    /// Specifies no waits
849    None,
850    /// If either of the `WGL_EXT_swap_control_tear` and `GLX_EXT_swap_control_tear` extensions
851    /// are enabled, allows the adaptively swap the frame. Sometimes called Adaptive V-sync
852    Adaptive,
853    /// Synchronizes the buffers every N frames. Set to 1 for V-sync
854    Sync(u32),
855}
856
857/// An OpenGL process address.
858pub type GLProc = ffi::GLFWglproc;
859
860/// A Vulkan process address
861#[cfg(feature = "vulkan")]
862pub type VkProc = ffi::GLFWvkproc;
863
864/// Counts for (Calling glfwInit) - (Calling glfwTerminate)
865/// It uses for "global" refference counting for Glfw.
866static REF_COUNT_FOR_GLFW: AtomicUsize = AtomicUsize::new(0);
867
868/// A struct that represents a thread safe handle to a `Glfw`
869#[derive(Debug)]
870pub struct ThreadSafeGlfw {
871    glfw: Glfw,
872}
873
874impl ThreadSafeGlfw {
875    /// Creates a new `Glfw` wrapper that can be shared between threads
876    pub fn from(glfw: &mut Glfw) -> Self {
877        Self { glfw: glfw.clone() }
878    }
879
880    /// Wrapper function, please refer to [`Glfw::set_swap_interval`]
881    pub fn set_swap_interval(&mut self, interval: SwapInterval) {
882        self.glfw.set_swap_interval(interval);
883    }
884
885    /// Wrapper function, please refer to [`Glfw::extension_supported`]
886    pub fn extension_supported(&self, extension: &str) -> bool {
887        self.glfw.extension_supported(extension)
888    }
889
890    /// Wrapper function, please refer to [`Glfw::get_time`]
891    pub fn get_time(&self) -> f64 {
892        self.glfw.get_time()
893    }
894
895    /// Wrapper function, please refer to [`Glfw::set_time`]
896    pub fn set_time(&mut self, time: f64) {
897        self.glfw.set_time(time);
898    }
899
900    /// Wrapper function, please refer to [`Glfw::vulkan_supported`]
901    #[cfg(feature = "vulkan")]
902    pub fn vulkan_supported(&self) -> bool {
903        self.glfw.vulkan_supported()
904    }
905
906    /// Wrapper function, please refer to [`Glfw::get_required_instance_extensions`]
907    #[cfg(feature = "vulkan")]
908    pub fn get_required_instance_extensions(&self) -> Option<Vec<String>> {
909        self.glfw.get_required_instance_extensions()
910    }
911
912    /// Wrapper function, please refer to [`Glfw::get_instance_proc_address_raw`]
913    #[cfg(feature = "vulkan")]
914    pub fn get_instance_proc_address_raw(&self, instance: vk::Instance, procname: &str) -> VkProc {
915        self.glfw.get_instance_proc_address_raw(instance, procname)
916    }
917
918    /// Wrapper function, please refer to [`Glfw::get_physical_device_presentation_support_raw`]
919    #[cfg(feature = "vulkan")]
920    pub fn get_physical_device_presentation_support_raw(
921        &self,
922        instance: vk::Instance,
923        device: vk::PhysicalDevice,
924        queue_family: u32,
925    ) -> bool {
926        self.glfw
927            .get_physical_device_presentation_support_raw(instance, device, queue_family)
928    }
929
930    /// Wrapper function, please refer to [`Glfw::get_timer_value`]
931    pub fn get_timer_value(&self) -> u64 {
932        self.glfw.get_timer_value()
933    }
934
935    /// Wrapper function, please refer to [`Glfw::get_timer_frequency`]
936    pub fn get_timer_frequency(&self) -> u64 {
937        self.glfw.get_timer_frequency()
938    }
939
940    /// Wrapper function, please refer to [`Glfw::post_empty_event`]
941    pub fn post_empty_event(&self) {
942        self.glfw.post_empty_event()
943    }
944}
945
946unsafe impl Send for ThreadSafeGlfw {}
947
948/// A token from which to call various GLFW functions. It can be obtained by
949/// calling the `init` function. This cannot be sent to other tasks, and should
950/// only be initialized on the main platform thread. Whilst this might make
951/// performing some operations harder, this is to ensure thread safety is enforced
952/// statically.
953#[non_exhaustive]
954#[derive(Debug)]
955pub struct Glfw {
956    phantom: std::marker::PhantomData<*const ()>,
957}
958
959/// An error that might be returned when `glfw::init` is called.
960#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
961#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
962pub enum InitError {
963    /// Deprecated. Does not occur.
964    AlreadyInitialized,
965    /// An internal error occurred when trying to initialize the library.
966    Internal,
967}
968
969impl fmt::Display for InitError {
970    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
971        let description = match *self {
972            InitError::AlreadyInitialized => "Already Initialized",
973            InitError::Internal => "Internal Initialization Error",
974        };
975
976        f.write_str(description)
977    }
978}
979
980impl error::Error for InitError {}
981
982/// Initialization hints that can be set using the `init_hint` function.
983#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
984#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
985pub enum InitHint {
986    /// Specifies whether to also expose joystick hats as buttons, for compatibility with earlier
987    /// versions of GLFW that did not have `glfwGetJoystickHats`.
988    JoystickHatButtons(bool),
989    /// Specifies whether to set the current directory to the application to the
990    /// `Contents/Resources` subdirectory of the application's bundle, if present.
991    ///
992    /// This is ignored on platforms besides macOS.
993    CocoaChdirResources(bool),
994    /// Specifies whether to create a basic menu bar, either from a nib or manually, when the first
995    /// window is created, which is when AppKit is initialized.
996    ///
997    /// This is ignored on platforms besides macOS.
998    CocoaMenubar(bool),
999}
1000
1001/// Sets hints for the next initialization of GLFW.
1002///
1003/// The values you set hints to are never reset by GLFW, but they only take effect during
1004/// initialization. Once GLFW has been initialized, any values you set will be ignored until the
1005/// library is terminated and initialized again.
1006///
1007/// Wrapper for `glfwInitHint`.
1008pub fn init_hint(hint: InitHint) {
1009    match hint {
1010        InitHint::JoystickHatButtons(joystick_hat_buttons) => unsafe {
1011            ffi::glfwInitHint(ffi::JOYSTICK_HAT_BUTTONS, joystick_hat_buttons as c_int)
1012        },
1013        InitHint::CocoaChdirResources(chdir) => unsafe {
1014            ffi::glfwInitHint(ffi::COCOA_CHDIR_RESOURCES, chdir as c_int)
1015        },
1016        InitHint::CocoaMenubar(menubar) => unsafe {
1017            ffi::glfwInitHint(ffi::COCOA_MENUBAR, menubar as c_int)
1018        },
1019    }
1020}
1021/// Initializes the GLFW library. This must be called on the main platform
1022/// thread.
1023///
1024/// Wrapper for `glfwInit`.
1025///
1026/// # Example
1027///
1028/// ~~~no_run
1029/// extern crate glfw;
1030///
1031/// fn main() {
1032///    let glfw = glfw::init_no_callbacks().unwrap();
1033/// }
1034/// ~~~
1035///
1036/// # Error callback
1037///
1038/// An error callback can be set if desired. This allows for the handling of any
1039/// errors that occur during initialization. This can subsequently be changed
1040/// using the `glfw::init` function.
1041///
1042/// ~~~no_run
1043/// extern crate glfw;
1044/// #[macro_use]
1045/// extern crate log;
1046///
1047/// fn main() {
1048///    let glfw = glfw::init(error_callback).unwrap();
1049/// }
1050///
1051/// fn error_callback(err: glfw::Error, description: String) {
1052///     error!("GLFW error {:?}: {:?}", err, description);
1053/// }
1054/// ~~~
1055///
1056/// # Returns
1057///
1058/// - If initialization was successful a `Glfw` token will be returned along with a `Receiver` from
1059///   which errors can be intercepted.
1060/// - Subsequent calls to `init` will return `Glfw` token immediately.
1061/// - If an initialization error occurred within the GLFW library `Err(InternalInitError)` will be
1062///   returned.
1063pub fn init<T>(callback: T) -> Result<Glfw, InitError>
1064where
1065    T: FnMut(Error, String) + 'static,
1066{
1067    // Initialize the error callback. This is done
1068    // before `ffi::glfwInit` because errors could occur during
1069    // initialization.
1070    callbacks::error::set(callback);
1071
1072    init_no_callbacks()
1073}
1074
1075pub fn init_no_callbacks() -> Result<Glfw, InitError> {
1076    // initialize GLFW.
1077    // FYI: multiple not terminated ffi::glfwInit() returns ffi::TRUE immediately.
1078    // https://www.glfw.org/docs/latest/group__init.html#ga317aac130a235ab08c6db0834907d85e
1079    if unsafe { ffi::glfwInit() } == ffi::TRUE {
1080        REF_COUNT_FOR_GLFW.fetch_add(1, Ordering::SeqCst);
1081        Ok(Glfw {
1082            phantom: std::marker::PhantomData,
1083        })
1084    } else {
1085        Err(InitError::Internal)
1086    }
1087}
1088
1089impl Glfw {
1090    /// Sets the error callback, overwriting the previous one stored.
1091    ///
1092    /// # Example
1093    ///
1094    /// ~~~ignore
1095    /// // sets a new callback
1096    /// let mut error_count: usize = 0;
1097    /// glfw.set_error_callback(Some(move |error, description| {
1098    ///     println!("GLFW error {}: {}", error_count, description);
1099    ///     error_count += 1;
1100    /// }));
1101    ///
1102    /// // removes the previously set callback
1103    /// glfw.set_error_callback(None);
1104    /// ~~~
1105    ///
1106    /// The `fail_on_errors!()` and `log_errors!()` callback macros are provided for
1107    /// convenience. For example:
1108    ///
1109    /// ~~~ignore
1110    /// // triggers a task failure when a GLFW error is encountered.
1111    /// glfw.set_error_callback(fail_on_errors!());
1112    /// ~~~
1113    pub fn set_error_callback<T>(&mut self, callback: T)
1114    where
1115        T: FnMut(Error, String) + 'static,
1116    {
1117        callbacks::error::set(callback);
1118    }
1119
1120    /// Unsets the monitor callback
1121    pub fn unset_error_callback(&mut self) {
1122        callbacks::error::unset();
1123    }
1124
1125    /// Sets the monitor callback, overwriting the previous one stored.
1126    pub fn set_monitor_callback<T>(&mut self, callback: T)
1127    where
1128        T: FnMut(Monitor, MonitorEvent) + 'static,
1129    {
1130        callbacks::monitor::set(callback);
1131    }
1132
1133    /// Unsets the monitor callback
1134    pub fn unset_monitor_callback(&mut self) {
1135        callbacks::monitor::unset();
1136    }
1137
1138    /// Sets the joystick callback, overwriting the previous one stored
1139    pub fn set_joystick_callback<T>(&mut self, callback: T)
1140    where
1141        T: FnMut(JoystickId, JoystickEvent) + 'static,
1142    {
1143        callbacks::joystick::set(callback);
1144    }
1145
1146    /// Unsets the joystick callback
1147    pub fn unset_joystick_callback(&mut self) {
1148        callbacks::joystick::unset();
1149    }
1150
1151    /// Supplies the primary monitor to the closure provided, if it exists.
1152    /// This is usually the monitor where elements like the Windows task bar or
1153    /// the OS X menu bar is located.
1154    ///
1155    /// # Example
1156    ///
1157    /// ~~~ignore
1158    /// let (window, events) = glfw.with_primary_monitor(|_, m| {
1159    ///     glfw.create_window(300, 300, "Hello this is window",
1160    ///         m.map_or(glfw::WindowMode::Windowed, |m| glfw::FullScreen(m)))
1161    /// }).expect("Failed to create GLFW window.");
1162    /// ~~~
1163    pub fn with_primary_monitor<T, F>(&mut self, f: F) -> T
1164    where
1165        F: FnOnce(&mut Self, Option<&mut Monitor>) -> T,
1166    {
1167        match unsafe { ffi::glfwGetPrimaryMonitor() } {
1168            ptr if ptr.is_null() => f(self, None),
1169            ptr => f(self, Some(&mut Monitor { ptr })),
1170        }
1171    }
1172
1173    /// Supplies the window monitor to the closure provided, if it's fullscreen.
1174    ///
1175    /// # Example
1176    ///
1177    /// ~~~ignore
1178    /// let (window, events) = glfw.with_window_monitor(|_, m| {
1179    ///     glfw.create_window(300, 300, "Hello this is window",
1180    ///         m.map_or(glfw::WindowMode::Windowed, |m| glfw::FullScreen(m)))
1181    /// }).expect("Failed to create GLFW window.");
1182    /// ~~~
1183    pub fn with_window_monitor<T, F>(&mut self, window: &mut Window, f: F) -> T
1184    where
1185        F: FnOnce(&mut Self, Option<&mut Monitor>) -> T,
1186    {
1187        match unsafe { ffi::glfwGetWindowMonitor(window.ptr) } {
1188            ptr if ptr.is_null() => f(self, None),
1189            ptr => f(self, Some(&mut Monitor { ptr })),
1190        }
1191    }
1192
1193    /// Supplies a vector of the currently connected monitors to the closure
1194    /// provided.
1195    ///
1196    /// # Example
1197    ///
1198    /// ~~~ignore
1199    /// glfw.with_connected_monitors(|_, monitors| {
1200    ///     for monitor in monitors.iter() {
1201    ///         println!("{}: {}", monitor.get_name(), monitor.get_video_mode());
1202    ///     }
1203    /// });
1204    /// ~~~
1205    pub fn with_connected_monitors<T, F>(&mut self, f: F) -> T
1206    where
1207        F: FnOnce(&mut Self, &[&mut Monitor]) -> T,
1208    {
1209        unsafe {
1210            let mut count = 0;
1211            let ptr = ffi::glfwGetMonitors(&mut count);
1212            let mut monitors = slice::from_raw_parts(ptr as *const _, count as usize)
1213                .iter()
1214                .map(|&ptr| Monitor { ptr })
1215                .collect::<Vec<Monitor>>();
1216
1217            let refs: Vec<&mut Monitor> = monitors.iter_mut().collect();
1218            f(self, &refs)
1219        }
1220    }
1221
1222    /// Queries Vulkan support via `glfwVulkanSupported`
1223    #[cfg(feature = "vulkan")]
1224    pub fn vulkan_supported(&self) -> bool {
1225        unsafe { ffi::glfwVulkanSupported() == ffi::TRUE }
1226    }
1227
1228    /// This is used to set the window hints for the next call to
1229    /// `Glfw::create_window`. The hints can be reset to their default values
1230    /// using calling the `Glfw::default_window_hints` function.
1231    ///
1232    /// Wrapper for `glfwWindowHint`
1233    ///
1234    /// # OpenGL 3.x and 4.x on Mac OS X
1235    ///
1236    /// The only OpenGL 3.x and 4.x contexts supported by OS X are
1237    /// forward-compatible, core profile contexts.
1238    ///
1239    /// 10.7 and 10.8 support the following OpenGL versions:
1240    ///
1241    /// - `glfw::WindowHint::ContextVersion(3, 2)`
1242    ///
1243    /// 10.9 supports the following OpenGL versions
1244    ///
1245    /// - `glfw::WindowHint::ContextVersion(3, 2)`
1246    /// - `glfw::WindowHint::ContextVersion(3, 3)`
1247    /// - `glfw::WindowHint::ContextVersion(4, 1)`
1248    ///
1249    /// To create an OS X compatible context, the hints should be specified as
1250    /// follows:
1251    ///
1252    /// ~~~ignore
1253    /// glfw.window_hint(glfw::WindowHint::ContextVersion(3, 2));
1254    /// glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
1255    /// glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
1256    /// ~~~
1257    pub fn window_hint(&mut self, hint: WindowHint) {
1258        //This is just a simple function to unwrap the option and convert it to `c_int` or use
1259        // `GLFW_DONT_CARE`, then call `glfwWindowHint` with the result. It was required because
1260        // `GLFW_DONT_CARE` is signed, so `value.unwrap_or(ffi::DONT_CARE)` wouldn't work because
1261        // of the type difference.
1262        #[inline(always)]
1263        unsafe fn dont_care_hint(hint: c_int, value: Option<u32>) {
1264            ffi::glfwWindowHint(hint, unwrap_dont_care(value))
1265        }
1266
1267        #[inline(always)]
1268        unsafe fn string_hint(hint: c_int, value: Option<String>) {
1269            let value = if let Some(value) = &value {
1270                value.as_str()
1271            } else {
1272                ""
1273            };
1274            with_c_str(value, |value| ffi::glfwWindowHintString(hint, value))
1275        }
1276
1277        match hint {
1278            WindowHint::RedBits(bits) => unsafe { dont_care_hint(ffi::RED_BITS, bits) },
1279            WindowHint::GreenBits(bits) => unsafe { dont_care_hint(ffi::GREEN_BITS, bits) },
1280            WindowHint::BlueBits(bits) => unsafe { dont_care_hint(ffi::BLUE_BITS, bits) },
1281            WindowHint::AlphaBits(bits) => unsafe { dont_care_hint(ffi::ALPHA_BITS, bits) },
1282            WindowHint::DepthBits(bits) => unsafe { dont_care_hint(ffi::DEPTH_BITS, bits) },
1283            WindowHint::StencilBits(bits) => unsafe { dont_care_hint(ffi::STENCIL_BITS, bits) },
1284            WindowHint::AccumRedBits(bits) => unsafe { dont_care_hint(ffi::ACCUM_RED_BITS, bits) },
1285            WindowHint::AccumGreenBits(bits) => unsafe {
1286                dont_care_hint(ffi::ACCUM_GREEN_BITS, bits)
1287            },
1288            WindowHint::AccumBlueBits(bits) => unsafe {
1289                dont_care_hint(ffi::ACCUM_BLUE_BITS, bits)
1290            },
1291            WindowHint::AccumAlphaBits(bits) => unsafe {
1292                dont_care_hint(ffi::ACCUM_ALPHA_BITS, bits)
1293            },
1294            WindowHint::AuxBuffers(num_buffers) => unsafe {
1295                dont_care_hint(ffi::AUX_BUFFERS, num_buffers)
1296            },
1297            WindowHint::Samples(num_samples) => unsafe {
1298                dont_care_hint(ffi::SAMPLES, num_samples)
1299            },
1300            WindowHint::RefreshRate(rate) => unsafe { dont_care_hint(ffi::REFRESH_RATE, rate) },
1301            WindowHint::Stereo(is_stereo) => unsafe {
1302                ffi::glfwWindowHint(ffi::STEREO, is_stereo as c_int)
1303            },
1304            WindowHint::SRgbCapable(is_capable) => unsafe {
1305                ffi::glfwWindowHint(ffi::SRGB_CAPABLE, is_capable as c_int)
1306            },
1307            WindowHint::ClientApi(api) => unsafe {
1308                ffi::glfwWindowHint(ffi::CLIENT_API, api as c_int)
1309            },
1310            WindowHint::ContextVersionMajor(major) => unsafe {
1311                ffi::glfwWindowHint(ffi::CONTEXT_VERSION_MAJOR, major as c_int)
1312            },
1313            WindowHint::ContextVersionMinor(minor) => unsafe {
1314                ffi::glfwWindowHint(ffi::CONTEXT_VERSION_MINOR, minor as c_int)
1315            },
1316            WindowHint::ContextVersion(major, minor) => unsafe {
1317                ffi::glfwWindowHint(ffi::CONTEXT_VERSION_MAJOR, major as c_int);
1318                ffi::glfwWindowHint(ffi::CONTEXT_VERSION_MINOR, minor as c_int)
1319            },
1320            WindowHint::ContextRobustness(robustness) => unsafe {
1321                ffi::glfwWindowHint(ffi::CONTEXT_ROBUSTNESS, robustness as c_int)
1322            },
1323            WindowHint::OpenGlForwardCompat(is_compat) => unsafe {
1324                ffi::glfwWindowHint(ffi::OPENGL_FORWARD_COMPAT, is_compat as c_int)
1325            },
1326            WindowHint::OpenGlDebugContext(is_debug) => unsafe {
1327                ffi::glfwWindowHint(ffi::OPENGL_DEBUG_CONTEXT, is_debug as c_int)
1328            },
1329            WindowHint::OpenGlProfile(profile) => unsafe {
1330                ffi::glfwWindowHint(ffi::OPENGL_PROFILE, profile as c_int)
1331            },
1332            WindowHint::Resizable(is_resizable) => unsafe {
1333                ffi::glfwWindowHint(ffi::RESIZABLE, is_resizable as c_int)
1334            },
1335            WindowHint::Visible(is_visible) => unsafe {
1336                ffi::glfwWindowHint(ffi::VISIBLE, is_visible as c_int)
1337            },
1338            WindowHint::Decorated(is_decorated) => unsafe {
1339                ffi::glfwWindowHint(ffi::DECORATED, is_decorated as c_int)
1340            },
1341            WindowHint::AutoIconify(auto_iconify) => unsafe {
1342                ffi::glfwWindowHint(ffi::AUTO_ICONIFY, auto_iconify as c_int)
1343            },
1344            WindowHint::Floating(is_floating) => unsafe {
1345                ffi::glfwWindowHint(ffi::FLOATING, is_floating as c_int)
1346            },
1347            WindowHint::Focused(is_focused) => unsafe {
1348                ffi::glfwWindowHint(ffi::FOCUSED, is_focused as c_int)
1349            },
1350            WindowHint::Maximized(is_maximized) => unsafe {
1351                ffi::glfwWindowHint(ffi::MAXIMIZED, is_maximized as c_int)
1352            },
1353            WindowHint::ContextNoError(is_no_error) => unsafe {
1354                ffi::glfwWindowHint(ffi::CONTEXT_NO_ERROR, is_no_error as c_int)
1355            },
1356            WindowHint::ContextCreationApi(api) => unsafe {
1357                ffi::glfwWindowHint(ffi::CONTEXT_CREATION_API, api as c_int)
1358            },
1359            WindowHint::ContextReleaseBehavior(behavior) => unsafe {
1360                ffi::glfwWindowHint(ffi::CONTEXT_RELEASE_BEHAVIOR, behavior as c_int)
1361            },
1362            WindowHint::DoubleBuffer(is_dbuffered) => unsafe {
1363                ffi::glfwWindowHint(ffi::DOUBLEBUFFER, is_dbuffered as c_int)
1364            },
1365            WindowHint::CenterCursor(center_cursor) => unsafe {
1366                ffi::glfwWindowHint(ffi::CENTER_CURSOR, center_cursor as c_int)
1367            },
1368            WindowHint::TransparentFramebuffer(is_transparent) => unsafe {
1369                ffi::glfwWindowHint(ffi::TRANSPARENT_FRAMEBUFFER, is_transparent as c_int)
1370            },
1371            WindowHint::FocusOnShow(focus) => unsafe {
1372                ffi::glfwWindowHint(ffi::FOCUS_ON_SHOW, focus as c_int)
1373            },
1374            WindowHint::ScaleToMonitor(scale) => unsafe {
1375                ffi::glfwWindowHint(ffi::SCALE_TO_MONITOR, scale as c_int)
1376            },
1377            WindowHint::CocoaRetinaFramebuffer(retina_fb) => unsafe {
1378                ffi::glfwWindowHint(ffi::COCOA_RETINA_FRAMEBUFFER, retina_fb as c_int)
1379            },
1380            WindowHint::CocoaFrameName(name) => unsafe { string_hint(ffi::COCOA_FRAME_NAME, name) },
1381            WindowHint::CocoaGraphicsSwitching(graphics_switching) => unsafe {
1382                ffi::glfwWindowHint(ffi::COCOA_GRAPHICS_SWITCHING, graphics_switching as c_int)
1383            },
1384            WindowHint::X11ClassName(class_name) => unsafe {
1385                string_hint(ffi::X11_CLASS_NAME, class_name)
1386            },
1387            WindowHint::X11InstanceName(instance_name) => unsafe {
1388                string_hint(ffi::X11_INSTANCE_NAME, instance_name)
1389            },
1390        }
1391    }
1392
1393    /// Resets the window hints previously set by the `window_hint` function to
1394    /// their default values.
1395    ///
1396    /// Wrapper for `glfwDefaultWindowHints`.
1397    pub fn default_window_hints(&mut self) {
1398        unsafe {
1399            ffi::glfwDefaultWindowHints();
1400        }
1401    }
1402
1403    /// Creates a new window.
1404    ///
1405    /// Wrapper for `glfwCreateWindow`.
1406    pub fn create_window(
1407        &mut self,
1408        width: u32,
1409        height: u32,
1410        title: &str,
1411        mode: WindowMode<'_>,
1412    ) -> Option<(PWindow, GlfwReceiver<(f64, WindowEvent)>)> {
1413        #[cfg(feature = "wayland")]
1414        {
1415            // Has to be set otherwise wayland refuses to open window.
1416            self.window_hint(WindowHint::Focused(false));
1417        }
1418        self.create_window_intern(width, height, title, mode, None)
1419    }
1420
1421    /// Internal wrapper for `glfwCreateWindow`.
1422    fn create_window_intern(
1423        &self,
1424        width: u32,
1425        height: u32,
1426        title: &str,
1427        mode: WindowMode<'_>,
1428        share: Option<&Window>,
1429    ) -> Option<(PWindow, GlfwReceiver<(f64, WindowEvent)>)> {
1430        let ptr = unsafe {
1431            with_c_str(title, |title| {
1432                ffi::glfwCreateWindow(
1433                    width as c_int,
1434                    height as c_int,
1435                    title,
1436                    mode.to_ptr(),
1437                    match share {
1438                        Some(w) => w.ptr,
1439                        None => ptr::null_mut(),
1440                    },
1441                )
1442            })
1443        };
1444        if ptr.is_null() {
1445            None
1446        } else {
1447            let (drop_sender, drop_receiver) = channel();
1448            let (sender, receiver) = glfw_channel(16, 256);
1449            let window = Window {
1450                ptr,
1451                glfw: self.clone(),
1452                is_shared: share.is_some(),
1453                drop_sender: Some(drop_sender),
1454                drop_receiver,
1455                current_cursor: None,
1456            };
1457            let mut callbacks = Box::new(WindowCallbacks::new(sender));
1458            let mut window = PWindow(Box::new(window));
1459
1460            unsafe {
1461                callbacks.window_ptr = window.raw_ptr();
1462                ffi::glfwSetWindowUserPointer(ptr, mem::transmute(callbacks));
1463            }
1464
1465            Some((window, receiver))
1466        }
1467    }
1468
1469    /// Makes the context of the specified window current. If no window is given
1470    /// then the current context is detached.
1471    ///
1472    /// Wrapper for `glfwMakeContextCurrent`.
1473    pub fn make_context_current(&mut self, context: Option<&Window>) {
1474        match context {
1475            Some(window) => unsafe { ffi::glfwMakeContextCurrent(window.ptr) },
1476            None => unsafe { ffi::glfwMakeContextCurrent(ptr::null_mut()) },
1477        }
1478    }
1479
1480    /// Wrapper for `glfwGetX11Display`
1481    #[cfg(all(target_os = "linux", not(feature = "wayland")))]
1482    pub fn get_x11_display(&self) -> *mut c_void {
1483        unsafe { ffi::glfwGetX11Display() }
1484    }
1485
1486    /// Wrapper for `glfwGetWaylandDisplay`
1487    #[cfg(all(target_os = "linux", feature = "wayland"))]
1488    pub fn get_wayland_display(&self) -> *mut c_void {
1489        unsafe { ffi::glfwGetWaylandDisplay() }
1490    }
1491
1492    /// Immediately process the received events.
1493    ///
1494    /// Wrapper for `glfwPollEvents`.
1495    pub fn poll_events(&mut self) {
1496        unsafe {
1497            ffi::glfwPollEvents();
1498        }
1499    }
1500
1501    /// Immediately process the received events. The *unbuffered* variant differs by allowing
1502    /// inspection of events *prior* to their associated native callback returning. This also
1503    /// provides a way to synchronously respond to the event. Events returned by the closure
1504    /// are delivered to the channel receiver just as if `poll_events` was called. Returning
1505    /// `None` from the closure will drop the event.
1506    ///
1507    /// Wrapper for `glfwPollEvents`.
1508    pub fn poll_events_unbuffered<F>(&mut self, mut f: F)
1509    where
1510        F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>,
1511    {
1512        let _unset_handler_guard = unsafe { crate::callbacks::unbuffered::set_handler(&mut f) };
1513        self.poll_events();
1514    }
1515
1516    /// Sleep until at least one event has been received, and then perform the
1517    /// equivalent of `Glfw::poll_events`.
1518    ///
1519    /// Wrapper for `glfwWaitEvents`.
1520    pub fn wait_events(&mut self) {
1521        unsafe {
1522            ffi::glfwWaitEvents();
1523        }
1524    }
1525
1526    /// Sleep until at least one event has been received, and then perform the
1527    /// equivalent of `Glfw::poll_events_unbuffered`.
1528    ///
1529    /// Wrapper for `glfwWaitEvents`.
1530    pub fn wait_events_unbuffered<F>(&mut self, mut f: F)
1531    where
1532        F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>,
1533    {
1534        let _unset_handler_guard = unsafe { crate::callbacks::unbuffered::set_handler(&mut f) };
1535        self.wait_events();
1536    }
1537
1538    /// Sleep until at least one event has been received, or until the specified
1539    /// timeout is reached, and then perform the equivalent of `Glfw::poll_events`.
1540    /// Timeout is specified in seconds.
1541    ///
1542    /// Wrapper for `glfwWaitEventsTimeout`.
1543    pub fn wait_events_timeout(&mut self, timeout: f64) {
1544        unsafe {
1545            ffi::glfwWaitEventsTimeout(timeout);
1546        }
1547    }
1548
1549    /// Sleep until at least one event has been received, or until the specified
1550    /// timeout is reached, and then perform the equivalent of `Glfw::poll_events_unbuffered`.
1551    /// Timeout is specified in seconds.
1552    ///
1553    /// Wrapper for `glfwWaitEventsTimeout`.
1554    pub fn wait_events_timeout_unbuffered<F>(&mut self, timeout: f64, mut f: F)
1555    where
1556        F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>,
1557    {
1558        let _unset_handler_guard = unsafe { crate::callbacks::unbuffered::set_handler(&mut f) };
1559        self.wait_events_timeout(timeout);
1560    }
1561
1562    /// Posts an empty event from the current thread to the event queue, causing
1563    /// `wait_events` or `wait_events_timeout` to return.
1564    /// If no windows exist, this function returns immediately.
1565    ///
1566    /// Wrapper for `glfwPostEmptyEvent`.
1567    pub fn post_empty_event(&self) {
1568        unsafe {
1569            ffi::glfwPostEmptyEvent();
1570        }
1571    }
1572
1573    /// Returns the current value of the GLFW timer. Unless the timer has been
1574    /// set using `glfw::set_time`, the timer measures time elapsed since GLFW
1575    /// was initialized.
1576    ///
1577    /// Wrapper for `glfwGetTime`.
1578    pub fn get_time(&self) -> f64 {
1579        unsafe { ffi::glfwGetTime() as f64 }
1580    }
1581
1582    /// Sets the value of the GLFW timer.
1583    ///
1584    /// Wrapper for `glfwSetTime`.
1585    pub fn set_time(&mut self, time: f64) {
1586        unsafe {
1587            ffi::glfwSetTime(time as c_double);
1588        }
1589    }
1590
1591    /// Wrapper for `glfwGetTimerValue`.
1592    pub fn get_timer_value(&self) -> u64 {
1593        unsafe { ffi::glfwGetTimerValue() as u64 }
1594    }
1595
1596    /// Wrapper for `glfwGetTimerFrequency`
1597    pub fn get_timer_frequency(&self) -> u64 {
1598        unsafe { ffi::glfwGetTimerFrequency() as u64 }
1599    }
1600
1601    /// Sets the number of screen updates to wait before swapping the buffers of
1602    /// the current context and returning from `Window::swap_buffers`.
1603    ///
1604    /// Wrapper for `glfwSwapInterval`.
1605    pub fn set_swap_interval(&mut self, interval: SwapInterval) {
1606        unsafe {
1607            ffi::glfwSwapInterval(match interval {
1608                SwapInterval::None => 0_i32,
1609                SwapInterval::Adaptive => -1_i32,
1610                SwapInterval::Sync(interval) => interval as c_int,
1611            })
1612        }
1613    }
1614
1615    /// Returns `true` if the specified OpenGL or context creation API extension
1616    /// is supported by the current context.
1617    ///
1618    /// Wrapper for `glfwExtensionSupported`.
1619    pub fn extension_supported(&self, extension: &str) -> bool {
1620        unsafe {
1621            with_c_str(extension, |extension| {
1622                ffi::glfwExtensionSupported(extension) == ffi::TRUE
1623            })
1624        }
1625    }
1626
1627    /// Wrapper for `glfwGetRequiredInstanceExtensions`
1628    ///
1629    /// This function returns a Vector of names of Vulkan instance extensions
1630    /// required by GLFW for creating Vulkan surfaces for GLFW windows. If successful,
1631    /// the list will always contains `VK_KHR_surface`, so if you don't require any
1632    /// additional extensions you can pass this list directly to the `VkInstanceCreateInfo` struct.
1633    ///
1634    /// Will return `None` if the API is unavailable.
1635    #[cfg(feature = "vulkan")]
1636    pub fn get_required_instance_extensions(&self) -> Option<Vec<String>> {
1637        let mut len: c_uint = 0;
1638
1639        unsafe {
1640            let raw_extensions: *const *const c_char =
1641                ffi::glfwGetRequiredInstanceExtensions(&mut len as *mut c_uint);
1642
1643            if !raw_extensions.is_null() {
1644                return Some(
1645                    slice::from_raw_parts(raw_extensions, len as usize)
1646                        .iter()
1647                        .map(|extensions| string_from_c_str(*extensions))
1648                        .collect(),
1649                );
1650            }
1651        }
1652
1653        None
1654    }
1655
1656    /// Returns the address of the specified client API or extension function if
1657    /// it is supported by the current context, NULL otherwise.
1658    ///
1659    /// Wrapper for `glfwGetProcAddress`.
1660    pub fn get_proc_address_raw(&self, procname: &str) -> GLProc {
1661        debug_assert!(unsafe { ffi::glfwGetCurrentContext() } != std::ptr::null_mut());
1662        with_c_str(procname, |procname| unsafe {
1663            ffi::glfwGetProcAddress(procname)
1664        })
1665    }
1666
1667    /// This function returns the address of the specified Vulkan core or extension function
1668    /// for the specified instance. If instance is set to NULL it can return any function
1669    /// exported from the Vulkan loader, including at least the following functions:
1670    ///
1671    /// * `vkEnumerateInstanceExtensionProperties`
1672    /// * `vkEnumerateInstanceLayerProperties`
1673    /// * `vkCreateInstance`
1674    /// * `vkGetInstanceProcAddr`
1675    ///
1676    /// If Vulkan is not available on the machine, this function returns `NULL`
1677    ///
1678    /// Wrapper for `glfwGetInstanceProcAddress`
1679    #[cfg(feature = "vulkan")]
1680    pub fn get_instance_proc_address_raw(&self, instance: vk::Instance, procname: &str) -> VkProc {
1681        with_c_str(procname, |procname| unsafe {
1682            ffi::glfwGetInstanceProcAddress(instance, procname)
1683        })
1684    }
1685
1686    /// This function returns whether the specified queue family of the specified
1687    /// physical device supports presentation to the platform GLFW was built for.
1688    ///
1689    /// Wrapper for `glfwGetPhysicalDevicePresentationSupport`
1690    #[cfg(feature = "vulkan")]
1691    pub fn get_physical_device_presentation_support_raw(
1692        &self,
1693        instance: vk::Instance,
1694        device: vk::PhysicalDevice,
1695        queue_family: u32,
1696    ) -> bool {
1697        vk::TRUE
1698            == unsafe {
1699                ffi::glfwGetPhysicalDevicePresentationSupport(
1700                    instance,
1701                    device,
1702                    queue_family as c_uint,
1703                ) as u32
1704            }
1705    }
1706
1707    /// Constructs a `Joystick` handle corresponding to the supplied `JoystickId`.
1708    pub fn get_joystick(&self, id: JoystickId) -> Joystick {
1709        Joystick {
1710            id,
1711            glfw: self.clone(),
1712        }
1713    }
1714
1715    /// Wrapper for `glfwRawMouseMotionSupported`.
1716    pub fn supports_raw_motion(&self) -> bool {
1717        unsafe { ffi::glfwRawMouseMotionSupported() == ffi::TRUE }
1718    }
1719
1720    /// Parses the specified ASCII encoded string and updates the internal list with any gamepad
1721    /// mappings it finds. This string may contain either a single gamepad mapping or many mappings
1722    /// separated by newlines. The parser supports the full format of the `gamecontrollerdb.txt`
1723    /// source file including empty lines and comments.
1724    ///
1725    /// Wrapper for `glfwUpdateGamepadMappings`.
1726    ///
1727    /// # Returns
1728    ///
1729    /// `true` if successful, or `false` if an error occurred.
1730    pub fn update_gamepad_mappings(&self, mappings: &str) -> bool {
1731        unsafe {
1732            with_c_str(mappings, |mappings| {
1733                ffi::glfwUpdateGamepadMappings(mappings) == ffi::TRUE
1734            })
1735        }
1736    }
1737}
1738
1739impl Clone for Glfw {
1740    fn clone(&self) -> Self {
1741        REF_COUNT_FOR_GLFW.fetch_add(1, Ordering::SeqCst);
1742        Glfw {
1743            phantom: std::marker::PhantomData,
1744        }
1745    }
1746}
1747
1748impl Drop for Glfw {
1749    fn drop(&mut self) {
1750        let old_diff = REF_COUNT_FOR_GLFW.fetch_sub(1, Ordering::SeqCst);
1751        if old_diff == 1 {
1752            unsafe {
1753                ffi::glfwTerminate();
1754            }
1755        }
1756    }
1757}
1758
1759fn glfw_channel<T>(initial_capacity: usize, max_len: usize) -> (GlfwSender<T>, GlfwReceiver<T>) {
1760    let shared = Arc::new(SharedTransmitter {
1761        queue: Mutex::new(VecDeque::with_capacity(initial_capacity)),
1762        max_len,
1763    });
1764    let (mpsc_sender, mpsc_receiver) = channel();
1765
1766    let sender = GlfwSender {
1767        transmitter: shared.clone(),
1768        sender: mpsc_sender,
1769    };
1770    let receiver = GlfwReceiver {
1771        transmitter: shared.clone(),
1772        receiver: mpsc_receiver,
1773    };
1774    (sender, receiver)
1775}
1776
1777#[derive(Debug)]
1778struct SharedTransmitter<T> {
1779    queue: Mutex<VecDeque<T>>,
1780    max_len: usize,
1781}
1782
1783#[derive(Debug, Clone)]
1784struct GlfwSender<T> {
1785    transmitter: Arc<SharedTransmitter<T>>,
1786    sender: Sender<T>,
1787}
1788
1789impl<T> GlfwSender<T> {
1790    fn send(&self, v: T) {
1791        let mut queue = self.transmitter.queue.lock().unwrap();
1792        if queue.len() >= self.transmitter.max_len {
1793            let _ = self.sender.send(v);
1794        } else {
1795            queue.push_back(v);
1796        }
1797    }
1798}
1799
1800#[derive(Debug)]
1801pub struct GlfwReceiver<T> {
1802    transmitter: Arc<SharedTransmitter<T>>,
1803    receiver: Receiver<T>,
1804}
1805
1806impl<T> GlfwReceiver<T> {
1807    pub fn receive(&self) -> Option<T> {
1808        let ret = self.transmitter.queue.lock().unwrap().pop_front();
1809        if ret.is_some() {
1810            ret
1811        } else {
1812            match self.receiver.try_recv() {
1813                Ok(ret) => Some(ret),
1814                Err(_) => None,
1815            }
1816        }
1817    }
1818}
1819
1820struct WindowCallbacks {
1821    window_ptr: *mut Window,
1822    sender: GlfwSender<(f64, WindowEvent)>,
1823    pos_callback: Option<Box<dyn FnMut(&mut Window, i32, i32)>>,
1824    size_callback: Option<Box<dyn FnMut(&mut Window, i32, i32)>>,
1825    close_callback: Option<Box<dyn FnMut(&mut Window)>>,
1826    refresh_callback: Option<Box<dyn FnMut(&mut Window)>>,
1827    focus_callback: Option<Box<dyn FnMut(&mut Window, bool)>>,
1828    iconify_callback: Option<Box<dyn FnMut(&mut Window, bool)>>,
1829    framebuffer_size_callback: Option<Box<dyn FnMut(&mut Window, i32, i32)>>,
1830    key_callback: Option<Box<dyn FnMut(&mut Window, Key, Scancode, Action, Modifiers)>>,
1831    char_callback: Option<Box<dyn FnMut(&mut Window, char)>>,
1832    char_mods_callback: Option<Box<dyn FnMut(&mut Window, char, Modifiers)>>,
1833    mouse_button_callback: Option<Box<dyn FnMut(&mut Window, MouseButton, Action, Modifiers)>>,
1834    cursor_pos_callback: Option<Box<dyn FnMut(&mut Window, f64, f64)>>,
1835    cursor_enter_callback: Option<Box<dyn FnMut(&mut Window, bool)>>,
1836    scroll_callback: Option<Box<dyn FnMut(&mut Window, f64, f64)>>,
1837    drag_and_drop_callback: Option<Box<dyn FnMut(&mut Window, Vec<PathBuf>)>>,
1838    maximize_callback: Option<Box<dyn FnMut(&mut Window, bool)>>,
1839    content_scale_callback: Option<Box<dyn FnMut(&mut Window, f32, f32)>>,
1840    pos_polling: bool,
1841    size_polling: bool,
1842    close_polling: bool,
1843    refresh_polling: bool,
1844    focus_polling: bool,
1845    iconify_polling: bool,
1846    framebuffer_size_polling: bool,
1847    key_polling: bool,
1848    char_polling: bool,
1849    char_mods_polling: bool,
1850    mouse_button_polling: bool,
1851    cursor_pos_polling: bool,
1852    cursor_enter_polling: bool,
1853    scroll_polling: bool,
1854    drag_and_drop_polling: bool,
1855    maximize_polling: bool,
1856    content_scale_polling: bool,
1857}
1858
1859impl WindowCallbacks {
1860    fn new(sender: GlfwSender<(f64, WindowEvent)>) -> Self {
1861        Self {
1862            window_ptr: std::ptr::null_mut(),
1863            sender,
1864            pos_callback: None,
1865            size_callback: None,
1866            close_callback: None,
1867            refresh_callback: None,
1868            focus_callback: None,
1869            iconify_callback: None,
1870            framebuffer_size_callback: None,
1871            key_callback: None,
1872            char_callback: None,
1873            char_mods_callback: None,
1874            mouse_button_callback: None,
1875            cursor_pos_callback: None,
1876            cursor_enter_callback: None,
1877            scroll_callback: None,
1878            drag_and_drop_callback: None,
1879            maximize_callback: None,
1880            content_scale_callback: None,
1881            pos_polling: false,
1882            size_polling: false,
1883            close_polling: false,
1884            refresh_polling: false,
1885            focus_polling: false,
1886            iconify_polling: false,
1887            framebuffer_size_polling: false,
1888            key_polling: false,
1889            char_polling: false,
1890            char_mods_polling: false,
1891            mouse_button_polling: false,
1892            cursor_pos_polling: false,
1893            cursor_enter_polling: false,
1894            scroll_polling: false,
1895            drag_and_drop_polling: false,
1896            maximize_polling: false,
1897            content_scale_polling: false,
1898        }
1899    }
1900
1901    fn get_callbacks<'a>(window: *mut GLFWwindow) -> &'a mut WindowCallbacks {
1902        unsafe { &mut *(ffi::glfwGetWindowUserPointer(window) as *mut WindowCallbacks) }
1903    }
1904}
1905
1906/// Wrapper for `glfwGetError`.
1907pub fn get_error() -> Error {
1908    unsafe { mem::transmute(ffi::glfwGetError(null_mut())) }
1909}
1910
1911/// Wrapper for `glfwGetError`.
1912pub fn get_error_string() -> (Error, String) {
1913    unsafe {
1914        let mut description: *const c_char = null();
1915        let error: Error = mem::transmute(ffi::glfwGetError(&mut description));
1916        (error, string_from_c_str(description))
1917    }
1918}
1919
1920/// Wrapper for `glfwGetVersion`.
1921pub fn get_version() -> Version {
1922    unsafe {
1923        let mut major = 0;
1924        let mut minor = 0;
1925        let mut patch = 0;
1926        ffi::glfwGetVersion(&mut major, &mut minor, &mut patch);
1927        Version {
1928            major: major as u64,
1929            minor: minor as u64,
1930            patch: patch as u64,
1931        }
1932    }
1933}
1934
1935/// Replacement for `String::from_raw_buf`
1936pub unsafe fn string_from_c_str(c_str: *const c_char) -> String {
1937    String::from_utf8_lossy(CStr::from_ptr(c_str).to_bytes()).into_owned()
1938}
1939
1940/// Like `string_from_c_str`, but handles null pointers correctly
1941pub unsafe fn string_from_nullable_c_str(c_str: *const c_char) -> Option<String> {
1942    if c_str.is_null() {
1943        None
1944    } else {
1945        Some(string_from_c_str(c_str))
1946    }
1947}
1948
1949/// Replacement for `ToCStr::with_c_str`
1950pub fn with_c_str<F, T>(s: &str, f: F) -> T
1951where
1952    F: FnOnce(*const c_char) -> T,
1953{
1954    let c_str = CString::new(s.as_bytes());
1955    f(c_str.unwrap().as_bytes_with_nul().as_ptr() as *const _)
1956}
1957
1958/// Wrapper for `glfwGetVersionString`.
1959pub fn get_version_string() -> String {
1960    unsafe { string_from_c_str(ffi::glfwGetVersionString()) }
1961}
1962
1963/// A struct that wraps a `*GLFWmonitor` handle.
1964#[allow(missing_copy_implementations)]
1965pub struct Monitor {
1966    ptr: *mut ffi::GLFWmonitor,
1967}
1968
1969impl std::fmt::Debug for Monitor {
1970    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1971        write!(f, "Monitor({:p})", self.ptr)
1972    }
1973}
1974
1975impl Monitor {
1976    /// Wrapper for `glfwGetMonitorPos`.
1977    pub fn get_pos(&self) -> (i32, i32) {
1978        unsafe {
1979            let mut xpos = 0;
1980            let mut ypos = 0;
1981            ffi::glfwGetMonitorPos(self.ptr, &mut xpos, &mut ypos);
1982            (xpos as i32, ypos as i32)
1983        }
1984    }
1985
1986    /// Wrapper for `glfwGetMonitorPhysicalSize`.
1987    pub fn get_physical_size(&self) -> (i32, i32) {
1988        unsafe {
1989            let mut width = 0;
1990            let mut height = 0;
1991            ffi::glfwGetMonitorPhysicalSize(self.ptr, &mut width, &mut height);
1992            (width as i32, height as i32)
1993        }
1994    }
1995
1996    /// Wrapper for `glfwGetMonitorName`.
1997    pub fn get_name(&self) -> Option<String> {
1998        unsafe { string_from_nullable_c_str(ffi::glfwGetMonitorName(self.ptr)) }
1999    }
2000
2001    /// Wrapper for `glfwGetVideoModes`.
2002    pub fn get_video_modes(&self) -> Vec<VidMode> {
2003        unsafe {
2004            let mut count = 0;
2005            let ptr = ffi::glfwGetVideoModes(self.ptr, &mut count);
2006            slice::from_raw_parts(ptr, count as usize)
2007                .iter()
2008                .map(VidMode::from_glfw_vid_mode)
2009                .collect()
2010        }
2011    }
2012
2013    /// Wrapper for `glfwGetVideoMode`.
2014    pub fn get_video_mode(&self) -> Option<VidMode> {
2015        unsafe {
2016            // TODO: Can be returned to as_ref + map as in previous commit when (if?) as_ref
2017            // stabilizes.
2018            let ptr = ffi::glfwGetVideoMode(self.ptr);
2019            if ptr.is_null() {
2020                None
2021            } else {
2022                Some(VidMode::from_glfw_vid_mode(&*ptr))
2023            }
2024        }
2025    }
2026
2027    /// Wrapper for `glfwSetGamma`.
2028    pub fn set_gamma(&mut self, gamma: f32) {
2029        unsafe {
2030            ffi::glfwSetGamma(self.ptr, gamma as c_float);
2031        }
2032    }
2033
2034    /// Wrapper for `glfwGetGammaRamp`.
2035    pub fn get_gamma_ramp(&self) -> GammaRamp {
2036        unsafe {
2037            let llramp = *ffi::glfwGetGammaRamp(self.ptr);
2038            GammaRamp {
2039                red: slice::from_raw_parts(llramp.red as *const c_ushort, llramp.size as usize)
2040                    .iter()
2041                    .copied()
2042                    .collect(),
2043                green: slice::from_raw_parts(llramp.green as *const c_ushort, llramp.size as usize)
2044                    .iter()
2045                    .copied()
2046                    .collect(),
2047                blue: slice::from_raw_parts(llramp.blue as *const c_ushort, llramp.size as usize)
2048                    .iter()
2049                    .copied()
2050                    .collect(),
2051            }
2052        }
2053    }
2054
2055    /// Wrapper for `glfwSetGammaRamp`.
2056    pub fn set_gamma_ramp(&mut self, ramp: &mut GammaRamp) {
2057        unsafe {
2058            ffi::glfwSetGammaRamp(
2059                self.ptr,
2060                &ffi::GLFWgammaramp {
2061                    red: ramp.red.as_mut_ptr(),
2062                    green: ramp.green.as_mut_ptr(),
2063                    blue: ramp.blue.as_mut_ptr(),
2064                    size: ramp.red.len() as u32,
2065                },
2066            );
2067        }
2068    }
2069
2070    /// Wrapper for `glfwGetMonitorContentScale`.
2071    pub fn get_content_scale(&self) -> (f32, f32) {
2072        unsafe {
2073            let mut xscale = 0.0_f32;
2074            let mut yscale = 0.0_f32;
2075            ffi::glfwGetMonitorContentScale(self.ptr, &mut xscale, &mut yscale);
2076            (xscale, yscale)
2077        }
2078    }
2079
2080    /// Wrapper for `glfwGetMonitorWorkarea`.
2081    pub fn get_workarea(&self) -> (i32, i32, i32, i32) {
2082        unsafe {
2083            let mut xpos = 0;
2084            let mut ypos = 0;
2085            let mut width = 0;
2086            let mut height = 0;
2087            ffi::glfwGetMonitorWorkarea(self.ptr, &mut xpos, &mut ypos, &mut width, &mut height);
2088            (xpos, ypos, width, height)
2089        }
2090    }
2091}
2092
2093/// Monitor events.
2094#[repr(i32)]
2095#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2096#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2097pub enum MonitorEvent {
2098    Connected = ffi::CONNECTED,
2099    Disconnected = ffi::DISCONNECTED,
2100}
2101
2102impl VidMode {
2103    fn from_glfw_vid_mode(mode: &ffi::GLFWvidmode) -> VidMode {
2104        VidMode {
2105            width: mode.width as u32,
2106            height: mode.height as u32,
2107            red_bits: mode.redBits as u32,
2108            green_bits: mode.greenBits as u32,
2109            blue_bits: mode.blueBits as u32,
2110            refresh_rate: mode.refreshRate as u32,
2111        }
2112    }
2113}
2114
2115impl fmt::Debug for VidMode {
2116    /// Returns a string representation of the video mode.
2117    ///
2118    /// # Returns
2119    ///
2120    /// A string in the form:
2121    ///
2122    /// ~~~ignore
2123    /// ~"[width] x [height], [total_bits] ([red_bits] [green_bits] [blue_bits]) [refresh_rate] Hz"
2124    /// ~~~
2125    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2126        write!(
2127            f,
2128            "{} x {}, {} = {} + {} + {}, {} Hz",
2129            self.width,
2130            self.height,
2131            self.red_bits + self.green_bits + self.blue_bits,
2132            self.red_bits,
2133            self.green_bits,
2134            self.blue_bits,
2135            self.refresh_rate
2136        )
2137    }
2138}
2139
2140/// Window hints that can be set using the `window_hint` function.
2141#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2142#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2143pub enum WindowHint {
2144    /// Specifies the desired bit depth of the red component of the default framebuffer.
2145    RedBits(Option<u32>),
2146    /// Specifies the desired bit depth of the green component of the default framebuffer.
2147    GreenBits(Option<u32>),
2148    /// Specifies the desired bit depth of the blue component of the default framebuffer.
2149    BlueBits(Option<u32>),
2150    /// Specifies the desired bit depth of the alpha component of the default framebuffer.
2151    AlphaBits(Option<u32>),
2152    /// Specifies the desired bit depth of the depth component of the default framebuffer.
2153    DepthBits(Option<u32>),
2154    /// Specifies the desired bit depth of the stencil component of the default framebuffer.
2155    StencilBits(Option<u32>),
2156    /// Specifies the desired bit depth of the red component of the accumulation framebuffer.
2157    AccumRedBits(Option<u32>),
2158    /// Specifies the desired bit depth of the green component of the accumulation framebuffer.
2159    AccumGreenBits(Option<u32>),
2160    /// Specifies the desired bit depth of the blue component of the accumulation framebuffer.
2161    AccumBlueBits(Option<u32>),
2162    /// Specifies the desired bit depth of the alpha component of the accumulation framebuffer.
2163    AccumAlphaBits(Option<u32>),
2164    /// Specifies the desired number of auxiliary buffers.
2165    AuxBuffers(Option<u32>),
2166    /// Specifies whether to use stereoscopic rendering.
2167    Stereo(bool),
2168    /// Specifies the desired number of samples to use for multisampling. Zero
2169    /// disables multisampling.
2170    Samples(Option<u32>),
2171    /// Specifies whether the framebuffer should be sRGB capable.
2172    SRgbCapable(bool),
2173    /// Specifies the desired refresh rate for full screen windows. If set to `None`,
2174    /// the highest available refresh rate will be used.
2175    ///
2176    /// This hint is ignored for windowed mode windows.
2177    RefreshRate(Option<u32>),
2178    /// Specifies which `ClientApi` to create the context for.
2179    ClientApi(ClientApiHint),
2180    /// Specifies the major client API version that the created context must be
2181    /// compatible with.
2182    ///
2183    /// Window creation will fail if the resulting OpenGL version is less than
2184    /// the one requested.
2185    ContextVersionMajor(u32),
2186    /// Specifies the minor client API version that the created context must be
2187    /// compatible with.
2188    ///
2189    /// Window creation will fail if the resulting OpenGL version is less than
2190    /// the one requested.
2191    ContextVersionMinor(u32),
2192    /// Specifies the client API version that the created context must be
2193    /// compatible with. This is the same as successive calls to `window_hint`
2194    /// function with the `ContextVersionMajor` and `ContextVersionMinor` hints.
2195    ///
2196    /// Window creation will fail if the resulting OpenGL version is less than
2197    /// the one requested.
2198    ///
2199    /// If `ContextVersion(1, 0)` is requested, _most_ drivers will provide the
2200    /// highest available context.
2201    ContextVersion(u32, u32),
2202    /// Specifies the `ContextRobustness` strategy to be used.
2203    ContextRobustness(ContextRobustnessHint),
2204    /// Specifies whether the OpenGL context should be forward-compatible, i.e.
2205    /// one where all functionality deprecated in the requested version of
2206    /// OpenGL is removed. This may only be used if the requested OpenGL version
2207    /// is 3.0 or above.
2208    ///
2209    /// If another client API is requested, this hint is ignored.
2210    OpenGlForwardCompat(bool),
2211    /// Specifies whether to create a debug OpenGL context, which may have
2212    /// additional error and performance issue reporting functionality.
2213    ///
2214    /// If another client API is requested, this hint is ignored.
2215    OpenGlDebugContext(bool),
2216    /// Specifies which OpenGL profile to create the context for. If requesting
2217    /// an OpenGL version below 3.2, `OpenGlAnyProfile` must be used.
2218    ///
2219    /// If another client API is requested, this hint is ignored.
2220    OpenGlProfile(OpenGlProfileHint),
2221    /// Specifies whether the window will be resizable by the user. Even if this
2222    /// is set to `false`, the window can still be resized using the
2223    /// `Window::set_size` function.
2224    ///
2225    /// This hint is ignored for fullscreen windows.
2226    Resizable(bool),
2227    /// Specifies whether the window will be visible on creation.
2228    ///
2229    /// This hint is ignored for fullscreen windows.
2230    Visible(bool),
2231    /// Specifies whether the window will have platform-specific decorations
2232    /// such as a border, a close widget, etc.
2233    ///
2234    /// This hint is ignored for full screen windows.
2235    Decorated(bool),
2236    /// Specifies whether the (full screen) window will automatically iconify
2237    /// and restore the previous video mode on input focus loss.
2238    ///
2239    /// This hint is ignored for windowed mode windows.
2240    AutoIconify(bool),
2241    /// Specifies whether the window will be floating above other regular
2242    /// windows, also called topmost or always-on-top.
2243    ///
2244    /// This hint is ignored for full screen windows.
2245    Floating(bool),
2246    /// Specifies whether the windowed mode window will be given input focus when created.
2247    ///
2248    /// This hint is ignored for full screen and initially hidden windows.
2249    Focused(bool),
2250    /// Specifies whether the windowed mode window will be maximized when created.
2251    ///
2252    /// This hint is ignored for full screen windows.
2253    Maximized(bool),
2254    /// Specifies whether the OpenGL or OpenGL ES contexts do not emit errors,
2255    /// allowing for better performance in some situations.
2256    ContextNoError(bool),
2257    /// Specifies which context creation API to use to create the context.
2258    ContextCreationApi(ContextCreationApi),
2259    /// Specifies the behavior of the OpenGL pipeline when a context is transferred between threads
2260    ContextReleaseBehavior(ContextReleaseBehavior),
2261    /// Specifies whether the framebuffer should be double buffered.
2262    ///
2263    /// You nearly always want to use double buffering.
2264    ///
2265    /// Note that setting this to false will make `swap_buffers` do nothing useful,
2266    /// and your scene will have to be displayed some other way.
2267    DoubleBuffer(bool),
2268    /// Speficies whether the cursor should be centered over newly created full screen windows.
2269    ///
2270    /// This hint is ignored for windowed mode windows.
2271    CenterCursor(bool),
2272    /// Specifies whether the window framebuffer will be transparent.
2273    ///
2274    /// If enabled and supported by the system, the window framebuffer alpha channel will be used
2275    /// to combine the framebuffer with the background. This does not affect window decorations.
2276    TransparentFramebuffer(bool),
2277    /// Specifies whether the window will be given input focus when `Window::show` is called.
2278    FocusOnShow(bool),
2279    /// Specifies whether the window content area should be resized based on the monitor current
2280    /// scale of any monitor it is placed on.
2281    ///
2282    /// This includes the initial placement when the window is created.
2283    ScaleToMonitor(bool),
2284    /// Specifies whether to use full resolution framebuffers on Retina displays.
2285    ///
2286    /// This is ignored on platforms besides macOS.
2287    CocoaRetinaFramebuffer(bool),
2288    /// Specifies the UTF-8 encoded name to use for autosaving the window frame, or if empty
2289    /// disables frame autosaving for the window.
2290    ///
2291    /// This is ignored on platforms besides macOS.
2292    CocoaFrameName(Option<String>),
2293    /// Specifies whether to in participate in Automatic Graphics Switching, i.e. to allow the
2294    /// system to choose the integrated GPU for the OpenGL context and move it between GPUs if
2295    /// necessary or whether to force it to always run on the discrete GPU.
2296    ///
2297    /// Simpler programs and tools may want to enable this to save power, while games and other
2298    /// applications performing advanced rendering will want to leave it disabled.
2299    //
2300    //  A bundled application that wishes to participate in Automatic Graphics Switching should also
2301    // declare this in its `Info.plist` by setting the `NSSupportsAutomaticGraphicsSwitching` key to
2302    // `true`.
2303    ///
2304    /// This only affects systems with both integrated and discrete GPUs. This is ignored on
2305    /// platforms besides macOS.
2306    CocoaGraphicsSwitching(bool),
2307    /// Specifies the desired ASCII-encoded class part of the ICCCM `WM_CLASS` window property.
2308    X11ClassName(Option<String>),
2309    /// Specifies the desired ASCII-encoded instance part of the ICCCM `WM_CLASS` window property.
2310    X11InstanceName(Option<String>),
2311}
2312
2313/// Client API tokens.
2314#[repr(i32)]
2315#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2316#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2317pub enum ClientApiHint {
2318    NoApi = ffi::NO_API,
2319    OpenGl = ffi::OPENGL_API,
2320    OpenGlEs = ffi::OPENGL_ES_API,
2321}
2322
2323/// Context robustness tokens.
2324#[repr(i32)]
2325#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2326#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2327pub enum ContextRobustnessHint {
2328    NoRobustness = ffi::NO_ROBUSTNESS,
2329    NoResetNotification = ffi::NO_RESET_NOTIFICATION,
2330    LoseContextOnReset = ffi::LOSE_CONTEXT_ON_RESET,
2331}
2332
2333/// OpenGL profile tokens.
2334#[repr(i32)]
2335#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2336#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2337pub enum OpenGlProfileHint {
2338    Any = ffi::OPENGL_ANY_PROFILE,
2339    Core = ffi::OPENGL_CORE_PROFILE,
2340    Compat = ffi::OPENGL_COMPAT_PROFILE,
2341}
2342
2343/// Describes the mode of a window
2344#[derive(Copy, Clone, Debug)]
2345pub enum WindowMode<'a> {
2346    /// Full screen mode. Contains the monitor on which the window is displayed.
2347    FullScreen(&'a Monitor),
2348
2349    /// Windowed mode.
2350    Windowed,
2351}
2352
2353/// Private conversion methods for `glfw::WindowMode`
2354impl<'a> WindowMode<'a> {
2355    /// Returns a pointer to a monitor if the window is fullscreen, otherwise
2356    /// it returns a null pointer (if it is in windowed mode).
2357    fn to_ptr(&self) -> *mut ffi::GLFWmonitor {
2358        match *self {
2359            WindowMode::FullScreen(monitor) => monitor.ptr,
2360            WindowMode::Windowed => ptr::null_mut(),
2361        }
2362    }
2363}
2364
2365bitflags! {
2366    #[doc = "Key modifiers (e.g., Shift, Control, Alt, Super)"]
2367    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2368    pub struct Modifiers: ::std::os::raw::c_int {
2369        const Shift       = crate::ffi::MOD_SHIFT;
2370        const Control     = crate::ffi::MOD_CONTROL;
2371        const Alt         = crate::ffi::MOD_ALT;
2372        const Super       = crate::ffi::MOD_SUPER;
2373        const CapsLock    = crate::ffi::MOD_CAPS_LOCK;
2374        const NumLock     = crate::ffi::MOD_NUM_LOCK;
2375    }
2376}
2377
2378/// Keyboard code returned by the OS
2379pub type Scancode = c_int;
2380
2381/// Window event messages.
2382#[derive(Clone, PartialEq, PartialOrd, Debug)]
2383#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2384pub enum WindowEvent {
2385    Pos(i32, i32),
2386    Size(i32, i32),
2387    Close,
2388    Refresh,
2389    Focus(bool),
2390    Iconify(bool),
2391    FramebufferSize(i32, i32),
2392    MouseButton(MouseButton, Action, Modifiers),
2393    CursorPos(f64, f64),
2394    CursorEnter(bool),
2395    Scroll(f64, f64),
2396    Key(Key, Scancode, Action, Modifiers),
2397    Char(char),
2398    CharModifiers(char, Modifiers),
2399    FileDrop(Vec<PathBuf>),
2400    Maximize(bool),
2401    ContentScale(f32, f32),
2402}
2403
2404/// Returns an iterator that yields until no more messages are contained in the
2405/// `Receiver`'s queue. This is useful for event handling where the blocking
2406/// behaviour of `Receiver::iter` is undesirable.
2407///
2408/// # Example
2409///
2410/// ~~~ignore
2411/// for event in glfw::flush_messages(&events) {
2412///     // handle event
2413/// }
2414/// ~~~
2415pub fn flush_messages<Message: Send>(
2416    receiver: &GlfwReceiver<Message>,
2417) -> FlushedMessages<'_, Message> {
2418    FlushedMessages(receiver)
2419}
2420
2421/// An iterator that yields until no more messages are contained in the
2422/// `Receiver`'s queue.
2423#[derive(Debug)]
2424pub struct FlushedMessages<'a, Message: Send>(&'a GlfwReceiver<Message>);
2425
2426unsafe impl<'a, Message: 'a + Send> Send for FlushedMessages<'a, Message> {}
2427
2428impl<'a, Message: 'static + Send> Iterator for FlushedMessages<'a, Message> {
2429    type Item = Message;
2430
2431    fn next(&mut self) -> Option<Message> {
2432        let FlushedMessages(receiver) = *self;
2433        receiver.receive()
2434    }
2435}
2436
2437/// A struct that wraps a `*GLFWwindow` handle.
2438#[derive(Debug)]
2439pub struct Window {
2440    ptr: *mut ffi::GLFWwindow,
2441    pub is_shared: bool,
2442    /// A `Sender` that can be cloned out to child `RenderContext`s.
2443    drop_sender: Option<Sender<()>>,
2444    /// Once all  child`RenderContext`s have been dropped, calling `try_recv()`
2445    /// on the `drop_receiver` will result in an `Err(std::comm::Disconnected)`,
2446    /// indicating that it is safe to drop the `Window`.
2447    #[allow(unused)]
2448    drop_receiver: Receiver<()>,
2449    /// This is here to allow owning the current Cursor object instead
2450    /// of forcing the user to take care of its lifetime.
2451    current_cursor: Option<Cursor>,
2452    pub glfw: Glfw,
2453}
2454
2455impl Window {
2456    /// Returns the address of the specified client API or extension function if
2457    /// it is supported by the context associated with this Window. If this Window is not the
2458    /// current context, it will make it the current context.
2459    ///
2460    /// Wrapper for `glfwGetProcAddress`.
2461    pub fn get_proc_address(&mut self, procname: &str) -> GLProc {
2462        if self.ptr != unsafe { ffi::glfwGetCurrentContext() } {
2463            self.make_current();
2464        }
2465
2466        self.glfw.get_proc_address_raw(procname)
2467    }
2468
2469    /// This function returns the address of the specified Vulkan core or extension function
2470    /// for the specified instance. If instance is set to NULL it can return any function
2471    /// exported from the Vulkan loader, including at least the following functions:
2472    ///
2473    /// * `vkEnumerateInstanceExtensionProperties`
2474    /// * `vkEnumerateInstanceLayerProperties`
2475    /// * `vkCreateInstance`
2476    /// * `vkGetInstanceProcAddr`
2477    ///
2478    /// If Vulkan is not available on the machine, this function returns `NULL`
2479    ///
2480    /// Wrapper for `glfwGetInstanceProcAddress`
2481    #[cfg(feature = "vulkan")]
2482    pub fn get_instance_proc_address(&mut self, instance: vk::Instance, procname: &str) -> VkProc {
2483        self.glfw.get_instance_proc_address_raw(instance, procname)
2484    }
2485
2486    /// This function returns whether the specified queue family of the specified
2487    /// physical device supports presentation to the platform GLFW was built for.
2488    ///
2489    /// Wrapper for `glfwGetPhysicalDevicePresentationSupport`
2490    #[cfg(feature = "vulkan")]
2491    pub fn get_physical_device_presentation_support(
2492        &self,
2493        instance: vk::Instance,
2494        device: vk::PhysicalDevice,
2495        queue_family: u32,
2496    ) -> bool {
2497        self.glfw
2498            .get_physical_device_presentation_support_raw(instance, device, queue_family)
2499    }
2500
2501    /// wrapper for `glfwCreateWindowSurface`
2502    #[cfg(feature = "vulkan")]
2503    pub fn create_window_surface(
2504        &self,
2505        instance: vk::Instance,
2506        allocator: *const vk::AllocationCallbacks<'_>,
2507        surface: *mut vk::SurfaceKHR,
2508    ) -> vk::Result {
2509        unsafe { ffi::glfwCreateWindowSurface(instance, self.ptr, allocator, surface) }
2510    }
2511
2512    /// Creates a new shared window.
2513    ///
2514    /// Wrapper for `glfwCreateWindow`.
2515    pub fn create_shared(
2516        &self,
2517        width: u32,
2518        height: u32,
2519        title: &str,
2520        mode: WindowMode<'_>,
2521    ) -> Option<(PWindow, GlfwReceiver<(f64, WindowEvent)>)> {
2522        self.glfw
2523            .create_window_intern(width, height, title, mode, Some(self))
2524    }
2525
2526    /// Calling this method forces the destructor to be called, closing the
2527    /// window.
2528    pub fn close(self) {}
2529
2530    /// Returns a render context that can be shared between tasks, allowing
2531    /// for concurrent rendering.
2532    pub fn render_context(&mut self) -> PRenderContext {
2533        PRenderContext(Box::new(RenderContext {
2534            ptr: self.ptr,
2535            glfw: self.glfw.clone(),
2536            // this will only be None after dropping so this is safe
2537            drop_sender: self.drop_sender.as_ref().unwrap().clone(),
2538        }))
2539    }
2540
2541    /// Wrapper for `glfwWindowShouldClose`.
2542    pub fn should_close(&self) -> bool {
2543        unsafe { ffi::glfwWindowShouldClose(self.ptr) == ffi::TRUE }
2544    }
2545
2546    /// Wrapper for `glfwSetWindowShouldClose`.
2547    pub fn set_should_close(&mut self, value: bool) {
2548        unsafe { ffi::glfwSetWindowShouldClose(self.ptr, value as c_int) }
2549    }
2550
2551    /// Sets the title of the window.
2552    ///
2553    /// Wrapper for `glfwSetWindowTitle`.
2554    pub fn set_title(&mut self, title: &str) {
2555        unsafe {
2556            with_c_str(title, |title| {
2557                ffi::glfwSetWindowTitle(self.ptr, title);
2558            });
2559        }
2560    }
2561
2562    /// Wrapper for `glfwGetWindowPos`.
2563    pub fn get_pos(&self) -> (i32, i32) {
2564        unsafe {
2565            let mut xpos = 0;
2566            let mut ypos = 0;
2567            ffi::glfwGetWindowPos(self.ptr, &mut xpos, &mut ypos);
2568            (xpos as i32, ypos as i32)
2569        }
2570    }
2571
2572    /// Wrapper for `glfwSetWindowPos`.
2573    pub fn set_pos(&mut self, xpos: i32, ypos: i32) {
2574        unsafe {
2575            ffi::glfwSetWindowPos(self.ptr, xpos as c_int, ypos as c_int);
2576        }
2577    }
2578
2579    /// Wrapper for `glfwGetWindowSize`.
2580    pub fn get_size(&self) -> (i32, i32) {
2581        unsafe {
2582            let mut width = 0;
2583            let mut height = 0;
2584            ffi::glfwGetWindowSize(self.ptr, &mut width, &mut height);
2585            (width as i32, height as i32)
2586        }
2587    }
2588
2589    /// Wrapper for `glfwSetWindowSize`.
2590    pub fn set_size(&mut self, width: i32, height: i32) {
2591        unsafe {
2592            ffi::glfwSetWindowSize(self.ptr, width as c_int, height as c_int);
2593        }
2594    }
2595
2596    /// Wrapper for `glfwGetWindowFrameSize`
2597    ///
2598    /// Returns `(left, top, right, bottom)` edge window frame sizes, in screen coordinates.
2599    pub fn get_frame_size(&self) -> (i32, i32, i32, i32) {
2600        let (mut left, mut top, mut right, mut bottom): (i32, i32, i32, i32) = (0, 0, 0, 0);
2601
2602        unsafe {
2603            ffi::glfwGetWindowFrameSize(
2604                self.ptr,
2605                &mut left as *mut c_int,
2606                &mut top as *mut c_int,
2607                &mut right as *mut c_int,
2608                &mut bottom as *mut c_int,
2609            );
2610        }
2611
2612        (left, top, right, bottom)
2613    }
2614
2615    /// Wrapper for `glfwGetFramebufferSize`.
2616    pub fn get_framebuffer_size(&self) -> (i32, i32) {
2617        unsafe {
2618            let mut width = 0;
2619            let mut height = 0;
2620            ffi::glfwGetFramebufferSize(self.ptr, &mut width, &mut height);
2621            (width as i32, height as i32)
2622        }
2623    }
2624
2625    /// Wrapper for `glfwSetWindowAspectRatio`.
2626    pub fn set_aspect_ratio(&mut self, numer: u32, denum: u32) {
2627        unsafe { ffi::glfwSetWindowAspectRatio(self.ptr, numer as c_int, denum as c_int) }
2628    }
2629
2630    /// Wrapper for `glfwSetWindowSizeLimits`.
2631    ///
2632    /// A value of `None` is equivalent to `GLFW_DONT_CARE`.
2633    /// If `minwidth` or `minheight` are `None`, no minimum size is enforced.
2634    /// If `maxwidth` or `maxheight` are `None`, no maximum size is enforced.
2635    pub fn set_size_limits(
2636        &mut self,
2637        minwidth: Option<u32>,
2638        minheight: Option<u32>,
2639        maxwidth: Option<u32>,
2640        maxheight: Option<u32>,
2641    ) {
2642        unsafe {
2643            ffi::glfwSetWindowSizeLimits(
2644                self.ptr,
2645                unwrap_dont_care(minwidth),
2646                unwrap_dont_care(minheight),
2647                unwrap_dont_care(maxwidth),
2648                unwrap_dont_care(maxheight),
2649            )
2650        }
2651    }
2652
2653    /// Wrapper for `glfwIconifyWindow`.
2654    pub fn iconify(&mut self) {
2655        unsafe {
2656            ffi::glfwIconifyWindow(self.ptr);
2657        }
2658    }
2659
2660    /// Wrapper for `glfwRestoreWindow`.
2661    pub fn restore(&mut self) {
2662        unsafe {
2663            ffi::glfwRestoreWindow(self.ptr);
2664        }
2665    }
2666
2667    /// Wrapper for `glfwMaximizeWindow`
2668    pub fn maximize(&mut self) {
2669        unsafe { ffi::glfwMaximizeWindow(self.ptr) }
2670    }
2671
2672    /// Wrapper for `glfwShowWindow`.
2673    pub fn show(&mut self) {
2674        unsafe {
2675            ffi::glfwShowWindow(self.ptr);
2676        }
2677    }
2678
2679    /// Wrapper for `glfwHideWindow`.
2680    pub fn hide(&mut self) {
2681        unsafe {
2682            ffi::glfwHideWindow(self.ptr);
2683        }
2684    }
2685
2686    /// Returns whether the window is fullscreen or windowed.
2687    ///
2688    /// # Example
2689    ///
2690    /// ~~~ignore
2691    /// window.with_window_mode(|mode| {
2692    ///     match mode {
2693    ///         glfw::Windowed => println!("Windowed"),
2694    ///         glfw::FullScreen(m) => println!("FullScreen({})", m.get_name()),
2695    ///     }
2696    /// });
2697    /// ~~~
2698    pub fn with_window_mode<T, F>(&self, f: F) -> T
2699    where
2700        F: FnOnce(WindowMode<'_>) -> T,
2701    {
2702        let ptr = unsafe { ffi::glfwGetWindowMonitor(self.ptr) };
2703        if ptr.is_null() {
2704            f(WindowMode::Windowed)
2705        } else {
2706            f(WindowMode::FullScreen(&Monitor { ptr }))
2707        }
2708    }
2709
2710    /// Wrapper for `glfwSetWindowMonitor`
2711    pub fn set_monitor(
2712        &mut self,
2713        mode: WindowMode<'_>,
2714        xpos: i32,
2715        ypos: i32,
2716        width: u32,
2717        height: u32,
2718        refresh_rate: Option<u32>,
2719    ) {
2720        let monitor_ptr = if let WindowMode::FullScreen(monitor) = mode {
2721            monitor.ptr
2722        } else {
2723            ptr::null_mut()
2724        };
2725
2726        unsafe {
2727            ffi::glfwSetWindowMonitor(
2728                self.ptr,
2729                monitor_ptr,
2730                xpos as c_int,
2731                ypos as c_int,
2732                width as c_int,
2733                height as c_int,
2734                unwrap_dont_care(refresh_rate),
2735            )
2736        }
2737    }
2738
2739    /// Wrapper for `glfwFocusWindow`
2740    ///
2741    /// It is NOT recommended to use this function, as it steals focus from other applications
2742    /// and can be extremely disruptive to the user.
2743    pub fn focus(&mut self) {
2744        unsafe { ffi::glfwFocusWindow(self.ptr) }
2745    }
2746
2747    /// Wrapper for `glfwGetWindowAttrib` called with `FOCUSED`.
2748    pub fn is_focused(&self) -> bool {
2749        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::FOCUSED) == ffi::TRUE }
2750    }
2751
2752    /// Wrapper for `glfwGetWindowAttrib` called with `ICONIFIED`.
2753    pub fn is_iconified(&self) -> bool {
2754        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::ICONIFIED) == ffi::TRUE }
2755    }
2756
2757    /// Wrapper for `glfwGetWindowattrib` called with `MAXIMIZED`.
2758    pub fn is_maximized(&self) -> bool {
2759        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::MAXIMIZED) == ffi::TRUE }
2760    }
2761
2762    /// Wrapper for `glfwGetWindowAttrib` called with `CLIENT_API`.
2763    pub fn get_client_api(&self) -> c_int {
2764        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::CLIENT_API) }
2765    }
2766
2767    /// Wrapper for `glfwGetWindowAttrib` called with
2768    /// `CONTEXT_VERSION_MAJOR`, `CONTEXT_VERSION_MINOR` and `CONTEXT_REVISION`.
2769    ///
2770    /// # Returns
2771    ///
2772    /// The client API version of the window's context in a version struct.
2773    pub fn get_context_version(&self) -> Version {
2774        unsafe {
2775            Version {
2776                major: ffi::glfwGetWindowAttrib(self.ptr, ffi::CONTEXT_VERSION_MAJOR) as u64,
2777                minor: ffi::glfwGetWindowAttrib(self.ptr, ffi::CONTEXT_VERSION_MINOR) as u64,
2778                patch: ffi::glfwGetWindowAttrib(self.ptr, ffi::CONTEXT_REVISION) as u64,
2779            }
2780        }
2781    }
2782
2783    /// Wrapper for `glfwGetWindowAttrib` called with `CONTEXT_ROBUSTNESS`.
2784    pub fn get_context_robustness(&self) -> c_int {
2785        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::CONTEXT_ROBUSTNESS) }
2786    }
2787
2788    /// Wrapper for `glfwGetWindowAttrib` called with `OPENGL_FORWARD_COMPAT`.
2789    pub fn is_opengl_forward_compat(&self) -> bool {
2790        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::OPENGL_FORWARD_COMPAT) == ffi::TRUE }
2791    }
2792
2793    /// Wrapper for `glfwGetWindowAttrib` called with `OPENGL_DEBUG_CONTEXT`.
2794    pub fn is_opengl_debug_context(&self) -> bool {
2795        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::OPENGL_DEBUG_CONTEXT) == ffi::TRUE }
2796    }
2797
2798    /// Wrapper for `glfwGetWindowAttrib` called with `OPENGL_PROFILE`.
2799    pub fn get_opengl_profile(&self) -> c_int {
2800        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::OPENGL_PROFILE) }
2801    }
2802
2803    /// Wrapper for `glfwGetWindowAttrib` called with `RESIZABLE`.
2804    pub fn is_resizable(&self) -> bool {
2805        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::RESIZABLE) == ffi::TRUE }
2806    }
2807
2808    /// Wrapper for `glfwSetWindowAttrib` called with `RESIZABLE`.
2809    pub fn set_resizable(&mut self, resizable: bool) {
2810        unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::RESIZABLE, resizable as c_int) }
2811    }
2812
2813    /// Wrapper for `glfwGetWindowAttrib` called with `VISIBLE`.
2814    pub fn is_visible(&self) -> bool {
2815        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::VISIBLE) == ffi::TRUE }
2816    }
2817
2818    /// Wrapper for `glfwGetWindowAttrib` called with `DECORATED`.
2819    pub fn is_decorated(&self) -> bool {
2820        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::DECORATED) == ffi::TRUE }
2821    }
2822
2823    /// Wrapper for `glfwSetWindowAttrib` called with `DECORATED`.
2824    pub fn set_decorated(&mut self, decorated: bool) {
2825        unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::DECORATED, decorated as c_int) }
2826    }
2827
2828    /// Wrapper for `glfwGetWindowAttrib` called with `AUTO_ICONIFY`.
2829    pub fn is_auto_iconify(&self) -> bool {
2830        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::AUTO_ICONIFY) == ffi::TRUE }
2831    }
2832
2833    /// Wrapper for `glfwSetWindowAttrib` called with `AUTO_ICONIFY`.
2834    pub fn set_auto_iconify(&mut self, auto_iconify: bool) {
2835        unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::AUTO_ICONIFY, auto_iconify as c_int) }
2836    }
2837
2838    /// Wrapper for `glfwGetWindowAttrib` called with `FLOATING`.
2839    pub fn is_floating(&self) -> bool {
2840        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::FLOATING) == ffi::TRUE }
2841    }
2842
2843    /// Wrapper for `glfwSetWindowAttrib` called with `FLOATING`.
2844    pub fn set_floating(&mut self, floating: bool) {
2845        unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::FLOATING, floating as c_int) }
2846    }
2847
2848    /// Wrapper for `glfwGetWindowAttrib` called with `TRANSPARENT_FRAMEBUFFER`.
2849    pub fn is_framebuffer_transparent(&self) -> bool {
2850        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::TRANSPARENT_FRAMEBUFFER) == ffi::TRUE }
2851    }
2852
2853    /// Wrapper for `glfwGetWindowAttrib` called with `FOCUS_ON_SHOW`.
2854    pub fn is_focus_on_show(&self) -> bool {
2855        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::FOCUS_ON_SHOW) == ffi::TRUE }
2856    }
2857
2858    /// Wrapper for `glfwSetWindowAttrib` called with `FOCUS_ON_SHOW`.
2859    pub fn set_focus_on_show(&mut self, focus_on_show: bool) {
2860        unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::FOCUS_ON_SHOW, focus_on_show as c_int) }
2861    }
2862
2863    /// Wrapper for `glfwGetWindowAttrib` called with `HOVERED`.
2864    pub fn is_hovered(&self) -> bool {
2865        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::HOVERED) == ffi::TRUE }
2866    }
2867
2868    new_callback!(
2869        doc -> "Wrapper for `glfwSetWindowPosCallback`.",
2870        set -> set_pos_callback,
2871        unset -> unset_pos_callback,
2872        poll -> set_pos_polling,
2873        callback_field -> pos_callback,
2874        poll_field -> pos_polling,
2875        window_event -> Pos(i32, i32),
2876        glfw -> glfwSetWindowPosCallback(x: c_int, y: c_int),
2877        convert_args -> (x as i32, y as i32),
2878        secret -> _pos_callback
2879    );
2880
2881    new_callback!(
2882        doc -> "Wrapper for `glfwSetWindowSizeCallback`.",
2883        set -> set_size_callback,
2884        unset -> unset_size_callback,
2885        poll -> set_size_polling,
2886        callback_field -> size_callback,
2887        poll_field -> size_polling,
2888        window_event -> Size(i32, i32),
2889        glfw -> glfwSetWindowSizeCallback(width: c_int, height: c_int),
2890        convert_args -> (width as i32, height as i32),
2891        secret -> _size_callback
2892    );
2893
2894    new_callback!(
2895        doc -> "Wrapper for `glfwSetWindowCloseCallback`.",
2896        set -> set_close_callback,
2897        unset -> unset_close_callback,
2898        poll -> set_close_polling,
2899        callback_field -> close_callback,
2900        poll_field -> close_polling,
2901        window_event -> Close,
2902        glfw -> glfwSetWindowCloseCallback(),
2903        convert_args -> (),
2904        secret -> _close_callback
2905    );
2906
2907    new_callback!(
2908        doc -> "Wrapper for `glfwSetWindowRefreshCallback`.",
2909        set -> set_refresh_callback,
2910        unset -> unset_refresh_callback,
2911        poll -> set_refresh_polling,
2912        callback_field -> refresh_callback,
2913        poll_field -> refresh_polling,
2914        window_event -> Refresh,
2915        glfw -> glfwSetWindowRefreshCallback(),
2916        convert_args -> (),
2917        secret -> _refresh_callback
2918    );
2919
2920    new_callback!(
2921        doc -> "Wrapper for `glfwSetWindowFocusCallback`.",
2922        set -> set_focus_callback,
2923        unset -> unset_focus_callback,
2924        poll -> set_focus_polling,
2925        callback_field -> focus_callback,
2926        poll_field -> focus_polling,
2927        window_event -> Focus(bool),
2928        glfw -> glfwSetWindowFocusCallback(focused: c_int),
2929        convert_args -> (focused == ffi::TRUE),
2930        secret -> _focus_callback
2931    );
2932
2933    new_callback!(
2934        doc -> "Wrapper for `glfwSetWindowIconifyCallback`.",
2935        set -> set_iconify_callback,
2936        unset -> unset_iconify_callback,
2937        poll -> set_iconify_polling,
2938        callback_field -> iconify_callback,
2939        poll_field -> iconify_polling,
2940        window_event -> Iconify(bool),
2941        glfw -> glfwSetWindowIconifyCallback(iconified: c_int),
2942        convert_args -> (iconified == ffi::TRUE),
2943        secret -> _iconify_callback
2944    );
2945
2946    new_callback!(
2947        doc -> "Wrapper for `glfwSetFramebufferSizeCallback`.",
2948        set -> set_framebuffer_size_callback,
2949        unset -> unset_framebuffer_size_callback,
2950        poll -> set_framebuffer_size_polling,
2951        callback_field -> framebuffer_size_callback,
2952        poll_field -> framebuffer_size_polling,
2953        window_event -> FramebufferSize(i32, i32),
2954        glfw -> glfwSetFramebufferSizeCallback(width: c_int, height: c_int),
2955        convert_args -> (width as i32, height as i32),
2956        secret -> _framebuffer_size_callback
2957    );
2958
2959    new_callback!(
2960        doc -> "Wrapper for `glfwSetKeyCallback`.",
2961        set -> set_key_callback,
2962        unset -> unset_key_callback,
2963        poll -> set_key_polling,
2964        callback_field -> key_callback,
2965        poll_field -> key_polling,
2966        window_event -> Key(Key, Scancode, Action, Modifiers),
2967        glfw -> glfwSetKeyCallback(key: c_int, scancode: c_int, action: c_int, mods: c_int),
2968        convert_args -> (
2969            mem::transmute(key),
2970            scancode, mem::transmute(action),
2971            Modifiers::from_bits(mods).unwrap()
2972        ),
2973        secret -> _key_callback
2974    );
2975
2976    new_callback!(
2977        doc -> "Wrapper for `glfwSetCharCallback`.",
2978        set -> set_char_callback,
2979        unset -> unset_char_callback,
2980        poll -> set_char_polling,
2981        callback_field -> char_callback,
2982        poll_field -> char_polling,
2983        window_event -> Char(char),
2984        glfw -> glfwSetCharCallback(character: c_uint),
2985        convert_args -> (::std::char::from_u32(character).unwrap()),
2986        secret -> _char_callback
2987    );
2988
2989    new_callback!(
2990        doc -> "Wrapper for `glfwSetCharModsCallback`.",
2991        set -> set_char_mods_callback,
2992        unset -> unset_char_mods_callback,
2993        poll -> set_char_mods_polling,
2994        callback_field -> char_mods_callback,
2995        poll_field -> char_mods_polling,
2996        window_event -> CharModifiers(char, Modifiers),
2997        glfw -> glfwSetCharModsCallback(character: c_uint, mods: c_int),
2998        convert_args -> (
2999            ::std::char::from_u32(character).unwrap(),
3000            Modifiers::from_bits(mods).unwrap()
3001        ),
3002        secret -> _char_mods_callback
3003    );
3004
3005    new_callback!(
3006        doc -> "Wrapper for `glfwSetMouseButtonCallback`.",
3007        set -> set_mouse_button_callback,
3008        unset -> unset_mouse_button_callback,
3009        poll -> set_mouse_button_polling,
3010        callback_field -> mouse_button_callback,
3011        poll_field -> mouse_button_polling,
3012        window_event -> MouseButton(MouseButton, Action, Modifiers),
3013        glfw -> glfwSetMouseButtonCallback(button: c_int, action: c_int, mods: c_int),
3014        convert_args -> (
3015            mem::transmute(button),
3016            mem::transmute(action),
3017            Modifiers::from_bits(mods).unwrap()
3018        ),
3019        secret -> _mouse_button_callback
3020    );
3021
3022    new_callback!(
3023        doc -> "Wrapper for `glfwSetCursorPosCallback`.",
3024        set -> set_cursor_pos_callback,
3025        unset -> unset_cursor_pos_callback,
3026        poll -> set_cursor_pos_polling,
3027        callback_field -> cursor_pos_callback,
3028        poll_field -> cursor_pos_polling,
3029        window_event -> CursorPos(f64, f64),
3030        glfw -> glfwSetCursorPosCallback(x: c_double, y: c_double),
3031        convert_args -> (x as f64, y as f64),
3032        secret -> _cursor_pos_callback
3033    );
3034
3035    new_callback!(
3036        doc -> "Wrapper for `glfwSetCursorEnterCallback`.",
3037        set -> set_cursor_enter_callback,
3038        unset -> unset_cursor_enter_callback,
3039        poll -> set_cursor_enter_polling,
3040        callback_field -> cursor_enter_callback,
3041        poll_field -> cursor_enter_polling,
3042        window_event -> CursorEnter(bool),
3043        glfw -> glfwSetCursorEnterCallback(entered: c_int),
3044        convert_args -> (entered == ffi::TRUE),
3045        secret -> _cursor_enter_callback
3046    );
3047
3048    new_callback!(
3049        doc -> "Wrapper for `glfwSetScrollCallback`.",
3050        set -> set_scroll_callback,
3051        unset -> unset_scroll_callback,
3052        poll -> set_scroll_polling,
3053        callback_field -> scroll_callback,
3054        poll_field -> scroll_polling,
3055        window_event -> Scroll(f64, f64),
3056        glfw -> glfwSetScrollCallback(x: c_double, y: c_double),
3057        convert_args -> (x as f64, y as f64),
3058        secret -> _scroll_callback
3059    );
3060
3061    new_callback!(
3062        doc -> "Wrapper for `glfwSetDropCallback`.",
3063        set -> set_drag_and_drop_callback,
3064        unset -> unset_drag_and_drop_callback,
3065        poll -> set_drag_and_drop_polling,
3066        callback_field -> drag_and_drop_callback,
3067        poll_field -> drag_and_drop_polling,
3068        window_event -> FileDrop(Vec<PathBuf>),
3069        glfw -> glfwSetDropCallback(num_paths: c_int, paths: *mut *const c_char),
3070        convert_args -> ({
3071            slice::from_raw_parts(paths, num_paths as usize)
3072            .iter()
3073            .map(|path| PathBuf::from(std::str::from_utf8({
3074                CStr::from_ptr(*path)
3075                    .to_bytes()
3076            })
3077            .unwrap()
3078            .to_string()))
3079            .collect()
3080        }),
3081        secret -> _drag_and_drop_callback
3082    );
3083
3084    new_callback!(
3085        doc -> "Wrapper for `glfwSetWindowMaximizeCallback`.",
3086        set -> set_maximize_callback,
3087        unset -> unset_maximize_callback,
3088        poll -> set_maximize_polling,
3089        callback_field -> maximize_callback,
3090        poll_field -> maximize_polling,
3091        window_event -> Maximize(bool),
3092        glfw -> glfwSetWindowMaximizeCallback(maximized: c_int),
3093        convert_args -> (maximized == ffi::TRUE),
3094        secret -> _maximize_callback
3095    );
3096
3097    new_callback!(
3098        doc -> "Wrapper for `glfwSetWindowContentScaleCallback`.",
3099        set -> set_content_scale_callback,
3100        unset -> unset_content_scale_callback,
3101        poll -> set_content_scale_polling,
3102        callback_field -> content_scale_callback,
3103        poll_field -> content_scale_polling,
3104        window_event -> ContentScale(f32, f32),
3105        glfw -> glfwSetWindowContentScaleCallback(xscale: c_float, yscale: c_float),
3106        convert_args -> (xscale as f32, yscale as f32),
3107        secret -> _content_scale_callback
3108    );
3109
3110    /// Starts or stops polling for all available events
3111    pub fn set_all_polling(&mut self, should_poll: bool) {
3112        self.set_pos_polling(should_poll);
3113        self.set_size_polling(should_poll);
3114        self.set_close_polling(should_poll);
3115        self.set_refresh_polling(should_poll);
3116        self.set_focus_polling(should_poll);
3117        self.set_iconify_polling(should_poll);
3118        self.set_framebuffer_size_polling(should_poll);
3119        self.set_key_polling(should_poll);
3120        self.set_char_polling(should_poll);
3121        self.set_char_mods_polling(should_poll);
3122        self.set_mouse_button_polling(should_poll);
3123        self.set_cursor_pos_polling(should_poll);
3124        self.set_cursor_enter_polling(should_poll);
3125        self.set_scroll_polling(should_poll);
3126        self.set_drag_and_drop_polling(should_poll);
3127        self.set_maximize_polling(should_poll);
3128        self.set_content_scale_polling(should_poll);
3129    }
3130
3131    /// Wrapper for `glfwGetInputMode` called with `CURSOR`.
3132    pub fn get_cursor_mode(&self) -> CursorMode {
3133        unsafe { mem::transmute(ffi::glfwGetInputMode(self.ptr, ffi::CURSOR)) }
3134    }
3135
3136    /// Wrapper for `glfwSetInputMode` called with `CURSOR`.
3137    pub fn set_cursor_mode(&mut self, mode: CursorMode) {
3138        unsafe {
3139            ffi::glfwSetInputMode(self.ptr, ffi::CURSOR, mode as c_int);
3140        }
3141    }
3142
3143    /// Wrapper for `glfwSetCursor` using `Cursor`
3144    ///
3145    /// The window will take ownership of the cursor, and will not Drop it
3146    /// until it is replaced or the window itself is destroyed.
3147    ///
3148    /// Returns the previously set Cursor or None if no cursor was set.
3149    pub fn set_cursor(&mut self, cursor: Option<Cursor>) -> Option<Cursor> {
3150        let previous = mem::replace(&mut self.current_cursor, cursor);
3151
3152        unsafe {
3153            ffi::glfwSetCursor(
3154                self.ptr,
3155                match self.current_cursor {
3156                    Some(ref cursor) => cursor.ptr,
3157                    None => ptr::null_mut(),
3158                },
3159            )
3160        }
3161
3162        previous
3163    }
3164
3165    /// Sets the window icon from the given images by called `glfwSetWindowIcon`
3166    ///
3167    /// Multiple images can be specified for allowing the OS to choose the best size where
3168    /// necessary.
3169    ///
3170    /// Example:
3171    ///
3172    /// ```ignore
3173    /// if let DynamicImage::ImageRgba8(icon) = image::open("examples/icon.png").unwrap() {
3174    ///    window.set_icon(vec![
3175    ///        imageops::resize(&icon, 16, 16, image::imageops::Lanczos3),
3176    ///        imageops::resize(&icon, 32, 32, image::imageops::Lanczos3),
3177    ///        imageops::resize(&icon, 48, 48, image::imageops::Lanczos3)
3178    ///    ]);
3179    /// }
3180    /// ```
3181    #[cfg(feature = "image")]
3182    pub fn set_icon(&mut self, images: Vec<image::RgbaImage>) {
3183        // When the images are turned into Vecs, the lifetimes of them go into the Vec lifetime
3184        // So they need to be kept until the function ends.
3185        let image_data: Vec<(Vec<_>, u32, u32)> = images
3186            .into_iter()
3187            .map(|image| {
3188                let (width, height) = image.dimensions();
3189
3190                (image.into_vec(), width, height)
3191            })
3192            .collect();
3193
3194        let glfw_images: Vec<ffi::GLFWimage> = image_data
3195            .iter()
3196            .map(|data| ffi::GLFWimage {
3197                width: data.1 as c_int,
3198                height: data.2 as c_int,
3199                pixels: data.0.as_ptr() as *const c_uchar,
3200            })
3201            .collect();
3202
3203        unsafe {
3204            ffi::glfwSetWindowIcon(
3205                self.ptr,
3206                glfw_images.len() as c_int,
3207                glfw_images.as_ptr() as *const ffi::GLFWimage,
3208            )
3209        }
3210    }
3211
3212    /// Sets the window icon via `glfwSetWindowIcon` from a set a set of vectors
3213    /// containing pixels in RGBA format (one pixel per 32-bit integer)
3214    pub fn set_icon_from_pixels(&mut self, images: Vec<PixelImage>) {
3215        let glfw_images: Vec<ffi::GLFWimage> = images
3216            .iter()
3217            .map(|image: &PixelImage| ffi::GLFWimage {
3218                width: image.width as c_int,
3219                height: image.height as c_int,
3220                pixels: image.pixels.as_ptr() as *const c_uchar,
3221            })
3222            .collect();
3223
3224        unsafe {
3225            ffi::glfwSetWindowIcon(
3226                self.ptr,
3227                glfw_images.len() as c_int,
3228                glfw_images.as_ptr() as *const ffi::GLFWimage,
3229            )
3230        }
3231    }
3232
3233    /// Wrapper for `glfwGetInputMode` called with `STICKY_KEYS`.
3234    pub fn has_sticky_keys(&self) -> bool {
3235        unsafe { ffi::glfwGetInputMode(self.ptr, ffi::STICKY_KEYS) == ffi::TRUE }
3236    }
3237
3238    /// Wrapper for `glfwSetInputMode` called with `STICKY_KEYS`.
3239    pub fn set_sticky_keys(&mut self, value: bool) {
3240        unsafe {
3241            ffi::glfwSetInputMode(self.ptr, ffi::STICKY_KEYS, value as c_int);
3242        }
3243    }
3244
3245    /// Wrapper for `glfwGetInputMode` called with `STICKY_MOUSE_BUTTONS`.
3246    pub fn has_sticky_mouse_buttons(&self) -> bool {
3247        unsafe { ffi::glfwGetInputMode(self.ptr, ffi::STICKY_MOUSE_BUTTONS) == ffi::TRUE }
3248    }
3249
3250    /// Wrapper for `glfwSetInputMode` called with `STICKY_MOUSE_BUTTONS`.
3251    pub fn set_sticky_mouse_buttons(&mut self, value: bool) {
3252        unsafe {
3253            ffi::glfwSetInputMode(self.ptr, ffi::STICKY_MOUSE_BUTTONS, value as c_int);
3254        }
3255    }
3256
3257    /// Wrapper for `glfwGetInputMode` called with `LOCK_KEY_MODS`
3258    pub fn does_store_lock_key_mods(&self) -> bool {
3259        unsafe { ffi::glfwGetInputMode(self.ptr, ffi::LOCK_KEY_MODS) == ffi::TRUE }
3260    }
3261
3262    /// Wrapper for `glfwSetInputMode` called with `LOCK_KEY_MODS`
3263    pub fn set_store_lock_key_mods(&mut self, value: bool) {
3264        unsafe { ffi::glfwSetInputMode(self.ptr, ffi::LOCK_KEY_MODS, value as c_int) }
3265    }
3266
3267    /// Wrapper for `glfwGetInputMode` called with `RAW_MOUSE_MOTION`
3268    pub fn uses_raw_mouse_motion(&self) -> bool {
3269        unsafe { ffi::glfwGetInputMode(self.ptr, ffi::RAW_MOUSE_MOTION) == ffi::TRUE }
3270    }
3271
3272    /// Wrapper for `glfwSetInputMode` called with `RAW_MOUSE_MOTION`
3273    pub fn set_raw_mouse_motion(&mut self, value: bool) {
3274        unsafe { ffi::glfwSetInputMode(self.ptr, ffi::RAW_MOUSE_MOTION, value as c_int) }
3275    }
3276
3277    /// Wrapper for `glfwGetKey`.
3278    pub fn get_key(&self, key: Key) -> Action {
3279        unsafe { mem::transmute(ffi::glfwGetKey(self.ptr, key as c_int)) }
3280    }
3281
3282    /// Wrapper for `glfwGetMouseButton`.
3283    pub fn get_mouse_button(&self, button: MouseButton) -> Action {
3284        unsafe { mem::transmute(ffi::glfwGetMouseButton(self.ptr, button as c_int)) }
3285    }
3286
3287    /// Wrapper for `glfwGetCursorPos`.
3288    pub fn get_cursor_pos(&self) -> (f64, f64) {
3289        unsafe {
3290            let mut xpos = 0.0;
3291            let mut ypos = 0.0;
3292            ffi::glfwGetCursorPos(self.ptr, &mut xpos, &mut ypos);
3293            (xpos as f64, ypos as f64)
3294        }
3295    }
3296
3297    /// Wrapper for `glfwSetCursorPos`.
3298    pub fn set_cursor_pos(&mut self, xpos: f64, ypos: f64) {
3299        unsafe {
3300            ffi::glfwSetCursorPos(self.ptr, xpos as c_double, ypos as c_double);
3301        }
3302    }
3303
3304    /// Wrapper for `glfwGetClipboardString`.
3305    pub fn set_clipboard_string(&mut self, string: &str) {
3306        unsafe {
3307            with_c_str(string, |string| {
3308                ffi::glfwSetClipboardString(self.ptr, string);
3309            });
3310        }
3311    }
3312
3313    /// Wrapper for `glfwGetClipboardString`.
3314    pub fn get_clipboard_string(&self) -> Option<String> {
3315        unsafe { string_from_nullable_c_str(ffi::glfwGetClipboardString(self.ptr)) }
3316    }
3317
3318    /// Wrapper for `glfwGetWindowOpacity`.
3319    pub fn get_opacity(&self) -> f32 {
3320        unsafe { ffi::glfwGetWindowOpacity(self.ptr) }
3321    }
3322
3323    /// Wrapper for `glfwSetWindowOpacity`.
3324    pub fn set_opacity(&mut self, opacity: f32) {
3325        unsafe { ffi::glfwSetWindowOpacity(self.ptr, opacity) }
3326    }
3327
3328    /// Wrapper for `glfwRequestWindowAttention`.
3329    pub fn request_attention(&mut self) {
3330        unsafe { ffi::glfwRequestWindowAttention(self.ptr) }
3331    }
3332
3333    /// Wrapper for `glfwGetWindowContentScale`.
3334    pub fn get_content_scale(&self) -> (f32, f32) {
3335        unsafe {
3336            let mut xscale = 0.0_f32;
3337            let mut yscale = 0.0_f32;
3338            ffi::glfwGetWindowContentScale(self.ptr, &mut xscale, &mut yscale);
3339            (xscale, yscale)
3340        }
3341    }
3342
3343    /// Wrapper for `glfwGetWin32Window`
3344    #[cfg(target_os = "windows")]
3345    pub fn get_win32_window(&self) -> *mut c_void {
3346        unsafe { ffi::glfwGetWin32Window(self.ptr) }
3347    }
3348
3349    /// Wrapper for `glfwGetWGLContext`
3350    #[cfg(target_os = "windows")]
3351    pub fn get_wgl_context(&self) -> *mut c_void {
3352        unsafe { ffi::glfwGetWGLContext(self.ptr) }
3353    }
3354
3355    /// Wrapper for `glfwGetCocoaWindow`
3356    #[cfg(target_os = "macos")]
3357    pub fn get_cocoa_window(&self) -> *mut c_void {
3358        unsafe { ffi::glfwGetCocoaWindow(self.ptr) }
3359    }
3360
3361    /// Wrapper for `glfwGetNSGLContext`
3362    #[cfg(target_os = "macos")]
3363    pub fn get_nsgl_context(&self) -> *mut c_void {
3364        unsafe { ffi::glfwGetNSGLContext(self.ptr) }
3365    }
3366
3367    /// Wrapper for `glfwGetX11Window`
3368    #[cfg(all(target_os = "linux", not(feature = "wayland")))]
3369    pub fn get_x11_window(&self) -> *mut c_void {
3370        unsafe { ffi::glfwGetX11Window(self.ptr) }
3371    }
3372
3373    /// Wrapper for `glfwGetWaylandWindow`
3374    #[cfg(all(target_os = "linux", feature = "wayland"))]
3375    pub fn get_wayland_window(&self) -> *mut c_void {
3376        unsafe { ffi::glfwGetWaylandWindow(self.ptr) }
3377    }
3378
3379    /// Wrapper for `glfwGetGLXContext`
3380    #[cfg(target_os = "linux")]
3381    pub fn get_glx_context(&self) -> *mut c_void {
3382        unsafe { ffi::glfwGetGLXContext(self.ptr) }
3383    }
3384}
3385
3386impl Drop for Window {
3387    /// Closes the window and performs the necessary cleanups. This will block
3388    /// until all associated `RenderContext`s were also dropped, and emit a
3389    /// `debug!` message to that effect.
3390    ///
3391    /// Wrapper for `glfwDestroyWindow`.
3392    fn drop(&mut self) {
3393        drop(self.drop_sender.take());
3394
3395        // Check if all senders from the child `RenderContext`s have hung up.
3396        #[cfg(feature = "log")]
3397        if self.drop_receiver.try_recv() != Err(std::sync::mpsc::TryRecvError::Disconnected) {
3398            debug!("Attempted to drop a Window before the `RenderContext` was dropped.");
3399            debug!("Blocking until the `RenderContext` was dropped.");
3400            let _ = self.drop_receiver.recv();
3401        }
3402
3403        if !self.ptr.is_null() {
3404            unsafe {
3405                let _: Box<WindowCallbacks> =
3406                    mem::transmute(ffi::glfwGetWindowUserPointer(self.ptr));
3407            }
3408        }
3409
3410        if !self.is_shared {
3411            unsafe {
3412                ffi::glfwDestroyWindow(self.ptr);
3413            }
3414        }
3415    }
3416}
3417
3418#[derive(Debug)]
3419#[repr(transparent)]
3420pub struct PRenderContext(Box<RenderContext>);
3421
3422impl Deref for PRenderContext {
3423    type Target = RenderContext;
3424    fn deref(&self) -> &Self::Target {
3425        self.0.deref()
3426    }
3427}
3428
3429impl DerefMut for PRenderContext {
3430    fn deref_mut(&mut self) -> &mut Self::Target {
3431        self.0.deref_mut()
3432    }
3433}
3434
3435unsafe impl Send for PRenderContext {}
3436unsafe impl Sync for PRenderContext {}
3437
3438#[cfg(feature = "raw-window-handle-v0-6")]
3439impl HasWindowHandle for PRenderContext {
3440    fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
3441        self.0.window_handle()
3442    }
3443}
3444
3445#[cfg(feature = "raw-window-handle-v0-6")]
3446impl HasDisplayHandle for PRenderContext {
3447    fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
3448        self.0.display_handle()
3449    }
3450}
3451
3452/// A rendering context that can be shared between tasks.
3453#[derive(Debug)]
3454pub struct RenderContext {
3455    ptr: *mut ffi::GLFWwindow,
3456    glfw: Glfw,
3457    /// As long as this sender is alive, it is not safe to drop the parent
3458    /// `Window`.
3459    #[allow(dead_code)]
3460    drop_sender: Sender<()>,
3461}
3462
3463impl RenderContext {
3464    /// Wrapper function, please refer to [`Window::get_proc_address`]
3465    pub fn get_proc_address(&mut self, procname: &str) -> GLProc {
3466        if self.ptr != unsafe { ffi::glfwGetCurrentContext() } {
3467            self.make_current();
3468        }
3469
3470        self.glfw.get_proc_address_raw(procname)
3471    }
3472
3473    /// Wrapper function, please refer to [`Window::get_instance_proc_address`]
3474    #[cfg(feature = "vulkan")]
3475    pub fn get_instance_proc_address(&mut self, instance: vk::Instance, procname: &str) -> VkProc {
3476        self.glfw.get_instance_proc_address_raw(instance, procname)
3477    }
3478
3479    /// Wrapper function, please refer to [`Window::get_physical_device_presentation_support`]
3480    #[cfg(feature = "vulkan")]
3481    pub fn get_physical_device_presentation_support(
3482        &self,
3483        instance: vk::Instance,
3484        device: vk::PhysicalDevice,
3485        queue_family: u32,
3486    ) -> bool {
3487        self.glfw
3488            .get_physical_device_presentation_support_raw(instance, device, queue_family)
3489    }
3490
3491    /// Wrapper function, please refer to [`Window::create_window_surface`]
3492    #[cfg(feature = "vulkan")]
3493    pub fn create_window_surface(
3494        &self,
3495        instance: vk::Instance,
3496        allocator: *const vk::AllocationCallbacks<'_>,
3497        surface: *mut vk::SurfaceKHR,
3498    ) -> vk::Result {
3499        unsafe { ffi::glfwCreateWindowSurface(instance, self.ptr, allocator, surface) }
3500    }
3501}
3502
3503unsafe impl Send for RenderContext {}
3504
3505/// Methods common to renderable contexts
3506pub trait Context {
3507    /// Returns the pointer to the underlying `GLFWwindow`.
3508    fn window_ptr(&self) -> *mut ffi::GLFWwindow;
3509
3510    /// Returns the unique identifier for this window.
3511    fn window_id(&self) -> WindowId {
3512        self.window_ptr() as WindowId
3513    }
3514
3515    /// Swaps the front and back buffers of the window. If the swap interval is
3516    /// greater than zero, the GPU driver waits the specified number of screen
3517    /// updates before swapping the buffers.
3518    ///
3519    /// Wrapper for `glfwSwapBuffers`.
3520    fn swap_buffers(&mut self) {
3521        let ptr = self.window_ptr();
3522        unsafe {
3523            ffi::glfwSwapBuffers(ptr);
3524        }
3525    }
3526
3527    /// Returns `true` if the window is the current context.
3528    fn is_current(&self) -> bool {
3529        self.window_ptr() == unsafe { ffi::glfwGetCurrentContext() }
3530    }
3531
3532    /// Wrapper for `glfwMakeContextCurrent`
3533    fn make_current(&mut self) {
3534        let ptr = self.window_ptr();
3535        unsafe {
3536            ffi::glfwMakeContextCurrent(ptr);
3537        }
3538    }
3539
3540    /// Wrapper for `glfwWindowShouldClose`.
3541    fn should_close(&self) -> bool {
3542        let ptr = self.window_ptr();
3543        unsafe { ffi::glfwWindowShouldClose(ptr) == ffi::TRUE }
3544    }
3545
3546    /// Wrapper for `glfwSetWindowShouldClose`.
3547    fn set_should_close(&mut self, value: bool) {
3548        let ptr = self.window_ptr();
3549        unsafe {
3550            ffi::glfwSetWindowShouldClose(ptr, value as c_int);
3551        }
3552    }
3553
3554    /// Wrapper for `glfwPostEmptyEvent`.
3555    fn post_empty_event(&self) {
3556        unsafe { ffi::glfwPostEmptyEvent() }
3557    }
3558}
3559
3560impl Context for Window {
3561    fn window_ptr(&self) -> *mut ffi::GLFWwindow {
3562        self.ptr
3563    }
3564}
3565
3566impl Context for RenderContext {
3567    fn window_ptr(&self) -> *mut ffi::GLFWwindow {
3568        self.ptr
3569    }
3570}
3571
3572#[cfg(feature = "raw-window-handle-v0-6")]
3573impl HasWindowHandle for Window {
3574    fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
3575        Ok(unsafe { WindowHandle::borrow_raw(raw_window_handle(self)) })
3576    }
3577}
3578
3579#[cfg(feature = "raw-window-handle-v0-6")]
3580impl HasWindowHandle for RenderContext {
3581    fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
3582        Ok(unsafe { WindowHandle::borrow_raw(raw_window_handle(self)) })
3583    }
3584}
3585
3586#[cfg(feature = "raw-window-handle-v0-6")]
3587impl HasDisplayHandle for Window {
3588    fn display_handle(&'_ self) -> Result<DisplayHandle<'_>, HandleError> {
3589        Ok(unsafe { DisplayHandle::borrow_raw(raw_display_handle()) })
3590    }
3591}
3592
3593#[cfg(feature = "raw-window-handle-v0-6")]
3594impl HasDisplayHandle for RenderContext {
3595    fn display_handle(&'_ self) -> Result<DisplayHandle<'_>, HandleError> {
3596        Ok(unsafe { DisplayHandle::borrow_raw(raw_display_handle()) })
3597    }
3598}
3599
3600#[cfg(feature = "raw-window-handle-v0-5")]
3601unsafe impl HasRawWindowHandle for Window {
3602    fn raw_window_handle(&self) -> RawWindowHandle {
3603        raw_window_handle(self)
3604    }
3605}
3606
3607#[cfg(feature = "raw-window-handle-v0-5")]
3608unsafe impl HasRawWindowHandle for RenderContext {
3609    fn raw_window_handle(&self) -> RawWindowHandle {
3610        raw_window_handle(self)
3611    }
3612}
3613
3614#[cfg(feature = "raw-window-handle-v0-5")]
3615unsafe impl HasRawDisplayHandle for Window {
3616    fn raw_display_handle(&self) -> RawDisplayHandle {
3617        raw_display_handle()
3618    }
3619}
3620
3621#[cfg(feature = "raw-window-handle-v0-5")]
3622unsafe impl HasRawDisplayHandle for RenderContext {
3623    fn raw_display_handle(&self) -> RawDisplayHandle {
3624        raw_display_handle()
3625    }
3626}
3627
3628#[cfg(feature = "raw-window-handle-v0-6")]
3629fn raw_window_handle<C: Context>(context: &C) -> RawWindowHandle {
3630    #[cfg(target_family = "windows")]
3631    {
3632        use std::num::NonZeroIsize;
3633
3634        use raw_window_handle::Win32WindowHandle;
3635        let (hwnd, hinstance): (*mut std::ffi::c_void, *mut std::ffi::c_void) = unsafe {
3636            let hwnd = ffi::glfwGetWin32Window(context.window_ptr());
3637            let hinstance: *mut c_void =
3638                winapi::um::libloaderapi::GetModuleHandleW(std::ptr::null()) as _;
3639            (hwnd, hinstance as _)
3640        };
3641        let mut handle = Win32WindowHandle::new(NonZeroIsize::new(hwnd as isize).unwrap());
3642        handle.hinstance = NonZeroIsize::new(hinstance as isize);
3643        RawWindowHandle::Win32(handle)
3644    }
3645    #[cfg(all(
3646        any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3647        not(feature = "wayland")
3648    ))]
3649    {
3650        use raw_window_handle::XlibWindowHandle;
3651        let window =
3652            unsafe { ffi::glfwGetX11Window(context.window_ptr()) as std::os::raw::c_ulong };
3653        RawWindowHandle::Xlib(XlibWindowHandle::new(window))
3654    }
3655    #[cfg(all(
3656        any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3657        feature = "wayland"
3658    ))]
3659    {
3660        use std::ptr::NonNull;
3661
3662        use raw_window_handle::WaylandWindowHandle;
3663        let surface = unsafe { ffi::glfwGetWaylandWindow(context.window_ptr()) };
3664        let handle = WaylandWindowHandle::new(
3665            NonNull::new(surface).expect("wayland window surface is null"),
3666        );
3667        RawWindowHandle::Wayland(handle)
3668    }
3669    #[cfg(target_os = "macos")]
3670    {
3671        use std::ptr::NonNull;
3672
3673        use objc2::msg_send_id;
3674        use objc2::rc::Id;
3675        use objc2::runtime::NSObject;
3676        use raw_window_handle::AppKitWindowHandle;
3677        let ns_window: *mut NSObject =
3678            unsafe { ffi::glfwGetCocoaWindow(context.window_ptr()) as *mut _ };
3679        let ns_view: Option<Id<NSObject>> = unsafe { msg_send_id![ns_window, contentView] };
3680        let ns_view = ns_view.expect("failed to access contentView on GLFW NSWindow");
3681        let ns_view: NonNull<NSObject> = NonNull::from(&*ns_view);
3682        let handle = AppKitWindowHandle::new(ns_view.cast());
3683        RawWindowHandle::AppKit(handle)
3684    }
3685    #[cfg(target_os = "emscripten")]
3686    {
3687        let _ = context; // to avoid unused lint
3688        let mut wh = raw_window_handle::WebWindowHandle::new(1);
3689        // glfw on emscripten only supports a single window. so, just hardcode it
3690        // sdl2 crate does the same. users can just add `data-raw-handle="1"` attribute to their
3691        // canvas element
3692        RawWindowHandle::Web(wh)
3693    }
3694}
3695
3696#[cfg(feature = "raw-window-handle-v0-6")]
3697fn raw_display_handle() -> RawDisplayHandle {
3698    #[cfg(target_family = "windows")]
3699    {
3700        use raw_window_handle::WindowsDisplayHandle;
3701        RawDisplayHandle::Windows(WindowsDisplayHandle::new())
3702    }
3703    #[cfg(all(
3704        any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3705        not(feature = "wayland")
3706    ))]
3707    {
3708        use std::ptr::NonNull;
3709
3710        use raw_window_handle::XlibDisplayHandle;
3711        let display = NonNull::new(unsafe { ffi::glfwGetX11Display() });
3712        let handle = XlibDisplayHandle::new(display, 0);
3713        RawDisplayHandle::Xlib(handle)
3714    }
3715    #[cfg(all(
3716        any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3717        feature = "wayland"
3718    ))]
3719    {
3720        use std::ptr::NonNull;
3721
3722        use raw_window_handle::WaylandDisplayHandle;
3723        let display =
3724            NonNull::new(unsafe { ffi::glfwGetWaylandDisplay() }).expect("wayland display is null");
3725        let handle = WaylandDisplayHandle::new(display);
3726        RawDisplayHandle::Wayland(handle)
3727    }
3728    #[cfg(target_os = "macos")]
3729    {
3730        use raw_window_handle::AppKitDisplayHandle;
3731        RawDisplayHandle::AppKit(AppKitDisplayHandle::new())
3732    }
3733    #[cfg(target_os = "emscripten")]
3734    {
3735        RawDisplayHandle::Web(raw_window_handle::WebDisplayHandle::new())
3736    }
3737}
3738
3739#[cfg(feature = "raw-window-handle-v0-5")]
3740fn raw_window_handle<C: Context>(context: &C) -> RawWindowHandle {
3741    #[cfg(target_family = "windows")]
3742    {
3743        use raw_window_handle::Win32WindowHandle;
3744        let (hwnd, hinstance) = unsafe {
3745            let hwnd = ffi::glfwGetWin32Window(context.window_ptr());
3746            let hinstance = winapi::um::libloaderapi::GetModuleHandleW(std::ptr::null());
3747            (hwnd, hinstance as _)
3748        };
3749        let mut handle = Win32WindowHandle::empty();
3750        handle.hwnd = hwnd;
3751        handle.hinstance = hinstance;
3752        RawWindowHandle::Win32(handle)
3753    }
3754    #[cfg(all(
3755        any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3756        not(feature = "wayland")
3757    ))]
3758    {
3759        use raw_window_handle::XlibWindowHandle;
3760        let mut handle = XlibWindowHandle::empty();
3761        handle.window =
3762            unsafe { ffi::glfwGetX11Window(context.window_ptr()) as std::os::raw::c_ulong };
3763        RawWindowHandle::Xlib(handle)
3764    }
3765    #[cfg(all(
3766        any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3767        feature = "wayland"
3768    ))]
3769    {
3770        use raw_window_handle::WaylandWindowHandle;
3771        let mut handle = WaylandWindowHandle::empty();
3772        handle.surface = unsafe { ffi::glfwGetWaylandWindow(context.window_ptr()) };
3773        RawWindowHandle::Wayland(handle)
3774    }
3775    #[cfg(target_os = "macos")]
3776    {
3777        use raw_window_handle::AppKitWindowHandle;
3778        let (ns_window, ns_view) = unsafe {
3779            let ns_window: *mut objc::runtime::Object =
3780                ffi::glfwGetCocoaWindow(context.window_ptr()) as *mut _;
3781            let ns_view: *mut objc::runtime::Object = objc::msg_send![ns_window, contentView];
3782            assert_ne!(ns_view, std::ptr::null_mut());
3783            (
3784                ns_window as *mut std::ffi::c_void,
3785                ns_view as *mut std::ffi::c_void,
3786            )
3787        };
3788        let mut handle = AppKitWindowHandle::empty();
3789        handle.ns_window = ns_window;
3790        handle.ns_view = ns_view;
3791        RawWindowHandle::AppKit(handle)
3792    }
3793    #[cfg(target_os = "emscripten")]
3794    {
3795        let _ = context; // to avoid unused lint
3796        let mut wh = raw_window_handle::WebWindowHandle::empty();
3797        // glfw on emscripten only supports a single window. so, just hardcode it
3798        // sdl2 crate does the same. users can just add `data-raw-handle="1"` attribute to their
3799        // canvas element
3800        wh.id = 1;
3801        RawWindowHandle::Web(wh)
3802    }
3803}
3804
3805#[cfg(feature = "raw-window-handle-v0-5")]
3806fn raw_display_handle() -> RawDisplayHandle {
3807    #[cfg(target_family = "windows")]
3808    {
3809        use raw_window_handle::WindowsDisplayHandle;
3810        RawDisplayHandle::Windows(WindowsDisplayHandle::empty())
3811    }
3812    #[cfg(all(
3813        any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3814        not(feature = "wayland")
3815    ))]
3816    {
3817        use raw_window_handle::XlibDisplayHandle;
3818        let mut handle = XlibDisplayHandle::empty();
3819        handle.display = unsafe { ffi::glfwGetX11Display() };
3820        RawDisplayHandle::Xlib(handle)
3821    }
3822    #[cfg(all(
3823        any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"),
3824        feature = "wayland"
3825    ))]
3826    {
3827        use raw_window_handle::WaylandDisplayHandle;
3828        let mut handle = WaylandDisplayHandle::empty();
3829        handle.display = unsafe { ffi::glfwGetWaylandDisplay() };
3830        RawDisplayHandle::Wayland(handle)
3831    }
3832    #[cfg(target_os = "macos")]
3833    {
3834        use raw_window_handle::AppKitDisplayHandle;
3835        RawDisplayHandle::AppKit(AppKitDisplayHandle::empty())
3836    }
3837    #[cfg(target_os = "emscripten")]
3838    {
3839        RawDisplayHandle::Web(raw_window_handle::WebDisplayHandle::empty())
3840    }
3841}
3842
3843/// Wrapper for `glfwMakeContextCurrent`.
3844pub fn make_context_current(context: Option<&dyn Context>) {
3845    match context {
3846        Some(ctx) => unsafe { ffi::glfwMakeContextCurrent(ctx.window_ptr()) },
3847        None => unsafe { ffi::glfwMakeContextCurrent(ptr::null_mut()) },
3848    }
3849}
3850
3851/// Joystick identifier tokens.
3852#[repr(i32)]
3853#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
3854#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3855pub enum JoystickId {
3856    Joystick1 = ffi::JOYSTICK_1,
3857    Joystick2 = ffi::JOYSTICK_2,
3858    Joystick3 = ffi::JOYSTICK_3,
3859    Joystick4 = ffi::JOYSTICK_4,
3860    Joystick5 = ffi::JOYSTICK_5,
3861    Joystick6 = ffi::JOYSTICK_6,
3862    Joystick7 = ffi::JOYSTICK_7,
3863    Joystick8 = ffi::JOYSTICK_8,
3864    Joystick9 = ffi::JOYSTICK_9,
3865    Joystick10 = ffi::JOYSTICK_10,
3866    Joystick11 = ffi::JOYSTICK_11,
3867    Joystick12 = ffi::JOYSTICK_12,
3868    Joystick13 = ffi::JOYSTICK_13,
3869    Joystick14 = ffi::JOYSTICK_14,
3870    Joystick15 = ffi::JOYSTICK_15,
3871    Joystick16 = ffi::JOYSTICK_16,
3872}
3873
3874impl JoystickId {
3875    /// Converts from `i32`.
3876    pub fn from_i32(n: i32) -> Option<JoystickId> {
3877        if (0..=ffi::JOYSTICK_LAST).contains(&n) {
3878            Some(unsafe { mem::transmute(n) })
3879        } else {
3880            None
3881        }
3882    }
3883}
3884
3885/// Button identifier tokens.
3886#[repr(i32)]
3887#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
3888#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3889pub enum GamepadButton {
3890    ButtonA = ffi::GAMEPAD_BUTTON_A,
3891    ButtonB = ffi::GAMEPAD_BUTTON_B,
3892    ButtonX = ffi::GAMEPAD_BUTTON_X,
3893    ButtonY = ffi::GAMEPAD_BUTTON_Y,
3894    ButtonLeftBumper = ffi::GAMEPAD_BUTTON_LEFT_BUMPER,
3895    ButtonRightBumper = ffi::GAMEPAD_BUTTON_RIGHT_BUMPER,
3896    ButtonBack = ffi::GAMEPAD_BUTTON_BACK,
3897    ButtonStart = ffi::GAMEPAD_BUTTON_START,
3898    ButtonGuide = ffi::GAMEPAD_BUTTON_GUIDE,
3899    ButtonLeftThumb = ffi::GAMEPAD_BUTTON_LEFT_THUMB,
3900    ButtonRightThumb = ffi::GAMEPAD_BUTTON_RIGHT_THUMB,
3901    ButtonDpadUp = ffi::GAMEPAD_BUTTON_DPAD_UP,
3902    ButtonDpadRight = ffi::GAMEPAD_BUTTON_DPAD_RIGHT,
3903    ButtonDpadDown = ffi::GAMEPAD_BUTTON_DPAD_DOWN,
3904    ButtonDpadLeft = ffi::GAMEPAD_BUTTON_DPAD_LEFT,
3905}
3906
3907impl GamepadButton {
3908    /// Converts from `i32`.
3909    pub fn from_i32(n: i32) -> Option<GamepadButton> {
3910        if (0..=ffi::GAMEPAD_BUTTON_LAST).contains(&n) {
3911            Some(unsafe { mem::transmute(n) })
3912        } else {
3913            None
3914        }
3915    }
3916}
3917
3918/// Axis identifier tokens.
3919#[repr(i32)]
3920#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
3921#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3922pub enum GamepadAxis {
3923    AxisLeftX = ffi::GAMEPAD_AXIS_LEFT_X,
3924    AxisLeftY = ffi::GAMEPAD_AXIS_LEFT_Y,
3925    AxisRightX = ffi::GAMEPAD_AXIS_RIGHT_X,
3926    AxisRightY = ffi::GAMEPAD_AXIS_RIGHT_Y,
3927    AxisLeftTrigger = ffi::GAMEPAD_AXIS_LEFT_TRIGGER,
3928    AxisRightTrigger = ffi::GAMEPAD_AXIS_RIGHT_TRIGGER,
3929}
3930
3931impl GamepadAxis {
3932    /// Converts from `i32`.
3933    pub fn from_i32(n: i32) -> Option<GamepadAxis> {
3934        if (0..=ffi::GAMEPAD_AXIS_LAST).contains(&n) {
3935            Some(unsafe { mem::transmute(n) })
3936        } else {
3937            None
3938        }
3939    }
3940}
3941
3942bitflags! {
3943    #[doc = "Joystick hats."]
3944    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3945    pub struct JoystickHats: ::std::os::raw::c_int {
3946        const Centered = crate::ffi::HAT_CENTERED;
3947        const Up       = crate::ffi::HAT_UP;
3948        const Right    = crate::ffi::HAT_RIGHT;
3949        const Down     = crate::ffi::HAT_DOWN;
3950        const Left     = crate::ffi::HAT_LEFT;
3951    }
3952}
3953
3954/// A joystick handle.
3955#[derive(Clone, Debug)]
3956pub struct Joystick {
3957    pub id: JoystickId,
3958    pub glfw: Glfw,
3959}
3960
3961/// State of a gamepad.
3962#[derive(Copy, Clone, Debug)]
3963#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3964pub struct GamepadState {
3965    buttons: [Action; (ffi::GAMEPAD_BUTTON_LAST + 1) as usize],
3966    axes: [f32; (ffi::GAMEPAD_AXIS_LAST + 1) as usize],
3967}
3968
3969/// Joystick events.
3970#[repr(i32)]
3971#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
3972#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3973pub enum JoystickEvent {
3974    Connected = ffi::CONNECTED,
3975    Disconnected = ffi::DISCONNECTED,
3976}
3977
3978impl Joystick {
3979    /// Wrapper for `glfwJoystickPresent`.
3980    pub fn is_present(&self) -> bool {
3981        unsafe { ffi::glfwJoystickPresent(self.id as c_int) == ffi::TRUE }
3982    }
3983
3984    /// Wrapper for `glfwGetJoystickAxes`.
3985    pub fn get_axes(&self) -> Vec<f32> {
3986        unsafe {
3987            let mut count = 0;
3988            let ptr = ffi::glfwGetJoystickAxes(self.id as c_int, &mut count);
3989            slice::from_raw_parts(ptr, count as usize)
3990                .iter()
3991                .map(|&a| a as f32)
3992                .collect()
3993        }
3994    }
3995
3996    /// Wrapper for `glfwGetJoystickButtons`.
3997    pub fn get_buttons(&self) -> Vec<c_int> {
3998        unsafe {
3999            let mut count = 0;
4000            let ptr = ffi::glfwGetJoystickButtons(self.id as c_int, &mut count);
4001            slice::from_raw_parts(ptr, count as usize)
4002                .iter()
4003                .map(|&b| b as c_int)
4004                .collect()
4005        }
4006    }
4007
4008    /// Wrapper for `glfwGetJoystickHats`.
4009    pub fn get_hats(&self) -> Vec<JoystickHats> {
4010        unsafe {
4011            let mut count = 0;
4012            let ptr = ffi::glfwGetJoystickHats(self.id as c_int, &mut count);
4013            slice::from_raw_parts(ptr, count as usize)
4014                .iter()
4015                .map(|&b| mem::transmute(b as c_int))
4016                .collect()
4017        }
4018    }
4019
4020    /// Wrapper for `glfwGetJoystickName`.
4021    pub fn get_name(&self) -> Option<String> {
4022        unsafe { string_from_nullable_c_str(ffi::glfwGetJoystickName(self.id as c_int)) }
4023    }
4024
4025    /// Wrapper for `glfwGetJoystickGUID`.
4026    pub fn get_guid(&self) -> Option<String> {
4027        unsafe { string_from_nullable_c_str(ffi::glfwGetJoystickGUID(self.id as c_int)) }
4028    }
4029
4030    /// Wrapper for `glfwJoystickIsGamepad`.
4031    pub fn is_gamepad(&self) -> bool {
4032        unsafe { ffi::glfwJoystickIsGamepad(self.id as c_int) == ffi::TRUE }
4033    }
4034
4035    /// Wrapper for `glfwGetGamepadName`.
4036    pub fn get_gamepad_name(&self) -> Option<String> {
4037        unsafe { string_from_nullable_c_str(ffi::glfwGetGamepadName(self.id as c_int)) }
4038    }
4039
4040    /// Wrapper for `glfwGetGamepadState`.
4041    pub fn get_gamepad_state(&self) -> Option<GamepadState> {
4042        unsafe {
4043            let mut state = ffi::GLFWgamepadstate {
4044                buttons: [0; (ffi::GAMEPAD_BUTTON_LAST + 1) as usize],
4045                axes: [0_f32; (ffi::GAMEPAD_AXIS_LAST + 1) as usize],
4046            };
4047            if ffi::glfwGetGamepadState(self.id as c_int, &mut state) == ffi::TRUE {
4048                Some(state.into())
4049            } else {
4050                None
4051            }
4052        }
4053    }
4054}
4055
4056impl From<ffi::GLFWgamepadstate> for GamepadState {
4057    fn from(state: ffi::GLFWgamepadstate) -> Self {
4058        let mut buttons = [Action::Release; (ffi::GAMEPAD_BUTTON_LAST + 1) as usize];
4059        let mut axes = [0_f32; (ffi::GAMEPAD_AXIS_LAST + 1) as usize];
4060        unsafe {
4061            state
4062                .buttons
4063                .iter()
4064                .map(|&b| mem::transmute(b as c_int))
4065                .zip(buttons.iter_mut())
4066                .for_each(|(a, b)| *b = a);
4067        }
4068        state
4069            .axes
4070            .iter()
4071            .map(|&f| f as f32)
4072            .zip(axes.iter_mut())
4073            .for_each(|(a, b)| *b = a);
4074        Self { buttons, axes }
4075    }
4076}
4077
4078impl GamepadState {
4079    pub fn get_button_state(&self, button: GamepadButton) -> Action {
4080        self.buttons[button as usize]
4081    }
4082
4083    pub fn get_axis(&self, axis: GamepadAxis) -> f32 {
4084        self.axes[axis as usize]
4085    }
4086}
4087
4088#[inline(always)]
4089fn unwrap_dont_care(value: Option<u32>) -> c_int {
4090    match value {
4091        Some(v) => v as c_int,
4092        None => ffi::DONT_CARE,
4093    }
4094}