Chromium Code Reviews| Index: ui/views/mouse_watcher.cc |
| diff --git a/ui/views/mouse_watcher.cc b/ui/views/mouse_watcher.cc |
| index 5a2b4bd0ae813babf915cddcc79aeaf60a9f42e7..bee59848dbadee586b5aa330eaef8ea291a7e5b3 100644 |
| --- a/ui/views/mouse_watcher.cc |
| +++ b/ui/views/mouse_watcher.cc |
| @@ -13,12 +13,20 @@ |
| #include "ui/events/event_utils.h" |
| #include "ui/gfx/screen.h" |
| +#if defined(USE_AURA) |
| +#include "ui/aura/env.h" |
| +#include "ui/aura/window.h" |
| +#include "ui/events/event.h" |
| +#include "ui/events/event_handler.h" |
| +#endif |
| + |
| namespace views { |
| // Amount of time between when the mouse moves outside the Host's zone and when |
| // the listener is notified. |
| const int kNotifyListenerTimeMs = 300; |
| +#if defined(OS_WIN) && !defined(USE_AURA) |
|
sky
2013/11/05 18:52:56
I'm going with totally different ifdefs since hope
|
| class MouseWatcher::Observer : public base::MessageLoopForUI::Observer { |
| public: |
| explicit Observer(MouseWatcher* mouse_watcher) |
| @@ -32,7 +40,6 @@ class MouseWatcher::Observer : public base::MessageLoopForUI::Observer { |
| } |
| // MessageLoop::Observer implementation: |
| -#if defined(OS_WIN) |
| virtual base::EventStatus WillProcessEvent( |
| const base::NativeEvent& event) OVERRIDE { |
| return base::EVENT_CONTINUE; |
| @@ -60,37 +67,85 @@ class MouseWatcher::Observer : public base::MessageLoopForUI::Observer { |
| break; |
| } |
| } |
| -#elif defined(USE_AURA) |
| - virtual base::EventStatus WillProcessEvent( |
| - const base::NativeEvent& event) OVERRIDE { |
| - return base::EVENT_CONTINUE; |
| + |
| + private: |
| + MouseWatcherHost* host() const { return mouse_watcher_->host_.get(); } |
| + |
| + // Called from the message loop observer when a mouse movement has occurred. |
| + void HandleGlobalMouseMoveEvent(MouseWatcherHost::MouseEventType event_type) { |
| + bool contained = host()->Contains( |
| + // TODO(scottmg): Native is wrong http://crbug.com/133312 |
| + gfx::Screen::GetNativeScreen()->GetCursorScreenPoint(), |
| + event_type); |
| + if (!contained) { |
| + // Mouse moved outside the host's zone, start a timer to notify the |
| + // listener. |
| + if (!notify_listener_factory_.HasWeakPtrs()) { |
| + base::MessageLoop::current()->PostDelayedTask( |
| + FROM_HERE, |
| + base::Bind(&Observer::NotifyListener, |
| + notify_listener_factory_.GetWeakPtr()), |
| + event_type == MouseWatcherHost::MOUSE_MOVE |
| + ? base::TimeDelta::FromMilliseconds(kNotifyListenerTimeMs) |
| + : mouse_watcher_->notify_on_exit_time_); |
| + } |
| + } else { |
| + // Mouse moved quickly out of the host and then into it again, so cancel |
| + // the timer. |
| + notify_listener_factory_.InvalidateWeakPtrs(); |
| + } |
| } |
| - virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE { |
| - switch (ui::EventTypeFromNative(event)) { |
| + |
| + void NotifyListener() { |
| + mouse_watcher_->NotifyListener(); |
| + // WARNING: we've been deleted. |
| + } |
| + |
| + private: |
| + MouseWatcher* mouse_watcher_; |
| + |
| + // A factory that is used to construct a delayed callback to the listener. |
| + base::WeakPtrFactory<Observer> notify_listener_factory_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Observer); |
| +}; |
| +#else |
| +class MouseWatcher::Observer : public ui::EventHandler { |
| + public: |
| + explicit Observer(MouseWatcher* mouse_watcher) |
| + : mouse_watcher_(mouse_watcher), |
| + notify_listener_factory_(this) { |
| + aura::Env::GetInstance()->AddPreTargetHandler(this); |
| + } |
| + |
| + virtual ~Observer() { |
| + aura::Env::GetInstance()->RemovePreTargetHandler(this); |
| + } |
| + |
| + // ui::EventHandler implementation: |
| + virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE { |
| + switch (event->type()) { |
| 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(MouseWatcherHost::MOUSE_MOVE); |
| + HandleMouseEvent(MouseWatcherHost::MOUSE_MOVE); |
| break; |
| case ui::ET_MOUSE_EXITED: |
| - HandleGlobalMouseMoveEvent(MouseWatcherHost::MOUSE_EXIT); |
| + HandleMouseEvent(MouseWatcherHost::MOUSE_EXIT); |
| break; |
| default: |
| break; |
| } |
| } |
| -#endif |
| private: |
| MouseWatcherHost* host() const { return mouse_watcher_->host_.get(); } |
| - // Called from the message loop observer when a mouse movement has occurred. |
| - void HandleGlobalMouseMoveEvent(MouseWatcherHost::MouseEventType event_type) { |
| - bool contained = host()->Contains( |
| - // TODO(scottmg): Native is wrong http://crbug.com/133312 |
| - gfx::Screen::GetNativeScreen()->GetCursorScreenPoint(), |
| - event_type); |
| - if (!contained) { |
| + // Called when a mouse event we're interested is seen. |
| + void HandleMouseEvent(MouseWatcherHost::MouseEventType event_type) { |
| + // It's safe to use last_mouse_location() here as this function is invoked |
| + // during event dispatching. |
| + if (!host()->Contains(aura::Env::GetInstance()->last_mouse_location(), |
| + event_type)) { |
| // Mouse moved outside the host's zone, start a timer to notify the |
| // listener. |
| if (!notify_listener_factory_.HasWeakPtrs()) { |
| @@ -122,6 +177,7 @@ class MouseWatcher::Observer : public base::MessageLoopForUI::Observer { |
| DISALLOW_COPY_AND_ASSIGN(Observer); |
| }; |
| +#endif |
| MouseWatcherListener::~MouseWatcherListener() { |
| } |