Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / ui / views / mouse_watcher.cc
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.
4
5 #include "ui/views/mouse_watcher.h"
6
7 #include "base/bind.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"
17
18 namespace views {
19
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;
23
24 class MouseWatcher::Observer : public ui::EventHandler {
25  public:
26   explicit Observer(MouseWatcher* mouse_watcher)
27       : mouse_watcher_(mouse_watcher),
28         event_monitor_(views::EventMonitor::Create(this)),
29         notify_listener_factory_(this) {
30   }
31
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);
38         break;
39       case ui::ET_MOUSE_EXITED:
40         HandleMouseEvent(MouseWatcherHost::MOUSE_EXIT);
41         break;
42       default:
43         break;
44     }
45   }
46
47  private:
48   MouseWatcherHost* host() const { return mouse_watcher_->host_.get(); }
49
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
56       // listener.
57       if (!notify_listener_factory_.HasWeakPtrs()) {
58         base::MessageLoop::current()->PostDelayedTask(
59             FROM_HERE,
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_);
65       }
66     } else {
67       // Mouse moved quickly out of the host and then into it again, so cancel
68       // the timer.
69       notify_listener_factory_.InvalidateWeakPtrs();
70     }
71   }
72
73   void NotifyListener() {
74     mouse_watcher_->NotifyListener();
75     // WARNING: we've been deleted.
76   }
77
78  private:
79   MouseWatcher* mouse_watcher_;
80   scoped_ptr<views::EventMonitor> event_monitor_;
81
82   // A factory that is used to construct a delayed callback to the listener.
83   base::WeakPtrFactory<Observer> notify_listener_factory_;
84
85   DISALLOW_COPY_AND_ASSIGN(Observer);
86 };
87
88 MouseWatcherListener::~MouseWatcherListener() {
89 }
90
91 MouseWatcherHost::~MouseWatcherHost() {
92 }
93
94 MouseWatcher::MouseWatcher(MouseWatcherHost* host,
95                            MouseWatcherListener* listener)
96     : host_(host),
97       listener_(listener),
98       notify_on_exit_time_(base::TimeDelta::FromMilliseconds(
99           kNotifyListenerTimeMs)) {
100 }
101
102 MouseWatcher::~MouseWatcher() {
103 }
104
105 void MouseWatcher::Start() {
106   if (!is_observing())
107     observer_.reset(new Observer(this));
108 }
109
110 void MouseWatcher::Stop() {
111   observer_.reset(NULL);
112 }
113
114 void MouseWatcher::NotifyListener() {
115   observer_.reset(NULL);
116   listener_->MouseMovedOutOfHost();
117 }
118
119 }  // namespace views