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}