show_image/backend/
event.rs

1use super::mouse_cache::MouseCache;
2
3pub fn convert_winit_event(
4	event: winit::event::Event<()>,
5	mouse_cache: &MouseCache,
6) -> Option<crate::event::Event> {
7	use crate::event::Event as C;
8	use winit::event::Event as W;
9
10	match event {
11		W::UserEvent(_) => None,
12		W::WindowEvent { window_id, event } => Some(convert_winit_window_event(window_id, event, mouse_cache)?.into()),
13		W::DeviceEvent { device_id, event } => Some(convert_winit_device_event(device_id, event).into()),
14		W::NewEvents(_) => Some(C::NewEvents),
15		W::MainEventsCleared => Some(C::MainEventsCleared),
16		W::RedrawRequested(window_id) => Some(C::WindowEvent(crate::event::WindowRedrawRequestedEvent { window_id }.into())),
17		W::RedrawEventsCleared => Some(C::RedrawEventsCleared),
18		// You can't stop the event loop!
19		W::LoopDestroyed => None,
20		W::Suspended => Some(C::Suspended),
21		W::Resumed => Some(C::Resumed),
22	}
23}
24
25pub fn convert_winit_device_event(
26	device_id: winit::event::DeviceId,
27	event: winit::event::DeviceEvent,
28) -> crate::event::DeviceEvent {
29	use crate::event;
30	use winit::event::DeviceEvent as W;
31	match event {
32		W::Added => event::DeviceAddedEvent { device_id }.into(),
33		W::Removed => event::DeviceRemovedEvent { device_id }.into(),
34		W::MouseMotion { delta } => event::DeviceMouseMotionEvent {
35			device_id,
36			delta: glam::DVec2::new(delta.0, delta.1).as_vec2(),
37		}
38		.into(),
39		W::MouseWheel { delta } => event::DeviceMouseWheelEvent { device_id, delta }.into(),
40		W::Motion { axis, value } => event::DeviceMotionEvent { device_id, axis, value }.into(),
41		W::Button { button, state } => event::DeviceButtonEvent {
42			device_id,
43			button,
44			state: state.into(),
45		}
46		.into(),
47		W::Key(input) => event::DeviceKeyboardInputEvent {
48			device_id,
49			input: convert_winit_keyboard_input(input),
50		}
51		.into(),
52		W::Text { codepoint } => event::DeviceTextInputEvent { device_id, codepoint }.into(),
53	}
54}
55
56pub fn convert_winit_window_event(
57	window_id: winit::window::WindowId,
58	event: winit::event::WindowEvent,
59	mouse_cache: &MouseCache,
60) -> Option<crate::event::WindowEvent> {
61	use crate::event;
62	use winit::event::WindowEvent as W;
63
64	#[allow(deprecated)]
65	match event {
66		W::Ime(_) => None,
67		W::Occluded(_) => None,
68		W::Resized(size) => Some(event::WindowResizedEvent { window_id, size: glam::UVec2::new(size.width, size.height) }.into()),
69		W::Moved(position) => Some(event::WindowMovedEvent { window_id, position: glam::IVec2::new(position.x, position.y) }.into()),
70		W::CloseRequested => Some(event::WindowCloseRequestedEvent { window_id }.into()),
71		W::Destroyed => Some(event::WindowDestroyedEvent { window_id }.into()),
72		W::DroppedFile(file) => Some(event::WindowDroppedFileEvent { window_id, file }.into()),
73		W::HoveredFile(file) => Some(event::WindowHoveredFileEvent { window_id, file }.into()),
74		W::HoveredFileCancelled => Some(event::WindowHoveredFileCancelledEvent { window_id }.into()),
75		W::ReceivedCharacter(character) => Some(event::WindowTextInputEvent { window_id, character }.into()),
76		W::Focused(true) => Some(event::WindowFocusGainedEvent { window_id }.into()),
77		W::Focused(false) => Some(event::WindowFocusLostEvent { window_id }.into()),
78		W::KeyboardInput {
79			device_id,
80			input,
81			is_synthetic,
82		} => Some(
83			event::WindowKeyboardInputEvent {
84				window_id,
85				device_id,
86				input: convert_winit_keyboard_input(input),
87				is_synthetic,
88			}
89			.into(),
90		),
91		W::ModifiersChanged(_) => None,
92		W::CursorMoved {
93			device_id,
94			position,
95			modifiers,
96		} => {
97			let position = glam::DVec2::new(position.x, position.y).as_vec2();
98			Some(event::WindowMouseMoveEvent {
99				window_id,
100				device_id,
101				position,
102				prev_position: mouse_cache.get_prev_position(window_id, device_id).unwrap_or(position),
103				modifiers,
104				buttons: mouse_cache.get_buttons(device_id).cloned().unwrap_or_default(),
105			}.into())
106		},
107		W::CursorEntered { device_id } => Some(event::WindowMouseEnterEvent {
108			window_id,
109			device_id,
110			buttons: mouse_cache.get_buttons(device_id).cloned().unwrap_or_default(),
111		}.into()),
112		W::CursorLeft { device_id } => Some(event::WindowMouseLeaveEvent {
113			window_id,
114			device_id,
115			buttons: mouse_cache.get_buttons(device_id).cloned().unwrap_or_default(),
116		}.into()),
117		W::MouseWheel {
118			device_id,
119			delta,
120			phase,
121			modifiers,
122		} => Some(
123			event::WindowMouseWheelEvent {
124				window_id,
125				device_id,
126				delta,
127				phase,
128				position: mouse_cache.get_position(window_id, device_id),
129				buttons: mouse_cache.get_buttons(device_id).cloned().unwrap_or_default(),
130				modifiers,
131			}
132			.into(),
133		),
134		W::MouseInput {
135			device_id,
136			state,
137			button,
138			modifiers,
139		} => {
140			let position = mouse_cache.get_position(window_id, device_id)?;
141			let prev_position = mouse_cache.get_prev_position(window_id, device_id).unwrap_or(position);
142			Some(event::WindowMouseButtonEvent {
143				window_id,
144				device_id,
145				button: button.into(),
146				state: state.into(),
147				position,
148				prev_position,
149				buttons: mouse_cache.get_buttons(device_id).cloned().unwrap_or_default(),
150				modifiers,
151			}.into())
152		},
153		W::TouchpadPressure {
154			device_id,
155			pressure,
156			stage,
157		} => Some(
158			event::WindowTouchpadPressureEvent {
159				window_id,
160				device_id,
161				pressure,
162				stage,
163			}
164			.into(),
165		),
166		W::AxisMotion { device_id, axis, value } => Some(
167			event::WindowAxisMotionEvent {
168				window_id,
169				device_id,
170				axis,
171				value,
172			}
173			.into(),
174		),
175		W::Touch(touch) => Some(event::WindowTouchEvent { window_id, touch }.into()),
176		W::TouchpadMagnify { device_id, delta, phase } => Some(
177			event::WindowTouchpadMagnifyEvent {
178				window_id,
179				device_id,
180				scale: 1.0 + delta,
181				phase,
182			}.into()
183		),
184		W::SmartMagnify { .. } => None,
185		W::TouchpadRotate { device_id, delta, phase } => Some(
186			event::WindowTouchpadRotateEvent {
187				window_id,
188				device_id,
189				angle_radians: delta.to_radians().into(),
190				phase,
191			}.into()
192		),
193		W::ThemeChanged(theme) => Some(
194			event::WindowThemeChangedEvent {
195				window_id,
196				theme: theme.into(),
197			}
198			.into(),
199		),
200		W::ScaleFactorChanged { scale_factor, .. } => Some(event::WindowScaleFactorChangedEvent { window_id, scale_factor }.into()),
201	}
202}
203
204pub fn convert_winit_keyboard_input(input: winit::event::KeyboardInput) -> crate::event::KeyboardInput {
205	#[allow(deprecated)]
206	crate::event::KeyboardInput {
207		scan_code: input.scancode,
208		key_code: input.virtual_keycode,
209		modifiers: input.modifiers,
210		state: input.state.into(),
211	}
212}
213
214/// Map a non-user [`Event`] to an [`Event`] with different `UserEvent`.
215///
216/// If the event was a [`Event::UserEvent`], it is returned as [`Err`].
217pub fn map_nonuser_event<T, U>(event: winit::event::Event<T>) -> Result<winit::event::Event<U>, T> {
218	use winit::event::Event::*;
219	match event {
220		UserEvent(x) => Err(x),
221		WindowEvent { window_id, event } => Ok(WindowEvent { window_id, event }),
222		DeviceEvent { device_id, event } => Ok(DeviceEvent { device_id, event }),
223		NewEvents(cause) => Ok(NewEvents(cause)),
224		MainEventsCleared => Ok(MainEventsCleared),
225		RedrawRequested(wid) => Ok(RedrawRequested(wid)),
226		RedrawEventsCleared => Ok(RedrawEventsCleared),
227		LoopDestroyed => Ok(LoopDestroyed),
228		Suspended => Ok(Suspended),
229		Resumed => Ok(Resumed),
230	}
231}
232
233impl From<winit::event::ElementState> for crate::event::ElementState {
234	fn from(other: winit::event::ElementState) -> Self {
235		match other {
236			winit::event::ElementState::Pressed => Self::Pressed,
237			winit::event::ElementState::Released => Self::Released,
238		}
239	}
240}
241
242impl From<winit::event::MouseButton> for crate::event::MouseButton {
243	fn from(other: winit::event::MouseButton) -> Self {
244		match other {
245			winit::event::MouseButton::Left => Self::Left,
246			winit::event::MouseButton::Right => Self::Right,
247			winit::event::MouseButton::Middle => Self::Middle,
248			winit::event::MouseButton::Other(x) => Self::Other(x),
249		}
250	}
251}
252
253impl From<winit::window::Theme> for crate::event::Theme {
254	fn from(other: winit::window::Theme) -> Self {
255		match other {
256			winit::window::Theme::Light => Self::Light,
257			winit::window::Theme::Dark => Self::Dark,
258		}
259	}
260}