input/
lib.rs

1#![crate_name = "input"]
2#![deny(
3    rust_2018_compatibility,
4    rust_2018_idioms,
5    future_incompatible,
6    nonstandard_style,
7    unused,
8    clippy::all,
9    clippy::doc_markdown,
10    missing_docs,
11    missing_copy_implementations,
12    missing_debug_implementations
13)]
14
15//! A flexible structure for user interactions
16//! to be used in window frameworks and widgets libraries.
17
18#[macro_use]
19extern crate bitflags;
20#[macro_use]
21extern crate serde_derive;
22
23use std::{any::Any, cmp::Ordering, fmt, path::PathBuf, sync::Arc};
24
25pub use controller::{ControllerAxisArgs, ControllerButton, ControllerHat};
26pub use keyboard::Key;
27pub use mouse::MouseButton;
28
29pub mod controller;
30pub mod keyboard;
31pub mod mouse;
32
33pub use after_render::{AfterRenderArgs, AfterRenderEvent};
34pub use button::{ButtonArgs, ButtonEvent, ButtonState, PressEvent, ReleaseEvent};
35pub use close::{CloseArgs, CloseEvent};
36pub use controller::ControllerAxisEvent;
37pub use cursor::CursorEvent;
38use event_id::EventId;
39pub use focus::FocusEvent;
40pub use generic_event::GenericEvent;
41pub use idle::{IdleArgs, IdleEvent};
42pub use mouse::{MouseCursorEvent, MouseRelativeEvent, MouseScrollEvent};
43pub use render::{RenderArgs, RenderEvent};
44pub use resize::{ResizeArgs, ResizeEvent};
45pub use text::TextEvent;
46pub use touch::{Touch, TouchArgs, TouchEvent};
47pub use update::{UpdateArgs, UpdateEvent};
48
49pub mod event_id;
50pub mod generic_event;
51
52mod after_render;
53mod button;
54mod close;
55mod cursor;
56mod focus;
57mod idle;
58mod render;
59mod resize;
60mod text;
61mod touch;
62mod update;
63
64/// The type of time stamp.
65///
66/// Measured in milliseconds since initialization of window.
67pub type TimeStamp = u32;
68
69/// Models different kinds of buttons.
70#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, PartialOrd, Ord, Eq, Hash, Debug)]
71pub enum Button {
72    /// A keyboard button.
73    Keyboard(Key),
74    /// A mouse button.
75    Mouse(MouseButton),
76    /// A controller button.
77    Controller(ControllerButton),
78    /// A controller hat (d-Pad)
79    Hat(ControllerHat),
80}
81
82/// Models different kinds of motion.
83#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, PartialOrd, Debug)]
84pub enum Motion {
85    /// Position in window coordinates.
86    MouseCursor([f64; 2]),
87    /// Position in relative coordinates.
88    MouseRelative([f64; 2]),
89    /// Position in scroll ticks.
90    MouseScroll([f64; 2]),
91    /// Controller axis move event.
92    ControllerAxis(ControllerAxisArgs),
93    /// Touch event.
94    Touch(TouchArgs),
95}
96
97/// Stores controller hat state.
98#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
99pub enum HatState {
100    /// Centered (no direction).
101    Centered,
102    /// Up direction.
103    Up,
104    /// Right direction.
105    Right,
106    /// Down direction.
107    Down,
108    /// Left direction.
109    Left,
110    /// Right-up direction.
111    RightUp,
112    /// Right-down direction.
113    RightDown,
114    /// Left-up direction.
115    LeftUp,
116    /// Left-down direction.
117    LeftDown,
118}
119
120/// Models dragging and dropping files.
121#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, Hash)]
122pub enum FileDrag {
123    /// A file is being hovered over the window.
124    Hover(PathBuf),
125    /// A file has been dropped into the window.
126    Drop(PathBuf),
127    /// A file was hovered, but has exited the window.
128    Cancel,
129}
130
131/// Models input events.
132#[derive(Clone, Debug, PartialEq, PartialOrd, Deserialize, Serialize)]
133pub enum Input {
134    /// Changed button state.
135    Button(ButtonArgs),
136    /// Moved mouse cursor.
137    Move(Motion),
138    /// Text (usually from keyboard).
139    Text(String),
140    /// Window got resized.
141    Resize(ResizeArgs),
142    /// Window gained or lost focus.
143    Focus(bool),
144    /// Window gained or lost cursor.
145    Cursor(bool),
146    /// A file is being dragged or dropped over the window.
147    FileDrag(FileDrag),
148    /// Window closed.
149    Close(CloseArgs),
150}
151
152/// Models loop events.
153#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Deserialize, Serialize)]
154pub enum Loop {
155    /// Render graphics.
156    Render(RenderArgs),
157    /// After rendering and swapping buffers.
158    AfterRender(AfterRenderArgs),
159    /// Update the state of the application.
160    Update(UpdateArgs),
161    /// Do background tasks that can be done incrementally.
162    Idle(IdleArgs),
163}
164
165/// Models all events.
166#[derive(Clone)]
167pub enum Event {
168    /// Input events.
169    ///
170    /// Time stamp is ignored when comparing input events for equality and order.
171    Input(Input, Option<TimeStamp>),
172    /// Events that commonly used by event loops.
173    Loop(Loop),
174    /// Custom event.
175    ///
176    /// When comparing two custom events for equality,
177    /// they always return `false`.
178    ///
179    /// When comparing partial order of two custom events,
180    /// the event ids are checked and if they are equal it returns `None`.
181    ///
182    /// Time stamp is ignored both when comparing custom events for equality and order.
183    Custom(EventId, Arc<dyn Any + Send + Sync>, Option<TimeStamp>),
184}
185
186impl fmt::Debug for Event {
187    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188        match *self {
189            Event::Input(ref input, _) => write!(f, "{:?}", input),
190            Event::Loop(ref l) => write!(f, "{:?}", l),
191            Event::Custom(ref id, _, _) => write!(f, "Custom({:?}, _)", id),
192        }
193    }
194}
195
196impl PartialEq for Event {
197    fn eq(&self, other: &Event) -> bool {
198        use Event::*;
199
200        match (self, other) {
201            (&Input(ref a, _), &Input(ref b, _)) => a == b,
202            (&Loop(ref a), &Loop(ref b)) => a == b,
203            (_, _) => false,
204        }
205    }
206}
207
208impl PartialOrd for Event {
209    fn partial_cmp(&self, other: &Event) -> Option<Ordering> {
210        use Event::*;
211
212        match (self, other) {
213            (&Input(ref a, _), &Input(ref b, _)) => a.partial_cmp(b),
214            (&Loop(ref a), &Loop(ref b)) => a.partial_cmp(b),
215            (&Custom(ref a_id, _, _), &Custom(ref b_id, _, _)) => {
216                let res = a_id.partial_cmp(b_id);
217                if res == Some(Ordering::Equal) {
218                    None
219                } else {
220                    res
221                }
222            }
223            (&Input(_, _), _) => Some(Ordering::Less),
224            (_, &Input(_, _)) => Some(Ordering::Greater),
225            (&Loop(_), &Custom(_, _, _)) => Some(Ordering::Less),
226            (&Custom(_, _, _), &Loop(_)) => Some(Ordering::Greater),
227        }
228    }
229}
230
231impl From<Key> for Button {
232    fn from(key: Key) -> Self {
233        Button::Keyboard(key)
234    }
235}
236
237impl From<MouseButton> for Button {
238    fn from(btn: MouseButton) -> Self {
239        Button::Mouse(btn)
240    }
241}
242
243impl From<ControllerButton> for Button {
244    fn from(btn: ControllerButton) -> Self {
245        Button::Controller(btn)
246    }
247}
248
249impl From<ButtonArgs> for Input {
250    fn from(args: ButtonArgs) -> Self {
251        Input::Button(args)
252    }
253}
254
255impl From<ControllerAxisArgs> for Motion {
256    fn from(args: ControllerAxisArgs) -> Self {
257        Motion::ControllerAxis(args)
258    }
259}
260
261impl From<ControllerAxisArgs> for Input {
262    fn from(args: ControllerAxisArgs) -> Self {
263        Input::Move(Motion::ControllerAxis(args))
264    }
265}
266
267impl From<TouchArgs> for Motion {
268    fn from(args: TouchArgs) -> Self {
269        Motion::Touch(args)
270    }
271}
272
273impl From<TouchArgs> for Input {
274    fn from(args: TouchArgs) -> Self {
275        Input::Move(Motion::Touch(args))
276    }
277}
278
279impl From<Motion> for Input {
280    fn from(motion: Motion) -> Self {
281        Input::Move(motion)
282    }
283}
284
285impl From<RenderArgs> for Loop {
286    fn from(args: RenderArgs) -> Self {
287        Loop::Render(args)
288    }
289}
290
291impl From<RenderArgs> for Event {
292    fn from(args: RenderArgs) -> Self {
293        Event::Loop(Loop::Render(args))
294    }
295}
296
297impl From<AfterRenderArgs> for Loop {
298    fn from(args: AfterRenderArgs) -> Self {
299        Loop::AfterRender(args)
300    }
301}
302
303impl From<AfterRenderArgs> for Event {
304    fn from(args: AfterRenderArgs) -> Self {
305        Event::Loop(Loop::AfterRender(args))
306    }
307}
308
309impl From<UpdateArgs> for Loop {
310    fn from(args: UpdateArgs) -> Self {
311        Loop::Update(args)
312    }
313}
314
315impl From<UpdateArgs> for Event {
316    fn from(args: UpdateArgs) -> Self {
317        Event::Loop(Loop::Update(args))
318    }
319}
320
321impl From<IdleArgs> for Loop {
322    fn from(args: IdleArgs) -> Self {
323        Loop::Idle(args)
324    }
325}
326
327impl From<IdleArgs> for Event {
328    fn from(args: IdleArgs) -> Self {
329        Event::Loop(Loop::Idle(args))
330    }
331}
332
333impl From<CloseArgs> for Input {
334    fn from(args: CloseArgs) -> Self {
335        Input::Close(args)
336    }
337}
338
339impl<T> From<T> for Event
340where
341    Input: From<T>,
342{
343    fn from(args: T) -> Self {
344        Event::Input(args.into(), None)
345    }
346}
347
348impl<T> From<(T, Option<TimeStamp>)> for Event
349where
350    Input: From<T>,
351{
352    fn from(args: (T, Option<TimeStamp>)) -> Self {
353        Event::Input(args.0.into(), args.1)
354    }
355}
356
357impl From<Loop> for Event {
358    fn from(l: Loop) -> Self {
359        Event::Loop(l)
360    }
361}
362
363impl From<Event> for Option<Input> {
364    fn from(event: Event) -> Option<Input> {
365        if let Event::Input(input, _) = event {
366            Some(input)
367        } else {
368            None
369        }
370    }
371}
372
373impl From<Event> for Option<Loop> {
374    fn from(event: Event) -> Option<Loop> {
375        if let Event::Loop(l) = event {
376            Some(l)
377        } else {
378            None
379        }
380    }
381}
382
383#[cfg(test)]
384mod tests {
385    use super::*;
386
387    #[test]
388    fn test_input_sync_send() {
389        fn chk<T: Sync + Send>() {}
390
391        chk::<Input>();
392        chk::<Loop>();
393        chk::<Event>();
394    }
395}