1use conrod_core::{
2 event::Input,
3 input::{self, Button},
4};
5use vek::*;
6use winit::event::{self, WindowEvent};
7
8fn conrod_convert_key(key: &winit::keyboard::Key) -> input::Key {
13 match key {
14 winit::keyboard::Key::Named(key) => match key {
15 winit::keyboard::NamedKey::Escape => input::keyboard::Key::Escape,
16 winit::keyboard::NamedKey::F1 => input::keyboard::Key::F1,
17 winit::keyboard::NamedKey::F2 => input::keyboard::Key::F2,
18 winit::keyboard::NamedKey::F3 => input::keyboard::Key::F3,
19 winit::keyboard::NamedKey::F4 => input::keyboard::Key::F4,
20 winit::keyboard::NamedKey::F5 => input::keyboard::Key::F5,
21 winit::keyboard::NamedKey::F6 => input::keyboard::Key::F6,
22 winit::keyboard::NamedKey::F7 => input::keyboard::Key::F7,
23 winit::keyboard::NamedKey::F8 => input::keyboard::Key::F8,
24 winit::keyboard::NamedKey::F9 => input::keyboard::Key::F9,
25 winit::keyboard::NamedKey::F10 => input::keyboard::Key::F10,
26 winit::keyboard::NamedKey::F11 => input::keyboard::Key::F11,
27 winit::keyboard::NamedKey::F12 => input::keyboard::Key::F12,
28 winit::keyboard::NamedKey::F13 => input::keyboard::Key::F13,
29 winit::keyboard::NamedKey::F14 => input::keyboard::Key::F14,
30 winit::keyboard::NamedKey::F15 => input::keyboard::Key::F15,
31 winit::keyboard::NamedKey::F16 => input::keyboard::Key::F16,
32 winit::keyboard::NamedKey::F17 => input::keyboard::Key::F17,
33 winit::keyboard::NamedKey::F18 => input::keyboard::Key::F18,
34 winit::keyboard::NamedKey::F19 => input::keyboard::Key::F19,
35 winit::keyboard::NamedKey::F20 => input::keyboard::Key::F20,
36 winit::keyboard::NamedKey::F21 => input::keyboard::Key::F21,
37 winit::keyboard::NamedKey::F22 => input::keyboard::Key::F22,
38 winit::keyboard::NamedKey::F23 => input::keyboard::Key::F23,
39 winit::keyboard::NamedKey::F24 => input::keyboard::Key::F24,
40 winit::keyboard::NamedKey::ScrollLock => input::keyboard::Key::ScrollLock,
41 winit::keyboard::NamedKey::Pause => input::keyboard::Key::Pause,
42 winit::keyboard::NamedKey::Insert => input::keyboard::Key::Insert,
43 winit::keyboard::NamedKey::Home => input::keyboard::Key::Home,
44 winit::keyboard::NamedKey::Delete => input::keyboard::Key::Delete,
45 winit::keyboard::NamedKey::End => input::keyboard::Key::End,
46 winit::keyboard::NamedKey::PageDown => input::keyboard::Key::PageDown,
47 winit::keyboard::NamedKey::PageUp => input::keyboard::Key::PageUp,
48 winit::keyboard::NamedKey::ArrowLeft => input::keyboard::Key::Left,
49 winit::keyboard::NamedKey::ArrowUp => input::keyboard::Key::Up,
50 winit::keyboard::NamedKey::ArrowRight => input::keyboard::Key::Right,
51 winit::keyboard::NamedKey::ArrowDown => input::keyboard::Key::Down,
52 winit::keyboard::NamedKey::Backspace => input::keyboard::Key::Backspace,
53 winit::keyboard::NamedKey::Enter => input::keyboard::Key::Return,
54 winit::keyboard::NamedKey::Space => input::keyboard::Key::Space,
55 winit::keyboard::NamedKey::AudioVolumeMute => input::keyboard::Key::AudioMute,
56 winit::keyboard::NamedKey::MediaTrackNext => input::keyboard::Key::AudioNext,
57 winit::keyboard::NamedKey::Power => input::keyboard::Key::Power,
58 winit::keyboard::NamedKey::MediaTrackPrevious => input::keyboard::Key::AudioPrev,
59 winit::keyboard::NamedKey::Tab => input::keyboard::Key::Tab,
60 winit::keyboard::NamedKey::AudioVolumeDown => input::keyboard::Key::VolumeDown,
61 winit::keyboard::NamedKey::AudioVolumeUp => input::keyboard::Key::VolumeUp,
62 winit::keyboard::NamedKey::Copy => input::keyboard::Key::Copy,
63 winit::keyboard::NamedKey::Paste => input::keyboard::Key::Paste,
64 winit::keyboard::NamedKey::Cut => input::keyboard::Key::Cut,
65 winit::keyboard::NamedKey::Shift => input::keyboard::Key::RShift,
68 winit::keyboard::NamedKey::Control => input::keyboard::Key::RCtrl,
69 winit::keyboard::NamedKey::Alt => input::keyboard::Key::RAlt,
70 _ => input::keyboard::Key::Unknown,
71 },
72 winit::keyboard::Key::Character(c) => match c.as_str() {
73 "a" | "A" => input::keyboard::Key::A,
74 "b" | "B" => input::keyboard::Key::B,
75 "c" | "C" => input::keyboard::Key::C,
76 "d" | "D" => input::keyboard::Key::D,
77 "e" | "E" => input::keyboard::Key::E,
78 "f" | "F" => input::keyboard::Key::F,
79 "g" | "G" => input::keyboard::Key::G,
80 "h" | "H" => input::keyboard::Key::H,
81 "i" | "I" => input::keyboard::Key::I,
82 "j" | "J" => input::keyboard::Key::J,
83 "k" | "K" => input::keyboard::Key::K,
84 "l" | "L" => input::keyboard::Key::L,
85 "m" | "M" => input::keyboard::Key::M,
86 "n" | "N" => input::keyboard::Key::N,
87 "o" | "O" => input::keyboard::Key::O,
88 "p" | "P" => input::keyboard::Key::P,
89 "q" | "Q" => input::keyboard::Key::Q,
90 "r" | "R" => input::keyboard::Key::R,
91 "s" | "S" => input::keyboard::Key::S,
92 "t" | "T" => input::keyboard::Key::T,
93 "u" | "U" => input::keyboard::Key::U,
94 "v" | "V" => input::keyboard::Key::V,
95 "w" | "W" => input::keyboard::Key::W,
96 "x" | "X" => input::keyboard::Key::X,
97 "y" | "Y" => input::keyboard::Key::Y,
98 "z" | "Z" => input::keyboard::Key::Z,
99 "*" => input::keyboard::Key::Asterisk,
100 "\\" => input::keyboard::Key::Backslash,
101 "^" => input::keyboard::Key::Caret,
102 ":" => input::keyboard::Key::Colon,
103 "," => input::keyboard::Key::Comma,
104 "=" => input::keyboard::Key::Equals,
105 "-" => input::keyboard::Key::Minus,
106 "+" => input::keyboard::Key::Plus,
107 ";" => input::keyboard::Key::Semicolon,
108 "/" => input::keyboard::Key::Slash,
109 " " => input::keyboard::Key::Space,
110 "_" => input::keyboard::Key::Underscore,
111 _ => input::keyboard::Key::Unknown,
112 },
113 winit::keyboard::Key::Unidentified(_) | winit::keyboard::Key::Dead(_) => {
114 input::keyboard::Key::Unknown
115 },
116 }
117}
118
119fn conrod_convert_mouse_button(button: &event::MouseButton) -> input::Button {
120 input::Button::Mouse(match button {
121 event::MouseButton::Left => input::MouseButton::Left,
122 event::MouseButton::Right => input::MouseButton::Right,
123 event::MouseButton::Middle => input::MouseButton::Middle,
124 event::MouseButton::Other(0) => input::MouseButton::X1,
125 event::MouseButton::Other(1) => input::MouseButton::X2,
126 event::MouseButton::Other(2) => input::MouseButton::Button6,
127 event::MouseButton::Other(3) => input::MouseButton::Button7,
128 event::MouseButton::Other(4) => input::MouseButton::Button8,
129 _ => input::MouseButton::Unknown,
130 })
131}
132
133fn conrod_convert_event(
134 event: &WindowEvent,
135 window: &winit::window::Window,
136 modifiers: winit::keyboard::ModifiersState,
137) -> Option<Input> {
138 let hidpi = window.scale_factor();
139 let winit::dpi::LogicalSize { width, height } = window.inner_size().to_logical::<f64>(hidpi);
140 let tx = |x: f64| x - width / 2.0;
141 let ty = |y: f64| -(y - height / 2.0);
142
143 Some(match event {
144 WindowEvent::Resized(physical_size) => {
145 let winit::dpi::LogicalSize { width, height } = physical_size.to_logical::<f64>(hidpi);
146 Input::Resize(width as _, height as _)
147 },
148 WindowEvent::Focused(focused) => Input::Focus(*focused),
149 WindowEvent::KeyboardInput { event, .. } => {
150 if let Some(text) = &event.text {
154 if let Some(c) = text.chars().next() {
155 if !c.is_control()
156 && !modifiers.alt_key()
157 && !modifiers.control_key()
158 && !modifiers.super_key()
159 {
160 return event.state.is_pressed().then(|| Input::Text(c.to_string()));
161 }
162 }
163 }
164
165 let key = input::Button::Keyboard(conrod_convert_key(&event.logical_key));
166
167 match event.state {
168 event::ElementState::Pressed => Input::Press(key),
169 event::ElementState::Released => Input::Release(key),
170 }
171 },
172 WindowEvent::Touch(event::Touch {
173 phase,
174 location,
175 id,
176 ..
177 }) => {
178 let winit::dpi::LogicalPosition { x, y } = location.to_logical::<f64>(hidpi);
179 let phase = match phase {
180 event::TouchPhase::Started => input::touch::Phase::Start,
181 event::TouchPhase::Moved => input::touch::Phase::Move,
182 event::TouchPhase::Cancelled => input::touch::Phase::Cancel,
183 event::TouchPhase::Ended => input::touch::Phase::End,
184 };
185 let xy = [tx(x), ty(y)];
186 let id = input::touch::Id::new(*id);
187 let touch = input::Touch { phase, id, xy };
188 Input::Touch(touch)
189 },
190 WindowEvent::CursorMoved { position, .. } => {
191 let winit::dpi::LogicalPosition { x, y } = position.to_logical::<f64>(hidpi);
192 let x = tx(x);
193 let y = ty(y);
194 let motion = input::Motion::MouseCursor { x, y };
195 Input::Motion(motion)
196 },
197 WindowEvent::MouseWheel { delta, .. } => match delta {
198 event::MouseScrollDelta::PixelDelta(physical_position) => {
199 let winit::dpi::LogicalPosition { x, y } =
200 physical_position.to_logical::<f64>(hidpi);
201 let x = x as conrod_core::Scalar;
202 let y = -y as conrod_core::Scalar;
203 let motion = input::Motion::Scroll { x, y };
204 Input::Motion(motion)
205 },
206 event::MouseScrollDelta::LineDelta(x, y) => {
207 const ARBITRARY_POINTS_PER_LINE_FACTOR: conrod_core::Scalar = 10.0;
208 let x = ARBITRARY_POINTS_PER_LINE_FACTOR * *x as conrod_core::Scalar;
209 let y = ARBITRARY_POINTS_PER_LINE_FACTOR * -y as conrod_core::Scalar;
210 Input::Motion(input::Motion::Scroll { x, y })
211 },
212 },
213 WindowEvent::MouseInput { state, button, .. } => {
214 let button = conrod_convert_mouse_button(button);
215 match state {
216 event::ElementState::Pressed => Input::Press(button),
217 event::ElementState::Released => Input::Release(button),
218 }
219 },
220 WindowEvent::RedrawRequested => Input::Redraw,
221 _ => return None,
222 })
223}
224
225#[derive(Clone, Debug)]
226pub struct Event(pub Input);
227
228impl Event {
229 pub fn try_from(
230 event: &event::Event<()>,
231 window: &winit::window::Window,
232 modifiers: winit::keyboard::ModifiersState,
233 ) -> Option<Self> {
234 match event {
235 event::Event::WindowEvent { event, .. } => {
236 conrod_convert_event(event, window, modifiers).map(Self)
237 },
238 _ => None,
239 }
240 }
241
242 pub fn is_keyboard_or_mouse(&self) -> bool {
243 matches!(
244 self.0,
245 Input::Press(_)
246 | Input::Release(_)
247 | Input::Motion(_)
248 | Input::Touch(_)
249 | Input::Text(_)
250 )
251 }
252
253 pub fn is_keyboard(&self) -> bool {
254 matches!(
255 self.0,
256 Input::Press(Button::Keyboard(_))
257 | Input::Release(Button::Keyboard(_))
258 | Input::Text(_)
259 )
260 }
261
262 pub fn new_resize(dims: Vec2<f64>) -> Self { Self(Input::Resize(dims.x, dims.y)) }
263}