• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //! Contains the InputVerifier, used to validate a stream of input events.
18 
19 use crate::ffi::RustPointerProperties;
20 use crate::input::{DeviceId, MotionAction, MotionButton, MotionFlags, Source, SourceClass};
21 use log::info;
22 use std::collections::HashMap;
23 use std::collections::HashSet;
24 
25 /// Represents a movement or state change event from a pointer device. The Rust equivalent of the
26 /// C++ NotifyMotionArgs struct.
27 #[derive(Clone, Copy)]
28 pub struct NotifyMotionArgs<'a> {
29     /// The ID of the device that emitted the event.
30     pub device_id: DeviceId,
31 
32     /// The type of device that emitted the event.
33     pub source: Source,
34 
35     /// The type of event that took place.
36     pub action: MotionAction,
37 
38     /// The properties of each of the pointers involved in the event.
39     pub pointer_properties: &'a [RustPointerProperties],
40 
41     /// Flags applied to the event.
42     pub flags: MotionFlags,
43 
44     /// The set of buttons that were pressed at the time of the event.
45     ///
46     /// We allow DOWN events to include buttons in their state for which BUTTON_PRESS events haven't
47     /// been sent yet. In that case, the DOWN should be immediately followed by BUTTON_PRESS events
48     /// for those buttons, building up to a button state matching that of the DOWN. For example, if
49     /// the user presses the primary and secondary buttons at exactly the same time, we'd expect
50     /// this sequence:
51     ///
52     /// | Action         | Action button | Button state           |
53     /// |----------------|---------------|------------------------|
54     /// | `HOVER_EXIT`   | -             | -                      |
55     /// | `DOWN`         | -             | `PRIMARY`, `SECONDARY` |
56     /// | `BUTTON_PRESS` | `PRIMARY`     | `PRIMARY`              |
57     /// | `BUTTON_PRESS` | `SECONDARY`   | `PRIMARY`, `SECONDARY` |
58     /// | `MOVE`         | -             | `PRIMARY`, `SECONDARY` |
59     pub button_state: MotionButton,
60 }
61 
62 /// Verifies the properties of an event that should always be true, regardless of the current state.
verify_event(event: NotifyMotionArgs<'_>, verify_buttons: bool) -> Result<(), String>63 fn verify_event(event: NotifyMotionArgs<'_>, verify_buttons: bool) -> Result<(), String> {
64     let pointer_count = event.pointer_properties.len();
65     if pointer_count < 1 {
66         return Err(format!("Invalid {} event: no pointers", event.action));
67     }
68     match event.action {
69         MotionAction::Down
70         | MotionAction::HoverEnter
71         | MotionAction::HoverExit
72         | MotionAction::HoverMove
73         | MotionAction::Up => {
74             if pointer_count != 1 {
75                 return Err(format!(
76                     "Invalid {} event: there are {} pointers in the event",
77                     event.action, pointer_count
78                 ));
79             }
80         }
81 
82         MotionAction::Cancel => {
83             if !event.flags.contains(MotionFlags::CANCELED) {
84                 return Err(format!(
85                     "For ACTION_CANCEL, must set FLAG_CANCELED. Received flags: {:#?}",
86                     event.flags
87                 ));
88             }
89         }
90 
91         MotionAction::PointerDown { action_index } | MotionAction::PointerUp { action_index } => {
92             if action_index >= pointer_count {
93                 return Err(format!(
94                     "Got {}, but event has {} pointer(s)",
95                     event.action, pointer_count
96                 ));
97             }
98         }
99 
100         MotionAction::ButtonPress { action_button }
101         | MotionAction::ButtonRelease { action_button } => {
102             if verify_buttons {
103                 let button_count = action_button.iter().count();
104                 if button_count != 1 {
105                     return Err(format!(
106                         "Invalid {} event: must specify a single action button, not {} action \
107                          buttons",
108                         event.action, button_count
109                     ));
110                 }
111             }
112         }
113 
114         _ => {}
115     }
116     Ok(())
117 }
118 
119 /// Keeps track of the button state for a single device and verifies events against it.
120 #[derive(Default)]
121 struct ButtonVerifier {
122     /// The current button state of the device.
123     button_state: MotionButton,
124 
125     /// The set of "pending buttons", which were seen in the last DOWN event's button state but
126     /// for which we haven't seen BUTTON_PRESS events yet (see [`NotifyMotionArgs::button_state`]).
127     pending_buttons: MotionButton,
128 }
129 
130 impl ButtonVerifier {
process_event(&mut self, event: NotifyMotionArgs<'_>) -> Result<(), String>131     pub fn process_event(&mut self, event: NotifyMotionArgs<'_>) -> Result<(), String> {
132         if !self.pending_buttons.is_empty() {
133             // We just saw a DOWN with some additional buttons in its state, so it should be
134             // immediately followed by ButtonPress events for those buttons.
135             match event.action {
136                 MotionAction::ButtonPress { action_button }
137                     if self.pending_buttons.contains(action_button) =>
138                 {
139                     self.pending_buttons -= action_button;
140                 }
141                 _ => {
142                     return Err(format!(
143                         "After DOWN event, expected BUTTON_PRESS event(s) for {:?}, but got {}",
144                         self.pending_buttons, event.action
145                     ));
146                 }
147             }
148         }
149         let expected_state = match event.action {
150             MotionAction::Down => {
151                 if self.button_state - event.button_state != MotionButton::empty() {
152                     return Err(format!(
153                         "DOWN event button state is missing {:?}",
154                         self.button_state - event.button_state
155                     ));
156                 }
157                 self.pending_buttons = event.button_state - self.button_state;
158                 // We've already checked that the state isn't missing any already-down buttons, and
159                 // extra buttons are valid on DOWN actions, so bypass the expected state check.
160                 event.button_state
161             }
162             MotionAction::ButtonPress { action_button } => {
163                 if self.button_state.contains(action_button) {
164                     return Err(format!(
165                         "Duplicate BUTTON_PRESS; button state already contains {action_button:?}"
166                     ));
167                 }
168                 self.button_state | action_button
169             }
170             MotionAction::ButtonRelease { action_button } => {
171                 if !self.button_state.contains(action_button) {
172                     return Err(format!(
173                         "Invalid BUTTON_RELEASE; button state doesn't contain {action_button:?}",
174                     ));
175                 }
176                 self.button_state - action_button
177             }
178             _ => self.button_state,
179         };
180         if event.button_state != expected_state {
181             return Err(format!(
182                 "Expected {} button state to be {:?}, but was {:?}",
183                 event.action, expected_state, event.button_state
184             ));
185         }
186         // DOWN events can have pending buttons, so don't update the state for them.
187         if event.action != MotionAction::Down {
188             self.button_state = event.button_state;
189         }
190         Ok(())
191     }
192 }
193 
194 /// The InputVerifier is used to validate a stream of input events.
195 pub struct InputVerifier {
196     name: String,
197     should_log: bool,
198     verify_buttons: bool,
199     touching_pointer_ids_by_device: HashMap<DeviceId, HashSet<i32>>,
200     hovering_pointer_ids_by_device: HashMap<DeviceId, HashSet<i32>>,
201     button_verifier_by_device: HashMap<DeviceId, ButtonVerifier>,
202 }
203 
204 impl InputVerifier {
205     /// Create a new InputVerifier.
new(name: &str, should_log: bool, verify_buttons: bool) -> Self206     pub fn new(name: &str, should_log: bool, verify_buttons: bool) -> Self {
207         logger::init(
208             logger::Config::default()
209                 .with_tag_on_device("InputVerifier")
210                 .with_max_level(log::LevelFilter::Trace),
211         );
212         Self {
213             name: name.to_owned(),
214             should_log,
215             verify_buttons,
216             touching_pointer_ids_by_device: HashMap::new(),
217             hovering_pointer_ids_by_device: HashMap::new(),
218             button_verifier_by_device: HashMap::new(),
219         }
220     }
221 
222     /// Process a pointer movement event from an InputDevice.
223     /// If the event is not valid, we return an error string that describes the issue.
process_movement(&mut self, event: NotifyMotionArgs<'_>) -> Result<(), String>224     pub fn process_movement(&mut self, event: NotifyMotionArgs<'_>) -> Result<(), String> {
225         if !event.source.is_from_class(SourceClass::Pointer) {
226             // Skip non-pointer sources like MOUSE_RELATIVE for now
227             return Ok(());
228         }
229         if self.should_log {
230             info!(
231                 "Processing {} for device {:?} ({} pointer{}) on {}",
232                 event.action,
233                 event.device_id,
234                 event.pointer_properties.len(),
235                 if event.pointer_properties.len() == 1 { "" } else { "s" },
236                 self.name
237             );
238         }
239 
240         verify_event(event, self.verify_buttons)?;
241 
242         if self.verify_buttons {
243             self.button_verifier_by_device
244                 .entry(event.device_id)
245                 .or_default()
246                 .process_event(event)?;
247         }
248 
249         match event.action {
250             MotionAction::Down => {
251                 if self.touching_pointer_ids_by_device.contains_key(&event.device_id) {
252                     return Err(format!(
253                         "{}: Invalid DOWN event - pointers already down for device {:?}: {:?}",
254                         self.name, event.device_id, self.touching_pointer_ids_by_device
255                     ));
256                 }
257                 let it = self.touching_pointer_ids_by_device.entry(event.device_id).or_default();
258                 it.insert(event.pointer_properties[0].id);
259             }
260             MotionAction::PointerDown { action_index } => {
261                 if !self.touching_pointer_ids_by_device.contains_key(&event.device_id) {
262                     return Err(format!(
263                         "{}: Received POINTER_DOWN but no pointers are currently down \
264                         for device {:?}",
265                         self.name, event.device_id
266                     ));
267                 }
268                 let it = self.touching_pointer_ids_by_device.get_mut(&event.device_id).unwrap();
269                 if it.len() != event.pointer_properties.len() - 1 {
270                     return Err(format!(
271                         "{}: There are currently {} touching pointers, but the incoming \
272                          POINTER_DOWN event has {}",
273                         self.name,
274                         it.len(),
275                         event.pointer_properties.len()
276                     ));
277                 }
278                 let pointer_id = event.pointer_properties[action_index].id;
279                 if it.contains(&pointer_id) {
280                     return Err(format!(
281                         "{}: Pointer with id={} already present found in the properties",
282                         self.name, pointer_id
283                     ));
284                 }
285                 it.insert(pointer_id);
286             }
287             MotionAction::Move => {
288                 if !self.ensure_touching_pointers_match(event.device_id, event.pointer_properties) {
289                     return Err(format!(
290                         "{}: ACTION_MOVE touching pointers don't match",
291                         self.name
292                     ));
293                 }
294             }
295             MotionAction::PointerUp { action_index } => {
296                 if !self.ensure_touching_pointers_match(event.device_id, event.pointer_properties) {
297                     return Err(format!(
298                         "{}: ACTION_POINTER_UP touching pointers don't match",
299                         self.name
300                     ));
301                 }
302                 let it = self.touching_pointer_ids_by_device.get_mut(&event.device_id).unwrap();
303                 let pointer_id = event.pointer_properties[action_index].id;
304                 it.remove(&pointer_id);
305             }
306             MotionAction::Up => {
307                 if !self.touching_pointer_ids_by_device.contains_key(&event.device_id) {
308                     return Err(format!(
309                         "{} Received ACTION_UP but no pointers are currently down for device {:?}",
310                         self.name, event.device_id
311                     ));
312                 }
313                 let it = self.touching_pointer_ids_by_device.get_mut(&event.device_id).unwrap();
314                 if it.len() != 1 {
315                     return Err(format!(
316                         "{}: Got ACTION_UP, but we have pointers: {:?} for device {:?}",
317                         self.name, it, event.device_id
318                     ));
319                 }
320                 let pointer_id = event.pointer_properties[0].id;
321                 if !it.contains(&pointer_id) {
322                     return Err(format!(
323                         "{}: Got ACTION_UP, but pointerId {} is not touching. Touching pointers:\
324                         {:?} for device {:?}",
325                         self.name, pointer_id, it, event.device_id
326                     ));
327                 }
328                 self.touching_pointer_ids_by_device.remove(&event.device_id);
329             }
330             MotionAction::Cancel => {
331                 if !self.ensure_touching_pointers_match(event.device_id, event.pointer_properties) {
332                     return Err(format!(
333                         "{}: Got ACTION_CANCEL, but the pointers don't match. \
334                         Existing pointers: {:?}",
335                         self.name, self.touching_pointer_ids_by_device
336                     ));
337                 }
338                 self.touching_pointer_ids_by_device.remove(&event.device_id);
339             }
340             /*
341              * The hovering protocol currently supports a single pointer only, because we do not
342              * have ACTION_HOVER_POINTER_ENTER or ACTION_HOVER_POINTER_EXIT.
343              * Still, we are keeping the infrastructure here pretty general in case that is
344              * eventually supported.
345              */
346             MotionAction::HoverEnter => {
347                 if self.hovering_pointer_ids_by_device.contains_key(&event.device_id) {
348                     return Err(format!(
349                         "{}: Invalid HOVER_ENTER event - pointers already hovering for device {:?}:\
350                         {:?}",
351                         self.name, event.device_id, self.hovering_pointer_ids_by_device
352                     ));
353                 }
354                 let it = self.hovering_pointer_ids_by_device.entry(event.device_id).or_default();
355                 it.insert(event.pointer_properties[0].id);
356             }
357             MotionAction::HoverMove => {
358                 // For compatibility reasons, we allow HOVER_MOVE without a prior HOVER_ENTER.
359                 // If there was no prior HOVER_ENTER, just start a new hovering pointer.
360                 let it = self.hovering_pointer_ids_by_device.entry(event.device_id).or_default();
361                 it.insert(event.pointer_properties[0].id);
362             }
363             MotionAction::HoverExit => {
364                 if !self.hovering_pointer_ids_by_device.contains_key(&event.device_id) {
365                     return Err(format!(
366                         "{}: Invalid HOVER_EXIT event - no pointers are hovering for device {:?}",
367                         self.name, event.device_id
368                     ));
369                 }
370                 let pointer_id = event.pointer_properties[0].id;
371                 let it = self.hovering_pointer_ids_by_device.get_mut(&event.device_id).unwrap();
372                 it.remove(&pointer_id);
373 
374                 if !it.is_empty() {
375                     return Err(format!(
376                         "{}: Removed hovering pointer {}, but pointers are still\
377                                hovering for device {:?}: {:?}",
378                         self.name, pointer_id, event.device_id, it
379                     ));
380                 }
381                 self.hovering_pointer_ids_by_device.remove(&event.device_id);
382             }
383             _ => return Ok(()),
384         }
385         Ok(())
386     }
387 
388     /// Notify the verifier that the device has been reset, which will cause the verifier to erase
389     /// the current internal state for this device. Subsequent events from this device are expected
390     //// to start a new gesture.
reset_device(&mut self, device_id: DeviceId)391     pub fn reset_device(&mut self, device_id: DeviceId) {
392         self.touching_pointer_ids_by_device.remove(&device_id);
393         self.hovering_pointer_ids_by_device.remove(&device_id);
394     }
395 
ensure_touching_pointers_match( &self, device_id: DeviceId, pointer_properties: &[RustPointerProperties], ) -> bool396     fn ensure_touching_pointers_match(
397         &self,
398         device_id: DeviceId,
399         pointer_properties: &[RustPointerProperties],
400     ) -> bool {
401         let Some(pointers) = self.touching_pointer_ids_by_device.get(&device_id) else {
402             return false;
403         };
404 
405         if pointers.len() != pointer_properties.len() {
406             return false;
407         }
408 
409         for pointer_property in pointer_properties.iter() {
410             let pointer_id = pointer_property.id;
411             if !pointers.contains(&pointer_id) {
412                 return false;
413             }
414         }
415         true
416     }
417 }
418 
419 #[cfg(test)]
420 mod tests {
421     use crate::input::MotionButton;
422     use crate::input_verifier::InputVerifier;
423     use crate::input_verifier::NotifyMotionArgs;
424     use crate::DeviceId;
425     use crate::MotionAction;
426     use crate::MotionFlags;
427     use crate::RustPointerProperties;
428     use crate::Source;
429 
430     const BASE_POINTER_PROPERTIES: [RustPointerProperties; 1] = [RustPointerProperties { id: 0 }];
431     const BASE_EVENT: NotifyMotionArgs = NotifyMotionArgs {
432         device_id: DeviceId(1),
433         source: Source::Touchscreen,
434         action: MotionAction::Down,
435         pointer_properties: &BASE_POINTER_PROPERTIES,
436         flags: MotionFlags::empty(),
437         button_state: MotionButton::empty(),
438     };
439     const BASE_MOUSE_EVENT: NotifyMotionArgs =
440         NotifyMotionArgs { source: Source::Mouse, ..BASE_EVENT };
441 
442     #[test]
443     /**
444      * Send a DOWN event with 2 pointers and ensure that it's marked as invalid.
445      */
bad_down_event()446     fn bad_down_event() {
447         let mut verifier =
448             InputVerifier::new("Test", /*should_log*/ true, /*verify_buttons*/ true);
449         let pointer_properties =
450             Vec::from([RustPointerProperties { id: 0 }, RustPointerProperties { id: 1 }]);
451         assert!(verifier
452             .process_movement(NotifyMotionArgs {
453                 action: MotionAction::Down,
454                 pointer_properties: &pointer_properties,
455                 ..BASE_EVENT
456             })
457             .is_err());
458     }
459 
460     #[test]
single_pointer_stream()461     fn single_pointer_stream() {
462         let mut verifier =
463             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
464         let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
465         assert!(verifier
466             .process_movement(NotifyMotionArgs {
467                 action: MotionAction::Down,
468                 pointer_properties: &pointer_properties,
469                 ..BASE_EVENT
470             })
471             .is_ok());
472         assert!(verifier
473             .process_movement(NotifyMotionArgs {
474                 action: MotionAction::Move,
475                 pointer_properties: &pointer_properties,
476                 ..BASE_EVENT
477             })
478             .is_ok());
479         assert!(verifier
480             .process_movement(NotifyMotionArgs {
481                 action: MotionAction::Up,
482                 pointer_properties: &pointer_properties,
483                 ..BASE_EVENT
484             })
485             .is_ok());
486     }
487 
488     #[test]
two_pointer_stream()489     fn two_pointer_stream() {
490         let mut verifier =
491             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
492         let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
493         assert!(verifier
494             .process_movement(NotifyMotionArgs {
495                 action: MotionAction::Down,
496                 pointer_properties: &pointer_properties,
497                 ..BASE_EVENT
498             })
499             .is_ok());
500         // POINTER 1 DOWN
501         let two_pointer_properties =
502             Vec::from([RustPointerProperties { id: 0 }, RustPointerProperties { id: 1 }]);
503         assert!(verifier
504             .process_movement(NotifyMotionArgs {
505                 action: MotionAction::PointerDown { action_index: 1 },
506                 pointer_properties: &two_pointer_properties,
507                 ..BASE_EVENT
508             })
509             .is_ok());
510         // POINTER 0 UP
511         assert!(verifier
512             .process_movement(NotifyMotionArgs {
513                 action: MotionAction::PointerUp { action_index: 0 },
514                 pointer_properties: &two_pointer_properties,
515                 ..BASE_EVENT
516             })
517             .is_ok());
518         // ACTION_UP for pointer id=1
519         let pointer_1_properties = Vec::from([RustPointerProperties { id: 1 }]);
520         assert!(verifier
521             .process_movement(NotifyMotionArgs {
522                 action: MotionAction::Up,
523                 pointer_properties: &pointer_1_properties,
524                 ..BASE_EVENT
525             })
526             .is_ok());
527     }
528 
529     #[test]
multi_device_stream()530     fn multi_device_stream() {
531         let mut verifier =
532             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
533         assert!(verifier
534             .process_movement(NotifyMotionArgs {
535                 device_id: DeviceId(1),
536                 action: MotionAction::Down,
537                 ..BASE_EVENT
538             })
539             .is_ok());
540         assert!(verifier
541             .process_movement(NotifyMotionArgs {
542                 device_id: DeviceId(1),
543                 action: MotionAction::Move,
544                 ..BASE_EVENT
545             })
546             .is_ok());
547         assert!(verifier
548             .process_movement(NotifyMotionArgs {
549                 device_id: DeviceId(2),
550                 action: MotionAction::Down,
551                 ..BASE_EVENT
552             })
553             .is_ok());
554         assert!(verifier
555             .process_movement(NotifyMotionArgs {
556                 device_id: DeviceId(2),
557                 action: MotionAction::Move,
558                 ..BASE_EVENT
559             })
560             .is_ok());
561         assert!(verifier
562             .process_movement(NotifyMotionArgs {
563                 device_id: DeviceId(1),
564                 action: MotionAction::Up,
565                 ..BASE_EVENT
566             })
567             .is_ok());
568     }
569 
570     #[test]
action_cancel()571     fn action_cancel() {
572         let mut verifier =
573             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
574         assert!(verifier
575             .process_movement(NotifyMotionArgs {
576                 action: MotionAction::Down,
577                 flags: MotionFlags::empty(),
578                 ..BASE_EVENT
579             })
580             .is_ok());
581         assert!(verifier
582             .process_movement(NotifyMotionArgs {
583                 action: MotionAction::Cancel,
584                 flags: MotionFlags::CANCELED,
585                 ..BASE_EVENT
586             })
587             .is_ok());
588     }
589 
590     #[test]
invalid_action_cancel()591     fn invalid_action_cancel() {
592         let mut verifier =
593             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
594         assert!(verifier
595             .process_movement(NotifyMotionArgs { action: MotionAction::Down, ..BASE_EVENT })
596             .is_ok());
597         assert!(verifier
598             .process_movement(NotifyMotionArgs { action: MotionAction::Cancel, ..BASE_EVENT })
599             .is_err());
600     }
601 
602     #[test]
invalid_up()603     fn invalid_up() {
604         let mut verifier =
605             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
606         assert!(verifier
607             .process_movement(NotifyMotionArgs { action: MotionAction::Up, ..BASE_EVENT })
608             .is_err());
609     }
610 
611     #[test]
correct_hover_sequence()612     fn correct_hover_sequence() {
613         let mut verifier =
614             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
615         assert!(verifier
616             .process_movement(NotifyMotionArgs { action: MotionAction::HoverEnter, ..BASE_EVENT })
617             .is_ok());
618 
619         assert!(verifier
620             .process_movement(NotifyMotionArgs { action: MotionAction::HoverMove, ..BASE_EVENT })
621             .is_ok());
622 
623         assert!(verifier
624             .process_movement(NotifyMotionArgs { action: MotionAction::HoverExit, ..BASE_EVENT })
625             .is_ok());
626 
627         assert!(verifier
628             .process_movement(NotifyMotionArgs { action: MotionAction::HoverEnter, ..BASE_EVENT })
629             .is_ok());
630     }
631 
632     #[test]
double_hover_enter()633     fn double_hover_enter() {
634         let mut verifier =
635             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
636         assert!(verifier
637             .process_movement(NotifyMotionArgs { action: MotionAction::HoverEnter, ..BASE_EVENT })
638             .is_ok());
639 
640         assert!(verifier
641             .process_movement(NotifyMotionArgs { action: MotionAction::HoverEnter, ..BASE_EVENT })
642             .is_err());
643     }
644 
645     // Send a MOVE without a preceding DOWN event. This is OK because it's from source
646     // MOUSE_RELATIVE, which is used during pointer capture. The verifier should allow such event.
647     #[test]
relative_mouse_move()648     fn relative_mouse_move() {
649         let mut verifier =
650             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
651         assert!(verifier
652             .process_movement(NotifyMotionArgs {
653                 device_id: DeviceId(2),
654                 source: Source::MouseRelative,
655                 action: MotionAction::Move,
656                 ..BASE_EVENT
657             })
658             .is_ok());
659     }
660 
661     // Send a MOVE event with incorrect number of pointers (one of the pointers is missing).
662     #[test]
move_with_wrong_number_of_pointers()663     fn move_with_wrong_number_of_pointers() {
664         let mut verifier =
665             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
666         let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
667         assert!(verifier
668             .process_movement(NotifyMotionArgs {
669                 action: MotionAction::Down,
670                 pointer_properties: &pointer_properties,
671                 ..BASE_EVENT
672             })
673             .is_ok());
674         // POINTER 1 DOWN
675         let two_pointer_properties =
676             Vec::from([RustPointerProperties { id: 0 }, RustPointerProperties { id: 1 }]);
677         assert!(verifier
678             .process_movement(NotifyMotionArgs {
679                 action: MotionAction::PointerDown { action_index: 1 },
680                 pointer_properties: &two_pointer_properties,
681                 ..BASE_EVENT
682             })
683             .is_ok());
684         // MOVE event with 1 pointer missing (the pointer with id = 1). It should be rejected
685         assert!(verifier
686             .process_movement(NotifyMotionArgs {
687                 action: MotionAction::Move,
688                 pointer_properties: &pointer_properties,
689                 ..BASE_EVENT
690             })
691             .is_err());
692     }
693 
694     #[test]
correct_button_press()695     fn correct_button_press() {
696         let mut verifier =
697             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
698         assert!(verifier
699             .process_movement(NotifyMotionArgs {
700                 action: MotionAction::ButtonPress { action_button: MotionButton::Primary },
701                 button_state: MotionButton::Primary,
702                 ..BASE_MOUSE_EVENT
703             })
704             .is_ok());
705     }
706 
707     #[test]
button_press_without_action_button()708     fn button_press_without_action_button() {
709         let mut verifier =
710             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
711         assert!(verifier
712             .process_movement(NotifyMotionArgs {
713                 action: MotionAction::ButtonPress { action_button: MotionButton::empty() },
714                 button_state: MotionButton::empty(),
715                 ..BASE_MOUSE_EVENT
716             })
717             .is_err());
718     }
719 
720     #[test]
button_press_with_multiple_action_buttons()721     fn button_press_with_multiple_action_buttons() {
722         let mut verifier =
723             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
724         assert!(verifier
725             .process_movement(NotifyMotionArgs {
726                 action: MotionAction::ButtonPress {
727                     action_button: MotionButton::Back | MotionButton::Forward
728                 },
729                 button_state: MotionButton::Back | MotionButton::Forward,
730                 ..BASE_MOUSE_EVENT
731             })
732             .is_err());
733     }
734 
735     #[test]
button_press_without_action_button_in_state()736     fn button_press_without_action_button_in_state() {
737         let mut verifier =
738             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
739         assert!(verifier
740             .process_movement(NotifyMotionArgs {
741                 action: MotionAction::ButtonPress { action_button: MotionButton::Primary },
742                 button_state: MotionButton::empty(),
743                 ..BASE_MOUSE_EVENT
744             })
745             .is_err());
746     }
747 
748     #[test]
button_release_with_action_button_in_state()749     fn button_release_with_action_button_in_state() {
750         let mut verifier =
751             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
752         assert!(verifier
753             .process_movement(NotifyMotionArgs {
754                 action: MotionAction::ButtonPress { action_button: MotionButton::Primary },
755                 button_state: MotionButton::Primary,
756                 ..BASE_MOUSE_EVENT
757             })
758             .is_ok());
759         assert!(verifier
760             .process_movement(NotifyMotionArgs {
761                 action: MotionAction::ButtonRelease { action_button: MotionButton::Primary },
762                 button_state: MotionButton::Primary,
763                 ..BASE_MOUSE_EVENT
764             })
765             .is_err());
766     }
767 
768     #[test]
nonbutton_action_with_button_state_change()769     fn nonbutton_action_with_button_state_change() {
770         let mut verifier =
771             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
772         assert!(verifier
773             .process_movement(NotifyMotionArgs {
774                 action: MotionAction::HoverEnter,
775                 button_state: MotionButton::empty(),
776                 ..BASE_MOUSE_EVENT
777             })
778             .is_ok());
779         assert!(verifier
780             .process_movement(NotifyMotionArgs {
781                 action: MotionAction::HoverMove,
782                 button_state: MotionButton::Back,
783                 ..BASE_MOUSE_EVENT
784             })
785             .is_err());
786     }
787 
788     #[test]
nonbutton_action_missing_button_state()789     fn nonbutton_action_missing_button_state() {
790         let mut verifier =
791             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
792         assert!(verifier
793             .process_movement(NotifyMotionArgs {
794                 action: MotionAction::HoverEnter,
795                 button_state: MotionButton::empty(),
796                 ..BASE_MOUSE_EVENT
797             })
798             .is_ok());
799         assert!(verifier
800             .process_movement(NotifyMotionArgs {
801                 action: MotionAction::ButtonPress { action_button: MotionButton::Back },
802                 button_state: MotionButton::Back,
803                 ..BASE_MOUSE_EVENT
804             })
805             .is_ok());
806         assert!(verifier
807             .process_movement(NotifyMotionArgs {
808                 action: MotionAction::HoverMove,
809                 button_state: MotionButton::empty(),
810                 ..BASE_MOUSE_EVENT
811             })
812             .is_err());
813     }
814 
815     #[test]
up_without_button_release()816     fn up_without_button_release() {
817         let mut verifier =
818             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
819         assert!(verifier
820             .process_movement(NotifyMotionArgs {
821                 action: MotionAction::Down,
822                 button_state: MotionButton::Primary,
823                 ..BASE_MOUSE_EVENT
824             })
825             .is_ok());
826         assert!(verifier
827             .process_movement(NotifyMotionArgs {
828                 action: MotionAction::ButtonPress { action_button: MotionButton::Primary },
829                 button_state: MotionButton::Primary,
830                 ..BASE_MOUSE_EVENT
831             })
832             .is_ok());
833         // This UP event shouldn't change the button state; a BUTTON_RELEASE before it should.
834         assert!(verifier
835             .process_movement(NotifyMotionArgs {
836                 action: MotionAction::Up,
837                 button_state: MotionButton::empty(),
838                 ..BASE_MOUSE_EVENT
839             })
840             .is_err());
841     }
842 
843     #[test]
button_press_for_already_pressed_button()844     fn button_press_for_already_pressed_button() {
845         let mut verifier =
846             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
847         assert!(verifier
848             .process_movement(NotifyMotionArgs {
849                 action: MotionAction::ButtonPress { action_button: MotionButton::Back },
850                 button_state: MotionButton::Back,
851                 ..BASE_MOUSE_EVENT
852             })
853             .is_ok());
854         assert!(verifier
855             .process_movement(NotifyMotionArgs {
856                 action: MotionAction::ButtonPress { action_button: MotionButton::Back },
857                 button_state: MotionButton::Back,
858                 ..BASE_MOUSE_EVENT
859             })
860             .is_err());
861     }
862 
863     #[test]
button_release_for_unpressed_button()864     fn button_release_for_unpressed_button() {
865         let mut verifier =
866             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
867         assert!(verifier
868             .process_movement(NotifyMotionArgs {
869                 action: MotionAction::ButtonRelease { action_button: MotionButton::Back },
870                 button_state: MotionButton::empty(),
871                 ..BASE_MOUSE_EVENT
872             })
873             .is_err());
874     }
875 
876     #[test]
correct_multiple_button_presses_without_down()877     fn correct_multiple_button_presses_without_down() {
878         let mut verifier =
879             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
880         assert!(verifier
881             .process_movement(NotifyMotionArgs {
882                 action: MotionAction::ButtonPress { action_button: MotionButton::Back },
883                 button_state: MotionButton::Back,
884                 ..BASE_MOUSE_EVENT
885             })
886             .is_ok());
887         assert!(verifier
888             .process_movement(NotifyMotionArgs {
889                 action: MotionAction::ButtonPress { action_button: MotionButton::Forward },
890                 button_state: MotionButton::Back | MotionButton::Forward,
891                 ..BASE_MOUSE_EVENT
892             })
893             .is_ok());
894     }
895 
896     #[test]
correct_down_with_button_press()897     fn correct_down_with_button_press() {
898         let mut verifier =
899             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
900         assert!(verifier
901             .process_movement(NotifyMotionArgs {
902                 action: MotionAction::Down,
903                 button_state: MotionButton::Primary | MotionButton::Secondary,
904                 ..BASE_MOUSE_EVENT
905             })
906             .is_ok());
907         assert!(verifier
908             .process_movement(NotifyMotionArgs {
909                 action: MotionAction::ButtonPress { action_button: MotionButton::Primary },
910                 button_state: MotionButton::Primary,
911                 ..BASE_MOUSE_EVENT
912             })
913             .is_ok());
914         assert!(verifier
915             .process_movement(NotifyMotionArgs {
916                 action: MotionAction::ButtonPress { action_button: MotionButton::Secondary },
917                 button_state: MotionButton::Primary | MotionButton::Secondary,
918                 ..BASE_MOUSE_EVENT
919             })
920             .is_ok());
921         // Also check that the MOVE afterwards is OK, as that's where errors would be raised if not
922         // enough BUTTON_PRESSes were sent.
923         assert!(verifier
924             .process_movement(NotifyMotionArgs {
925                 action: MotionAction::Move,
926                 button_state: MotionButton::Primary | MotionButton::Secondary,
927                 ..BASE_MOUSE_EVENT
928             })
929             .is_ok());
930     }
931 
932     #[test]
down_with_button_state_change_not_followed_by_button_press()933     fn down_with_button_state_change_not_followed_by_button_press() {
934         let mut verifier =
935             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
936         assert!(verifier
937             .process_movement(NotifyMotionArgs {
938                 action: MotionAction::Down,
939                 button_state: MotionButton::Primary,
940                 ..BASE_MOUSE_EVENT
941             })
942             .is_ok());
943         // The DOWN event itself is OK, but it needs to be immediately followed by a BUTTON_PRESS.
944         assert!(verifier
945             .process_movement(NotifyMotionArgs {
946                 action: MotionAction::Move,
947                 button_state: MotionButton::Primary,
948                 ..BASE_MOUSE_EVENT
949             })
950             .is_err());
951     }
952 
953     #[test]
down_with_button_state_change_not_followed_by_enough_button_presses()954     fn down_with_button_state_change_not_followed_by_enough_button_presses() {
955         let mut verifier =
956             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
957         assert!(verifier
958             .process_movement(NotifyMotionArgs {
959                 action: MotionAction::Down,
960                 button_state: MotionButton::Primary | MotionButton::Secondary,
961                 ..BASE_MOUSE_EVENT
962             })
963             .is_ok());
964         // The DOWN event itself is OK, but it needs to be immediately followed by two
965         // BUTTON_PRESSes, one for each button.
966         assert!(verifier
967             .process_movement(NotifyMotionArgs {
968                 action: MotionAction::ButtonPress { action_button: MotionButton::Primary },
969                 button_state: MotionButton::Primary,
970                 ..BASE_MOUSE_EVENT
971             })
972             .is_ok());
973         assert!(verifier
974             .process_movement(NotifyMotionArgs {
975                 action: MotionAction::Move,
976                 button_state: MotionButton::Primary,
977                 ..BASE_MOUSE_EVENT
978             })
979             .is_err());
980     }
981 
982     #[test]
down_missing_already_pressed_button()983     fn down_missing_already_pressed_button() {
984         let mut verifier =
985             InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
986         assert!(verifier
987             .process_movement(NotifyMotionArgs {
988                 action: MotionAction::ButtonPress { action_button: MotionButton::Back },
989                 button_state: MotionButton::Back,
990                 ..BASE_MOUSE_EVENT
991             })
992             .is_ok());
993         assert!(verifier
994             .process_movement(NotifyMotionArgs {
995                 action: MotionAction::Down,
996                 button_state: MotionButton::empty(),
997                 ..BASE_MOUSE_EVENT
998             })
999             .is_err());
1000     }
1001 }
1002