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