carnelian/input/
flatland.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::geometry::IntVector;
6use crate::input::{mouse, touch, Button, ButtonSet, DeviceId, Event, EventType};
7use crate::{IntPoint, IntSize};
8use euclid::default::Transform2D;
9use euclid::point2;
10use fidl_fuchsia_ui_pointer::{EventPhase, MouseEvent, TouchEvent};
11use std::collections::HashSet;
12
13#[derive(Default)]
14pub(crate) struct FlatlandMouseInputHandler {
15    pressed_mouse_buttons: HashSet<u8>,
16    cursor_position: IntPoint,
17    device_id: u32,
18}
19
20impl FlatlandMouseInputHandler {
21    pub fn new(device_id: u32) -> Self {
22        Self { device_id, ..Default::default() }
23    }
24
25    fn events_from_mouse_event(&mut self, mouse_event: &MouseEvent) -> Vec<Event> {
26        let transform = Transform2D::identity();
27        let event_time = mouse_event.timestamp.expect("timestamp") as u64;
28        // pointer_sample is None for mouse events with MouseEventStreamInfo::Exited.
29        let pointer_sample = match mouse_event.pointer_sample.as_ref() {
30            Some(pointer_sample) => pointer_sample,
31            None => return Vec::new(),
32        };
33        let position_in_viewport =
34            pointer_sample.position_in_viewport.expect("position_in_viewport");
35        let pressed_buttons: HashSet<u8> =
36            if let Some(ref pressed_buttons) = pointer_sample.pressed_buttons {
37                let pressed_buttons_set = pressed_buttons.iter().cloned().collect();
38                pressed_buttons_set
39            } else {
40                HashSet::new()
41            };
42        let button_set = ButtonSet::new(&pressed_buttons);
43        let device_id = &DeviceId(format!("mouse-{}", self.device_id));
44        let new_cursor_position = point2(position_in_viewport[0], position_in_viewport[1]).to_i32();
45        let move_event = if new_cursor_position != self.cursor_position {
46            let event = mouse::create_event(
47                event_time,
48                device_id,
49                &button_set,
50                new_cursor_position,
51                &transform,
52                mouse::Phase::Moved,
53            );
54            Some(event)
55        } else {
56            None
57        };
58
59        self.cursor_position = new_cursor_position;
60
61        let newly_pressed = pressed_buttons.difference(&self.pressed_mouse_buttons).map(|button| {
62            mouse::create_event(
63                event_time,
64                device_id,
65                &button_set,
66                new_cursor_position,
67                &transform,
68                mouse::Phase::Down(Button(*button)),
69            )
70        });
71
72        let released = self.pressed_mouse_buttons.difference(&pressed_buttons).map(|button| {
73            mouse::create_event(
74                event_time,
75                device_id,
76                &button_set,
77                new_cursor_position,
78                &transform,
79                mouse::Phase::Up(Button(*button)),
80            )
81        });
82
83        let wheel_v = pointer_sample.scroll_v.unwrap_or(0) as i32;
84        let wheel_h = pointer_sample.scroll_h.unwrap_or(0) as i32;
85        let wheel = if wheel_v != 0 || wheel_h != 0 {
86            Some(mouse::create_event(
87                event_time,
88                device_id,
89                &button_set,
90                new_cursor_position,
91                &transform,
92                mouse::Phase::Wheel(IntVector::new(wheel_h, wheel_v)),
93            ))
94        } else {
95            None
96        };
97
98        let events = newly_pressed.chain(move_event).chain(wheel).chain(released).collect();
99        self.pressed_mouse_buttons = pressed_buttons;
100        events
101    }
102
103    pub fn handle_mouse_events(&mut self, events: &Vec<MouseEvent>) -> Vec<Event> {
104        let mut converted_events = Vec::new();
105        for event in events {
106            converted_events.extend(self.events_from_mouse_event(event));
107        }
108        converted_events
109    }
110}
111
112#[derive(Default)]
113pub(crate) struct FlatlandTouchInputHandler {}
114
115impl FlatlandTouchInputHandler {
116    fn flatland_phase_to_phase(phase: EventPhase, location: IntPoint) -> touch::Phase {
117        match phase {
118            EventPhase::Add => touch::Phase::Down(location, IntSize::zero()),
119            EventPhase::Change => touch::Phase::Moved(location, IntSize::zero()),
120            EventPhase::Remove => touch::Phase::Remove,
121            EventPhase::Cancel => touch::Phase::Cancel,
122        }
123    }
124
125    fn convert_touch_event(&mut self, touch_event: &TouchEvent) -> Vec<Event> {
126        let event_time = touch_event.timestamp.expect("timestamp") as u64;
127        if let Some(pointer_sample) = touch_event.pointer_sample.as_ref() {
128            let mut converted_events = Vec::new();
129            let interaction_id = pointer_sample.interaction.expect("interaction");
130            let device_id = DeviceId(format!("touch-{}", interaction_id.device_id));
131            let flatland_phase = pointer_sample.phase.expect("phase");
132            let position_in_viewport =
133                pointer_sample.position_in_viewport.expect("position_in_viewport");
134            let location = point2(position_in_viewport[0], position_in_viewport[1]).to_i32();
135            let phase = Self::flatland_phase_to_phase(flatland_phase, location);
136            let contact =
137                touch::Contact { contact_id: touch::ContactId(interaction_id.pointer_id), phase };
138            let buttons = ButtonSet::default();
139            let touch_event = touch::Event { buttons, contacts: vec![contact] };
140            let new_event = Event {
141                event_type: EventType::Touch(touch_event),
142                device_id: device_id.clone(),
143                event_time: event_time,
144            };
145            if flatland_phase == EventPhase::Remove || flatland_phase == EventPhase::Cancel {
146                let contact = touch::Contact {
147                    contact_id: touch::ContactId(interaction_id.pointer_id),
148                    phase: touch::Phase::Up,
149                };
150                let touch_event =
151                    touch::Event { buttons: ButtonSet::default(), contacts: vec![contact] };
152                let up_event = Event {
153                    event_type: EventType::Touch(touch_event),
154                    device_id: device_id,
155                    event_time: event_time,
156                };
157                converted_events.push(up_event);
158            }
159            converted_events.push(new_event);
160            converted_events
161        } else {
162            Vec::new()
163        }
164    }
165
166    pub fn handle_events(&mut self, events: &Vec<TouchEvent>) -> Vec<Event> {
167        let mut converted_events = Vec::new();
168        for event in events {
169            converted_events.extend(self.convert_touch_event(event));
170        }
171        converted_events
172    }
173}