pepper_input_handler.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 "remoting/client/plugin/pepper_input_handler.h"
6
7#include "base/logging.h"
8#include "ppapi/c/dev/ppb_keyboard_input_event_dev.h"
9#include "ppapi/cpp/input_event.h"
10#include "ppapi/cpp/module_impl.h"
11#include "ppapi/cpp/point.h"
12#include "remoting/proto/event.pb.h"
13
14namespace remoting {
15
16PepperInputHandler::PepperInputHandler(protocol::InputStub* input_stub)
17    : input_stub_(input_stub),
18      wheel_delta_x_(0),
19      wheel_delta_y_(0),
20      wheel_ticks_x_(0),
21      wheel_ticks_y_(0)
22{
23}
24
25PepperInputHandler::~PepperInputHandler() {
26}
27
28// Helper function to get the USB key code using the Dev InputEvent interface.
29uint32_t GetUsbKeyCode(pp::KeyboardInputEvent pp_key_event) {
30  const PPB_KeyboardInputEvent_Dev* key_event_interface =
31      reinterpret_cast<const PPB_KeyboardInputEvent_Dev*>(
32          pp::Module::Get()->GetBrowserInterface(
33              PPB_KEYBOARD_INPUT_EVENT_DEV_INTERFACE));
34  if (!key_event_interface)
35    return 0;
36  return key_event_interface->GetUsbKeyCode(pp_key_event.pp_resource());
37}
38
39bool PepperInputHandler::HandleInputEvent(const pp::InputEvent& event) {
40  switch (event.GetType()) {
41    case PP_INPUTEVENT_TYPE_CONTEXTMENU: {
42      // We need to return true here or else we'll get a local (plugin) context
43      // menu instead of the mouseup event for the right click.
44      return true;
45    }
46
47    case PP_INPUTEVENT_TYPE_KEYDOWN:
48    case PP_INPUTEVENT_TYPE_KEYUP: {
49      pp::KeyboardInputEvent pp_key_event(event);
50      protocol::KeyEvent key_event;
51      key_event.set_usb_keycode(GetUsbKeyCode(pp_key_event));
52      key_event.set_pressed(event.GetType() == PP_INPUTEVENT_TYPE_KEYDOWN);
53      input_stub_->InjectKeyEvent(key_event);
54      return true;
55    }
56
57    case PP_INPUTEVENT_TYPE_MOUSEDOWN:
58    case PP_INPUTEVENT_TYPE_MOUSEUP: {
59      pp::MouseInputEvent pp_mouse_event(event);
60      protocol::MouseEvent mouse_event;
61      switch (pp_mouse_event.GetButton()) {
62        case PP_INPUTEVENT_MOUSEBUTTON_LEFT:
63          mouse_event.set_button(protocol::MouseEvent::BUTTON_LEFT);
64          break;
65        case PP_INPUTEVENT_MOUSEBUTTON_MIDDLE:
66          mouse_event.set_button(protocol::MouseEvent::BUTTON_MIDDLE);
67          break;
68        case PP_INPUTEVENT_MOUSEBUTTON_RIGHT:
69          mouse_event.set_button(protocol::MouseEvent::BUTTON_RIGHT);
70          break;
71        case PP_INPUTEVENT_MOUSEBUTTON_NONE:
72          break;
73      }
74      if (mouse_event.has_button()) {
75        bool is_down = (event.GetType() == PP_INPUTEVENT_TYPE_MOUSEDOWN);
76        mouse_event.set_button_down(is_down);
77        mouse_event.set_x(pp_mouse_event.GetPosition().x());
78        mouse_event.set_y(pp_mouse_event.GetPosition().y());
79        input_stub_->InjectMouseEvent(mouse_event);
80      }
81      return true;
82    }
83
84    case PP_INPUTEVENT_TYPE_MOUSEMOVE:
85    case PP_INPUTEVENT_TYPE_MOUSEENTER:
86    case PP_INPUTEVENT_TYPE_MOUSELEAVE: {
87      pp::MouseInputEvent pp_mouse_event(event);
88      protocol::MouseEvent mouse_event;
89      mouse_event.set_x(pp_mouse_event.GetPosition().x());
90      mouse_event.set_y(pp_mouse_event.GetPosition().y());
91      input_stub_->InjectMouseEvent(mouse_event);
92      return true;
93    }
94
95    case PP_INPUTEVENT_TYPE_WHEEL: {
96      pp::WheelInputEvent pp_wheel_event(event);
97
98      // Don't handle scroll-by-page events, for now.
99      if (pp_wheel_event.GetScrollByPage())
100        return false;
101
102      // Add this event to our accumulated sub-pixel deltas.
103      pp::FloatPoint delta = pp_wheel_event.GetDelta();
104      wheel_delta_x_ += delta.x();
105      wheel_delta_y_ += delta.y();
106
107      // If there is at least a pixel's movement, emit an event.
108      int delta_x = static_cast<int>(wheel_delta_x_);
109      int delta_y = static_cast<int>(wheel_delta_y_);
110      if (delta_x != 0 || delta_y != 0) {
111        wheel_delta_x_ -= delta_x;
112        wheel_delta_y_ -= delta_y;
113        protocol::MouseEvent mouse_event;
114        mouse_event.set_wheel_delta_x(delta_x);
115        mouse_event.set_wheel_delta_y(delta_y);
116
117        // Add legacy wheel "tick" offsets to the event.
118        // TODO(wez): Remove this once all hosts support the new
119        // fields.  See crbug.com/155668.
120#if defined(OS_WIN)
121        // Windows' standard value for WHEEL_DELTA.
122        const float kPixelsPerWheelTick = 120.0f;
123#elif defined(OS_MAC)
124        // From Source/WebKit/chromium/src/mac/WebInputFactory.mm.
125        const float kPixelsPerWheelTick = 40.0f;
126#else // OS_MAC
127        // From Source/WebKit/chromium/src/gtk/WebInputFactory.cc.
128        const float kPixelsPerWheelTick = 160.0f / 3.0f;
129#endif // OS_MAC
130        wheel_ticks_x_ += delta_x / kPixelsPerWheelTick;
131        wheel_ticks_y_ += delta_y / kPixelsPerWheelTick;
132        int ticks_x = static_cast<int>(wheel_ticks_x_);
133        int ticks_y = static_cast<int>(wheel_ticks_y_);
134        wheel_ticks_x_ -= ticks_x;
135        wheel_ticks_y_ -= ticks_y;
136        mouse_event.set_wheel_offset_x(ticks_x);
137        mouse_event.set_wheel_offset_y(ticks_y);
138
139        input_stub_->InjectMouseEvent(mouse_event);
140      }
141      return true;
142    }
143
144    case PP_INPUTEVENT_TYPE_CHAR:
145      // Consume but ignore character input events.
146      return true;
147
148    default: {
149      LOG(INFO) << "Unhandled input event: " << event.GetType();
150      break;
151    }
152  }
153
154  return false;
155}
156
157}  // namespace remoting
158