winit_event_helper/callbacks/
window.rs

1use std::path::PathBuf;
2
3use winit::{
4    dpi::{PhysicalPosition, PhysicalSize},
5    event::{AxisId, Ime, KeyboardInput, WindowEvent, TouchPhase},
6    window::Theme,
7};
8
9use crate::{
10    create_callbacks,
11    definitions::{CursorState, LineDelta, PixelDelta, QuitWindow},
12    input::data::InputData,
13    IdLessTouch,
14};
15
16#[cfg(feature = "windows_with_device_ids")]
17use crate::input::data::InputDataWithId;
18
19create_callbacks! {
20    /// A collection of data used for [WindowEvent] callbacks.
21    ///
22    /// [WindowCallbacks] holds the callbacks themselves.
23    pub struct WindowCallbackData: WindowCallbacks<D> {
24        ign opt pub position: PhysicalPosition<i32>,
25        ign opt pub size: PhysicalSize<u32>,
26        clr opt pub focused: bool,
27        clr opt pub occluded: bool,
28        clr opt pub moved: PhysicalPosition<i32>,
29        clr opt pub resized: PhysicalSize<u32>,
30        clr opt pub cursor_state: CursorState,
31        clr opt pub cursor_entered: bool,
32        clr opt pub cursor_moved: PhysicalPosition<f64>,
33        clr opt pub quit: QuitWindow,
34        clr opt pub scale_factor: f64,
35        clr opt pub theme: Theme,
36        clr opt pub hover_cancelled: bool,
37        clr opt pub mouse_wheel: (LineDelta, PixelDelta),
38        clr opt pub smart_magnify: usize,
39        clr vec pub text: char,
40        clr vec pub ime: Ime,
41        clr vec pub touch: IdLessTouch,
42        clr vec pub touchpad_pressure: (i64, f32),
43        clr vec pub touchpad_magnify: (f64, TouchPhase),
44        clr vec pub touchpad_rotate: (f32, TouchPhase),
45        clr vec pub axis_motion: (AxisId, f64),
46        clr set pub hovered_files: PathBuf,
47        clr set pub dropped_files: PathBuf,
48        clr cus pub inputs: InputData,
49        #[cfg(feature="windows_with_device_ids")]
50        clr map pub cursor_entered_with_id: DeviceId => Option<bool>,
51        #[cfg(feature="windows_with_device_ids")]
52        clr map pub cursor_moved_with_id: DeviceId => Option<PhysicalPosition<f64>>,
53        #[cfg(feature="windows_with_device_ids")]
54        clr map pub touch_with_id: DeviceId => Vec<IdLessTouch>,
55        #[cfg(feature="windows_with_device_ids")]
56        clr map pub touchpad_magnify_with_id: DeviceId => Vec<(f64, TouchPhase)>,
57        #[cfg(feature="windows_with_device_ids")]
58        clr map pub touchpad_rotate_with_id: DeviceId => Vec<(f32, TouchPhase)>,
59        #[cfg(feature="windows_with_device_ids")]
60        clr map pub touchpad_pressure_with_id: DeviceId => Vec<(i64, f32)>,
61        #[cfg(feature="windows_with_device_ids")]
62        clr map pub mouse_wheel_with_id: DeviceId => (LineDelta, PixelDelta),
63        #[cfg(feature="windows_with_device_ids")]
64        clr map pub smart_magnify_with_id: DeviceId => Option<usize>,
65        #[cfg(feature="windows_with_device_ids")]
66        clr map pub axis_motion_with_id: DeviceId => Vec<(AxisId, f64)>,
67        #[cfg(feature="windows_with_device_ids")]
68        clr cus pub inputs_with_id: InputDataWithId<D>,
69    }
70}
71
72impl WindowCallbackData {
73    pub fn update(&mut self, event: &WindowEvent) {
74        #[allow(unused_variables)]
75        match event {
76            &WindowEvent::Focused(is_focused) => self.focused = Some(is_focused),
77            &WindowEvent::Moved(new_position) => {
78                self.moved = Some(new_position);
79                self.position = Some(new_position);
80            }
81            &WindowEvent::Resized(new_size) => {
82                self.resized = Some(new_size);
83                self.size = Some(new_size);
84            }
85            &WindowEvent::MouseInput {
86                device_id,
87                button,
88                state,
89                ..
90            } => {
91                self.inputs.update(button, state);
92
93                #[cfg(feature = "windows_with_device_ids")]
94                self.inputs_with_id
95                    .entry(device_id)
96                    .or_default()
97                    .update(button, state);
98            }
99            &WindowEvent::Destroyed => {
100                self.quit
101                    .get_or_insert(QuitWindow::empty())
102                    .insert(QuitWindow::DESTROYED);
103            }
104            &WindowEvent::ReceivedCharacter(codepoint) => {
105                self.text.push(codepoint);
106            }
107            &WindowEvent::KeyboardInput {
108                device_id,
109                input:
110                    KeyboardInput {
111                        virtual_keycode,
112                        state,
113                        scancode,
114                        ..
115                    },
116                ..
117            } => {
118                self.inputs.update(scancode, state);
119
120                #[cfg(feature = "windows_with_device_ids")]
121                self.inputs_with_id
122                    .entry(device_id)
123                    .or_default()
124                    .update(scancode, state);
125
126                if let Some(key) = virtual_keycode {
127                    self.inputs.update(key, state);
128
129                    #[cfg(feature = "windows_with_device_ids")]
130                    self.inputs_with_id
131                        .entry(device_id)
132                        .or_default()
133                        .update(key, state);
134                }
135            }
136            &WindowEvent::ModifiersChanged(modifiers) => {
137                self.inputs.update_modifiers(modifiers);
138            }
139            &WindowEvent::MouseWheel {
140                device_id, delta, ..
141            } => {
142                let (lines, pixels) = self.mouse_wheel.get_or_insert(Default::default());
143                *lines += delta.try_into().unwrap_or_default();
144                *pixels += delta.try_into().unwrap_or_default();
145
146                #[cfg(feature = "windows_with_device_ids")]
147                {
148                    let (lines, pixels) = self.mouse_wheel_with_id.entry(device_id).or_default();
149                    *lines += delta.try_into().unwrap_or_default();
150                    *pixels += delta.try_into().unwrap_or_default();
151                }
152            }
153            &WindowEvent::AxisMotion {
154                device_id,
155                axis,
156                value,
157                ..
158            } => {
159                self.axis_motion.push((axis, value));
160
161                #[cfg(feature = "windows_with_device_ids")]
162                self.axis_motion_with_id
163                    .entry(device_id)
164                    .or_default()
165                    .push((axis, value));
166            }
167            WindowEvent::CloseRequested => {
168                self.quit
169                    .get_or_insert(QuitWindow::empty())
170                    .insert(QuitWindow::CLOSE_REQUESTED);
171            }
172            WindowEvent::DroppedFile(path) => {
173                self.dropped_files.insert(path.clone());
174            }
175            WindowEvent::HoveredFile(path) => {
176                self.hovered_files.insert(path.clone());
177            }
178            WindowEvent::HoveredFileCancelled => self.hover_cancelled = Some(true),
179            WindowEvent::Ime(ime) => self.ime.push(ime.clone()),
180            &WindowEvent::Occluded(is_occluded) => self.occluded = Some(is_occluded),
181            &WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
182                self.scale_factor = Some(scale_factor)
183            }
184            &WindowEvent::ThemeChanged(theme) => self.theme = Some(theme),
185            &WindowEvent::Touch(touch) => {
186                self.touch.push(touch.into());
187
188                #[cfg(feature = "windows_with_device_ids")]
189                self.touch_with_id
190                    .entry(touch.device_id)
191                    .or_default()
192                    .push(touch.into());
193            }
194            &WindowEvent::TouchpadPressure {
195                device_id,
196                stage,
197                pressure,
198                ..
199            } => {
200                self.touchpad_pressure.push((stage, pressure));
201
202                #[cfg(feature = "windows_with_device_ids")]
203                self.touchpad_pressure_with_id
204                    .entry(device_id)
205                    .or_default()
206                    .push((stage, pressure));
207            }
208            &WindowEvent::CursorMoved {
209                device_id,
210                position,
211                ..
212            } => {
213                self.cursor_moved = Some(position);
214
215                #[cfg(feature = "windows_with_device_ids")]
216                {
217                    *self.cursor_moved_with_id.entry(device_id).or_default() = Some(position);
218
219                }
220            },
221            &WindowEvent::CursorEntered { device_id } => {
222                self.cursor_entered = Some(true);
223
224                #[cfg(feature = "windows_with_device_ids")]
225                {
226                    *self.cursor_entered_with_id.entry(device_id).or_default() = Some(true);
227                }
228            }
229            &WindowEvent::CursorLeft { device_id } => {
230                self.cursor_entered = Some(false);
231
232                #[cfg(feature = "windows_with_device_ids")]
233                {
234                    *self.cursor_entered_with_id.entry(device_id).or_default() = Some(false);
235                }
236            }
237            &WindowEvent::TouchpadMagnify {
238                device_id,
239                delta,
240                phase,
241            } => {
242                self.touchpad_magnify.push((delta, phase));
243
244                #[cfg(feature = "windows_with_device_ids")]
245                {
246                    self.touchpad_magnify_with_id.entry(device_id).or_default().push((delta, phase));
247                }
248            },
249            &WindowEvent::TouchpadRotate {
250                device_id,
251                delta,
252                phase,
253            } => {
254                self.touchpad_rotate.push((delta, phase));
255
256                #[cfg(feature = "windows_with_device_ids")]
257                {
258                    self.touchpad_rotate_with_id.entry(device_id).or_default().push((delta, phase));
259                }
260            },
261            &WindowEvent::SmartMagnify { device_id } => {
262                *self.smart_magnify.get_or_insert(0) += 1;
263
264                #[cfg(feature = "windows_with_device_ids")]
265                {
266                    *self.smart_magnify_with_id.entry(device_id).or_default() += 1;
267                }
268            },
269        }
270    }
271}