speedy2d/
window.rs

1/*
2 *  Copyright 2021 QuantumBadger
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
17use std::fmt::{Display, Formatter};
18use std::marker::PhantomData;
19
20use crate::dimen::{IVec2, UVec2, Vec2};
21use crate::error::{BacktraceError, ErrorMessage};
22use crate::{GLRenderer, Graphics2D};
23
24#[cfg(all(not(target_arch = "wasm32"), not(any(doc, doctest))))]
25type WindowHelperInnerType<UserEventType> =
26    crate::window_internal_glutin::WindowHelperGlutin<UserEventType>;
27
28#[cfg(all(not(target_arch = "wasm32"), not(any(doc, doctest))))]
29type UserEventSenderInnerType<UserEventType> =
30    crate::window_internal_glutin::UserEventSenderGlutin<UserEventType>;
31
32#[cfg(all(target_arch = "wasm32", not(any(doc, doctest))))]
33type WindowHelperInnerType<UserEventType> =
34    crate::window_internal_web::WindowHelperWeb<UserEventType>;
35
36#[cfg(all(target_arch = "wasm32", not(any(doc, doctest))))]
37type UserEventSenderInnerType<UserEventType> =
38    crate::window_internal_web::UserEventSenderWeb<UserEventType>;
39
40#[cfg(any(doc, doctest))]
41type WindowHelperInnerType<UserEventType> = PhantomData<UserEventType>;
42
43#[cfg(any(doc, doctest))]
44type UserEventSenderInnerType<UserEventType> = PhantomData<UserEventType>;
45
46/// Error occurring when sending a user event.
47#[derive(Clone, Debug, Hash, Eq, PartialEq, Copy)]
48pub enum EventLoopSendError
49{
50    /// Send failed as the event loop no longer exists.
51    EventLoopNoLongerExists
52}
53
54/// Allows user events to be sent to the event loop from other threads.
55pub struct UserEventSender<UserEventType: 'static>
56{
57    inner: UserEventSenderInnerType<UserEventType>
58}
59
60impl<UserEventType> Clone for UserEventSender<UserEventType>
61{
62    fn clone(&self) -> Self
63    {
64        UserEventSender {
65            inner: self.inner.clone()
66        }
67    }
68}
69
70impl<UserEventType> UserEventSender<UserEventType>
71{
72    pub(crate) fn new(inner: UserEventSenderInnerType<UserEventType>) -> Self
73    {
74        Self { inner }
75    }
76
77    /// Sends a user-defined event to the event loop. This will cause
78    /// [WindowHandler::on_user_event] to be invoked on the event loop
79    /// thread.
80    ///
81    /// This may be invoked from a different thread to the one running the event
82    /// loop.
83    #[inline]
84    pub fn send_event(&self, event: UserEventType) -> Result<(), EventLoopSendError>
85    {
86        self.inner.send_event(event)
87    }
88}
89
90/// Error occurring when creating a window.
91#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
92#[non_exhaustive]
93pub enum WindowCreationError
94{
95    /// Could not find the primary monitor.
96    PrimaryMonitorNotFound,
97    /// Could not find a suitable graphics context. Speedy2D attempts to find
98    /// the best possible context configuration by trying multiple options for
99    /// vsync and multisampling.
100    SuitableContextNotFound,
101    /// Failed to make the graphics context current.
102    MakeContextCurrentFailed,
103    /// Failed to instantiate the renderer.
104    RendererCreationFailed,
105    /// Failed to instantiate the main window event loop.
106    EventLoopCreationFailed
107}
108
109impl Display for WindowCreationError
110{
111    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result
112    {
113        f.write_str(match self {
114            WindowCreationError::PrimaryMonitorNotFound => "Primary monitor not found",
115            WindowCreationError::SuitableContextNotFound => {
116                "Could not find a suitable graphics context"
117            }
118            WindowCreationError::MakeContextCurrentFailed => {
119                "Failed to make the graphics context current"
120            }
121            WindowCreationError::RendererCreationFailed => {
122                "Failed to create the renderer"
123            }
124            WindowCreationError::EventLoopCreationFailed => {
125                "Failed to instantiate the main window event loop"
126            }
127        })
128    }
129}
130
131/// A set of callbacks for an active window. If a callback is not implemented,
132/// it will do nothing by default, so it is only necessary to implement the
133/// callbacks you actually need.
134pub trait WindowHandler<UserEventType = ()>
135{
136    /// Invoked once when the window first starts.
137    #[allow(unused_variables)]
138    #[inline]
139    fn on_start(
140        &mut self,
141        helper: &mut WindowHelper<UserEventType>,
142        info: WindowStartupInfo
143    )
144    {
145    }
146
147    /// Invoked when a user-defined event is received, allowing you to wake up
148    /// the event loop to handle events from other threads.
149    ///
150    /// See [WindowHelper::create_user_event_sender].
151    #[allow(unused_variables)]
152    #[inline]
153    fn on_user_event(
154        &mut self,
155        helper: &mut WindowHelper<UserEventType>,
156        user_event: UserEventType
157    )
158    {
159    }
160
161    /// Invoked when the window is resized.
162    #[allow(unused_variables)]
163    #[inline]
164    fn on_resize(&mut self, helper: &mut WindowHelper<UserEventType>, size_pixels: UVec2)
165    {
166    }
167
168    /// Invoked if the mouse cursor becomes grabbed or un-grabbed. See
169    /// [WindowHelper::set_cursor_grab].
170    ///
171    /// Note: mouse movement events will behave differently depending on the
172    /// current cursor grabbing status.
173    #[allow(unused_variables)]
174    #[inline]
175    fn on_mouse_grab_status_changed(
176        &mut self,
177        helper: &mut WindowHelper<UserEventType>,
178        mouse_grabbed: bool
179    )
180    {
181    }
182
183    /// Invoked if the window enters or exits fullscreen mode. See
184    /// [WindowHelper::set_fullscreen_mode].
185    #[allow(unused_variables)]
186    #[inline]
187    fn on_fullscreen_status_changed(
188        &mut self,
189        helper: &mut WindowHelper<UserEventType>,
190        fullscreen: bool
191    )
192    {
193    }
194
195    /// Invoked when the window scale factor changes.
196    #[allow(unused_variables)]
197    #[inline]
198    fn on_scale_factor_changed(
199        &mut self,
200        helper: &mut WindowHelper<UserEventType>,
201        scale_factor: f64
202    )
203    {
204    }
205
206    /// Invoked when the contents of the window needs to be redrawn.
207    ///
208    /// It is possible to request a redraw from any callback using
209    /// [WindowHelper::request_redraw].
210    #[allow(unused_variables)]
211    #[inline]
212    fn on_draw(
213        &mut self,
214        helper: &mut WindowHelper<UserEventType>,
215        graphics: &mut Graphics2D
216    )
217    {
218    }
219
220    /// Invoked when the mouse changes position.
221    ///
222    /// Normally, this provides the absolute  position of the mouse in the
223    /// window/canvas. However, if the mouse cursor is grabbed, this will
224    /// instead provide the amount of relative movement since the last move
225    /// event.
226    ///
227    /// See [WindowHandler::on_mouse_grab_status_changed].
228    #[allow(unused_variables)]
229    #[inline]
230    fn on_mouse_move(&mut self, helper: &mut WindowHelper<UserEventType>, position: Vec2)
231    {
232    }
233
234    /// Invoked when a mouse button is pressed.
235    #[allow(unused_variables)]
236    #[inline]
237    fn on_mouse_button_down(
238        &mut self,
239        helper: &mut WindowHelper<UserEventType>,
240        button: MouseButton
241    )
242    {
243    }
244
245    /// Invoked when a mouse button is released.
246    #[allow(unused_variables)]
247    #[inline]
248    fn on_mouse_button_up(
249        &mut self,
250        helper: &mut WindowHelper<UserEventType>,
251        button: MouseButton
252    )
253    {
254    }
255
256    /// Invoked when the mouse wheel moves.
257    #[allow(unused_variables)]
258    #[inline]
259    fn on_mouse_wheel_scroll(
260        &mut self,
261        helper: &mut WindowHelper<UserEventType>,
262        distance: MouseScrollDistance
263    )
264    {
265    }
266
267    /// Invoked when a keyboard key is pressed.
268    ///
269    /// To detect when a character is typed, see the
270    /// [WindowHandler::on_keyboard_char] callback.
271    #[allow(unused_variables)]
272    #[inline]
273    fn on_key_down(
274        &mut self,
275        helper: &mut WindowHelper<UserEventType>,
276        virtual_key_code: Option<VirtualKeyCode>,
277        scancode: KeyScancode
278    )
279    {
280    }
281
282    /// Invoked when a keyboard key is released.
283    #[allow(unused_variables)]
284    #[inline]
285    fn on_key_up(
286        &mut self,
287        helper: &mut WindowHelper<UserEventType>,
288        virtual_key_code: Option<VirtualKeyCode>,
289        scancode: KeyScancode
290    )
291    {
292    }
293
294    /// Invoked when a character is typed on the keyboard.
295    ///
296    /// This is invoked in addition to the [WindowHandler::on_key_up] and
297    /// [WindowHandler::on_key_down] callbacks.
298    #[allow(unused_variables)]
299    #[inline]
300    fn on_keyboard_char(
301        &mut self,
302        helper: &mut WindowHelper<UserEventType>,
303        unicode_codepoint: char
304    )
305    {
306    }
307
308    /// Invoked when the state of the modifier keys has changed.
309    #[allow(unused_variables)]
310    #[inline]
311    fn on_keyboard_modifiers_changed(
312        &mut self,
313        helper: &mut WindowHelper<UserEventType>,
314        state: ModifiersState
315    )
316    {
317    }
318}
319
320pub(crate) struct DrawingWindowHandler<UserEventType, H>
321where
322    UserEventType: 'static,
323    H: WindowHandler<UserEventType>
324{
325    window_handler: H,
326    renderer: GLRenderer,
327    phantom: PhantomData<UserEventType>
328}
329
330impl<UserEventType, H> DrawingWindowHandler<UserEventType, H>
331where
332    H: WindowHandler<UserEventType>,
333    UserEventType: 'static
334{
335    pub fn new(window_handler: H, renderer: GLRenderer) -> Self
336    {
337        DrawingWindowHandler {
338            window_handler,
339            renderer,
340            phantom: PhantomData
341        }
342    }
343
344    #[inline]
345    pub fn on_start(
346        &mut self,
347        helper: &mut WindowHelper<UserEventType>,
348        info: WindowStartupInfo
349    )
350    {
351        self.window_handler.on_start(helper, info);
352    }
353
354    #[inline]
355    pub fn on_user_event(
356        &mut self,
357        helper: &mut WindowHelper<UserEventType>,
358        user_event: UserEventType
359    )
360    {
361        self.window_handler.on_user_event(helper, user_event)
362    }
363
364    #[inline]
365    pub fn on_resize(
366        &mut self,
367        helper: &mut WindowHelper<UserEventType>,
368        size_pixels: UVec2
369    )
370    {
371        self.renderer.set_viewport_size_pixels(size_pixels);
372        self.window_handler.on_resize(helper, size_pixels)
373    }
374
375    #[inline]
376    pub fn on_mouse_grab_status_changed(
377        &mut self,
378        helper: &mut WindowHelper<UserEventType>,
379        mouse_grabbed: bool
380    )
381    {
382        self.window_handler
383            .on_mouse_grab_status_changed(helper, mouse_grabbed)
384    }
385
386    #[inline]
387    pub fn on_fullscreen_status_changed(
388        &mut self,
389        helper: &mut WindowHelper<UserEventType>,
390        fullscreen: bool
391    )
392    {
393        self.window_handler
394            .on_fullscreen_status_changed(helper, fullscreen)
395    }
396
397    #[inline]
398    pub fn on_scale_factor_changed(
399        &mut self,
400        helper: &mut WindowHelper<UserEventType>,
401        scale_factor: f64
402    )
403    {
404        self.window_handler
405            .on_scale_factor_changed(helper, scale_factor)
406    }
407
408    #[inline]
409    pub fn on_draw(&mut self, helper: &mut WindowHelper<UserEventType>)
410    {
411        let renderer = &mut self.renderer;
412        let window_handler = &mut self.window_handler;
413
414        renderer.draw_frame(|graphics| window_handler.on_draw(helper, graphics))
415    }
416
417    #[inline]
418    pub fn on_mouse_move(
419        &mut self,
420        helper: &mut WindowHelper<UserEventType>,
421        position: Vec2
422    )
423    {
424        self.window_handler.on_mouse_move(helper, position)
425    }
426
427    #[inline]
428    pub fn on_mouse_button_down(
429        &mut self,
430        helper: &mut WindowHelper<UserEventType>,
431        button: MouseButton
432    )
433    {
434        self.window_handler.on_mouse_button_down(helper, button)
435    }
436
437    #[inline]
438    pub fn on_mouse_button_up(
439        &mut self,
440        helper: &mut WindowHelper<UserEventType>,
441        button: MouseButton
442    )
443    {
444        self.window_handler.on_mouse_button_up(helper, button)
445    }
446
447    #[inline]
448    pub fn on_mouse_wheel_scroll(
449        &mut self,
450        helper: &mut WindowHelper<UserEventType>,
451        distance: MouseScrollDistance
452    )
453    {
454        self.window_handler.on_mouse_wheel_scroll(helper, distance)
455    }
456
457    #[inline]
458    pub fn on_key_down(
459        &mut self,
460        helper: &mut WindowHelper<UserEventType>,
461        virtual_key_code: Option<VirtualKeyCode>,
462        scancode: KeyScancode
463    )
464    {
465        self.window_handler
466            .on_key_down(helper, virtual_key_code, scancode)
467    }
468
469    #[inline]
470    pub fn on_key_up(
471        &mut self,
472        helper: &mut WindowHelper<UserEventType>,
473        virtual_key_code: Option<VirtualKeyCode>,
474        scancode: KeyScancode
475    )
476    {
477        self.window_handler
478            .on_key_up(helper, virtual_key_code, scancode)
479    }
480
481    #[inline]
482    pub fn on_keyboard_char(
483        &mut self,
484        helper: &mut WindowHelper<UserEventType>,
485        unicode_codepoint: char
486    )
487    {
488        self.window_handler
489            .on_keyboard_char(helper, unicode_codepoint)
490    }
491
492    #[inline]
493    pub fn on_keyboard_modifiers_changed(
494        &mut self,
495        helper: &mut WindowHelper<UserEventType>,
496        state: ModifiersState
497    )
498    {
499        self.window_handler
500            .on_keyboard_modifiers_changed(helper, state)
501    }
502}
503
504/// A set of helper methods to perform actions on a [crate::Window].
505pub struct WindowHelper<UserEventType = ()>
506where
507    UserEventType: 'static
508{
509    inner: WindowHelperInnerType<UserEventType>
510}
511
512impl<UserEventType> WindowHelper<UserEventType>
513{
514    pub(crate) fn new(inner: WindowHelperInnerType<UserEventType>) -> Self
515    {
516        WindowHelper { inner }
517    }
518
519    #[inline]
520    #[must_use]
521    pub(crate) fn inner(&mut self) -> &mut WindowHelperInnerType<UserEventType>
522    {
523        &mut self.inner
524    }
525
526    /// Causes the event loop to stop processing events, and terminate the
527    /// application.
528    ///
529    /// Note: The event loop will stop only once the current callback has
530    /// returned, rather than terminating immediately.
531    ///
532    /// Once the event loop has stopped, the entire process will end with error
533    /// code 0, even if other threads are running.
534    ///
535    /// If your `WindowHandler` struct implements `Drop`, it will be safely
536    /// destructed before exiting.
537    ///
538    /// No further callbacks will be given once this function has been called.
539    pub fn terminate_loop(&mut self)
540    {
541        self.inner.terminate_loop()
542    }
543
544    /// Sets the window icon from the provided RGBA pixels.
545    ///
546    /// On Windows, the base icon size is 16x16, however a multiple of this
547    /// (e.g. 32x32) should be provided for high-resolution displays.
548    ///
549    /// For `WebCanvas`, this function has no effect.
550    pub fn set_icon_from_rgba_pixels<S>(
551        &self,
552        data: Vec<u8>,
553        size: S
554    ) -> Result<(), BacktraceError<ErrorMessage>>
555    where
556        S: Into<UVec2>
557    {
558        self.inner.set_icon_from_rgba_pixels(data, size.into())
559    }
560
561    /// Sets the visibility of the mouse cursor.
562    pub fn set_cursor_visible(&self, visible: bool)
563    {
564        self.inner.set_cursor_visible(visible)
565    }
566
567    /// Grabs the cursor, preventing it from leaving the window.
568    pub fn set_cursor_grab(
569        &self,
570        grabbed: bool
571    ) -> Result<(), BacktraceError<ErrorMessage>>
572    {
573        self.inner.set_cursor_grab(grabbed)
574    }
575
576    /// Set to false to prevent the user from resizing the window.
577    ///
578    /// For `WebCanvas`, this function has no effect.
579    pub fn set_resizable(&self, resizable: bool)
580    {
581        self.inner.set_resizable(resizable)
582    }
583
584    /// Request that the window is redrawn.
585    ///
586    /// This will cause the [WindowHandler::on_draw] callback to be invoked on
587    /// the next frame.
588    #[inline]
589    pub fn request_redraw(&self)
590    {
591        self.inner.request_redraw()
592    }
593
594    /// Sets the window title.
595    pub fn set_title<S: AsRef<str>>(&self, title: S)
596    {
597        self.inner.set_title(title.as_ref())
598    }
599
600    /// Sets the window fullscreen mode.
601    ///
602    /// When using a web canvas, permission for this operation may be denied,
603    /// depending on where this is called from, and the user's browser settings.
604    /// If the operation is successful, the
605    /// [WindowHandler::on_fullscreen_status_changed] callback will be invoked.
606    pub fn set_fullscreen_mode(&self, mode: WindowFullscreenMode)
607    {
608        self.inner.set_fullscreen_mode(mode)
609    }
610
611    /// Sets the window size in pixels. This is the window's inner size,
612    /// excluding the border.
613    ///
614    /// For `WebCanvas`, this function has no effect.
615    pub fn set_size_pixels<S: Into<UVec2>>(&self, size: S)
616    {
617        self.inner.set_size_pixels(size)
618    }
619
620    /// Gets the window size in pixels.
621    pub fn get_size_pixels(&self) -> UVec2
622    {
623        self.inner.get_size_pixels()
624    }
625
626    /// Sets the position of the window in pixels. If multiple monitors are in
627    /// use, this will be the distance from the top left of the display
628    /// area, spanning all the monitors.
629    ///
630    /// For `WebCanvas`, this function has no effect.
631    pub fn set_position_pixels<P: Into<IVec2>>(&self, position: P)
632    {
633        self.inner.set_position_pixels(position)
634    }
635
636    /// Sets the window size in scaled device-independent pixels. This is the
637    /// window's inner size, excluding the border.
638    ///
639    /// For `WebCanvas`, this function has no effect.
640    pub fn set_size_scaled_pixels<S: Into<Vec2>>(&self, size: S)
641    {
642        self.inner.set_size_scaled_pixels(size)
643    }
644
645    /// Sets the position of the window in scaled device-independent pixels. If
646    /// multiple monitors are in use, this will be the distance from the top
647    /// left of the display area, spanning all the monitors.
648    ///
649    /// For `WebCanvas`, this function has no effect.
650    pub fn set_position_scaled_pixels<P: Into<Vec2>>(&self, position: P)
651    {
652        self.inner.set_position_scaled_pixels(position)
653    }
654
655    /// Gets the window's scale factor.
656    #[inline]
657    #[must_use]
658    pub fn get_scale_factor(&self) -> f64
659    {
660        self.inner.get_scale_factor()
661    }
662
663    /// Creates a [UserEventSender], which can be used to post custom events to
664    /// this event loop from another thread.
665    ///
666    /// See [UserEventSender::send_event], [WindowHandler::on_user_event].
667    pub fn create_user_event_sender(&self) -> UserEventSender<UserEventType>
668    {
669        self.inner.create_user_event_sender()
670    }
671}
672
673#[cfg(any(doc, doctest, not(target_arch = "wasm32")))]
674#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
675#[must_use]
676pub(crate) enum WindowEventLoopAction
677{
678    /// Continue running the event loop.
679    Continue,
680
681    /// Stops the event loop. This will cause the entire process to end with
682    /// error code 0, even if other threads are running.
683    ///
684    /// No further callbacks will be given once a handler has returned this
685    /// value. The handler itself will be dropped before exiting.
686    Exit
687}
688
689/// Information about the starting state of the window.
690#[derive(Debug, PartialEq, Clone)]
691pub struct WindowStartupInfo
692{
693    viewport_size_pixels: UVec2,
694    scale_factor: f64
695}
696
697impl WindowStartupInfo
698{
699    pub(crate) fn new(viewport_size_pixels: UVec2, scale_factor: f64) -> Self
700    {
701        WindowStartupInfo {
702            viewport_size_pixels,
703            scale_factor
704        }
705    }
706
707    /// The scale factor of the window. When a high-dpi display is in use,
708    /// this will be greater than `1.0`.
709    pub fn scale_factor(&self) -> f64
710    {
711        self.scale_factor
712    }
713
714    /// The size of the viewport in pixels.
715    pub fn viewport_size_pixels(&self) -> &UVec2
716    {
717        &self.viewport_size_pixels
718    }
719}
720
721/// Identifies a mouse button.
722#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
723#[non_exhaustive]
724pub enum MouseButton
725{
726    /// The left mouse button.
727    Left,
728    /// The middle mouse button.
729    Middle,
730    /// The right mouse button.
731    Right,
732    /// The mouse back button.
733    Back,
734    /// The mouse forward button.
735    Forward,
736    /// Another mouse button, identified by a number.
737    Other(u16)
738}
739
740/// Describes a difference in the mouse scroll wheel position.
741#[derive(Debug, PartialEq, Clone, Copy)]
742pub enum MouseScrollDistance
743{
744    /// Number of lines or rows to scroll in each direction. The `y` field
745    /// represents the vertical scroll direction on a typical mouse wheel.
746    Lines
747    {
748        /// The horizontal scroll distance. Negative values indicate scrolling
749        /// left, and positive values indicate scrolling right.
750        x: f64,
751        /// The vertical scroll distance. Negative values indicate scrolling
752        /// down, and positive values indicate scrolling up.
753        y: f64,
754        /// The forward/backward scroll distance, supported on some 3D mice.
755        z: f64
756    },
757    /// Number of pixels to scroll in each direction. Scroll events are
758    /// expressed in pixels if supported by the device (eg. a touchpad) and
759    /// platform. The `y` field represents the vertical scroll direction on a
760    /// typical mouse wheel.
761    Pixels
762    {
763        /// The horizontal scroll distance. Negative values indicate scrolling
764        /// left, and positive values indicate scrolling right.
765        x: f64,
766        /// The vertical scroll distance. Negative values indicate scrolling
767        /// down, and positive values indicate scrolling up.
768        y: f64,
769        /// The forward/backward scroll distance, supported on some 3D mice.
770        z: f64
771    },
772    /// Number of pages to scroll in each direction (only supported for
773    /// WebCanvas). The `y` field represents the vertical scroll direction on a
774    /// typical mouse wheel.
775    Pages
776    {
777        /// The horizontal scroll distance. Negative values indicate scrolling
778        /// left, and positive values indicate scrolling right.
779        x: f64,
780        /// The vertical scroll distance. Negative values indicate scrolling
781        /// down, and positive values indicate scrolling up.
782        y: f64,
783        /// The forward/backward scroll distance, supported on some 3D mice.
784        z: f64
785    }
786}
787
788/// A virtual key code.
789#[allow(missing_docs)]
790#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
791#[non_exhaustive]
792pub enum VirtualKeyCode
793{
794    Key1,
795    Key2,
796    Key3,
797    Key4,
798    Key5,
799    Key6,
800    Key7,
801    Key8,
802    Key9,
803    Key0,
804
805    A,
806    B,
807    C,
808    D,
809    E,
810    F,
811    G,
812    H,
813    I,
814    J,
815    K,
816    L,
817    M,
818    N,
819    O,
820    P,
821    Q,
822    R,
823    S,
824    T,
825    U,
826    V,
827    W,
828    X,
829    Y,
830    Z,
831
832    Escape,
833
834    F1,
835    F2,
836    F3,
837    F4,
838    F5,
839    F6,
840    F7,
841    F8,
842    F9,
843    F10,
844    F11,
845    F12,
846    F13,
847    F14,
848    F15,
849    F16,
850    F17,
851    F18,
852    F19,
853    F20,
854    F21,
855    F22,
856    F23,
857    F24,
858
859    PrintScreen,
860    ScrollLock,
861    PauseBreak,
862
863    Insert,
864    Home,
865    Delete,
866    End,
867    PageDown,
868    PageUp,
869
870    Left,
871    Up,
872    Right,
873    Down,
874
875    Backspace,
876    Return,
877    Space,
878
879    Compose,
880
881    Caret,
882
883    Numlock,
884    Numpad0,
885    Numpad1,
886    Numpad2,
887    Numpad3,
888    Numpad4,
889    Numpad5,
890    Numpad6,
891    Numpad7,
892    Numpad8,
893    Numpad9,
894    NumpadAdd,
895    NumpadDivide,
896    NumpadDecimal,
897    NumpadComma,
898    NumpadEnter,
899    NumpadEquals,
900    NumpadMultiply,
901    NumpadSubtract,
902
903    AbntC1,
904    AbntC2,
905    Apostrophe,
906    Apps,
907    Asterisk,
908    At,
909    Ax,
910    Backslash,
911    Calculator,
912    Capital,
913    Colon,
914    Comma,
915    Convert,
916    Equals,
917    Grave,
918    Kana,
919    Kanji,
920    LAlt,
921    LBracket,
922    LControl,
923    LShift,
924    LWin,
925    Mail,
926    MediaSelect,
927    MediaStop,
928    Minus,
929    Mute,
930    MyComputer,
931    NavigateForward,
932    NavigateBackward,
933    NextTrack,
934    NoConvert,
935    OEM102,
936    Period,
937    PlayPause,
938    Plus,
939    Power,
940    PrevTrack,
941    RAlt,
942    RBracket,
943    RControl,
944    RShift,
945    RWin,
946    Semicolon,
947    Slash,
948    Sleep,
949    Stop,
950    Sysrq,
951    Tab,
952    Underline,
953    Unlabeled,
954    VolumeDown,
955    VolumeUp,
956    Wake,
957    WebBack,
958    WebFavorites,
959    WebForward,
960    WebHome,
961    WebRefresh,
962    WebSearch,
963    WebStop,
964    Yen,
965    Copy,
966    Paste,
967    Cut
968}
969
970/// The state of the modifier keys.
971#[derive(Debug, Hash, PartialEq, Eq, Clone, Default)]
972pub struct ModifiersState
973{
974    pub(crate) ctrl: bool,
975    pub(crate) alt: bool,
976    pub(crate) shift: bool,
977    pub(crate) logo: bool
978}
979
980impl ModifiersState
981{
982    /// This is true if the CTRL key is pressed.
983    #[inline]
984    #[must_use]
985    pub fn ctrl(&self) -> bool
986    {
987        self.ctrl
988    }
989
990    /// This is true if the ALT key is pressed.
991    #[inline]
992    #[must_use]
993    pub fn alt(&self) -> bool
994    {
995        self.alt
996    }
997
998    /// This is true if the SHIFT key is pressed.
999    #[inline]
1000    #[must_use]
1001    pub fn shift(&self) -> bool
1002    {
1003        self.shift
1004    }
1005
1006    /// This is true if the logo key is pressed (normally the Windows key).
1007    #[inline]
1008    #[must_use]
1009    pub fn logo(&self) -> bool
1010    {
1011        self.logo
1012    }
1013}
1014
1015/// Configuration options about the mode in which the window should be created,
1016/// for example fullscreen or windowed.
1017#[derive(Debug, PartialEq, Clone)]
1018pub(crate) enum WindowCreationMode
1019{
1020    /// Create the window in non-fullscreen mode.
1021    Windowed
1022    {
1023        /// The size of the window.
1024        size: WindowSize,
1025
1026        /// The position of the window.
1027        position: Option<WindowPosition>
1028    },
1029
1030    /// Create the window in fullscreen borderless mode.
1031    FullscreenBorderless
1032}
1033
1034/// The size of the window to create.
1035#[derive(Debug, PartialEq, Clone)]
1036pub enum WindowSize
1037{
1038    /// Define the window size in pixels.
1039    PhysicalPixels(UVec2),
1040    /// Define the window size in device-independent scaled pixels.
1041    ScaledPixels(Vec2),
1042    /// Make the window fill the screen, except for a margin around the outer
1043    /// edges.
1044    MarginPhysicalPixels(u32),
1045    /// Make the window fill the screen, except for a margin around the outer
1046    /// edges.
1047    MarginScaledPixels(f32)
1048}
1049
1050/// The position of the window to create.
1051#[derive(Debug, Hash, PartialEq, Eq, Clone)]
1052pub enum WindowPosition
1053{
1054    /// Place the window in the center of the primary monitor.
1055    Center,
1056    /// Place the window at the specified pixel location from the top left of
1057    /// the primary monitor.
1058    PrimaryMonitorPixelsFromTopLeft(IVec2)
1059}
1060
1061/// Whether or not the window is in fullscreen mode.
1062#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
1063pub enum WindowFullscreenMode
1064{
1065    /// Non-fullscreen mode.
1066    Windowed,
1067    /// Fullscreen borderless mode.
1068    FullscreenBorderless
1069}
1070
1071/// Options used during the creation of a window.
1072#[derive(Debug, Clone, PartialEq)]
1073pub struct WindowCreationOptions
1074{
1075    pub(crate) mode: WindowCreationMode,
1076    pub(crate) multisampling: u16,
1077    pub(crate) vsync: bool,
1078    pub(crate) always_on_top: bool,
1079    pub(crate) resizable: bool,
1080    pub(crate) maximized: bool,
1081    pub(crate) transparent: bool,
1082    pub(crate) decorations: bool
1083}
1084
1085impl WindowCreationOptions
1086{
1087    /// Instantiates a new `WindowCreationOptions` structure with the default
1088    /// options, in non-fullscreen mode.
1089    pub fn new_windowed(size: WindowSize, position: Option<WindowPosition>) -> Self
1090    {
1091        Self::new(WindowCreationMode::Windowed { size, position })
1092    }
1093
1094    /// Instantiates a new `WindowCreationOptions` structure with the default
1095    /// options, in borderless fullscreen mode.
1096    #[inline]
1097    #[must_use]
1098    pub fn new_fullscreen_borderless() -> Self
1099    {
1100        Self::new(WindowCreationMode::FullscreenBorderless)
1101    }
1102
1103    #[inline]
1104    #[must_use]
1105    fn new(mode: WindowCreationMode) -> Self
1106    {
1107        WindowCreationOptions {
1108            mode,
1109            multisampling: 16,
1110            vsync: true,
1111            always_on_top: false,
1112            resizable: true,
1113            maximized: false,
1114            decorations: true,
1115            transparent: false
1116        }
1117    }
1118
1119    /// Sets the maximum level of multisampling which will be applied. By
1120    /// default this is set to `16`.
1121    ///
1122    /// Note that this depends on platform support, and setting this may have no
1123    /// effect.
1124    #[inline]
1125    #[must_use]
1126    pub fn with_multisampling(mut self, multisampling: u16) -> Self
1127    {
1128        self.multisampling = multisampling;
1129        self
1130    }
1131
1132    /// Sets whether or not vsync should be enabled. This can increase latency,
1133    /// but should eliminate tearing. By default this is set to `true`.
1134    ///
1135    /// Note that this depends on platform support, and setting this may have no
1136    /// effect.
1137    #[inline]
1138    #[must_use]
1139    pub fn with_vsync(mut self, vsync: bool) -> Self
1140    {
1141        self.vsync = vsync;
1142        self
1143    }
1144
1145    /// Sets whether or not the window can be resized by the user. The default
1146    /// is `true`.
1147    #[inline]
1148    #[must_use]
1149    pub fn with_resizable(mut self, resizable: bool) -> Self
1150    {
1151        self.resizable = resizable;
1152        self
1153    }
1154
1155    /// If set to `true`, the window will be placed above other windows. The
1156    /// default is `false`.
1157    #[inline]
1158    #[must_use]
1159    pub fn with_always_on_top(mut self, always_on_top: bool) -> Self
1160    {
1161        self.always_on_top = always_on_top;
1162        self
1163    }
1164
1165    /// If set to `true`, the window will be initially maximized. The default is
1166    /// `false`.
1167    #[inline]
1168    #[must_use]
1169    pub fn with_maximized(mut self, maximized: bool) -> Self
1170    {
1171        self.maximized = maximized;
1172        self
1173    }
1174
1175    /// If set to `false`, the window will have no border.  The default is
1176    /// `true`.
1177    #[inline]
1178    #[must_use]
1179    pub fn with_decorations(mut self, decorations: bool) -> Self
1180    {
1181        self.decorations = decorations;
1182        self
1183    }
1184
1185    /// Sets whether the background of the window should be transparent. The
1186    /// default is `false`.
1187    ///
1188    /// Note that this depends on platform support, and setting this may have no
1189    /// effect.
1190    #[inline]
1191    #[must_use]
1192    pub fn with_transparent(mut self, transparent: bool) -> Self
1193    {
1194        self.transparent = transparent;
1195        self
1196    }
1197}
1198
1199/// Type representing a keyboard scancode.
1200pub type KeyScancode = u32;