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