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_(EventMonitor::CreateApplicationMonitor(this)),
29 notify_listener_factory_(this) {
32 // ui::EventHandler implementation:
33 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
);
42 case ui::ET_MOUSE_PRESSED
:
43 HandleMouseEvent(MouseWatcherHost::MOUSE_PRESS
);
51 MouseWatcherHost
* host() const { return mouse_watcher_
->host_
.get(); }
53 // Called when a mouse event we're interested is seen.
54 void HandleMouseEvent(MouseWatcherHost::MouseEventType event_type
) {
55 // It's safe to use last_mouse_location() here as this function is invoked
56 // during event dispatching.
57 if (!host()->Contains(EventMonitor::GetLastMouseLocation(), event_type
)) {
58 if (event_type
== MouseWatcherHost::MOUSE_PRESS
) {
60 } else if (!notify_listener_factory_
.HasWeakPtrs()) {
61 // Mouse moved outside the host's zone, start a timer to notify the
63 base::MessageLoop::current()->PostDelayedTask(
65 base::Bind(&Observer::NotifyListener
,
66 notify_listener_factory_
.GetWeakPtr()),
67 event_type
== MouseWatcherHost::MOUSE_MOVE
68 ? base::TimeDelta::FromMilliseconds(kNotifyListenerTimeMs
)
69 : mouse_watcher_
->notify_on_exit_time_
);
72 // Mouse moved quickly out of the host and then into it again, so cancel
74 notify_listener_factory_
.InvalidateWeakPtrs();
78 void NotifyListener() {
79 mouse_watcher_
->NotifyListener();
80 // WARNING: we've been deleted.
84 MouseWatcher
* mouse_watcher_
;
85 scoped_ptr
<views::EventMonitor
> event_monitor_
;
87 // A factory that is used to construct a delayed callback to the listener.
88 base::WeakPtrFactory
<Observer
> notify_listener_factory_
;
90 DISALLOW_COPY_AND_ASSIGN(Observer
);
93 MouseWatcherListener::~MouseWatcherListener() {
96 MouseWatcherHost::~MouseWatcherHost() {
99 MouseWatcher::MouseWatcher(MouseWatcherHost
* host
,
100 MouseWatcherListener
* listener
)
103 notify_on_exit_time_(base::TimeDelta::FromMilliseconds(
104 kNotifyListenerTimeMs
)) {
107 MouseWatcher::~MouseWatcher() {
110 void MouseWatcher::Start() {
112 observer_
.reset(new Observer(this));
115 void MouseWatcher::Stop() {
116 observer_
.reset(NULL
);
119 void MouseWatcher::NotifyListener() {
120 observer_
.reset(NULL
);
121 listener_
->MouseMovedOutOfHost();