1 // Copyright 2013-2016 The GLFW-RS Developers. For a full listing of the authors,
2 // refer to the AUTHORS file at the top-level directory of this distribution.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #![crate_type = "lib"]
17 #![crate_type = "rlib"]
18 #![crate_type = "dylib"]
19 #![crate_name = "glfw"]
20 
21 #![allow(non_upper_case_globals)]
22 
23 //! An idiomatic wrapper for the GLFW library.
24 //!
25 //! # Example
26 //!
27 //! ~~~no_run
28 //! extern crate glfw;
29 //!
30 //! use glfw::{Action, Context, Key};
31 //!
32 //! fn main() {
33 //!    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
34 //!
35 //!     // Create a windowed mode window and its OpenGL context
36 //!     let (mut window, events) = glfw.create_window(300, 300, "Hello this is window", glfw::WindowMode::Windowed)
37 //!         .expect("Failed to create GLFW window.");
38 //!
39 //!     // Make the window's context current
40 //!     window.make_current();
41 //!     window.set_key_polling(true);
42 //!
43 //!     // Loop until the user closes the window
44 //!     while !window.should_close() {
45 //!         // Swap front and back buffers
46 //!         window.swap_buffers();
47 //!
48 //!         // Poll for and process events
49 //!         glfw.poll_events();
50 //!         for (_, event) in glfw::flush_messages(&events) {
51 //!             println!("{:?}", event);
52 //!             match event {
53 //!                 glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
54 //!                     window.set_should_close(true)
55 //!                 },
56 //!                 _ => {},
57 //!             }
58 //!         }
59 //!     }
60 //! }
61 //! ~~~
62 //!
63 //! # Cargo Features
64 //!
65 //! Use the `vulkan` feature flag to enable all Vulkan functions and types.
66 //!
67 //! Use the `image` feature flag to enable use of the [`image`](https://github.com/PistonDevelopers/image) library for cursors and icons.
68 //!
69 //! Use the `all` feature flag to enable both at the same time.
70 //!
71 
72 // TODO: Document differences between GLFW and glfw-rs
73 
74 extern crate semver;
75 extern crate libc;
76 #[cfg(feature = "vulkan")]
77 extern crate vk_sys;
78 #[macro_use]
79 extern crate log;
80 #[macro_use]
81 extern crate bitflags;
82 #[cfg(feature = "image")]
83 extern crate image;
84 extern crate raw_window_handle;
85 #[cfg(all(target_os="macos"))]
86 #[macro_use]
87 extern crate objc;
88 
89 use libc::{c_char, c_double, c_float, c_int};
90 use libc::{c_ushort, c_void, c_uchar};
91 #[cfg(feature = "vulkan")]
92 use libc::c_uint;
93 use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
94 use std::ffi::{CStr, CString};
95 use std::mem;
96 use std::sync::mpsc::{channel, Receiver, Sender};
97 use std::fmt;
98 use std::error;
99 use std::marker::Send;
100 use std::ptr;
101 use std::slice;
102 use std::path::PathBuf;
103 use std::sync::atomic::{AtomicUsize, Ordering};
104 use semver::Version;
105 
106 #[cfg(feature = "vulkan")]
107 use vk_sys::{
108     self as vk,
109     Instance as VkInstance,
110     PhysicalDevice as VkPhysicalDevice
111 };
112 
113 /// Alias to `MouseButton1`, supplied for improved clarity.
114 pub use self::MouseButton::Button1 as MouseButtonLeft;
115 /// Alias to `MouseButton2`, supplied for improved clarity.
116 pub use self::MouseButton::Button2 as MouseButtonRight;
117 /// Alias to `MouseButton3`, supplied for improved clarity.
118 pub use self::MouseButton::Button3 as MouseButtonMiddle;
119 
120 pub mod ffi;
121 mod callbacks;
122 
123 /// Unique identifier for a `Window`.
124 pub type WindowId = usize;
125 
126 /// Input actions.
127 #[repr(i32)]
128 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
129 pub enum Action {
130     Release                      = ffi::RELEASE,
131     Press                        = ffi::PRESS,
132     Repeat                       = ffi::REPEAT,
133 }
134 
135 /// Input keys.
136 #[repr(i32)]
137 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
138 pub enum Key {
139     Space                    = ffi::KEY_SPACE,
140     Apostrophe               = ffi::KEY_APOSTROPHE,
141     Comma                    = ffi::KEY_COMMA,
142     Minus                    = ffi::KEY_MINUS,
143     Period                   = ffi::KEY_PERIOD,
144     Slash                    = ffi::KEY_SLASH,
145     Num0                     = ffi::KEY_0,
146     Num1                     = ffi::KEY_1,
147     Num2                     = ffi::KEY_2,
148     Num3                     = ffi::KEY_3,
149     Num4                     = ffi::KEY_4,
150     Num5                     = ffi::KEY_5,
151     Num6                     = ffi::KEY_6,
152     Num7                     = ffi::KEY_7,
153     Num8                     = ffi::KEY_8,
154     Num9                     = ffi::KEY_9,
155     Semicolon                = ffi::KEY_SEMICOLON,
156     Equal                    = ffi::KEY_EQUAL,
157     A                        = ffi::KEY_A,
158     B                        = ffi::KEY_B,
159     C                        = ffi::KEY_C,
160     D                        = ffi::KEY_D,
161     E                        = ffi::KEY_E,
162     F                        = ffi::KEY_F,
163     G                        = ffi::KEY_G,
164     H                        = ffi::KEY_H,
165     I                        = ffi::KEY_I,
166     J                        = ffi::KEY_J,
167     K                        = ffi::KEY_K,
168     L                        = ffi::KEY_L,
169     M                        = ffi::KEY_M,
170     N                        = ffi::KEY_N,
171     O                        = ffi::KEY_O,
172     P                        = ffi::KEY_P,
173     Q                        = ffi::KEY_Q,
174     R                        = ffi::KEY_R,
175     S                        = ffi::KEY_S,
176     T                        = ffi::KEY_T,
177     U                        = ffi::KEY_U,
178     V                        = ffi::KEY_V,
179     W                        = ffi::KEY_W,
180     X                        = ffi::KEY_X,
181     Y                        = ffi::KEY_Y,
182     Z                        = ffi::KEY_Z,
183     LeftBracket              = ffi::KEY_LEFT_BRACKET,
184     Backslash                = ffi::KEY_BACKSLASH,
185     RightBracket             = ffi::KEY_RIGHT_BRACKET,
186     GraveAccent              = ffi::KEY_GRAVE_ACCENT,
187     World1                   = ffi::KEY_WORLD_1,
188     World2                   = ffi::KEY_WORLD_2,
189 
190     Escape                   = ffi::KEY_ESCAPE,
191     Enter                    = ffi::KEY_ENTER,
192     Tab                      = ffi::KEY_TAB,
193     Backspace                = ffi::KEY_BACKSPACE,
194     Insert                   = ffi::KEY_INSERT,
195     Delete                   = ffi::KEY_DELETE,
196     Right                    = ffi::KEY_RIGHT,
197     Left                     = ffi::KEY_LEFT,
198     Down                     = ffi::KEY_DOWN,
199     Up                       = ffi::KEY_UP,
200     PageUp                   = ffi::KEY_PAGE_UP,
201     PageDown                 = ffi::KEY_PAGE_DOWN,
202     Home                     = ffi::KEY_HOME,
203     End                      = ffi::KEY_END,
204     CapsLock                 = ffi::KEY_CAPS_LOCK,
205     ScrollLock               = ffi::KEY_SCROLL_LOCK,
206     NumLock                  = ffi::KEY_NUM_LOCK,
207     PrintScreen              = ffi::KEY_PRINT_SCREEN,
208     Pause                    = ffi::KEY_PAUSE,
209     F1                       = ffi::KEY_F1,
210     F2                       = ffi::KEY_F2,
211     F3                       = ffi::KEY_F3,
212     F4                       = ffi::KEY_F4,
213     F5                       = ffi::KEY_F5,
214     F6                       = ffi::KEY_F6,
215     F7                       = ffi::KEY_F7,
216     F8                       = ffi::KEY_F8,
217     F9                       = ffi::KEY_F9,
218     F10                      = ffi::KEY_F10,
219     F11                      = ffi::KEY_F11,
220     F12                      = ffi::KEY_F12,
221     F13                      = ffi::KEY_F13,
222     F14                      = ffi::KEY_F14,
223     F15                      = ffi::KEY_F15,
224     F16                      = ffi::KEY_F16,
225     F17                      = ffi::KEY_F17,
226     F18                      = ffi::KEY_F18,
227     F19                      = ffi::KEY_F19,
228     F20                      = ffi::KEY_F20,
229     F21                      = ffi::KEY_F21,
230     F22                      = ffi::KEY_F22,
231     F23                      = ffi::KEY_F23,
232     F24                      = ffi::KEY_F24,
233     F25                      = ffi::KEY_F25,
234     Kp0                      = ffi::KEY_KP_0,
235     Kp1                      = ffi::KEY_KP_1,
236     Kp2                      = ffi::KEY_KP_2,
237     Kp3                      = ffi::KEY_KP_3,
238     Kp4                      = ffi::KEY_KP_4,
239     Kp5                      = ffi::KEY_KP_5,
240     Kp6                      = ffi::KEY_KP_6,
241     Kp7                      = ffi::KEY_KP_7,
242     Kp8                      = ffi::KEY_KP_8,
243     Kp9                      = ffi::KEY_KP_9,
244     KpDecimal                = ffi::KEY_KP_DECIMAL,
245     KpDivide                 = ffi::KEY_KP_DIVIDE,
246     KpMultiply               = ffi::KEY_KP_MULTIPLY,
247     KpSubtract               = ffi::KEY_KP_SUBTRACT,
248     KpAdd                    = ffi::KEY_KP_ADD,
249     KpEnter                  = ffi::KEY_KP_ENTER,
250     KpEqual                  = ffi::KEY_KP_EQUAL,
251     LeftShift                = ffi::KEY_LEFT_SHIFT,
252     LeftControl              = ffi::KEY_LEFT_CONTROL,
253     LeftAlt                  = ffi::KEY_LEFT_ALT,
254     LeftSuper                = ffi::KEY_LEFT_SUPER,
255     RightShift               = ffi::KEY_RIGHT_SHIFT,
256     RightControl             = ffi::KEY_RIGHT_CONTROL,
257     RightAlt                 = ffi::KEY_RIGHT_ALT,
258     RightSuper               = ffi::KEY_RIGHT_SUPER,
259     Menu                     = ffi::KEY_MENU,
260     Unknown                  = ffi::KEY_UNKNOWN
261 }
262 
263 /// Wrapper around 'glfwGetKeyName`
get_key_name(key: Option<Key>, scancode: Option<Scancode>) -> Option<String>264 pub fn get_key_name(key: Option<Key>, scancode: Option<Scancode>) -> Option<String> {
265     unsafe {
266         string_from_nullable_c_str(ffi::glfwGetKeyName(match key {
267             Some(k) => k as c_int,
268             None => ffi::KEY_UNKNOWN
269         }, scancode.unwrap_or(ffi::KEY_UNKNOWN)))
270     }
271 }
272 
273 /// Wrapper around 'glfwGetKeyName`
274 #[deprecated(since = "0.16.0", note = "'key_name' can cause a segfault, use 'get_key_name' instead")]
key_name(key: Option<Key>, scancode: Option<Scancode>) -> String275 pub fn key_name(key: Option<Key>, scancode: Option<Scancode>) -> String {
276     unsafe {
277         string_from_c_str(ffi::glfwGetKeyName(match key {
278             Some(k) => k as c_int,
279             None => ffi::KEY_UNKNOWN
280         }, scancode.unwrap_or(ffi::KEY_UNKNOWN)))
281     }
282 }
283 
284 /// Wrapper around `glfwGetKeyScancode`.
get_key_scancode(key: Option<Key>) -> Option<Scancode>285 pub fn get_key_scancode(key: Option<Key>) -> Option<Scancode> {
286     unsafe {
287         match ffi::glfwGetKeyScancode(match key {
288             Some(key) => key as c_int,
289             None => ffi::KEY_UNKNOWN,
290         }) {
291             ffi::KEY_UNKNOWN => None,
292             scancode => Some(scancode as Scancode),
293         }
294     }
295 }
296 
297 impl Key {
298     /// Wrapper around 'glfwGetKeyName` without scancode
299     #[deprecated(since = "0.16.0", note = "Key method 'name' can cause a segfault, use 'get_name' instead")]
name(&self) -> String300     pub fn name(&self) -> String {
301         #[allow(deprecated)]
302         key_name(Some(*self), None)
303     }
304 
305     /// Wrapper around 'glfwGetKeyName` without scancode
get_name(&self) -> Option<String>306     pub fn get_name(&self) -> Option<String> {
307 	    get_key_name(Some(*self), None)
308     }
309 
310     /// Wrapper around `glfwGetKeyScancode`.
get_scancode(&self) -> Option<Scancode>311     pub fn get_scancode(&self) -> Option<Scancode> {
312         get_key_scancode(Some(*self))
313     }
314 }
315 
316 /// Mouse buttons. The `MouseButtonLeft`, `MouseButtonRight`, and
317 /// `MouseButtonMiddle` aliases are supplied for convenience.
318 #[repr(i32)]
319 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
320 pub enum MouseButton {
321     /// The left mouse button. A `MouseButtonLeft` alias is provided to improve clarity.
322     Button1                = ffi::MOUSE_BUTTON_1,
323     /// The right mouse button. A `MouseButtonRight` alias is provided to improve clarity.
324     Button2                = ffi::MOUSE_BUTTON_2,
325     /// The middle mouse button. A `MouseButtonMiddle` alias is provided to improve clarity.
326     Button3                = ffi::MOUSE_BUTTON_3,
327     Button4                = ffi::MOUSE_BUTTON_4,
328     Button5                = ffi::MOUSE_BUTTON_5,
329     Button6                = ffi::MOUSE_BUTTON_6,
330     Button7                = ffi::MOUSE_BUTTON_7,
331     Button8                = ffi::MOUSE_BUTTON_8,
332 }
333 
334 impl MouseButton {
335     /// Converts from `i32`.
from_i32(n: i32) -> Option<MouseButton>336     pub fn from_i32(n: i32) -> Option<MouseButton> {
337         if n >= 0 && n <= ffi::MOUSE_BUTTON_LAST {
338             Some(unsafe { mem::transmute(n) })
339         } else {
340             None
341         }
342     }
343 }
344 
345 /// Formats the type using aliases rather than the default variant names.
346 ///
347 /// # Example
348 ///
349 /// ~~~ignore
350 /// assert_eq(format!("{}", glfw::MouseButtonLeft), "MouseButton1");
351 /// assert_eq(format!("{}", glfw::DebugAliases(glfw::MouseButtonLeft)), "MouseButtonLeft");
352 /// ~~~
353 pub struct DebugAliases<T>(pub T);
354 
355 impl fmt::Debug for DebugAliases<MouseButton> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result356     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
357         let DebugAliases(button) = *self;
358         match button {
359             MouseButtonLeft     => write!(f, "MouseButtonLeft"),
360             MouseButtonRight    => write!(f, "MouseButtonRight"),
361             MouseButtonMiddle   => write!(f, "MouseButtonMiddle"),
362             button              => button.fmt(f),
363         }
364     }
365 }
366 
367 #[derive(Copy, Clone)]
368 pub struct Callback<Fn, UserData> {
369     pub f: Fn,
370     pub data: UserData,
371 }
372 
373 /// Tokens corresponding to various error types.
374 #[repr(i32)]
375 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
376 pub enum Error {
377     NoError                     = ffi::NO_ERROR,
378     NotInitialized              = ffi::NOT_INITIALIZED,
379     NoCurrentContext            = ffi::NO_CURRENT_CONTEXT,
380     InvalidEnum                 = ffi::INVALID_ENUM,
381     InvalidValue                = ffi::INVALID_VALUE,
382     OutOfMemory                 = ffi::OUT_OF_MEMORY,
383     ApiUnavailable              = ffi::API_UNAVAILABLE,
384     VersionUnavailable          = ffi::VERSION_UNAVAILABLE,
385     PlatformError               = ffi::PLATFORM_ERROR,
386     FormatUnavailable           = ffi::FORMAT_UNAVAILABLE,
387     NoWindowContext             = ffi::NO_WINDOW_CONTEXT,
388 }
389 
390 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result391     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
392         use std::error::Error;
393 
394         f.write_str(self.description())
395     }
396 }
397 
398 impl error::Error for Error {
description(&self) -> &str399     fn description(&self) -> &str {
400         match *self {
401             Error::NoError => "NoError",
402             Error::NotInitialized => "NotInitialized",
403             Error::NoCurrentContext => "NoCurrentContext",
404             Error::InvalidEnum => "InvalidEnum",
405             Error::InvalidValue => "InvalidValue",
406             Error::OutOfMemory => "OutOfMemory",
407             Error::ApiUnavailable => "ApiUnavailable",
408             Error::VersionUnavailable => "VersionUnavailable",
409             Error::PlatformError => "PlatformError",
410             Error::FormatUnavailable => "FormatUnavailable",
411             Error::NoWindowContext => "NoWindowContext",
412         }
413     }
414 }
415 
416 /// An error callback. This can be supplied with some user data to be passed to
417 /// the callback function when it is triggered.
418 pub type ErrorCallback<UserData> = Callback<fn(Error, String, &UserData), UserData>;
419 
420 /// The function to be used with the `FAIL_ON_ERRORS` callback.
fail_on_errors(_: Error, description: String, _: &())421 pub fn fail_on_errors(_: Error, description: String, _: &()) {
422     panic!("GLFW Error: {}", description);
423 }
424 
425 /// A callback that triggers a task failure when an error is encountered.
426 pub static FAIL_ON_ERRORS: Option<ErrorCallback<()>> =
427     Some(Callback { f: fail_on_errors as fn(Error, String, &()), data: () });
428 
429 /// The function to be used with the `LOG_ERRORS` callback.
log_errors(_: Error, description: String, _: &())430 pub fn log_errors(_: Error, description: String, _: &()) {
431     error!("GLFW Error: {}", description);
432 }
433 
434 /// A callback that logs each error as it is encountered without triggering a
435 /// task failure.
436 pub static LOG_ERRORS: Option<ErrorCallback<()>> =
437     Some(Callback { f: log_errors as fn(Error, String, &()), data: () });
438 
439 /// When not using the `image` library, or if you just want to,
440 /// you can specify an image from its raw pixel data using this structure.
441 pub struct PixelImage {
442     /// Width of the image in pixels
443     pub width: u32,
444     /// Height of the image in pixels
445     pub height: u32,
446     /// Pixels are 4 bytes each, one byte for each RGBA subpixel.
447     pub pixels: Vec<u32>
448 }
449 
450 /// Cursor modes.
451 #[repr(i32)]
452 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
453 pub enum CursorMode {
454     Normal                = ffi::CURSOR_NORMAL,
455     Hidden                = ffi::CURSOR_HIDDEN,
456     Disabled              = ffi::CURSOR_DISABLED,
457 }
458 
459 /// Standard cursors provided by GLFW
460 #[repr(i32)]
461 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
462 pub enum StandardCursor {
463     /// The regular arrow cursor shape.
464     Arrow                 = ffi::ARROW_CURSOR,
465     /// The text input I-beam cursor shape.
466     IBeam                 = ffi::IBEAM_CURSOR,
467     /// The crosshair shape.
468     Crosshair             = ffi::CROSSHAIR_CURSOR,
469     /// The hand shape.
470     Hand                  = ffi::HAND_CURSOR,
471     /// The horizontal resize arrow shape.
472     HResize               = ffi::HRESIZE_CURSOR,
473     /// The vertical resize arrow shape.
474     VResize               = ffi::VRESIZE_CURSOR
475 }
476 
477 /// Represents a window cursor that can be used to display any
478 /// of the standard cursors or load a custom cursor from an image.
479 ///
480 /// Note that the cursor object has a lifetime and will not display
481 /// correctly after it has been dropped.
482 pub struct Cursor {
483     ptr: *mut ffi::GLFWcursor
484 }
485 
486 impl Drop for Cursor {
drop(&mut self)487     fn drop(&mut self) {
488         unsafe { ffi::glfwDestroyCursor(self.ptr) }
489     }
490 }
491 
492 impl Cursor {
493     /// Create a new cursor using `glfwCreateStandardCursor`
standard(cursor: StandardCursor) -> Cursor494     pub fn standard(cursor: StandardCursor) -> Cursor {
495         Cursor {
496             ptr: unsafe { ffi::glfwCreateStandardCursor(cursor as c_int) }
497         }
498     }
499 
500     /// Creates a new cursor from the image provided via `glfwCreateCursor`
501     ///
502     /// Note that the cursor image will be the same size as the image provided,
503     /// so scaling it beforehand may be required.
504     ///
505     /// The cursor hotspot is specified in pixels, relative to the upper-left
506     /// corner of the cursor image. Like all other coordinate systems in GLFW,
507     /// the X-axis points to the right and the Y-axis points down.
508     #[cfg(feature = "image")]
create(image: image::RgbaImage, x_hotspot: u32, y_hotspot: u32) -> Cursor509     pub fn create(image: image::RgbaImage, x_hotspot: u32, y_hotspot: u32) -> Cursor {
510         let (width, height) = image.dimensions();
511 
512         let image_data = image.into_vec();
513 
514         let glfw_image = ffi::GLFWimage {
515             width: width as c_int,
516             height: height as c_int,
517             pixels: image_data.as_ptr() as *const c_uchar
518         };
519 
520         Cursor {
521             ptr: unsafe { ffi::glfwCreateCursor(&glfw_image as *const ffi::GLFWimage, x_hotspot as c_int, y_hotspot as c_int) }
522         }
523     }
524 
525     /// Creates a new cursor from the `PixelImage` provided via `glfwCreateCursor`
526     ///
527     /// Note that the cursor image will be the same size as the image provided,
528     /// so scaling it beforehand may be required.
529     ///
530     /// The cursor hotspot is specified in pixels, relative to the upper-left
531     /// corner of the cursor image. Like all other coordinate systems in GLFW,
532     /// the X-axis points to the right and the Y-axis points down.
create_from_pixels(image: PixelImage, x_hotspot: u32, y_hotspot: u32) -> Cursor533     pub fn create_from_pixels(image: PixelImage, x_hotspot: u32, y_hotspot: u32) -> Cursor {
534         let glfw_image = ffi::GLFWimage {
535             width: image.width as c_int,
536             height: image.height as c_int,
537             pixels: image.pixels.as_ptr() as *const c_uchar
538         };
539 
540         Cursor {
541             ptr: unsafe { ffi::glfwCreateCursor(&glfw_image as *const ffi::GLFWimage, x_hotspot as c_int, y_hotspot as c_int) }
542         }
543     }
544 }
545 
546 /// Describes a single video mode.
547 #[derive(Copy, Clone)]
548 pub struct VidMode {
549     pub width:        u32,
550     pub height:       u32,
551     pub red_bits:     u32,
552     pub green_bits:   u32,
553     pub blue_bits:    u32,
554     pub refresh_rate: u32,
555 }
556 
557 /// Describes the gamma ramp of a monitor.
558 pub struct GammaRamp {
559     pub red:    Vec<c_ushort>,
560     pub green:  Vec<c_ushort>,
561     pub blue:   Vec<c_ushort>,
562 }
563 
564 /// `ContextReleaseBehavior` specifies the release behavior to be used by the context.
565 #[repr(i32)]
566 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
567 pub enum ContextReleaseBehavior {
568     Any                   = ffi::ANY_RELEASE_BEHAVIOR,
569     /// `Flush` tells the context to flush the pipeline whenever the context is released from being the current one.
570     Flush                 = ffi::RELEASE_BEHAVIOR_FLUSH,
571     /// `None` tells the context to NOT flush the pipeline on release
572     None                  = ffi::RELEASE_BEHAVIOR_NONE
573 }
574 
575 /// Specifies the API to use to create the context
576 #[repr(i32)]
577 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
578 pub enum ContextCreationApi {
579     Native                = ffi::NATIVE_CONTEXT_API,
580     Egl                   = ffi::EGL_CONTEXT_API,
581     OsMesa                = ffi::OSMESA_CONTEXT_API,
582 }
583 
584 /// Specifies how the context should handle swapping the buffers.
585 ///
586 /// i.e. the number of screen updates to wait from the time
587 /// `glfwSwapBuffers`/`context.swap_buffers`
588 /// was called before swapping the buffers and returning.
589 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
590 pub enum SwapInterval {
591     /// Specifies no waits
592     None,
593     /// If either of the `WGL_EXT_swap_control_tear` and `GLX_EXT_swap_control_tear` extensions
594     /// are enabled, allows the adaptively swap the frame. Sometimes called Adaptive V-sync
595     Adaptive,
596     /// Synchronizes the buffers every N frames. Set to 1 for V-sync
597     Sync(u32)
598 }
599 
600 /// An OpenGL process address.
601 pub type GLProc = ffi::GLFWglproc;
602 
603 /// A Vulkan process address
604 #[cfg(feature = "vulkan")]
605 pub type VkProc = ffi::GLFWvkproc;
606 
607 /// Counts for (Calling glfwInit) - (Calling glfwTerminate)
608 /// It uses for "global" refference counting for Glfw.
609 static REF_COUNT_FOR_GLFW: AtomicUsize = AtomicUsize::new(0);
610 
611 /// A token from which to call various GLFW functions. It can be obtained by
612 /// calling the `init` function. This cannot be sent to other tasks, and should
613 /// only be initialized on the main platform thread. Whilst this might make
614 /// performing some operations harder, this is to ensure thread safety is enforced
615 /// statically.
616 pub struct Glfw;
617 
618 /// An error that might be returned when `glfw::init` is called.
619 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
620 pub enum InitError {
621     /// Deprecated. Does not occur.
622     AlreadyInitialized,
623     /// An internal error occurred when trying to initialize the library.
624     Internal,
625 }
626 
627 impl fmt::Display for InitError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result628     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
629         use std::error::Error;
630 
631         f.write_str(self.description())
632     }
633 }
634 
635 impl error::Error for InitError {
description(&self) -> &str636     fn description(&self) -> &str {
637         match *self {
638             InitError::AlreadyInitialized => "Already Initialized",
639             InitError::Internal => "Internal Initialization Error",
640         }
641     }
642 }
643 
644 /// Initialization hints that can be set using the `init_hint` function.
645 #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
646 pub enum InitHint {
647     /// Specifies whether to also expose joystick hats as buttons, for compatibility with ealier
648     /// versions of GLFW that did not have `glfwGetJoystickHats`.
649     JoystickHatButtons(bool),
650     /// Specifies whether to set the current directory to the application to the `Contents/Resources`
651     /// subdirectory of the application's bundle, if present.
652     ///
653     /// This is ignored on platforms besides macOS.
654     CocoaChdirResources(bool),
655     /// Specifies whether to create a basic menu bar, either from a nib or manually, when the first
656     /// window is created, which is when AppKit is initialized.
657     ///
658     /// This is ignored on platforms besides macOS.
659     CocoaMenubar(bool),
660 }
661 
662 /// Sets hints for the next initialization of GLFW.
663 ///
664 /// The values you set hints to are never reset by GLFW, but they only take effect during
665 /// initialization. Once GLFW has been initialized, any values you set will be ignored until the
666 /// library is terminated and initialized again.
667 ///
668 /// Wrapper for `glfwInitHint`.
init_hint(hint: InitHint)669 pub fn init_hint(hint: InitHint) {
670     match hint {
671         InitHint::JoystickHatButtons(joystick_hat_buttons) => unsafe { ffi::glfwInitHint(ffi::JOYSTICK_HAT_BUTTONS, joystick_hat_buttons as c_int) },
672         InitHint::CocoaChdirResources(chdir) => unsafe { ffi::glfwInitHint(ffi::COCOA_CHDIR_RESOURCES, chdir as c_int) },
673         InitHint::CocoaMenubar(menubar) => unsafe { ffi::glfwInitHint(ffi::COCOA_MENUBAR, menubar as c_int) },
674     }
675 }
676 
677 /// Initializes the GLFW library. This must be called on the main platform
678 /// thread.
679 ///
680 /// Wrapper for `glfwInit`.
681 ///
682 /// # Error callback
683 ///
684 /// An error callback can be set if desired. This allows for the handling of any
685 /// errors that occur during initialization. This can subsequently be changed
686 /// using the `Glfw::set_error_callback` function.
687 ///
688 /// # Example
689 ///
690 /// ~~~no_run
691 /// extern crate glfw;
692 ///
693 /// fn main() {
694 ///    let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
695 /// }
696 /// ~~~
697 ///
698 /// # Returns
699 ///
700 /// - If initialization was successful a `Glfw` token will be returned along
701 ///   with a `Receiver` from which errors can be intercepted.
702 /// - Subsequent calls to `init` will return `Glfw` token immediately.
703 /// - If an initialization error occurred within the GLFW library
704 ///   `Err(InternalInitError)` will be returned.
init<UserData: 'static>( mut callback: Option<ErrorCallback<UserData>>, ) -> Result<Glfw, InitError>705 pub fn init<UserData: 'static>(
706     mut callback: Option<ErrorCallback<UserData>>,
707 ) -> Result<Glfw, InitError> {
708     // Initialize the error callback if it was supplied. This is done
709     // before `ffi::glfwInit` because errors could occur during
710     // initialization.
711     match callback.take() {
712         Some(f) => callbacks::error::set(f),
713         None => callbacks::error::unset(),
714     }
715     // initialize GLFW.
716     // FYI: multiple not terminated ffi::glfwInit() returns ffi::TRUE immediately.
717     // https://www.glfw.org/docs/latest/group__init.html#ga317aac130a235ab08c6db0834907d85e
718     if unsafe { ffi::glfwInit() } == ffi::TRUE {
719         REF_COUNT_FOR_GLFW.fetch_add(1, Ordering::SeqCst);
720         Ok(Glfw)
721     } else {
722         Err(InitError::Internal)
723     }
724 }
725 
726 impl Glfw {
727     /// Sets the error callback, overwriting the previous one stored.
728     ///
729     /// # Example
730     ///
731     /// ~~~ignore
732     /// use std::cell::Cell;
733     ///
734     /// fn error_callback(_: glfw::Error, description: String, error_count: &Cell<usize>) {
735     ///     println!("GLFW error {}: {}", error_count.get(), description);
736     ///     error_count.set(error_count.get() + 1);
737     /// }
738     ///
739     /// // sets a new callback
740     /// glfw.set_error_callback(Some(
741     ///     glfw::Callback {
742     ///         f: error_callback,
743     ///         data: Cell::new(0),
744     ///     }
745     /// ));
746     ///
747     /// // removes the previously set callback
748     /// glfw.set_error_callback(None);
749     /// ~~~
750     ///
751     /// The `FAIL_ON_ERRORS` and `LOG_ERRORS` callbacks are provided for
752     /// convenience. For example:
753     ///
754     /// ~~~ignore
755     /// // triggers a task failure when a GLFW error is encountered.
756     /// glfw.set_error_callback(glfw::FAIL_ON_ERRORS);
757     /// ~~~
set_error_callback<UserData: 'static>(&mut self, callback: Option<ErrorCallback<UserData>>)758     pub fn set_error_callback<UserData: 'static>(&mut self, callback: Option<ErrorCallback<UserData>>) {
759         match callback {
760             Some(f) => callbacks::error::set(f),
761             None    => callbacks::error::unset(),
762         }
763     }
764 
765     /// Sets the monitor callback, overwriting the previous one stored.
set_monitor_callback<UserData: 'static>(&mut self, callback: Option<MonitorCallback<UserData>>)766     pub fn set_monitor_callback<UserData: 'static>(&mut self, callback: Option<MonitorCallback<UserData>>) {
767         match callback {
768             Some(f) => callbacks::monitor::set(f),
769             None    => callbacks::monitor::unset(),
770         }
771     }
772 
773     /// Sets the joystick callback, overwriting the previous one stored
set_joystick_callback<UserData: 'static>(&mut self, callback: Option<JoystickCallback<UserData>>)774     pub fn set_joystick_callback<UserData: 'static>(&mut self, callback: Option<JoystickCallback<UserData>>) {
775         match callback {
776             Some(f) => callbacks::joystick::set(f),
777             None    => callbacks::joystick::unset(),
778         }
779     }
780 
781     /// Supplies the primary monitor to the closure provided, if it exists.
782     /// This is usually the monitor where elements like the Windows task bar or
783     /// the OS X menu bar is located.
784     ///
785     /// # Example
786     ///
787     /// ~~~ignore
788     /// let (window, events) = glfw.with_primary_monitor(|_, m| {
789     ///     glfw.create_window(300, 300, "Hello this is window",
790     ///         m.map_or(glfw::WindowMode::Windowed, |m| glfw::FullScreen(m)))
791     /// }).expect("Failed to create GLFW window.");
792     /// ~~~
with_primary_monitor<T, F>(&mut self, f: F) -> T where F: Fn(&mut Self, Option<&Monitor>) -> T793     pub fn with_primary_monitor<T, F>(&mut self, f: F) -> T where F: Fn(&mut Self, Option<&Monitor>) -> T {
794         match unsafe { ffi::glfwGetPrimaryMonitor() } {
795             ptr if ptr.is_null() => f(self, None),
796             ptr => f(self, Some(&Monitor {
797                 ptr: ptr
798             })),
799         }
800     }
801 
802     /// Supplies the primary monitor to the closure provided, if it exists.
803     /// This is usually the monitor where elements like the Windows task bar or
804     /// the OS X menu bar is located.
805     ///
806     /// Variant that can accept an `FnMut` closure.
807     ///
808     /// # Example
809     ///
810     /// ~~~ignore
811     /// glfw.with_primary_monitor(|_: &mut _, m: Option<&glfw::Monitor>| {
812     ///     let monitor = m.unwrap();
813     ///
814     ///     let mode: glfw::VidMode = monitor.get_video_mode().unwrap();
815     ///
816     ///     // Modifying `window` requires `FnMut`
817     ///     window.set_monitor(glfw::WindowMode::FullScreen(&monitor), 0, 0, mode.width, mode.height, Some(mode.refresh_rate));
818     /// });
819     /// ~~~
with_primary_monitor_mut<T, F>(&mut self, mut f: F) -> T where F: FnMut(&mut Self, Option<&Monitor>) -> T820     pub fn with_primary_monitor_mut<T, F>(&mut self, mut f: F) -> T where F: FnMut(&mut Self, Option<&Monitor>) -> T {
821         match unsafe { ffi::glfwGetPrimaryMonitor() } {
822             ptr if ptr.is_null() => f(self, None),
823             ptr => f(self, Some(&Monitor {
824                 ptr: ptr
825             })),
826         }
827     }
828 
829     /// Supplies a vector of the currently connected monitors to the closure
830     /// provided.
831     ///
832     /// # Example
833     ///
834     /// ~~~ignore
835     /// glfw.with_connected_monitors(|_, monitors| {
836     ///     for monitor in monitors.iter() {
837     ///         println!("{}: {}", monitor.get_name(), monitor.get_video_mode());
838     ///     }
839     /// });
840     /// ~~~
with_connected_monitors<T, F>(&mut self, f: F) -> T where F: Fn(&mut Self, &[Monitor]) -> T841     pub fn with_connected_monitors<T, F>(&mut self, f: F) -> T where F: Fn(&mut Self, &[Monitor]) -> T {
842         unsafe {
843             let mut count = 0;
844             let ptr = ffi::glfwGetMonitors(&mut count);
845             f(self,
846               &slice::from_raw_parts(ptr as *const _, count as usize).iter().map(|&ptr| {
847                 Monitor {
848                     ptr: ptr
849                 }
850             }).collect::<Vec<Monitor>>())
851         }
852     }
853 
854     /// Supplies a vector of the currently connected monitors to the closure
855     /// provided.
856     ///
857     /// Variant that can accept an `FnMut` closure.
858     ///
859     /// # Example
860     ///
861     /// ~~~ignore
862     /// glfw.with_connected_monitors(|_, monitors| {
863     ///     for monitor in monitors.iter() {
864     ///         println!("{}: {}", monitor.get_name(), monitor.get_video_mode());
865     ///     }
866     /// });
867     /// ~~~
with_connected_monitors_mut<T, F>(&mut self, mut f: F) -> T where F: FnMut(&mut Self, &[Monitor]) -> T868     pub fn with_connected_monitors_mut<T, F>(&mut self, mut f: F) -> T where F: FnMut(&mut Self, &[Monitor]) -> T {
869         unsafe {
870             let mut count = 0;
871             let ptr = ffi::glfwGetMonitors(&mut count);
872             f(self,
873               &slice::from_raw_parts(ptr as *const _, count as usize).iter().map(|&ptr| {
874                   Monitor {
875                       ptr: ptr
876                   }
877               }).collect::<Vec<Monitor>>())
878         }
879     }
880 
881     /// Queries Vulkan support via `glfwVulkanSupported`
882     #[cfg(feature = "vulkan")]
vulkan_supported(&self) -> bool883     pub fn vulkan_supported(&self) -> bool {
884         unsafe { ffi::glfwVulkanSupported() == ffi::TRUE }
885     }
886 
887     /// This is used to set the window hints for the next call to
888     /// `Glfw::create_window`. The hints can be reset to their default values
889     /// using calling the `Glfw::default_window_hints` function.
890     ///
891     /// Wrapper for `glfwWindowHint`
892     ///
893     /// # OpenGL 3.x and 4.x on Mac OS X
894     ///
895     /// The only OpenGL 3.x and 4.x contexts supported by OS X are
896     /// forward-compatible, core profile contexts.
897     ///
898     /// 10.7 and 10.8 support the following OpenGL versions:
899     ///
900     /// - `glfw::WindowHint::ContextVersion(3, 2)`
901     ///
902     /// 10.9 supports the following OpenGL versions
903     ///
904     /// - `glfw::WindowHint::ContextVersion(3, 2)`
905     /// - `glfw::WindowHint::ContextVersion(3, 3)`
906     /// - `glfw::WindowHint::ContextVersion(4, 1)`
907     ///
908     /// To create an OS X compatible context, the hints should be specified as
909     /// follows:
910     ///
911     /// ~~~ignore
912     /// glfw.window_hint(glfw::WindowHint::ContextVersion(3, 2));
913     /// glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
914     /// glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
915     /// ~~~
window_hint(&mut self, hint: WindowHint)916     pub fn window_hint(&mut self, hint: WindowHint) {
917         //This is just a simple function to unwrap the option and convert it to `c_int` or use `GLFW_DONT_CARE`,
918         //then call `glfwWindowHint` with the result. It was required because `GLFW_DONT_CARE` is signed,
919         //so `value.unwrap_or(ffi::DONT_CARE)` wouldn't work because of the type difference.
920         #[inline(always)]
921         unsafe fn dont_care_hint(hint: c_int, value: Option<u32>) {
922             ffi::glfwWindowHint(hint, match value {
923                 Some(v) => v as c_int,
924                 None => ffi::DONT_CARE
925             })
926         }
927 
928         #[inline(always)]
929         unsafe fn string_hint(hint: c_int, value: Option<String>) {
930             let value = if let Some(value) = &value {
931                 value.as_str()
932             } else {
933                 ""
934             };
935             with_c_str(value, |value| {
936                 ffi::glfwWindowHintString(hint, value)
937             })
938         }
939 
940         match hint {
941             WindowHint::RedBits(bits)                    => unsafe { dont_care_hint(ffi::RED_BITS,                      bits) },
942             WindowHint::GreenBits(bits)                  => unsafe { dont_care_hint(ffi::GREEN_BITS,                    bits) },
943             WindowHint::BlueBits(bits)                   => unsafe { dont_care_hint(ffi::BLUE_BITS,                     bits) },
944             WindowHint::AlphaBits(bits)                  => unsafe { dont_care_hint(ffi::ALPHA_BITS,                    bits) },
945             WindowHint::DepthBits(bits)                  => unsafe { dont_care_hint(ffi::DEPTH_BITS,                    bits) },
946             WindowHint::StencilBits(bits)                => unsafe { dont_care_hint(ffi::STENCIL_BITS,                  bits) },
947             WindowHint::AccumRedBits(bits)               => unsafe { dont_care_hint(ffi::ACCUM_RED_BITS,                bits) },
948             WindowHint::AccumGreenBits(bits)             => unsafe { dont_care_hint(ffi::ACCUM_GREEN_BITS,              bits) },
949             WindowHint::AccumBlueBits(bits)              => unsafe { dont_care_hint(ffi::ACCUM_BLUE_BITS,               bits) },
950             WindowHint::AccumAlphaBits(bits)             => unsafe { dont_care_hint(ffi::ACCUM_ALPHA_BITS,              bits) },
951             WindowHint::AuxBuffers(num_buffers)          => unsafe { dont_care_hint(ffi::AUX_BUFFERS,                   num_buffers) },
952             WindowHint::Samples(num_samples)             => unsafe { dont_care_hint(ffi::SAMPLES,                       num_samples) },
953             WindowHint::RefreshRate(rate)                => unsafe { dont_care_hint(ffi::REFRESH_RATE,                  rate) },
954             WindowHint::Stereo(is_stereo)                => unsafe { ffi::glfwWindowHint(ffi::STEREO,                   is_stereo as c_int) },
955             WindowHint::SRgbCapable(is_capable)          => unsafe { ffi::glfwWindowHint(ffi::SRGB_CAPABLE,             is_capable as c_int) },
956             WindowHint::ClientApi(api)                   => unsafe { ffi::glfwWindowHint(ffi::CLIENT_API,               api as c_int) },
957             WindowHint::ContextVersionMajor(major)       => unsafe { ffi::glfwWindowHint(ffi::CONTEXT_VERSION_MAJOR,    major as c_int) },
958             WindowHint::ContextVersionMinor(minor)       => unsafe { ffi::glfwWindowHint(ffi::CONTEXT_VERSION_MINOR,    minor as c_int) },
959             WindowHint::ContextVersion(major, minor)     => unsafe {
960                 ffi::glfwWindowHint(ffi::CONTEXT_VERSION_MAJOR, major as c_int);
961                 ffi::glfwWindowHint(ffi::CONTEXT_VERSION_MINOR, minor as c_int)
962             },
963             WindowHint::ContextRobustness(robustness)    => unsafe { ffi::glfwWindowHint(ffi::CONTEXT_ROBUSTNESS,       robustness as c_int) },
964             WindowHint::OpenGlForwardCompat(is_compat)   => unsafe { ffi::glfwWindowHint(ffi::OPENGL_FORWARD_COMPAT,    is_compat as c_int) },
965             WindowHint::OpenGlDebugContext(is_debug)     => unsafe { ffi::glfwWindowHint(ffi::OPENGL_DEBUG_CONTEXT,     is_debug as c_int) },
966             WindowHint::OpenGlProfile(profile)           => unsafe { ffi::glfwWindowHint(ffi::OPENGL_PROFILE,           profile as c_int) },
967             WindowHint::Resizable(is_resizable)          => unsafe { ffi::glfwWindowHint(ffi::RESIZABLE,                is_resizable as c_int) },
968             WindowHint::Visible(is_visible)              => unsafe { ffi::glfwWindowHint(ffi::VISIBLE,                  is_visible as c_int) },
969             WindowHint::Decorated(is_decorated)          => unsafe { ffi::glfwWindowHint(ffi::DECORATED,                is_decorated as c_int) },
970             WindowHint::AutoIconify(auto_iconify)        => unsafe { ffi::glfwWindowHint(ffi::AUTO_ICONIFY,             auto_iconify as c_int) },
971             WindowHint::Floating(is_floating)            => unsafe { ffi::glfwWindowHint(ffi::FLOATING,                 is_floating as c_int) },
972             WindowHint::Focused(is_focused)              => unsafe { ffi::glfwWindowHint(ffi::FOCUSED,                  is_focused as c_int) },
973             WindowHint::ContextNoError(is_no_error)      => unsafe { ffi::glfwWindowHint(ffi::CONTEXT_NO_ERROR,         is_no_error as c_int) },
974             WindowHint::ContextCreationApi(api)          => unsafe { ffi::glfwWindowHint(ffi::CONTEXT_CREATION_API,     api as c_int) },
975             WindowHint::ContextReleaseBehavior(behavior) => unsafe { ffi::glfwWindowHint(ffi::CONTEXT_RELEASE_BEHAVIOR, behavior as c_int) },
976             WindowHint::DoubleBuffer(is_dbuffered)       => unsafe { ffi::glfwWindowHint(ffi::DOUBLEBUFFER,             is_dbuffered as c_int) },
977             WindowHint::CenterCursor(center_cursor) => unsafe { ffi::glfwWindowHint(ffi::CENTER_CURSOR, center_cursor as c_int) },
978             WindowHint::TransparentFramebuffer(is_transparent) => unsafe { ffi::glfwWindowHint(ffi::TRANSPARENT_FRAMEBUFFER, is_transparent as c_int) },
979             WindowHint::FocusOnShow(focus) => unsafe { ffi::glfwWindowHint(ffi::FOCUS_ON_SHOW, focus as c_int) },
980             WindowHint::ScaleToMonitor(scale) => unsafe { ffi::glfwWindowHint(ffi::SCALE_TO_MONITOR, scale as c_int) },
981             WindowHint::CocoaRetinaFramebuffer(retina_fb) => unsafe { ffi::glfwWindowHint(ffi::COCOA_RETINA_FRAMEBUFFER, retina_fb as c_int) },
982             WindowHint::CocoaFrameName(name) => unsafe { string_hint(ffi::COCOA_FRAME_NAME, name) }
983             WindowHint::CocoaGraphicsSwitching(graphics_switching) => unsafe { ffi::glfwWindowHint(ffi::COCOA_GRAPHICS_SWITCHING, graphics_switching as c_int) },
984             WindowHint::X11ClassName(class_name) => unsafe { string_hint(ffi::X11_CLASS_NAME, class_name) },
985             WindowHint::X11InstanceName(instance_name) => unsafe { string_hint(ffi::X11_INSTANCE_NAME, instance_name) },
986         }
987     }
988 
989     /// Resets the window hints previously set by the `window_hint` function to
990     /// their default values.
991     ///
992     /// Wrapper for `glfwDefaultWindowHints`.
default_window_hints(&mut self)993     pub fn default_window_hints(&mut self) {
994         unsafe { ffi::glfwDefaultWindowHints(); }
995     }
996 
997     /// Creates a new window.
998     ///
999     /// Wrapper for `glfwCreateWindow`.
create_window(&self, width: u32, height: u32, title: &str, mode: WindowMode) -> Option<(Window, Receiver<(f64, WindowEvent)>)>1000     pub fn create_window(&self, width: u32, height: u32, title: &str, mode: WindowMode) -> Option<(Window, Receiver<(f64, WindowEvent)>)> {
1001         self.create_window_intern(width, height, title, mode, None)
1002     }
1003 
1004     /// Internal wrapper for `glfwCreateWindow`.
create_window_intern(&self, width: u32, height: u32, title: &str, mode: WindowMode, share: Option<&Window>) -> Option<(Window, Receiver<(f64, WindowEvent)>)>1005     fn create_window_intern(&self, width: u32, height: u32, title: &str, mode: WindowMode, share: Option<&Window>) -> Option<(Window, Receiver<(f64, WindowEvent)>)> {
1006         let ptr = unsafe {
1007             with_c_str(title, |title| {
1008                 ffi::glfwCreateWindow(
1009                     width as c_int,
1010                     height as c_int,
1011                     title,
1012                     mode.to_ptr(),
1013                     match share { Some(w) => w.ptr, None => ptr::null_mut() }
1014                 )
1015             })
1016         };
1017         if ptr.is_null() {
1018             None
1019         } else {
1020             let (drop_sender, drop_receiver) = channel();
1021             let (sender, receiver) = channel();
1022             unsafe { ffi::glfwSetWindowUserPointer(ptr, mem::transmute(Box::new(sender))); }
1023             Some((
1024                 Window {
1025                     ptr: ptr,
1026                     glfw: self.clone(),
1027                     is_shared: share.is_some(),
1028                     drop_sender: Some(drop_sender),
1029                     drop_receiver: drop_receiver,
1030                     current_cursor: None
1031                 },
1032                 receiver,
1033             ))
1034         }
1035     }
1036 
1037     /// Makes the context of the specified window current. If no window is given
1038     /// then the current context is detached.
1039     ///
1040     /// Wrapper for `glfwMakeContextCurrent`.
make_context_current(&mut self, context: Option<&Window>)1041     pub fn make_context_current(&mut self, context: Option<&Window>) {
1042         match context {
1043             Some(window) => unsafe { ffi::glfwMakeContextCurrent(window.ptr) },
1044             None         => unsafe { ffi::glfwMakeContextCurrent(ptr::null_mut()) },
1045         }
1046     }
1047 
1048     /// Wrapper for `glfwGetX11Display`
1049     #[cfg(target_os="linux")]
get_x11_display(&self) -> *mut c_void1050     pub fn get_x11_display(&self) -> *mut c_void {
1051         unsafe { ffi::glfwGetX11Display() }
1052     }
1053 
1054     /// Immediately process the received events.
1055     ///
1056     /// Wrapper for `glfwPollEvents`.
poll_events(&mut self)1057     pub fn poll_events(&mut self) {
1058         unsafe { ffi::glfwPollEvents(); }
1059     }
1060 
1061     /// Immediately process the received events. The *unbuffered* variant differs by allowing
1062     /// inspection of events *prior* to their associated native callback returning. This also
1063     /// provides a way to synchronously respond to the event. Events returned by the closure
1064     /// are delivered to the channel receiver just as if `poll_events` was called. Returning
1065     /// `None` from the closure will drop the event.
1066     ///
1067     /// Wrapper for `glfwPollEvents`.
poll_events_unbuffered<F>(&mut self, mut f: F) where F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>1068     pub fn poll_events_unbuffered<F>(&mut self, mut f: F)
1069         where
1070             F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>
1071     {
1072         let _unset_handler_guard = unsafe {
1073             crate::callbacks::unbuffered::set_handler(&mut f)
1074         };
1075         self.poll_events();
1076     }
1077 
1078     /// Sleep until at least one event has been received, and then perform the
1079     /// equivalent of `Glfw::poll_events`.
1080     ///
1081     /// Wrapper for `glfwWaitEvents`.
wait_events(&mut self)1082     pub fn wait_events(&mut self) {
1083         unsafe { ffi::glfwWaitEvents(); }
1084     }
1085 
1086     /// Sleep until at least one event has been received, and then perform the
1087     /// equivalent of `Glfw::poll_events_unbuffered`.
1088     ///
1089     /// Wrapper for `glfwWaitEvents`.
wait_events_unbuffered<F>(&mut self, mut f: F) where F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>1090     pub fn wait_events_unbuffered<F>(&mut self, mut f: F)
1091         where
1092             F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>
1093     {
1094         let _unset_handler_guard = unsafe {
1095             crate::callbacks::unbuffered::set_handler(&mut f)
1096         };
1097         self.wait_events();
1098     }
1099 
1100     /// Sleep until at least one event has been received, or until the specified
1101     /// timeout is reached, and then perform the equivalent of `Glfw::poll_events`.
1102     /// Timeout is specified in seconds.
1103     ///
1104     /// Wrapper for `glfwWaitEventsTimeout`.
wait_events_timeout(&mut self, timeout: f64)1105     pub fn wait_events_timeout(&mut self, timeout: f64) {
1106         unsafe { ffi::glfwWaitEventsTimeout(timeout); }
1107     }
1108 
1109     /// Sleep until at least one event has been received, or until the specified
1110     /// timeout is reached, and then perform the equivalent of `Glfw::poll_events_unbuffered`.
1111     /// Timeout is specified in seconds.
1112     ///
1113     /// Wrapper for `glfwWaitEventsTimeout`.
wait_events_timeout_unbuffered<F>(&mut self, timeout: f64, mut f: F) where F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>1114     pub fn wait_events_timeout_unbuffered<F>(&mut self, timeout: f64, mut f: F)
1115         where
1116             F: FnMut(WindowId, (f64, WindowEvent)) -> Option<(f64, WindowEvent)>
1117     {
1118         let _unset_handler_guard = unsafe {
1119             crate::callbacks::unbuffered::set_handler(&mut f)
1120         };
1121         self.wait_events_timeout(timeout);
1122     }
1123 
1124     /// Posts an empty event from the current thread to the event queue, causing
1125     /// `wait_events` or `wait_events_timeout` to return.
1126     /// If no windows exist, this function returns immediately.
1127     ///
1128     /// Wrapper for `glfwPostEmptyEvent`.
post_empty_event(&mut self)1129     pub fn post_empty_event(&mut self) {
1130         unsafe { ffi::glfwPostEmptyEvent(); }
1131     }
1132 
1133     /// Returns the current value of the GLFW timer. Unless the timer has been
1134     /// set using `glfw::set_time`, the timer measures time elapsed since GLFW
1135     /// was initialized.
1136     ///
1137     /// Wrapper for `glfwGetTime`.
get_time(&self) -> f641138     pub fn get_time(&self) -> f64 {
1139         unsafe { ffi::glfwGetTime() as f64 }
1140     }
1141 
1142     /// Sets the value of the GLFW timer.
1143     ///
1144     /// Wrapper for `glfwSetTime`.
set_time(&mut self, time: f64)1145     pub fn set_time(&mut self, time: f64) {
1146         unsafe { ffi::glfwSetTime(time as c_double); }
1147     }
1148 
1149     /// Wrapper for `glfwGetTimerValue`.
get_timer_value() -> u641150     pub fn get_timer_value() -> u64 {
1151         unsafe { ffi::glfwGetTimerValue() as u64 }
1152     }
1153 
1154     /// Wrapper for `glfwGetTimerFrequency`
get_timer_frequency() -> u641155     pub fn get_timer_frequency() -> u64 {
1156         unsafe { ffi::glfwGetTimerFrequency() as u64 }
1157     }
1158 
1159     /// Sets the number of screen updates to wait before swapping the buffers of
1160     /// the current context and returning from `Window::swap_buffers`.
1161     ///
1162     /// Wrapper for `glfwSwapInterval`.
set_swap_interval(&mut self, interval: SwapInterval)1163     pub fn set_swap_interval(&mut self, interval: SwapInterval) {
1164         unsafe {
1165             ffi::glfwSwapInterval(match interval {
1166                 SwapInterval::None           =>  0       as c_int,
1167                 SwapInterval::Adaptive       => -1       as c_int,
1168                 SwapInterval::Sync(interval) => interval as c_int
1169             })
1170         }
1171     }
1172 
1173     /// Returns `true` if the specified OpenGL or context creation API extension
1174     /// is supported by the current context.
1175     ///
1176     /// Wrapper for `glfwExtensionSupported`.
extension_supported(&self, extension: &str) -> bool1177     pub fn extension_supported(&self, extension: &str) -> bool {
1178         unsafe {
1179             with_c_str(extension, |extension| {
1180                 ffi::glfwExtensionSupported(extension) == ffi::TRUE
1181             })
1182         }
1183     }
1184 
1185     /// Wrapper for `glfwGetRequiredInstanceExtensions`
1186     ///
1187     /// This function returns a Vector of names of Vulkan instance extensions
1188     /// required by GLFW for creating Vulkan surfaces for GLFW windows. If successful,
1189     /// the list will always contains `VK_KHR_surface`, so if you don't require any
1190     /// additional extensions you can pass this list directly to the `VkInstanceCreateInfo` struct.
1191     ///
1192     /// Will return `None` if the API is unavailable.
1193     #[cfg(feature = "vulkan")]
get_required_instance_extensions(&self) -> Option<Vec<String>>1194     pub fn get_required_instance_extensions(&self) -> Option<Vec<String>> {
1195         let mut len: c_uint = 0;
1196 
1197         unsafe {
1198             let raw_extensions: *const *const c_char = ffi::glfwGetRequiredInstanceExtensions(&mut len as *mut c_uint);
1199 
1200             if !raw_extensions.is_null() {
1201                 return Some(slice::from_raw_parts(raw_extensions, len as usize)
1202                     .iter()
1203                     .map(|extensions| string_from_c_str(*extensions))
1204                     .collect());
1205             }
1206         }
1207 
1208         None
1209     }
1210 
1211     /// Returns the address of the specified client API or extension function if
1212     /// it is supported by the current context, NULL otherwise.
1213     ///
1214     /// Wrapper for `glfwGetProcAddress`.
get_proc_address_raw(&self, procname: &str) -> GLProc1215     pub fn get_proc_address_raw(&self, procname: &str) -> GLProc {
1216         debug_assert!(unsafe { ffi::glfwGetCurrentContext() } != std::ptr::null_mut());
1217         with_c_str(procname, |procname| {
1218             unsafe { ffi::glfwGetProcAddress(procname) }
1219         })
1220     }
1221 
1222     /// This function returns the address of the specified Vulkan core or extension function
1223     /// for the specified instance. If instance is set to NULL it can return any function
1224     /// exported from the Vulkan loader, including at least the following functions:
1225     ///
1226     /// * `vkEnumerateInstanceExtensionProperties`
1227     /// * `vkEnumerateInstanceLayerProperties`
1228     /// * `vkCreateInstance`
1229     /// * `vkGetInstanceProcAddr`
1230     ///
1231     /// If Vulkan is not available on the machine, this function returns `NULL`
1232     ///
1233     /// Wrapper for `glfwGetInstanceProcAddress`
1234     #[cfg(feature = "vulkan")]
get_instance_proc_address_raw(&self, instance: VkInstance, procname: &str) -> VkProc1235     pub fn get_instance_proc_address_raw(&self, instance: VkInstance, procname: &str) -> VkProc {
1236         with_c_str(procname, |procname| {
1237             unsafe { ffi::glfwGetInstanceProcAddress(instance, procname) }
1238         })
1239     }
1240 
1241     /// This function returns whether the specified queue family of the specified
1242     /// physical device supports presentation to the platform GLFW was built for.
1243     ///
1244     /// Wrapper for `glfwGetPhysicalDevicePresentationSupport`
1245     #[cfg(feature = "vulkan")]
get_physical_device_presentation_support_raw(&self, instance: VkInstance, device: VkPhysicalDevice, queue_family: u32) -> bool1246     pub fn get_physical_device_presentation_support_raw(&self, instance: VkInstance, device: VkPhysicalDevice, queue_family: u32) -> bool {
1247         vk::TRUE == unsafe { ffi::glfwGetPhysicalDevicePresentationSupport(instance, device, queue_family as c_uint) as u32 }
1248     }
1249 
1250     /// Constructs a `Joystick` handle corresponding to the supplied `JoystickId`.
get_joystick(&self, id: JoystickId) -> Joystick1251     pub fn get_joystick(&self, id: JoystickId) -> Joystick {
1252         Joystick { id: id, glfw: self.clone() }
1253     }
1254 
1255     /// Wrapper for `glfwRawMouseMotionSupported`.
supports_raw_motion(&self) -> bool1256     pub fn supports_raw_motion(&self) -> bool {
1257         unsafe { ffi::glfwRawMouseMotionSupported() == ffi::TRUE }
1258     }
1259 
1260     /// Parses the specified ASCII encoded string and updates the internal list with any gamepad
1261     /// mappings it finds. This string may contain either a single gamepad mapping or many mappings
1262     /// separated by newlines. The parser supports the full format of the `gamecontrollerdb.txt`
1263     /// source file including empty lines and comments.
1264     ///
1265     /// Wrapper for `glfwUpdateGamepadMappings`.
1266     ///
1267     /// # Returns
1268     ///
1269     /// `true` if successful, or `false` if an error occured.
update_gamepad_mappings(&self, mappings: &str) -> bool1270     pub fn update_gamepad_mappings(&self, mappings: &str) -> bool {
1271         unsafe {
1272             let c_str = CString::new(mappings.as_bytes());
1273             let ptr = c_str.unwrap().as_bytes_with_nul().as_ptr() as *const c_char;
1274             ffi::glfwUpdateGamepadMappings(ptr) == ffi::TRUE
1275         }
1276     }
1277 }
1278 
1279 impl Clone for Glfw {
clone(&self) -> Self1280     fn clone(&self) -> Self {
1281         REF_COUNT_FOR_GLFW.fetch_add(1, Ordering::SeqCst);
1282         Glfw
1283     }
1284 }
1285 
1286 impl Drop for Glfw {
drop(&mut self)1287     fn drop(&mut self) {
1288         let old_diff = REF_COUNT_FOR_GLFW.fetch_sub(1, Ordering::SeqCst);
1289         if old_diff == 1 {
1290             unsafe { ffi::glfwTerminate(); }
1291         }
1292     }
1293 }
1294 
1295 /// Wrapper for `glfwGetVersion`.
get_version() -> Version1296 pub fn get_version() -> Version {
1297     unsafe {
1298         let mut major = 0;
1299         let mut minor = 0;
1300         let mut patch = 0;
1301         ffi::glfwGetVersion(&mut major, &mut minor, &mut patch);
1302         Version {
1303             major: major as u64,
1304             minor: minor as u64,
1305             patch: patch as u64,
1306             pre:   Vec::new(),
1307             build: Vec::new(),
1308         }
1309     }
1310 }
1311 
1312 /// Replacement for `String::from_raw_buf`
string_from_c_str(c_str: *const c_char) -> String1313 pub unsafe fn string_from_c_str(c_str: *const c_char) -> String {
1314     String::from_utf8_lossy(CStr::from_ptr(c_str).to_bytes()).into_owned()
1315 }
1316 
1317 /// Like `string_from_c_str`, but handles null pointers correctly
string_from_nullable_c_str(c_str: *const c_char) -> Option<String>1318 pub unsafe fn string_from_nullable_c_str(c_str: *const c_char) -> Option<String> {
1319     if c_str.is_null() {
1320         None
1321     } else {
1322         Some(string_from_c_str(c_str))
1323     }
1324 }
1325 
1326 /// Replacement for `ToCStr::with_c_str`
with_c_str<F, T>(s: &str, f: F) -> T where F: FnOnce(*const c_char) -> T1327 pub fn with_c_str<F, T>(s: &str, f: F) -> T where F: FnOnce(*const c_char) -> T {
1328     let c_str = CString::new(s.as_bytes());
1329     f(c_str.unwrap().as_bytes_with_nul().as_ptr() as *const _)
1330 }
1331 
1332 /// Wrapper for `glfwGetVersionString`.
get_version_string() -> String1333 pub fn get_version_string() -> String {
1334     unsafe { string_from_c_str(ffi::glfwGetVersionString()) }
1335 }
1336 
1337 /// An monitor callback. This can be supplied with some user data to be passed
1338 /// to the callback function when it is triggered.
1339 pub type MonitorCallback<UserData> = Callback<fn(Monitor, MonitorEvent, &UserData), UserData>;
1340 
1341 /// A struct that wraps a `*GLFWmonitor` handle.
1342 #[allow(missing_copy_implementations)]
1343 pub struct Monitor {
1344     ptr: *mut ffi::GLFWmonitor
1345 }
1346 
1347 impl std::fmt::Debug for Monitor {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result1348     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1349         write!(f, "Monitor({:p})", self.ptr)
1350     }
1351 }
1352 
1353 impl Monitor {
1354     /// Wrapper for `glfwGetMonitorPos`.
get_pos(&self) -> (i32, i32)1355     pub fn get_pos(&self) -> (i32, i32) {
1356         unsafe {
1357             let mut xpos = 0;
1358             let mut ypos = 0;
1359             ffi::glfwGetMonitorPos(self.ptr, &mut xpos, &mut ypos);
1360             (xpos as i32, ypos as i32)
1361         }
1362     }
1363 
1364     /// Wrapper for `glfwGetMonitorPhysicalSize`.
get_physical_size(&self) -> (i32, i32)1365     pub fn get_physical_size(&self) -> (i32, i32) {
1366         unsafe {
1367             let mut width = 0;
1368             let mut height = 0;
1369             ffi::glfwGetMonitorPhysicalSize(self.ptr, &mut width, &mut height);
1370             (width as i32, height as i32)
1371         }
1372     }
1373 
1374     /// Wrapper for `glfwGetMonitorName`.
get_name(&self) -> Option<String>1375     pub fn get_name(&self) -> Option<String> {
1376         unsafe { string_from_nullable_c_str(ffi::glfwGetMonitorName(self.ptr)) }
1377     }
1378 
1379     /// Wrapper for `glfwGetVideoModes`.
get_video_modes(&self) -> Vec<VidMode>1380     pub fn get_video_modes(&self) -> Vec<VidMode> {
1381         unsafe {
1382             let mut count = 0;
1383             let ptr = ffi::glfwGetVideoModes(self.ptr, &mut count);
1384             slice::from_raw_parts(ptr, count as usize).iter().map(VidMode::from_glfw_vid_mode).collect()
1385         }
1386     }
1387 
1388     /// Wrapper for `glfwGetVideoMode`.
get_video_mode(&self) -> Option<VidMode>1389     pub fn get_video_mode(&self) -> Option<VidMode> {
1390         unsafe {
1391             // TODO: Can be returned to as_ref + map as in previous commit when (if?) as_ref stabilizes.
1392             let ptr = ffi::glfwGetVideoMode(self.ptr);
1393             if ptr.is_null() {
1394                 None
1395             } else {
1396                 Some(VidMode::from_glfw_vid_mode(&*ptr))
1397             }
1398         }
1399     }
1400 
1401     /// Wrapper for `glfwSetGamma`.
set_gamma(&mut self, gamma: f32)1402     pub fn set_gamma(&mut self, gamma: f32) {
1403         unsafe { ffi::glfwSetGamma(self.ptr, gamma as c_float); }
1404     }
1405 
1406     /// Wrapper for `glfwGetGammaRamp`.
get_gamma_ramp(&self) -> GammaRamp1407     pub fn get_gamma_ramp(&self) -> GammaRamp {
1408         unsafe {
1409             let llramp = *ffi::glfwGetGammaRamp(self.ptr);
1410             GammaRamp {
1411                 red:    slice::from_raw_parts(llramp.red as *const c_ushort, llramp.size as usize)
1412                               .iter().map(|&x| x).collect(),
1413                 green:  slice::from_raw_parts(llramp.green as *const c_ushort, llramp.size as usize)
1414                               .iter().map(|&x| x).collect(),
1415                 blue:   slice::from_raw_parts(llramp.blue as *const c_ushort, llramp.size as usize)
1416                               .iter().map(|&x| x).collect(),
1417             }
1418         }
1419     }
1420 
1421     /// Wrapper for `glfwSetGammaRamp`.
set_gamma_ramp(&mut self, ramp: &mut GammaRamp)1422     pub fn set_gamma_ramp(&mut self, ramp: &mut GammaRamp) {
1423         unsafe {
1424             ffi::glfwSetGammaRamp(
1425                 self.ptr,
1426                 &ffi::GLFWgammaramp {
1427                     red:    ramp.red.as_mut_ptr(),
1428                     green:  ramp.green.as_mut_ptr(),
1429                     blue:   ramp.blue.as_mut_ptr(),
1430                     size:   ramp.red.len() as u32,
1431                 }
1432             );
1433         }
1434     }
1435 
1436     /// Wrapper for `glfwGetMonitorContentScale`.
get_content_scale(&self) -> (f32, f32)1437     pub fn get_content_scale(&self) -> (f32, f32) {
1438         unsafe {
1439             let mut xscale = 0.0_f32;
1440             let mut yscale = 0.0_f32;
1441             ffi::glfwGetMonitorContentScale(self.ptr, &mut xscale, &mut yscale);
1442             (xscale, yscale)
1443         }
1444     }
1445 
1446     /// Wrapper for `glfwGetMonitorWorkarea`.
get_workarea(&self) -> (i32, i32, i32, i32)1447     pub fn get_workarea(&self) -> (i32, i32, i32, i32) {
1448         unsafe {
1449             let mut xpos = 0;
1450             let mut ypos = 0;
1451             let mut width = 0;
1452             let mut height = 0;
1453             ffi::glfwGetMonitorWorkarea(self.ptr, &mut xpos, &mut ypos, &mut width, &mut height);
1454             (xpos, ypos, width, height)
1455         }
1456     }
1457 }
1458 
1459 /// Monitor events.
1460 #[repr(i32)]
1461 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
1462 pub enum MonitorEvent {
1463     Connected                   = ffi::CONNECTED,
1464     Disconnected                = ffi::DISCONNECTED,
1465 }
1466 
1467 impl VidMode {
from_glfw_vid_mode(mode: &ffi::GLFWvidmode) -> VidMode1468     fn from_glfw_vid_mode(mode: &ffi::GLFWvidmode) -> VidMode {
1469         VidMode {
1470             width:        mode.width as u32,
1471             height:       mode.height as u32,
1472             red_bits:     mode.redBits as u32,
1473             green_bits:   mode.greenBits as u32,
1474             blue_bits:    mode.blueBits as u32,
1475             refresh_rate: mode.refreshRate as u32,
1476         }
1477     }
1478 }
1479 
1480 impl fmt::Debug for VidMode {
1481     /// Returns a string representation of the video mode.
1482     ///
1483     /// # Returns
1484     ///
1485     /// A string in the form:
1486     ///
1487     /// ~~~ignore
1488     /// ~"[width] x [height], [total_bits] ([red_bits] [green_bits] [blue_bits]) [refresh_rate] Hz"
1489     /// ~~~
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1490     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1491         write!(f, "{} x {}, {} = {} + {} + {}, {} Hz",
1492             self.width, self.height,
1493             self.red_bits + self.green_bits + self.blue_bits,
1494             self.red_bits, self.green_bits, self.blue_bits,
1495             self.refresh_rate)
1496     }
1497 }
1498 
1499 /// Window hints that can be set using the `window_hint` function.
1500 #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
1501 pub enum WindowHint {
1502     /// Specifies the desired bit depth of the red component of the default framebuffer.
1503     RedBits(Option<u32>),
1504     /// Specifies the desired bit depth of the green component of the default framebuffer.
1505     GreenBits(Option<u32>),
1506     /// Specifies the desired bit depth of the blue component of the default framebuffer.
1507     BlueBits(Option<u32>),
1508     /// Specifies the desired bit depth of the alpha component of the default framebuffer.
1509     AlphaBits(Option<u32>),
1510     /// Specifies the desired bit depth of the depth component of the default framebuffer.
1511     DepthBits(Option<u32>),
1512     /// Specifies the desired bit depth of the stencil component of the default framebuffer.
1513     StencilBits(Option<u32>),
1514     /// Specifies the desired bit depth of the red component of the accumulation framebuffer.
1515     AccumRedBits(Option<u32>),
1516     /// Specifies the desired bit depth of the green component of the accumulation framebuffer.
1517     AccumGreenBits(Option<u32>),
1518     /// Specifies the desired bit depth of the blue component of the accumulation framebuffer.
1519     AccumBlueBits(Option<u32>),
1520     /// Specifies the desired bit depth of the alpha component of the accumulation framebuffer.
1521     AccumAlphaBits(Option<u32>),
1522     /// Specifies the desired number of auxiliary buffers.
1523     AuxBuffers(Option<u32>),
1524     /// Specifies whether to use stereoscopic rendering.
1525     Stereo(bool),
1526     /// Specifies the desired number of samples to use for multisampling. Zero
1527     /// disables multisampling.
1528     Samples(Option<u32>),
1529     /// Specifies whether the framebuffer should be sRGB capable.
1530     SRgbCapable(bool),
1531     /// Specifies the desired refresh rate for full screen windows. If set to `None`,
1532     /// the highest available refresh rate will be used.
1533     ///
1534     /// This hint is ignored for windowed mode windows.
1535     RefreshRate(Option<u32>),
1536     /// Specifies which `ClientApi` to create the context for.
1537     ClientApi(ClientApiHint),
1538     /// Specifies the major client API version that the created context must be
1539     /// compatible with.
1540     ///
1541     /// Window creation will fail if the resulting OpenGL version is less than
1542     /// the one requested.
1543     ContextVersionMajor(u32),
1544     /// Specifies the minor client API version that the created context must be
1545     /// compatible with.
1546     ///
1547     /// Window creation will fail if the resulting OpenGL version is less than
1548     /// the one requested.
1549     ContextVersionMinor(u32),
1550     /// Specifies the client API version that the created context must be
1551     /// compatible with. This is the same as successive calls to `window_hint`
1552     /// function with the `ContextVersionMajor` and `ContextVersionMinor` hints.
1553     ///
1554     /// Window creation will fail if the resulting OpenGL version is less than
1555     /// the one requested.
1556     ///
1557     /// If `ContextVersion(1, 0)` is requested, _most_ drivers will provide the
1558     /// highest available context.
1559     ContextVersion(u32, u32),
1560     /// Specifies the `ContextRobustness` strategy to be used.
1561     ContextRobustness(ContextRobustnessHint),
1562     /// Specifies whether the OpenGL context should be forward-compatible, i.e.
1563     /// one where all functionality deprecated in the requested version of
1564     /// OpenGL is removed. This may only be used if the requested OpenGL version
1565     /// is 3.0 or above.
1566     ///
1567     /// If another client API is requested, this hint is ignored.
1568     OpenGlForwardCompat(bool),
1569     /// Specifies whether to create a debug OpenGL context, which may have
1570     /// additional error and performance issue reporting functionality.
1571     ///
1572     /// If another client API is requested, this hint is ignored.
1573     OpenGlDebugContext(bool),
1574     /// Specifies which OpenGL profile to create the context for. If requesting
1575     /// an OpenGL version below 3.2, `OpenGlAnyProfile` must be used.
1576     ///
1577     /// If another client API is requested, this hint is ignored.
1578     OpenGlProfile(OpenGlProfileHint),
1579     /// Specifies whether the window will be resizable by the user. Even if this
1580     /// is set to `false`, the window can still be resized using the
1581     /// `Window::set_size` function.
1582     ///
1583     /// This hint is ignored for fullscreen windows.
1584     Resizable(bool),
1585     /// Specifies whether the window will be visible on creation.
1586     ///
1587     /// This hint is ignored for fullscreen windows.
1588     Visible(bool),
1589     /// Specifies whether the window will have platform-specific decorations
1590     /// such as a border, a close widget, etc.
1591     ///
1592     /// This hint is ignored for full screen windows.
1593     Decorated(bool),
1594     /// Specifies whether the (full screen) window will automatically iconify
1595     /// and restore the previous video mode on input focus loss.
1596     ///
1597     /// This hint is ignored for windowed mode windows.
1598     AutoIconify(bool),
1599     /// Specifies whether the window will be floating above other regular
1600     /// windows, also called topmost or always-on-top.
1601     ///
1602     /// This hint is ignored for full screen windows.
1603     Floating(bool),
1604     /// Specifies whether the windowed mode window will be given input focus when created.
1605     ///
1606     /// This hint is ignored for full screen and initially hidden windows.
1607     Focused(bool),
1608     /// Specifies whether the OpenGL or OpenGL ES contexts do not emit errors,
1609     /// allowing for better performance in some situations.
1610     ContextNoError(bool),
1611     /// Specifies which context creation API to use to create the context.
1612     ContextCreationApi(ContextCreationApi),
1613     /// Specifies the behavior of the OpenGL pipeline when a context is transferred between threads
1614     ContextReleaseBehavior(ContextReleaseBehavior),
1615     /// Specifies whether the framebuffer should be double buffered.
1616     ///
1617     /// You nearly always want to use double buffering.
1618     ///
1619     /// Note that setting this to false will make `swap_buffers` do nothing useful,
1620     /// and your scene will have to be displayed some other way.
1621     DoubleBuffer(bool),
1622     /// Speficies whether the cursor should be centered over newly created full screen windows.
1623     ///
1624     /// This hint is ignored for windowed mode windows.
1625     CenterCursor(bool),
1626     /// Specifies whether the window framebuffer will be transparent.
1627     ///
1628     /// If enabled and supported by the system, the window framebuffer alpha channel will be used to
1629     /// combine the framebuffer with the background. This does not affect window decorations.
1630     TransparentFramebuffer(bool),
1631     /// Specifies whether the window will be given input focus when `Window::show` is called.
1632     FocusOnShow(bool),
1633     /// Specifies whether the window content area should be resized based on the monitor current scale
1634     /// of any monitor it is placed on.
1635     ///
1636     /// This includes the initial placement when the window is created.
1637     ScaleToMonitor(bool),
1638     /// Specifies whether to use full resolution framebuffers on Retina displays.
1639     ///
1640     /// This is ignored on platforms besides macOS.
1641     CocoaRetinaFramebuffer(bool),
1642     /// Specifies the UTF-8 encoded name to use for autosaving the window frame, or if empty disables
1643     /// frame autosaving for the window.
1644     ///
1645     /// This is ignored on platforms besides macOS.
1646     CocoaFrameName(Option<String>),
1647     /// Specifies whether to in participate in Automatic Graphics Switching, i.e. to allow the system
1648     /// to choose the integrated GPU for the OpenGL context and move it between GPUs if necessary or
1649     /// whether to force it to always run on the discrete GPU.
1650     ///
1651     /// Simpler programs and tools may want to enable this to save power, while games and other
1652     /// applications performing advanced rendering will want to leave it disabled.
1653     //
1654     //  A bundled application that wishes to participate in Automatic Graphics Switching should also
1655     // declare this in its `Info.plist` by setting the `NSSupportsAutomaticGraphicsSwitching` key to
1656     // `true`.
1657     ///
1658     /// This only affects systems with both integrated and discrete GPUs. This is ignored on platforms
1659     /// besides macOS.
1660     CocoaGraphicsSwitching(bool),
1661     /// Specifies the desired ASCII-encoded class part of the ICCCM `WM_CLASS` window property.
1662     X11ClassName(Option<String>),
1663     /// Specifies the desired ASCII-encoded instance part of the ICCCM `WM_CLASS` window property.
1664     X11InstanceName(Option<String>),
1665 }
1666 
1667 /// Client API tokens.
1668 #[repr(i32)]
1669 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
1670 pub enum ClientApiHint {
1671     NoApi                    = ffi::NO_API,
1672     OpenGl                   = ffi::OPENGL_API,
1673     OpenGlEs                 = ffi::OPENGL_ES_API,
1674 }
1675 
1676 /// Context robustness tokens.
1677 #[repr(i32)]
1678 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
1679 pub enum ContextRobustnessHint {
1680     NoRobustness                = ffi::NO_ROBUSTNESS,
1681     NoResetNotification         = ffi::NO_RESET_NOTIFICATION,
1682     LoseContextOnReset          = ffi::LOSE_CONTEXT_ON_RESET,
1683 }
1684 
1685 /// OpenGL profile tokens.
1686 #[repr(i32)]
1687 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
1688 pub enum OpenGlProfileHint {
1689     Any            = ffi::OPENGL_ANY_PROFILE,
1690     Core           = ffi::OPENGL_CORE_PROFILE,
1691     Compat         = ffi::OPENGL_COMPAT_PROFILE,
1692 }
1693 
1694 /// Describes the mode of a window
1695 #[derive(Copy, Clone, Debug)]
1696 pub enum WindowMode<'a> {
1697     /// Full screen mode. Contains the monitor on which the window is displayed.
1698     FullScreen(&'a Monitor),
1699 
1700     /// Windowed mode.
1701     Windowed,
1702 }
1703 
1704 /// Private conversion methods for `glfw::WindowMode`
1705 impl<'a> WindowMode<'a> {
1706     /// Returns a pointer to a monitor if the window is fullscreen, otherwise
1707     /// it returns a null pointer (if it is in windowed mode).
to_ptr(&self) -> *mut ffi::GLFWmonitor1708     fn to_ptr(&self) -> *mut ffi::GLFWmonitor {
1709         match *self {
1710             WindowMode::FullScreen(ref monitor) => monitor.ptr,
1711             WindowMode::Windowed                => ptr::null_mut(),
1712         }
1713     }
1714 }
1715 
1716 bitflags! {
1717     #[doc = "Key modifiers (e.g., Shift, Control, Alt, Super)"]
1718     pub struct Modifiers: ::libc::c_int {
1719         const Shift       = ::ffi::MOD_SHIFT;
1720         const Control     = ::ffi::MOD_CONTROL;
1721         const Alt         = ::ffi::MOD_ALT;
1722         const Super       = ::ffi::MOD_SUPER;
1723         const CapsLock    = ::ffi::MOD_CAPS_LOCK;
1724         const NumLock     = ::ffi::MOD_NUM_LOCK;
1725     }
1726 }
1727 
1728 /// Keyboard code returned by the OS
1729 pub type Scancode = c_int;
1730 
1731 /// Window event messages.
1732 #[derive(Clone, PartialEq, PartialOrd, Debug)]
1733 pub enum WindowEvent {
1734     Pos(i32, i32),
1735     Size(i32, i32),
1736     Close,
1737     Refresh,
1738     Focus(bool),
1739     Iconify(bool),
1740     FramebufferSize(i32, i32),
1741     MouseButton(MouseButton, Action, Modifiers),
1742     CursorPos(f64, f64),
1743     CursorEnter(bool),
1744     Scroll(f64, f64),
1745     Key(Key, Scancode, Action, Modifiers),
1746     Char(char),
1747     CharModifiers(char, Modifiers),
1748     FileDrop(Vec<PathBuf>),
1749     Maximize(bool),
1750     ContentScale(f32, f32),
1751 }
1752 
1753 /// Returns an iterator that yields until no more messages are contained in the
1754 /// `Receiver`'s queue. This is useful for event handling where the blocking
1755 /// behaviour of `Receiver::iter` is undesirable.
1756 ///
1757 /// # Example
1758 ///
1759 /// ~~~ignore
1760 /// for event in glfw::flush_messages(&events) {
1761 ///     // handle event
1762 /// }
1763 /// ~~~
flush_messages<'a, Message: Send>(receiver: &'a Receiver<Message>) -> FlushedMessages<'a, Message>1764 pub fn flush_messages<'a, Message: Send>(receiver: &'a Receiver<Message>) -> FlushedMessages<'a, Message> {
1765     FlushedMessages(receiver)
1766 }
1767 
1768 /// An iterator that yields until no more messages are contained in the
1769 /// `Receiver`'s queue.
1770 pub struct FlushedMessages<'a, Message: 'a + Send>(&'a Receiver<Message>);
1771 
1772 unsafe impl<'a, Message: 'a + Send> Send for FlushedMessages<'a, Message> {
1773 }
1774 
1775 impl<'a, Message: 'static + Send> Iterator for FlushedMessages<'a, Message> {
1776     type Item = Message;
1777 
next(&mut self) -> Option<Message>1778     fn next(&mut self) -> Option<Message> {
1779         let FlushedMessages(receiver) = *self;
1780         match receiver.try_recv() {
1781             Ok(message) => Some(message),
1782             _ => None,
1783         }
1784     }
1785 }
1786 
1787 /// A struct that wraps a `*GLFWwindow` handle.
1788 pub struct Window {
1789     ptr: *mut ffi::GLFWwindow,
1790     pub glfw: Glfw,
1791     pub is_shared: bool,
1792     /// A `Sender` that can be cloned out to child `RenderContext`s.
1793     drop_sender: Option<Sender<()>>,
1794     /// Once all  child`RenderContext`s have been dropped, calling `try_recv()`
1795     /// on the `drop_receiver` will result in an `Err(std::comm::Disconnected)`,
1796     /// indicating that it is safe to drop the `Window`.
1797     drop_receiver: Receiver<()>,
1798     /// This is here to allow owning the current Cursor object instead
1799     /// of forcing the user to take care of its lifetime.
1800     current_cursor: Option<Cursor>
1801 }
1802 
1803 macro_rules! set_window_callback {
1804     ($window:ident, $should_poll:expr, $ll_fn:ident, $callback:ident) => ({
1805         if $should_poll {
1806             unsafe { ffi::$ll_fn($window.ptr, Some(callbacks::$callback)); }
1807         } else {
1808             unsafe { ffi::$ll_fn($window.ptr, None); }
1809         }
1810     })
1811 }
1812 
1813 impl Window {
1814     /// Returns the address of the specified client API or extension function if
1815     /// it is supported by the context associated with this Window. If this Window is not the
1816     /// current context, it will make it the current context.
1817     ///
1818     /// Wrapper for `glfwGetProcAddress`.
get_proc_address(&mut self, procname: &str) -> GLProc1819     pub fn get_proc_address(&mut self, procname: &str) -> GLProc {
1820         if self.ptr != unsafe { ffi::glfwGetCurrentContext() } {
1821             self.make_current();
1822         }
1823 
1824         self.glfw.get_proc_address_raw(procname)
1825     }
1826 
1827     /// This function returns the address of the specified Vulkan core or extension function
1828     /// for the specified instance. If instance is set to NULL it can return any function
1829     /// exported from the Vulkan loader, including at least the following functions:
1830     ///
1831     /// * `vkEnumerateInstanceExtensionProperties`
1832     /// * `vkEnumerateInstanceLayerProperties`
1833     /// * `vkCreateInstance`
1834     /// * `vkGetInstanceProcAddr`
1835     ///
1836     /// If Vulkan is not available on the machine, this function returns `NULL`
1837     ///
1838     /// Wrapper for `glfwGetInstanceProcAddress`
1839     #[cfg(feature = "vulkan")]
get_instance_proc_address(&mut self, instance: VkInstance, procname: &str) -> VkProc1840     pub fn get_instance_proc_address(&mut self, instance: VkInstance, procname: &str) -> VkProc {
1841         self.glfw.get_instance_proc_address_raw(instance, procname)
1842     }
1843 
1844     /// This function returns whether the specified queue family of the specified
1845     /// physical device supports presentation to the platform GLFW was built for.
1846     ///
1847     /// Wrapper for `glfwGetPhysicalDevicePresentationSupport`
1848     #[cfg(feature = "vulkan")]
get_physical_device_presentation_support(&self, instance: VkInstance, device: VkPhysicalDevice, queue_family: u32) -> bool1849     pub fn get_physical_device_presentation_support(&self, instance: VkInstance, device: VkPhysicalDevice, queue_family: u32) -> bool {
1850         self.glfw.get_physical_device_presentation_support_raw(instance, device, queue_family)
1851     }
1852 
1853     /// Wrapper for `glfwCreateWindow`.
create_shared(&self, width: u32, height: u32, title: &str, mode: WindowMode) -> Option<(Window, Receiver<(f64, WindowEvent)>)>1854     pub fn create_shared(&self, width: u32, height: u32, title: &str, mode: WindowMode) -> Option<(Window, Receiver<(f64, WindowEvent)>)> {
1855         self.glfw.create_window_intern(width, height, title, mode, Some(self))
1856     }
1857 
1858     /// Calling this method forces the destructor to be called, closing the
1859     /// window.
close(self)1860     pub fn close(self) {}
1861 
1862     /// Returns a render context that can be shared between tasks, allowing
1863     /// for concurrent rendering.
render_context(&mut self) -> RenderContext1864     pub fn render_context(&mut self) -> RenderContext {
1865         RenderContext {
1866             ptr: self.ptr,
1867             // this will only be None after dropping so this is safe
1868             drop_sender: self.drop_sender.as_ref().unwrap().clone()
1869         }
1870     }
1871 
1872     /// Wrapper for `glfwWindowShouldClose`.
should_close(&self) -> bool1873     pub fn should_close(&self) -> bool {
1874         unsafe { ffi::glfwWindowShouldClose(self.ptr) == ffi::TRUE }
1875     }
1876 
1877     /// Wrapper for `glfwSetWindowShouldClose`.
set_should_close(&mut self, value: bool)1878     pub fn set_should_close(&mut self, value: bool) {
1879         unsafe { ffi::glfwSetWindowShouldClose(self.ptr, value as c_int) }
1880     }
1881 
1882     /// Sets the title of the window.
1883     ///
1884     /// Wrapper for `glfwSetWindowTitle`.
set_title(&mut self, title: &str)1885     pub fn set_title(&mut self, title: &str) {
1886         unsafe {
1887             with_c_str(title, |title| {
1888                 ffi::glfwSetWindowTitle(self.ptr, title);
1889             });
1890         }
1891     }
1892 
1893     /// Wrapper for `glfwGetWindowPos`.
get_pos(&self) -> (i32, i32)1894     pub fn get_pos(&self) -> (i32, i32) {
1895         unsafe {
1896             let mut xpos = 0;
1897             let mut ypos = 0;
1898             ffi::glfwGetWindowPos(self.ptr, &mut xpos, &mut ypos);
1899             (xpos as i32, ypos as i32)
1900         }
1901     }
1902 
1903     /// Wrapper for `glfwSetWindowPos`.
set_pos(&mut self, xpos: i32, ypos: i32)1904     pub fn set_pos(&mut self, xpos: i32, ypos: i32) {
1905         unsafe { ffi::glfwSetWindowPos(self.ptr, xpos as c_int, ypos as c_int); }
1906     }
1907 
1908     /// Wrapper for `glfwGetWindowSize`.
get_size(&self) -> (i32, i32)1909     pub fn get_size(&self) -> (i32, i32) {
1910         unsafe {
1911             let mut width = 0;
1912             let mut height = 0;
1913             ffi::glfwGetWindowSize(self.ptr, &mut width, &mut height);
1914             (width as i32, height as i32)
1915         }
1916     }
1917 
1918     /// Wrapper for `glfwSetWindowSize`.
set_size(&mut self, width: i32, height: i32)1919     pub fn set_size(&mut self, width: i32, height: i32) {
1920         unsafe { ffi::glfwSetWindowSize(self.ptr, width as c_int, height as c_int); }
1921     }
1922 
1923     /// Wrapper for `glfwGetWindowFrameSize`
1924     ///
1925     /// Returns `(left, top, right, bottom)` edge window frame sizes, in screen coordinates.
get_frame_size(&self) -> (i32, i32, i32, i32)1926     pub fn get_frame_size(&self) -> (i32, i32, i32, i32) {
1927         let (mut left, mut top, mut right, mut bottom): (i32, i32, i32, i32) = (0, 0, 0, 0);
1928 
1929         unsafe {
1930             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);
1931         }
1932 
1933         (left, top, right, bottom)
1934     }
1935 
1936     /// Wrapper for `glfwGetFramebufferSize`.
get_framebuffer_size(&self) -> (i32, i32)1937     pub fn get_framebuffer_size(&self) -> (i32, i32) {
1938         unsafe {
1939             let mut width = 0;
1940             let mut height = 0;
1941             ffi::glfwGetFramebufferSize(self.ptr, &mut width, &mut height);
1942             (width as i32, height as i32)
1943         }
1944     }
1945 
1946     /// Wrapper for `glfwSetWindowAspectRatio`.
set_aspect_ratio(&mut self, numer: u32, denum: u32)1947     pub fn set_aspect_ratio(&mut self, numer: u32, denum: u32) {
1948         unsafe { ffi::glfwSetWindowAspectRatio(self.ptr, numer as c_int, denum as c_int) }
1949     }
1950 
1951     /// Wrapper for `glfwSetWindowSizeLimits`.
set_size_limits(&mut self, minwidth: u32, minheight: u32, maxwidth: u32, maxheight: u32)1952     pub fn set_size_limits(&mut self, minwidth: u32, minheight: u32, maxwidth: u32, maxheight: u32) {
1953         unsafe { ffi::glfwSetWindowSizeLimits(self.ptr , minwidth as c_int, minheight as c_int, maxwidth as c_int, maxheight as c_int) }
1954     }
1955 
1956     /// Wrapper for `glfwIconifyWindow`.
iconify(&mut self)1957     pub fn iconify(&mut self) {
1958         unsafe { ffi::glfwIconifyWindow(self.ptr); }
1959     }
1960 
1961     /// Wrapper for `glfwRestoreWindow`.
restore(&mut self)1962     pub fn restore(&mut self) {
1963         unsafe { ffi::glfwRestoreWindow(self.ptr); }
1964     }
1965 
1966     /// Wrapper for `glfwMaximizeWindow`
maximize(&mut self)1967     pub fn maximize(&mut self) {
1968         unsafe { ffi::glfwMaximizeWindow(self.ptr) }
1969     }
1970 
1971     /// Wrapper for `glfwShowWindow`.
show(&mut self)1972     pub fn show(&mut self) {
1973         unsafe { ffi::glfwShowWindow(self.ptr); }
1974     }
1975 
1976     /// Wrapper for `glfwHideWindow`.
hide(&mut self)1977     pub fn hide(&mut self) {
1978         unsafe { ffi::glfwHideWindow(self.ptr); }
1979     }
1980 
1981     /// Returns whether the window is fullscreen or windowed.
1982     ///
1983     /// # Example
1984     ///
1985     /// ~~~ignore
1986     /// window.with_window_mode(|mode| {
1987     ///     match mode {
1988     ///         glfw::Windowed => println!("Windowed"),
1989     ///         glfw::FullScreen(m) => println!("FullScreen({})", m.get_name()),
1990     ///     }
1991     /// });
1992     /// ~~~
with_window_mode<T, F>(&self, f: F) -> T where F: Fn(WindowMode) -> T1993     pub fn with_window_mode<T, F>(&self, f: F) -> T where F: Fn(WindowMode) -> T {
1994         let ptr = unsafe { ffi::glfwGetWindowMonitor(self.ptr) };
1995         if ptr.is_null() {
1996             f(WindowMode::Windowed)
1997         } else {
1998             f(WindowMode::FullScreen(&Monitor {
1999                 ptr: ptr
2000             }))
2001         }
2002     }
2003 
2004     /// Returns whether the window is fullscreen or windowed.
2005     ///
2006     /// Variant that can accept an `FnMut` closure.
2007     ///
2008     /// # Example
2009     ///
2010     /// ~~~ignore
2011     /// window.with_window_mode(|mode| {
2012     ///     match mode {
2013     ///         glfw::Windowed => println!("Windowed"),
2014     ///         glfw::FullScreen(m) => println!("FullScreen({})", m.get_name()),
2015     ///     }
2016     /// });
2017     /// ~~~
with_window_mode_mut<T, F>(&self, mut f: F) -> T where F: FnMut(WindowMode) -> T2018     pub fn with_window_mode_mut<T, F>(&self, mut f: F) -> T where F: FnMut(WindowMode) -> T {
2019         let ptr = unsafe { ffi::glfwGetWindowMonitor(self.ptr) };
2020         if ptr.is_null() {
2021             f(WindowMode::Windowed)
2022         } else {
2023             f(WindowMode::FullScreen(&Monitor {
2024                 ptr: ptr
2025             }))
2026         }
2027     }
2028 
2029     /// Wrapper for `glfwSetWindowMonitor`
set_monitor(&mut self, mode: WindowMode, xpos: i32, ypos: i32, width: u32, height: u32, refresh_rate: Option<u32>)2030     pub fn set_monitor(&mut self, mode: WindowMode, xpos: i32, ypos: i32, width: u32, height: u32, refresh_rate: Option<u32>) {
2031         let monitor_ptr = if let WindowMode::FullScreen(ref monitor) = mode { monitor.ptr } else { ptr::null_mut() };
2032 
2033         unsafe {
2034             ffi::glfwSetWindowMonitor(self.ptr, monitor_ptr, xpos as c_int, ypos as c_int, width as c_int, height as c_int, match refresh_rate {
2035                 Some(value) => value as c_int,
2036                 None => ffi::DONT_CARE
2037             })
2038         }
2039     }
2040 
2041     /// Wrapper for `glfwFocusWindow`
2042     ///
2043     /// It is NOT recommended to use this function, as it steals focus from other applications
2044     /// and can be extremely disruptive to the user.
focus(&mut self)2045     pub fn focus(&mut self) {
2046         unsafe { ffi::glfwFocusWindow(self.ptr) }
2047     }
2048 
2049     /// Wrapper for `glfwGetWindowAttrib` called with `FOCUSED`.
is_focused(&self) -> bool2050     pub fn is_focused(&self) -> bool {
2051         unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::FOCUSED) == ffi::TRUE }
2052     }
2053 
2054     /// Wrapper for `glfwGetWindowAttrib` called with `ICONIFIED`.
is_iconified(&self) -> bool2055     pub fn is_iconified(&self) -> bool {
2056         unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::ICONIFIED) == ffi::TRUE }
2057     }
2058 
2059     /// Wrapper for `glfwGetWindowattrib` called with `MAXIMIZED`.
is_maximized(&self) -> bool2060     pub fn is_maximized(&self) -> bool {
2061         unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::MAXIMIZED) == ffi::TRUE }
2062     }
2063 
2064     /// Wrapper for `glfwGetWindowAttrib` called with `CLIENT_API`.
get_client_api(&self) -> c_int2065     pub fn get_client_api(&self) -> c_int {
2066         unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::CLIENT_API) }
2067     }
2068 
2069     /// Wrapper for `glfwGetWindowAttrib` called with
2070     /// `CONTEXT_VERSION_MAJOR`, `CONTEXT_VERSION_MINOR` and `CONTEXT_REVISION`.
2071     ///
2072     /// # Returns
2073     ///
2074     /// The client API version of the window's context in a version struct.
get_context_version(&self) -> Version2075     pub fn get_context_version(&self) -> Version {
2076         unsafe {
2077             Version {
2078                 major: ffi::glfwGetWindowAttrib(self.ptr, ffi::CONTEXT_VERSION_MAJOR) as u64,
2079                 minor: ffi::glfwGetWindowAttrib(self.ptr, ffi::CONTEXT_VERSION_MINOR) as u64,
2080                 patch: ffi::glfwGetWindowAttrib(self.ptr, ffi::CONTEXT_REVISION) as u64,
2081                 pre:   Vec::new(),
2082                 build: Vec::new(),
2083             }
2084         }
2085     }
2086 
2087     /// Wrapper for `glfwGetWindowAttrib` called with `CONTEXT_ROBUSTNESS`.
get_context_robustness(&self) -> c_int2088     pub fn get_context_robustness(&self) -> c_int {
2089         unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::CONTEXT_ROBUSTNESS) }
2090     }
2091 
2092     /// Wrapper for `glfwGetWindowAttrib` called with `OPENGL_FORWARD_COMPAT`.
is_opengl_forward_compat(&self) -> bool2093     pub fn is_opengl_forward_compat(&self) -> bool {
2094         unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::OPENGL_FORWARD_COMPAT) == ffi::TRUE }
2095     }
2096 
2097     /// Wrapper for `glfwGetWindowAttrib` called with `OPENGL_DEBUG_CONTEXT`.
is_opengl_debug_context(&self) -> bool2098     pub fn is_opengl_debug_context(&self) -> bool {
2099         unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::OPENGL_DEBUG_CONTEXT) == ffi::TRUE }
2100     }
2101 
2102     /// Wrapper for `glfwGetWindowAttrib` called with `OPENGL_PROFILE`.
get_opengl_profile(&self) -> c_int2103     pub fn get_opengl_profile(&self) -> c_int {
2104         unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::OPENGL_PROFILE) }
2105     }
2106 
2107     /// Wrapper for `glfwGetWindowAttrib` called with `RESIZABLE`.
is_resizable(&self) -> bool2108     pub fn is_resizable(&self) -> bool {
2109         unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::RESIZABLE) == ffi::TRUE }
2110     }
2111 
2112     /// Wrapper for `glfwSetWindowAttrib` called with `RESIZABLE`.
set_resizable(&mut self, resizable: bool)2113     pub fn set_resizable(&mut self, resizable: bool) {
2114         unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::RESIZABLE, resizable as c_int) }
2115     }
2116 
2117     /// Wrapper for `glfwGetWindowAttrib` called with `VISIBLE`.
is_visible(&self) -> bool2118     pub fn is_visible(&self) -> bool {
2119         unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::VISIBLE) == ffi::TRUE }
2120     }
2121 
2122     /// Wrapper for `glfwGetWindowAttrib` called with `DECORATED`.
is_decorated(&self) -> bool2123     pub fn is_decorated(&self) -> bool {
2124         unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::DECORATED) == ffi::TRUE }
2125     }
2126 
2127     /// Wrapper for `glfwSetWindowAttrib` called with `DECORATED`.
set_decorated(&mut self, decorated: bool)2128     pub fn set_decorated(&mut self, decorated: bool) {
2129         unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::DECORATED, decorated as c_int) }
2130     }
2131 
2132     /// Wrapper for `glfwGetWindowAttrib` called with `AUTO_ICONIFY`.
is_auto_iconify(&self) -> bool2133     pub fn is_auto_iconify(&self) -> bool {
2134         unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::AUTO_ICONIFY) == ffi::TRUE }
2135     }
2136 
2137     /// Wrapper for `glfwSetWindowAttrib` called with `AUTO_ICONIFY`.
set_auto_iconify(&mut self, auto_iconify: bool)2138     pub fn set_auto_iconify(&mut self, auto_iconify: bool) {
2139         unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::AUTO_ICONIFY, auto_iconify as c_int) }
2140     }
2141 
2142     /// Wrapper for `glfwGetWindowAttrib` called with `FLOATING`.
is_floating(&self) -> bool2143     pub fn is_floating(&self) -> bool {
2144         unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::FLOATING) == ffi::TRUE }
2145     }
2146 
2147     /// Wrapper for `glfwSetWindowAttrib` called with `FLOATING`.
set_floating(&mut self, floating: bool)2148     pub fn set_floating(&mut self, floating: bool) {
2149         unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::FLOATING, floating as c_int) }
2150     }
2151 
2152     /// Wrapper for `glfwGetWindowAttrib` called with `TRANSPARENT_FRAMEBUFFER`.
is_framebuffer_transparent(&self) -> bool2153     pub fn is_framebuffer_transparent(&self) -> bool {
2154         unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::TRANSPARENT_FRAMEBUFFER) == ffi::TRUE }
2155     }
2156 
2157     /// Wrapper for `glfwGetWindowAttrib` called with `FOCUS_ON_SHOW`.
is_focus_on_show(&self) -> bool2158     pub fn is_focus_on_show(&self) -> bool {
2159         unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::FOCUS_ON_SHOW) == ffi::TRUE }
2160     }
2161 
2162     /// Wrapper for `glfwSetWindowAttrib` called with `FOCUS_ON_SHOW`.
set_focus_on_show(&mut self, focus_on_show: bool)2163     pub fn set_focus_on_show(&mut self, focus_on_show: bool) {
2164         unsafe { ffi::glfwSetWindowAttrib(self.ptr, ffi::FOCUS_ON_SHOW, focus_on_show as c_int) }
2165     }
2166 
2167     /// Wrapper for `glfwGetWindowAttrib` called with `HOVERED`.
is_hovered(&self) -> bool2168     pub fn is_hovered(&self) -> bool {
2169         unsafe { ffi::glfwGetWindowAttrib(self.ptr, ffi::HOVERED) == ffi::TRUE }
2170     }
2171 
2172     /// Wrapper for `glfwSetWindowPosCallback`.
set_pos_polling(&mut self, should_poll: bool)2173     pub fn set_pos_polling(&mut self, should_poll: bool) {
2174         set_window_callback!(self, should_poll, glfwSetWindowPosCallback, window_pos_callback);
2175     }
2176 
2177     /// Starts or stops polling for all available events
set_all_polling(&mut self, should_poll: bool)2178     pub fn set_all_polling(&mut self, should_poll: bool) {
2179         self.set_pos_polling(should_poll);
2180         self.set_size_polling(should_poll);
2181         self.set_close_polling(should_poll);
2182         self.set_refresh_polling(should_poll);
2183         self.set_focus_polling(should_poll);
2184         self.set_iconify_polling(should_poll);
2185         self.set_framebuffer_size_polling(should_poll);
2186         self.set_key_polling(should_poll);
2187         self.set_char_polling(should_poll);
2188         self.set_char_mods_polling(should_poll);
2189         self.set_mouse_button_polling(should_poll);
2190         self.set_cursor_pos_polling(should_poll);
2191         self.set_cursor_enter_polling(should_poll);
2192         self.set_scroll_polling(should_poll);
2193         self.set_drag_and_drop_polling(should_poll);
2194         self.set_maximize_polling(should_poll);
2195         self.set_content_scale_polling(should_poll);
2196     }
2197 
2198     /// Wrapper for `glfwSetWindowSizeCallback`.
set_size_polling(&mut self, should_poll: bool)2199     pub fn set_size_polling(&mut self, should_poll: bool) {
2200         set_window_callback!(self, should_poll, glfwSetWindowSizeCallback, window_size_callback);
2201     }
2202 
2203     /// Wrapper for `glfwSetWindowCloseCallback`.
set_close_polling(&mut self, should_poll: bool)2204     pub fn set_close_polling(&mut self, should_poll: bool) {
2205         set_window_callback!(self, should_poll, glfwSetWindowCloseCallback, window_close_callback);
2206     }
2207 
2208     /// Wrapper for `glfwSetWindowRefreshCallback`.
set_refresh_polling(&mut self, should_poll: bool)2209     pub fn set_refresh_polling(&mut self, should_poll: bool) {
2210         set_window_callback!(self, should_poll, glfwSetWindowRefreshCallback, window_refresh_callback);
2211     }
2212 
2213     /// Wrapper for `glfwSetWindowFocusCallback`.
set_focus_polling(&mut self, should_poll: bool)2214     pub fn set_focus_polling(&mut self, should_poll: bool) {
2215         set_window_callback!(self, should_poll, glfwSetWindowFocusCallback, window_focus_callback);
2216     }
2217 
2218     /// Wrapper for `glfwSetWindowIconifyCallback`.
set_iconify_polling(&mut self, should_poll: bool)2219     pub fn set_iconify_polling(&mut self, should_poll: bool) {
2220         set_window_callback!(self, should_poll, glfwSetWindowIconifyCallback, window_iconify_callback);
2221     }
2222 
2223     /// Wrapper for `glfwSetFramebufferSizeCallback`.
set_framebuffer_size_polling(&mut self, should_poll: bool)2224     pub fn set_framebuffer_size_polling(&mut self, should_poll: bool) {
2225         set_window_callback!(self, should_poll, glfwSetFramebufferSizeCallback, framebuffer_size_callback);
2226     }
2227 
2228     /// Wrapper for `glfwSetDropCallback`.
set_drag_and_drop_polling(&mut self, should_poll: bool)2229     pub fn set_drag_and_drop_polling(&mut self, should_poll: bool) {
2230         set_window_callback!(self, should_poll, glfwSetDropCallback, drop_callback);
2231     }
2232 
2233     /// Wrapper for `glfwSetWindowMaximizeCallback`.
set_maximize_polling(&mut self, should_poll: bool)2234     pub fn set_maximize_polling(&mut self, should_poll: bool) {
2235         set_window_callback!(self, should_poll, glfwSetWindowMaximizeCallback, window_maximize_callback);
2236     }
2237 
2238     /// Wrapper for `glfwSetWindowContentScaleCallback`.
set_content_scale_polling(&mut self, should_poll: bool)2239     pub fn set_content_scale_polling(&mut self, should_poll: bool) {
2240         set_window_callback!(self, should_poll, glfwSetWindowContentScaleCallback, window_content_scale_callback);
2241     }
2242 
2243     /// Wrapper for `glfwGetInputMode` called with `CURSOR`.
get_cursor_mode(&self) -> CursorMode2244     pub fn get_cursor_mode(&self) -> CursorMode {
2245         unsafe { mem::transmute(ffi::glfwGetInputMode(self.ptr, ffi::CURSOR)) }
2246     }
2247 
2248     /// Wrapper for `glfwSetInputMode` called with `CURSOR`.
set_cursor_mode(&mut self, mode: CursorMode)2249     pub fn set_cursor_mode(&mut self, mode: CursorMode) {
2250         unsafe { ffi::glfwSetInputMode(self.ptr, ffi::CURSOR, mode as c_int); }
2251     }
2252 
2253     /// Wrapper for `glfwSetCursor` using `Cursor`
2254     ///
2255     /// The window will take ownership of the cursor, and will not Drop it
2256     /// until it is replaced or the window itself is destroyed.
2257     ///
2258     /// Returns the previously set Cursor or None if no cursor was set.
set_cursor(&mut self, cursor: Option<Cursor>) -> Option<Cursor>2259     pub fn set_cursor(&mut self, cursor: Option<Cursor>) -> Option<Cursor> {
2260         let previous = mem::replace(&mut self.current_cursor, cursor);
2261 
2262         unsafe {
2263             ffi::glfwSetCursor(self.ptr, match self.current_cursor {
2264                 Some(ref cursor) => cursor.ptr,
2265                 None => ptr::null_mut()
2266             })
2267         }
2268 
2269         previous
2270     }
2271 
2272     /// Sets the window icon from the given images by called `glfwSetWindowIcon`
2273     ///
2274     /// Multiple images can be specified for allowing the OS to choose the best size where necessary.
2275     ///
2276     /// Example:
2277     ///
2278     /// ```ignore
2279     ///if let DynamicImage::ImageRgba8(icon) = image::open("examples/icon.png").unwrap() {
2280     ///    window.set_icon(vec![
2281     ///        imageops::resize(&icon, 16, 16, image::imageops::Lanczos3),
2282     ///        imageops::resize(&icon, 32, 32, image::imageops::Lanczos3),
2283     ///        imageops::resize(&icon, 48, 48, image::imageops::Lanczos3)
2284     ///    ]);
2285     ///}
2286     /// ```
2287     #[cfg(feature = "image")]
set_icon(&mut self, images: Vec<image::RgbaImage>)2288     pub fn set_icon(&mut self, images: Vec<image::RgbaImage>) {
2289         // When the images are turned into Vecs, the lifetimes of them go into the Vec lifetime
2290         // So they need to be kept until the function ends.
2291         let image_data : Vec<(Vec<_>, u32, u32)> = images.into_iter().map(|image| {
2292             let (width, height) = image.dimensions();
2293 
2294             (image.into_vec(), width, height)
2295         }).collect();
2296 
2297         let glfw_images: Vec<ffi::GLFWimage> = image_data.iter().map(|ref data| {
2298             ffi::GLFWimage {
2299                 width:  data.1 as c_int,
2300                 height: data.2 as c_int,
2301                 pixels: data.0.as_ptr() as *const c_uchar
2302             }
2303         }).collect();
2304 
2305         unsafe {
2306             ffi::glfwSetWindowIcon(self.ptr, glfw_images.len() as c_int, glfw_images.as_ptr() as *const ffi::GLFWimage)
2307         }
2308     }
2309 
2310     /// Sets the window icon via `glfwSetWindowIcon` from a set a set of vectors
2311     /// containing pixels in RGBA format (one pixel per 32-bit integer)
set_icon_from_pixels(&mut self, images: Vec<PixelImage>)2312     pub fn set_icon_from_pixels(&mut self, images: Vec<PixelImage>) {
2313         let glfw_images: Vec<ffi::GLFWimage> = images.iter().map(|image: &PixelImage| {
2314             ffi::GLFWimage {
2315                 width: image.width as c_int,
2316                 height: image.height as c_int,
2317                 pixels: image.pixels.as_ptr() as *const c_uchar
2318             }
2319         }).collect();
2320 
2321         unsafe {
2322             ffi::glfwSetWindowIcon(self.ptr, glfw_images.len() as c_int, glfw_images.as_ptr() as *const ffi::GLFWimage)
2323         }
2324     }
2325 
2326     /// Wrapper for `glfwGetInputMode` called with `STICKY_KEYS`.
has_sticky_keys(&self) -> bool2327     pub fn has_sticky_keys(&self) -> bool {
2328         unsafe { ffi::glfwGetInputMode(self.ptr, ffi::STICKY_KEYS) == ffi::TRUE }
2329     }
2330 
2331     /// Wrapper for `glfwSetInputMode` called with `STICKY_KEYS`.
set_sticky_keys(&mut self, value: bool)2332     pub fn set_sticky_keys(&mut self, value: bool) {
2333         unsafe { ffi::glfwSetInputMode(self.ptr, ffi::STICKY_KEYS, value as c_int); }
2334     }
2335 
2336     /// Wrapper for `glfwGetInputMode` called with `STICKY_MOUSE_BUTTONS`.
has_sticky_mouse_buttons(&self) -> bool2337     pub fn has_sticky_mouse_buttons(&self) -> bool {
2338         unsafe { ffi::glfwGetInputMode(self.ptr, ffi::STICKY_MOUSE_BUTTONS) == ffi::TRUE }
2339     }
2340 
2341     /// Wrapper for `glfwSetInputMode` called with `STICKY_MOUSE_BUTTONS`.
set_sticky_mouse_buttons(&mut self, value: bool)2342     pub fn set_sticky_mouse_buttons(&mut self, value: bool) {
2343         unsafe { ffi::glfwSetInputMode(self.ptr, ffi::STICKY_MOUSE_BUTTONS, value as c_int); }
2344     }
2345 
2346     /// Wrapper for `glfwGetInputMode` called with `LOCK_KEY_MODS`
does_store_lock_key_mods(&self) -> bool2347     pub fn does_store_lock_key_mods(&self) -> bool {
2348         unsafe { ffi::glfwGetInputMode(self.ptr, ffi::LOCK_KEY_MODS) == ffi::TRUE }
2349     }
2350 
2351     /// Wrapper for `glfwSetInputMode` called with `LOCK_KEY_MODS`
set_store_lock_key_mods(&mut self, value: bool)2352     pub fn set_store_lock_key_mods(&mut self, value: bool) {
2353         unsafe { ffi::glfwSetInputMode(self.ptr, ffi::LOCK_KEY_MODS, value as c_int) }
2354     }
2355 
2356     /// Wrapper for `glfwGetInputMode` called with `RAW_MOUSE_MOTION`
uses_raw_mouse_motion(&self) -> bool2357     pub fn uses_raw_mouse_motion(&self) -> bool {
2358         unsafe { ffi::glfwGetInputMode(self.ptr, ffi::RAW_MOUSE_MOTION) == ffi::TRUE }
2359     }
2360 
2361     /// Wrapper for `glfwSetInputMode` called with `RAW_MOUSE_MOTION`
set_raw_mouse_motion(&mut self, value: bool)2362     pub fn set_raw_mouse_motion(&mut self, value: bool) {
2363         unsafe { ffi::glfwSetInputMode(self.ptr, ffi::RAW_MOUSE_MOTION, value as c_int) }
2364     }
2365 
2366     /// Wrapper for `glfwGetKey`.
get_key(&self, key: Key) -> Action2367     pub fn get_key(&self, key: Key) -> Action {
2368         unsafe { mem::transmute(ffi::glfwGetKey(self.ptr, key as c_int)) }
2369     }
2370 
2371     /// Wrapper for `glfwGetMouseButton`.
get_mouse_button(&self, button: MouseButton) -> Action2372     pub fn get_mouse_button(&self, button: MouseButton) -> Action {
2373         unsafe { mem::transmute(ffi::glfwGetMouseButton(self.ptr, button as c_int)) }
2374     }
2375 
2376     /// Wrapper for `glfwGetCursorPos`.
get_cursor_pos(&self) -> (f64, f64)2377     pub fn get_cursor_pos(&self) -> (f64, f64) {
2378         unsafe {
2379             let mut xpos = 0.0;
2380             let mut ypos = 0.0;
2381             ffi::glfwGetCursorPos(self.ptr, &mut xpos, &mut ypos);
2382             (xpos as f64, ypos as f64)
2383         }
2384     }
2385 
2386     /// Wrapper for `glfwSetCursorPos`.
set_cursor_pos(&mut self, xpos: f64, ypos: f64)2387     pub fn set_cursor_pos(&mut self, xpos: f64, ypos: f64) {
2388         unsafe { ffi::glfwSetCursorPos(self.ptr, xpos as c_double, ypos as c_double); }
2389     }
2390 
2391     /// Wrapper for `glfwSetKeyCallback`.
set_key_polling(&mut self, should_poll: bool)2392     pub fn set_key_polling(&mut self, should_poll: bool) {
2393         set_window_callback!(self, should_poll, glfwSetKeyCallback, key_callback);
2394     }
2395 
2396     /// Wrapper for `glfwSetCharCallback`.
set_char_polling(&mut self, should_poll: bool)2397     pub fn set_char_polling(&mut self, should_poll: bool) {
2398         set_window_callback!(self, should_poll, glfwSetCharCallback, char_callback);
2399     }
2400 
2401     /// Wrapper for `glfwSetCharModsCallback`
set_char_mods_polling(&mut self, should_poll: bool)2402     pub fn set_char_mods_polling(&mut self, should_poll: bool) {
2403         set_window_callback!(self, should_poll, glfwSetCharModsCallback, char_mods_callback);
2404     }
2405 
2406     /// Wrapper for `glfwSetMouseButtonCallback`.
set_mouse_button_polling(&mut self, should_poll: bool)2407     pub fn set_mouse_button_polling(&mut self, should_poll: bool) {
2408         set_window_callback!(self, should_poll, glfwSetMouseButtonCallback, mouse_button_callback);
2409     }
2410 
2411     /// Wrapper for `glfwSetCursorPosCallback`.
set_cursor_pos_polling(&mut self, should_poll: bool)2412     pub fn set_cursor_pos_polling(&mut self, should_poll: bool) {
2413         set_window_callback!(self, should_poll, glfwSetCursorPosCallback, cursor_pos_callback);
2414     }
2415 
2416     /// Wrapper for `glfwSetCursorEnterCallback`.
set_cursor_enter_polling(&mut self, should_poll: bool)2417     pub fn set_cursor_enter_polling(&mut self, should_poll: bool) {
2418         set_window_callback!(self, should_poll, glfwSetCursorEnterCallback, cursor_enter_callback);
2419     }
2420 
2421     /// Wrapper for `glfwSetScrollCallback`.
set_scroll_polling(&mut self, should_poll: bool)2422     pub fn set_scroll_polling(&mut self, should_poll: bool) {
2423         set_window_callback!(self, should_poll, glfwSetScrollCallback, scroll_callback);
2424     }
2425 
2426     /// Wrapper for `glfwGetClipboardString`.
set_clipboard_string(&mut self, string: &str)2427     pub fn set_clipboard_string(&mut self, string: &str) {
2428         unsafe {
2429             with_c_str(string, |string| {
2430                 ffi::glfwSetClipboardString(self.ptr, string);
2431             });
2432         }
2433     }
2434 
2435     /// Wrapper for `glfwGetClipboardString`.
get_clipboard_string(&self) -> Option<String>2436     pub fn get_clipboard_string(&self) -> Option<String> {
2437         unsafe { string_from_nullable_c_str(ffi::glfwGetClipboardString(self.ptr)) }
2438     }
2439 
2440     /// Wrapper for 'glfwGetWindowOpacity'.
get_opacity(&self) -> f322441     pub fn get_opacity(&self) -> f32 {
2442         unsafe { ffi::glfwGetWindowOpacity(self.ptr) }
2443     }
2444 
2445     /// Wrapper for 'glfwSetWindowOpacity'.
set_opacity(&mut self, opacity: f32)2446     pub fn set_opacity(&mut self, opacity: f32) {
2447         unsafe { ffi::glfwSetWindowOpacity(self.ptr, opacity) }
2448     }
2449 
2450     /// Wrapper for `glfwRequestWindowAttention`.
request_attention(&mut self)2451     pub fn request_attention(&mut self) {
2452         unsafe { ffi::glfwRequestWindowAttention(self.ptr) }
2453     }
2454 
2455     /// Wrapper for `glfwGetWindowContentScale`.
get_content_scale(&self) -> (f32, f32)2456     pub fn get_content_scale(&self) -> (f32, f32) {
2457         unsafe {
2458             let mut xscale = 0.0_f32;
2459             let mut yscale = 0.0_f32;
2460             ffi::glfwGetWindowContentScale(self.ptr, &mut xscale, &mut yscale);
2461             (xscale, yscale)
2462         }
2463     }
2464 
2465     /// Wrapper for `glfwGetWin32Window`
2466     #[cfg(target_os="windows")]
get_win32_window(&self) -> *mut c_void2467     pub fn get_win32_window(&self) -> *mut c_void {
2468         unsafe { ffi::glfwGetWin32Window(self.ptr) }
2469     }
2470 
2471     /// Wrapper for `glfwGetWGLContext`
2472     #[cfg(target_os="windows")]
get_wgl_context(&self) -> *mut c_void2473     pub fn get_wgl_context(&self) -> *mut c_void {
2474         unsafe { ffi::glfwGetWGLContext(self.ptr) }
2475     }
2476 
2477     /// Wrapper for `glfwGetCocoaWindow`
2478     #[cfg(target_os="macos")]
get_cocoa_window(&self) -> *mut c_void2479     pub fn get_cocoa_window(&self) -> *mut c_void {
2480         unsafe { ffi::glfwGetCocoaWindow(self.ptr) }
2481     }
2482 
2483     /// Wrapper for `glfwGetNSGLContext`
2484     #[cfg(target_os="macos")]
get_nsgl_context(&self) -> *mut c_void2485     pub fn get_nsgl_context(&self) -> *mut c_void {
2486         unsafe { ffi::glfwGetNSGLContext(self.ptr) }
2487     }
2488 
2489     /// Wrapper for `glfwGetX11Window`
2490     #[cfg(target_os="linux")]
get_x11_window(&self) -> *mut c_void2491     pub fn get_x11_window(&self) -> *mut c_void {
2492         unsafe { ffi::glfwGetX11Window(self.ptr) }
2493     }
2494 
2495     /// Wrapper for `glfwGetGLXContext`
2496     #[cfg(target_os="linux")]
get_glx_context(&self) -> *mut c_void2497     pub fn get_glx_context(&self) -> *mut c_void {
2498         unsafe { ffi::glfwGetGLXContext(self.ptr) }
2499     }
2500 }
2501 
2502 impl Drop for Window {
2503     /// Closes the window and performs the necessary cleanups. This will block
2504     /// until all associated `RenderContext`s were also dropped, and emit a
2505     /// `debug!` message to that effect.
2506     ///
2507     /// Wrapper for `glfwDestroyWindow`.
drop(&mut self)2508     fn drop(&mut self) {
2509         drop(self.drop_sender.take());
2510 
2511         // Check if all senders from the child `RenderContext`s have hung up.
2512         if self.drop_receiver.try_recv() != Err(std::sync::mpsc::TryRecvError::Disconnected) {
2513             debug!("Attempted to drop a Window before the `RenderContext` was dropped.");
2514             debug!("Blocking until the `RenderContext` was dropped.");
2515             let _ = self.drop_receiver.recv();
2516         }
2517 
2518         if !self.ptr.is_null() {
2519             unsafe {
2520                 let _: Box<Sender<(f64, WindowEvent)>> = mem::transmute(ffi::glfwGetWindowUserPointer(self.ptr));
2521             }
2522         }
2523 
2524         if !self.is_shared {
2525             unsafe { ffi::glfwDestroyWindow(self.ptr); }
2526         }
2527     }
2528 }
2529 
2530 /// A rendering context that can be shared between tasks.
2531 pub struct RenderContext {
2532     ptr: *mut ffi::GLFWwindow,
2533     /// As long as this sender is alive, it is not safe to drop the parent
2534     /// `Window`.
2535     #[allow(dead_code)]
2536     drop_sender: Sender<()>,
2537 }
2538 
2539 unsafe impl Send for RenderContext {}
2540 
2541 /// Methods common to renderable contexts
2542 pub trait Context {
2543     /// Returns the pointer to the underlying `GLFWwindow`.
window_ptr(&self) -> *mut ffi::GLFWwindow2544     fn window_ptr(&self) -> *mut ffi::GLFWwindow;
2545 
2546     /// Returns the unique identifier for this window.
window_id(&self) -> WindowId2547     fn window_id(&self) -> WindowId {
2548         self.window_ptr() as WindowId
2549     }
2550 
2551     /// Swaps the front and back buffers of the window. If the swap interval is
2552     /// greater than zero, the GPU driver waits the specified number of screen
2553     /// updates before swapping the buffers.
2554     ///
2555     /// Wrapper for `glfwSwapBuffers`.
swap_buffers(&mut self)2556     fn swap_buffers(&mut self) {
2557         let ptr = self.window_ptr();
2558         unsafe { ffi::glfwSwapBuffers(ptr); }
2559     }
2560 
2561     /// Returns `true` if the window is the current context.
is_current(&self) -> bool2562     fn is_current(&self) -> bool {
2563         self.window_ptr() == unsafe { ffi::glfwGetCurrentContext() }
2564     }
2565 
2566     /// Wrapper for `glfwMakeContextCurrent`
make_current(&mut self)2567     fn make_current(&mut self) {
2568         let ptr = self.window_ptr();
2569         unsafe { ffi::glfwMakeContextCurrent(ptr); }
2570     }
2571 
2572     /// Wrapper for `glfwWindowShouldClose`.
should_close(&self) -> bool2573     fn should_close(&self) -> bool {
2574         let ptr = self.window_ptr();
2575         unsafe { ffi::glfwWindowShouldClose(ptr) == ffi::TRUE }
2576     }
2577 
2578     /// Wrapper for `glfwSetWindowShouldClose`.
set_should_close(&mut self, value: bool)2579     fn set_should_close(&mut self, value: bool) {
2580         let ptr = self.window_ptr();
2581         unsafe { ffi::glfwSetWindowShouldClose(ptr, value as c_int); }
2582     }
2583 
2584     /// Wrapper for `glfwPostEmptyEvent`.
post_empty_event(&self)2585     fn post_empty_event(&self) {
2586         unsafe { ffi::glfwPostEmptyEvent() }
2587     }
2588 }
2589 
2590 impl Context for Window {
window_ptr(&self) -> *mut ffi::GLFWwindow2591     fn window_ptr(&self) -> *mut ffi::GLFWwindow { self.ptr }
2592 }
2593 
2594 impl Context for RenderContext {
window_ptr(&self) -> *mut ffi::GLFWwindow2595     fn window_ptr(&self) -> *mut ffi::GLFWwindow { self.ptr }
2596 }
2597 
2598 unsafe impl HasRawWindowHandle for Window {
raw_window_handle(&self) -> RawWindowHandle2599     fn raw_window_handle(&self) -> RawWindowHandle {
2600         raw_window_handle(self)
2601     }
2602 }
2603 
2604 unsafe impl HasRawWindowHandle for RenderContext {
raw_window_handle(&self) -> RawWindowHandle2605     fn raw_window_handle(&self) -> RawWindowHandle {
2606         raw_window_handle(self)
2607     }
2608 }
2609 
raw_window_handle<C: Context>(context: &C) -> RawWindowHandle2610 fn raw_window_handle<C: Context>(context: &C) -> RawWindowHandle {
2611     #[cfg(target_family = "windows")]
2612     {
2613         use raw_window_handle::windows::WindowsHandle;
2614         let hwnd = unsafe {
2615             ffi::glfwGetWin32Window(context.window_ptr())
2616         };
2617         RawWindowHandle::Windows(WindowsHandle {
2618             hwnd,
2619             ..WindowsHandle::empty()
2620         })
2621     }
2622 
2623     #[cfg(any(target_os="linux", target_os="freebsd", target_os="dragonfly"))]
2624     {
2625         use raw_window_handle::unix::XlibHandle;
2626         let (window, display) = unsafe {
2627             let window = ffi::glfwGetX11Window(context.window_ptr());
2628             let display = ffi::glfwGetX11Display();
2629             (window as std::os::raw::c_ulong, display)
2630         };
2631         RawWindowHandle::Xlib(XlibHandle {
2632             window,
2633             display,
2634             ..XlibHandle::empty()
2635         })
2636     }
2637 
2638     #[cfg(target_os="macos")]
2639     {
2640         use raw_window_handle::macos::MacOSHandle;
2641         let (ns_window, ns_view) = unsafe {
2642             let ns_window: *mut objc::runtime::Object = ffi::glfwGetCocoaWindow(context.window_ptr()) as *mut _;
2643             let ns_view: *mut objc::runtime::Object = objc::msg_send![ns_window, contentView];
2644             assert_ne!(ns_view, std::ptr::null_mut());
2645             (ns_window as *mut std::ffi::c_void, ns_view as *mut std::ffi::c_void)
2646         };
2647         RawWindowHandle::MacOS(MacOSHandle {
2648             ns_window,
2649             ns_view,
2650             ..MacOSHandle::empty()
2651         })
2652     }
2653 }
2654 
2655 /// Wrapper for `glfwMakeContextCurrent`.
make_context_current(context: Option<&dyn Context>)2656 pub fn make_context_current(context: Option<&dyn Context>) {
2657     match context {
2658         Some(ctx) => unsafe { ffi::glfwMakeContextCurrent(ctx.window_ptr()) },
2659         None      => unsafe { ffi::glfwMakeContextCurrent(ptr::null_mut()) },
2660     }
2661 }
2662 
2663 /// Joystick identifier tokens.
2664 #[repr(i32)]
2665 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2666 pub enum JoystickId {
2667     Joystick1       = ffi::JOYSTICK_1,
2668     Joystick2       = ffi::JOYSTICK_2,
2669     Joystick3       = ffi::JOYSTICK_3,
2670     Joystick4       = ffi::JOYSTICK_4,
2671     Joystick5       = ffi::JOYSTICK_5,
2672     Joystick6       = ffi::JOYSTICK_6,
2673     Joystick7       = ffi::JOYSTICK_7,
2674     Joystick8       = ffi::JOYSTICK_8,
2675     Joystick9       = ffi::JOYSTICK_9,
2676     Joystick10      = ffi::JOYSTICK_10,
2677     Joystick11      = ffi::JOYSTICK_11,
2678     Joystick12      = ffi::JOYSTICK_12,
2679     Joystick13      = ffi::JOYSTICK_13,
2680     Joystick14      = ffi::JOYSTICK_14,
2681     Joystick15      = ffi::JOYSTICK_15,
2682     Joystick16      = ffi::JOYSTICK_16,
2683 }
2684 
2685 impl JoystickId {
2686     /// Converts from `i32`.
from_i32(n: i32) -> Option<JoystickId>2687     pub fn from_i32(n: i32) -> Option<JoystickId> {
2688         if n >= 0 && n <= ffi::JOYSTICK_LAST {
2689             Some(unsafe { mem::transmute(n) })
2690         } else {
2691             None
2692         }
2693     }
2694 }
2695 
2696 /// Button identifier tokens.
2697 #[repr(i32)]
2698 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2699 pub enum GamepadButton {
2700     ButtonA           = ffi::GAMEPAD_BUTTON_A,
2701     ButtonB           = ffi::GAMEPAD_BUTTON_B,
2702     ButtonX           = ffi::GAMEPAD_BUTTON_X,
2703     ButtonY           = ffi::GAMEPAD_BUTTON_Y,
2704     ButtonLeftBumper  = ffi::GAMEPAD_BUTTON_LEFT_BUMPER,
2705     ButtonRightBumper = ffi::GAMEPAD_BUTTON_RIGHT_BUMPER,
2706     ButtonBack        = ffi::GAMEPAD_BUTTON_BACK,
2707     ButtonStart       = ffi::GAMEPAD_BUTTON_START,
2708     ButtonGuide       = ffi::GAMEPAD_BUTTON_GUIDE,
2709     ButtonLeftThumb   = ffi::GAMEPAD_BUTTON_LEFT_THUMB,
2710     ButtonRightThumb  = ffi::GAMEPAD_BUTTON_RIGHT_THUMB,
2711     ButtonDpadUp      = ffi::GAMEPAD_BUTTON_DPAD_UP,
2712     ButtonDpadRight   = ffi::GAMEPAD_BUTTON_DPAD_RIGHT,
2713     ButtonDpadDown    = ffi::GAMEPAD_BUTTON_DPAD_DOWN,
2714     ButtonDpadLeft    = ffi::GAMEPAD_BUTTON_DPAD_LEFT,
2715 }
2716 
2717 impl GamepadButton {
2718     /// Converts from `i32`.
from_i32(n: i32) -> Option<GamepadButton>2719     pub fn from_i32(n: i32) -> Option<GamepadButton> {
2720         if n >= 0 && n <= ffi::GAMEPAD_BUTTON_LAST {
2721             Some(unsafe { mem::transmute(n) })
2722         } else {
2723             None
2724         }
2725     }
2726 }
2727 
2728 /// Axis identifier tokens.
2729 #[repr(i32)]
2730 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2731 pub enum GamepadAxis {
2732     AxisLeftX        = ffi::GAMEPAD_AXIS_LEFT_X,
2733     AxisLeftY        = ffi::GAMEPAD_AXIS_LEFT_Y,
2734     AxisRightX       = ffi::GAMEPAD_AXIS_RIGHT_X,
2735     AxisRightY       = ffi::GAMEPAD_AXIS_RIGHT_Y,
2736     AxisLeftTrigger  = ffi::GAMEPAD_AXIS_LEFT_TRIGGER,
2737     AxisRightTrigger = ffi::GAMEPAD_AXIS_RIGHT_TRIGGER,
2738 }
2739 
2740 impl GamepadAxis {
2741     /// Converts from `i32`.
from_i32(n: i32) -> Option<GamepadAxis>2742     pub fn from_i32(n: i32) -> Option<GamepadAxis> {
2743         if n >= 0 && n <= ffi::GAMEPAD_AXIS_LAST {
2744             Some(unsafe { mem::transmute(n) })
2745         } else {
2746             None
2747         }
2748     }
2749 }
2750 
2751 bitflags! {
2752     #[doc = "Joystick hats."]
2753     pub struct JoystickHats: ::libc::c_int {
2754         const Centered = ::ffi::HAT_CENTERED;
2755         const Up       = ::ffi::HAT_UP;
2756         const Right    = ::ffi::HAT_RIGHT;
2757         const Down     = ::ffi::HAT_DOWN;
2758         const Left     = ::ffi::HAT_LEFT;
2759     }
2760 }
2761 
2762 /// A joystick handle.
2763 #[derive(Clone)]
2764 pub struct Joystick {
2765     pub id: JoystickId,
2766     pub glfw: Glfw,
2767 }
2768 
2769 /// State of a gamepad.
2770 pub struct GamepadState {
2771     buttons: [Action; (ffi::GAMEPAD_BUTTON_LAST + 1) as usize],
2772     axes: [f32; (ffi::GAMEPAD_AXIS_LAST + 1) as usize],
2773 }
2774 
2775 /// Joystick events.
2776 #[repr(i32)]
2777 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
2778 pub enum JoystickEvent {
2779     Connected                   = ffi::CONNECTED,
2780     Disconnected                = ffi::DISCONNECTED,
2781 }
2782 
2783 /// An joystick callback. This can be supplied with some user data to be passed
2784 /// to the callback function when it is triggered.
2785 pub type JoystickCallback<UserData> = Callback<fn(JoystickId, JoystickEvent, &UserData), UserData>;
2786 
2787 impl Joystick {
2788     /// Wrapper for `glfwJoystickPresent`.
is_present(&self) -> bool2789     pub fn is_present(&self) -> bool {
2790         unsafe { ffi::glfwJoystickPresent(self.id as c_int) == ffi::TRUE }
2791     }
2792 
2793     /// Wrapper for `glfwGetJoystickAxes`.
get_axes(&self) -> Vec<f32>2794     pub fn get_axes(&self) -> Vec<f32> {
2795         unsafe {
2796             let mut count = 0;
2797             let ptr = ffi::glfwGetJoystickAxes(self.id as c_int, &mut count);
2798             slice::from_raw_parts(ptr, count as usize).iter().map(|&a| a as f32).collect()
2799         }
2800     }
2801 
2802     /// Wrapper for `glfwGetJoystickButtons`.
get_buttons(&self) -> Vec<c_int>2803     pub fn get_buttons(&self) -> Vec<c_int> {
2804         unsafe {
2805             let mut count = 0;
2806             let ptr = ffi::glfwGetJoystickButtons(self.id as c_int, &mut count);
2807             slice::from_raw_parts(ptr, count as usize).iter().map(|&b| b as c_int).collect()
2808         }
2809     }
2810 
2811     /// Wrapper for `glfwGetJoystickHats`.
get_hats(&self) -> Vec<JoystickHats>2812     pub fn get_hats(&self) -> Vec<JoystickHats> {
2813         unsafe {
2814             let mut count = 0;
2815             let ptr = ffi::glfwGetJoystickHats(self.id as c_int, &mut count);
2816             slice::from_raw_parts(ptr, count as usize).iter().map(|&b| mem::transmute(b as c_int)).collect()
2817         }
2818     }
2819 
2820     /// Wrapper for `glfwGetJoystickName`.
get_name(&self) -> Option<String>2821     pub fn get_name(&self) -> Option<String> {
2822         unsafe { string_from_nullable_c_str(ffi::glfwGetJoystickName(self.id as c_int)) }
2823     }
2824 
2825     /// Wrapper for `glfwGetJoystickGUID`.
get_guid(&self) -> Option<String>2826     pub fn get_guid(&self) -> Option<String> {
2827         unsafe { string_from_nullable_c_str(ffi::glfwGetJoystickGUID(self.id as c_int)) }
2828     }
2829 
2830     /// Wrapper for `glfwJoystickIsGamepad`.
is_gamepad(&self) -> bool2831     pub fn is_gamepad(&self) -> bool {
2832         unsafe { ffi::glfwJoystickIsGamepad(self.id as c_int) == ffi::TRUE }
2833     }
2834 
2835     /// Wrapper for `glfwGetGamepadName`.
get_gamepad_name(&self) -> Option<String>2836     pub fn get_gamepad_name(&self) -> Option<String> {
2837         unsafe { string_from_nullable_c_str(ffi::glfwGetGamepadName(self.id as c_int)) }
2838     }
2839 
2840     /// Wrapper for `glfwGetGamepadState`.
get_gamepad_state(&self) -> Option<GamepadState>2841     pub fn get_gamepad_state(&self) -> Option<GamepadState> {
2842         unsafe {
2843             let mut state = ffi::GLFWgamepadstate {
2844                 buttons: [0; (ffi::GAMEPAD_BUTTON_LAST + 1) as usize],
2845                 axes: [0_f32; (ffi::GAMEPAD_AXIS_LAST + 1) as usize],
2846             };
2847             if ffi::glfwGetGamepadState(self.id as c_int, &mut state) == ffi::TRUE {
2848                 Some(state.into())
2849             } else {
2850                 None
2851             }
2852         }
2853     }
2854 }
2855 
2856 impl From<ffi::GLFWgamepadstate> for GamepadState {
from(state: ffi::GLFWgamepadstate) -> Self2857     fn from(state: ffi::GLFWgamepadstate) -> Self {
2858         let mut buttons = [Action::Release; (ffi::GAMEPAD_BUTTON_LAST + 1) as usize];
2859         let mut axes = [0_f32; (ffi::GAMEPAD_AXIS_LAST + 1) as usize];
2860         unsafe {
2861             state.buttons.iter().map(|&b| mem::transmute(b as c_int))
2862                 .zip(buttons.iter_mut()).for_each(|(a, b)| *b = a);
2863         }
2864         state.axes.iter().map(|&f| f as f32)
2865             .zip(axes.iter_mut()).for_each(|(a, b)| *b = a);
2866         Self {
2867             buttons,
2868             axes,
2869         }
2870     }
2871 }
2872 
2873 impl GamepadState {
get_button_state(&self, button: GamepadButton) -> Action2874     pub fn get_button_state(&self, button: GamepadButton) -> Action {
2875         self.buttons[button as usize]
2876     }
2877 
get_axis(&self, axis: GamepadAxis) -> f322878     pub fn get_axis(&self, axis: GamepadAxis) -> f32 {
2879         self.axes[axis as usize]
2880     }
2881 }
2882