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