#![crate_type = "lib"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![crate_name = "glfw"]
#![deny(
rust_2018_compatibility,
rust_2018_idioms,
nonstandard_style,
unused,
future_incompatible,
missing_copy_implementations,
missing_debug_implementations,
missing_abi,
clippy::doc_markdown
)]
#![allow(non_upper_case_globals)]
macro_rules! make_user_callback_functions {
    (
        doc -> $doc:literal,
        set -> $set:ident,
        unset -> $unset:ident,
        poll -> $poll:ident,
        callback_field -> $callback_field:ident,
        poll_field -> $poll_field:ident,
        glfw -> $glfw:ident,
        args -> ($($args:ty),*),
        secret -> $secret:ident
    ) => {
        #[doc = $doc]
        pub fn $set<T>(&mut self, callback: T)
        where T: FnMut(&mut Window, $($args),*) + 'static {
            unsafe {
                let callbacks = WindowCallbacks::get_callbacks(self.ptr);
                callbacks.$callback_field = Some(Box::new(callback));
                ffi::$glfw(self.ptr, Some(Self::$secret));
            }
        }
        #[doc = $doc]
        pub fn $unset(&mut self) {
            unsafe {
                let callbacks = WindowCallbacks::get_callbacks(self.ptr);
                callbacks.$callback_field = None;
                if !callbacks.$poll_field {
                    ffi::$glfw(self.ptr, None);
                }
            }
        }
        #[doc = $doc]
        pub fn $poll(&mut self, should_poll: bool) {
            unsafe {
                let callbacks = WindowCallbacks::get_callbacks(self.ptr);
                callbacks.$poll_field = should_poll;
                if should_poll {
                    ffi::$glfw(self.ptr, Some(Self::$secret));
                } else if callbacks.$callback_field.is_none() {
                    ffi::$glfw(self.ptr, None);
                }
            }
        }
    }
}
macro_rules! new_callback {
    (
        doc -> $doc:literal,
        set -> $set:ident,
        unset -> $unset:ident,
        poll -> $poll:ident,
        callback_field -> $callback_field:ident,
        poll_field -> $poll_field:ident,
        window_event -> $window_event:ident ($($args:ty),+),
        glfw -> $glfw:ident ($($glfw_arg_names:ident: $glfw_args:ty),*),
        convert_args -> ($($convert_args:expr),*),
        secret -> $secret:ident
    ) => {
        #[allow(unused_unsafe)]
        extern "C" fn $secret(glfw_window: *mut GLFWwindow, $($glfw_arg_names: $glfw_args),*) {
            unsafe {
                let callbacks = WindowCallbacks::get_callbacks(glfw_window);
                let window = &mut *callbacks.window_ptr;
                if let Some(func) = &mut callbacks.$callback_field {
                    func(window, $($convert_args),*);
                }
                if callbacks.$poll_field {
                    let event = (ffi::glfwGetTime() as f64, WindowEvent::$window_event($($convert_args),*));
                    if let Some(event) = callbacks::unbuffered::handle(glfw_window as WindowId, event) {
                        callbacks.sender.send(event);
                    }
                }
            }
        }
        make_user_callback_functions!(
            doc -> $doc,
            set -> $set,
            unset -> $unset,
            poll -> $poll,
            callback_field -> $callback_field,
            poll_field -> $poll_field,
            glfw -> $glfw,
            args -> ($($args),*),
            secret -> $secret
        );
    };
    (
        doc -> $doc:literal,
        set -> $set:ident,
        unset -> $unset:ident,
        poll -> $poll:ident,
        callback_field -> $callback_field:ident,
        poll_field -> $poll_field:ident,
        window_event -> $window_event:ident,
        glfw -> $glfw:ident ($($glfw_arg_names:ident: $glfw_args:ty),*),
        convert_args -> ($($convert_args:expr),*),
        secret -> $secret:ident
    ) => {
        #[allow(unused_unsafe)]
        extern "C" fn $secret(glfw_window: *mut GLFWwindow, $($glfw_arg_names: $glfw_args),*) {
            unsafe {
                let callbacks = WindowCallbacks::get_callbacks(glfw_window);
                let window = &mut *callbacks.window_ptr;
                if let Some(func) = &mut callbacks.$callback_field {
                    func(window);
                }
                if callbacks.$poll_field {
                    let event = (ffi::glfwGetTime() as f64, WindowEvent::$window_event);
                    if let Some(event) = callbacks::unbuffered::handle(glfw_window as WindowId, event) {
                        callbacks.sender.send(event);
                    }
                }
            }
        }
        make_user_callback_functions!(
            doc -> $doc,
            set -> $set,
            unset -> $unset,
            poll -> $poll,
            callback_field -> $callback_field,
            poll_field -> $poll_field,
            glfw -> $glfw,
            args -> (),
            secret -> $secret
        );
    }
}
#[cfg(feature = "log")]
#[macro_use]
extern crate log;
#[macro_use]
extern crate bitflags;
#[cfg(feature = "image")]
extern crate image;
#[cfg(feature = "raw-window-handle-v0-6")]
extern crate raw_window_handle_0_6 as raw_window_handle;
#[cfg(feature = "raw-window-handle-v0-5")]
extern crate raw_window_handle_0_5 as raw_window_handle;
use std::collections::VecDeque;
#[cfg(feature = "raw-window-handle-v0-5")]
use raw_window_handle::{HasRawWindowHandle, HasRawDisplayHandle};
#[cfg(feature = "raw-window-handle-v0-6")]
use raw_window_handle::{HasDisplayHandle, HasWindowHandle, WindowHandle, HandleError, DisplayHandle};
use raw_window_handle::{RawWindowHandle, RawDisplayHandle};
use std::error;
use std::ffi::{CStr, CString};
use std::fmt;
use std::marker::Send;
use std::mem;
#[cfg(feature = "vulkan")]
use std::os::raw::c_uint;
use std::os::raw::{c_char, c_double, c_float, c_int};
use std::os::raw::{c_uchar, c_ushort};
#[cfg(not(target_os = "emscripten"))]
use std::os::raw::c_void;
use std::path::PathBuf;
use std::ptr;
use std::ptr::{null, null_mut};
use std::slice;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{channel, Receiver, Sender};
#[allow(unused)]
use std::ffi::*;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Mutex};
#[cfg(feature = "vulkan")]
use ash::vk;
use crate::ffi::GLFWwindow;
pub use self::MouseButton::Button1 as MouseButtonLeft;
pub use self::MouseButton::Button2 as MouseButtonRight;
pub use self::MouseButton::Button3 as MouseButtonMiddle;
mod callbacks;
pub mod ffi;
#[derive(Debug)]
#[repr(transparent)]
pub struct PWindow(Box<Window>);
impl PWindow {
    fn raw_ptr(&mut self) -> *mut Window {
        self.0.deref_mut()
    }
}
impl Deref for PWindow {
    type Target = Window;
    fn deref(&self) -> &Self::Target {
        self.0.deref()
    }
}
impl DerefMut for PWindow {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.0.deref_mut()
    }
}
unsafe impl Send for PWindow {}
unsafe impl Sync for PWindow {}
#[cfg(feature = "raw-window-handle-v0-6")]
impl HasWindowHandle for PWindow {
    fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
        self.0.window_handle()
    }
}
#[cfg(feature = "raw-window-handle-v0-6")]
impl HasDisplayHandle for PWindow {
    fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
        self.0.display_handle()
    }
}
pub type WindowId = usize;
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Version {
    pub major: u64,
    pub minor: u64,
    pub patch: u64,
}
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum Action {
    Release = ffi::RELEASE,
    Press = ffi::PRESS,
    Repeat = ffi::REPEAT,
}
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum Key {
    Space = ffi::KEY_SPACE,
    Apostrophe = ffi::KEY_APOSTROPHE,
    Comma = ffi::KEY_COMMA,
    Minus = ffi::KEY_MINUS,
    Period = ffi::KEY_PERIOD,
    Slash = ffi::KEY_SLASH,
    Num0 = ffi::KEY_0,
    Num1 = ffi::KEY_1,
    Num2 = ffi::KEY_2,
    Num3 = ffi::KEY_3,
    Num4 = ffi::KEY_4,
    Num5 = ffi::KEY_5,
    Num6 = ffi::KEY_6,
    Num7 = ffi::KEY_7,
    Num8 = ffi::KEY_8,
    Num9 = ffi::KEY_9,
    Semicolon = ffi::KEY_SEMICOLON,
    Equal = ffi::KEY_EQUAL,
    A = ffi::KEY_A,
    B = ffi::KEY_B,
    C = ffi::KEY_C,
    D = ffi::KEY_D,
    E = ffi::KEY_E,
    F = ffi::KEY_F,
    G = ffi::KEY_G,
    H = ffi::KEY_H,
    I = ffi::KEY_I,
    J = ffi::KEY_J,
    K = ffi::KEY_K,
    L = ffi::KEY_L,
    M = ffi::KEY_M,
    N = ffi::KEY_N,
    O = ffi::KEY_O,
    P = ffi::KEY_P,
    Q = ffi::KEY_Q,
    R = ffi::KEY_R,
    S = ffi::KEY_S,
    T = ffi::KEY_T,
    U = ffi::KEY_U,
    V = ffi::KEY_V,
    W = ffi::KEY_W,
    X = ffi::KEY_X,
    Y = ffi::KEY_Y,
    Z = ffi::KEY_Z,
    LeftBracket = ffi::KEY_LEFT_BRACKET,
    Backslash = ffi::KEY_BACKSLASH,
    RightBracket = ffi::KEY_RIGHT_BRACKET,
    GraveAccent = ffi::KEY_GRAVE_ACCENT,
    World1 = ffi::KEY_WORLD_1,
    World2 = ffi::KEY_WORLD_2,
    Escape = ffi::KEY_ESCAPE,
    Enter = ffi::KEY_ENTER,
    Tab = ffi::KEY_TAB,
    Backspace = ffi::KEY_BACKSPACE,
    Insert = ffi::KEY_INSERT,
    Delete = ffi::KEY_DELETE,
    Right = ffi::KEY_RIGHT,
    Left = ffi::KEY_LEFT,
    Down = ffi::KEY_DOWN,
    Up = ffi::KEY_UP,
    PageUp = ffi::KEY_PAGE_UP,
    PageDown = ffi::KEY_PAGE_DOWN,
    Home = ffi::KEY_HOME,
    End = ffi::KEY_END,
    CapsLock = ffi::KEY_CAPS_LOCK,
    ScrollLock = ffi::KEY_SCROLL_LOCK,
    NumLock = ffi::KEY_NUM_LOCK,
    PrintScreen = ffi::KEY_PRINT_SCREEN,
    Pause = ffi::KEY_PAUSE,
    F1 = ffi::KEY_F1,
    F2 = ffi::KEY_F2,
    F3 = ffi::KEY_F3,
    F4 = ffi::KEY_F4,
    F5 = ffi::KEY_F5,
    F6 = ffi::KEY_F6,
    F7 = ffi::KEY_F7,
    F8 = ffi::KEY_F8,
    F9 = ffi::KEY_F9,
    F10 = ffi::KEY_F10,
    F11 = ffi::KEY_F11,
    F12 = ffi::KEY_F12,
    F13 = ffi::KEY_F13,
    F14 = ffi::KEY_F14,
    F15 = ffi::KEY_F15,
    F16 = ffi::KEY_F16,
    F17 = ffi::KEY_F17,
    F18 = ffi::KEY_F18,
    F19 = ffi::KEY_F19,
    F20 = ffi::KEY_F20,
    F21 = ffi::KEY_F21,
    F22 = ffi::KEY_F22,
    F23 = ffi::KEY_F23,
    F24 = ffi::KEY_F24,
    F25 = ffi::KEY_F25,
    Kp0 = ffi::KEY_KP_0,
    Kp1 = ffi::KEY_KP_1,
    Kp2 = ffi::KEY_KP_2,
    Kp3 = ffi::KEY_KP_3,
    Kp4 = ffi::KEY_KP_4,
    Kp5 = ffi::KEY_KP_5,
    Kp6 = ffi::KEY_KP_6,
    Kp7 = ffi::KEY_KP_7,
    Kp8 = ffi::KEY_KP_8,
    Kp9 = ffi::KEY_KP_9,
    KpDecimal = ffi::KEY_KP_DECIMAL,
    KpDivide = ffi::KEY_KP_DIVIDE,
    KpMultiply = ffi::KEY_KP_MULTIPLY,
    KpSubtract = ffi::KEY_KP_SUBTRACT,
    KpAdd = ffi::KEY_KP_ADD,
    KpEnter = ffi::KEY_KP_ENTER,
    KpEqual = ffi::KEY_KP_EQUAL,
    LeftShift = ffi::KEY_LEFT_SHIFT,
    LeftControl = ffi::KEY_LEFT_CONTROL,
    LeftAlt = ffi::KEY_LEFT_ALT,
    LeftSuper = ffi::KEY_LEFT_SUPER,
    RightShift = ffi::KEY_RIGHT_SHIFT,
    RightControl = ffi::KEY_RIGHT_CONTROL,
    RightAlt = ffi::KEY_RIGHT_ALT,
    RightSuper = ffi::KEY_RIGHT_SUPER,
    Menu = ffi::KEY_MENU,
    Unknown = ffi::KEY_UNKNOWN,
}
pub fn get_key_name(key: Option<Key>, scancode: Option<Scancode>) -> Option<String> {
    unsafe {
        string_from_nullable_c_str(ffi::glfwGetKeyName(
            match key {
                Some(k) => k as c_int,
                None => ffi::KEY_UNKNOWN,
            },
            scancode.unwrap_or(ffi::KEY_UNKNOWN),
        ))
    }
}
#[deprecated(
since = "0.16.0",
note = "'key_name' can cause a segfault, use 'get_key_name' instead"
)]
pub fn key_name(key: Option<Key>, scancode: Option<Scancode>) -> String {
    unsafe {
        string_from_c_str(ffi::glfwGetKeyName(
            match key {
                Some(k) => k as c_int,
                None => ffi::KEY_UNKNOWN,
            },
            scancode.unwrap_or(ffi::KEY_UNKNOWN),
        ))
    }
}
pub fn get_key_scancode(key: Option<Key>) -> Option<Scancode> {
    unsafe {
        match ffi::glfwGetKeyScancode(match key {
            Some(key) => key as c_int,
            None => ffi::KEY_UNKNOWN,
        }) {
            ffi::KEY_UNKNOWN => None,
            scancode => Some(scancode as Scancode),
        }
    }
}
impl Key {
    #[deprecated(
    since = "0.16.0",
    note = "Key method 'name' can cause a segfault, use 'get_name' instead"
    )]
    pub fn name(&self) -> String {
        #[allow(deprecated)]
        key_name(Some(*self), None)
    }
    pub fn get_name(&self) -> Option<String> {
        get_key_name(Some(*self), None)
    }
    pub fn get_scancode(&self) -> Option<Scancode> {
        get_key_scancode(Some(*self))
    }
}
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum MouseButton {
    Button1 = ffi::MOUSE_BUTTON_1,
    Button2 = ffi::MOUSE_BUTTON_2,
    Button3 = ffi::MOUSE_BUTTON_3,
    Button4 = ffi::MOUSE_BUTTON_4,
    Button5 = ffi::MOUSE_BUTTON_5,
    Button6 = ffi::MOUSE_BUTTON_6,
    Button7 = ffi::MOUSE_BUTTON_7,
    Button8 = ffi::MOUSE_BUTTON_8,
}
impl MouseButton {
    pub fn from_i32(n: i32) -> Option<MouseButton> {
        if (0..=ffi::MOUSE_BUTTON_LAST).contains(&n) {
            Some(unsafe { mem::transmute(n) })
        } else {
            None
        }
    }
}
pub struct DebugAliases<T>(pub T);
impl fmt::Debug for DebugAliases<MouseButton> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let DebugAliases(button) = *self;
        match button {
            MouseButtonLeft => write!(f, "MouseButtonLeft"),
            MouseButtonRight => write!(f, "MouseButtonRight"),
            MouseButtonMiddle => write!(f, "MouseButtonMiddle"),
            button => button.fmt(f),
        }
    }
}
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum Error {
    NoError = ffi::NO_ERROR,
    NotInitialized = ffi::NOT_INITIALIZED,
    NoCurrentContext = ffi::NO_CURRENT_CONTEXT,
    InvalidEnum = ffi::INVALID_ENUM,
    InvalidValue = ffi::INVALID_VALUE,
    OutOfMemory = ffi::OUT_OF_MEMORY,
    ApiUnavailable = ffi::API_UNAVAILABLE,
    VersionUnavailable = ffi::VERSION_UNAVAILABLE,
    PlatformError = ffi::PLATFORM_ERROR,
    FormatUnavailable = ffi::FORMAT_UNAVAILABLE,
    NoWindowContext = ffi::NO_WINDOW_CONTEXT,
}
impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let description = match *self {
            Error::NoError => "NoError",
            Error::NotInitialized => "NotInitialized",
            Error::NoCurrentContext => "NoCurrentContext",
            Error::InvalidEnum => "InvalidEnum",
            Error::InvalidValue => "InvalidValue",
            Error::OutOfMemory => "OutOfMemory",
            Error::ApiUnavailable => "ApiUnavailable",
            Error::VersionUnavailable => "VersionUnavailable",
            Error::PlatformError => "PlatformError",
            Error::FormatUnavailable => "FormatUnavailable",
            Error::NoWindowContext => "NoWindowContext",
        };
        f.write_str(description)
    }
}
impl error::Error for Error {}
pub fn fail_on_errors(_: Error, description: String) {
    panic!("GLFW Error: {}", description);
}
#[macro_export]
macro_rules! fail_on_errors {
    () => {{
        |error, description| {
            fail_on_errors(error, description);
        }
    }}
}
#[cfg(feature = "log")]
pub fn log_errors(_: Error, description: String) {
    error!("GLFW Error: {}", description);
}
#[cfg(not(feature = "log"))]
pub fn log_errors(_: Error, description: String) {
    eprintln!("GLFW Error: {}", description);
}
#[macro_export]
macro_rules! log_errors {
    () => {{
        |error, description| {
            log_errors(error, description);
        }
    }}
}
#[derive(Debug)]
pub struct PixelImage {
    pub width: u32,
    pub height: u32,
    pub pixels: Vec<u32>,
}
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum CursorMode {
    Normal = ffi::CURSOR_NORMAL,
    Hidden = ffi::CURSOR_HIDDEN,
    Disabled = ffi::CURSOR_DISABLED,
}
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum StandardCursor {
    Arrow = ffi::ARROW_CURSOR,
    IBeam = ffi::IBEAM_CURSOR,
    Crosshair = ffi::CROSSHAIR_CURSOR,
    Hand = ffi::HAND_CURSOR,
    HResize = ffi::HRESIZE_CURSOR,
    VResize = ffi::VRESIZE_CURSOR,
}
#[derive(Debug)]
pub struct Cursor {
    ptr: *mut ffi::GLFWcursor,
}
impl Drop for Cursor {
    fn drop(&mut self) {
        unsafe { ffi::glfwDestroyCursor(self.ptr) }
    }
}
impl Cursor {
    pub fn standard(cursor: StandardCursor) -> Cursor {
        Cursor {
            ptr: unsafe { ffi::glfwCreateStandardCursor(cursor as c_int) },
        }
    }
    #[cfg(feature = "image")]
    pub fn create(image: image::RgbaImage, x_hotspot: u32, y_hotspot: u32) -> Cursor {
        let (width, height) = image.dimensions();
        let image_data = image.into_vec();
        let glfw_image = ffi::GLFWimage {
            width: width as c_int,
            height: height as c_int,
            pixels: image_data.as_ptr() as *const c_uchar,
        };
        Cursor {
            ptr: unsafe {
                ffi::glfwCreateCursor(
                    &glfw_image as *const ffi::GLFWimage,
                    x_hotspot as c_int,
                    y_hotspot as c_int,
                )
            },
        }
    }
    pub fn create_from_pixels(image: PixelImage, x_hotspot: u32, y_hotspot: u32) -> Cursor {
        let glfw_image = ffi::GLFWimage {
            width: image.width as c_int,
            height: image.height as c_int,
            pixels: image.pixels.as_ptr() as *const c_uchar,
        };
        Cursor {
            ptr: unsafe {
                ffi::glfwCreateCursor(
                    &glfw_image as *const ffi::GLFWimage,
                    x_hotspot as c_int,
                    y_hotspot as c_int,
                )
            },
        }
    }
}
#[derive(Copy, Clone)]
pub struct VidMode {
    pub width: u32,
    pub height: u32,
    pub red_bits: u32,
    pub green_bits: u32,
    pub blue_bits: u32,
    pub refresh_rate: u32,
}
#[derive(Debug)]
pub struct GammaRamp {
    pub red: Vec<c_ushort>,
    pub green: Vec<c_ushort>,
    pub blue: Vec<c_ushort>,
}
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum ContextReleaseBehavior {
    Any = ffi::ANY_RELEASE_BEHAVIOR,
    Flush = ffi::RELEASE_BEHAVIOR_FLUSH,
    None = ffi::RELEASE_BEHAVIOR_NONE,
}
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum ContextCreationApi {
    Native = ffi::NATIVE_CONTEXT_API,
    Egl = ffi::EGL_CONTEXT_API,
    OsMesa = ffi::OSMESA_CONTEXT_API,
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum SwapInterval {
    None,
    Adaptive,
    Sync(u32),
}
pub type GLProc = ffi::GLFWglproc;
#[cfg(feature = "vulkan")]
pub type VkProc = ffi::GLFWvkproc;
static REF_COUNT_FOR_GLFW: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
pub struct ThreadSafeGlfw {
    glfw: Glfw
}
impl ThreadSafeGlfw {
    pub fn from(glfw: &mut Glfw) -> Self {
        Self {
            glfw: glfw.clone()
        }
    }
    pub fn set_swap_interval(&mut self, interval: SwapInterval) {
        self.glfw.set_swap_interval(interval);
    }
    pub fn extension_supported(&self, extension: &str) -> bool {
        self.glfw.extension_supported(extension)
    }
    pub fn get_time(&self) -> f64 {
        self.glfw.get_time()
    }
    pub fn set_time(&mut self, time: f64) {
        self.glfw.set_time(time);
    }
    #[cfg(feature = "vulkan")]
    pub fn vulkan_supported(&self) -> bool {
        self.glfw.vulkan_supported()
    }
    #[cfg(feature = "vulkan")]
    pub fn get_required_instance_extensions(&self) -> Option<Vec<String>> {
        self.glfw.get_required_instance_extensions()
    }
    #[cfg(feature = "vulkan")]
    pub fn get_instance_proc_address_raw(&self, instance: vk::Instance, procname: &str) -> VkProc {
        self.glfw.get_instance_proc_address_raw(instance, procname)
    }
    #[cfg(feature = "vulkan")]
    pub fn get_physical_device_presentation_support_raw(
        &self,
        instance: vk::Instance,
        device: vk::PhysicalDevice,
        queue_family: u32,
    ) -> bool {
        self.glfw.get_physical_device_presentation_support_raw(instance, device, queue_family)
    }
    pub fn get_timer_value(&self) -> u64 {
        self.glfw.get_timer_value()
    }
    pub fn get_timer_frequency(&self) -> u64 {
        self.glfw.get_timer_frequency()
    }
    pub fn post_empty_event(&self) {
        self.glfw.post_empty_event()
    }
}
unsafe impl Send for ThreadSafeGlfw {}
#[non_exhaustive]
#[derive(Debug)]
pub struct Glfw {
    phantom: std::marker::PhantomData<*const ()>,
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum InitError {
    AlreadyInitialized,
    Internal,
}
impl fmt::Display for InitError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let description = match *self {
            InitError::AlreadyInitialized => "Already Initialized",
            InitError::Internal => "Internal Initialization Error",
        };
        f.write_str(description)
    }
}
impl error::Error for InitError {}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum InitHint {
    JoystickHatButtons(bool),
    CocoaChdirResources(bool),
    CocoaMenubar(bool),
}
pub fn init_hint(hint: InitHint) {
    match hint {
        InitHint::JoystickHatButtons(joystick_hat_buttons) => unsafe {
            ffi::glfwInitHint(ffi::JOYSTICK_HAT_BUTTONS, joystick_hat_buttons as c_int)
        },
        InitHint::CocoaChdirResources(chdir) => unsafe {
            ffi::glfwInitHint(ffi::COCOA_CHDIR_RESOURCES, chdir as c_int)
        },
        InitHint::CocoaMenubar(menubar) => unsafe {
            ffi::glfwInitHint(ffi::COCOA_MENUBAR, menubar as c_int)
        },
    }
}
pub fn init<T>(callback: T)
    -> Result<Glfw, InitError>
    where T: FnMut(Error, String) + 'static
{
    callbacks::error::set(callback);
    init_no_callbacks()
}
pub fn init_no_callbacks() -> Result<Glfw, InitError>
{
    if unsafe { ffi::glfwInit() } == ffi::TRUE {
        REF_COUNT_FOR_GLFW.fetch_add(1, Ordering::SeqCst);
        Ok(Glfw {phantom: std::marker::PhantomData})
    } else {
        Err(InitError::Internal)
    }
}
impl Glfw {
    pub fn set_error_callback<T>(
        &mut self,
        callback: T,
    )
    where T: FnMut(Error, String) + 'static
    {
        callbacks::error::set(callback);
    }
    pub fn unset_error_callback(
        &mut self,
    )
    {
        callbacks::error::unset();
    }
    pub fn set_monitor_callback<T>(
        &mut self,
        callback: T
    )
    where T: FnMut(Monitor, MonitorEvent) + 'static
    {
        callbacks::monitor::set(callback);
    }
    pub fn unset_monitor_callback(
        &mut self,
    )
    {
        callbacks::monitor::unset();
    }
    pub fn set_joystick_callback<T>(
        &mut self,
        callback: T,
    )
    where T: FnMut(JoystickId, JoystickEvent) + 'static
    {
        callbacks::joystick::set(callback);
    }
    pub fn unset_joystick_callback(
        &mut self,
    )
    {
        callbacks::joystick::unset();
    }
    pub fn with_primary_monitor<T, F>(&mut self, f: F) -> T
    where
        F: FnOnce(&mut Self, Option<&mut Monitor>) -> T,
    {
        match unsafe { ffi::glfwGetPrimaryMonitor() } {
            ptr if ptr.is_null() => f(self, None),
            ptr => f(self, Some(&mut Monitor { ptr })),
        }
    }
    pub fn with_window_monitor<T, F>(&mut self, window: &mut Window, f: F) -> T
        where
            F: FnOnce(&mut Self, Option<&mut Monitor>) -> T,
    {
        match unsafe { ffi::glfwGetWindowMonitor(window.ptr) } {
            ptr if ptr.is_null() => f(self, None),
            ptr => f(self, Some(&mut Monitor { ptr })),
        }
    }
    pub fn with_connected_monitors<T, F>(&mut self, f: F) -> T
    where
        F: FnOnce(&mut Self, &[&mut Monitor]) -> T,
    {
        unsafe {
            let mut count = 0;
            let ptr = ffi::glfwGetMonitors(&mut count);
            let mut monitors = slice::from_raw_parts(ptr as *const _, count as usize)
                .iter()
                .map(|&ptr| Monitor { ptr })
                .collect::<Vec<Monitor>>();
            let refs: Vec<&mut Monitor> = monitors
                .iter_mut()
                .collect();
            f(self, &refs)
        }
    }
    #[cfg(feature = "vulkan")]
    pub fn vulkan_supported(&self) -> bool {
        unsafe { ffi::glfwVulkanSupported() == ffi::TRUE }
    }
    pub fn window_hint(&mut self, hint: WindowHint) {
        #[inline(always)]
        unsafe fn dont_care_hint(hint: c_int, value: Option<u32>) {
            ffi::glfwWindowHint(hint, unwrap_dont_care(value))
        }
        #[inline(always)]
        unsafe fn string_hint(hint: c_int, value: Option<String>) {
            let value = if let Some(value) = &value {
                value.as_str()
            } else {
                ""
            };
            with_c_str(value, |value| ffi::glfwWindowHintString(hint, value))
        }
        match hint {
            WindowHint::RedBits(bits) => unsafe { dont_care_hint(ffi::RED_BITS, bits) },
            WindowHint::GreenBits(bits) => unsafe { dont_care_hint(ffi::GREEN_BITS, bits) },
            WindowHint::BlueBits(bits) => unsafe { dont_care_hint(ffi::BLUE_BITS, bits) },
            WindowHint::AlphaBits(bits) => unsafe { dont_care_hint(ffi::ALPHA_BITS, bits) },
            WindowHint::DepthBits(bits) => unsafe { dont_care_hint(ffi::DEPTH_BITS, bits) },
            WindowHint::StencilBits(bits) => unsafe { dont_care_hint(ffi::STENCIL_BITS, bits) },
            WindowHint::AccumRedBits(bits) => unsafe { dont_care_hint(ffi::ACCUM_RED_BITS, bits) },
            WindowHint::AccumGreenBits(bits) => unsafe {
                dont_care_hint(ffi::ACCUM_GREEN_BITS, bits)
            },
            WindowHint::AccumBlueBits(bits) => unsafe {
                dont_care_hint(ffi::ACCUM_BLUE_BITS, bits)
            },
            WindowHint::AccumAlphaBits(bits) => unsafe {
                dont_care_hint(ffi::ACCUM_ALPHA_BITS, bits)
            },
            WindowHint::AuxBuffers(num_buffers) => unsafe {
                dont_care_hint(ffi::AUX_BUFFERS, num_buffers)
            },
            WindowHint::Samples(num_samples) => unsafe {
                dont_care_hint(ffi::SAMPLES, num_samples)
            },
            WindowHint::RefreshRate(rate) => unsafe { dont_care_hint(ffi::REFRESH_RATE, rate) },
            WindowHint::Stereo(is_stereo) => unsafe {
                ffi::glfwWindowHint(ffi::STEREO, is_stereo as c_int)
            },
            WindowHint::SRgbCapable(is_capable) => unsafe {
                ffi::glfwWindowHint(ffi::SRGB_CAPABLE, is_capable as c_int)
            },
            WindowHint::ClientApi(api) => unsafe {
                ffi::glfwWindowHint(ffi::CLIENT_API, api as c_int)
            },
            WindowHint::ContextVersionMajor(major) => unsafe {
                ffi::glfwWindowHint(ffi::CONTEXT_VERSION_MAJOR, major as c_int)
            },
            WindowHint::ContextVersionMinor(minor) => unsafe {
                ffi::glfwWindowHint(ffi::CONTEXT_VERSION_MINOR, minor as c_int)
            },
            WindowHint::ContextVersion(major, minor) => unsafe {
                ffi::glfwWindowHint(ffi::CONTEXT_VERSION_MAJOR, major as c_int);
                ffi::glfwWindowHint(ffi::CONTEXT_VERSION_MINOR, minor as c_int)
            },
            WindowHint::ContextRobustness(robustness) => unsafe {
                ffi::glfwWindowHint(ffi::CONTEXT_ROBUSTNESS, robustness as c_int)
            },
            WindowHint::OpenGlForwardCompat(is_compat) => unsafe {
                ffi::glfwWindowHint(ffi::OPENGL_FORWARD_COMPAT, is_compat as c_int)
            },
            WindowHint::OpenGlDebugContext(is_debug) => unsafe {
                ffi::glfwWindowHint(ffi::OPENGL_DEBUG_CONTEXT, is_debug as c_int)
            },
            WindowHint::OpenGlProfile(profile) => unsafe {
                ffi::glfwWindowHint(ffi::OPENGL_PROFILE, profile as c_int)
            },
            WindowHint::Resizable(is_resizable) => unsafe {
                ffi::glfwWindowHint(ffi::RESIZABLE, is_resizable as c_int)
            },
            WindowHint::Visible(is_visible) => unsafe {
                ffi::glfwWindowHint(ffi::VISIBLE, is_visible as c_int)
            },
            WindowHint::Decorated(is_decorated) => unsafe {
                ffi::glfwWindowHint(ffi::DECORATED, is_decorated as c_int)
            },
            WindowHint::AutoIconify(auto_iconify) => unsafe {
                ffi::glfwWindowHint(ffi::AUTO_ICONIFY, auto_iconify as c_int)
            },
            WindowHint::Floating(is_floating) => unsafe {
                ffi::glfwWindowHint(ffi::FLOATING, is_floating as c_int)
            },
            WindowHint::Focused(is_focused) => unsafe {
                ffi::glfwWindowHint(ffi::FOCUSED, is_focused as c_int)
            },
            WindowHint::Maximized(is_maximized) => unsafe {
                ffi::glfwWindowHint(ffi::MAXIMIZED, is_maximized as c_int)
            },
            WindowHint::ContextNoError(is_no_error) => unsafe {
                ffi::glfwWindowHint(ffi::CONTEXT_NO_ERROR, is_no_error as c_int)
            },
            WindowHint::ContextCreationApi(api) => unsafe {
                ffi::glfwWindowHint(ffi::CONTEXT_CREATION_API, api as c_int)
            },
            WindowHint::ContextReleaseBehavior(behavior) => unsafe {
                ffi::glfwWindowHint(ffi::CONTEXT_RELEASE_BEHAVIOR, behavior as c_int)
            },
            WindowHint::DoubleBuffer(is_dbuffered) => unsafe {
                ffi::glfwWindowHint(ffi::DOUBLEBUFFER, is_dbuffered as c_int)
            },
            WindowHint::CenterCursor(center_cursor) => unsafe {
                ffi::glfwWindowHint(ffi::CENTER_CURSOR, center_cursor as c_int)
            },
            WindowHint::TransparentFramebuffer(is_transparent) => unsafe {
                ffi::glfwWindowHint(ffi::TRANSPARENT_FRAMEBUFFER, is_transparent as c_int)
            },
            WindowHint::FocusOnShow(focus) => unsafe {
                ffi::glfwWindowHint(ffi::FOCUS_ON_SHOW, focus as c_int)
            },
            WindowHint::ScaleToMonitor(scale) => unsafe {
                ffi::glfwWindowHint(ffi::SCALE_TO_MONITOR, scale as c_int)
            },
            WindowHint::CocoaRetinaFramebuffer(retina_fb) => unsafe {
                ffi::glfwWindowHint(ffi::COCOA_RETINA_FRAMEBUFFER, retina_fb as c_int)
            },
            WindowHint::CocoaFrameName(name) => unsafe { string_hint(ffi::COCOA_FRAME_NAME, name) },
            WindowHint::CocoaGraphicsSwitching(graphics_switching) => unsafe {
                ffi::glfwWindowHint(ffi::COCOA_GRAPHICS_SWITCHING, graphics_switching as c_int)
            },
            WindowHint::X11ClassName(class_name) => unsafe {
                string_hint(ffi::X11_CLASS_NAME, class_name)
            },
            WindowHint::X11InstanceName(instance_name) => unsafe {
                string_hint(ffi::X11_INSTANCE_NAME, instance_name)
            },
        }
    }
    pub fn default_window_hints(&mut self) {
        unsafe {
            ffi::glfwDefaultWindowHints();
        }
    }
    pub fn create_window(
        &mut self,
        width: u32,
        height: u32,
        title: &str,
        mode: WindowMode<'_>,
    ) -> Option<(PWindow, GlfwReceiver<(f64, WindowEvent)>)> {
        #[cfg(feature = "wayland")]
        {
            self.window_hint(WindowHint::Focused(false));
        }
        self.create_window_intern(width, height, title, mode, None)
    }
    fn create_window_intern(
        &self,
        width: u32,
        height: u32,
        title: &str,
        mode: WindowMode<'_>,
        share: Option<&Window>,
    ) -> Option<(PWindow, GlfwReceiver<(f64, WindowEvent)>)> {
        let ptr = unsafe {
            with_c_str(title, |title| {
                ffi::glfwCreateWindow(
                    width as c_int,
                    height as c_int,
                    title,
                    mode.to_ptr(),
                    match share {
                        Some(w) => w.ptr,
                        None => ptr::null_mut(),
                    },
                )
            })
        };
        if ptr.is_null() {
            None
        } else {
            let (drop_sender, drop_receiver) = channel();
            let (sender, receiver) = glfw_channel(16, 256);
            let window = Window {
                ptr,
                glfw: self.clone(),
                is_shared: share.is_some(),
                drop_sender: Some(drop_sender),
                drop_receiver,
                current_cursor: None,
            };
            let mut callbacks = Box::new(WindowCallbacks::new(sender));
            let mut window = PWindow(Box::new(window));
            unsafe {
                callbacks.window_ptr = window.raw_ptr();
                ffi::glfwSetWindowUserPointer(ptr, mem::transmute(callbacks));
            }
            Some((window, receiver))
        }
    }
    pub fn make_context_current(&mut self, context: Option<&Window>) {
        match context {
            Some(window) => unsafe { ffi::glfwMakeContextCurrent(window.ptr) },
            None => unsafe { ffi::glfwMakeContextCurrent(ptr::null_mut()) },
        }
    }
    #[cfg(all(target_os = "linux", not(feature = "wayland")))]
    pub fn get_x11_display(&self) -> *mut c_void {
        unsafe { ffi::glfwGetX11Display() }
    }
    #[cfg(all(target_os = "linux", feature = "wayland"))]
    pub fn get_wayland_display(&self) -> *mut c_void {
        unsafe { ffi::glfwGetWaylandDisplay() }
    }
    pub fn poll_events(&mut self) {
        unsafe {
            ffi::glfwPollEvents();
        }
    }
    pub fn poll_events_unbuffered<F>(&mut self, mut f: F)
        where
            F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>,
    {
        let _unset_handler_guard = unsafe { crate::callbacks::unbuffered::set_handler(&mut f) };
        self.poll_events();
    }
    pub fn wait_events(&mut self) {
        unsafe {
            ffi::glfwWaitEvents();
        }
    }
    pub fn wait_events_unbuffered<F>(&mut self, mut f: F)
        where
            F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>,
    {
        let _unset_handler_guard = unsafe { crate::callbacks::unbuffered::set_handler(&mut f) };
        self.wait_events();
    }
    pub fn wait_events_timeout(&mut self, timeout: f64) {
        unsafe {
            ffi::glfwWaitEventsTimeout(timeout);
        }
    }
    pub fn wait_events_timeout_unbuffered<F>(&mut self, timeout: f64, mut f: F)
        where
            F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>,
    {
        let _unset_handler_guard = unsafe { crate::callbacks::unbuffered::set_handler(&mut f) };
        self.wait_events_timeout(timeout);
    }
    pub fn post_empty_event(&self) {
        unsafe {
            ffi::glfwPostEmptyEvent();
        }
    }
    pub fn get_time(&self) -> f64 {
        unsafe { ffi::glfwGetTime() as f64 }
    }
    pub fn set_time(&mut self, time: f64) {
        unsafe {
            ffi::glfwSetTime(time as c_double);
        }
    }
    pub fn get_timer_value(&self) -> u64 {
        unsafe { ffi::glfwGetTimerValue() as u64 }
    }
    pub fn get_timer_frequency(&self) -> u64 {
        unsafe { ffi::glfwGetTimerFrequency() as u64 }
    }
    pub fn set_swap_interval(&mut self, interval: SwapInterval) {
        unsafe {
            ffi::glfwSwapInterval(match interval {
                SwapInterval::None => 0_i32,
                SwapInterval::Adaptive => -1_i32,
                SwapInterval::Sync(interval) => interval as c_int,
            })
        }
    }
    pub fn extension_supported(&self, extension: &str) -> bool {
        unsafe {
            with_c_str(extension, |extension| {
                ffi::glfwExtensionSupported(extension) == ffi::TRUE
            })
        }
    }
    #[cfg(feature = "vulkan")]
    pub fn get_required_instance_extensions(&self) -> Option<Vec<String>> {
        let mut len: c_uint = 0;
        unsafe {
            let raw_extensions: *const *const c_char =
                ffi::glfwGetRequiredInstanceExtensions(&mut len as *mut c_uint);
            if !raw_extensions.is_null() {
                return Some(
                    slice::from_raw_parts(raw_extensions, len as usize)
                        .iter()
                        .map(|extensions| string_from_c_str(*extensions))
                        .collect(),
                );
            }
        }
        None
    }
    pub fn get_proc_address_raw(&self, procname: &str) -> GLProc {
        debug_assert!(unsafe { ffi::glfwGetCurrentContext() } != std::ptr::null_mut());
        with_c_str(procname, |procname| unsafe {
            ffi::glfwGetProcAddress(procname)
        })
    }
    #[cfg(feature = "vulkan")]
    pub fn get_instance_proc_address_raw(&self, instance: vk::Instance, procname: &str) -> VkProc {
        with_c_str(procname, |procname| unsafe {
            ffi::glfwGetInstanceProcAddress(instance, procname)
        })
    }
    #[cfg(feature = "vulkan")]
    pub fn get_physical_device_presentation_support_raw(
        &self,
        instance: vk::Instance,
        device: vk::PhysicalDevice,
        queue_family: u32,
    ) -> bool {
        vk::TRUE
            == unsafe {
            ffi::glfwGetPhysicalDevicePresentationSupport(
                instance,
                device,
                queue_family as c_uint,
            ) as u32
        }
    }
    pub fn get_joystick(&self, id: JoystickId) -> Joystick {
        Joystick {
            id,
            glfw: self.clone(),
        }
    }
    pub fn supports_raw_motion(&self) -> bool {
        unsafe { ffi::glfwRawMouseMotionSupported() == ffi::TRUE }
    }
    pub fn update_gamepad_mappings(&self, mappings: &str) -> bool {
        unsafe {
            with_c_str(mappings, |mappings| {
                ffi::glfwUpdateGamepadMappings(mappings) == ffi::TRUE
            })
        }
    }
}
impl Clone for Glfw {
    fn clone(&self) -> Self {
        REF_COUNT_FOR_GLFW.fetch_add(1, Ordering::SeqCst);
        Glfw {phantom: std::marker::PhantomData}
    }
}
impl Drop for Glfw {
    fn drop(&mut self) {
        let old_diff = REF_COUNT_FOR_GLFW.fetch_sub(1, Ordering::SeqCst);
        if old_diff == 1 {
            unsafe {
                ffi::glfwTerminate();
            }
        }
    }
}
fn glfw_channel<T>(initial_capacity: usize, max_len: usize) -> (GlfwSender<T>, GlfwReceiver<T>) {
    let shared = Arc::new(SharedTransmitter {
        queue: Mutex::new(VecDeque::with_capacity(initial_capacity)),
        max_len
    });
    let (mpsc_sender, mpsc_receiver) = channel();
    let sender = GlfwSender { transmitter: shared.clone(), sender: mpsc_sender };
    let receiver = GlfwReceiver { transmitter: shared.clone(), receiver: mpsc_receiver };
    (sender, receiver)
}
#[derive(Debug)]
struct SharedTransmitter<T> {
    queue: Mutex<VecDeque<T>>,
    max_len: usize,
}
#[derive(Debug, Clone)]
struct GlfwSender<T> {
    transmitter: Arc<SharedTransmitter<T>>,
    sender: Sender<T>
}
impl<T> GlfwSender<T> {
    fn send(&self, v: T) {
        let mut queue = self.transmitter.queue.lock().unwrap();
        if queue.len() >= self.transmitter.max_len {
            let _ = self.sender.send(v);
        } else {
            queue.push_back(v);
        }
    }
}
#[derive(Debug)]
pub struct GlfwReceiver<T> {
    transmitter: Arc<SharedTransmitter<T>>,
    receiver: Receiver<T>
}
impl<T> GlfwReceiver<T> {
    pub fn receive(&self) -> Option<T> {
        let ret = self.transmitter.queue.lock().unwrap().pop_front();
        if ret.is_some() {
            ret
        } else {
            match self.receiver.try_recv() {
                Ok(ret) => Some(ret),
                Err(_) => None
            }
        }
    }
}
struct WindowCallbacks {
    window_ptr: *mut Window,
    sender: GlfwSender<(f64, WindowEvent)>,
    pos_callback: Option<Box<dyn FnMut(&mut Window, i32, i32)>>,
    size_callback: Option<Box<dyn FnMut(&mut Window, i32, i32)>>,
    close_callback: Option<Box<dyn FnMut(&mut Window)>>,
    refresh_callback: Option<Box<dyn FnMut(&mut Window)>>,
    focus_callback: Option<Box<dyn FnMut(&mut Window, bool)>>,
    iconify_callback: Option<Box<dyn FnMut(&mut Window, bool)>>,
    framebuffer_size_callback: Option<Box<dyn FnMut(&mut Window, i32, i32)>>,
    key_callback: Option<Box<dyn FnMut(&mut Window, Key, Scancode, Action, Modifiers)>>,
    char_callback: Option<Box<dyn FnMut(&mut Window, char)>>,
    char_mods_callback: Option<Box<dyn FnMut(&mut Window, char, Modifiers)>>,
    mouse_button_callback: Option<Box<dyn FnMut(&mut Window, MouseButton, Action, Modifiers)>>,
    cursor_pos_callback: Option<Box<dyn FnMut(&mut Window, f64, f64)>>,
    cursor_enter_callback: Option<Box<dyn FnMut(&mut Window, bool)>>,
    scroll_callback: Option<Box<dyn FnMut(&mut Window, f64, f64)>>,
    drag_and_drop_callback: Option<Box<dyn FnMut(&mut Window, Vec<PathBuf>)>>,
    maximize_callback: Option<Box<dyn FnMut(&mut Window, bool)>>,
    content_scale_callback: Option<Box<dyn FnMut(&mut Window, f32, f32)>>,
    pos_polling: bool,
    size_polling: bool,
    close_polling: bool,
    refresh_polling: bool,
    focus_polling: bool,
    iconify_polling: bool,
    framebuffer_size_polling: bool,
    key_polling: bool,
    char_polling: bool,
    char_mods_polling: bool,
    mouse_button_polling: bool,
    cursor_pos_polling: bool,
    cursor_enter_polling: bool,
    scroll_polling: bool,
    drag_and_drop_polling: bool,
    maximize_polling: bool,
    content_scale_polling: bool
}
impl WindowCallbacks {
    fn new(sender: GlfwSender<(f64, WindowEvent)>) -> Self {
        Self {
            window_ptr: std::ptr::null_mut(),
            sender,
            pos_callback: None,
            size_callback: None,
            close_callback: None,
            refresh_callback: None,
            focus_callback: None,
            iconify_callback: None,
            framebuffer_size_callback: None,
            key_callback: None,
            char_callback: None,
            char_mods_callback: None,
            mouse_button_callback: None,
            cursor_pos_callback: None,
            cursor_enter_callback: None,
            scroll_callback: None,
            drag_and_drop_callback: None,
            maximize_callback: None,
            content_scale_callback: None,
            pos_polling: false,
            size_polling: false,
            close_polling: false,
            refresh_polling: false,
            focus_polling: false,
            iconify_polling: false,
            framebuffer_size_polling: false,
            key_polling: false,
            char_polling: false,
            char_mods_polling: false,
            mouse_button_polling: false,
            cursor_pos_polling: false,
            cursor_enter_polling: false,
            scroll_polling: false,
            drag_and_drop_polling: false,
            maximize_polling: false,
            content_scale_polling: false
        }
    }
    fn get_callbacks<'a>(window: *mut GLFWwindow) -> &'a mut WindowCallbacks {
        unsafe {
            &mut *(ffi::glfwGetWindowUserPointer(window) as *mut WindowCallbacks)
        }
    }
}
pub fn get_error() -> Error {
    unsafe {
        mem::transmute(ffi::glfwGetError(null_mut()))
    }
}
pub fn get_error_string() -> (Error, String) {
    unsafe {
        let mut description: *const c_char = null();
        let error: Error = mem::transmute(ffi::glfwGetError(&mut description));
        (error, string_from_c_str(description))
    }
}
pub fn get_version() -> Version {
    unsafe {
        let mut major = 0;
        let mut minor = 0;
        let mut patch = 0;
        ffi::glfwGetVersion(&mut major, &mut minor, &mut patch);
        Version {
            major: major as u64,
            minor: minor as u64,
            patch: patch as u64,
        }
    }
}
pub unsafe fn string_from_c_str(c_str: *const c_char) -> String {
    String::from_utf8_lossy(CStr::from_ptr(c_str).to_bytes()).into_owned()
}
pub unsafe fn string_from_nullable_c_str(c_str: *const c_char) -> Option<String> {
    if c_str.is_null() {
        None
    } else {
        Some(string_from_c_str(c_str))
    }
}
pub fn with_c_str<F, T>(s: &str, f: F) -> T
    where
        F: FnOnce(*const c_char) -> T,
{
    let c_str = CString::new(s.as_bytes());
    f(c_str.unwrap().as_bytes_with_nul().as_ptr() as *const _)
}
pub fn get_version_string() -> String {
    unsafe { string_from_c_str(ffi::glfwGetVersionString()) }
}
#[allow(missing_copy_implementations)]
pub struct Monitor {
    ptr: *mut ffi::GLFWmonitor,
}
impl std::fmt::Debug for Monitor {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Monitor({:p})", self.ptr)
    }
}
impl Monitor {
    pub fn get_pos(&self) -> (i32, i32) {
        unsafe {
            let mut xpos = 0;
            let mut ypos = 0;
            ffi::glfwGetMonitorPos(self.ptr, &mut xpos, &mut ypos);
            (xpos as i32, ypos as i32)
        }
    }
    pub fn get_physical_size(&self) -> (i32, i32) {
        unsafe {
            let mut width = 0;
            let mut height = 0;
            ffi::glfwGetMonitorPhysicalSize(self.ptr, &mut width, &mut height);
            (width as i32, height as i32)
        }
    }
    pub fn get_name(&self) -> Option<String> {
        unsafe { string_from_nullable_c_str(ffi::glfwGetMonitorName(self.ptr)) }
    }
    pub fn get_video_modes(&self) -> Vec<VidMode> {
        unsafe {
            let mut count = 0;
            let ptr = ffi::glfwGetVideoModes(self.ptr, &mut count);
            slice::from_raw_parts(ptr, count as usize)
                .iter()
                .map(VidMode::from_glfw_vid_mode)
                .collect()
        }
    }
    pub fn get_video_mode(&self) -> Option<VidMode> {
        unsafe {
            let ptr = ffi::glfwGetVideoMode(self.ptr);
            if ptr.is_null() {
                None
            } else {
                Some(VidMode::from_glfw_vid_mode(&*ptr))
            }
        }
    }
    pub fn set_gamma(&mut self, gamma: f32) {
        unsafe {
            ffi::glfwSetGamma(self.ptr, gamma as c_float);
        }
    }
    pub fn get_gamma_ramp(&self) -> GammaRamp {
        unsafe {
            let llramp = *ffi::glfwGetGammaRamp(self.ptr);
            GammaRamp {
                red: slice::from_raw_parts(llramp.red as *const c_ushort, llramp.size as usize)
                    .iter()
                    .copied()
                    .collect(),
                green: slice::from_raw_parts(llramp.green as *const c_ushort, llramp.size as usize)
                    .iter()
                    .copied()
                    .collect(),
                blue: slice::from_raw_parts(llramp.blue as *const c_ushort, llramp.size as usize)
                    .iter()
                    .copied()
                    .collect(),
            }
        }
    }
    pub fn set_gamma_ramp(&mut self, ramp: &mut GammaRamp) {
        unsafe {
            ffi::glfwSetGammaRamp(
                self.ptr,
                &ffi::GLFWgammaramp {
                    red: ramp.red.as_mut_ptr(),
                    green: ramp.green.as_mut_ptr(),
                    blue: ramp.blue.as_mut_ptr(),
                    size: ramp.red.len() as u32,
                },
            );
        }
    }
    pub fn get_content_scale(&self) -> (f32, f32) {
        unsafe {
            let mut xscale = 0.0_f32;
            let mut yscale = 0.0_f32;
            ffi::glfwGetMonitorContentScale(self.ptr, &mut xscale, &mut yscale);
            (xscale, yscale)
        }
    }
    pub fn get_workarea(&self) -> (i32, i32, i32, i32) {
        unsafe {
            let mut xpos = 0;
            let mut ypos = 0;
            let mut width = 0;
            let mut height = 0;
            ffi::glfwGetMonitorWorkarea(self.ptr, &mut xpos, &mut ypos, &mut width, &mut height);
            (xpos, ypos, width, height)
        }
    }
}
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum MonitorEvent {
    Connected = ffi::CONNECTED,
    Disconnected = ffi::DISCONNECTED,
}
impl VidMode {
    fn from_glfw_vid_mode(mode: &ffi::GLFWvidmode) -> VidMode {
        VidMode {
            width: mode.width as u32,
            height: mode.height as u32,
            red_bits: mode.redBits as u32,
            green_bits: mode.greenBits as u32,
            blue_bits: mode.blueBits as u32,
            refresh_rate: mode.refreshRate as u32,
        }
    }
}
impl fmt::Debug for VidMode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{} x {}, {} = {} + {} + {}, {} Hz",
            self.width,
            self.height,
            self.red_bits + self.green_bits + self.blue_bits,
            self.red_bits,
            self.green_bits,
            self.blue_bits,
            self.refresh_rate
        )
    }
}
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum WindowHint {
    RedBits(Option<u32>),
    GreenBits(Option<u32>),
    BlueBits(Option<u32>),
    AlphaBits(Option<u32>),
    DepthBits(Option<u32>),
    StencilBits(Option<u32>),
    AccumRedBits(Option<u32>),
    AccumGreenBits(Option<u32>),
    AccumBlueBits(Option<u32>),
    AccumAlphaBits(Option<u32>),
    AuxBuffers(Option<u32>),
    Stereo(bool),
    Samples(Option<u32>),
    SRgbCapable(bool),
    RefreshRate(Option<u32>),
    ClientApi(ClientApiHint),
    ContextVersionMajor(u32),
    ContextVersionMinor(u32),
    ContextVersion(u32, u32),
    ContextRobustness(ContextRobustnessHint),
    OpenGlForwardCompat(bool),
    OpenGlDebugContext(bool),
    OpenGlProfile(OpenGlProfileHint),
    Resizable(bool),
    Visible(bool),
    Decorated(bool),
    AutoIconify(bool),
    Floating(bool),
    Focused(bool),
    Maximized(bool),
    ContextNoError(bool),
    ContextCreationApi(ContextCreationApi),
    ContextReleaseBehavior(ContextReleaseBehavior),
    DoubleBuffer(bool),
    CenterCursor(bool),
    TransparentFramebuffer(bool),
    FocusOnShow(bool),
    ScaleToMonitor(bool),
    CocoaRetinaFramebuffer(bool),
    CocoaFrameName(Option<String>),
    CocoaGraphicsSwitching(bool),
    X11ClassName(Option<String>),
    X11InstanceName(Option<String>),
}
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum ClientApiHint {
    NoApi = ffi::NO_API,
    OpenGl = ffi::OPENGL_API,
    OpenGlEs = ffi::OPENGL_ES_API,
}
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum ContextRobustnessHint {
    NoRobustness = ffi::NO_ROBUSTNESS,
    NoResetNotification = ffi::NO_RESET_NOTIFICATION,
    LoseContextOnReset = ffi::LOSE_CONTEXT_ON_RESET,
}
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum OpenGlProfileHint {
    Any = ffi::OPENGL_ANY_PROFILE,
    Core = ffi::OPENGL_CORE_PROFILE,
    Compat = ffi::OPENGL_COMPAT_PROFILE,
}
#[derive(Copy, Clone, Debug)]
pub enum WindowMode<'a> {
    FullScreen(&'a Monitor),
    Windowed,
}
impl<'a> WindowMode<'a> {
    fn to_ptr(&self) -> *mut ffi::GLFWmonitor {
        match *self {
            WindowMode::FullScreen(monitor) => monitor.ptr,
            WindowMode::Windowed => ptr::null_mut(),
        }
    }
}
bitflags! {
    #[doc = "Key modifiers (e.g., Shift, Control, Alt, Super)"]
    pub struct Modifiers: ::std::os::raw::c_int {
        const Shift       = crate::ffi::MOD_SHIFT;
        const Control     = crate::ffi::MOD_CONTROL;
        const Alt         = crate::ffi::MOD_ALT;
        const Super       = crate::ffi::MOD_SUPER;
        const CapsLock    = crate::ffi::MOD_CAPS_LOCK;
        const NumLock     = crate::ffi::MOD_NUM_LOCK;
    }
}
pub type Scancode = c_int;
#[derive(Clone, PartialEq, PartialOrd, Debug)]
pub enum WindowEvent {
    Pos(i32, i32),
    Size(i32, i32),
    Close,
    Refresh,
    Focus(bool),
    Iconify(bool),
    FramebufferSize(i32, i32),
    MouseButton(MouseButton, Action, Modifiers),
    CursorPos(f64, f64),
    CursorEnter(bool),
    Scroll(f64, f64),
    Key(Key, Scancode, Action, Modifiers),
    Char(char),
    CharModifiers(char, Modifiers),
    FileDrop(Vec<PathBuf>),
    Maximize(bool),
    ContentScale(f32, f32),
}
pub fn flush_messages<Message: Send>(receiver: &GlfwReceiver<Message>) -> FlushedMessages<'_, Message> {
    FlushedMessages(receiver)
}
#[derive(Debug)]
pub struct FlushedMessages<'a, Message: Send>(&'a GlfwReceiver<Message>);
unsafe impl<'a, Message: 'a + Send> Send for FlushedMessages<'a, Message> {}
impl<'a, Message: 'static + Send> Iterator for FlushedMessages<'a, Message> {
    type Item = Message;
    fn next(&mut self) -> Option<Message> {
        let FlushedMessages(receiver) = *self;
        receiver.receive()
    }
}
#[derive(Debug)]
pub struct Window {
    ptr: *mut ffi::GLFWwindow,
    pub is_shared: bool,
    drop_sender: Option<Sender<()>>,
    #[allow(unused)]
    drop_receiver: Receiver<()>,
    current_cursor: Option<Cursor>,
    pub glfw: Glfw,
}
impl Window {
    pub fn get_proc_address(&mut self, procname: &str) -> GLProc {
        if self.ptr != unsafe { ffi::glfwGetCurrentContext() } {
            self.make_current();
        }
        self.glfw.get_proc_address_raw(procname)
    }
    #[cfg(feature = "vulkan")]
    pub fn get_instance_proc_address(&mut self, instance: vk::Instance, procname: &str) -> VkProc {
        self.glfw.get_instance_proc_address_raw(instance, procname)
    }
    #[cfg(feature = "vulkan")]
    pub fn get_physical_device_presentation_support(
        &self,
        instance: vk::Instance,
        device: vk::PhysicalDevice,
        queue_family: u32,
    ) -> bool {
        self.glfw
            .get_physical_device_presentation_support_raw(instance, device, queue_family)
    }
    #[cfg(feature = "vulkan")]
    pub fn create_window_surface(
        &self,
        instance: vk::Instance,
        allocator: *const vk::AllocationCallbacks<'_>,
        surface: *mut vk::SurfaceKHR,
    ) -> vk::Result {
        unsafe { ffi::glfwCreateWindowSurface(instance, self.ptr, allocator, surface) }
    }
    pub fn create_shared(
        &self,
        width: u32,
        height: u32,
        title: &str,
        mode: WindowMode<'_>,
    ) -> Option<(PWindow, GlfwReceiver<(f64, WindowEvent)>)> {
        self.glfw
            .create_window_intern(width, height, title, mode, Some(self))
    }
    pub fn close(self) {}
    pub fn render_context(&mut self) -> PRenderContext {
        PRenderContext(Box::new(RenderContext {
            ptr: self.ptr,
            glfw: self.glfw.clone(),
            drop_sender: self.drop_sender.as_ref().unwrap().clone(),
        }))
    }
    pub fn should_close(&self) -> bool {
        unsafe { ffi::glfwWindowShouldClose(self.ptr) == ffi::TRUE }
    }
    pub fn set_should_close(&mut self, value: bool) {
        unsafe { ffi::glfwSetWindowShouldClose(self.ptr, value as c_int) }
    }
    pub fn set_title(&mut self, title: &str) {
        unsafe {
            with_c_str(title, |title| {
                ffi::glfwSetWindowTitle(self.ptr, title);
            });
        }
    }
    pub fn get_pos(&self) -> (i32, i32) {
        unsafe {
            let mut xpos = 0;
            let mut ypos = 0;
            ffi::glfwGetWindowPos(self.ptr, &mut xpos, &mut ypos);
            (xpos as i32, ypos as i32)
        }
    }
    pub fn set_pos(&mut self, xpos: i32, ypos: i32) {
        unsafe {
            ffi::glfwSetWindowPos(self.ptr, xpos as c_int, ypos as c_int);
        }
    }
    pub fn get_size(&self) -> (i32, i32) {
        unsafe {
            let mut width = 0;
            let mut height = 0;
            ffi::glfwGetWindowSize(self.ptr, &mut width, &mut height);
            (width as i32, height as i32)
        }
    }
    pub fn set_size(&mut self, width: i32, height: i32) {
        unsafe {
            ffi::glfwSetWindowSize(self.ptr, width as c_int, height as c_int);
        }
    }
    pub fn get_frame_size(&self) -> (i32, i32, i32, i32) {
        let (mut left, mut top, mut right, mut bottom): (i32, i32, i32, i32) = (0, 0, 0, 0);
        unsafe {
            ffi::glfwGetWindowFrameSize(
                self.ptr,
                &mut left as *mut c_int,
                &mut top as *mut c_int,
                &mut right as *mut c_int,
                &mut bottom as *mut c_int,
            );
        }
        (left, top, right, bottom)
    }
    pub fn get_framebuffer_size(&self) -> (i32, i32) {
        unsafe {
            let mut width = 0;
            let mut height = 0;
            ffi::glfwGetFramebufferSize(self.ptr, &mut width, &mut height);
            (width as i32, height as i32)
        }
    }
    pub fn set_aspect_ratio(&mut self, numer: u32, denum: u32) {
        unsafe { ffi::glfwSetWindowAspectRatio(self.ptr, numer as c_int, denum as c_int) }
    }
    pub fn set_size_limits(
        &mut self,
        minwidth: Option<u32>,
        minheight: Option<u32>,
        maxwidth: Option<u32>,
        maxheight: Option<u32>,
    ) {
        unsafe {
            ffi::glfwSetWindowSizeLimits(
                self.ptr,
                unwrap_dont_care(minwidth),
                unwrap_dont_care(minheight),
                unwrap_dont_care(maxwidth),
                unwrap_dont_care(maxheight),
            )
        }
    }
    pub fn iconify(&mut self) {
        unsafe {
            ffi::glfwIconifyWindow(self.ptr);
        }
    }
    pub fn restore(&mut self) {
        unsafe {
            ffi::glfwRestoreWindow(self.ptr);
        }
    }
    pub fn maximize(&mut self) {
        unsafe { ffi::glfwMaximizeWindow(self.ptr) }
    }
    pub fn show(&mut self) {
        unsafe {
            ffi::glfwShowWindow(self.ptr);
        }
    }
    pub fn hide(&mut self) {
        unsafe {
            ffi::glfwHideWindow(self.ptr);
        }
    }
    pub fn with_window_mode<T, F>(&self, f: F) -> T
        where
            F: FnOnce(WindowMode<'_>) -> T,
    {
        let ptr = unsafe { ffi::glfwGetWindowMonitor(self.ptr) };
        if ptr.is_null() {
            f(WindowMode::Windowed)
        } else {
            f(WindowMode::FullScreen(&Monitor { ptr }))
        }
    }
    pub fn set_monitor(
        &mut self,
        mode: WindowMode<'_>,
        xpos: i32,
        ypos: i32,
        width: u32,
        height: u32,
        refresh_rate: Option<u32>,
    ) {
        let monitor_ptr = if let WindowMode::FullScreen(monitor) = mode {
            monitor.ptr
        } else {
            ptr::null_mut()
        };
        unsafe {
            ffi::glfwSetWindowMonitor(
                self.ptr,
                monitor_ptr,
                xpos as c_int,
                ypos as c_int,
                width as c_int,
                height as c_int,
                unwrap_dont_care(refresh_rate),
            )
        }
    }
    pub fn focus(&mut self) {
        unsafe { ffi::glfwFocusWindow(self.ptr) }
    }
    pub fn is_focused(&self) -> bool {
        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::FOCUSED) == ffi::TRUE }
    }
    pub fn is_iconified(&self) -> bool {
        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::ICONIFIED) == ffi::TRUE }
    }
    pub fn is_maximized(&self) -> bool {
        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::MAXIMIZED) == ffi::TRUE }
    }
    pub fn get_client_api(&self) -> c_int {
        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::CLIENT_API) }
    }
    pub fn get_context_version(&self) -> Version {
        unsafe {
            Version {
                major: ffi::glfwGetWindowAttrib(self.ptr, ffi::CONTEXT_VERSION_MAJOR) as u64,
                minor: ffi::glfwGetWindowAttrib(self.ptr, ffi::CONTEXT_VERSION_MINOR) as u64,
                patch: ffi::glfwGetWindowAttrib(self.ptr, ffi::CONTEXT_REVISION) as u64,
            }
        }
    }
    pub fn get_context_robustness(&self) -> c_int {
        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::CONTEXT_ROBUSTNESS) }
    }
    pub fn is_opengl_forward_compat(&self) -> bool {
        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::OPENGL_FORWARD_COMPAT) == ffi::TRUE }
    }
    pub fn is_opengl_debug_context(&self) -> bool {
        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::OPENGL_DEBUG_CONTEXT) == ffi::TRUE }
    }
    pub fn get_opengl_profile(&self) -> c_int {
        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::OPENGL_PROFILE) }
    }
    pub fn is_resizable(&self) -> bool {
        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::RESIZABLE) == ffi::TRUE }
    }
    pub fn set_resizable(&mut self, resizable: bool) {
        unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::RESIZABLE, resizable as c_int) }
    }
    pub fn is_visible(&self) -> bool {
        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::VISIBLE) == ffi::TRUE }
    }
    pub fn is_decorated(&self) -> bool {
        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::DECORATED) == ffi::TRUE }
    }
    pub fn set_decorated(&mut self, decorated: bool) {
        unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::DECORATED, decorated as c_int) }
    }
    pub fn is_auto_iconify(&self) -> bool {
        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::AUTO_ICONIFY) == ffi::TRUE }
    }
    pub fn set_auto_iconify(&mut self, auto_iconify: bool) {
        unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::AUTO_ICONIFY, auto_iconify as c_int) }
    }
    pub fn is_floating(&self) -> bool {
        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::FLOATING) == ffi::TRUE }
    }
    pub fn set_floating(&mut self, floating: bool) {
        unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::FLOATING, floating as c_int) }
    }
    pub fn is_framebuffer_transparent(&self) -> bool {
        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::TRANSPARENT_FRAMEBUFFER) == ffi::TRUE }
    }
    pub fn is_focus_on_show(&self) -> bool {
        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::FOCUS_ON_SHOW) == ffi::TRUE }
    }
    pub fn set_focus_on_show(&mut self, focus_on_show: bool) {
        unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::FOCUS_ON_SHOW, focus_on_show as c_int) }
    }
    pub fn is_hovered(&self) -> bool {
        unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::HOVERED) == ffi::TRUE }
    }
    new_callback!(
        doc -> "Wrapper for `glfwSetWindowPosCallback`.",
        set -> set_pos_callback,
        unset -> unset_pos_callback,
        poll -> set_pos_polling,
        callback_field -> pos_callback,
        poll_field -> pos_polling,
        window_event -> Pos(i32, i32),
        glfw -> glfwSetWindowPosCallback(x: c_int, y: c_int),
        convert_args -> (x as i32, y as i32),
        secret -> _pos_callback
    );
    new_callback!(
        doc -> "Wrapper for `glfwSetWindowSizeCallback`.",
        set -> set_size_callback,
        unset -> unset_size_callback,
        poll -> set_size_polling,
        callback_field -> size_callback,
        poll_field -> size_polling,
        window_event -> Size(i32, i32),
        glfw -> glfwSetWindowSizeCallback(width: c_int, height: c_int),
        convert_args -> (width as i32, height as i32),
        secret -> _size_callback
    );
    new_callback!(
        doc -> "Wrapper for `glfwSetWindowCloseCallback`.",
        set -> set_close_callback,
        unset -> unset_close_callback,
        poll -> set_close_polling,
        callback_field -> close_callback,
        poll_field -> close_polling,
        window_event -> Close,
        glfw -> glfwSetWindowCloseCallback(),
        convert_args -> (),
        secret -> _close_callback
    );
    new_callback!(
        doc -> "Wrapper for `glfwSetWindowRefreshCallback`.",
        set -> set_refresh_callback,
        unset -> unset_refresh_callback,
        poll -> set_refresh_polling,
        callback_field -> refresh_callback,
        poll_field -> refresh_polling,
        window_event -> Refresh,
        glfw -> glfwSetWindowRefreshCallback(),
        convert_args -> (),
        secret -> _refresh_callback
    );
    new_callback!(
        doc -> "Wrapper for `glfwSetWindowFocusCallback`.",
        set -> set_focus_callback,
        unset -> unset_focus_callback,
        poll -> set_focus_polling,
        callback_field -> focus_callback,
        poll_field -> focus_polling,
        window_event -> Focus(bool),
        glfw -> glfwSetWindowFocusCallback(focused: c_int),
        convert_args -> (focused == ffi::TRUE),
        secret -> _focus_callback
    );
    new_callback!(
        doc -> "Wrapper for `glfwSetWindowIconifyCallback`.",
        set -> set_iconify_callback,
        unset -> unset_iconify_callback,
        poll -> set_iconify_polling,
        callback_field -> iconify_callback,
        poll_field -> iconify_polling,
        window_event -> Iconify(bool),
        glfw -> glfwSetWindowIconifyCallback(iconified: c_int),
        convert_args -> (iconified == ffi::TRUE),
        secret -> _iconify_callback
    );
    new_callback!(
        doc -> "Wrapper for `glfwSetFramebufferSizeCallback`.",
        set -> set_framebuffer_size_callback,
        unset -> unset_framebuffer_size_callback,
        poll -> set_framebuffer_size_polling,
        callback_field -> framebuffer_size_callback,
        poll_field -> framebuffer_size_polling,
        window_event -> FramebufferSize(i32, i32),
        glfw -> glfwSetFramebufferSizeCallback(width: c_int, height: c_int),
        convert_args -> (width as i32, height as i32),
        secret -> _framebuffer_size_callback
    );
    new_callback!(
        doc -> "Wrapper for `glfwSetKeyCallback`.",
        set -> set_key_callback,
        unset -> unset_key_callback,
        poll -> set_key_polling,
        callback_field -> key_callback,
        poll_field -> key_polling,
        window_event -> Key(Key, Scancode, Action, Modifiers),
        glfw -> glfwSetKeyCallback(key: c_int, scancode: c_int, action: c_int, mods: c_int),
        convert_args -> (
            mem::transmute(key),
            scancode, mem::transmute(action),
            Modifiers::from_bits(mods).unwrap()
        ),
        secret -> _key_callback
    );
    new_callback!(
        doc -> "Wrapper for `glfwSetCharCallback`.",
        set -> set_char_callback,
        unset -> unset_char_callback,
        poll -> set_char_polling,
        callback_field -> char_callback,
        poll_field -> char_polling,
        window_event -> Char(char),
        glfw -> glfwSetCharCallback(character: c_uint),
        convert_args -> (::std::char::from_u32(character).unwrap()),
        secret -> _char_callback
    );
    new_callback!(
        doc -> "Wrapper for `glfwSetCharModsCallback`.",
        set -> set_char_mods_callback,
        unset -> unset_char_mods_callback,
        poll -> set_char_mods_polling,
        callback_field -> char_mods_callback,
        poll_field -> char_mods_polling,
        window_event -> CharModifiers(char, Modifiers),
        glfw -> glfwSetCharModsCallback(character: c_uint, mods: c_int),
        convert_args -> (
            ::std::char::from_u32(character).unwrap(),
            Modifiers::from_bits(mods).unwrap()
        ),
        secret -> _char_mods_callback
    );
    new_callback!(
        doc -> "Wrapper for `glfwSetMouseButtonCallback`.",
        set -> set_mouse_button_callback,
        unset -> unset_mouse_button_callback,
        poll -> set_mouse_button_polling,
        callback_field -> mouse_button_callback,
        poll_field -> mouse_button_polling,
        window_event -> MouseButton(MouseButton, Action, Modifiers),
        glfw -> glfwSetMouseButtonCallback(button: c_int, action: c_int, mods: c_int),
        convert_args -> (
            mem::transmute(button),
            mem::transmute(action),
            Modifiers::from_bits(mods).unwrap()
        ),
        secret -> _mouse_button_callback
    );
    new_callback!(
        doc -> "Wrapper for `glfwSetCursorPosCallback`.",
        set -> set_cursor_pos_callback,
        unset -> unset_cursor_pos_callback,
        poll -> set_cursor_pos_polling,
        callback_field -> cursor_pos_callback,
        poll_field -> cursor_pos_polling,
        window_event -> CursorPos(f64, f64),
        glfw -> glfwSetCursorPosCallback(x: c_double, y: c_double),
        convert_args -> (x as f64, y as f64),
        secret -> _cursor_pos_callback
    );
    new_callback!(
        doc -> "Wrapper for `glfwSetCursorEnterCallback`.",
        set -> set_cursor_enter_callback,
        unset -> unset_cursor_enter_callback,
        poll -> set_cursor_enter_polling,
        callback_field -> cursor_enter_callback,
        poll_field -> cursor_enter_polling,
        window_event -> CursorEnter(bool),
        glfw -> glfwSetCursorEnterCallback(entered: c_int),
        convert_args -> (entered == ffi::TRUE),
        secret -> _cursor_enter_callback
    );
    new_callback!(
        doc -> "Wrapper for `glfwSetScrollCallback`.",
        set -> set_scroll_callback,
        unset -> unset_scroll_callback,
        poll -> set_scroll_polling,
        callback_field -> scroll_callback,
        poll_field -> scroll_polling,
        window_event -> Scroll(f64, f64),
        glfw -> glfwSetScrollCallback(x: c_double, y: c_double),
        convert_args -> (x as f64, y as f64),
        secret -> _scroll_callback
    );
    new_callback!(
        doc -> "Wrapper for `glfwSetDropCallback`.",
        set -> set_drag_and_drop_callback,
        unset -> unset_drag_and_drop_callback,
        poll -> set_drag_and_drop_polling,
        callback_field -> drag_and_drop_callback,
        poll_field -> drag_and_drop_polling,
        window_event -> FileDrop(Vec<PathBuf>),
        glfw -> glfwSetDropCallback(num_paths: c_int, paths: *mut *const c_char),
        convert_args -> ({
            slice::from_raw_parts(paths, num_paths as usize)
            .iter()
            .map(|path| PathBuf::from(std::str::from_utf8({
                CStr::from_ptr(*path)
                    .to_bytes()
            })
            .unwrap()
            .to_string()))
            .collect()
        }),
        secret -> _drag_and_drop_callback
    );
    new_callback!(
        doc -> "Wrapper for `glfwSetWindowMaximizeCallback`.",
        set -> set_maximize_callback,
        unset -> unset_maximize_callback,
        poll -> set_maximize_polling,
        callback_field -> maximize_callback,
        poll_field -> maximize_polling,
        window_event -> Maximize(bool),
        glfw -> glfwSetWindowMaximizeCallback(maximized: c_int),
        convert_args -> (maximized == ffi::TRUE),
        secret -> _maximize_callback
    );
    new_callback!(
        doc -> "Wrapper for `glfwSetWindowContentScaleCallback`.",
        set -> set_content_scale_callback,
        unset -> unset_content_scale_callback,
        poll -> set_content_scale_polling,
        callback_field -> content_scale_callback,
        poll_field -> content_scale_polling,
        window_event -> ContentScale(f32, f32),
        glfw -> glfwSetWindowContentScaleCallback(xscale: c_float, yscale: c_float),
        convert_args -> (xscale as f32, yscale as f32),
        secret -> _content_scale_callback
    );
    pub fn set_all_polling(&mut self, should_poll: bool) {
        self.set_pos_polling(should_poll);
        self.set_size_polling(should_poll);
        self.set_close_polling(should_poll);
        self.set_refresh_polling(should_poll);
        self.set_focus_polling(should_poll);
        self.set_iconify_polling(should_poll);
        self.set_framebuffer_size_polling(should_poll);
        self.set_key_polling(should_poll);
        self.set_char_polling(should_poll);
        self.set_char_mods_polling(should_poll);
        self.set_mouse_button_polling(should_poll);
        self.set_cursor_pos_polling(should_poll);
        self.set_cursor_enter_polling(should_poll);
        self.set_scroll_polling(should_poll);
        self.set_drag_and_drop_polling(should_poll);
        self.set_maximize_polling(should_poll);
        self.set_content_scale_polling(should_poll);
    }
    pub fn get_cursor_mode(&self) -> CursorMode {
        unsafe { mem::transmute(ffi::glfwGetInputMode(self.ptr, ffi::CURSOR)) }
    }
    pub fn set_cursor_mode(&mut self, mode: CursorMode) {
        unsafe {
            ffi::glfwSetInputMode(self.ptr, ffi::CURSOR, mode as c_int);
        }
    }
    pub fn set_cursor(&mut self, cursor: Option<Cursor>) -> Option<Cursor> {
        let previous = mem::replace(&mut self.current_cursor, cursor);
        unsafe {
            ffi::glfwSetCursor(
                self.ptr,
                match self.current_cursor {
                    Some(ref cursor) => cursor.ptr,
                    None => ptr::null_mut(),
                },
            )
        }
        previous
    }
    #[cfg(feature = "image")]
    pub fn set_icon(&mut self, images: Vec<image::RgbaImage>) {
        let image_data: Vec<(Vec<_>, u32, u32)> = images
            .into_iter()
            .map(|image| {
                let (width, height) = image.dimensions();
                (image.into_vec(), width, height)
            })
            .collect();
        let glfw_images: Vec<ffi::GLFWimage> = image_data
            .iter()
            .map(|data| ffi::GLFWimage {
                width: data.1 as c_int,
                height: data.2 as c_int,
                pixels: data.0.as_ptr() as *const c_uchar,
            })
            .collect();
        unsafe {
            ffi::glfwSetWindowIcon(
                self.ptr,
                glfw_images.len() as c_int,
                glfw_images.as_ptr() as *const ffi::GLFWimage,
            )
        }
    }
    pub fn set_icon_from_pixels(&mut self, images: Vec<PixelImage>) {
        let glfw_images: Vec<ffi::GLFWimage> = images
            .iter()
            .map(|image: &PixelImage| ffi::GLFWimage {
                width: image.width as c_int,
                height: image.height as c_int,
                pixels: image.pixels.as_ptr() as *const c_uchar,
            })
            .collect();
        unsafe {
            ffi::glfwSetWindowIcon(
                self.ptr,
                glfw_images.len() as c_int,
                glfw_images.as_ptr() as *const ffi::GLFWimage,
            )
        }
    }
    pub fn has_sticky_keys(&self) -> bool {
        unsafe { ffi::glfwGetInputMode(self.ptr, ffi::STICKY_KEYS) == ffi::TRUE }
    }
    pub fn set_sticky_keys(&mut self, value: bool) {
        unsafe {
            ffi::glfwSetInputMode(self.ptr, ffi::STICKY_KEYS, value as c_int);
        }
    }
    pub fn has_sticky_mouse_buttons(&self) -> bool {
        unsafe { ffi::glfwGetInputMode(self.ptr, ffi::STICKY_MOUSE_BUTTONS) == ffi::TRUE }
    }
    pub fn set_sticky_mouse_buttons(&mut self, value: bool) {
        unsafe {
            ffi::glfwSetInputMode(self.ptr, ffi::STICKY_MOUSE_BUTTONS, value as c_int);
        }
    }
    pub fn does_store_lock_key_mods(&self) -> bool {
        unsafe { ffi::glfwGetInputMode(self.ptr, ffi::LOCK_KEY_MODS) == ffi::TRUE }
    }
    pub fn set_store_lock_key_mods(&mut self, value: bool) {
        unsafe { ffi::glfwSetInputMode(self.ptr, ffi::LOCK_KEY_MODS, value as c_int) }
    }
    pub fn uses_raw_mouse_motion(&self) -> bool {
        unsafe { ffi::glfwGetInputMode(self.ptr, ffi::RAW_MOUSE_MOTION) == ffi::TRUE }
    }
    pub fn set_raw_mouse_motion(&mut self, value: bool) {
        unsafe { ffi::glfwSetInputMode(self.ptr, ffi::RAW_MOUSE_MOTION, value as c_int) }
    }
    pub fn get_key(&self, key: Key) -> Action {
        unsafe { mem::transmute(ffi::glfwGetKey(self.ptr, key as c_int)) }
    }
    pub fn get_mouse_button(&self, button: MouseButton) -> Action {
        unsafe { mem::transmute(ffi::glfwGetMouseButton(self.ptr, button as c_int)) }
    }
    pub fn get_cursor_pos(&self) -> (f64, f64) {
        unsafe {
            let mut xpos = 0.0;
            let mut ypos = 0.0;
            ffi::glfwGetCursorPos(self.ptr, &mut xpos, &mut ypos);
            (xpos as f64, ypos as f64)
        }
    }
    pub fn set_cursor_pos(&mut self, xpos: f64, ypos: f64) {
        unsafe {
            ffi::glfwSetCursorPos(self.ptr, xpos as c_double, ypos as c_double);
        }
    }
    pub fn set_clipboard_string(&mut self, string: &str) {
        unsafe {
            with_c_str(string, |string| {
                ffi::glfwSetClipboardString(self.ptr, string);
            });
        }
    }
    pub fn get_clipboard_string(&self) -> Option<String> {
        unsafe { string_from_nullable_c_str(ffi::glfwGetClipboardString(self.ptr)) }
    }
    pub fn get_opacity(&self) -> f32 {
        unsafe { ffi::glfwGetWindowOpacity(self.ptr) }
    }
    pub fn set_opacity(&mut self, opacity: f32) {
        unsafe { ffi::glfwSetWindowOpacity(self.ptr, opacity) }
    }
    pub fn request_attention(&mut self) {
        unsafe { ffi::glfwRequestWindowAttention(self.ptr) }
    }
    pub fn get_content_scale(&self) -> (f32, f32) {
        unsafe {
            let mut xscale = 0.0_f32;
            let mut yscale = 0.0_f32;
            ffi::glfwGetWindowContentScale(self.ptr, &mut xscale, &mut yscale);
            (xscale, yscale)
        }
    }
    #[cfg(target_os = "windows")]
    pub fn get_win32_window(&self) -> *mut c_void {
        unsafe { ffi::glfwGetWin32Window(self.ptr) }
    }
    #[cfg(target_os = "windows")]
    pub fn get_wgl_context(&self) -> *mut c_void {
        unsafe { ffi::glfwGetWGLContext(self.ptr) }
    }
    #[cfg(target_os = "macos")]
    pub fn get_cocoa_window(&self) -> *mut c_void {
        unsafe { ffi::glfwGetCocoaWindow(self.ptr) }
    }
    #[cfg(target_os = "macos")]
    pub fn get_nsgl_context(&self) -> *mut c_void {
        unsafe { ffi::glfwGetNSGLContext(self.ptr) }
    }
    #[cfg(all(target_os = "linux", not(feature = "wayland")))]
    pub fn get_x11_window(&self) -> *mut c_void {
        unsafe { ffi::glfwGetX11Window(self.ptr) }
    }
    #[cfg(all(target_os = "linux", feature = "wayland"))]
    pub fn get_wayland_window(&self) -> *mut c_void {
        unsafe { ffi::glfwGetWaylandWindow(self.ptr) }
    }
    #[cfg(target_os = "linux")]
    pub fn get_glx_context(&self) -> *mut c_void {
        unsafe { ffi::glfwGetGLXContext(self.ptr) }
    }
}
impl Drop for Window {
    fn drop(&mut self) {
        drop(self.drop_sender.take());
        #[cfg(feature = "log")]
        if self.drop_receiver.try_recv() != Err(std::sync::mpsc::TryRecvError::Disconnected) {
            debug!("Attempted to drop a Window before the `RenderContext` was dropped.");
            debug!("Blocking until the `RenderContext` was dropped.");
            let _ = self.drop_receiver.recv();
        }
        if !self.ptr.is_null() {
            unsafe {
                let _: Box<WindowCallbacks> =
                    mem::transmute(ffi::glfwGetWindowUserPointer(self.ptr));
            }
        }
        if !self.is_shared {
            unsafe {
                ffi::glfwDestroyWindow(self.ptr);
            }
        }
    }
}
#[derive(Debug)]
#[repr(transparent)]
pub struct PRenderContext(Box<RenderContext>);
impl Deref for PRenderContext {
    type Target = RenderContext;
    fn deref(&self) -> &Self::Target {
        self.0.deref()
    }
}
impl DerefMut for PRenderContext {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.0.deref_mut()
    }
}
unsafe impl Send for PRenderContext {}
unsafe impl Sync for PRenderContext {}
#[cfg(feature = "raw-window-handle-v0-6")]
impl HasWindowHandle for PRenderContext {
    fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
        self.0.window_handle()
    }
}
#[cfg(feature = "raw-window-handle-v0-6")]
impl HasDisplayHandle for PRenderContext {
    fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
        self.0.display_handle()
    }
}
#[derive(Debug)]
pub struct RenderContext {
    ptr: *mut ffi::GLFWwindow,
    glfw: Glfw,
    #[allow(dead_code)]
    drop_sender: Sender<()>,
}
impl RenderContext {
    pub fn get_proc_address(&mut self, procname: &str) -> GLProc {
        if self.ptr != unsafe { ffi::glfwGetCurrentContext() } {
            self.make_current();
        }
        self.glfw.get_proc_address_raw(procname)
    }
    #[cfg(feature = "vulkan")]
    pub fn get_instance_proc_address(&mut self, instance: vk::Instance, procname: &str) -> VkProc {
        self.glfw.get_instance_proc_address_raw(instance, procname)
    }
    #[cfg(feature = "vulkan")]
    pub fn get_physical_device_presentation_support(
        &self,
        instance: vk::Instance,
        device: vk::PhysicalDevice,
        queue_family: u32,
    ) -> bool {
        self.glfw
            .get_physical_device_presentation_support_raw(instance, device, queue_family)
    }
    #[cfg(feature = "vulkan")]
    pub fn create_window_surface(
        &self,
        instance: vk::Instance,
        allocator: *const vk::AllocationCallbacks<'_>,
        surface: *mut vk::SurfaceKHR,
    ) -> vk::Result {
        unsafe { ffi::glfwCreateWindowSurface(instance, self.ptr, allocator, surface) }
    }
}
unsafe impl Send for RenderContext {}
pub trait Context {
    fn window_ptr(&self) -> *mut ffi::GLFWwindow;
    fn window_id(&self) -> WindowId {
        self.window_ptr() as WindowId
    }
    fn swap_buffers(&mut self) {
        let ptr = self.window_ptr();
        unsafe {
            ffi::glfwSwapBuffers(ptr);
        }
    }
    fn is_current(&self) -> bool {
        self.window_ptr() == unsafe { ffi::glfwGetCurrentContext() }
    }
    fn make_current(&mut self) {
        let ptr = self.window_ptr();
        unsafe {
            ffi::glfwMakeContextCurrent(ptr);
        }
    }
    fn should_close(&self) -> bool {
        let ptr = self.window_ptr();
        unsafe { ffi::glfwWindowShouldClose(ptr) == ffi::TRUE }
    }
    fn set_should_close(&mut self, value: bool) {
        let ptr = self.window_ptr();
        unsafe {
            ffi::glfwSetWindowShouldClose(ptr, value as c_int);
        }
    }
    fn post_empty_event(&self) {
        unsafe { ffi::glfwPostEmptyEvent() }
    }
}
impl Context for Window {
    fn window_ptr(&self) -> *mut ffi::GLFWwindow {
        self.ptr
    }
}
impl Context for RenderContext {
    fn window_ptr(&self) -> *mut ffi::GLFWwindow {
        self.ptr
    }
}
#[cfg(feature = "raw-window-handle-v0-6")]
impl HasWindowHandle for Window {
    fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
        Ok(unsafe { WindowHandle::borrow_raw(raw_window_handle(self)) })
    }
}
#[cfg(feature = "raw-window-handle-v0-6")]
impl HasWindowHandle for RenderContext {
    fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
        Ok(unsafe { WindowHandle::borrow_raw(raw_window_handle(self)) })
    }
}
#[cfg(feature = "raw-window-handle-v0-6")]
impl HasDisplayHandle for Window {
    fn display_handle(&'_ self) -> Result<DisplayHandle<'_>, HandleError> {
        Ok(unsafe { DisplayHandle::borrow_raw(raw_display_handle()) })
    }
}
#[cfg(feature = "raw-window-handle-v0-6")]
impl HasDisplayHandle for RenderContext {
    fn display_handle(&'_ self) -> Result<DisplayHandle<'_>, HandleError> {
        Ok(unsafe { DisplayHandle::borrow_raw(raw_display_handle()) })
    }
}
#[cfg(feature = "raw-window-handle-v0-5")]
unsafe impl HasRawWindowHandle for Window {
    fn raw_window_handle(&self) -> RawWindowHandle {
        raw_window_handle(self)
    }
}
#[cfg(feature = "raw-window-handle-v0-5")]
unsafe impl HasRawWindowHandle for RenderContext {
    fn raw_window_handle(&self) -> RawWindowHandle {
        raw_window_handle(self)
    }
}
#[cfg(feature = "raw-window-handle-v0-5")]
unsafe impl HasRawDisplayHandle for Window {
    fn raw_display_handle(&self) -> RawDisplayHandle {
        raw_display_handle()
    }
}
#[cfg(feature = "raw-window-handle-v0-5")]
unsafe impl HasRawDisplayHandle for RenderContext {
    fn raw_display_handle(&self) -> RawDisplayHandle {
        raw_display_handle()
    }
}
#[cfg(feature = "raw-window-handle-v0-6")]
fn raw_window_handle<C: Context>(context: &C) -> RawWindowHandle {
    #[cfg(target_family = "windows")]
    {
        use raw_window_handle::Win32WindowHandle;
        use std::num::NonZeroIsize;
        let (hwnd, hinstance): (*mut std::ffi::c_void, *mut std::ffi::c_void) = unsafe {
            let hwnd= ffi::glfwGetWin32Window(context.window_ptr());
            let hinstance: *mut c_void = winapi::um::libloaderapi::GetModuleHandleW(std::ptr::null()) as _;
            (hwnd, hinstance as _)
        };
        let mut handle = Win32WindowHandle::new(NonZeroIsize::new(hwnd as isize).unwrap());
        handle.hinstance = NonZeroIsize::new(hinstance as isize);
        RawWindowHandle::Win32(handle)
    }
    #[cfg(all(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"), not(feature = "wayland")))]
    {
        use raw_window_handle::XlibWindowHandle;
        let window = unsafe { ffi::glfwGetX11Window(context.window_ptr()) as std::os::raw::c_ulong };
        RawWindowHandle::Xlib(XlibWindowHandle::new(window))
    }
    #[cfg(all(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"), feature = "wayland"))]
    {
        use raw_window_handle::WaylandWindowHandle;
        use std::ptr::NonNull;
        let surface = unsafe { ffi::glfwGetWaylandWindow(context.window_ptr()) };
        let handle = WaylandWindowHandle::new(NonNull::new(surface).expect("wayland window surface is null"));
        RawWindowHandle::Wayland(handle)
    }
    #[cfg(target_os = "macos")]
    {
        use objc2::msg_send_id;
        use objc2::rc::Id;
        use objc2::runtime::NSObject;
        use raw_window_handle::AppKitWindowHandle;
        use std::ptr::NonNull;
        let ns_window: *mut NSObject =
            unsafe { ffi::glfwGetCocoaWindow(context.window_ptr()) as *mut _ };
        let ns_view: Option<Id<NSObject>> = unsafe { msg_send_id![ns_window, contentView] };
        let ns_view = ns_view.expect("failed to access contentView on GLFW NSWindow");
        let ns_view: NonNull<NSObject> = NonNull::from(&*ns_view);
        let handle = AppKitWindowHandle::new(ns_view.cast());
        RawWindowHandle::AppKit(handle)
    }
    #[cfg(target_os = "emscripten")]
    {
        let _ = context; let mut wh = raw_window_handle::WebWindowHandle::new(1);
        RawWindowHandle::Web(wh)
    }
}
#[cfg(feature = "raw-window-handle-v0-6")]
fn raw_display_handle() -> RawDisplayHandle {
    #[cfg(target_family = "windows")]
    {
        use raw_window_handle::WindowsDisplayHandle;
        RawDisplayHandle::Windows(WindowsDisplayHandle::new())
    }
    #[cfg(all(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"), not(feature = "wayland")))]
    {
        use raw_window_handle::XlibDisplayHandle;
        use std::ptr::NonNull;
        let display = NonNull::new(unsafe { ffi::glfwGetX11Display() });
        let handle = XlibDisplayHandle::new(display, 0);
        RawDisplayHandle::Xlib(handle)
    }
    #[cfg(all(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"), feature = "wayland"))]
    {
        use raw_window_handle::WaylandDisplayHandle;
        use std::ptr::NonNull;
        let display = NonNull::new(unsafe { ffi::glfwGetWaylandDisplay() }).expect("wayland display is null");
        let handle = WaylandDisplayHandle::new(display);
        RawDisplayHandle::Wayland(handle)
    }
    #[cfg(target_os = "macos")]
    {
        use raw_window_handle::AppKitDisplayHandle;
        RawDisplayHandle::AppKit(AppKitDisplayHandle::new())
    }
    #[cfg(target_os = "emscripten")]
    {
        RawDisplayHandle::Web(raw_window_handle::WebDisplayHandle::new())
    }
}
#[cfg(feature = "raw-window-handle-v0-5")]
fn raw_window_handle<C: Context>(context: &C) -> RawWindowHandle {
    #[cfg(target_family = "windows")]
    {
        use raw_window_handle::Win32WindowHandle;
        let (hwnd, hinstance) = unsafe {
            let hwnd = ffi::glfwGetWin32Window(context.window_ptr());
            let hinstance = winapi::um::libloaderapi::GetModuleHandleW(std::ptr::null());
            (hwnd, hinstance as _)
        };
        let mut handle = Win32WindowHandle::empty();
        handle.hwnd = hwnd;
        handle.hinstance = hinstance;
        RawWindowHandle::Win32(handle)
    }
    #[cfg(all(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"), not(feature = "wayland")))]
    {
        use raw_window_handle::XlibWindowHandle;
        let mut handle = XlibWindowHandle::empty();
        handle.window = unsafe { ffi::glfwGetX11Window(context.window_ptr()) as std::os::raw::c_ulong };
        RawWindowHandle::Xlib(handle)
    }
    #[cfg(all(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"), feature = "wayland"))]
    {
        use raw_window_handle::WaylandWindowHandle;
        let mut handle = WaylandWindowHandle::empty();
        handle.surface = unsafe { ffi::glfwGetWaylandWindow(context.window_ptr()) };
        RawWindowHandle::Wayland(handle)
    }
    #[cfg(target_os = "macos")]
    {
        use raw_window_handle::AppKitWindowHandle;
        let (ns_window, ns_view) = unsafe {
            let ns_window: *mut objc::runtime::Object =
                ffi::glfwGetCocoaWindow(context.window_ptr()) as *mut _;
            let ns_view: *mut objc::runtime::Object = objc::msg_send![ns_window, contentView];
            assert_ne!(ns_view, std::ptr::null_mut());
            (
                ns_window as *mut std::ffi::c_void,
                ns_view as *mut std::ffi::c_void,
            )
        };
        let mut handle = AppKitWindowHandle::empty();
        handle.ns_window = ns_window;
        handle.ns_view = ns_view;
        RawWindowHandle::AppKit(handle)
    }
    #[cfg(target_os = "emscripten")]
    {
        let _ = context; let mut wh = raw_window_handle::WebWindowHandle::empty();
        wh.id = 1;
        RawWindowHandle::Web(wh)
    }
}
#[cfg(feature = "raw-window-handle-v0-5")]
fn raw_display_handle() -> RawDisplayHandle {
    #[cfg(target_family = "windows")]
    {
        use raw_window_handle::WindowsDisplayHandle;
        RawDisplayHandle::Windows(WindowsDisplayHandle::empty())
    }
    #[cfg(all(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"), not(feature = "wayland")))]
    {
        use raw_window_handle::XlibDisplayHandle;
        let mut handle = XlibDisplayHandle::empty();
        handle.display = unsafe { ffi::glfwGetX11Display() };
        RawDisplayHandle::Xlib(handle)
    }
    #[cfg(all(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"), feature = "wayland"))]
    {
        use raw_window_handle::WaylandDisplayHandle;
        let mut handle = WaylandDisplayHandle::empty();
        handle.display = unsafe { ffi::glfwGetWaylandDisplay() };
        RawDisplayHandle::Wayland(handle)
    }
    #[cfg(target_os = "macos")]
    {
        use raw_window_handle::AppKitDisplayHandle;
        RawDisplayHandle::AppKit(AppKitDisplayHandle::empty())
    }
    #[cfg(target_os = "emscripten")]
    {
        RawDisplayHandle::Web(raw_window_handle::WebDisplayHandle::empty())
    }
}
pub fn make_context_current(context: Option<&dyn Context>) {
    match context {
        Some(ctx) => unsafe { ffi::glfwMakeContextCurrent(ctx.window_ptr()) },
        None => unsafe { ffi::glfwMakeContextCurrent(ptr::null_mut()) },
    }
}
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum JoystickId {
    Joystick1 = ffi::JOYSTICK_1,
    Joystick2 = ffi::JOYSTICK_2,
    Joystick3 = ffi::JOYSTICK_3,
    Joystick4 = ffi::JOYSTICK_4,
    Joystick5 = ffi::JOYSTICK_5,
    Joystick6 = ffi::JOYSTICK_6,
    Joystick7 = ffi::JOYSTICK_7,
    Joystick8 = ffi::JOYSTICK_8,
    Joystick9 = ffi::JOYSTICK_9,
    Joystick10 = ffi::JOYSTICK_10,
    Joystick11 = ffi::JOYSTICK_11,
    Joystick12 = ffi::JOYSTICK_12,
    Joystick13 = ffi::JOYSTICK_13,
    Joystick14 = ffi::JOYSTICK_14,
    Joystick15 = ffi::JOYSTICK_15,
    Joystick16 = ffi::JOYSTICK_16,
}
impl JoystickId {
    pub fn from_i32(n: i32) -> Option<JoystickId> {
        if (0..=ffi::JOYSTICK_LAST).contains(&n) {
            Some(unsafe { mem::transmute(n) })
        } else {
            None
        }
    }
}
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum GamepadButton {
    ButtonA = ffi::GAMEPAD_BUTTON_A,
    ButtonB = ffi::GAMEPAD_BUTTON_B,
    ButtonX = ffi::GAMEPAD_BUTTON_X,
    ButtonY = ffi::GAMEPAD_BUTTON_Y,
    ButtonLeftBumper = ffi::GAMEPAD_BUTTON_LEFT_BUMPER,
    ButtonRightBumper = ffi::GAMEPAD_BUTTON_RIGHT_BUMPER,
    ButtonBack = ffi::GAMEPAD_BUTTON_BACK,
    ButtonStart = ffi::GAMEPAD_BUTTON_START,
    ButtonGuide = ffi::GAMEPAD_BUTTON_GUIDE,
    ButtonLeftThumb = ffi::GAMEPAD_BUTTON_LEFT_THUMB,
    ButtonRightThumb = ffi::GAMEPAD_BUTTON_RIGHT_THUMB,
    ButtonDpadUp = ffi::GAMEPAD_BUTTON_DPAD_UP,
    ButtonDpadRight = ffi::GAMEPAD_BUTTON_DPAD_RIGHT,
    ButtonDpadDown = ffi::GAMEPAD_BUTTON_DPAD_DOWN,
    ButtonDpadLeft = ffi::GAMEPAD_BUTTON_DPAD_LEFT,
}
impl GamepadButton {
    pub fn from_i32(n: i32) -> Option<GamepadButton> {
        if (0..=ffi::GAMEPAD_BUTTON_LAST).contains(&n) {
            Some(unsafe { mem::transmute(n) })
        } else {
            None
        }
    }
}
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum GamepadAxis {
    AxisLeftX = ffi::GAMEPAD_AXIS_LEFT_X,
    AxisLeftY = ffi::GAMEPAD_AXIS_LEFT_Y,
    AxisRightX = ffi::GAMEPAD_AXIS_RIGHT_X,
    AxisRightY = ffi::GAMEPAD_AXIS_RIGHT_Y,
    AxisLeftTrigger = ffi::GAMEPAD_AXIS_LEFT_TRIGGER,
    AxisRightTrigger = ffi::GAMEPAD_AXIS_RIGHT_TRIGGER,
}
impl GamepadAxis {
    pub fn from_i32(n: i32) -> Option<GamepadAxis> {
        if (0..=ffi::GAMEPAD_AXIS_LAST).contains(&n) {
            Some(unsafe { mem::transmute(n) })
        } else {
            None
        }
    }
}
bitflags! {
    #[doc = "Joystick hats."]
    pub struct JoystickHats: ::std::os::raw::c_int {
        const Centered = crate::ffi::HAT_CENTERED;
        const Up       = crate::ffi::HAT_UP;
        const Right    = crate::ffi::HAT_RIGHT;
        const Down     = crate::ffi::HAT_DOWN;
        const Left     = crate::ffi::HAT_LEFT;
    }
}
#[derive(Clone, Debug)]
pub struct Joystick {
    pub id: JoystickId,
    pub glfw: Glfw,
}
#[derive(Copy, Clone, Debug)]
pub struct GamepadState {
    buttons: [Action; (ffi::GAMEPAD_BUTTON_LAST + 1) as usize],
    axes: [f32; (ffi::GAMEPAD_AXIS_LAST + 1) as usize],
}
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum JoystickEvent {
    Connected = ffi::CONNECTED,
    Disconnected = ffi::DISCONNECTED,
}
impl Joystick {
    pub fn is_present(&self) -> bool {
        unsafe { ffi::glfwJoystickPresent(self.id as c_int) == ffi::TRUE }
    }
    pub fn get_axes(&self) -> Vec<f32> {
        unsafe {
            let mut count = 0;
            let ptr = ffi::glfwGetJoystickAxes(self.id as c_int, &mut count);
            slice::from_raw_parts(ptr, count as usize)
                .iter()
                .map(|&a| a as f32)
                .collect()
        }
    }
    pub fn get_buttons(&self) -> Vec<c_int> {
        unsafe {
            let mut count = 0;
            let ptr = ffi::glfwGetJoystickButtons(self.id as c_int, &mut count);
            slice::from_raw_parts(ptr, count as usize)
                .iter()
                .map(|&b| b as c_int)
                .collect()
        }
    }
    pub fn get_hats(&self) -> Vec<JoystickHats> {
        unsafe {
            let mut count = 0;
            let ptr = ffi::glfwGetJoystickHats(self.id as c_int, &mut count);
            slice::from_raw_parts(ptr, count as usize)
                .iter()
                .map(|&b| mem::transmute(b as c_int))
                .collect()
        }
    }
    pub fn get_name(&self) -> Option<String> {
        unsafe { string_from_nullable_c_str(ffi::glfwGetJoystickName(self.id as c_int)) }
    }
    pub fn get_guid(&self) -> Option<String> {
        unsafe { string_from_nullable_c_str(ffi::glfwGetJoystickGUID(self.id as c_int)) }
    }
    pub fn is_gamepad(&self) -> bool {
        unsafe { ffi::glfwJoystickIsGamepad(self.id as c_int) == ffi::TRUE }
    }
    pub fn get_gamepad_name(&self) -> Option<String> {
        unsafe { string_from_nullable_c_str(ffi::glfwGetGamepadName(self.id as c_int)) }
    }
    pub fn get_gamepad_state(&self) -> Option<GamepadState> {
        unsafe {
            let mut state = ffi::GLFWgamepadstate {
                buttons: [0; (ffi::GAMEPAD_BUTTON_LAST + 1) as usize],
                axes: [0_f32; (ffi::GAMEPAD_AXIS_LAST + 1) as usize],
            };
            if ffi::glfwGetGamepadState(self.id as c_int, &mut state) == ffi::TRUE {
                Some(state.into())
            } else {
                None
            }
        }
    }
}
impl From<ffi::GLFWgamepadstate> for GamepadState {
    fn from(state: ffi::GLFWgamepadstate) -> Self {
        let mut buttons = [Action::Release; (ffi::GAMEPAD_BUTTON_LAST + 1) as usize];
        let mut axes = [0_f32; (ffi::GAMEPAD_AXIS_LAST + 1) as usize];
        unsafe {
            state
                .buttons
                .iter()
                .map(|&b| mem::transmute(b as c_int))
                .zip(buttons.iter_mut())
                .for_each(|(a, b)| *b = a);
        }
        state
            .axes
            .iter()
            .map(|&f| f as f32)
            .zip(axes.iter_mut())
            .for_each(|(a, b)| *b = a);
        Self { buttons, axes }
    }
}
impl GamepadState {
    pub fn get_button_state(&self, button: GamepadButton) -> Action {
        self.buttons[button as usize]
    }
    pub fn get_axis(&self, axis: GamepadAxis) -> f32 {
        self.axes[axis as usize]
    }
}
#[inline(always)]
fn unwrap_dont_care(value: Option<u32>) -> c_int {
    match value {
        Some(v) => v as c_int,
        None => ffi::DONT_CARE,
    }
}