1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
//! Event types.

pub use device::*;
pub use window::*;

pub use winit::event::AxisId;
pub use winit::event::ButtonId;
pub use winit::event::DeviceId;
pub use winit::event::Force;
pub use winit::event::ModifiersState;
pub use winit::event::MouseScrollDelta;
pub use winit::event::ScanCode;
pub use winit::event::StartCause;
pub use winit::event::Touch;
pub use winit::event::TouchPhase;
pub use winit::event::VirtualKeyCode;

macro_rules! impl_from_variant {
	($for:ident::$variant:ident($from:ty)) => {
		impl From<$from> for $for {
			fn from(other: $from) -> Self {
				Self::$variant(other)
			}
		}
	};
}

mod device;
mod window;

/// Control flow properties for event handlers.
///
/// Instances of this struct are passed to event handlers
/// to allow them to remove themselves and to stop event propagation.
#[derive(Debug, Default, Clone)]
pub struct EventHandlerControlFlow {
	/// Remove the event handler after it returned.
	pub remove_handler: bool,

	/// Stop propagation of the event to other event handlers.
	pub stop_propagation: bool,
}

/// Global event.
///
/// This also includes window events for all windows.
#[derive(Debug, Clone)]
pub enum Event {
	/// New events are available for processing.
	///
	/// This indicates the start of a new event-processing cycle.
	NewEvents,

	/// A window event.
	WindowEvent(WindowEvent),

	/// A device event.
	DeviceEvent(DeviceEvent),

	/// The application has been suspended.
	Suspended,

	/// The application has been resumed.
	Resumed,

	/// All input events have been processed and redraw processing is about to begin.
	MainEventsCleared,

	/// All open redraw requests have been processed.
	RedrawEventsCleared,

	/// All windows were closed.
	///
	/// This event can be received multiple times if you open a new window after all windows were closed.
	AllWindowsClosed,
}

impl_from_variant!(Event::WindowEvent(WindowEvent));
impl_from_variant!(Event::DeviceEvent(DeviceEvent));

/// Keyboard input.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct KeyboardInput {
	/// Scan code of the physical key.
	///
	/// This should not change if the user adjusts the host's keyboard map.
	/// Use when the physical location of the key is more important than the key's host GUI semantics, such as for movement controls in a first-person game.
	pub scan_code: ScanCode,

	/// Virtual key code indentifying the semantic meaning of the key.
	///
	/// Use this when the semantics of the key are more important than the physical location of the key, such as when implementing appropriate behavior for "page up".
	pub key_code: Option<VirtualKeyCode>,

	/// State of the key (pressed or released).
	pub state: ElementState,

	/// Keyboard modifiers that were active at the time of the event.
	pub modifiers: ModifiersState,
}

/// OS theme (light or dark).
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Theme {
	/// The theme is a light theme.
	Light,

	/// The theme is a dark theme.
	Dark,
}

impl Theme {
	/// Check if the theme is light.
	pub fn is_light(self) -> bool {
		self == Self::Light
	}

	/// Check if the theme is dark.
	pub fn is_dark(self) -> bool {
		self == Self::Dark
	}
}

/// State of a button or key.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum ElementState {
	/// The button or key is pressed.
	Pressed,

	/// The button or key is released.
	Released,
}

impl ElementState {
	/// Check if the button or key is pressed.
	pub fn is_pressed(self) -> bool {
		self == Self::Pressed
	}

	/// Check if the button or key is released.
	pub fn is_released(self) -> bool {
		self == Self::Released
	}
}

#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
/// A mouse button.
pub enum MouseButton {
	/// The left mouse button.
	Left,

	/// The right mouse button.
	Right,

	/// The middle mouse button (usually triggered by pressing the scroll wheel).
	Middle,

	/// An other mouse button identified by index.
	Other(u16),
}

impl MouseButton {
	/// Check if the button is the left mouse button.
	pub fn is_left(self) -> bool {
		self == Self::Left
	}

	/// Check if the button is the right mouse button.
	pub fn is_right(self) -> bool {
		self == Self::Right
	}

	/// Check if the button is the middle mouse button.
	pub fn is_middle(self) -> bool {
		self == Self::Middle
	}

	/// Check if the button is a specific other button.
	pub fn is_other(self, other: u16) -> bool {
		self == Self::Other(other)
	}
}

/// The state of all mouse buttons.
#[derive(Debug, Clone, Default)]
pub struct MouseButtonState {
	/// The set of pressed buttons.
	buttons: std::collections::BTreeSet<MouseButton>,
}

impl MouseButtonState {
	/// Check if a button is pressed.
	pub fn is_pressed(&self, button: MouseButton) -> bool {
		self.buttons.get(&button).is_some()
	}

	/// Iterate over all pressed buttons.
	pub fn iter_pressed(&self) -> impl Iterator<Item = MouseButton> + '_ {
		self.buttons.iter().copied()
	}

	/// Mark a button as pressed or unpressed.
	pub fn set_pressed(&mut self, button: MouseButton, pressed: bool) {
		if pressed {
			self.buttons.insert(button);
		} else {
			self.buttons.remove(&button);
		}
	}
}