Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / renderer / pepper / event_conversion.cc
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