glutin/
window.rs

1use std::collections::vec_deque::IntoIter as VecDequeIter;
2use std::default::Default;
3use std::path::PathBuf;
4
5use Api;
6use ContextError;
7use CreationError;
8use CursorState;
9use Event;
10use GlContext;
11use GlProfile;
12use GlRequest;
13use MouseCursor;
14use PixelFormat;
15use Robustness;
16use Window;
17use WindowID;
18use WindowBuilder;
19use native_monitor::NativeMonitorId;
20
21use libc;
22use platform;
23
24impl<'a> WindowBuilder<'a> {
25    /// Initializes a new `WindowBuilder` with default values.
26    #[inline]
27    pub fn new() -> WindowBuilder<'a> {
28        WindowBuilder {
29            pf_reqs: Default::default(),
30            window: Default::default(),
31            opengl: Default::default(),
32            platform_specific: Default::default(),
33        }
34    }
35
36    /// Requests the window to be of specific dimensions.
37    ///
38    /// Width and height are in pixels.
39    #[inline]
40    pub fn with_dimensions(mut self, width: u32, height: u32) -> WindowBuilder<'a> {
41        self.window.dimensions = Some((width, height));
42        self
43    }
44    
45    /// Sets a minimum dimension size for the window
46    ///
47    /// Width and height are in pixels.
48    #[inline]
49    pub fn with_min_dimensions(mut self, width: u32, height: u32) -> WindowBuilder<'a> {
50        self.window.min_dimensions = Some((width, height));
51        self
52    }
53
54    /// Sets a maximum dimension size for the window
55    ///
56    /// Width and height are in pixels.
57    #[inline]
58    pub fn with_max_dimensions(mut self, width: u32, height: u32) -> WindowBuilder<'a> {
59        self.window.max_dimensions = Some((width, height));
60        self
61    }
62
63    /// Requests a specific title for the window.
64    #[inline]
65    pub fn with_title<T: Into<String>>(mut self, title: T) -> WindowBuilder<'a> {
66        self.window.title = title.into();
67        self
68    }
69
70    /// Requests fullscreen mode.
71    ///
72    /// If you don't specify dimensions for the window, it will match the monitor's.
73    #[inline]
74    pub fn with_fullscreen(mut self, monitor: MonitorId) -> WindowBuilder<'a> {
75        let MonitorId(monitor) = monitor;
76        self.window.monitor = Some(monitor);
77        self
78    }
79
80    /// The created window will share all its OpenGL objects with the window in the parameter.
81    ///
82    /// There are some exceptions, like FBOs or VAOs. See the OpenGL documentation.
83    #[inline]
84    pub fn with_shared_lists(mut self, other: &'a Window) -> WindowBuilder<'a> {
85        self.opengl.sharing = Some(&other.window);
86        self
87    }
88
89    /// Sets how the backend should choose the OpenGL API and version.
90    #[inline]
91    pub fn with_gl(mut self, request: GlRequest) -> WindowBuilder<'a> {
92        self.opengl.version = request;
93        self
94    }
95
96    /// Sets the desired OpenGL context profile.
97    #[inline]
98    pub fn with_gl_profile(mut self, profile: GlProfile) -> WindowBuilder<'a> {
99        self.opengl.profile = Some(profile);
100        self
101    }
102
103    /// Sets the *debug* flag for the OpenGL context.
104    ///
105    /// The default value for this flag is `cfg!(debug_assertions)`, which means that it's enabled
106    /// when you run `cargo build` and disabled when you run `cargo build --release`.
107    #[inline]
108    pub fn with_gl_debug_flag(mut self, flag: bool) -> WindowBuilder<'a> {
109        self.opengl.debug = flag;
110        self
111    }
112
113    /// Sets the robustness of the OpenGL context. See the docs of `Robustness`.
114    #[inline]
115    pub fn with_gl_robustness(mut self, robustness: Robustness) -> WindowBuilder<'a> {
116        self.opengl.robustness = robustness;
117        self
118    }
119
120    /// Requests that the window has vsync enabled.
121    #[inline]
122    pub fn with_vsync(mut self) -> WindowBuilder<'a> {
123        self.opengl.vsync = true;
124        self
125    }
126
127    /// Sets whether the window will be initially hidden or visible.
128    #[inline]
129    pub fn with_visibility(mut self, visible: bool) -> WindowBuilder<'a> {
130        self.window.visible = visible;
131        self
132    }
133
134    /// Sets the multisampling level to request.
135    ///
136    /// # Panic
137    ///
138    /// Will panic if `samples` is not a power of two.
139    #[inline]
140    pub fn with_multisampling(mut self, samples: u16) -> WindowBuilder<'a> {
141        assert!(samples.is_power_of_two());
142        self.pf_reqs.multisampling = Some(samples);
143        self
144    }
145
146    /// Sets the number of bits in the depth buffer.
147    #[inline]
148    pub fn with_depth_buffer(mut self, bits: u8) -> WindowBuilder<'a> {
149        self.pf_reqs.depth_bits = Some(bits);
150        self
151    }
152
153    /// Sets the number of bits in the stencil buffer.
154    #[inline]
155    pub fn with_stencil_buffer(mut self, bits: u8) -> WindowBuilder<'a> {
156        self.pf_reqs.stencil_bits = Some(bits);
157        self
158    }
159
160    /// Sets the number of bits in the color buffer.
161    #[inline]
162    pub fn with_pixel_format(mut self, color_bits: u8, alpha_bits: u8) -> WindowBuilder<'a> {
163        self.pf_reqs.color_bits = Some(color_bits);
164        self.pf_reqs.alpha_bits = Some(alpha_bits);
165        self
166    }
167
168    /// Request the backend to be stereoscopic.
169    #[inline]
170    pub fn with_stereoscopy(mut self) -> WindowBuilder<'a> {
171        self.pf_reqs.stereoscopy = true;
172        self
173    }
174
175    /// Sets whether sRGB should be enabled on the window. `None` means "I don't care".
176    #[inline]
177    pub fn with_srgb(mut self, srgb_enabled: Option<bool>) -> WindowBuilder<'a> {
178        self.pf_reqs.srgb = srgb_enabled.unwrap_or(false);
179        self
180    }
181
182    /// Sets whether the background of the window should be transparent.
183    #[inline]
184    pub fn with_transparency(mut self, transparent: bool) -> WindowBuilder<'a> {
185        self.window.transparent = transparent;
186        self
187    }
188
189    /// Sets whether the window should have a border, a title bar, etc.
190    #[inline]
191    pub fn with_decorations(mut self, decorations: bool) -> WindowBuilder<'a> {
192        self.window.decorations = decorations;
193        self
194    }
195
196    /// Enables multitouch
197    #[inline]
198    pub fn with_multitouch(mut self) -> WindowBuilder<'a> {
199        self.window.multitouch = true;
200        self
201    }
202
203    /// Sets the icon for the window. The supplied path must reference a PNG file.
204    #[inline]
205    pub fn with_icon(mut self, icon_path: PathBuf) -> WindowBuilder<'a> {
206        self.window.icon = Some(icon_path);
207        self
208    }
209
210    /// Sets the parent window
211    pub fn with_parent(mut self, parent: Option<WindowID>) -> WindowBuilder<'a> {
212        self.window.parent = parent;
213        self
214    }
215
216    /// Builds the window.
217    ///
218    /// Error should be very rare and only occur in case of permission denied, incompatible system,
219    /// out of memory, etc.
220    pub fn build(mut self) -> Result<Window, CreationError> {
221        // resizing the window to the dimensions of the monitor when fullscreen
222        if self.window.dimensions.is_none() && self.window.monitor.is_some() {
223            self.window.dimensions = Some(self.window.monitor.as_ref().unwrap().get_dimensions())
224        }
225
226        // default dimensions
227        if self.window.dimensions.is_none() {
228            self.window.dimensions = Some((1024, 768));
229        }
230
231        // building
232        platform::Window::new(&self.window, &self.pf_reqs, &self.opengl, &self.platform_specific)
233                            .map(|w| Window { window: w })
234    }
235
236    /// Builds the window.
237    ///
238    /// The context is build in a *strict* way. That means that if the backend couldn't give
239    /// you what you requested, an `Err` will be returned.
240    #[inline]
241    pub fn build_strict(self) -> Result<Window, CreationError> {
242        self.build()
243    }
244}
245
246
247impl Default for Window {
248    #[inline]
249    fn default() -> Window {
250        Window::new().unwrap()
251    }
252}
253
254impl Window {
255    /// Creates a new OpenGL context, and a Window for platforms where this is appropriate.
256    ///
257    /// This function is equivalent to `WindowBuilder::new().build()`.
258    ///
259    /// Error should be very rare and only occur in case of permission denied, incompatible system,
260    ///  out of memory, etc.
261    #[inline]
262    pub fn new() -> Result<Window, CreationError> {
263        let builder = WindowBuilder::new();
264        builder.build()
265    }
266
267    /// Modifies the title of the window.
268    ///
269    /// This is a no-op if the window has already been closed.
270    #[inline]
271    pub fn set_title(&self, title: &str) {
272        self.window.set_title(title)
273    }
274
275    /// Shows the window if it was hidden.
276    ///
277    /// ## Platform-specific
278    ///
279    /// - Has no effect on Android
280    ///
281    #[inline]
282    pub fn show(&self) {
283        self.window.show()
284    }
285
286    /// Hides the window if it was visible.
287    ///
288    /// ## Platform-specific
289    ///
290    /// - Has no effect on Android
291    ///
292    #[inline]
293    pub fn hide(&self) {
294        self.window.hide()
295    }
296
297    /// Returns the position of the top-left hand corner of the window relative to the
298    ///  top-left hand corner of the desktop.
299    ///
300    /// Note that the top-left hand corner of the desktop is not necessarily the same as
301    ///  the screen. If the user uses a desktop with multiple monitors, the top-left hand corner
302    ///  of the desktop is the top-left hand corner of the monitor at the top-left of the desktop.
303    ///
304    /// The coordinates can be negative if the top-left hand corner of the window is outside
305    ///  of the visible screen region.
306    ///
307    /// Returns `None` if the window no longer exists.
308    #[inline]
309    pub fn get_position(&self) -> Option<(i32, i32)> {
310        self.window.get_position()
311    }
312
313    /// Modifies the position of the window.
314    ///
315    /// See `get_position` for more informations about the coordinates.
316    ///
317    /// This is a no-op if the window has already been closed.
318    #[inline]
319    pub fn set_position(&self, x: i32, y: i32) {
320        self.window.set_position(x, y)
321    }
322
323    /// Returns the size in points of the client area of the window.
324    ///
325    /// The client area is the content of the window, excluding the title bar and borders.
326    /// To get the dimensions of the frame buffer when calling `glViewport`, multiply with hidpi factor.
327    ///
328    /// Returns `None` if the window no longer exists.
329    ///
330    /// DEPRECATED
331    #[inline]
332    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
333        self.window.get_inner_size()
334    }
335    
336    /// Returns the size in points of the client area of the window.
337    ///
338    /// The client area is the content of the window, excluding the title bar and borders.
339    /// To get the dimensions of the frame buffer when calling `glViewport`, multiply with hidpi factor.
340    ///
341    /// Returns `None` if the window no longer exists.
342    #[inline]
343    pub fn get_inner_size_points(&self) -> Option<(u32, u32)> {
344        self.window.get_inner_size()
345    }
346
347
348    /// Returns the size in pixels of the client area of the window.
349    ///
350    /// The client area is the content of the window, excluding the title bar and borders.
351    /// These are the dimensions of the frame buffer, and the dimensions that you should use
352    ///  when you call `glViewport`.
353    ///
354    /// Returns `None` if the window no longer exists.
355    #[inline]
356    pub fn get_inner_size_pixels(&self) -> Option<(u32, u32)> {
357        self.window.get_inner_size().map(|(x, y)| {
358            let hidpi = self.hidpi_factor();
359            ((x as f32 * hidpi) as u32, (y as f32 * hidpi) as u32)
360        })
361    }
362
363    /// Returns the size in pixels of the window.
364    ///
365    /// These dimensions include title bar and borders. If you don't want these, you should use
366    ///  use `get_inner_size` instead.
367    ///
368    /// Returns `None` if the window no longer exists.
369    #[inline]
370    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
371        self.window.get_outer_size()
372    }
373
374    /// Modifies the inner size of the window.
375    ///
376    /// See `get_inner_size` for more informations about the values.
377    ///
378    /// This is a no-op if the window has already been closed.
379    #[inline]
380    pub fn set_inner_size(&self, x: u32, y: u32) {
381        self.window.set_inner_size(x, y)
382    }
383
384    /// Returns an iterator that poll for the next event in the window's events queue.
385    /// Returns `None` if there is no event in the queue.
386    ///
387    /// Contrary to `wait_events`, this function never blocks.
388    #[inline]
389    pub fn poll_events(&self) -> PollEventsIterator {
390        PollEventsIterator(self.window.poll_events())
391    }
392
393    /// Returns an iterator that returns events one by one, blocking if necessary until one is
394    /// available.
395    ///
396    /// The iterator never returns `None`.
397    #[inline]
398    pub fn wait_events(&self) -> WaitEventsIterator {
399        WaitEventsIterator(self.window.wait_events())
400    }
401
402    /// Sets the context as the current context.
403    #[inline]
404    pub unsafe fn make_current(&self) -> Result<(), ContextError> {
405        self.window.make_current()
406    }
407
408    /// Returns true if this context is the current one in this thread.
409    #[inline]
410    pub fn is_current(&self) -> bool {
411        self.window.is_current()
412    }
413
414    /// Returns the address of an OpenGL function.
415    ///
416    /// Contrary to `wglGetProcAddress`, all available OpenGL functions return an address.
417    #[inline]
418    pub fn get_proc_address(&self, addr: &str) -> *const () {
419        self.window.get_proc_address(addr)
420    }
421
422    /// Swaps the buffers in case of double or triple buffering.
423    ///
424    /// You should call this function every time you have finished rendering, or the image
425    ///  may not be displayed on the screen.
426    ///
427    /// **Warning**: if you enabled vsync, this function will block until the next time the screen
428    /// is refreshed. However drivers can choose to override your vsync settings, which means that
429    /// you can't know in advance whether `swap_buffers` will block or not.
430    #[inline]
431    pub fn swap_buffers(&self) -> Result<(), ContextError> {
432        self.window.swap_buffers()
433    }
434
435    /// DEPRECATED. Gets the native platform specific display for this window.
436    /// This is typically only required when integrating with
437    /// other libraries that need this information.
438    #[inline]
439    pub unsafe fn platform_display(&self) -> *mut libc::c_void {
440        self.window.platform_display()
441    }
442
443    /// DEPRECATED. Gets the native platform specific window handle. This is
444    /// typically only required when integrating with other libraries
445    /// that need this information.
446    #[inline]
447    pub unsafe fn platform_window(&self) -> *mut libc::c_void {
448        self.window.platform_window()
449    }
450
451    /// Returns the API that is currently provided by this window.
452    ///
453    /// - On Windows and OS/X, this always returns `OpenGl`.
454    /// - On Android, this always returns `OpenGlEs`.
455    /// - On Linux, it must be checked at runtime.
456    #[inline]
457    pub fn get_api(&self) -> Api {
458        self.window.get_api()
459    }
460
461    /// Returns the pixel format of this window.
462    #[inline]
463    pub fn get_pixel_format(&self) -> PixelFormat {
464        self.window.get_pixel_format()
465    }
466
467    /// Create a window proxy for this window, that can be freely
468    /// passed to different threads.
469    #[inline]
470    pub fn create_window_proxy(&self) -> WindowProxy {
471        WindowProxy {
472            proxy: self.window.create_window_proxy()
473        }
474    }
475
476    /// Sets a resize callback that is called by Mac (and potentially other
477    /// operating systems) during resize operations. This can be used to repaint
478    /// during window resizing.
479    #[inline]
480    pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
481        self.window.set_window_resize_callback(callback);
482    }
483
484    /// Modifies the mouse cursor of the window.
485    /// Has no effect on Android.
486    pub fn set_cursor(&self, cursor: MouseCursor) {
487        self.window.set_cursor(cursor);
488    }
489
490    /// Returns the ratio between the backing framebuffer resolution and the
491    /// window size in screen pixels. This is typically one for a normal display
492    /// and two for a retina display.
493    #[inline]
494    pub fn hidpi_factor(&self) -> f32 {
495        self.window.hidpi_factor()
496    }
497
498    /// Changes the position of the cursor in window coordinates.
499    #[inline]
500    pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
501        self.window.set_cursor_position(x, y)
502    }
503
504    /// Sets how glutin handles the cursor. See the documentation of `CursorState` for details.
505    ///
506    /// Has no effect on Android.
507    #[inline]
508    pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
509        self.window.set_cursor_state(state)
510    }
511}
512
513impl GlContext for Window {
514    #[inline]
515    unsafe fn make_current(&self) -> Result<(), ContextError> {
516        self.make_current()
517    }
518
519    #[inline]
520    fn is_current(&self) -> bool {
521        self.is_current()
522    }
523
524    #[inline]
525    fn get_proc_address(&self, addr: &str) -> *const () {
526        self.get_proc_address(addr)
527    }
528
529    #[inline]
530    fn swap_buffers(&self) -> Result<(), ContextError> {
531        self.swap_buffers()
532    }
533
534    #[inline]
535    fn get_api(&self) -> Api {
536        self.get_api()
537    }
538
539    #[inline]
540    fn get_pixel_format(&self) -> PixelFormat {
541        self.get_pixel_format()
542    }
543}
544
545/// Represents a thread safe subset of operations that can be called
546/// on a window. This structure can be safely cloned and sent between
547/// threads.
548#[derive(Clone)]
549pub struct WindowProxy {
550    proxy: platform::WindowProxy,
551}
552
553impl WindowProxy {
554    /// Triggers a blocked event loop to wake up. This is
555    /// typically called when another thread wants to wake
556    /// up the blocked rendering thread to cause a refresh.
557    #[inline]
558    pub fn wakeup_event_loop(&self) {
559        self.proxy.wakeup_event_loop();
560    }
561}
562/// An iterator for the `poll_events` function.
563pub struct PollEventsIterator<'a>(platform::PollEventsIterator<'a>);
564
565impl<'a> Iterator for PollEventsIterator<'a> {
566    type Item = Event;
567
568    #[inline]
569    fn next(&mut self) -> Option<Event> {
570        self.0.next()
571    }
572
573    #[inline]
574    fn size_hint(&self) -> (usize, Option<usize>) {
575        self.0.size_hint()
576    }
577}
578
579/// An iterator for the `wait_events` function.
580pub struct WaitEventsIterator<'a>(platform::WaitEventsIterator<'a>);
581
582impl<'a> Iterator for WaitEventsIterator<'a> {
583    type Item = Event;
584
585    #[inline]
586    fn next(&mut self) -> Option<Event> {
587        self.0.next()
588    }
589
590    #[inline]
591    fn size_hint(&self) -> (usize, Option<usize>) {
592        self.0.size_hint()
593    }
594}
595
596/// An iterator for the list of available monitors.
597// Implementation note: we retreive the list once, then serve each element by one by one.
598// This may change in the future.
599pub struct AvailableMonitorsIter {
600    data: VecDequeIter<platform::MonitorId>,
601}
602
603impl Iterator for AvailableMonitorsIter {
604    type Item = MonitorId;
605
606    #[inline]
607    fn next(&mut self) -> Option<MonitorId> {
608        self.data.next().map(|id| MonitorId(id))
609    }
610
611    #[inline]
612    fn size_hint(&self) -> (usize, Option<usize>) {
613        self.data.size_hint()
614    }
615}
616
617/// Returns the list of all available monitors.
618#[inline]
619pub fn get_available_monitors() -> AvailableMonitorsIter {
620    let data = platform::get_available_monitors();
621    AvailableMonitorsIter{ data: data.into_iter() }
622}
623
624/// Returns the primary monitor of the system.
625#[inline]
626pub fn get_primary_monitor() -> MonitorId {
627    MonitorId(platform::get_primary_monitor())
628}
629
630/// Identifier for a monitor.
631pub struct MonitorId(platform::MonitorId);
632
633impl MonitorId {
634    /// Returns a human-readable name of the monitor.
635    #[inline]
636    pub fn get_name(&self) -> Option<String> {
637        let &MonitorId(ref id) = self;
638        id.get_name()
639    }
640
641    /// Returns the native platform identifier for this monitor.
642    #[inline]
643    pub fn get_native_identifier(&self) -> NativeMonitorId {
644        let &MonitorId(ref id) = self;
645        id.get_native_identifier()
646    }
647
648    /// Returns the number of pixels currently displayed on the monitor.
649    #[inline]
650    pub fn get_dimensions(&self) -> (u32, u32) {
651        let &MonitorId(ref id) = self;
652        id.get_dimensions()
653    }
654}