OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium 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 | |
5 #include "mojo/converters/input_events/input_events_type_converters.h" | |
6 | |
7 #include <stdint.h> | |
8 | |
9 #include <utility> | |
10 | |
11 #if defined(USE_X11) | |
12 #include <X11/extensions/XInput2.h> | |
13 #include <X11/Xlib.h> | |
14 #endif | |
15 | |
16 #include "components/mus/public/interfaces/input_events.mojom.h" | |
17 #include "mojo/converters/input_events/mojo_extended_key_event_data.h" | |
18 #include "ui/events/event_utils.h" | |
19 #include "ui/events/keycodes/dom/keycode_converter.h" | |
20 #include "ui/events/keycodes/keyboard_codes.h" | |
21 #include "ui/gfx/geometry/mojo/geometry_type_converters.h" | |
22 | |
23 namespace mojo { | |
24 namespace { | |
25 | |
26 ui::EventType MojoMouseEventTypeToUIEvent(const mus::mojom::EventPtr& event) { | |
27 DCHECK(event->pointer_data); | |
28 DCHECK_EQ(mus::mojom::PointerKind::MOUSE, event->pointer_data->kind); | |
29 switch (event->action) { | |
30 case mus::mojom::EventType::POINTER_DOWN: | |
31 return ui::ET_MOUSE_PRESSED; | |
32 | |
33 case mus::mojom::EventType::POINTER_UP: | |
34 return ui::ET_MOUSE_RELEASED; | |
35 | |
36 case mus::mojom::EventType::POINTER_MOVE: | |
37 DCHECK(event->pointer_data); | |
38 if (event->flags & (mus::mojom::kEventFlagLeftMouseButton | | |
39 mus::mojom::kEventFlagMiddleMouseButton | | |
40 mus::mojom::kEventFlagRightMouseButton)) { | |
41 return ui::ET_MOUSE_DRAGGED; | |
42 } | |
43 return ui::ET_MOUSE_MOVED; | |
44 | |
45 case mus::mojom::EventType::MOUSE_EXIT: | |
46 return ui::ET_MOUSE_EXITED; | |
47 | |
48 default: | |
49 NOTREACHED(); | |
50 } | |
51 | |
52 return ui::ET_MOUSE_RELEASED; | |
53 } | |
54 | |
55 ui::EventType MojoTouchEventTypeToUIEvent(const mus::mojom::EventPtr& event) { | |
56 DCHECK(event->pointer_data); | |
57 DCHECK_EQ(mus::mojom::PointerKind::TOUCH, event->pointer_data->kind); | |
58 switch (event->action) { | |
59 case mus::mojom::EventType::POINTER_DOWN: | |
60 return ui::ET_TOUCH_PRESSED; | |
61 | |
62 case mus::mojom::EventType::POINTER_UP: | |
63 return ui::ET_TOUCH_RELEASED; | |
64 | |
65 case mus::mojom::EventType::POINTER_MOVE: | |
66 return ui::ET_TOUCH_MOVED; | |
67 | |
68 case mus::mojom::EventType::POINTER_CANCEL: | |
69 return ui::ET_TOUCH_CANCELLED; | |
70 | |
71 default: | |
72 NOTREACHED(); | |
73 } | |
74 | |
75 return ui::ET_TOUCH_CANCELLED; | |
76 } | |
77 | |
78 ui::EventType MojoWheelEventTypeToUIEvent(const mus::mojom::EventPtr& event) { | |
79 DCHECK(event->pointer_data && event->pointer_data->wheel_data); | |
80 return ui::ET_MOUSEWHEEL; | |
81 } | |
82 | |
83 void SetPointerDataLocationFromEvent(const ui::LocatedEvent& located_event, | |
84 mus::mojom::LocationData* location_data) { | |
85 location_data->x = located_event.location_f().x(); | |
86 location_data->y = located_event.location_f().y(); | |
87 location_data->screen_x = located_event.root_location_f().x(); | |
88 location_data->screen_y = located_event.root_location_f().y(); | |
89 } | |
90 | |
91 } // namespace | |
92 | |
93 static_assert(mus::mojom::kEventFlagNone == static_cast<int32_t>(ui::EF_NONE), | |
94 "EVENT_FLAGS must match"); | |
95 static_assert(mus::mojom::kEventFlagIsSynthesized == | |
96 static_cast<int32_t>(ui::EF_IS_SYNTHESIZED), | |
97 "EVENT_FLAGS must match"); | |
98 static_assert(mus::mojom::kEventFlagShiftDown == | |
99 static_cast<int32_t>(ui::EF_SHIFT_DOWN), | |
100 "EVENT_FLAGS must match"); | |
101 static_assert(mus::mojom::kEventFlagControlDown == | |
102 static_cast<int32_t>(ui::EF_CONTROL_DOWN), | |
103 "EVENT_FLAGS must match"); | |
104 static_assert(mus::mojom::kEventFlagAltDown == | |
105 static_cast<int32_t>(ui::EF_ALT_DOWN), | |
106 "EVENT_FLAGS must match"); | |
107 static_assert(mus::mojom::kEventFlagCommandDown == | |
108 static_cast<int32_t>(ui::EF_COMMAND_DOWN), | |
109 "EVENT_FLAGS must match"); | |
110 static_assert(mus::mojom::kEventFlagAltgrDown == | |
111 static_cast<int32_t>(ui::EF_ALTGR_DOWN), | |
112 "EVENT_FLAGS must match"); | |
113 static_assert(mus::mojom::kEventFlagMod3Down == | |
114 static_cast<int32_t>(ui::EF_MOD3_DOWN), | |
115 "EVENT_FLAGS must match"); | |
116 static_assert(mus::mojom::kEventFlagNumLockOn == | |
117 static_cast<int32_t>(ui::EF_NUM_LOCK_ON), | |
118 "EVENT_FLAGS must match"); | |
119 static_assert(mus::mojom::kEventFlagCapsLockOn == | |
120 static_cast<int32_t>(ui::EF_CAPS_LOCK_ON), | |
121 "EVENT_FLAGS must match"); | |
122 static_assert(mus::mojom::kEventFlagScrollLockOn == | |
123 static_cast<int32_t>(ui::EF_SCROLL_LOCK_ON), | |
124 "EVENT_FLAGS must match"); | |
125 static_assert(mus::mojom::kEventFlagLeftMouseButton == | |
126 static_cast<int32_t>(ui::EF_LEFT_MOUSE_BUTTON), | |
127 "EVENT_FLAGS must match"); | |
128 static_assert(mus::mojom::kEventFlagMiddleMouseButton == | |
129 static_cast<int32_t>(ui::EF_MIDDLE_MOUSE_BUTTON), | |
130 "EVENT_FLAGS must match"); | |
131 static_assert(mus::mojom::kEventFlagRightMouseButton == | |
132 static_cast<int32_t>(ui::EF_RIGHT_MOUSE_BUTTON), | |
133 "EVENT_FLAGS must match"); | |
134 static_assert(mus::mojom::kEventFlagBackMouseButton == | |
135 static_cast<int32_t>(ui::EF_BACK_MOUSE_BUTTON), | |
136 "EVENT_FLAGS must match"); | |
137 static_assert(mus::mojom::kEventFlagForwardMouseButton == | |
138 static_cast<int32_t>(ui::EF_FORWARD_MOUSE_BUTTON), | |
139 "EVENT_FLAGS must match"); | |
140 | |
141 // static | |
142 mus::mojom::EventType | |
143 TypeConverter<mus::mojom::EventType, ui::EventType>::Convert( | |
144 ui::EventType type) { | |
145 switch (type) { | |
146 case ui::ET_MOUSE_PRESSED: | |
147 case ui::ET_TOUCH_PRESSED: | |
148 case ui::ET_POINTER_DOWN: | |
149 return mus::mojom::EventType::POINTER_DOWN; | |
150 | |
151 case ui::ET_MOUSE_DRAGGED: | |
152 case ui::ET_MOUSE_MOVED: | |
153 case ui::ET_MOUSE_ENTERED: | |
154 case ui::ET_TOUCH_MOVED: | |
155 case ui::ET_POINTER_MOVED: | |
156 return mus::mojom::EventType::POINTER_MOVE; | |
157 | |
158 case ui::ET_MOUSE_EXITED: | |
159 case ui::ET_POINTER_EXITED: | |
160 return mus::mojom::EventType::MOUSE_EXIT; | |
161 | |
162 case ui::ET_MOUSEWHEEL: | |
163 return mus::mojom::EventType::WHEEL; | |
164 | |
165 case ui::ET_MOUSE_RELEASED: | |
166 case ui::ET_TOUCH_RELEASED: | |
167 case ui::ET_POINTER_UP: | |
168 return mus::mojom::EventType::POINTER_UP; | |
169 | |
170 case ui::ET_TOUCH_CANCELLED: | |
171 case ui::ET_POINTER_CANCELLED: | |
172 return mus::mojom::EventType::POINTER_CANCEL; | |
173 | |
174 case ui::ET_KEY_PRESSED: | |
175 return mus::mojom::EventType::KEY_PRESSED; | |
176 | |
177 case ui::ET_KEY_RELEASED: | |
178 return mus::mojom::EventType::KEY_RELEASED; | |
179 | |
180 default: | |
181 break; | |
182 } | |
183 return mus::mojom::EventType::UNKNOWN; | |
184 } | |
185 | |
186 mus::mojom::EventPtr TypeConverter<mus::mojom::EventPtr, ui::Event>::Convert( | |
187 const ui::Event& input) { | |
188 const mus::mojom::EventType type = | |
189 ConvertTo<mus::mojom::EventType>(input.type()); | |
190 if (type == mus::mojom::EventType::UNKNOWN) | |
191 return nullptr; | |
192 | |
193 mus::mojom::EventPtr event = mus::mojom::Event::New(); | |
194 event->action = type; | |
195 event->flags = input.flags(); | |
196 event->time_stamp = input.time_stamp().ToInternalValue(); | |
197 | |
198 if (input.IsPointerEvent()) { | |
199 const ui::PointerEvent* pointer_event = | |
200 static_cast<const ui::PointerEvent*>(&input); | |
201 const ui::PointerDetails& pointer_details = | |
202 pointer_event->pointer_details(); | |
203 | |
204 mus::mojom::PointerDataPtr pointer_data(mus::mojom::PointerData::New()); | |
205 pointer_data->pointer_id = pointer_event->pointer_id(); | |
206 | |
207 switch (pointer_details.pointer_type) { | |
208 case ui::EventPointerType::POINTER_TYPE_MOUSE: | |
209 pointer_data->kind = mus::mojom::PointerKind::MOUSE; | |
210 break; | |
211 case ui::EventPointerType::POINTER_TYPE_TOUCH: | |
212 pointer_data->kind = mus::mojom::PointerKind::TOUCH; | |
213 break; | |
214 default: | |
215 NOTIMPLEMENTED(); | |
216 } | |
217 | |
218 mus::mojom::LocationDataPtr location_data(mus::mojom::LocationData::New()); | |
219 SetPointerDataLocationFromEvent(*pointer_event, location_data.get()); | |
220 pointer_data->location = std::move(location_data); | |
221 | |
222 mus::mojom::BrushDataPtr brush_data(mus::mojom::BrushData::New()); | |
223 brush_data->width = pointer_details.radius_x; | |
224 brush_data->height = pointer_details.radius_y; | |
225 brush_data->pressure = pointer_details.force; | |
226 brush_data->tilt_x = pointer_details.tilt_x; | |
227 brush_data->tilt_y = pointer_details.tilt_y; | |
228 pointer_data->brush_data = std::move(brush_data); | |
229 event->pointer_data = std::move(pointer_data); | |
230 | |
231 } else if (input.IsMouseEvent()) { | |
232 const ui::LocatedEvent* located_event = | |
233 static_cast<const ui::LocatedEvent*>(&input); | |
234 mus::mojom::PointerDataPtr pointer_data(mus::mojom::PointerData::New()); | |
235 // TODO(sky): come up with a better way to handle this. | |
236 pointer_data->pointer_id = std::numeric_limits<int32_t>::max(); | |
237 pointer_data->kind = mus::mojom::PointerKind::MOUSE; | |
238 mus::mojom::LocationDataPtr location_data(mus::mojom::LocationData::New()); | |
239 SetPointerDataLocationFromEvent(*located_event, location_data.get()); | |
240 pointer_data->location = std::move(location_data); | |
241 | |
242 if (input.IsMouseWheelEvent()) { | |
243 const ui::MouseWheelEvent* wheel_event = | |
244 static_cast<const ui::MouseWheelEvent*>(&input); | |
245 | |
246 mus::mojom::WheelDataPtr wheel_data(mus::mojom::WheelData::New()); | |
247 | |
248 // TODO(rjkroege): Support page scrolling on windows by directly | |
249 // cracking into a mojo event when the native event is available. | |
250 wheel_data->mode = mus::mojom::WheelMode::LINE; | |
251 // TODO(rjkroege): Support precise scrolling deltas. | |
252 | |
253 if ((input.flags() & ui::EF_SHIFT_DOWN) != 0 && | |
254 wheel_event->x_offset() == 0) { | |
255 wheel_data->delta_x = wheel_event->y_offset(); | |
256 wheel_data->delta_y = 0; | |
257 wheel_data->delta_z = 0; | |
258 } else { | |
259 // TODO(rjkroege): support z in ui::Events. | |
260 wheel_data->delta_x = wheel_event->x_offset(); | |
261 wheel_data->delta_y = wheel_event->y_offset(); | |
262 wheel_data->delta_z = 0; | |
263 } | |
264 pointer_data->wheel_data = std::move(wheel_data); | |
265 } | |
266 event->pointer_data = std::move(pointer_data); | |
267 } else if (input.IsTouchEvent()) { | |
268 const ui::TouchEvent* touch_event = | |
269 static_cast<const ui::TouchEvent*>(&input); | |
270 | |
271 mus::mojom::PointerDataPtr pointer_data(mus::mojom::PointerData::New()); | |
272 pointer_data->pointer_id = touch_event->touch_id(); | |
273 pointer_data->kind = mus::mojom::PointerKind::TOUCH; | |
274 mus::mojom::LocationDataPtr location_data(mus::mojom::LocationData::New()); | |
275 SetPointerDataLocationFromEvent(*touch_event, location_data.get()); | |
276 pointer_data->location = std::move(location_data); | |
277 | |
278 mus::mojom::BrushDataPtr brush_data(mus::mojom::BrushData::New()); | |
279 | |
280 // TODO(rjk): this is in the wrong coordinate system | |
281 brush_data->width = touch_event->pointer_details().radius_x; | |
282 brush_data->height = touch_event->pointer_details().radius_y; | |
283 // TODO(rjk): update for touch_event->rotation_angle(); | |
284 brush_data->pressure = touch_event->pointer_details().force; | |
285 brush_data->tilt_x = 0; | |
286 brush_data->tilt_y = 0; | |
287 pointer_data->brush_data = std::move(brush_data); | |
288 event->pointer_data = std::move(pointer_data); | |
289 | |
290 // TODO(rjkroege): Plumb raw pointer events on windows. | |
291 // TODO(rjkroege): Handle force-touch on MacOS | |
292 // TODO(rjkroege): Adjust brush data appropriately for Android. | |
293 } else if (input.IsKeyEvent()) { | |
294 const ui::KeyEvent* key_event = static_cast<const ui::KeyEvent*>(&input); | |
295 mus::mojom::KeyDataPtr key_data(mus::mojom::KeyData::New()); | |
296 key_data->key_code = key_event->GetConflatedWindowsKeyCode(); | |
297 key_data->native_key_code = | |
298 ui::KeycodeConverter::DomCodeToNativeKeycode(key_event->code()); | |
299 key_data->is_char = key_event->is_char(); | |
300 key_data->character = key_event->GetCharacter(); | |
301 | |
302 if (key_event->extended_key_event_data()) { | |
303 const MojoExtendedKeyEventData* data = | |
304 static_cast<const MojoExtendedKeyEventData*>( | |
305 key_event->extended_key_event_data()); | |
306 key_data->windows_key_code = | |
307 static_cast<mus::mojom::KeyboardCode>(data->windows_key_code()); | |
308 key_data->text = data->text(); | |
309 key_data->unmodified_text = data->unmodified_text(); | |
310 } else { | |
311 key_data->windows_key_code = static_cast<mus::mojom::KeyboardCode>( | |
312 key_event->GetLocatedWindowsKeyboardCode()); | |
313 key_data->text = key_event->GetText(); | |
314 key_data->unmodified_text = key_event->GetUnmodifiedText(); | |
315 } | |
316 event->key_data = std::move(key_data); | |
317 } | |
318 return event; | |
319 } | |
320 | |
321 // static | |
322 mus::mojom::EventPtr TypeConverter<mus::mojom::EventPtr, ui::KeyEvent>::Convert( | |
323 const ui::KeyEvent& input) { | |
324 return mus::mojom::Event::From(static_cast<const ui::Event&>(input)); | |
325 } | |
326 | |
327 // static | |
328 std::unique_ptr<ui::Event> | |
329 TypeConverter<std::unique_ptr<ui::Event>, mus::mojom::EventPtr>::Convert( | |
330 const mus::mojom::EventPtr& input) { | |
331 gfx::PointF location; | |
332 gfx::PointF screen_location; | |
333 if (input->pointer_data && input->pointer_data->location) { | |
334 location.SetPoint(input->pointer_data->location->x, | |
335 input->pointer_data->location->y); | |
336 screen_location.SetPoint(input->pointer_data->location->screen_x, | |
337 input->pointer_data->location->screen_y); | |
338 } | |
339 | |
340 switch (input->action) { | |
341 case mus::mojom::EventType::KEY_PRESSED: | |
342 case mus::mojom::EventType::KEY_RELEASED: { | |
343 std::unique_ptr<ui::KeyEvent> key_event; | |
344 if (input->key_data->is_char) { | |
345 key_event.reset(new ui::KeyEvent( | |
346 static_cast<base::char16>(input->key_data->character), | |
347 static_cast<ui::KeyboardCode>(input->key_data->key_code), | |
348 input->flags)); | |
349 } else { | |
350 key_event.reset(new ui::KeyEvent( | |
351 input->action == mus::mojom::EventType::KEY_PRESSED | |
352 ? ui::ET_KEY_PRESSED | |
353 : ui::ET_KEY_RELEASED, | |
354 | |
355 static_cast<ui::KeyboardCode>(input->key_data->key_code), | |
356 input->flags)); | |
357 } | |
358 key_event->SetExtendedKeyEventData( | |
359 std::unique_ptr<ui::ExtendedKeyEventData>( | |
360 new MojoExtendedKeyEventData( | |
361 static_cast<int32_t>(input->key_data->windows_key_code), | |
362 input->key_data->text, input->key_data->unmodified_text))); | |
363 return std::move(key_event); | |
364 } | |
365 case mus::mojom::EventType::POINTER_DOWN: | |
366 case mus::mojom::EventType::POINTER_UP: | |
367 case mus::mojom::EventType::POINTER_MOVE: | |
368 case mus::mojom::EventType::POINTER_CANCEL: | |
369 case mus::mojom::EventType::MOUSE_EXIT: { | |
370 switch (input->pointer_data->kind) { | |
371 case mus::mojom::PointerKind::MOUSE: { | |
372 // TODO: last flags isn't right. Need to send changed_flags. | |
373 std::unique_ptr<ui::MouseEvent> event(new ui::MouseEvent( | |
374 MojoMouseEventTypeToUIEvent(input), gfx::Point(), gfx::Point(), | |
375 ui::EventTimeForNow(), ui::EventFlags(input->flags), | |
376 ui::EventFlags(input->flags))); | |
377 event->set_location_f(location); | |
378 event->set_root_location_f(screen_location); | |
379 return std::move(event); | |
380 } break; | |
381 case mus::mojom::PointerKind::TOUCH: { | |
382 DCHECK(input->pointer_data->brush_data); | |
383 std::unique_ptr<ui::TouchEvent> touch_event(new ui::TouchEvent( | |
384 MojoTouchEventTypeToUIEvent(input), gfx::Point(), | |
385 ui::EventFlags(input->flags), input->pointer_data->pointer_id, | |
386 base::TimeDelta::FromInternalValue(input->time_stamp), | |
387 input->pointer_data->brush_data->width, | |
388 input->pointer_data->brush_data->height, 0, | |
389 input->pointer_data->brush_data->pressure)); | |
390 touch_event->set_location_f(location); | |
391 touch_event->set_root_location_f(screen_location); | |
392 return std::move(touch_event); | |
393 } break; | |
394 case mus::mojom::PointerKind::PEN: | |
395 NOTIMPLEMENTED(); | |
396 break; | |
397 } | |
398 } break; | |
399 case mus::mojom::EventType::WHEEL: { | |
400 DCHECK(input->pointer_data && input->pointer_data->wheel_data); | |
401 std::unique_ptr<ui::MouseEvent> pre_wheel_event(new ui::MouseEvent( | |
402 MojoWheelEventTypeToUIEvent(input), gfx::Point(), gfx::Point(), | |
403 ui::EventTimeForNow(), ui::EventFlags(input->flags), | |
404 ui::EventFlags(input->flags))); | |
405 pre_wheel_event->set_location_f(location); | |
406 pre_wheel_event->set_root_location_f(screen_location); | |
407 std::unique_ptr<ui::MouseEvent> wheel_event(new ui::MouseWheelEvent( | |
408 *pre_wheel_event, | |
409 static_cast<int>(input->pointer_data->wheel_data->delta_x), | |
410 static_cast<int>(input->pointer_data->wheel_data->delta_y))); | |
411 return std::move(wheel_event); | |
412 } break; | |
413 | |
414 default: | |
415 NOTIMPLEMENTED(); | |
416 } | |
417 // TODO: need to support time_stamp. | |
418 return nullptr; | |
419 } | |
420 | |
421 } // namespace mojo | |
OLD | NEW |