diff options
9 files changed, 118 insertions, 18 deletions
diff --git a/content/browser/renderer_host/render_view_host.cc b/content/browser/renderer_host/render_view_host.cc index ca7d244..441acb6 100644 --- a/content/browser/renderer_host/render_view_host.cc +++ b/content/browser/renderer_host/render_view_host.cc @@ -551,6 +551,11 @@ void RenderViewHost::LostCapture() { delegate_->LostCapture(); } +void RenderViewHost::LostMouseLock() { + RenderWidgetHost::LostMouseLock(); + delegate_->LostMouseLock(); +} + void RenderViewHost::SetInitialFocus(bool reverse) { Send(new ViewMsg_SetInitialFocus(routing_id(), reverse)); } @@ -1142,9 +1147,9 @@ void RenderViewHost::NotifyRendererResponsive() { delegate_->RendererResponsive(this); } -bool RenderViewHost::CanLockMouse() const { +void RenderViewHost::RequestToLockMouse() { // Only allow to lock the mouse when the current tab is in fullscreen mode. - return delegate_->IsFullscreenForCurrentTab(); + GotResponseToLockMouseRequest(delegate_->IsFullscreenForCurrentTab()); } bool RenderViewHost::IsFullscreen() const { @@ -1243,7 +1248,7 @@ void RenderViewHost::SetAltErrorPageURL(const GURL& url) { } void RenderViewHost::ExitFullscreen() { - UnlockMouseIfNecessary(); + RejectMouseLockOrUnlockIfNecessary(); Send(new ViewMsg_ExitFullscreen(routing_id())); } diff --git a/content/browser/renderer_host/render_view_host.h b/content/browser/renderer_host/render_view_host.h index 5fd540c..8947391 100644 --- a/content/browser/renderer_host/render_view_host.h +++ b/content/browser/renderer_host/render_view_host.h @@ -334,6 +334,7 @@ class CONTENT_EXPORT RenderViewHost : public RenderWidgetHost { virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; virtual void GotFocus() OVERRIDE; virtual void LostCapture() OVERRIDE; + virtual void LostMouseLock() OVERRIDE; virtual void ForwardMouseEvent( const WebKit::WebMouseEvent& mouse_event) OVERRIDE; virtual void OnMouseActivate() OVERRIDE; @@ -462,7 +463,7 @@ class CONTENT_EXPORT RenderViewHost : public RenderWidgetHost { virtual void OnUserGesture() OVERRIDE; virtual void NotifyRendererUnresponsive() OVERRIDE; virtual void NotifyRendererResponsive() OVERRIDE; - virtual bool CanLockMouse() const OVERRIDE; + virtual void RequestToLockMouse() OVERRIDE; virtual bool IsFullscreen() const OVERRIDE; virtual void OnMsgFocus() OVERRIDE; virtual void OnMsgBlur() OVERRIDE; diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h index 8b1126d..b9962b6 100644 --- a/content/browser/renderer_host/render_view_host_delegate.h +++ b/content/browser/renderer_host/render_view_host_delegate.h @@ -385,6 +385,14 @@ class CONTENT_EXPORT RenderViewHostDelegate : public IPC::Channel::Listener { const GURL& source_url, const std::string& name, const base::ListValue& args) {} + // Requests to lock the mouse. Once the request is approved or rejected, + // GotResponseToLockMouseRequest() will be called on the requesting render + // view host. + virtual void RequestToLockMouse() {} + + // Notification that the view has lost the mouse lock. + virtual void LostMouseLock() {} + protected: virtual ~RenderViewHostDelegate() {} }; diff --git a/content/browser/renderer_host/render_widget_host.cc b/content/browser/renderer_host/render_widget_host.cc index 43639bf..0ee9b0e 100644 --- a/content/browser/renderer_host/render_widget_host.cc +++ b/content/browser/renderer_host/render_widget_host.cc @@ -99,7 +99,8 @@ RenderWidgetHost::RenderWidgetHost(RenderProcessHost* process, text_direction_updated_(false), text_direction_(WebKit::WebTextDirectionLeftToRight), text_direction_canceled_(false), - suppress_next_char_events_(false) { + suppress_next_char_events_(false), + pending_mouse_lock_request_(false) { if (routing_id_ == MSG_ROUTING_NONE) routing_id_ = process_->GetNextRoutingID(); @@ -380,7 +381,11 @@ void RenderWidgetHost::Focus() { } void RenderWidgetHost::Blur() { - UnlockMouseIfNecessary(); + // If there is a pending mouse lock request, we don't want to reject it at + // this point. The user can switch focus back to this view and approve the + // request later. + if (IsMouseLocked()) + view_->UnlockMouse(); Send(new ViewMsg_SetFocus(routing_id_, false)); } @@ -394,7 +399,7 @@ void RenderWidgetHost::LostMouseLock() { } void RenderWidgetHost::ViewDestroyed() { - UnlockMouseIfNecessary(); + RejectMouseLockOrUnlockIfNecessary(); // TODO(evanm): tracking this may no longer be necessary; // eliminate this function if so. @@ -802,13 +807,20 @@ void RenderWidgetHost::ImeCancelComposition() { std::vector<WebKit::WebCompositionUnderline>(), 0, 0)); } -bool RenderWidgetHost::CanLockMouse() const { - return false; +void RenderWidgetHost::RequestToLockMouse() { + // Directly reject to lock the mouse. Subclass can override this method to + // decide whether to allow mouse lock or not. + GotResponseToLockMouseRequest(false); } -void RenderWidgetHost::UnlockMouseIfNecessary() { - if (IsMouseLocked()) +void RenderWidgetHost::RejectMouseLockOrUnlockIfNecessary() { + DCHECK(!pending_mouse_lock_request_ || !IsMouseLocked()); + if (pending_mouse_lock_request_) { + pending_mouse_lock_request_ = false; + Send(new ViewMsg_LockMouse_ACK(routing_id_, false)); + } else if (IsMouseLocked()) { view_->UnlockMouse(); + } } bool RenderWidgetHost::IsMouseLocked() const { @@ -1152,15 +1164,20 @@ void RenderWidgetHost::OnMsgDidActivateAcceleratedCompositing(bool activated) { } void RenderWidgetHost::OnMsgLockMouse() { - if (!CanLockMouse() || !view_ || !view_->HasFocus()|| !view_->LockMouse()) { + if (pending_mouse_lock_request_) { Send(new ViewMsg_LockMouse_ACK(routing_id_, false)); - } else { + return; + } else if (IsMouseLocked()) { Send(new ViewMsg_LockMouse_ACK(routing_id_, true)); + return; } + + pending_mouse_lock_request_ = true; + RequestToLockMouse(); } void RenderWidgetHost::OnMsgUnlockMouse() { - UnlockMouseIfNecessary(); + RejectMouseLockOrUnlockIfNecessary(); } #if defined(OS_POSIX) @@ -1391,3 +1408,24 @@ void RenderWidgetHost::SelectAll() { Send(new ViewMsg_SelectAll(routing_id())); UserMetrics::RecordAction(UserMetricsAction("SelectAll")); } +bool RenderWidgetHost::GotResponseToLockMouseRequest(bool allowed) { + if (!allowed) { + RejectMouseLockOrUnlockIfNecessary(); + return false; + } else { + if (!pending_mouse_lock_request_) { + // This is possible, e.g., the plugin sends us an unlock request before + // the user allows to lock to mouse. + return false; + } + + pending_mouse_lock_request_ = false; + if (!view_ || !view_->HasFocus()|| !view_->LockMouse()) { + Send(new ViewMsg_LockMouse_ACK(routing_id_, false)); + return false; + } else { + Send(new ViewMsg_LockMouse_ACK(routing_id_, true)); + return true; + } + } +} diff --git a/content/browser/renderer_host/render_widget_host.h b/content/browser/renderer_host/render_widget_host.h index 25cec88..9c82042 100644 --- a/content/browser/renderer_host/render_widget_host.h +++ b/content/browser/renderer_host/render_widget_host.h @@ -423,6 +423,11 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Channel::Listener, void Delete(); void SelectAll(); + // Called when the reponse to a pending mouse lock request has arrived. + // Returns true if |allowed| is true and the mouse has been successfully + // locked. + bool GotResponseToLockMouseRequest(bool allowed); + protected: // Internal implementation of the public Forward*Event() methods. void ForwardInputEvent(const WebKit::WebInputEvent& input_event, @@ -472,11 +477,12 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Channel::Listener, virtual void NotifyRendererResponsive() {} // RenderViewHost overrides this method to impose further restrictions on when - // to allow mouse lock. For now, it only allows to lock the mouse when the - // current tab is in fullscreen mode. - virtual bool CanLockMouse() const; + // to allow mouse lock. + // Once the request is approved or rejected, GotResponseToLockMouseRequest() + // will be called. + virtual void RequestToLockMouse(); - void UnlockMouseIfNecessary(); + void RejectMouseLockOrUnlockIfNecessary(); bool IsMouseLocked() const; // RenderViewHost overrides this method to report when in fullscreen mode. @@ -742,6 +748,8 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Channel::Listener, // The last scroll offset of the render widget. gfx::Point last_scroll_offset_; + bool pending_mouse_lock_request_; + DISALLOW_COPY_AND_ASSIGN(RenderWidgetHost); }; diff --git a/content/browser/tab_contents/tab_contents.cc b/content/browser/tab_contents/tab_contents.cc index 3f1a786..35951e4 100644 --- a/content/browser/tab_contents/tab_contents.cc +++ b/content/browser/tab_contents/tab_contents.cc @@ -503,6 +503,19 @@ bool TabContents::IsFullscreenForCurrentTab() const { return delegate_ ? delegate_->IsFullscreenForTab(this) : false; } +void TabContents::RequestToLockMouse() { + if (delegate_) { + delegate_->RequestToLockMouse(this); + } else { + GotResponseToLockMouseRequest(false); + } +} + +void TabContents::LostMouseLock() { + if (delegate_) + delegate_->LostMouseLock(); +} + void TabContents::UpdatePreferredSize(const gfx::Size& pref_size) { if (delegate_) delegate_->UpdatePreferredSize(this, pref_size); @@ -1983,3 +1996,9 @@ void TabContents::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) { RenderWidgetHostView* rwh_view = view()->CreateViewForWidget(rvh); rwh_view->SetSize(view()->GetContainerSize()); } + +bool TabContents::GotResponseToLockMouseRequest(bool allowed) { + return render_view_host() ? + render_view_host()->GotResponseToLockMouseRequest(allowed) : false; +} + diff --git a/content/browser/tab_contents/tab_contents.h b/content/browser/tab_contents/tab_contents.h index d2542fa..49b9c9f 100644 --- a/content/browser/tab_contents/tab_contents.h +++ b/content/browser/tab_contents/tab_contents.h @@ -470,6 +470,11 @@ class CONTENT_EXPORT TabContents : public PageNavigator, // the pending WebUI, the committed WebUI, or NULL. WebUI* GetWebUIForCurrentState(); + // Called when the reponse to a pending mouse lock request has arrived. + // Returns true if |allowed| is true and the mouse has been successfully + // locked. + bool GotResponseToLockMouseRequest(bool allowed); + protected: friend class TabContentsObserver; @@ -692,6 +697,8 @@ class CONTENT_EXPORT TabContents : public PageNavigator, virtual void ToggleFullscreenMode(bool enter_fullscreen) OVERRIDE; virtual bool IsFullscreenForCurrentTab() const OVERRIDE; virtual void UpdatePreferredSize(const gfx::Size& pref_size) OVERRIDE; + virtual void RequestToLockMouse() OVERRIDE; + virtual void LostMouseLock() OVERRIDE; // RenderViewHostManager::Delegate ------------------------------------------- diff --git a/content/browser/tab_contents/tab_contents_delegate.cc b/content/browser/tab_contents/tab_contents_delegate.cc index a9849e2..723775d 100644 --- a/content/browser/tab_contents/tab_contents_delegate.cc +++ b/content/browser/tab_contents/tab_contents_delegate.cc @@ -327,6 +327,9 @@ void TabContentsDelegate::UpdatePreferredSize(TabContents* source, const gfx::Size& pref_size) { } +void TabContentsDelegate::RequestToLockMouse(TabContents* tab) { +} + TabContentsDelegate::~TabContentsDelegate() { while (!attached_contents_.empty()) { TabContents* tab_contents = *attached_contents_.begin(); @@ -344,3 +347,6 @@ void TabContentsDelegate::Detach(TabContents* tab_contents) { DCHECK(attached_contents_.find(tab_contents) != attached_contents_.end()); attached_contents_.erase(tab_contents); } + +void TabContentsDelegate::LostMouseLock() { +} diff --git a/content/browser/tab_contents/tab_contents_delegate.h b/content/browser/tab_contents/tab_contents_delegate.h index c863922..43ddf6a 100644 --- a/content/browser/tab_contents/tab_contents_delegate.h +++ b/content/browser/tab_contents/tab_contents_delegate.h @@ -348,6 +348,14 @@ class CONTENT_EXPORT TabContentsDelegate { virtual void UpdatePreferredSize(TabContents* source, const gfx::Size& pref_size); + // Requests to lock the mouse. Once the request is approved or rejected, + // GotResponseToLockMouseRequest() will be called on the requesting tab + // contents. + virtual void RequestToLockMouse(TabContents* tab); + + // Notification that the page has lost the mouse lock. + virtual void LostMouseLock(); + protected: virtual ~TabContentsDelegate(); |