From 86b1dc18859817e039361c623e3b0e4074593367 Mon Sep 17 00:00:00 2001
From: "davemoore@chromium.org"
 <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>
Date: Mon, 6 Feb 2012 19:19:13 +0000
Subject: Refactored MouseWatcher to allow regions other than Views to be
 monitored.

BUG=None
TEST=None

Review URL: https://chromiumcodereview.appspot.com/9309110

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@120583 0039d316-1c4b-4281-b951-d872f2087c98
---
 ui/views/mouse_watcher.cc | 80 ++++++++++++++++-------------------------------
 1 file changed, 27 insertions(+), 53 deletions(-)

(limited to 'ui/views/mouse_watcher.cc')

diff --git a/ui/views/mouse_watcher.cc b/ui/views/mouse_watcher.cc
index 1115901..4b963d9 100644
--- a/ui/views/mouse_watcher.cc
+++ b/ui/views/mouse_watcher.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -11,12 +11,10 @@
 #include "base/message_loop.h"
 #include "ui/base/events.h"
 #include "ui/gfx/screen.h"
-#include "ui/views/view.h"
-#include "ui/views/widget/widget.h"
 
 namespace views {
 
-// Amount of time between when the mouse moves outside the view's zone and when
+// Amount of time between when the mouse moves outside the Host's zone and when
 // the listener is notified.
 const int kNotifyListenerTimeMs = 300;
 
@@ -41,7 +39,7 @@ class MouseWatcher::Observer : public MessageLoopForUI::Observer {
 
   virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE {
     // We spy on three different Windows messages here to see if the mouse has
-    // moved out of the bounds of the view. The messages are:
+    // moved out of the bounds of the current view. The messages are:
     //
     // WM_MOUSEMOVE:
     //   For when the mouse moves from the view into the rest of the browser UI,
@@ -53,11 +51,11 @@ class MouseWatcher::Observer : public MessageLoopForUI::Observer {
     //
     switch (event.message) {
       case WM_MOUSEMOVE:
-        HandleGlobalMouseMoveEvent(false);
+        HandleGlobalMouseMoveEvent(MouseWatcherHost::MOUSE_MOVE);
         break;
       case WM_MOUSELEAVE:
       case WM_NCMOUSELEAVE:
-        HandleGlobalMouseMoveEvent(true);
+        HandleGlobalMouseMoveEvent(MouseWatcherHost::MOUSE_EXIT);
         break;
     }
   }
@@ -66,11 +64,11 @@ class MouseWatcher::Observer : public MessageLoopForUI::Observer {
       base::wayland::WaylandEvent* event) OVERRIDE {
     switch (event->type) {
       case base::wayland::WAYLAND_MOTION:
-        HandleGlobalMouseMoveEvent(false);
+        HandleGlobalMouseMoveEvent(MouseWatcherHost::MOUSE_MOVE);
         break;
       case base::wayland::WAYLAND_POINTER_FOCUS:
         if (!event->pointer_focus.state)
-          HandleGlobalMouseMoveEvent(true);
+          HandleGlobalMouseMoveEvent(MouseWatcherHost::MOUSE_EXIT);
         break;
       default:
         break;
@@ -87,10 +85,10 @@ class MouseWatcher::Observer : public MessageLoopForUI::Observer {
       case ui::ET_MOUSE_MOVED:
       case ui::ET_MOUSE_DRAGGED:
         // DRAGGED is a special case of MOVED. See events_win.cc/events_x.cc.
-        HandleGlobalMouseMoveEvent(false);
+        HandleGlobalMouseMoveEvent(MouseWatcherHost::MOUSE_MOVE);
         break;
       case ui::ET_MOUSE_EXITED:
-        HandleGlobalMouseMoveEvent(true);
+        HandleGlobalMouseMoveEvent(MouseWatcherHost::MOUSE_EXIT);
         break;
       default:
         break;
@@ -103,10 +101,10 @@ class MouseWatcher::Observer : public MessageLoopForUI::Observer {
   virtual void DidProcessEvent(GdkEvent* event) OVERRIDE {
     switch (event->type) {
       case GDK_MOTION_NOTIFY:
-        HandleGlobalMouseMoveEvent(false);
+        HandleGlobalMouseMoveEvent(MOUSE_MOVE);
         break;
       case GDK_LEAVE_NOTIFY:
-        HandleGlobalMouseMoveEvent(true);
+        HandleGlobalMouseMoveEvent(MOUSE_EXIT);
         break;
       default:
         break;
@@ -115,51 +113,26 @@ class MouseWatcher::Observer : public MessageLoopForUI::Observer {
 #endif
 
  private:
-  View* view() const { return mouse_watcher_->host_; }
-
-  // Returns whether or not the cursor is currently in the view's "zone" which
-  // is defined as a slightly larger region than the view.
-  bool IsCursorInViewZone() {
-    gfx::Rect bounds = view()->GetLocalBounds();
-    gfx::Point view_topleft(bounds.origin());
-    View::ConvertPointToScreen(view(), &view_topleft);
-    bounds.set_origin(view_topleft);
-    bounds.SetRect(view_topleft.x() - mouse_watcher_->hot_zone_insets_.left(),
-                   view_topleft.y() - mouse_watcher_->hot_zone_insets_.top(),
-                   bounds.width() + mouse_watcher_->hot_zone_insets_.width(),
-                   bounds.height() + mouse_watcher_->hot_zone_insets_.height());
-
-    gfx::Point cursor_point = gfx::Screen::GetCursorScreenPoint();
-
-    return bounds.Contains(cursor_point.x(), cursor_point.y());
-  }
-
-  // Returns true if the mouse is over the view's window.
-  bool IsMouseOverWindow() {
-    Widget* widget = view()->GetWidget();
-    if (!widget)
-      return false;
-
-    return gfx::Screen::GetWindowAtCursorScreenPoint() ==
-        widget->GetNativeWindow();
-  }
+  MouseWatcherHost* host() const { return mouse_watcher_->host_.get(); }
 
   // Called from the message loop observer when a mouse movement has occurred.
-  void HandleGlobalMouseMoveEvent(bool check_window) {
-    bool in_view = IsCursorInViewZone();
-    if (!in_view || (check_window && !IsMouseOverWindow())) {
-      // Mouse moved outside the view's zone, start a timer to notify the
+  void HandleGlobalMouseMoveEvent(MouseWatcherHost::MouseEventType event_type) {
+    bool contained = host()->Contains(
+        gfx::Screen::GetCursorScreenPoint(), event_type);
+    if (!contained) {
+      // Mouse moved outside the host's zone, start a timer to notify the
       // listener.
       if (!notify_listener_factory_.HasWeakPtrs()) {
         MessageLoop::current()->PostDelayedTask(
             FROM_HERE,
             base::Bind(&Observer::NotifyListener,
                        notify_listener_factory_.GetWeakPtr()),
-            !in_view ? kNotifyListenerTimeMs :
-                       mouse_watcher_->notify_on_exit_time_ms_);
+            event_type ==
+                MouseWatcherHost::MOUSE_MOVE ? kNotifyListenerTimeMs :
+                    mouse_watcher_->notify_on_exit_time_ms_);
       }
     } else {
-      // Mouse moved quickly out of the view and then into it again, so cancel
+      // Mouse moved quickly out of the host and then into it again, so cancel
       // the timer.
       notify_listener_factory_.InvalidateWeakPtrs();
     }
@@ -182,12 +155,13 @@ class MouseWatcher::Observer : public MessageLoopForUI::Observer {
 MouseWatcherListener::~MouseWatcherListener() {
 }
 
-MouseWatcher::MouseWatcher(View* host,
-                           MouseWatcherListener* listener,
-                           const gfx::Insets& hot_zone_insets)
+MouseWatcherHost::~MouseWatcherHost() {
+}
+
+MouseWatcher::MouseWatcher(MouseWatcherHost* host,
+                           MouseWatcherListener* listener)
     : host_(host),
       listener_(listener),
-      hot_zone_insets_(hot_zone_insets),
       notify_on_exit_time_ms_(kNotifyListenerTimeMs) {
 }
 
@@ -205,7 +179,7 @@ void MouseWatcher::Stop() {
 
 void MouseWatcher::NotifyListener() {
   observer_.reset(NULL);
-  listener_->MouseMovedOutOfView();
+  listener_->MouseMovedOutOfHost();
 }
 
 }  // namespace views
-- 
cgit v1.1