Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "views/mouse_watcher.h" | 5 #include "views/mouse_watcher.h" |
| 6 | 6 |
| 7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/task.h" | 9 #include "base/task.h" |
| 10 #include "views/screen.h" | 10 #include "views/screen.h" |
| 11 #include "views/view.h" | 11 #include "views/view.h" |
| 12 #include "views/window/window.h" | |
| 12 | 13 |
| 13 namespace views { | 14 namespace views { |
| 14 | 15 |
| 15 // Amount of time between when the mouse moves outside the view's zone and when | 16 // Amount of time between when the mouse moves outside the view's zone and when |
| 16 // the listener is notified. | 17 // the listener is notified. |
| 17 static const int kNotifyListenerTimeMs = 300; | 18 static const int kNotifyListenerTimeMs = 300; |
| 18 | 19 |
| 19 class MouseWatcher::Observer : public MessageLoopForUI::Observer { | 20 class MouseWatcher::Observer : public MessageLoopForUI::Observer { |
| 20 public: | 21 public: |
| 21 explicit Observer(MouseWatcher* mouse_watcher) | 22 explicit Observer(MouseWatcher* mouse_watcher) |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 40 // WM_MOUSEMOVE: | 41 // WM_MOUSEMOVE: |
| 41 // For when the mouse moves from the view into the rest of the browser UI, | 42 // For when the mouse moves from the view into the rest of the browser UI, |
| 42 // i.e. within the bounds of the same windows HWND. | 43 // i.e. within the bounds of the same windows HWND. |
| 43 // WM_MOUSELEAVE: | 44 // WM_MOUSELEAVE: |
| 44 // For when the mouse moves out of the bounds of the view's HWND. | 45 // For when the mouse moves out of the bounds of the view's HWND. |
| 45 // WM_NCMOUSELEAVE: | 46 // WM_NCMOUSELEAVE: |
| 46 // For notification when the mouse leaves the _non-client_ area. | 47 // For notification when the mouse leaves the _non-client_ area. |
| 47 // | 48 // |
| 48 switch (msg.message) { | 49 switch (msg.message) { |
| 49 case WM_MOUSEMOVE: | 50 case WM_MOUSEMOVE: |
| 51 HandleGlobalMouseMoveEvent(false); | |
| 52 break; | |
| 50 case WM_MOUSELEAVE: | 53 case WM_MOUSELEAVE: |
| 51 case WM_NCMOUSELEAVE: | 54 case WM_NCMOUSELEAVE: |
| 52 HandleGlobalMouseMoveEvent(); | 55 HandleGlobalMouseMoveEvent(true); |
| 53 break; | 56 break; |
| 54 } | 57 } |
| 55 } | 58 } |
| 56 #else | 59 #else |
| 57 void WillProcessEvent(GdkEvent* event) { | 60 void WillProcessEvent(GdkEvent* event) { |
| 58 } | 61 } |
| 59 | 62 |
| 60 void DidProcessEvent(GdkEvent* event) { | 63 void DidProcessEvent(GdkEvent* event) { |
| 61 switch (event->type) { | 64 switch (event->type) { |
| 62 case GDK_MOTION_NOTIFY: | 65 case GDK_MOTION_NOTIFY: |
| 66 HandleGlobalMouseMoveEvent(false); | |
| 67 break; | |
| 63 case GDK_LEAVE_NOTIFY: | 68 case GDK_LEAVE_NOTIFY: |
| 64 HandleGlobalMouseMoveEvent(); | 69 HandleGlobalMouseMoveEvent(true); |
| 65 break; | 70 break; |
| 66 default: | 71 default: |
| 67 break; | 72 break; |
| 68 } | 73 } |
| 69 } | 74 } |
| 70 #endif | 75 #endif |
| 71 | 76 |
| 72 private: | 77 private: |
| 73 views::View* view() { return mouse_watcher_->host_; } | 78 View* view() { return mouse_watcher_->host_; } |
|
Jay Civelli
2010/08/26 16:10:32
Make it const.
| |
| 74 | 79 |
| 75 // Returns whether or not the cursor is currently in the view's "zone" which | 80 // Returns whether or not the cursor is currently in the view's "zone" which |
| 76 // is defined as a slightly larger region than the view. | 81 // is defined as a slightly larger region than the view. |
| 77 bool IsCursorInViewZone() { | 82 bool IsCursorInViewZone() { |
| 78 gfx::Rect bounds = view()->GetLocalBounds(true); | 83 gfx::Rect bounds = view()->GetLocalBounds(true); |
| 79 gfx::Point view_topleft(bounds.origin()); | 84 gfx::Point view_topleft(bounds.origin()); |
| 80 views::View::ConvertPointToScreen(view(), &view_topleft); | 85 View::ConvertPointToScreen(view(), &view_topleft); |
| 81 bounds.set_origin(view_topleft); | 86 bounds.set_origin(view_topleft); |
| 82 bounds.SetRect(view_topleft.x() - mouse_watcher_->hot_zone_insets_.left(), | 87 bounds.SetRect(view_topleft.x() - mouse_watcher_->hot_zone_insets_.left(), |
| 83 view_topleft.y() - mouse_watcher_->hot_zone_insets_.top(), | 88 view_topleft.y() - mouse_watcher_->hot_zone_insets_.top(), |
| 84 bounds.width() + mouse_watcher_->hot_zone_insets_.width(), | 89 bounds.width() + mouse_watcher_->hot_zone_insets_.width(), |
| 85 bounds.height() + mouse_watcher_->hot_zone_insets_.height()); | 90 bounds.height() + mouse_watcher_->hot_zone_insets_.height()); |
| 86 | 91 |
| 87 gfx::Point cursor_point = views::Screen::GetCursorScreenPoint(); | 92 gfx::Point cursor_point = Screen::GetCursorScreenPoint(); |
| 88 | 93 |
| 89 return bounds.Contains(cursor_point.x(), cursor_point.y()); | 94 return bounds.Contains(cursor_point.x(), cursor_point.y()); |
| 90 } | 95 } |
| 91 | 96 |
| 97 // Returns true if the mouse is over the view's window. | |
| 98 bool IsMouseOverWindow() { | |
| 99 return Screen::GetWindowAtCursorScreenPoint() == | |
| 100 view()->GetWindow()->GetNativeWindow(); | |
| 101 } | |
| 102 | |
| 92 // Called from the message loop observer when a mouse movement has occurred. | 103 // Called from the message loop observer when a mouse movement has occurred. |
| 93 void HandleGlobalMouseMoveEvent() { | 104 void HandleGlobalMouseMoveEvent(bool check_window) { |
| 94 if (!IsCursorInViewZone()) { | 105 bool in_view = IsCursorInViewZone(); |
| 106 if (!in_view || (check_window && !IsMouseOverWindow())) { | |
| 95 // Mouse moved outside the view's zone, start a timer to notify the | 107 // Mouse moved outside the view's zone, start a timer to notify the |
| 96 // listener. | 108 // listener. |
| 97 if (notify_listener_factory_.empty()) { | 109 if (notify_listener_factory_.empty()) { |
| 98 MessageLoop::current()->PostDelayedTask( | 110 MessageLoop::current()->PostDelayedTask( |
| 99 FROM_HERE, | 111 FROM_HERE, |
| 100 notify_listener_factory_.NewRunnableMethod( | 112 notify_listener_factory_.NewRunnableMethod( |
| 101 &Observer::NotifyListener), | 113 &Observer::NotifyListener), |
| 102 kNotifyListenerTimeMs); | 114 !in_view ? kNotifyListenerTimeMs : |
| 115 mouse_watcher_->notify_on_exit_time_ms_); | |
| 103 } | 116 } |
| 104 } else { | 117 } else { |
| 105 // Mouse moved quickly out of the view and then into it again, so cancel | 118 // Mouse moved quickly out of the view and then into it again, so cancel |
| 106 // the timer. | 119 // the timer. |
| 107 notify_listener_factory_.RevokeAll(); | 120 notify_listener_factory_.RevokeAll(); |
| 108 } | 121 } |
| 109 } | 122 } |
| 110 | 123 |
| 111 void NotifyListener() { | 124 void NotifyListener() { |
| 112 mouse_watcher_->NotifyListener(); | 125 mouse_watcher_->NotifyListener(); |
| 113 // WARNING: we've been deleted. | 126 // WARNING: we've been deleted. |
| 114 } | 127 } |
| 115 | 128 |
| 116 private: | 129 private: |
| 117 MouseWatcher* mouse_watcher_; | 130 MouseWatcher* mouse_watcher_; |
| 118 | 131 |
| 119 // A factory that is used to construct a delayed callback to the listener. | 132 // A factory that is used to construct a delayed callback to the listener. |
| 120 ScopedRunnableMethodFactory<Observer> notify_listener_factory_; | 133 ScopedRunnableMethodFactory<Observer> notify_listener_factory_; |
| 121 | 134 |
| 122 DISALLOW_COPY_AND_ASSIGN(Observer); | 135 DISALLOW_COPY_AND_ASSIGN(Observer); |
| 123 }; | 136 }; |
| 124 | 137 |
| 125 MouseWatcherListener::~MouseWatcherListener() { | 138 MouseWatcherListener::~MouseWatcherListener() { |
| 126 } | 139 } |
| 127 | 140 |
| 128 MouseWatcher::MouseWatcher(views::View* host, | 141 MouseWatcher::MouseWatcher(View* host, |
| 129 MouseWatcherListener* listener, | 142 MouseWatcherListener* listener, |
| 130 const gfx::Insets& hot_zone_insets) | 143 const gfx::Insets& hot_zone_insets) |
| 131 : host_(host), | 144 : host_(host), |
| 132 listener_(listener), | 145 listener_(listener), |
| 133 hot_zone_insets_(hot_zone_insets) { | 146 hot_zone_insets_(hot_zone_insets), |
| 147 notify_on_exit_time_ms_(kNotifyListenerTimeMs) { | |
| 134 } | 148 } |
| 135 | 149 |
| 136 MouseWatcher::~MouseWatcher() { | 150 MouseWatcher::~MouseWatcher() { |
| 137 } | 151 } |
| 138 | 152 |
| 139 void MouseWatcher::Start() { | 153 void MouseWatcher::Start() { |
| 140 if (!is_observing()) | 154 if (!is_observing()) |
| 141 observer_.reset(new Observer(this)); | 155 observer_.reset(new Observer(this)); |
| 142 } | 156 } |
| 143 | 157 |
| 144 void MouseWatcher::Stop() { | 158 void MouseWatcher::Stop() { |
| 145 observer_.reset(NULL); | 159 observer_.reset(NULL); |
| 146 } | 160 } |
| 147 | 161 |
| 148 void MouseWatcher::NotifyListener() { | 162 void MouseWatcher::NotifyListener() { |
| 149 observer_.reset(NULL); | 163 observer_.reset(NULL); |
| 150 listener_->MouseMovedOutOfView(); | 164 listener_->MouseMovedOutOfView(); |
| 151 } | 165 } |
| 152 | 166 |
| 153 } // namespace views | 167 } // namespace views |
| OLD | NEW |