1 #![allow(dead_code)]
2 use std::io;
3 
4 use std::fmt;
5 
6 #[cfg(not(feature = "glfw"))]
7 #[path = "dummy.rs"]
8 pub mod backend;
9 
10 #[cfg(feature = "glfw")]
11 #[path = "glfw.rs"]
12 pub mod backend;
13 
14 /// Initialize the platform.
init( title: &str, w: u32, h: u32, hints: &[WindowHint], context: GraphicsContext, ) -> io::Result<(backend::Window, backend::Events)>15 pub fn init(
16     title: &str,
17     w: u32,
18     h: u32,
19     hints: &[WindowHint],
20     context: GraphicsContext,
21 ) -> io::Result<(backend::Window, backend::Events)> {
22     backend::init(title, w, h, hints, context)
23 }
24 
25 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
26 pub enum GraphicsContext {
27     None,
28     Gl,
29 }
30 
31 #[derive(Debug, Copy, Clone)]
32 pub enum WindowHint {
33     Resizable(bool),
34     Visible(bool),
35 }
36 
37 /// Describes an event from a `Window`.
38 #[derive(Clone, Debug, PartialEq)]
39 pub enum WindowEvent {
40     /// The size of the window has changed. Contains the client area's new dimensions.
41     Resized(LogicalSize),
42 
43     /// The position of the window has changed. Contains the window's new position.
44     Moved(LogicalPosition),
45 
46     /// The window was minimized.
47     Minimized,
48 
49     /// The window was restored after having been minimized.
50     Restored,
51 
52     /// The window has been requested to close.
53     CloseRequested,
54 
55     /// The window has been destroyed.
56     Destroyed,
57 
58     /// The window received a unicode character.
59     ReceivedCharacter(char),
60 
61     /// The window gained or lost focus.
62     Focused(bool),
63 
64     /// An event from the keyboard has been received.
65     KeyboardInput(KeyboardInput),
66 
67     /// The cursor has moved on the window.
68     CursorMoved {
69         /// Coords in pixels relative to the top-left corner of the window.
70         position: LogicalPosition,
71     },
72 
73     /// The cursor has entered the window.
74     CursorEntered,
75 
76     /// The cursor has left the window.
77     CursorLeft,
78 
79     /// A mouse button press has been received.
80     MouseInput {
81         state: InputState,
82         button: MouseButton,
83         modifiers: ModifiersState,
84     },
85 
86     /// The mouse wheel has been used.
87     MouseWheel { delta: LogicalDelta },
88 
89     /// The OS or application has requested that the window be redrawn.
90     RedrawRequested,
91 
92     /// There are no more inputs to process, the application can do work.
93     Ready,
94 
95     /// The content scale factor of the window has changed.  For example,
96     /// the window was moved to a higher DPI screen.
97     ScaleFactorChanged(f64),
98 
99     /// No-op event, for events we don't handle.
100     Noop,
101 }
102 
103 impl WindowEvent {
104     /// Events that are triggered by user input.
is_input(&self) -> bool105     pub fn is_input(&self) -> bool {
106         match self {
107             Self::Resized(_)
108             | Self::Moved(_)
109             | Self::Minimized
110             | Self::Restored
111             | Self::CloseRequested
112             | Self::Destroyed
113             | Self::ReceivedCharacter(_)
114             | Self::Focused(_)
115             | Self::KeyboardInput(_)
116             | Self::CursorMoved { .. }
117             | Self::CursorEntered
118             | Self::CursorLeft
119             | Self::MouseInput { .. }
120             | Self::ScaleFactorChanged(_) => true,
121             _ => false,
122         }
123     }
124 }
125 
126 /// Describes a keyboard input event.
127 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
128 pub struct KeyboardInput {
129     pub state: InputState,
130     pub key: Option<Key>,
131     pub modifiers: ModifiersState,
132 }
133 
134 /// Describes the input state of a key.
135 #[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
136 pub enum InputState {
137     Pressed,
138     Released,
139     Repeated,
140 }
141 
142 /// Describes a mouse button.
143 #[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
144 pub enum MouseButton {
145     Left,
146     Right,
147     Middle,
148     Other(u8),
149 }
150 
151 /// Symbolic name for a keyboard key.
152 #[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
153 #[repr(u32)]
154 #[rustfmt::skip]
155 pub enum Key {
156     // Number keys.
157     Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, Num0,
158 
159     // Alpha keys.
160     A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
161 
162     // Arrow keys.
163     Left, Up, Right, Down,
164 
165     // Control characters.
166     Backspace, Return, Space, Tab,
167     Escape, Insert, Home, Delete, End, PageDown, PageUp,
168 
169     // Punctuation.
170     Apostrophe, Grave, Caret, Comma, Period, Colon, Semicolon,
171     LBracket, RBracket,
172     Slash, Backslash,
173 
174     // Modifiers.
175     Alt, Control, Shift,
176 
177     // Math keys.
178     Equal, Minus,
179 
180     // Key is unknown/unsupported.
181     Unknown,
182 }
183 
184 impl From<char> for Key {
185     #[rustfmt::skip]
from(c: char) -> Self186     fn from(c: char) -> Self {
187         match c {
188             '0' => Key::Num0, '1' => Key::Num1, '2' => Key::Num2,
189             '3' => Key::Num3, '4' => Key::Num4, '5' => Key::Num5,
190             '6' => Key::Num6, '7' => Key::Num7, '8' => Key::Num8,
191             '9' => Key::Num9,
192 
193             'a' => Key::A, 'b' => Key::B, 'c' => Key::C, 'd' => Key::D,
194             'e' => Key::E, 'f' => Key::F, 'g' => Key::G, 'h' => Key::H,
195             'i' => Key::I, 'j' => Key::J, 'k' => Key::K, 'l' => Key::L,
196             'm' => Key::M, 'n' => Key::N, 'o' => Key::O, 'p' => Key::P,
197             'q' => Key::Q, 'r' => Key::R, 's' => Key::S, 't' => Key::T,
198             'u' => Key::U, 'v' => Key::V, 'w' => Key::W, 'x' => Key::X,
199             'y' => Key::Y, 'z' => Key::Z,
200 
201             '/' => Key::Slash, '[' => Key::LBracket, ']' => Key::RBracket,
202             '`' => Key::Grave, ',' => Key::Comma, '.' => Key::Period,
203             '=' => Key::Equal, '-' => Key::Minus, '\'' => Key::Apostrophe,
204             ';' => Key::Semicolon, ':' => Key::Colon, ' ' => Key::Space,
205             '\\' => Key::Backslash,
206             _ => Key::Unknown,
207         }
208     }
209 }
210 
211 impl fmt::Display for Key {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result212     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213         match self {
214             Key::A => "a".fmt(f),
215             Key::B => "b".fmt(f),
216             Key::C => "c".fmt(f),
217             Key::D => "d".fmt(f),
218             Key::E => "e".fmt(f),
219             Key::F => "f".fmt(f),
220             Key::G => "g".fmt(f),
221             Key::H => "h".fmt(f),
222             Key::I => "i".fmt(f),
223             Key::J => "j".fmt(f),
224             Key::K => "k".fmt(f),
225             Key::L => "l".fmt(f),
226             Key::M => "m".fmt(f),
227             Key::N => "n".fmt(f),
228             Key::O => "o".fmt(f),
229             Key::P => "p".fmt(f),
230             Key::Q => "q".fmt(f),
231             Key::R => "r".fmt(f),
232             Key::S => "s".fmt(f),
233             Key::T => "t".fmt(f),
234             Key::U => "u".fmt(f),
235             Key::V => "v".fmt(f),
236             Key::W => "w".fmt(f),
237             Key::X => "x".fmt(f),
238             Key::Y => "y".fmt(f),
239             Key::Z => "z".fmt(f),
240             Key::Num0 => "0".fmt(f),
241             Key::Num1 => "1".fmt(f),
242             Key::Num2 => "2".fmt(f),
243             Key::Num3 => "3".fmt(f),
244             Key::Num4 => "4".fmt(f),
245             Key::Num5 => "5".fmt(f),
246             Key::Num6 => "6".fmt(f),
247             Key::Num7 => "7".fmt(f),
248             Key::Num8 => "8".fmt(f),
249             Key::Num9 => "9".fmt(f),
250             Key::LBracket => "[".fmt(f),
251             Key::RBracket => "]".fmt(f),
252             Key::Comma => ",".fmt(f),
253             Key::Period => ".".fmt(f),
254             Key::Slash => "/".fmt(f),
255             Key::Backslash => "\\".fmt(f),
256             Key::Apostrophe => "'".fmt(f),
257             Key::Control => "<ctrl>".fmt(f),
258             Key::Shift => "<shift>".fmt(f),
259             Key::Alt => "<alt>".fmt(f),
260             Key::Up => "<up>".fmt(f),
261             Key::Down => "<down>".fmt(f),
262             Key::Left => "<left>".fmt(f),
263             Key::Right => "<right>".fmt(f),
264             Key::Return => "<return>".fmt(f),
265             Key::Backspace => "<backspace>".fmt(f),
266             Key::Space => "<space>".fmt(f),
267             Key::Tab => "<tab>".fmt(f),
268             Key::Escape => "<esc>".fmt(f),
269             Key::Insert => "<insert>".fmt(f),
270             Key::Delete => "<delete>".fmt(f),
271             Key::Home => "<home>".fmt(f),
272             Key::PageUp => "<pgup>".fmt(f),
273             Key::PageDown => "<pgdown>".fmt(f),
274             Key::Grave => "`".fmt(f),
275             Key::Caret => "^".fmt(f),
276             Key::End => "<end>".fmt(f),
277             Key::Colon => ":".fmt(f),
278             Key::Semicolon => ";".fmt(f),
279             Key::Equal => "=".fmt(f),
280             Key::Minus => "-".fmt(f),
281             _ => "???".fmt(f),
282         }
283     }
284 }
285 
286 impl Key {
287     pub fn is_modifier(&self) -> bool {
288         match self {
289             Key::Alt | Key::Control | Key::Shift => true,
290             _ => false,
291         }
292     }
293 }
294 
295 /// Represents the current state of the keyboard modifiers
296 #[derive(Default, Debug, Hash, PartialEq, Eq, Clone, Copy)]
297 pub struct ModifiersState {
298     /// The "shift" key
299     pub shift: bool,
300     /// The "control" key
301     pub ctrl: bool,
302     /// The "alt" key
303     pub alt: bool,
304     /// The "meta" key. This is the "windows" key on PC and "command" key on Mac.
305     pub meta: bool,
306 }
307 
308 impl fmt::Display for ModifiersState {
309     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
310         let mut s = String::new();
311         if self.ctrl {
312             s.push_str("<ctrl>");
313         }
314         if self.alt {
315             s.push_str("<alt>");
316         }
317         if self.meta {
318             s.push_str("<meta>");
319         }
320         if self.shift {
321             s.push_str("<shift>");
322         }
323         s.fmt(f)
324     }
325 }
326 
327 /// A delta represented in logical pixels.
328 #[derive(Debug, Copy, Clone, PartialEq)]
329 pub struct LogicalDelta {
330     pub x: f64,
331     pub y: f64,
332 }
333 
334 /// A position represented in logical pixels.
335 #[derive(Debug, Copy, Clone, PartialEq)]
336 pub struct LogicalPosition {
337     pub x: f64,
338     pub y: f64,
339 }
340 
341 impl LogicalPosition {
342     pub fn new(x: f64, y: f64) -> Self {
343         LogicalPosition { x, y }
344     }
345 
346     pub fn from_physical<T: Into<PhysicalPosition>>(physical: T, scale_factor: f64) -> Self {
347         physical.into().to_logical(self::pixel_ratio(scale_factor))
348     }
349 
350     pub fn to_physical(&self, scale_factor: f64) -> PhysicalPosition {
351         let x = self.x * self::pixel_ratio(scale_factor);
352         let y = self.y * self::pixel_ratio(scale_factor);
353         PhysicalPosition::new(x, y)
354     }
355 }
356 
357 /// A position represented in physical pixels.
358 #[derive(Debug, Copy, Clone, PartialEq)]
359 pub struct PhysicalPosition {
360     pub x: f64,
361     pub y: f64,
362 }
363 
364 impl PhysicalPosition {
365     pub fn new(x: f64, y: f64) -> Self {
366         PhysicalPosition { x, y }
367     }
368 
369     pub fn from_logical<T: Into<LogicalPosition>>(logical: T, scale_factor: f64) -> Self {
370         logical.into().to_physical(self::pixel_ratio(scale_factor))
371     }
372 
373     pub fn to_logical(&self, scale_factor: f64) -> LogicalPosition {
374         let x = self.x / self::pixel_ratio(scale_factor);
375         let y = self.y / self::pixel_ratio(scale_factor);
376         LogicalPosition::new(x, y)
377     }
378 }
379 
380 /// A size represented in logical pixels.
381 #[derive(Debug, Copy, Clone, PartialEq)]
382 pub struct LogicalSize {
383     pub width: f64,
384     pub height: f64,
385 }
386 
387 impl LogicalSize {
388     pub const fn new(width: f64, height: f64) -> Self {
389         LogicalSize { width, height }
390     }
391 
392     pub fn from_physical<T: Into<PhysicalSize>>(physical: T, scale_factor: f64) -> Self {
393         physical.into().to_logical(self::pixel_ratio(scale_factor))
394     }
395 
396     pub fn to_physical(&self, scale_factor: f64) -> PhysicalSize {
397         let width = self.width * self::pixel_ratio(scale_factor);
398         let height = self.height * self::pixel_ratio(scale_factor);
399         PhysicalSize::new(width, height)
400     }
401 
402     pub fn is_zero(&self) -> bool {
403         self.width < 1. || self.height < 1.
404     }
405 }
406 
407 impl From<(u32, u32)> for LogicalSize {
408     fn from((width, height): (u32, u32)) -> Self {
409         Self::new(width as f64, height as f64)
410     }
411 }
412 
413 impl Into<(u32, u32)> for LogicalSize {
414     /// Note that this rounds instead of truncating.
415     fn into(self) -> (u32, u32) {
416         (self.width.round() as _, self.height.round() as _)
417     }
418 }
419 
420 /// A size represented in physical pixels.
421 #[derive(Debug, Copy, Clone, PartialEq)]
422 pub struct PhysicalSize {
423     pub width: f64,
424     pub height: f64,
425 }
426 
427 impl PhysicalSize {
428     pub fn new(width: f64, height: f64) -> Self {
429         PhysicalSize { width, height }
430     }
431 
432     pub fn from_logical<T: Into<LogicalSize>>(logical: T, scale_factor: f64) -> Self {
433         logical.into().to_physical(self::pixel_ratio(scale_factor))
434     }
435 
436     pub fn to_logical(&self, scale_factor: f64) -> LogicalSize {
437         let width = self.width / self::pixel_ratio(scale_factor);
438         let height = self.height / self::pixel_ratio(scale_factor);
439         LogicalSize::new(width, height)
440     }
441 }
442 
443 impl From<(u32, u32)> for PhysicalSize {
444     fn from((width, height): (u32, u32)) -> Self {
445         Self::new(width as f64, height as f64)
446     }
447 }
448 
449 impl Into<(u32, u32)> for PhysicalSize {
450     /// Note that this rounds instead of truncating.
451     fn into(self) -> (u32, u32) {
452         (self.width.round() as _, self.height.round() as _)
453     }
454 }
455 
456 /// The ratio between screen coordinates and pixels, given the
457 /// content scale.
458 /// On macOS, screen coordinates don't map 1:1 with pixels. Hence,
459 /// our ratio between screen coordinates and pixels is whatever
460 /// the scaling factor is, which is always `2.0` on modern hardware.
461 #[cfg(target_os = "macos")]
462 pub fn pixel_ratio(scale_factor: f64) -> f64 {
463     scale_factor
464 }
465 
466 /// The ratio between screen coordinates and pixels, given the
467 /// content scale.
468 /// On Linux and Windows, screen coordinates always map 1:1 with pixels.
469 /// No matter the DPI settings and display, we always want to map a screen
470 /// coordinate with a single pixel.
471 #[cfg(not(target_os = "macos"))]
472 pub fn pixel_ratio(_scale_factor: f64) -> f64 {
473     1.0
474 }
475