carnelian/input/
flatland.rs1use 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 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}