1use std::collections::VecDeque;
4use std::ops::{Deref, DerefMut};
5
6#[derive(Clone, Debug, PartialEq, Eq)]
11pub struct QueuedEvent {
12 pub what: u16,
14 pub message: u32,
16 pub when: u32,
19 pub where_v: i16,
21 pub where_h: i16,
22 pub modifiers: u16,
24}
25
26#[derive(Clone, Debug, Default, PartialEq, Eq)]
31pub struct EventRecordSnapshot {
32 pub what: u16,
33 pub message: u32,
34 pub when: u32,
35 pub where_v: i16,
36 pub where_h: i16,
37 pub modifiers: u16,
38}
39
40#[derive(Clone, Debug, Default, PartialEq, Eq)]
42pub struct EventProbeResult {
43 pub available: bool,
44 pub record: EventRecordSnapshot,
45}
46
47#[derive(Clone, Debug, Default, PartialEq, Eq)]
52pub struct EventQueueProbeSnapshot {
53 pub post_result: Option<i16>,
54 pub event_avail: Option<EventProbeResult>,
55 pub os_event_avail: Option<EventProbeResult>,
56 pub get_os_event: Option<EventProbeResult>,
57}
58
59#[derive(Clone, Debug, PartialEq, Eq)]
63pub struct EventManagerSnapshot {
64 pub last_record: Option<EventRecordSnapshot>,
65 pub queue_probe: EventQueueProbeSnapshot,
66 pub queue_len: usize,
67 pub queued_event_types: Vec<u16>,
68 pub mouse_position: (i16, i16),
69 pub mouse_button: bool,
70 pub button_result: Option<bool>,
71 pub still_down_result: Option<bool>,
72 pub wait_mouse_up_result: Option<bool>,
73 pub key_map: [u8; 16],
74 pub lifecycle_activation_seen: bool,
75 pub lifecycle_update_seen: bool,
76 pub cursor_visible: bool,
77 pub cursor_level: i16,
78}
79
80#[derive(Clone, Debug, Default, PartialEq, Eq)]
83pub struct EventQueue {
84 events: VecDeque<QueuedEvent>,
85 menu_bar_invalid: bool,
86}
87
88impl EventQueue {
89 #[allow(dead_code)]
90 pub fn new() -> Self {
91 Self::default()
92 }
93
94 pub(crate) fn is_pristine(&self) -> bool {
95 self.events.is_empty() && !self.menu_bar_invalid
96 }
97
98 pub fn invalidate_menu_bar(&mut self) {
102 self.menu_bar_invalid = true;
103 }
104
105 pub fn take_menu_bar_invalidation(&mut self) -> bool {
107 std::mem::take(&mut self.menu_bar_invalid)
108 }
109
110 #[cfg(test)]
111 pub fn menu_bar_is_invalid(&self) -> bool {
112 self.menu_bar_invalid
113 }
114
115 pub fn merge(&mut self, mut other: Self) {
118 if other.take_menu_bar_invalidation() {
119 self.invalidate_menu_bar();
120 }
121 self.events.append(&mut other.events);
122 }
123}
124
125impl Deref for EventQueue {
126 type Target = VecDeque<QueuedEvent>;
127
128 fn deref(&self) -> &Self::Target {
129 &self.events
130 }
131}
132
133impl DerefMut for EventQueue {
134 fn deref_mut(&mut self) -> &mut Self::Target {
135 &mut self.events
136 }
137}
138
139impl FromIterator<QueuedEvent> for EventQueue {
140 fn from_iter<T: IntoIterator<Item = QueuedEvent>>(iter: T) -> Self {
141 Self {
142 events: iter.into_iter().collect(),
143 menu_bar_invalid: false,
144 }
145 }
146}
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151
152 #[test]
153 fn clone_is_a_detached_snapshot() {
154 let mut live = EventQueue::default();
155 live.push_back(QueuedEvent {
156 what: 3,
157 message: 0x1122_3344,
158 when: 0,
159 where_v: 10,
160 where_h: 20,
161 modifiers: 0x0100,
162 });
163
164 let mut snapshot = live.clone();
165 snapshot.front_mut().unwrap().message = 0x5566_7788;
166 snapshot.invalidate_menu_bar();
167
168 assert_eq!(live.front().unwrap().message, 0x1122_3344);
169 assert_eq!(snapshot.front().unwrap().message, 0x5566_7788);
170 assert!(!live.menu_bar_is_invalid());
171 assert!(snapshot.menu_bar_is_invalid());
172 }
173
174 #[test]
175 fn repeated_menu_bar_invalidations_coalesce_until_consumed() {
176 let mut queue = EventQueue::default();
177
178 queue.invalidate_menu_bar();
179 queue.invalidate_menu_bar();
180
181 assert!(queue.take_menu_bar_invalidation());
182 assert!(!queue.take_menu_bar_invalidation());
183 }
184
185 #[test]
186 fn queue_ordering_and_mutations_are_preserved() {
187 let mut queue = EventQueue::default();
188 queue.push_back(QueuedEvent {
189 what: 1,
190 message: 0x100,
191 when: 0,
192 where_v: 1,
193 where_h: 2,
194 modifiers: 0,
195 });
196 queue.push_back(QueuedEvent {
197 what: 2,
198 message: 0x200,
199 when: 0,
200 where_v: 3,
201 where_h: 4,
202 modifiers: 0,
203 });
204
205 assert_eq!(queue.len(), 2);
206 assert_eq!(queue.pop_front().map(|e| e.message), Some(0x100));
207 assert_eq!(queue.pop_front().map(|e| e.message), Some(0x200));
208 assert!(queue.is_empty());
209 }
210
211 #[test]
212 fn merge_preserves_order_and_combines_invalidation() {
213 let mut target = EventQueue::default();
214 target.push_back(QueuedEvent {
215 what: 1,
216 message: 0x111,
217 when: 0,
218 where_v: 1,
219 where_h: 2,
220 modifiers: 0,
221 });
222
223 let mut source = EventQueue::default();
224 source.push_back(QueuedEvent {
225 what: 2,
226 message: 0x222,
227 when: 0,
228 where_v: 3,
229 where_h: 4,
230 modifiers: 0,
231 });
232 source.invalidate_menu_bar();
233
234 assert!(!target.menu_bar_is_invalid());
235 assert!(source.menu_bar_is_invalid());
236
237 target.merge(source);
238
239 assert_eq!(target.len(), 2);
240 assert_eq!(target[0].message, 0x111);
241 assert_eq!(target[1].message, 0x222);
242 assert!(target.menu_bar_is_invalid());
243 }
244}