Add ICU message format support
[chromium-blink-merge.git] / content / renderer / pepper / event_conversion.cc
blobd09e04cded061d008dc3df27e35cd6cefe1d46fa
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.
5 #include "content/renderer/pepper/event_conversion.h"
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 "ppapi/c/pp_input_event.h"
17 #include "ppapi/shared_impl/ppb_input_event_shared.h"
18 #include "ppapi/shared_impl/time_conversion.h"
19 #include "third_party/WebKit/public/platform/WebGamepads.h"
20 #include "third_party/WebKit/public/platform/WebString.h"
21 #include "third_party/WebKit/public/web/WebInputEvent.h"
22 #include "ui/events/keycodes/dom/keycode_converter.h"
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;
36 namespace content {
38 namespace {
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 static_assert(static_cast<int>(PP_INPUTEVENT_MODIFIER_SHIFTKEY) ==
44 static_cast<int>(WebInputEvent::ShiftKey),
45 "ShiftKey should match");
46 static_assert(static_cast<int>(PP_INPUTEVENT_MODIFIER_CONTROLKEY) ==
47 static_cast<int>(WebInputEvent::ControlKey),
48 "ControlKey should match");
49 static_assert(static_cast<int>(PP_INPUTEVENT_MODIFIER_ALTKEY) ==
50 static_cast<int>(WebInputEvent::AltKey),
51 "AltKey should match");
52 static_assert(static_cast<int>(PP_INPUTEVENT_MODIFIER_METAKEY) ==
53 static_cast<int>(WebInputEvent::MetaKey),
54 "MetaKey should match");
55 static_assert(static_cast<int>(PP_INPUTEVENT_MODIFIER_ISKEYPAD) ==
56 static_cast<int>(WebInputEvent::IsKeyPad),
57 "KeyPad should match");
58 static_assert(static_cast<int>(PP_INPUTEVENT_MODIFIER_ISAUTOREPEAT) ==
59 static_cast<int>(WebInputEvent::IsAutoRepeat),
60 "AutoRepeat should match");
61 static_assert(static_cast<int>(PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) ==
62 static_cast<int>(WebInputEvent::LeftButtonDown),
63 "LeftButton should match");
64 static_assert(static_cast<int>(PP_INPUTEVENT_MODIFIER_MIDDLEBUTTONDOWN) ==
65 static_cast<int>(WebInputEvent::MiddleButtonDown),
66 "MiddleButton should match");
67 static_assert(static_cast<int>(PP_INPUTEVENT_MODIFIER_RIGHTBUTTONDOWN) ==
68 static_cast<int>(WebInputEvent::RightButtonDown),
69 "RightButton should match");
70 static_assert(static_cast<int>(PP_INPUTEVENT_MODIFIER_CAPSLOCKKEY) ==
71 static_cast<int>(WebInputEvent::CapsLockOn),
72 "CapsLock should match");
73 static_assert(static_cast<int>(PP_INPUTEVENT_MODIFIER_NUMLOCKKEY) ==
74 static_cast<int>(WebInputEvent::NumLockOn),
75 "NumLock should match");
76 static_assert(static_cast<int>(PP_INPUTEVENT_MODIFIER_ISLEFT) ==
77 static_cast<int>(WebInputEvent::IsLeft),
78 "IsLeft should match");
79 static_assert(static_cast<int>(PP_INPUTEVENT_MODIFIER_ISRIGHT) ==
80 static_cast<int>(WebInputEvent::IsRight),
81 "IsRight should match");
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;
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;
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 #if defined(OS_MACOSX)
139 // Workaround for |domCode| not being set on OS X. crbug.com/493833
140 result.code = ui::KeycodeConverter::DomCodeToCodeString(
141 ui::KeycodeConverter::NativeKeycodeToDomCode(key_event.nativeKeyCode));
142 #else
143 result.code = ui::KeycodeConverter::DomCodeToCodeString(
144 static_cast<ui::DomCode>(key_event.domCode));
145 #endif
146 result_events->push_back(result);
149 void AppendCharEvent(const WebInputEvent& event,
150 std::vector<InputEventData>* result_events) {
151 const WebKeyboardEvent& key_event =
152 static_cast<const WebKeyboardEvent&>(event);
154 // This is a bit complex, the input event will normally just have one 16-bit
155 // character in it, but may be zero or more than one. The text array is
156 // just padded with 0 values for the unused ones, but is not necessarily
157 // null-terminated.
159 // Here we see how many UTF-16 characters we have.
160 size_t utf16_char_count = 0;
161 while (utf16_char_count < WebKeyboardEvent::textLengthCap &&
162 key_event.text[utf16_char_count])
163 utf16_char_count++;
165 // Make a separate InputEventData for each Unicode character in the input.
166 base::i18n::UTF16CharIterator iter(key_event.text, utf16_char_count);
167 while (!iter.end()) {
168 InputEventData result = GetEventWithCommonFieldsAndType(event);
169 result.event_modifiers = key_event.modifiers;
170 base::WriteUnicodeCharacter(iter.get(), &result.character_text);
172 result_events->push_back(result);
173 iter.Advance();
177 void AppendMouseEvent(const WebInputEvent& event,
178 std::vector<InputEventData>* result_events) {
179 static_assert(static_cast<int>(WebMouseEvent::ButtonNone) ==
180 static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_NONE),
181 "MouseNone should match");
182 static_assert(static_cast<int>(WebMouseEvent::ButtonLeft) ==
183 static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_LEFT),
184 "MouseLeft should match");
185 static_assert(static_cast<int>(WebMouseEvent::ButtonRight) ==
186 static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_RIGHT),
187 "MouseRight should match");
188 static_assert(static_cast<int>(WebMouseEvent::ButtonMiddle) ==
189 static_cast<int>(PP_INPUTEVENT_MOUSEBUTTON_MIDDLE),
190 "MouseMiddle should match");
192 const WebMouseEvent& mouse_event = static_cast<const WebMouseEvent&>(event);
193 InputEventData result = GetEventWithCommonFieldsAndType(event);
194 result.event_modifiers = mouse_event.modifiers;
195 if (mouse_event.type == WebInputEvent::MouseDown ||
196 mouse_event.type == WebInputEvent::MouseMove ||
197 mouse_event.type == WebInputEvent::MouseUp) {
198 result.mouse_button =
199 static_cast<PP_InputEvent_MouseButton>(mouse_event.button);
201 result.mouse_position.x = mouse_event.x;
202 result.mouse_position.y = mouse_event.y;
203 result.mouse_click_count = mouse_event.clickCount;
204 result.mouse_movement.x = mouse_event.movementX;
205 result.mouse_movement.y = mouse_event.movementY;
206 result_events->push_back(result);
209 void AppendMouseWheelEvent(const WebInputEvent& event,
210 std::vector<InputEventData>* result_events) {
211 const WebMouseWheelEvent& mouse_wheel_event =
212 static_cast<const WebMouseWheelEvent&>(event);
213 InputEventData result = GetEventWithCommonFieldsAndType(event);
214 result.event_modifiers = mouse_wheel_event.modifiers;
215 result.wheel_delta.x = mouse_wheel_event.deltaX;
216 result.wheel_delta.y = mouse_wheel_event.deltaY;
217 result.wheel_ticks.x = mouse_wheel_event.wheelTicksX;
218 result.wheel_ticks.y = mouse_wheel_event.wheelTicksY;
219 result.wheel_scroll_by_page = !!mouse_wheel_event.scrollByPage;
220 result_events->push_back(result);
223 enum IncludedTouchPointTypes {
224 ALL, // All pointers targetting the plugin.
225 ACTIVE, // Only pointers that are currently down.
226 CHANGED // Only pointers that have changed since the previous event.
228 void SetPPTouchPoints(const WebTouchPoint* touches,
229 uint32_t touches_length,
230 IncludedTouchPointTypes included_types,
231 std::vector<PP_TouchPoint>* result) {
232 for (uint32_t i = 0; i < touches_length; i++) {
233 const WebTouchPoint& touch_point = touches[i];
234 if (included_types == ACTIVE &&
235 (touch_point.state == WebTouchPoint::StateReleased ||
236 touch_point.state == WebTouchPoint::StateCancelled)) {
237 continue;
239 if (included_types == CHANGED &&
240 (touch_point.state == WebTouchPoint::StateUndefined ||
241 touch_point.state == WebTouchPoint::StateStationary)) {
242 continue;
244 PP_TouchPoint pp_pt;
245 pp_pt.id = touch_point.id;
246 pp_pt.position.x = touch_point.position.x;
247 pp_pt.position.y = touch_point.position.y;
248 pp_pt.radius.x = touch_point.radiusX;
249 pp_pt.radius.y = touch_point.radiusY;
250 pp_pt.rotation_angle = touch_point.rotationAngle;
251 pp_pt.pressure = touch_point.force;
252 result->push_back(pp_pt);
256 void AppendTouchEvent(const WebInputEvent& event,
257 std::vector<InputEventData>* result_events) {
258 const WebTouchEvent& touch_event =
259 reinterpret_cast<const WebTouchEvent&>(event);
261 InputEventData result = GetEventWithCommonFieldsAndType(event);
262 SetPPTouchPoints(
263 touch_event.touches, touch_event.touchesLength, ACTIVE, &result.touches);
264 SetPPTouchPoints(touch_event.touches,
265 touch_event.touchesLength,
266 CHANGED,
267 &result.changed_touches);
268 SetPPTouchPoints(touch_event.touches,
269 touch_event.touchesLength,
270 ALL,
271 &result.target_touches);
273 result_events->push_back(result);
276 WebTouchPoint CreateWebTouchPoint(const PP_TouchPoint& pp_pt,
277 WebTouchPoint::State state) {
278 WebTouchPoint pt;
279 pt.id = pp_pt.id;
280 pt.position.x = pp_pt.position.x;
281 pt.position.y = pp_pt.position.y;
282 // TODO bug:http://code.google.com/p/chromium/issues/detail?id=93902
283 pt.screenPosition.x = 0;
284 pt.screenPosition.y = 0;
285 pt.force = pp_pt.pressure;
286 pt.radiusX = pp_pt.radius.x;
287 pt.radiusY = pp_pt.radius.y;
288 pt.rotationAngle = pp_pt.rotation_angle;
289 pt.state = state;
290 return pt;
293 bool HasTouchPointWithId(const WebTouchPoint* web_touches,
294 uint32_t web_touches_length,
295 uint32_t id) {
296 // Note: A brute force search to find the (potentially) existing touch point
297 // is cheap given the small bound on |WebTouchEvent::touchesLengthCap|.
298 for (uint32_t i = 0; i < web_touches_length; ++i) {
299 if (web_touches[i].id == static_cast<int>(id))
300 return true;
302 return false;
305 void SetWebTouchPointsIfNotYetSet(const std::vector<PP_TouchPoint>& pp_touches,
306 WebTouchPoint::State state,
307 WebTouchPoint* web_touches,
308 uint32_t* web_touches_length) {
309 const uint32_t initial_web_touches_length = *web_touches_length;
310 const uint32_t touches_length =
311 std::min(static_cast<uint32_t>(pp_touches.size()),
312 static_cast<uint32_t>(WebTouchEvent::touchesLengthCap));
313 for (uint32_t i = 0; i < touches_length; ++i) {
314 const uint32_t touch_index = *web_touches_length;
315 if (touch_index >= static_cast<uint32_t>(WebTouchEvent::touchesLengthCap))
316 return;
318 const PP_TouchPoint& pp_pt = pp_touches[i];
319 if (HasTouchPointWithId(web_touches, initial_web_touches_length, pp_pt.id))
320 continue;
322 web_touches[touch_index] = CreateWebTouchPoint(pp_pt, state);
323 ++(*web_touches_length);
327 WebTouchEvent* BuildTouchEvent(const InputEventData& event) {
328 WebTouchEvent* web_event = new WebTouchEvent();
329 WebTouchPoint::State state = WebTouchPoint::StateUndefined;
330 WebInputEvent::Type type = WebInputEvent::Undefined;
331 switch (event.event_type) {
332 case PP_INPUTEVENT_TYPE_TOUCHSTART:
333 type = WebInputEvent::TouchStart;
334 state = WebTouchPoint::StatePressed;
335 break;
336 case PP_INPUTEVENT_TYPE_TOUCHMOVE:
337 type = WebInputEvent::TouchMove;
338 state = WebTouchPoint::StateMoved;
339 break;
340 case PP_INPUTEVENT_TYPE_TOUCHEND:
341 type = WebInputEvent::TouchEnd;
342 state = WebTouchPoint::StateReleased;
343 break;
344 case PP_INPUTEVENT_TYPE_TOUCHCANCEL:
345 type = WebInputEvent::TouchCancel;
346 state = WebTouchPoint::StateCancelled;
347 break;
348 default:
349 NOTREACHED();
351 WebTouchEventTraits::ResetType(
352 type, PPTimeTicksToEventTime(event.event_time_stamp), web_event);
353 web_event->touchesLength = 0;
355 // First add all changed touches, then add only the remaining unset
356 // (stationary) touches.
357 SetWebTouchPointsIfNotYetSet(event.changed_touches,
358 state,
359 web_event->touches,
360 &web_event->touchesLength);
361 SetWebTouchPointsIfNotYetSet(event.touches,
362 WebTouchPoint::StateStationary,
363 web_event->touches,
364 &web_event->touchesLength);
366 return web_event;
369 WebKeyboardEvent* BuildKeyEvent(const InputEventData& event) {
370 WebKeyboardEvent* key_event = new WebKeyboardEvent();
371 switch (event.event_type) {
372 case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
373 key_event->type = WebInputEvent::RawKeyDown;
374 break;
375 case PP_INPUTEVENT_TYPE_KEYDOWN:
376 key_event->type = WebInputEvent::KeyDown;
377 break;
378 case PP_INPUTEVENT_TYPE_KEYUP:
379 key_event->type = WebInputEvent::KeyUp;
380 break;
381 default:
382 NOTREACHED();
384 key_event->timeStampSeconds = PPTimeTicksToEventTime(event.event_time_stamp);
385 key_event->modifiers = event.event_modifiers;
386 key_event->windowsKeyCode = event.key_code;
387 key_event->setKeyIdentifierFromWindowsKeyCode();
388 return key_event;
391 WebKeyboardEvent* BuildCharEvent(const InputEventData& event) {
392 WebKeyboardEvent* key_event = new WebKeyboardEvent();
393 key_event->type = WebInputEvent::Char;
394 key_event->timeStampSeconds = PPTimeTicksToEventTime(event.event_time_stamp);
395 key_event->modifiers = event.event_modifiers;
397 // Make sure to not read beyond the buffer in case some bad code doesn't
398 // NULL-terminate it (this is called from plugins).
399 size_t text_length_cap = WebKeyboardEvent::textLengthCap;
400 base::string16 text16 = base::UTF8ToUTF16(event.character_text);
402 memset(key_event->text, 0, text_length_cap);
403 memset(key_event->unmodifiedText, 0, text_length_cap);
404 for (size_t i = 0; i < std::min(text_length_cap, text16.size()); ++i)
405 key_event->text[i] = text16[i];
406 return key_event;
409 WebMouseEvent* BuildMouseEvent(const InputEventData& event) {
410 WebMouseEvent* mouse_event = new WebMouseEvent();
411 switch (event.event_type) {
412 case PP_INPUTEVENT_TYPE_MOUSEDOWN:
413 mouse_event->type = WebInputEvent::MouseDown;
414 break;
415 case PP_INPUTEVENT_TYPE_MOUSEUP:
416 mouse_event->type = WebInputEvent::MouseUp;
417 break;
418 case PP_INPUTEVENT_TYPE_MOUSEMOVE:
419 mouse_event->type = WebInputEvent::MouseMove;
420 break;
421 case PP_INPUTEVENT_TYPE_MOUSEENTER:
422 mouse_event->type = WebInputEvent::MouseEnter;
423 break;
424 case PP_INPUTEVENT_TYPE_MOUSELEAVE:
425 mouse_event->type = WebInputEvent::MouseLeave;
426 break;
427 case PP_INPUTEVENT_TYPE_CONTEXTMENU:
428 mouse_event->type = WebInputEvent::ContextMenu;
429 break;
430 default:
431 NOTREACHED();
433 mouse_event->timeStampSeconds =
434 PPTimeTicksToEventTime(event.event_time_stamp);
435 mouse_event->modifiers = event.event_modifiers;
436 mouse_event->button = static_cast<WebMouseEvent::Button>(event.mouse_button);
437 if (mouse_event->type == WebInputEvent::MouseMove) {
438 if (mouse_event->modifiers & WebInputEvent::LeftButtonDown)
439 mouse_event->button = WebMouseEvent::ButtonLeft;
440 else if (mouse_event->modifiers & WebInputEvent::MiddleButtonDown)
441 mouse_event->button = WebMouseEvent::ButtonMiddle;
442 else if (mouse_event->modifiers & WebInputEvent::RightButtonDown)
443 mouse_event->button = WebMouseEvent::ButtonRight;
445 mouse_event->x = event.mouse_position.x;
446 mouse_event->y = event.mouse_position.y;
447 mouse_event->clickCount = event.mouse_click_count;
448 mouse_event->movementX = event.mouse_movement.x;
449 mouse_event->movementY = event.mouse_movement.y;
450 return mouse_event;
453 WebMouseWheelEvent* BuildMouseWheelEvent(const InputEventData& event) {
454 WebMouseWheelEvent* mouse_wheel_event = new WebMouseWheelEvent();
455 mouse_wheel_event->type = WebInputEvent::MouseWheel;
456 mouse_wheel_event->timeStampSeconds =
457 PPTimeTicksToEventTime(event.event_time_stamp);
458 mouse_wheel_event->modifiers = event.event_modifiers;
459 mouse_wheel_event->deltaX = event.wheel_delta.x;
460 mouse_wheel_event->deltaY = event.wheel_delta.y;
461 mouse_wheel_event->wheelTicksX = event.wheel_ticks.x;
462 mouse_wheel_event->wheelTicksY = event.wheel_ticks.y;
463 mouse_wheel_event->scrollByPage = event.wheel_scroll_by_page;
464 return mouse_wheel_event;
467 #if !defined(OS_WIN)
468 #define VK_RETURN 0x0D
470 #define VK_PRIOR 0x21
471 #define VK_NEXT 0x22
472 #define VK_END 0x23
473 #define VK_HOME 0x24
474 #define VK_LEFT 0x25
475 #define VK_UP 0x26
476 #define VK_RIGHT 0x27
477 #define VK_DOWN 0x28
478 #define VK_SNAPSHOT 0x2C
479 #define VK_INSERT 0x2D
480 #define VK_DELETE 0x2E
482 #define VK_APPS 0x5D
484 #define VK_F1 0x70
485 #endif
487 // Convert a character string to a Windows virtual key code. Adapted from
488 // src/components/test_runner/event_sender.cc. This
489 // is used by CreateSimulatedWebInputEvents to convert keyboard events.
490 void GetKeyCode(const std::string& char_text,
491 WebUChar* code,
492 WebUChar* text,
493 bool* needs_shift_modifier,
494 bool* generate_char) {
495 WebUChar vk_code = 0;
496 WebUChar vk_text = 0;
497 *needs_shift_modifier = false;
498 *generate_char = false;
499 if ("\n" == char_text) {
500 vk_text = vk_code = VK_RETURN;
501 *generate_char = true;
502 } else if ("rightArrow" == char_text) {
503 vk_code = VK_RIGHT;
504 } else if ("downArrow" == char_text) {
505 vk_code = VK_DOWN;
506 } else if ("leftArrow" == char_text) {
507 vk_code = VK_LEFT;
508 } else if ("upArrow" == char_text) {
509 vk_code = VK_UP;
510 } else if ("insert" == char_text) {
511 vk_code = VK_INSERT;
512 } else if ("delete" == char_text) {
513 vk_code = VK_DELETE;
514 } else if ("pageUp" == char_text) {
515 vk_code = VK_PRIOR;
516 } else if ("pageDown" == char_text) {
517 vk_code = VK_NEXT;
518 } else if ("home" == char_text) {
519 vk_code = VK_HOME;
520 } else if ("end" == char_text) {
521 vk_code = VK_END;
522 } else if ("printScreen" == char_text) {
523 vk_code = VK_SNAPSHOT;
524 } else if ("menu" == char_text) {
525 vk_code = VK_APPS;
526 } else {
527 // Compare the input string with the function-key names defined by the
528 // DOM spec (i.e. "F1",...,"F24").
529 for (int i = 1; i <= 24; ++i) {
530 std::string functionKeyName = base::StringPrintf("F%d", i);
531 if (functionKeyName == char_text) {
532 vk_code = VK_F1 + (i - 1);
533 break;
536 if (!vk_code) {
537 WebString web_char_text =
538 WebString::fromUTF8(char_text.data(), char_text.size());
539 DCHECK_EQ(web_char_text.length(), 1U);
540 vk_text = vk_code = web_char_text.at(0);
541 *needs_shift_modifier =
542 (vk_code & 0xFF) >= 'A' && (vk_code & 0xFF) <= 'Z';
543 if ((vk_code & 0xFF) >= 'a' && (vk_code & 0xFF) <= 'z')
544 vk_code -= 'a' - 'A';
545 *generate_char = true;
549 *code = vk_code;
550 *text = vk_text;
553 } // namespace
555 void CreateInputEventData(const WebInputEvent& event,
556 std::vector<InputEventData>* result) {
557 result->clear();
559 switch (event.type) {
560 case WebInputEvent::MouseDown:
561 case WebInputEvent::MouseUp:
562 case WebInputEvent::MouseMove:
563 case WebInputEvent::MouseEnter:
564 case WebInputEvent::MouseLeave:
565 case WebInputEvent::ContextMenu:
566 AppendMouseEvent(event, result);
567 break;
568 case WebInputEvent::MouseWheel:
569 AppendMouseWheelEvent(event, result);
570 break;
571 case WebInputEvent::RawKeyDown:
572 case WebInputEvent::KeyDown:
573 case WebInputEvent::KeyUp:
574 AppendKeyEvent(event, result);
575 break;
576 case WebInputEvent::Char:
577 AppendCharEvent(event, result);
578 break;
579 case WebInputEvent::TouchStart:
580 case WebInputEvent::TouchMove:
581 case WebInputEvent::TouchEnd:
582 case WebInputEvent::TouchCancel:
583 AppendTouchEvent(event, result);
584 break;
585 case WebInputEvent::Undefined:
586 default:
587 break;
591 WebInputEvent* CreateWebInputEvent(const InputEventData& event) {
592 scoped_ptr<WebInputEvent> web_input_event;
593 switch (event.event_type) {
594 case PP_INPUTEVENT_TYPE_UNDEFINED:
595 return NULL;
596 case PP_INPUTEVENT_TYPE_MOUSEDOWN:
597 case PP_INPUTEVENT_TYPE_MOUSEUP:
598 case PP_INPUTEVENT_TYPE_MOUSEMOVE:
599 case PP_INPUTEVENT_TYPE_MOUSEENTER:
600 case PP_INPUTEVENT_TYPE_MOUSELEAVE:
601 case PP_INPUTEVENT_TYPE_CONTEXTMENU:
602 web_input_event.reset(BuildMouseEvent(event));
603 break;
604 case PP_INPUTEVENT_TYPE_WHEEL:
605 web_input_event.reset(BuildMouseWheelEvent(event));
606 break;
607 case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
608 case PP_INPUTEVENT_TYPE_KEYDOWN:
609 case PP_INPUTEVENT_TYPE_KEYUP:
610 web_input_event.reset(BuildKeyEvent(event));
611 break;
612 case PP_INPUTEVENT_TYPE_CHAR:
613 web_input_event.reset(BuildCharEvent(event));
614 break;
615 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START:
616 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
617 case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
618 case PP_INPUTEVENT_TYPE_IME_TEXT:
619 // TODO(kinaba) implement in WebKit an event structure to handle
620 // composition events.
621 NOTREACHED();
622 break;
623 case PP_INPUTEVENT_TYPE_TOUCHSTART:
624 case PP_INPUTEVENT_TYPE_TOUCHMOVE:
625 case PP_INPUTEVENT_TYPE_TOUCHEND:
626 case PP_INPUTEVENT_TYPE_TOUCHCANCEL:
627 web_input_event.reset(BuildTouchEvent(event));
628 break;
631 return web_input_event.release();
634 // Generate a coherent sequence of input events to simulate a user event.
635 // From src/components/test_runner/event_sender.cc.
636 std::vector<linked_ptr<WebInputEvent> > CreateSimulatedWebInputEvents(
637 const ppapi::InputEventData& event,
638 int plugin_x,
639 int plugin_y) {
640 std::vector<linked_ptr<WebInputEvent> > events;
641 linked_ptr<WebInputEvent> original_event(CreateWebInputEvent(event));
643 switch (event.event_type) {
644 case PP_INPUTEVENT_TYPE_MOUSEDOWN:
645 case PP_INPUTEVENT_TYPE_MOUSEUP:
646 case PP_INPUTEVENT_TYPE_MOUSEMOVE:
647 case PP_INPUTEVENT_TYPE_MOUSEENTER:
648 case PP_INPUTEVENT_TYPE_MOUSELEAVE:
649 case PP_INPUTEVENT_TYPE_TOUCHSTART:
650 case PP_INPUTEVENT_TYPE_TOUCHMOVE:
651 case PP_INPUTEVENT_TYPE_TOUCHEND:
652 case PP_INPUTEVENT_TYPE_TOUCHCANCEL:
653 events.push_back(original_event);
654 break;
656 case PP_INPUTEVENT_TYPE_WHEEL: {
657 WebMouseWheelEvent* web_mouse_wheel_event =
658 static_cast<WebMouseWheelEvent*>(original_event.get());
659 web_mouse_wheel_event->x = plugin_x;
660 web_mouse_wheel_event->y = plugin_y;
661 events.push_back(original_event);
662 break;
665 case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
666 case PP_INPUTEVENT_TYPE_KEYDOWN:
667 case PP_INPUTEVENT_TYPE_KEYUP: {
668 // Windows key down events should always be "raw" to avoid an ASSERT.
669 #if defined(OS_WIN)
670 WebKeyboardEvent* web_keyboard_event =
671 static_cast<WebKeyboardEvent*>(original_event.get());
672 if (web_keyboard_event->type == WebInputEvent::KeyDown)
673 web_keyboard_event->type = WebInputEvent::RawKeyDown;
674 #endif
675 events.push_back(original_event);
676 break;
679 case PP_INPUTEVENT_TYPE_CHAR: {
680 WebKeyboardEvent* web_char_event =
681 static_cast<WebKeyboardEvent*>(original_event.get());
683 WebUChar code = 0, text = 0;
684 bool needs_shift_modifier = false, generate_char = false;
685 GetKeyCode(event.character_text,
686 &code,
687 &text,
688 &needs_shift_modifier,
689 &generate_char);
691 // Synthesize key down and key up events in all cases.
692 scoped_ptr<WebKeyboardEvent> key_down_event(new WebKeyboardEvent());
693 scoped_ptr<WebKeyboardEvent> key_up_event(new WebKeyboardEvent());
695 key_down_event->type = WebInputEvent::RawKeyDown;
696 key_down_event->windowsKeyCode = code;
697 key_down_event->nativeKeyCode = code;
698 if (needs_shift_modifier)
699 key_down_event->modifiers |= WebInputEvent::ShiftKey;
701 // If a char event is needed, set the text fields.
702 if (generate_char) {
703 key_down_event->text[0] = text;
704 key_down_event->unmodifiedText[0] = text;
706 // Convert the key code to a string identifier.
707 key_down_event->setKeyIdentifierFromWindowsKeyCode();
709 *key_up_event = *web_char_event = *key_down_event;
711 events.push_back(linked_ptr<WebInputEvent>(key_down_event.release()));
713 if (generate_char) {
714 web_char_event->type = WebInputEvent::Char;
715 web_char_event->keyIdentifier[0] = '\0';
716 events.push_back(original_event);
719 key_up_event->type = WebInputEvent::KeyUp;
720 events.push_back(linked_ptr<WebInputEvent>(key_up_event.release()));
721 break;
724 default:
725 break;
727 return events;
730 PP_InputEvent_Class ClassifyInputEvent(WebInputEvent::Type type) {
731 switch (type) {
732 case WebInputEvent::MouseDown:
733 case WebInputEvent::MouseUp:
734 case WebInputEvent::MouseMove:
735 case WebInputEvent::MouseEnter:
736 case WebInputEvent::MouseLeave:
737 case WebInputEvent::ContextMenu:
738 return PP_INPUTEVENT_CLASS_MOUSE;
739 case WebInputEvent::MouseWheel:
740 return PP_INPUTEVENT_CLASS_WHEEL;
741 case WebInputEvent::RawKeyDown:
742 case WebInputEvent::KeyDown:
743 case WebInputEvent::KeyUp:
744 case WebInputEvent::Char:
745 return PP_INPUTEVENT_CLASS_KEYBOARD;
746 case WebInputEvent::TouchCancel:
747 case WebInputEvent::TouchEnd:
748 case WebInputEvent::TouchMove:
749 case WebInputEvent::TouchStart:
750 return PP_INPUTEVENT_CLASS_TOUCH;
751 case WebInputEvent::Undefined:
752 default:
753 CHECK(WebInputEvent::isGestureEventType(type));
754 return PP_InputEvent_Class(0);
758 } // namespace content