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/blink/blink_input_events_type_converters.h" 6 7 #include <utility> 8 9 #include "base/logging.h" 10 #include "base/time/time.h" 11 #include "third_party/WebKit/public/web/WebInputEvent.h" 12 #include "ui/events/base_event_utils.h" 13 #include "ui/events/event.h" 14 #include "ui/events/keycodes/dom/keycode_converter.h" 15 16 namespace mojo { 17 namespace { 18 19 // TODO(majidvp): remove this and directly use ui::EventFlagsToWebEventModifiers 20 int EventFlagsToWebEventModifiers(int flags) { 21 int modifiers = 0; 22 23 if (flags & ui::EF_SHIFT_DOWN) 24 modifiers |= blink::WebInputEvent::ShiftKey; 25 if (flags & ui::EF_CONTROL_DOWN) 26 modifiers |= blink::WebInputEvent::ControlKey; 27 if (flags & ui::EF_ALT_DOWN) 28 modifiers |= blink::WebInputEvent::AltKey; 29 // TODO(beng): MetaKey/META_MASK 30 if (flags & ui::EF_LEFT_MOUSE_BUTTON) 31 modifiers |= blink::WebInputEvent::LeftButtonDown; 32 if (flags & ui::EF_MIDDLE_MOUSE_BUTTON) 33 modifiers |= blink::WebInputEvent::MiddleButtonDown; 34 if (flags & ui::EF_RIGHT_MOUSE_BUTTON) 35 modifiers |= blink::WebInputEvent::RightButtonDown; 36 if (flags & ui::EF_CAPS_LOCK_ON) 37 modifiers |= blink::WebInputEvent::CapsLockOn; 38 return modifiers; 39 } 40 41 // TODO(majidvp): remove this and directly use ui::EventFlagsToWebEventModifiers 42 int EventFlagsToWebInputEventModifiers(int flags) { 43 return (flags & ui::EF_SHIFT_DOWN ? blink::WebInputEvent::ShiftKey : 0) | 44 (flags & ui::EF_CONTROL_DOWN ? blink::WebInputEvent::ControlKey : 0) | 45 (flags & ui::EF_CAPS_LOCK_ON ? blink::WebInputEvent::CapsLockOn : 0) | 46 (flags & ui::EF_ALT_DOWN ? blink::WebInputEvent::AltKey : 0); 47 } 48 49 int GetClickCount(int flags) { 50 if (flags & ui::EF_IS_TRIPLE_CLICK) 51 return 3; 52 else if (flags & ui::EF_IS_DOUBLE_CLICK) 53 return 2; 54 55 return 1; 56 } 57 58 void SetWebMouseEventLocation(const ui::LocatedEvent& located_event, 59 blink::WebMouseEvent* web_event) { 60 web_event->x = static_cast<int>(located_event.x()); 61 web_event->y = static_cast<int>(located_event.y()); 62 web_event->globalX = static_cast<int>(located_event.root_location_f().x()); 63 web_event->globalY = static_cast<int>(located_event.root_location_f().y()); 64 } 65 66 std::unique_ptr<blink::WebInputEvent> BuildWebMouseEventFrom( 67 const ui::PointerEvent& event) { 68 std::unique_ptr<blink::WebMouseEvent> web_event(new blink::WebMouseEvent); 69 70 web_event->pointerType = blink::WebPointerProperties::PointerType::Mouse; 71 SetWebMouseEventLocation(event, web_event.get()); 72 73 web_event->modifiers = EventFlagsToWebEventModifiers(event.flags()); 74 web_event->timeStampSeconds = ui::EventTimeStampToSeconds(event.time_stamp()); 75 76 web_event->button = blink::WebMouseEvent::ButtonNone; 77 if (event.flags() & ui::EF_LEFT_MOUSE_BUTTON) 78 web_event->button = blink::WebMouseEvent::ButtonLeft; 79 if (event.flags() & ui::EF_MIDDLE_MOUSE_BUTTON) 80 web_event->button = blink::WebMouseEvent::ButtonMiddle; 81 if (event.flags() & ui::EF_RIGHT_MOUSE_BUTTON) 82 web_event->button = blink::WebMouseEvent::ButtonRight; 83 84 switch (event.type()) { 85 case ui::ET_POINTER_DOWN: 86 web_event->type = blink::WebInputEvent::MouseDown; 87 break; 88 case ui::ET_POINTER_UP: 89 web_event->type = blink::WebInputEvent::MouseUp; 90 break; 91 case ui::ET_POINTER_MOVED: 92 web_event->type = blink::WebInputEvent::MouseMove; 93 break; 94 case ui::ET_MOUSE_EXITED: 95 web_event->type = blink::WebInputEvent::MouseLeave; 96 break; 97 default: 98 NOTIMPLEMENTED() << "Received unexpected event: " << event.type(); 99 break; 100 } 101 102 web_event->clickCount = GetClickCount(event.flags()); 103 104 return std::move(web_event); 105 } 106 107 std::unique_ptr<blink::WebInputEvent> BuildWebKeyboardEvent( 108 const ui::KeyEvent& event) { 109 std::unique_ptr<blink::WebKeyboardEvent> web_event( 110 new blink::WebKeyboardEvent); 111 112 web_event->modifiers = EventFlagsToWebInputEventModifiers(event.flags()); 113 web_event->timeStampSeconds = ui::EventTimeStampToSeconds(event.time_stamp()); 114 115 switch (event.type()) { 116 case ui::ET_KEY_PRESSED: 117 web_event->type = event.is_char() ? blink::WebInputEvent::Char 118 : blink::WebInputEvent::RawKeyDown; 119 break; 120 case ui::ET_KEY_RELEASED: 121 web_event->type = blink::WebInputEvent::KeyUp; 122 break; 123 default: 124 NOTREACHED(); 125 } 126 127 if (web_event->modifiers & blink::WebInputEvent::AltKey) 128 web_event->isSystemKey = true; 129 130 web_event->windowsKeyCode = event.GetLocatedWindowsKeyboardCode(); 131 web_event->nativeKeyCode = 132 ui::KeycodeConverter::DomCodeToNativeKeycode(event.code()); 133 web_event->text[0] = event.GetText(); 134 web_event->unmodifiedText[0] = event.GetUnmodifiedText(); 135 return std::move(web_event); 136 } 137 138 std::unique_ptr<blink::WebInputEvent> BuildWebMouseWheelEventFrom( 139 const ui::MouseWheelEvent& event) { 140 std::unique_ptr<blink::WebMouseWheelEvent> web_event( 141 new blink::WebMouseWheelEvent); 142 web_event->type = blink::WebInputEvent::MouseWheel; 143 web_event->button = blink::WebMouseEvent::ButtonNone; 144 web_event->modifiers = EventFlagsToWebEventModifiers(event.flags()); 145 web_event->timeStampSeconds = ui::EventTimeStampToSeconds(event.time_stamp()); 146 147 SetWebMouseEventLocation(event, web_event.get()); 148 149 // TODO(rjkroege): Update the following code once Blink supports 150 // DOM Level 3 wheel events 151 // (http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents) 152 web_event->deltaX = event.x_offset(); 153 web_event->deltaY = event.y_offset(); 154 155 web_event->wheelTicksX = web_event->deltaX / ui::MouseWheelEvent::kWheelDelta; 156 web_event->wheelTicksY = web_event->deltaY / ui::MouseWheelEvent::kWheelDelta; 157 158 // TODO(moshayedi): ui::WheelEvent currently only supports WHEEL_MODE_LINE. 159 // Add support for other wheel modes once ui::WheelEvent has support for them. 160 web_event->hasPreciseScrollingDeltas = false; 161 web_event->scrollByPage = false; 162 163 return std::move(web_event); 164 } 165 166 void SetWebTouchEventLocation(const ui::PointerEvent& event, 167 blink::WebTouchPoint* touch) { 168 touch->position.x = event.x(); 169 touch->position.y = event.y(); 170 touch->screenPosition.x = event.root_location_f().x(); 171 touch->screenPosition.y = event.root_location_f().y(); 172 } 173 174 std::unique_ptr<blink::WebInputEvent> BuildWebTouchEvent( 175 const ui::PointerEvent& event) { 176 std::unique_ptr<blink::WebTouchEvent> web_event(new blink::WebTouchEvent); 177 blink::WebTouchPoint* touch = &web_event->touches[event.pointer_id()]; 178 179 // TODO(jonross): we will need to buffer input events, as blink expects all 180 // active touch points to be in each WebInputEvent (crbug.com/578160) 181 SetWebTouchEventLocation(event, touch); 182 touch->pointerType = blink::WebPointerProperties::PointerType::Touch; 183 touch->radiusX = event.pointer_details().radius_x; 184 touch->radiusY = event.pointer_details().radius_y; 185 186 web_event->modifiers = EventFlagsToWebEventModifiers(event.flags()); 187 web_event->timeStampSeconds = ui::EventTimeStampToSeconds(event.time_stamp()); 188 web_event->uniqueTouchEventId = ui::GetNextTouchEventId(); 189 190 switch (event.type()) { 191 case ui::ET_POINTER_DOWN: 192 web_event->type = blink::WebInputEvent::TouchStart; 193 touch->state = blink::WebTouchPoint::StatePressed; 194 break; 195 case ui::ET_POINTER_UP: 196 web_event->type = blink::WebInputEvent::TouchEnd; 197 touch->state = blink::WebTouchPoint::StateReleased; 198 break; 199 case ui::ET_POINTER_MOVED: 200 web_event->type = blink::WebInputEvent::TouchMove; 201 touch->state = blink::WebTouchPoint::StateMoved; 202 break; 203 case ui::ET_POINTER_CANCELLED: 204 web_event->type = blink::WebInputEvent::TouchCancel; 205 touch->state = blink::WebTouchPoint::StateCancelled; 206 break; 207 default: 208 NOTIMPLEMENTED() << "Received non touch pointer event action: " 209 << event.type(); 210 break; 211 } 212 213 return std::move(web_event); 214 } 215 216 } // namespace 217 218 // static 219 std::unique_ptr<blink::WebInputEvent> 220 TypeConverter<std::unique_ptr<blink::WebInputEvent>, ui::Event>::Convert( 221 const ui::Event& event) { 222 DCHECK(event.IsKeyEvent() || event.IsPointerEvent() || 223 event.IsMouseWheelEvent()); 224 switch (event.type()) { 225 case ui::ET_POINTER_DOWN: 226 case ui::ET_POINTER_UP: 227 case ui::ET_POINTER_CANCELLED: 228 case ui::ET_POINTER_MOVED: 229 case ui::ET_POINTER_EXITED: 230 if (event.IsMousePointerEvent()) 231 return BuildWebMouseEventFrom(*event.AsPointerEvent()); 232 else if (event.IsTouchPointerEvent()) 233 return BuildWebTouchEvent(*event.AsPointerEvent()); 234 else 235 return nullptr; 236 case ui::ET_MOUSEWHEEL: 237 return BuildWebMouseWheelEventFrom(*event.AsMouseWheelEvent()); 238 case ui::ET_KEY_PRESSED: 239 case ui::ET_KEY_RELEASED: 240 return BuildWebKeyboardEvent(*event.AsKeyEvent()); 241 default: 242 return nullptr; 243 } 244 } 245 246 } // namespace mojo 247