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"
858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ppapi/cpp/image_data.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/input_event.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/module_impl.h"
1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ppapi/cpp/mouse_cursor.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/point.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ppapi/cpp/var.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/proto/event.pb.h"
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/events/keycodes/dom4/keycode_converter.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)PepperInputHandler::PepperInputHandler(
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    pp::Instance* instance)
2158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    : pp::MouseLock(instance),
2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      instance_(instance),
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      input_stub_(NULL),
2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      callback_factory_(this),
2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      has_focus_(false),
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      send_mouse_input_when_unfocused_(false),
2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      mouse_lock_state_(MouseLockDisallowed),
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wheel_delta_x_(0),
29558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      wheel_delta_y_(0),
30558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      wheel_ticks_x_(0),
31558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      wheel_ticks_y_(0) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PepperInputHandler::~PepperInputHandler() {}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper function to get the USB key code using the Dev InputEvent interface.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32_t GetUsbKeyCode(pp::KeyboardInputEvent pp_key_event) {
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Get the DOM3 |code| as a string.
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string codestr = pp_key_event.GetCode().AsString();
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Convert the |code| string into a USB keycode.
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return ui::KeycodeConverter::CodeToUsbKeycode(codestr.c_str());
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PepperInputHandler::HandleInputEvent(const pp::InputEvent& event) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (event.GetType()) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_INPUTEVENT_TYPE_CONTEXTMENU: {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We need to return true here or else we'll get a local (plugin) context
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // menu instead of the mouseup event for the right click.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_INPUTEVENT_TYPE_KEYDOWN:
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_INPUTEVENT_TYPE_KEYUP: {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::KeyboardInputEvent pp_key_event(event);
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      uint32_t modifiers = event.GetModifiers();
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      uint32_t lock_states = 0;
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (modifiers & PP_INPUTEVENT_MODIFIER_CAPSLOCKKEY)
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        lock_states |= protocol::KeyEvent::LOCK_STATES_CAPSLOCK;
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (modifiers & PP_INPUTEVENT_MODIFIER_NUMLOCKKEY)
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        lock_states |= protocol::KeyEvent::LOCK_STATES_NUMLOCK;
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      protocol::KeyEvent key_event;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key_event.set_usb_keycode(GetUsbKeyCode(pp_key_event));
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key_event.set_pressed(event.GetType() == PP_INPUTEVENT_TYPE_KEYDOWN);
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      key_event.set_lock_states(lock_states);
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (input_stub_)
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        input_stub_->InjectKeyEvent(key_event);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_INPUTEVENT_TYPE_MOUSEDOWN:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_INPUTEVENT_TYPE_MOUSEUP: {
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (!has_focus_ && !send_mouse_input_when_unfocused_)
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        return false;
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::MouseInputEvent pp_mouse_event(event);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      protocol::MouseEvent mouse_event;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (pp_mouse_event.GetButton()) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case PP_INPUTEVENT_MOUSEBUTTON_LEFT:
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          mouse_event.set_button(protocol::MouseEvent::BUTTON_LEFT);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case PP_INPUTEVENT_MOUSEBUTTON_MIDDLE:
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          mouse_event.set_button(protocol::MouseEvent::BUTTON_MIDDLE);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case PP_INPUTEVENT_MOUSEBUTTON_RIGHT:
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          mouse_event.set_button(protocol::MouseEvent::BUTTON_RIGHT);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case PP_INPUTEVENT_MOUSEBUTTON_NONE:
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (mouse_event.has_button()) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bool is_down = (event.GetType() == PP_INPUTEVENT_TYPE_MOUSEDOWN);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mouse_event.set_button_down(is_down);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mouse_event.set_x(pp_mouse_event.GetPosition().x());
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mouse_event.set_y(pp_mouse_event.GetPosition().y());
10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        // Add relative movement if the mouse is locked.
10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        if (mouse_lock_state_ == MouseLockOn) {
10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          pp::Point delta = pp_mouse_event.GetMovement();
10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          mouse_event.set_delta_x(delta.x());
10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          mouse_event.set_delta_y(delta.y());
10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        }
10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (input_stub_)
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          input_stub_->InjectMouseEvent(mouse_event);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_INPUTEVENT_TYPE_MOUSEMOVE:
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_INPUTEVENT_TYPE_MOUSEENTER:
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_INPUTEVENT_TYPE_MOUSELEAVE: {
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (!has_focus_ && !send_mouse_input_when_unfocused_)
118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        return false;
119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pp::MouseInputEvent pp_mouse_event(event);
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      protocol::MouseEvent mouse_event;
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      mouse_event.set_x(pp_mouse_event.GetPosition().x());
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      mouse_event.set_y(pp_mouse_event.GetPosition().y());
12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // Add relative movement if the mouse is locked.
12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (mouse_lock_state_ == MouseLockOn) {
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        pp::Point delta = pp_mouse_event.GetMovement();
12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        mouse_event.set_delta_x(delta.x());
12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        mouse_event.set_delta_y(delta.y());
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      }
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (input_stub_)
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        input_stub_->InjectMouseEvent(mouse_event);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_INPUTEVENT_TYPE_WHEEL: {
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (!has_focus_ && !send_mouse_input_when_unfocused_)
139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        return false;
140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pp::WheelInputEvent pp_wheel_event(event);
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Don't handle scroll-by-page events, for now.
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (pp_wheel_event.GetScrollByPage())
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return false;
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
147558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      // Add this event to our accumulated sub-pixel deltas and clicks.
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pp::FloatPoint delta = pp_wheel_event.GetDelta();
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      wheel_delta_x_ += delta.x();
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      wheel_delta_y_ += delta.y();
151558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      pp::FloatPoint ticks = pp_wheel_event.GetTicks();
152558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      wheel_ticks_x_ += ticks.x();
153558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      wheel_ticks_y_ += ticks.y();
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
155558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      // If there is at least a pixel's movement, emit an event. We don't
156558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      // ever expect to accumulate one tick's worth of scrolling without
157558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      // accumulating a pixel's worth at the same time, so this is safe.
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      int delta_x = static_cast<int>(wheel_delta_x_);
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      int delta_y = static_cast<int>(wheel_delta_y_);
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (delta_x != 0 || delta_y != 0) {
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        wheel_delta_x_ -= delta_x;
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        wheel_delta_y_ -= delta_y;
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        protocol::MouseEvent mouse_event;
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        mouse_event.set_wheel_delta_x(delta_x);
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        mouse_event.set_wheel_delta_y(delta_y);
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
167558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        // Always include the ticks in the event, even if insufficient pixel
168558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        // scrolling has accumulated for a single tick. This informs hosts
169558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        // that can't inject pixel-based scroll events that the client will
170558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        // accumulate them into tick-based scrolling, which gives a better
171558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        // overall experience than trying to do this host-side.
172558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        int ticks_x = static_cast<int>(wheel_ticks_x_);
173558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        int ticks_y = static_cast<int>(wheel_ticks_y_);
174558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        wheel_ticks_x_ -= ticks_x;
175558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        wheel_ticks_y_ -= ticks_y;
176558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        mouse_event.set_wheel_ticks_x(ticks_x);
177558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        mouse_event.set_wheel_ticks_y(ticks_y);
178558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (input_stub_)
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          input_stub_->InjectMouseEvent(mouse_event);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_INPUTEVENT_TYPE_CHAR:
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Consume but ignore character input events.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default: {
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      VLOG(0) << "Unhandled input event: " << event.GetType();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PepperInputHandler::AllowMouseLock() {
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK_EQ(mouse_lock_state_, MouseLockDisallowed);
20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  mouse_lock_state_ = MouseLockOff;
20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PepperInputHandler::DidChangeFocus(bool has_focus) {
20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  has_focus_ = has_focus;
20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (has_focus_)
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    RequestMouseLock();
20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PepperInputHandler::SetMouseCursor(scoped_ptr<pp::ImageData> image,
21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                        const pp::Point& hotspot) {
21158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  cursor_image_ = image.Pass();
21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  cursor_hotspot_ = hotspot;
21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (mouse_lock_state_ != MouseLockDisallowed && !cursor_image_) {
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    RequestMouseLock();
21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else {
21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    CancelMouseLock();
21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PepperInputHandler::MouseLockLost() {
22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(mouse_lock_state_ == MouseLockOn ||
22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         mouse_lock_state_ == MouseLockCancelling);
22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  mouse_lock_state_ = MouseLockOff;
22658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  UpdateMouseCursor();
22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PepperInputHandler::RequestMouseLock() {
23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Request mouse lock only if the plugin is focused, the host-supplied cursor
23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // is empty and no callback is pending.
23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (has_focus_ && !cursor_image_ && mouse_lock_state_ == MouseLockOff) {
23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    pp::CompletionCallback callback =
23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        callback_factory_.NewCallback(&PepperInputHandler::OnMouseLocked);
23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    int result = pp::MouseLock::LockMouse(callback);
23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DCHECK_EQ(result, PP_OK_COMPLETIONPENDING);
23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Hide cursor to avoid it becoming a black square (see crbug.com/285809).
23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    pp::MouseCursor::SetCursor(instance_, PP_MOUSECURSOR_TYPE_NONE);
24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
24158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    mouse_lock_state_ = MouseLockRequestPending;
24258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
24358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PepperInputHandler::CancelMouseLock() {
24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  switch (mouse_lock_state_) {
24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case MouseLockDisallowed:
24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case MouseLockOff:
24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      UpdateMouseCursor();
25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      break;
25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
25258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case MouseLockCancelling:
25358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      break;
25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case MouseLockRequestPending:
25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // The mouse lock request is pending. Delay UnlockMouse() call until
25758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // the callback is called.
25858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      mouse_lock_state_ = MouseLockCancelling;
25958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      break;
26058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
26158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case MouseLockOn:
26258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      pp::MouseLock::UnlockMouse();
26358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // Note that mouse-lock has been cancelled. We will continue to receive
26558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // locked events until MouseLockLost() is called back.
26658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      mouse_lock_state_ = MouseLockCancelling;
26758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      break;
26858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
26958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    default:
27058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      NOTREACHED();
27158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
27258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
27358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
27458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PepperInputHandler::UpdateMouseCursor() {
27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(mouse_lock_state_ == MouseLockDisallowed ||
27658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         mouse_lock_state_ == MouseLockOff);
27758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
27858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (cursor_image_) {
27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    pp::MouseCursor::SetCursor(instance_, PP_MOUSECURSOR_TYPE_CUSTOM,
28058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                               *cursor_image_,
28158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                               cursor_hotspot_);
28258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else {
28358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // If there is no cursor shape stored, either because the host never
28458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // supplied one, or we were previously in mouse-lock mode, then use
28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // a standard arrow pointer.
28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    pp::MouseCursor::SetCursor(instance_, PP_MOUSECURSOR_TYPE_POINTER);
28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PepperInputHandler::OnMouseLocked(int error) {
29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(mouse_lock_state_ == MouseLockRequestPending ||
29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         mouse_lock_state_ == MouseLockCancelling);
29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool should_cancel = (mouse_lock_state_ == MouseLockCancelling);
29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // See if the operation succeeded.
29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (error == PP_OK) {
29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    mouse_lock_state_ = MouseLockOn;
29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else {
30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    mouse_lock_state_ = MouseLockOff;
30158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    UpdateMouseCursor();
30258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
30458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Cancel as needed.
30558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (should_cancel)
30658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    CancelMouseLock();
30758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
30858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace remoting
310