Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: ui/views/mouse_watcher.cc

Issue 9309110: Refactored MouseWatcher to allow regions other than Views to (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Minor cleanup Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "ui/views/mouse_watcher.h" 5 #include "ui/views/mouse_watcher.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/compiler_specific.h" 8 #include "base/compiler_specific.h"
9 #include "base/event_types.h" 9 #include "base/event_types.h"
10 #include "base/memory/weak_ptr.h" 10 #include "base/memory/weak_ptr.h"
11 #include "base/message_loop.h" 11 #include "base/message_loop.h"
12 #include "ui/base/events.h" 12 #include "ui/base/events.h"
13 #include "ui/gfx/screen.h" 13 #include "ui/gfx/screen.h"
14 #include "ui/views/view.h"
15 #include "ui/views/widget/widget.h"
16 14
17 namespace views { 15 namespace views {
18 16
19 // Amount of time between when the mouse moves outside the view's zone and when 17 // Amount of time between when the mouse moves outside the Host's zone and when
20 // the listener is notified. 18 // the listener is notified.
21 const int kNotifyListenerTimeMs = 300; 19 const int kNotifyListenerTimeMs = 300;
22 20
23 class MouseWatcher::Observer : public MessageLoopForUI::Observer { 21 class MouseWatcher::Observer : public MessageLoopForUI::Observer {
24 public: 22 public:
25 explicit Observer(MouseWatcher* mouse_watcher) 23 explicit Observer(MouseWatcher* mouse_watcher)
26 : mouse_watcher_(mouse_watcher), 24 : mouse_watcher_(mouse_watcher),
27 ALLOW_THIS_IN_INITIALIZER_LIST(notify_listener_factory_(this)) { 25 ALLOW_THIS_IN_INITIALIZER_LIST(notify_listener_factory_(this)) {
28 MessageLoopForUI::current()->AddObserver(this); 26 MessageLoopForUI::current()->AddObserver(this);
29 } 27 }
30 28
31 ~Observer() { 29 ~Observer() {
32 MessageLoopForUI::current()->RemoveObserver(this); 30 MessageLoopForUI::current()->RemoveObserver(this);
33 } 31 }
34 32
35 // MessageLoop::Observer implementation: 33 // MessageLoop::Observer implementation:
36 #if defined(OS_WIN) 34 #if defined(OS_WIN)
37 virtual base::EventStatus WillProcessEvent( 35 virtual base::EventStatus WillProcessEvent(
38 const base::NativeEvent& event) OVERRIDE { 36 const base::NativeEvent& event) OVERRIDE {
39 return base::EVENT_CONTINUE; 37 return base::EVENT_CONTINUE;
40 } 38 }
41 39
42 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE { 40 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE {
43 // We spy on three different Windows messages here to see if the mouse has 41 // We spy on three different Windows messages here to see if the mouse has
44 // moved out of the bounds of the view. The messages are: 42 // moved out of the bounds of the current view. The messages are:
45 // 43 //
46 // WM_MOUSEMOVE: 44 // WM_MOUSEMOVE:
47 // For when the mouse moves from the view into the rest of the browser UI, 45 // For when the mouse moves from the view into the rest of the browser UI,
48 // i.e. within the bounds of the same windows HWND. 46 // i.e. within the bounds of the same windows HWND.
49 // WM_MOUSELEAVE: 47 // WM_MOUSELEAVE:
50 // For when the mouse moves out of the bounds of the view's HWND. 48 // For when the mouse moves out of the bounds of the view's HWND.
51 // WM_NCMOUSELEAVE: 49 // WM_NCMOUSELEAVE:
52 // For notification when the mouse leaves the _non-client_ area. 50 // For notification when the mouse leaves the _non-client_ area.
53 // 51 //
54 switch (event.message) { 52 switch (event.message) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 case GDK_LEAVE_NOTIFY: 106 case GDK_LEAVE_NOTIFY:
109 HandleGlobalMouseMoveEvent(true); 107 HandleGlobalMouseMoveEvent(true);
110 break; 108 break;
111 default: 109 default:
112 break; 110 break;
113 } 111 }
114 } 112 }
115 #endif 113 #endif
116 114
117 private: 115 private:
118 View* view() const { return mouse_watcher_->host_; } 116 MouseWatcherHost* host() const { return mouse_watcher_->host_.get(); }
119
120 // Returns whether or not the cursor is currently in the view's "zone" which
121 // is defined as a slightly larger region than the view.
122 bool IsCursorInViewZone() {
123 gfx::Rect bounds = view()->GetLocalBounds();
124 gfx::Point view_topleft(bounds.origin());
125 View::ConvertPointToScreen(view(), &view_topleft);
126 bounds.set_origin(view_topleft);
127 bounds.SetRect(view_topleft.x() - mouse_watcher_->hot_zone_insets_.left(),
128 view_topleft.y() - mouse_watcher_->hot_zone_insets_.top(),
129 bounds.width() + mouse_watcher_->hot_zone_insets_.width(),
130 bounds.height() + mouse_watcher_->hot_zone_insets_.height());
131
132 gfx::Point cursor_point = gfx::Screen::GetCursorScreenPoint();
133
134 return bounds.Contains(cursor_point.x(), cursor_point.y());
135 }
136
137 // Returns true if the mouse is over the view's window.
138 bool IsMouseOverWindow() {
139 Widget* widget = view()->GetWidget();
140 if (!widget)
141 return false;
142
143 return gfx::Screen::GetWindowAtCursorScreenPoint() ==
144 widget->GetNativeWindow();
145 }
146 117
147 // Called from the message loop observer when a mouse movement has occurred. 118 // Called from the message loop observer when a mouse movement has occurred.
148 void HandleGlobalMouseMoveEvent(bool check_window) { 119 void HandleGlobalMouseMoveEvent(bool check_window) {
sky 2012/02/06 16:03:34 Change this to take MouseWatcherHost::MouseEventTy
149 bool in_view = IsCursorInViewZone(); 120 MouseWatcherHost::MouseEventType type = check_window ?
150 if (!in_view || (check_window && !IsMouseOverWindow())) { 121 MouseWatcherHost::MOUSE_MOVE : MouseWatcherHost::MOUSE_EXITED;
151 // Mouse moved outside the view's zone, start a timer to notify the 122 bool contained = host()->Contains(
123 gfx::Screen::GetCursorScreenPoint(), type);
124 if (!contained) {
125 // Mouse moved outside the host's zone, start a timer to notify the
152 // listener. 126 // listener.
153 if (!notify_listener_factory_.HasWeakPtrs()) { 127 if (!notify_listener_factory_.HasWeakPtrs()) {
154 MessageLoop::current()->PostDelayedTask( 128 MessageLoop::current()->PostDelayedTask(
155 FROM_HERE, 129 FROM_HERE,
156 base::Bind(&Observer::NotifyListener, 130 base::Bind(&Observer::NotifyListener,
157 notify_listener_factory_.GetWeakPtr()), 131 notify_listener_factory_.GetWeakPtr()),
158 !in_view ? kNotifyListenerTimeMs : 132 !check_window ? kNotifyListenerTimeMs :
159 mouse_watcher_->notify_on_exit_time_ms_); 133 mouse_watcher_->notify_on_exit_time_ms_);
160 } 134 }
161 } else { 135 } else {
162 // Mouse moved quickly out of the view and then into it again, so cancel 136 // Mouse moved quickly out of the host and then into it again, so cancel
163 // the timer. 137 // the timer.
164 notify_listener_factory_.InvalidateWeakPtrs(); 138 notify_listener_factory_.InvalidateWeakPtrs();
165 } 139 }
166 } 140 }
167 141
168 void NotifyListener() { 142 void NotifyListener() {
169 mouse_watcher_->NotifyListener(); 143 mouse_watcher_->NotifyListener();
170 // WARNING: we've been deleted. 144 // WARNING: we've been deleted.
171 } 145 }
172 146
173 private: 147 private:
174 MouseWatcher* mouse_watcher_; 148 MouseWatcher* mouse_watcher_;
175 149
176 // A factory that is used to construct a delayed callback to the listener. 150 // A factory that is used to construct a delayed callback to the listener.
177 base::WeakPtrFactory<Observer> notify_listener_factory_; 151 base::WeakPtrFactory<Observer> notify_listener_factory_;
178 152
179 DISALLOW_COPY_AND_ASSIGN(Observer); 153 DISALLOW_COPY_AND_ASSIGN(Observer);
180 }; 154 };
181 155
182 MouseWatcherListener::~MouseWatcherListener() { 156 MouseWatcherListener::~MouseWatcherListener() {
183 } 157 }
184 158
185 MouseWatcher::MouseWatcher(View* host, 159 MouseWatcherHost::~MouseWatcherHost() {
186 MouseWatcherListener* listener, 160 }
187 const gfx::Insets& hot_zone_insets) 161
162 MouseWatcher::MouseWatcher(MouseWatcherHost* host,
163 MouseWatcherListener* listener)
188 : host_(host), 164 : host_(host),
189 listener_(listener), 165 listener_(listener),
190 hot_zone_insets_(hot_zone_insets),
191 notify_on_exit_time_ms_(kNotifyListenerTimeMs) { 166 notify_on_exit_time_ms_(kNotifyListenerTimeMs) {
192 } 167 }
193 168
194 MouseWatcher::~MouseWatcher() { 169 MouseWatcher::~MouseWatcher() {
195 } 170 }
196 171
197 void MouseWatcher::Start() { 172 void MouseWatcher::Start() {
198 if (!is_observing()) 173 if (!is_observing())
199 observer_.reset(new Observer(this)); 174 observer_.reset(new Observer(this));
200 } 175 }
201 176
202 void MouseWatcher::Stop() { 177 void MouseWatcher::Stop() {
203 observer_.reset(NULL); 178 observer_.reset(NULL);
204 } 179 }
205 180
206 void MouseWatcher::NotifyListener() { 181 void MouseWatcher::NotifyListener() {
207 observer_.reset(NULL); 182 observer_.reset(NULL);
208 listener_->MouseMovedOutOfView(); 183 listener_->MouseMovedOutOfHost();
209 } 184 }
210 185
211 } // namespace views 186 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698