Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ui / views / mouse_watcher.cc
blob00e6364e806da9fa9371c32fdc5567419bec2f54
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"
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"
18 namespace views {
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 {
25 public:
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);
38 break;
39 case ui::ET_MOUSE_EXITED:
40 HandleMouseEvent(MouseWatcherHost::MOUSE_EXIT);
41 break;
42 case ui::ET_MOUSE_PRESSED:
43 HandleMouseEvent(MouseWatcherHost::MOUSE_PRESS);
44 break;
45 default:
46 break;
50 private:
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) {
59 NotifyListener();
60 } else if (!notify_listener_factory_.HasWeakPtrs()) {
61 // Mouse moved outside the host's zone, start a timer to notify the
62 // listener.
63 base::MessageLoop::current()->PostDelayedTask(
64 FROM_HERE,
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_);
71 } else {
72 // Mouse moved quickly out of the host and then into it again, so cancel
73 // the timer.
74 notify_listener_factory_.InvalidateWeakPtrs();
78 void NotifyListener() {
79 mouse_watcher_->NotifyListener();
80 // WARNING: we've been deleted.
83 private:
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)
101 : host_(host),
102 listener_(listener),
103 notify_on_exit_time_(base::TimeDelta::FromMilliseconds(
104 kNotifyListenerTimeMs)) {
107 MouseWatcher::~MouseWatcher() {
110 void MouseWatcher::Start() {
111 if (!is_observing())
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();
124 } // namespace views