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