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/mouse_lock_dispatcher.h" 6 7 #include "base/logging.h" 8 #include "third_party/WebKit/public/web/WebInputEvent.h" 9 10 namespace content { 11 MouseLockDispatcher()12MouseLockDispatcher::MouseLockDispatcher() : mouse_locked_(false), 13 pending_lock_request_(false), 14 pending_unlock_request_(false), 15 unlocked_by_target_(false), 16 target_(NULL) { 17 } 18 ~MouseLockDispatcher()19MouseLockDispatcher::~MouseLockDispatcher() { 20 } 21 LockMouse(LockTarget * target)22bool MouseLockDispatcher::LockMouse(LockTarget* target) { 23 if (MouseLockedOrPendingAction()) 24 return false; 25 26 pending_lock_request_ = true; 27 target_ = target; 28 29 SendLockMouseRequest(unlocked_by_target_); 30 unlocked_by_target_ = false; 31 return true; 32 } 33 UnlockMouse(LockTarget * target)34void MouseLockDispatcher::UnlockMouse(LockTarget* target) { 35 if (target && target == target_ && !pending_unlock_request_) { 36 pending_unlock_request_ = true; 37 38 // When a target application voluntarily unlocks the mouse we permit 39 // relocking the mouse silently and with no user gesture requirement. 40 // Check that the lock request is not currently pending and not yet 41 // accepted by the browser process before setting |unlocked_by_target_|. 42 if (!pending_lock_request_) 43 unlocked_by_target_ = true; 44 45 SendUnlockMouseRequest(); 46 } 47 } 48 OnLockTargetDestroyed(LockTarget * target)49void MouseLockDispatcher::OnLockTargetDestroyed(LockTarget* target) { 50 if (target == target_) { 51 UnlockMouse(target); 52 target_ = NULL; 53 } 54 } 55 IsMouseLockedTo(LockTarget * target)56bool MouseLockDispatcher::IsMouseLockedTo(LockTarget* target) { 57 return mouse_locked_ && target_ == target; 58 } 59 WillHandleMouseEvent(const blink::WebMouseEvent & event)60bool MouseLockDispatcher::WillHandleMouseEvent( 61 const blink::WebMouseEvent& event) { 62 if (mouse_locked_ && target_) 63 return target_->HandleMouseLockedInputEvent(event); 64 return false; 65 } 66 OnLockMouseACK(bool succeeded)67void MouseLockDispatcher::OnLockMouseACK(bool succeeded) { 68 DCHECK(!mouse_locked_ && pending_lock_request_); 69 70 mouse_locked_ = succeeded; 71 pending_lock_request_ = false; 72 if (pending_unlock_request_ && !succeeded) { 73 // We have sent an unlock request after the lock request. However, since 74 // the lock request has failed, the unlock request will be ignored by the 75 // browser side and there won't be any response to it. 76 pending_unlock_request_ = false; 77 } 78 79 LockTarget* last_target = target_; 80 if (!succeeded) 81 target_ = NULL; 82 83 // Callbacks made after all state modification to prevent reentrant errors 84 // such as OnLockMouseACK() synchronously calling LockMouse(). 85 86 if (last_target) 87 last_target->OnLockMouseACK(succeeded); 88 } 89 OnMouseLockLost()90void MouseLockDispatcher::OnMouseLockLost() { 91 DCHECK(mouse_locked_ && !pending_lock_request_); 92 93 mouse_locked_ = false; 94 pending_unlock_request_ = false; 95 96 LockTarget* last_target = target_; 97 target_ = NULL; 98 99 // Callbacks made after all state modification to prevent reentrant errors 100 // such as OnMouseLockLost() synchronously calling LockMouse(). 101 102 if (last_target) 103 last_target->OnMouseLockLost(); 104 } 105 106 } // namespace content 107