1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/views/mouse_watcher.h"
8 #include "base/compiler_specific.h"
9 #include "base/event_types.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "ui/events/event.h"
13 #include "ui/events/event_constants.h"
14 #include "ui/events/event_handler.h"
15 #include "ui/events/event_utils.h"
16 #include "ui/views/event_monitor.h"
20 // Amount of time between when the mouse moves outside the Host's zone and when
21 // the listener is notified.
22 const int kNotifyListenerTimeMs
= 300;
24 class MouseWatcher::Observer
: public ui::EventHandler
{
26 explicit Observer(MouseWatcher
* mouse_watcher
)
27 : mouse_watcher_(mouse_watcher
),
28 event_monitor_(views::EventMonitor::Create(this)),
29 notify_listener_factory_(this) {
32 // ui::EventHandler implementation:
33 virtual void OnMouseEvent(ui::MouseEvent
* event
) override
{
34 switch (event
->type()) {
35 case ui::ET_MOUSE_MOVED
:
36 case ui::ET_MOUSE_DRAGGED
:
37 HandleMouseEvent(MouseWatcherHost::MOUSE_MOVE
);
39 case ui::ET_MOUSE_EXITED
:
40 HandleMouseEvent(MouseWatcherHost::MOUSE_EXIT
);
48 MouseWatcherHost
* host() const { return mouse_watcher_
->host_
.get(); }
50 // Called when a mouse event we're interested is seen.
51 void HandleMouseEvent(MouseWatcherHost::MouseEventType event_type
) {
52 // It's safe to use last_mouse_location() here as this function is invoked
53 // during event dispatching.
54 if (!host()->Contains(EventMonitor::GetLastMouseLocation(), event_type
)) {
55 // Mouse moved outside the host's zone, start a timer to notify the
57 if (!notify_listener_factory_
.HasWeakPtrs()) {
58 base::MessageLoop::current()->PostDelayedTask(
60 base::Bind(&Observer::NotifyListener
,
61 notify_listener_factory_
.GetWeakPtr()),
62 event_type
== MouseWatcherHost::MOUSE_MOVE
63 ? base::TimeDelta::FromMilliseconds(kNotifyListenerTimeMs
)
64 : mouse_watcher_
->notify_on_exit_time_
);
67 // Mouse moved quickly out of the host and then into it again, so cancel
69 notify_listener_factory_
.InvalidateWeakPtrs();
73 void NotifyListener() {
74 mouse_watcher_
->NotifyListener();
75 // WARNING: we've been deleted.
79 MouseWatcher
* mouse_watcher_
;
80 scoped_ptr
<views::EventMonitor
> event_monitor_
;
82 // A factory that is used to construct a delayed callback to the listener.
83 base::WeakPtrFactory
<Observer
> notify_listener_factory_
;
85 DISALLOW_COPY_AND_ASSIGN(Observer
);
88 MouseWatcherListener::~MouseWatcherListener() {
91 MouseWatcherHost::~MouseWatcherHost() {
94 MouseWatcher::MouseWatcher(MouseWatcherHost
* host
,
95 MouseWatcherListener
* listener
)
98 notify_on_exit_time_(base::TimeDelta::FromMilliseconds(
99 kNotifyListenerTimeMs
)) {
102 MouseWatcher::~MouseWatcher() {
105 void MouseWatcher::Start() {
107 observer_
.reset(new Observer(this));
110 void MouseWatcher::Stop() {
111 observer_
.reset(NULL
);
114 void MouseWatcher::NotifyListener() {
115 observer_
.reset(NULL
);
116 listener_
->MouseMovedOutOfHost();