| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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 <map> | |
| 6 | |
| 7 #include "webkit/plugins/ppapi/event_conversion.h" | |
| 8 | |
| 9 #include "base/basictypes.h" | |
| 10 #include "base/i18n/char_iterator.h" | |
| 11 #include "base/logging.h" | |
| 12 #include "base/memory/scoped_ptr.h" | |
| 13 #include "base/strings/string_util.h" | |
| 14 #include "base/strings/stringprintf.h" | |
| 15 #include "base/strings/utf_string_conversion_utils.h" | |
| 16 #include "base/strings/utf_string_conversions.h" | |
| 17 #include "ppapi/c/pp_input_event.h" | |
| 18 #include "ppapi/shared_impl/ppb_input_event_shared.h" | |
| 19 #include "ppapi/shared_impl/time_conversion.h" | |
| 20 #include "third_party/WebKit/public/platform/WebGamepads.h" | |
| 21 #include "third_party/WebKit/public/platform/WebString.h" | |
| 22 #include "third_party/WebKit/public/web/WebInputEvent.h" | |
| 23 #include "webkit/plugins/ppapi/common.h" | |
| 24 #include "webkit/plugins/ppapi/usb_key_code_conversion.h" | |
| 25 | |
| 26 using ppapi::EventTimeToPPTimeTicks; | |
| 27 using ppapi::InputEventData; | |
| 28 using ppapi::PPTimeTicksToEventTime; | |
| 29 using WebKit::WebInputEvent; | |
| 30 using WebKit::WebKeyboardEvent; | |
| 31 using WebKit::WebMouseEvent; | |
| 32 using WebKit::WebMouseWheelEvent; | |
| 33 using WebKit::WebString; | |
| 34 using WebKit::WebTouchEvent; | |
| 35 using WebKit::WebTouchPoint; | |
| 36 using WebKit::WebUChar; | |
| 37 | |
| 38 namespace webkit { | |
| 39 namespace ppapi { | |
| 40 | |
| 41 namespace { | |
| 42 | |
| 43 // Verify the modifier flags WebKit uses match the Pepper ones. If these start | |
| 44 // not matching, we'll need to write conversion code to preserve the Pepper | |
| 45 // values (since plugins will be depending on them). | |
| 46 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_SHIFTKEY) == | |
| 47 static_cast<int>(WebInputEvent::ShiftKey), | |
| 48 ShiftKeyMatches); | |
| 49 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_CONTROLKEY) == | |
| 50 static_cast<int>(WebInputEvent::ControlKey), | |
| 51 ControlKeyMatches); | |
| 52 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_ALTKEY) == | |
| 53 static_cast<int>(WebInputEvent::AltKey), | |
| 54 AltKeyMatches); | |
| 55 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_METAKEY) == | |
| 56 static_cast<int>(WebInputEvent::MetaKey), | |
| 57 MetaKeyMatches); | |
| 58 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_ISKEYPAD) == | |
| 59 static_cast<int>(WebInputEvent::IsKeyPad), | |
| 60 KeyPadMatches); | |
| 61 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_ISAUTOREPEAT) == | |
| 62 static_cast<int>(WebInputEvent::IsAutoRepeat), | |
| 63 AutoRepeatMatches); | |
| 64 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) == | |
| 65 static_cast<int>(WebInputEvent::LeftButtonDown), | |
| 66 LeftButtonMatches); | |
| 67 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_MIDDLEBUTTONDOWN) == | |
| 68 static_cast<int>(WebInputEvent::MiddleButtonDown), | |
| 69 MiddleButtonMatches); | |
| 70 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_RIGHTBUTTONDOWN) == | |
| 71 static_cast<int>(WebInputEvent::RightButtonDown), | |
| 72 RightButtonMatches); | |
| 73 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_CAPSLOCKKEY) == | |
| 74 static_cast<int>(WebInputEvent::CapsLockOn), | |
| 75 CapsLockMatches); | |
| 76 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_NUMLOCKKEY) == | |
| 77 static_cast<int>(WebInputEvent::NumLockOn), | |
| 78 NumLockMatches); | |
| 79 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_ISLEFT) == | |
| 80 static_cast<int>(WebInputEvent::IsLeft), | |
| 81 LeftMatches); | |
| 82 COMPILE_ASSERT(static_cast<int>(PP_INPUTEVENT_MODIFIER_ISRIGHT) == | |
| 83 static_cast<int>(WebInputEvent::IsRight), | |
| 84 RightMatches); | |
| 85 | |
| 86 PP_InputEvent_Type ConvertEventTypes(WebInputEvent::Type wetype) { | |
| 87 switch (wetype) { | |
| 88 case WebInputEvent::MouseDown: | |
| 89 return PP_INPUTEVENT_TYPE_MOUSEDOWN; | |
| 90 case WebInputEvent::MouseUp: | |
| 91 return PP_INPUTEVENT_TYPE_MOUSEUP; | |
| 92 case WebInputEvent::MouseMove: | |
| 93 return PP_INPUTEVENT_TYPE_MOUSEMOVE; | |
| 94 case WebInputEvent::MouseEnter: | |
| 95 return PP_INPUTEVENT_TYPE_MOUSEENTER; | |
| 96 case WebInputEvent::MouseLeave: | |
| 97 return PP_INPUTEVENT_TYPE_MOUSELEAVE; | |
| 98 case WebInputEvent::ContextMenu: | |
| 99 return PP_INPUTEVENT_TYPE_CONTEXTMENU; | |
| 100 case WebInputEvent::MouseWheel: | |
| 101 return PP_INPUTEVENT_TYPE_WHEEL; | |
| 102 case WebInputEvent::RawKeyDown: | |
| 103 return PP_INPUTEVENT_TYPE_RAWKEYDOWN; | |
| 104 case WebInputEvent::KeyDown: | |
| 105 return PP_INPUTEVENT_TYPE_KEYDOWN; | |
| 106 case WebInputEvent::KeyUp: | |
| 107 return PP_INPUTEVENT_TYPE_KEYUP; | |
| 108 case WebInputEvent::Char: | |
| 109 return PP_INPUTEVENT_TYPE_CHAR; | |
| 110 case WebInputEvent::TouchStart: | |
| 111 return PP_INPUTEVENT_TYPE_TOUCHSTART; | |
| 112 case WebInputEvent::TouchMove: | |
| 113 return PP_INPUTEVENT_TYPE_TOUCHMOVE; | |
| 114 case WebInputEvent::TouchEnd: | |
| 115 return PP_INPUTEVENT_TYPE_TOUCHEND; | |
| 116 case WebInputEvent::TouchCancel: | |
| 117 return PP_INPUTEVENT_TYPE_TOUCHCANCEL; | |
| 118 case WebInputEvent::Undefined: | |
| 119 default: | |
| 120 return PP_INPUTEVENT_TYPE_UNDEFINED; | |
| 121 } | |
| 122 } | |
| 123 | |
| 124 // Generates a PP_InputEvent with the fields common to all events, as well as | |
| 125 // the event type from the given web event. Event-specific fields will be zero | |
| 126 // initialized. | |
| 127 InputEventData GetEventWithCommonFieldsAndType(const WebInputEvent& web_event) { | |
| 128 InputEventData result; | |
| 129 result.event_type = ConvertEventTypes(web_event.type); | |
| 130 result.event_time_stamp = EventTimeToPPTimeTicks(web_event.timeStampSeconds); | |
| 131 result.usb_key_code = 0; | |
| 132 return result; | |
| 133 } | |
| 134 | |
| 135 void AppendKeyEvent(const WebInputEvent& event, | |
| 136 std::vector<InputEventData>* result_events) { | |
| 137 const WebKeyboardEvent& key_event = | |
| 138 static_cast<const WebKeyboardEvent&>(event); | |
| 139 InputEventData result = GetEventWithCommonFieldsAndType(event); | |
| 140 result.event_modifiers = key_event.modifiers; | |
| 141 result.key_code = key_event.windowsKeyCode; | |
| 142 result.usb_key_code = UsbKeyCodeForKeyboardEvent(key_event); | |
| 143 result_events->push_back(result); | |
| 144 } | |
| 145 | |
| 146 void AppendCharEvent(const WebInputEvent& event, | |
| 147 std::vector<InputEventData>* result_events) { | |
| 148 const WebKeyboardEvent& key_event = | |
| 149 static_cast<const WebKeyboardEvent&>(event); | |
| 150 | |
| 151 // This is a bit complex, the input event will normally just have one 16-bit | |
| 152 // character in it, but may be zero or more than one. The text array is | |
| 153 // just padded with 0 values for the unused ones, but is not necessarily | |
| 154 // null-terminated. | |
| 155 // | |
| 156 // Here we see how many UTF-16 characters we have. | |
| 157 size_t utf16_char_count = 0; | |
| 158 while (utf16_char_count < WebKeyboardEvent::textLengthCap && | |
| 159 key_event.text[utf16_char_count]) | |
| 160 utf16_char_count++; | |
| 161 | |
| 162 // Make a separate InputEventData for each Unicode character in the input. | |
| 163 base::i18n::UTF16CharIterator iter(key_event.text, utf16_char_count); | |
| 164 while (!iter.end()) { | |
| 165 InputEventData result = GetEventWithCommonFieldsAndType(event); | |
| 166 result.event_modifiers = key_event.modifiers; | |
| 167 base::WriteUnicodeCharacter(iter.get(), &result.character_text); | |
| 168 | |
| 169 result_events->push_back(result); | |
| 170 iter.Advance(); | |
| 171 } | |
| 172 } | |
| 173 | |
| 174 void AppendMouseEvent(const WebInputEvent& event, | |
| 175 std::vector<InputEventData>* result_events) { | |
| 176 COMPILE_ASSERT(static_cast<int>(WebMouseEvent::ButtonNone) == | |
| 177 static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_NONE), | |
| 178 MouseNone); | |
| 179 COMPILE_ASSERT(static_cast<int>(WebMouseEvent::ButtonLeft) == | |
| 180 static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_LEFT), | |
| 181 MouseLeft); | |
| 182 COMPILE_ASSERT(static_cast<int>(WebMouseEvent::ButtonRight) == | |
| 183 static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_RIGHT), | |
| 184 MouseRight); | |
| 185 COMPILE_ASSERT(static_cast<int>(WebMouseEvent::ButtonMiddle) == | |
| 186 static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_MIDDLE), | |
| 187 MouseMiddle); | |
| 188 | |
| 189 const WebMouseEvent& mouse_event = | |
| 190 static_cast<const WebMouseEvent&>(event); | |
| 191 InputEventData result = GetEventWithCommonFieldsAndType(event); | |
| 192 result.event_modifiers = mouse_event.modifiers; | |
| 193 if (mouse_event.type == WebInputEvent::MouseDown || | |
| 194 mouse_event.type == WebInputEvent::MouseMove || | |
| 195 mouse_event.type == WebInputEvent::MouseUp) { | |
| 196 result.mouse_button = | |
| 197 static_cast<PP_InputEvent_MouseButton>(mouse_event.button); | |
| 198 } | |
| 199 result.mouse_position.x = mouse_event.x; | |
| 200 result.mouse_position.y = mouse_event.y; | |
| 201 result.mouse_click_count = mouse_event.clickCount; | |
| 202 result.mouse_movement.x = mouse_event.movementX; | |
| 203 result.mouse_movement.y = mouse_event.movementY; | |
| 204 result_events->push_back(result); | |
| 205 } | |
| 206 | |
| 207 void AppendMouseWheelEvent(const WebInputEvent& event, | |
| 208 std::vector<InputEventData>* result_events) { | |
| 209 const WebMouseWheelEvent& mouse_wheel_event = | |
| 210 static_cast<const WebMouseWheelEvent&>(event); | |
| 211 InputEventData result = GetEventWithCommonFieldsAndType(event); | |
| 212 result.event_modifiers = mouse_wheel_event.modifiers; | |
| 213 result.wheel_delta.x = mouse_wheel_event.deltaX; | |
| 214 result.wheel_delta.y = mouse_wheel_event.deltaY; | |
| 215 result.wheel_ticks.x = mouse_wheel_event.wheelTicksX; | |
| 216 result.wheel_ticks.y = mouse_wheel_event.wheelTicksY; | |
| 217 result.wheel_scroll_by_page = !!mouse_wheel_event.scrollByPage; | |
| 218 result_events->push_back(result); | |
| 219 } | |
| 220 | |
| 221 void SetPPTouchPoints(const WebTouchPoint* touches, uint32_t touches_length, | |
| 222 std::vector<PP_TouchPoint>* result) { | |
| 223 for (uint32_t i = 0; i < touches_length; i++) { | |
| 224 const WebTouchPoint& touch_point = touches[i]; | |
| 225 PP_TouchPoint pp_pt; | |
| 226 pp_pt.id = touch_point.id; | |
| 227 pp_pt.position.x = touch_point.position.x; | |
| 228 pp_pt.position.y = touch_point.position.y; | |
| 229 pp_pt.radius.x = touch_point.radiusX; | |
| 230 pp_pt.radius.y = touch_point.radiusY; | |
| 231 pp_pt.rotation_angle = touch_point.rotationAngle; | |
| 232 pp_pt.pressure = touch_point.force; | |
| 233 result->push_back(pp_pt); | |
| 234 } | |
| 235 } | |
| 236 | |
| 237 void AppendTouchEvent(const WebInputEvent& event, | |
| 238 std::vector<InputEventData>* result_events) { | |
| 239 const WebTouchEvent& touch_event = | |
| 240 reinterpret_cast<const WebTouchEvent&>(event); | |
| 241 | |
| 242 InputEventData result = GetEventWithCommonFieldsAndType(event); | |
| 243 SetPPTouchPoints(touch_event.touches, touch_event.touchesLength, | |
| 244 &result.touches); | |
| 245 SetPPTouchPoints(touch_event.changedTouches, touch_event.changedTouchesLength, | |
| 246 &result.changed_touches); | |
| 247 SetPPTouchPoints(touch_event.targetTouches, touch_event.targetTouchesLength, | |
| 248 &result.target_touches); | |
| 249 | |
| 250 result_events->push_back(result); | |
| 251 } | |
| 252 | |
| 253 // Structure used to map touch point id's to touch states. Since the pepper | |
| 254 // touch event structure does not have states for individual touch points and | |
| 255 // instead relies on the event type in combination with the set of touch lists, | |
| 256 // we have to set the state for the changed touches to be the same as the event | |
| 257 // type and all others to be 'stationary.' | |
| 258 typedef std::map<uint32_t, WebTouchPoint::State> TouchStateMap; | |
| 259 | |
| 260 void SetWebTouchPoints(const std::vector<PP_TouchPoint>& pp_touches, | |
| 261 const TouchStateMap& states_map, | |
| 262 WebTouchPoint* web_touches, | |
| 263 uint32_t* web_touches_length) { | |
| 264 | |
| 265 for (uint32_t i = 0; i < pp_touches.size() && | |
| 266 i < WebTouchEvent::touchesLengthCap; i++) { | |
| 267 WebTouchPoint pt; | |
| 268 const PP_TouchPoint& pp_pt = pp_touches[i]; | |
| 269 pt.id = pp_pt.id; | |
| 270 | |
| 271 if (states_map.find(pt.id) == states_map.end()) | |
| 272 pt.state = WebTouchPoint::StateStationary; | |
| 273 else | |
| 274 pt.state = states_map.find(pt.id)->second; | |
| 275 | |
| 276 pt.position.x = pp_pt.position.x; | |
| 277 pt.position.y = pp_pt.position.y; | |
| 278 // TODO bug:http://code.google.com/p/chromium/issues/detail?id=93902 | |
| 279 pt.screenPosition.x = 0; | |
| 280 pt.screenPosition.y = 0; | |
| 281 pt.force = pp_pt.pressure; | |
| 282 pt.radiusX = pp_pt.radius.x; | |
| 283 pt.radiusY = pp_pt.radius.y; | |
| 284 pt.rotationAngle = pp_pt.rotation_angle; | |
| 285 web_touches[i] = pt; | |
| 286 (*web_touches_length)++; | |
| 287 } | |
| 288 } | |
| 289 | |
| 290 WebTouchEvent* BuildTouchEvent(const InputEventData& event) { | |
| 291 WebTouchEvent* web_event = new WebTouchEvent(); | |
| 292 WebTouchPoint::State state = WebTouchPoint::StateUndefined; | |
| 293 switch (event.event_type) { | |
| 294 case PP_INPUTEVENT_TYPE_TOUCHSTART: | |
| 295 web_event->type = WebInputEvent::TouchStart; | |
| 296 state = WebTouchPoint::StatePressed; | |
| 297 break; | |
| 298 case PP_INPUTEVENT_TYPE_TOUCHMOVE: | |
| 299 web_event->type = WebInputEvent::TouchMove; | |
| 300 state = WebTouchPoint::StateMoved; | |
| 301 break; | |
| 302 case PP_INPUTEVENT_TYPE_TOUCHEND: | |
| 303 web_event->type = WebInputEvent::TouchEnd; | |
| 304 state = WebTouchPoint::StateReleased; | |
| 305 break; | |
| 306 case PP_INPUTEVENT_TYPE_TOUCHCANCEL: | |
| 307 web_event->type = WebInputEvent::TouchCancel; | |
| 308 state = WebTouchPoint::StateCancelled; | |
| 309 break; | |
| 310 default: | |
| 311 NOTREACHED(); | |
| 312 } | |
| 313 | |
| 314 TouchStateMap states_map; | |
| 315 for (uint32_t i = 0; i < event.changed_touches.size(); i++) | |
| 316 states_map[event.changed_touches[i].id] = state; | |
| 317 | |
| 318 web_event->timeStampSeconds = PPTimeTicksToEventTime(event.event_time_stamp); | |
| 319 | |
| 320 SetWebTouchPoints(event.changed_touches, states_map, | |
| 321 web_event->changedTouches, | |
| 322 &web_event->changedTouchesLength); | |
| 323 | |
| 324 SetWebTouchPoints(event.touches, states_map, web_event->touches, | |
| 325 &web_event->touchesLength); | |
| 326 | |
| 327 SetWebTouchPoints(event.target_touches, states_map, web_event->targetTouches, | |
| 328 &web_event->targetTouchesLength); | |
| 329 | |
| 330 if (web_event->type == WebInputEvent::TouchEnd || | |
| 331 web_event->type == WebInputEvent::TouchCancel) { | |
| 332 SetWebTouchPoints(event.changed_touches, states_map, | |
| 333 web_event->touches, &web_event->touchesLength); | |
| 334 SetWebTouchPoints(event.changed_touches, states_map, | |
| 335 web_event->targetTouches, | |
| 336 &web_event->targetTouchesLength); | |
| 337 } | |
| 338 | |
| 339 return web_event; | |
| 340 } | |
| 341 | |
| 342 WebKeyboardEvent* BuildKeyEvent(const InputEventData& event) { | |
| 343 WebKeyboardEvent* key_event = new WebKeyboardEvent(); | |
| 344 switch (event.event_type) { | |
| 345 case PP_INPUTEVENT_TYPE_RAWKEYDOWN: | |
| 346 key_event->type = WebInputEvent::RawKeyDown; | |
| 347 break; | |
| 348 case PP_INPUTEVENT_TYPE_KEYDOWN: | |
| 349 key_event->type = WebInputEvent::KeyDown; | |
| 350 break; | |
| 351 case PP_INPUTEVENT_TYPE_KEYUP: | |
| 352 key_event->type = WebInputEvent::KeyUp; | |
| 353 break; | |
| 354 default: | |
| 355 NOTREACHED(); | |
| 356 } | |
| 357 key_event->timeStampSeconds = PPTimeTicksToEventTime(event.event_time_stamp); | |
| 358 key_event->modifiers = event.event_modifiers; | |
| 359 key_event->windowsKeyCode = event.key_code; | |
| 360 key_event->setKeyIdentifierFromWindowsKeyCode(); | |
| 361 return key_event; | |
| 362 } | |
| 363 | |
| 364 WebKeyboardEvent* BuildCharEvent(const InputEventData& event) { | |
| 365 WebKeyboardEvent* key_event = new WebKeyboardEvent(); | |
| 366 key_event->type = WebInputEvent::Char; | |
| 367 key_event->timeStampSeconds = PPTimeTicksToEventTime(event.event_time_stamp); | |
| 368 key_event->modifiers = event.event_modifiers; | |
| 369 | |
| 370 // Make sure to not read beyond the buffer in case some bad code doesn't | |
| 371 // NULL-terminate it (this is called from plugins). | |
| 372 size_t text_length_cap = WebKeyboardEvent::textLengthCap; | |
| 373 base::string16 text16 = UTF8ToUTF16(event.character_text); | |
| 374 | |
| 375 memset(key_event->text, 0, text_length_cap); | |
| 376 memset(key_event->unmodifiedText, 0, text_length_cap); | |
| 377 for (size_t i = 0; | |
| 378 i < std::min(text_length_cap, text16.size()); | |
| 379 ++i) | |
| 380 key_event->text[i] = text16[i]; | |
| 381 return key_event; | |
| 382 } | |
| 383 | |
| 384 WebMouseEvent* BuildMouseEvent(const InputEventData& event) { | |
| 385 WebMouseEvent* mouse_event = new WebMouseEvent(); | |
| 386 switch (event.event_type) { | |
| 387 case PP_INPUTEVENT_TYPE_MOUSEDOWN: | |
| 388 mouse_event->type = WebInputEvent::MouseDown; | |
| 389 break; | |
| 390 case PP_INPUTEVENT_TYPE_MOUSEUP: | |
| 391 mouse_event->type = WebInputEvent::MouseUp; | |
| 392 break; | |
| 393 case PP_INPUTEVENT_TYPE_MOUSEMOVE: | |
| 394 mouse_event->type = WebInputEvent::MouseMove; | |
| 395 break; | |
| 396 case PP_INPUTEVENT_TYPE_MOUSEENTER: | |
| 397 mouse_event->type = WebInputEvent::MouseEnter; | |
| 398 break; | |
| 399 case PP_INPUTEVENT_TYPE_MOUSELEAVE: | |
| 400 mouse_event->type = WebInputEvent::MouseLeave; | |
| 401 break; | |
| 402 case PP_INPUTEVENT_TYPE_CONTEXTMENU: | |
| 403 mouse_event->type = WebInputEvent::ContextMenu; | |
| 404 break; | |
| 405 default: | |
| 406 NOTREACHED(); | |
| 407 } | |
| 408 mouse_event->timeStampSeconds = | |
| 409 PPTimeTicksToEventTime(event.event_time_stamp); | |
| 410 mouse_event->modifiers = event.event_modifiers; | |
| 411 mouse_event->button = | |
| 412 static_cast<WebMouseEvent::Button>(event.mouse_button); | |
| 413 if (mouse_event->type == WebInputEvent::MouseMove) { | |
| 414 if (mouse_event->modifiers & WebInputEvent::LeftButtonDown) | |
| 415 mouse_event->button = WebMouseEvent::ButtonLeft; | |
| 416 else if (mouse_event->modifiers & WebInputEvent::MiddleButtonDown) | |
| 417 mouse_event->button = WebMouseEvent::ButtonMiddle; | |
| 418 else if (mouse_event->modifiers & WebInputEvent::RightButtonDown) | |
| 419 mouse_event->button = WebMouseEvent::ButtonRight; | |
| 420 } | |
| 421 mouse_event->x = event.mouse_position.x; | |
| 422 mouse_event->y = event.mouse_position.y; | |
| 423 mouse_event->clickCount = event.mouse_click_count; | |
| 424 mouse_event->movementX = event.mouse_movement.x; | |
| 425 mouse_event->movementY = event.mouse_movement.y; | |
| 426 return mouse_event; | |
| 427 } | |
| 428 | |
| 429 WebMouseWheelEvent* BuildMouseWheelEvent(const InputEventData& event) { | |
| 430 WebMouseWheelEvent* mouse_wheel_event = new WebMouseWheelEvent(); | |
| 431 mouse_wheel_event->type = WebInputEvent::MouseWheel; | |
| 432 mouse_wheel_event->timeStampSeconds = | |
| 433 PPTimeTicksToEventTime(event.event_time_stamp); | |
| 434 mouse_wheel_event->modifiers = event.event_modifiers; | |
| 435 mouse_wheel_event->deltaX = event.wheel_delta.x; | |
| 436 mouse_wheel_event->deltaY = event.wheel_delta.y; | |
| 437 mouse_wheel_event->wheelTicksX = event.wheel_ticks.x; | |
| 438 mouse_wheel_event->wheelTicksY = event.wheel_ticks.y; | |
| 439 mouse_wheel_event->scrollByPage = event.wheel_scroll_by_page; | |
| 440 return mouse_wheel_event; | |
| 441 } | |
| 442 | |
| 443 #if !defined(OS_WIN) | |
| 444 #define VK_RETURN 0x0D | |
| 445 | |
| 446 #define VK_PRIOR 0x21 | |
| 447 #define VK_NEXT 0x22 | |
| 448 #define VK_END 0x23 | |
| 449 #define VK_HOME 0x24 | |
| 450 #define VK_LEFT 0x25 | |
| 451 #define VK_UP 0x26 | |
| 452 #define VK_RIGHT 0x27 | |
| 453 #define VK_DOWN 0x28 | |
| 454 #define VK_SNAPSHOT 0x2C | |
| 455 #define VK_INSERT 0x2D | |
| 456 #define VK_DELETE 0x2E | |
| 457 | |
| 458 #define VK_APPS 0x5D | |
| 459 | |
| 460 #define VK_F1 0x70 | |
| 461 #endif | |
| 462 | |
| 463 // Convert a character string to a Windows virtual key code. Adapted from | |
| 464 // src/third_party/WebKit/Tools/DumpRenderTree/chromium/EventSender.cpp. This | |
| 465 // is used by CreateSimulatedWebInputEvents to convert keyboard events. | |
| 466 void GetKeyCode(const std::string& char_text, | |
| 467 WebUChar* code, | |
| 468 WebUChar* text, | |
| 469 bool* needs_shift_modifier, | |
| 470 bool* generate_char) { | |
| 471 WebUChar vk_code = 0; | |
| 472 WebUChar vk_text = 0; | |
| 473 *needs_shift_modifier = false; | |
| 474 *generate_char = false; | |
| 475 if ("\n" == char_text) { | |
| 476 vk_text = vk_code = VK_RETURN; | |
| 477 *generate_char = true; | |
| 478 } else if ("rightArrow" == char_text) { | |
| 479 vk_code = VK_RIGHT; | |
| 480 } else if ("downArrow" == char_text) { | |
| 481 vk_code = VK_DOWN; | |
| 482 } else if ("leftArrow" == char_text) { | |
| 483 vk_code = VK_LEFT; | |
| 484 } else if ("upArrow" == char_text) { | |
| 485 vk_code = VK_UP; | |
| 486 } else if ("insert" == char_text) { | |
| 487 vk_code = VK_INSERT; | |
| 488 } else if ("delete" == char_text) { | |
| 489 vk_code = VK_DELETE; | |
| 490 } else if ("pageUp" == char_text) { | |
| 491 vk_code = VK_PRIOR; | |
| 492 } else if ("pageDown" == char_text) { | |
| 493 vk_code = VK_NEXT; | |
| 494 } else if ("home" == char_text) { | |
| 495 vk_code = VK_HOME; | |
| 496 } else if ("end" == char_text) { | |
| 497 vk_code = VK_END; | |
| 498 } else if ("printScreen" == char_text) { | |
| 499 vk_code = VK_SNAPSHOT; | |
| 500 } else if ("menu" == char_text) { | |
| 501 vk_code = VK_APPS; | |
| 502 } else { | |
| 503 // Compare the input string with the function-key names defined by the | |
| 504 // DOM spec (i.e. "F1",...,"F24"). | |
| 505 for (int i = 1; i <= 24; ++i) { | |
| 506 std::string functionKeyName = base::StringPrintf("F%d", i); | |
| 507 if (functionKeyName == char_text) { | |
| 508 vk_code = VK_F1 + (i - 1); | |
| 509 break; | |
| 510 } | |
| 511 } | |
| 512 if (!vk_code) { | |
| 513 WebString web_char_text = | |
| 514 WebString::fromUTF8(char_text.data(), char_text.size()); | |
| 515 DCHECK_EQ(web_char_text.length(), 1U); | |
| 516 vk_text = vk_code = web_char_text.at(0); | |
| 517 *needs_shift_modifier = | |
| 518 (vk_code & 0xFF) >= 'A' && (vk_code & 0xFF) <= 'Z'; | |
| 519 if ((vk_code & 0xFF) >= 'a' && (vk_code & 0xFF) <= 'z') | |
| 520 vk_code -= 'a' - 'A'; | |
| 521 *generate_char = true; | |
| 522 } | |
| 523 } | |
| 524 | |
| 525 *code = vk_code; | |
| 526 *text = vk_text; | |
| 527 } | |
| 528 | |
| 529 } // namespace | |
| 530 | |
| 531 void CreateInputEventData(const WebInputEvent& event, | |
| 532 std::vector<InputEventData>* result) { | |
| 533 result->clear(); | |
| 534 | |
| 535 switch (event.type) { | |
| 536 case WebInputEvent::MouseDown: | |
| 537 case WebInputEvent::MouseUp: | |
| 538 case WebInputEvent::MouseMove: | |
| 539 case WebInputEvent::MouseEnter: | |
| 540 case WebInputEvent::MouseLeave: | |
| 541 case WebInputEvent::ContextMenu: | |
| 542 AppendMouseEvent(event, result); | |
| 543 break; | |
| 544 case WebInputEvent::MouseWheel: | |
| 545 AppendMouseWheelEvent(event, result); | |
| 546 break; | |
| 547 case WebInputEvent::RawKeyDown: | |
| 548 case WebInputEvent::KeyDown: | |
| 549 case WebInputEvent::KeyUp: | |
| 550 AppendKeyEvent(event, result); | |
| 551 break; | |
| 552 case WebInputEvent::Char: | |
| 553 AppendCharEvent(event, result); | |
| 554 break; | |
| 555 case WebInputEvent::TouchStart: | |
| 556 case WebInputEvent::TouchMove: | |
| 557 case WebInputEvent::TouchEnd: | |
| 558 case WebInputEvent::TouchCancel: | |
| 559 AppendTouchEvent(event, result); | |
| 560 break; | |
| 561 case WebInputEvent::Undefined: | |
| 562 default: | |
| 563 break; | |
| 564 } | |
| 565 } | |
| 566 | |
| 567 WebInputEvent* CreateWebInputEvent(const InputEventData& event) { | |
| 568 scoped_ptr<WebInputEvent> web_input_event; | |
| 569 switch (event.event_type) { | |
| 570 case PP_INPUTEVENT_TYPE_UNDEFINED: | |
| 571 return NULL; | |
| 572 case PP_INPUTEVENT_TYPE_MOUSEDOWN: | |
| 573 case PP_INPUTEVENT_TYPE_MOUSEUP: | |
| 574 case PP_INPUTEVENT_TYPE_MOUSEMOVE: | |
| 575 case PP_INPUTEVENT_TYPE_MOUSEENTER: | |
| 576 case PP_INPUTEVENT_TYPE_MOUSELEAVE: | |
| 577 case PP_INPUTEVENT_TYPE_CONTEXTMENU: | |
| 578 web_input_event.reset(BuildMouseEvent(event)); | |
| 579 break; | |
| 580 case PP_INPUTEVENT_TYPE_WHEEL: | |
| 581 web_input_event.reset(BuildMouseWheelEvent(event)); | |
| 582 break; | |
| 583 case PP_INPUTEVENT_TYPE_RAWKEYDOWN: | |
| 584 case PP_INPUTEVENT_TYPE_KEYDOWN: | |
| 585 case PP_INPUTEVENT_TYPE_KEYUP: | |
| 586 web_input_event.reset(BuildKeyEvent(event)); | |
| 587 break; | |
| 588 case PP_INPUTEVENT_TYPE_CHAR: | |
| 589 web_input_event.reset(BuildCharEvent(event)); | |
| 590 break; | |
| 591 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START: | |
| 592 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE: | |
| 593 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END: | |
| 594 case PP_INPUTEVENT_TYPE_IME_TEXT: | |
| 595 // TODO(kinaba) implement in WebKit an event structure to handle | |
| 596 // composition events. | |
| 597 NOTREACHED(); | |
| 598 break; | |
| 599 case PP_INPUTEVENT_TYPE_TOUCHSTART: | |
| 600 case PP_INPUTEVENT_TYPE_TOUCHMOVE: | |
| 601 case PP_INPUTEVENT_TYPE_TOUCHEND: | |
| 602 case PP_INPUTEVENT_TYPE_TOUCHCANCEL: | |
| 603 web_input_event.reset(BuildTouchEvent(event)); | |
| 604 break; | |
| 605 } | |
| 606 | |
| 607 return web_input_event.release(); | |
| 608 } | |
| 609 | |
| 610 // Generate a coherent sequence of input events to simulate a user event. | |
| 611 // From src/third_party/WebKit/Tools/DumpRenderTree/chromium/EventSender.cpp. | |
| 612 std::vector<linked_ptr<WebInputEvent> > CreateSimulatedWebInputEvents( | |
| 613 const ::ppapi::InputEventData& event, | |
| 614 int plugin_x, | |
| 615 int plugin_y) { | |
| 616 std::vector<linked_ptr<WebInputEvent> > events; | |
| 617 linked_ptr<WebInputEvent> original_event(CreateWebInputEvent(event)); | |
| 618 | |
| 619 switch (event.event_type) { | |
| 620 case PP_INPUTEVENT_TYPE_MOUSEDOWN: | |
| 621 case PP_INPUTEVENT_TYPE_MOUSEUP: | |
| 622 case PP_INPUTEVENT_TYPE_MOUSEMOVE: | |
| 623 case PP_INPUTEVENT_TYPE_MOUSEENTER: | |
| 624 case PP_INPUTEVENT_TYPE_MOUSELEAVE: | |
| 625 case PP_INPUTEVENT_TYPE_TOUCHSTART: | |
| 626 case PP_INPUTEVENT_TYPE_TOUCHMOVE: | |
| 627 case PP_INPUTEVENT_TYPE_TOUCHEND: | |
| 628 case PP_INPUTEVENT_TYPE_TOUCHCANCEL: | |
| 629 events.push_back(original_event); | |
| 630 break; | |
| 631 | |
| 632 case PP_INPUTEVENT_TYPE_WHEEL: { | |
| 633 WebMouseWheelEvent* web_mouse_wheel_event = | |
| 634 static_cast<WebMouseWheelEvent*>(original_event.get()); | |
| 635 web_mouse_wheel_event->x = plugin_x; | |
| 636 web_mouse_wheel_event->y = plugin_y; | |
| 637 events.push_back(original_event); | |
| 638 break; | |
| 639 } | |
| 640 | |
| 641 case PP_INPUTEVENT_TYPE_RAWKEYDOWN: | |
| 642 case PP_INPUTEVENT_TYPE_KEYDOWN: | |
| 643 case PP_INPUTEVENT_TYPE_KEYUP: { | |
| 644 // Windows key down events should always be "raw" to avoid an ASSERT. | |
| 645 #if defined(OS_WIN) | |
| 646 WebKeyboardEvent* web_keyboard_event = | |
| 647 static_cast<WebKeyboardEvent*>(original_event.get()); | |
| 648 if (web_keyboard_event->type == WebInputEvent::KeyDown) | |
| 649 web_keyboard_event->type = WebInputEvent::RawKeyDown; | |
| 650 #endif | |
| 651 events.push_back(original_event); | |
| 652 break; | |
| 653 } | |
| 654 | |
| 655 case PP_INPUTEVENT_TYPE_CHAR: { | |
| 656 WebKeyboardEvent* web_char_event = | |
| 657 static_cast<WebKeyboardEvent*>(original_event.get()); | |
| 658 | |
| 659 WebUChar code = 0, text = 0; | |
| 660 bool needs_shift_modifier = false, generate_char = false; | |
| 661 GetKeyCode(event.character_text, | |
| 662 &code, | |
| 663 &text, | |
| 664 &needs_shift_modifier, | |
| 665 &generate_char); | |
| 666 | |
| 667 // Synthesize key down and key up events in all cases. | |
| 668 scoped_ptr<WebKeyboardEvent> key_down_event(new WebKeyboardEvent()); | |
| 669 scoped_ptr<WebKeyboardEvent> key_up_event(new WebKeyboardEvent()); | |
| 670 | |
| 671 key_down_event->type = WebInputEvent::RawKeyDown; | |
| 672 key_down_event->windowsKeyCode = code; | |
| 673 key_down_event->nativeKeyCode = code; | |
| 674 if (needs_shift_modifier) | |
| 675 key_down_event->modifiers |= WebInputEvent::ShiftKey; | |
| 676 | |
| 677 // If a char event is needed, set the text fields. | |
| 678 if (generate_char) { | |
| 679 key_down_event->text[0] = text; | |
| 680 key_down_event->unmodifiedText[0] = text; | |
| 681 } | |
| 682 // Convert the key code to a string identifier. | |
| 683 key_down_event->setKeyIdentifierFromWindowsKeyCode(); | |
| 684 | |
| 685 *key_up_event = *web_char_event = *key_down_event; | |
| 686 | |
| 687 events.push_back(linked_ptr<WebInputEvent>(key_down_event.release())); | |
| 688 | |
| 689 if (generate_char) { | |
| 690 web_char_event->type = WebInputEvent::Char; | |
| 691 web_char_event->keyIdentifier[0] = '\0'; | |
| 692 events.push_back(original_event); | |
| 693 } | |
| 694 | |
| 695 key_up_event->type = WebInputEvent::KeyUp; | |
| 696 events.push_back(linked_ptr<WebInputEvent>(key_up_event.release())); | |
| 697 break; | |
| 698 } | |
| 699 | |
| 700 default: | |
| 701 break; | |
| 702 } | |
| 703 return events; | |
| 704 } | |
| 705 | |
| 706 PP_InputEvent_Class ClassifyInputEvent(WebInputEvent::Type type) { | |
| 707 switch (type) { | |
| 708 case WebInputEvent::MouseDown: | |
| 709 case WebInputEvent::MouseUp: | |
| 710 case WebInputEvent::MouseMove: | |
| 711 case WebInputEvent::MouseEnter: | |
| 712 case WebInputEvent::MouseLeave: | |
| 713 case WebInputEvent::ContextMenu: | |
| 714 return PP_INPUTEVENT_CLASS_MOUSE; | |
| 715 case WebInputEvent::MouseWheel: | |
| 716 return PP_INPUTEVENT_CLASS_WHEEL; | |
| 717 case WebInputEvent::RawKeyDown: | |
| 718 case WebInputEvent::KeyDown: | |
| 719 case WebInputEvent::KeyUp: | |
| 720 case WebInputEvent::Char: | |
| 721 return PP_INPUTEVENT_CLASS_KEYBOARD; | |
| 722 case WebInputEvent::TouchCancel: | |
| 723 case WebInputEvent::TouchEnd: | |
| 724 case WebInputEvent::TouchMove: | |
| 725 case WebInputEvent::TouchStart: | |
| 726 return PP_INPUTEVENT_CLASS_TOUCH; | |
| 727 case WebInputEvent::Undefined: | |
| 728 default: | |
| 729 NOTREACHED(); | |
| 730 return PP_InputEvent_Class(0); | |
| 731 } | |
| 732 } | |
| 733 | |
| 734 } // namespace ppapi | |
| 735 } // namespace webkit | |
| OLD | NEW |