Upstreaming browser/ui/uikit_ui_util from iOS.
[chromium-blink-merge.git] / remoting / client / plugin / pepper_mouse_locker.cc
blob0171763c23f7fe5fc3a3f3a97679679880818b1a
1 // Copyright 2014 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 "remoting/client/plugin/pepper_mouse_locker.h"
7 #include "base/logging.h"
8 #include "remoting/client/empty_cursor_filter.h"
9 #include "remoting/proto/control.pb.h"
11 namespace remoting {
13 PepperMouseLocker::PepperMouseLocker(
14 pp::Instance* instance,
15 const base::Callback<void(bool)>& enable_mouse_deltas,
16 protocol::CursorShapeStub* cursor_stub)
17 : pp::MouseLock(instance),
18 enable_mouse_deltas_(enable_mouse_deltas),
19 cursor_stub_(cursor_stub),
20 cursor_shape_(new protocol::CursorShapeInfo),
21 callback_factory_(this),
22 has_focus_(false),
23 mouse_lock_state_(MouseLockOff) {
24 *cursor_shape_ = EmptyCursorShape();
27 PepperMouseLocker::~PepperMouseLocker() {}
29 void PepperMouseLocker::DidChangeFocus(bool has_focus) {
30 has_focus_ = has_focus;
31 if (has_focus_)
32 RequestMouseLock();
35 void PepperMouseLocker::SetCursorShape(
36 const protocol::CursorShapeInfo& cursor_shape) {
37 *cursor_shape_ = cursor_shape;
38 if (IsCursorShapeEmpty(*cursor_shape_)) {
39 RequestMouseLock();
40 } else {
41 CancelMouseLock();
45 void PepperMouseLocker::MouseLockLost() {
46 DCHECK(mouse_lock_state_ == MouseLockOn ||
47 mouse_lock_state_ == MouseLockCancelling);
49 OnMouseLockOff();
52 void PepperMouseLocker::OnMouseLocked(int error) {
53 DCHECK(mouse_lock_state_ == MouseLockRequestPending ||
54 mouse_lock_state_ == MouseLockCancelling);
56 bool should_cancel = (mouse_lock_state_ == MouseLockCancelling);
58 // See if the operation succeeded.
59 if (error == PP_OK) {
60 mouse_lock_state_ = MouseLockOn;
61 enable_mouse_deltas_.Run(true);
62 } else {
63 OnMouseLockOff();
66 // Cancel as needed.
67 if (should_cancel)
68 CancelMouseLock();
71 void PepperMouseLocker::OnMouseLockOff() {
72 mouse_lock_state_ = MouseLockOff;
73 cursor_stub_->SetCursorShape(*cursor_shape_);
74 enable_mouse_deltas_.Run(false);
77 void PepperMouseLocker::RequestMouseLock() {
78 // Request mouse lock only if the plugin is focused, the host-supplied cursor
79 // is empty and no callback is pending.
80 if (!has_focus_)
81 return;
82 if (!IsCursorShapeEmpty(*cursor_shape_))
83 return;
84 if (mouse_lock_state_ != MouseLockOff)
85 return;
87 pp::CompletionCallback callback =
88 callback_factory_.NewCallback(&PepperMouseLocker::OnMouseLocked);
89 int result = pp::MouseLock::LockMouse(callback);
90 if (result != PP_OK_COMPLETIONPENDING) {
91 LOG(ERROR) << "Unexpected MouseLock result:" << result;
92 return;
94 mouse_lock_state_ = MouseLockRequestPending;
96 // Hide cursor to avoid it becoming a black square (see crbug.com/285809).
97 cursor_stub_->SetCursorShape(EmptyCursorShape());
100 void PepperMouseLocker::CancelMouseLock() {
101 switch (mouse_lock_state_) {
102 case MouseLockOff:
103 OnMouseLockOff();
104 break;
106 case MouseLockCancelling:
107 break;
109 case MouseLockRequestPending:
110 // The mouse lock request is pending. Delay UnlockMouse() call until
111 // the callback is called.
112 mouse_lock_state_ = MouseLockCancelling;
113 break;
115 case MouseLockOn:
116 pp::MouseLock::UnlockMouse();
118 // Note that mouse-lock has been cancelled. We will continue to receive
119 // locked events until MouseLockLost() is called back.
120 mouse_lock_state_ = MouseLockCancelling;
121 break;
123 default:
124 NOTREACHED();
128 } // namespace remoting