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 |