15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/client/plugin/pepper_input_handler.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/dev/ppb_keyboard_input_event_dev.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/input_event.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/module_impl.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/point.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/proto/event.pb.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PepperInputHandler::PepperInputHandler(protocol::InputStub* input_stub) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : input_stub_(input_stub), 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wheel_delta_x_(0), 19558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch wheel_delta_y_(0), 20558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch wheel_ticks_x_(0), 21558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch wheel_ticks_y_(0) { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PepperInputHandler::~PepperInputHandler() { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper function to get the USB key code using the Dev InputEvent interface. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32_t GetUsbKeyCode(pp::KeyboardInputEvent pp_key_event) { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PPB_KeyboardInputEvent_Dev* key_event_interface = 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const PPB_KeyboardInputEvent_Dev*>( 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::Module::Get()->GetBrowserInterface( 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PPB_KEYBOARD_INPUT_EVENT_DEV_INTERFACE)); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!key_event_interface) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return key_event_interface->GetUsbKeyCode(pp_key_event.pp_resource()); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PepperInputHandler::HandleInputEvent(const pp::InputEvent& event) { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (event.GetType()) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_CONTEXTMENU: { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to return true here or else we'll get a local (plugin) context 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // menu instead of the mouseup event for the right click. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_KEYDOWN: 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_KEYUP: { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::KeyboardInputEvent pp_key_event(event); 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch uint32_t modifiers = event.GetModifiers(); 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch uint32_t lock_states = 0; 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (modifiers & PP_INPUTEVENT_MODIFIER_CAPSLOCKKEY) 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch lock_states |= protocol::KeyEvent::LOCK_STATES_CAPSLOCK; 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (modifiers & PP_INPUTEVENT_MODIFIER_NUMLOCKKEY) 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch lock_states |= protocol::KeyEvent::LOCK_STATES_NUMLOCK; 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol::KeyEvent key_event; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.set_usb_keycode(GetUsbKeyCode(pp_key_event)); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.set_pressed(event.GetType() == PP_INPUTEVENT_TYPE_KEYDOWN); 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch key_event.set_lock_states(lock_states); 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_stub_->InjectKeyEvent(key_event); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_MOUSEDOWN: 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_MOUSEUP: { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp::MouseInputEvent pp_mouse_event(event); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol::MouseEvent mouse_event; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (pp_mouse_event.GetButton()) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_MOUSEBUTTON_LEFT: 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_event.set_button(protocol::MouseEvent::BUTTON_LEFT); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_MOUSEBUTTON_MIDDLE: 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_event.set_button(protocol::MouseEvent::BUTTON_MIDDLE); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_MOUSEBUTTON_RIGHT: 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_event.set_button(protocol::MouseEvent::BUTTON_RIGHT); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_MOUSEBUTTON_NONE: 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mouse_event.has_button()) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_down = (event.GetType() == PP_INPUTEVENT_TYPE_MOUSEDOWN); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_event.set_button_down(is_down); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_event.set_x(pp_mouse_event.GetPosition().x()); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_event.set_y(pp_mouse_event.GetPosition().y()); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_stub_->InjectMouseEvent(mouse_event); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_MOUSEMOVE: 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_MOUSEENTER: 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_MOUSELEAVE: { 97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pp::MouseInputEvent pp_mouse_event(event); 98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) protocol::MouseEvent mouse_event; 99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) mouse_event.set_x(pp_mouse_event.GetPosition().x()); 100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) mouse_event.set_y(pp_mouse_event.GetPosition().y()); 101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) input_stub_->InjectMouseEvent(mouse_event); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_WHEEL: { 106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pp::WheelInputEvent pp_wheel_event(event); 107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Don't handle scroll-by-page events, for now. 109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (pp_wheel_event.GetScrollByPage()) 110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 112558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Add this event to our accumulated sub-pixel deltas and clicks. 113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) pp::FloatPoint delta = pp_wheel_event.GetDelta(); 114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) wheel_delta_x_ += delta.x(); 115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) wheel_delta_y_ += delta.y(); 116558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch pp::FloatPoint ticks = pp_wheel_event.GetTicks(); 117558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch wheel_ticks_x_ += ticks.x(); 118558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch wheel_ticks_y_ += ticks.y(); 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 120558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // If there is at least a pixel's movement, emit an event. We don't 121558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // ever expect to accumulate one tick's worth of scrolling without 122558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // accumulating a pixel's worth at the same time, so this is safe. 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int delta_x = static_cast<int>(wheel_delta_x_); 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int delta_y = static_cast<int>(wheel_delta_y_); 125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (delta_x != 0 || delta_y != 0) { 126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) wheel_delta_x_ -= delta_x; 127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) wheel_delta_y_ -= delta_y; 128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) protocol::MouseEvent mouse_event; 129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) mouse_event.set_wheel_delta_x(delta_x); 130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) mouse_event.set_wheel_delta_y(delta_y); 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 132558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Always include the ticks in the event, even if insufficient pixel 133558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // scrolling has accumulated for a single tick. This informs hosts 134558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // that can't inject pixel-based scroll events that the client will 135558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // accumulate them into tick-based scrolling, which gives a better 136558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // overall experience than trying to do this host-side. 137558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch int ticks_x = static_cast<int>(wheel_ticks_x_); 138558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch int ticks_y = static_cast<int>(wheel_ticks_y_); 139558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch wheel_ticks_x_ -= ticks_x; 140558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch wheel_ticks_y_ -= ticks_y; 141558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch mouse_event.set_wheel_ticks_x(ticks_x); 142558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch mouse_event.set_wheel_ticks_y(ticks_y); 143558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) input_stub_->InjectMouseEvent(mouse_event); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PP_INPUTEVENT_TYPE_CHAR: 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Consume but ignore character input events. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(INFO) << "Unhandled input event: " << event.GetType(); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 163