OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/views/mus/pointer_watcher_event_router.h" | 5 #include "ui/views/mus/pointer_watcher_event_router.h" |
6 | 6 |
7 #include "services/ui/public/cpp/window.h" | 7 #include "services/ui/public/cpp/window.h" |
8 #include "services/ui/public/cpp/window_tree_client.h" | 8 #include "services/ui/public/cpp/window_tree_client.h" |
9 #include "ui/events/base_event_utils.h" | 9 #include "ui/events/base_event_utils.h" |
10 #include "ui/events/event.h" | 10 #include "ui/events/event.h" |
11 #include "ui/views/mus/native_widget_mus.h" | 11 #include "ui/views/mus/native_widget_mus.h" |
12 #include "ui/views/pointer_watcher.h" | 12 #include "ui/views/pointer_watcher.h" |
13 | 13 |
14 namespace views { | 14 namespace views { |
| 15 namespace { |
| 16 |
| 17 bool HasPointerWatcher( |
| 18 base::ObserverList<views::PointerWatcher, true>* observer_list) { |
| 19 if (!observer_list->might_have_observers()) |
| 20 return false; |
| 21 |
| 22 // might_have_observers() returned true, see if there really are any |
| 23 // observers. The only way to truly know is to use an Iterator and see if it |
| 24 // has at least one observer. |
| 25 base::ObserverList<PointerWatcher>::Iterator iterator(observer_list); |
| 26 return !!iterator.GetNext(); |
| 27 } |
| 28 |
| 29 } // namespace |
15 | 30 |
16 PointerWatcherEventRouter::PointerWatcherEventRouter( | 31 PointerWatcherEventRouter::PointerWatcherEventRouter( |
17 ui::WindowTreeClient* client) | 32 ui::WindowTreeClient* client) |
18 : window_tree_client_(client) { | 33 : window_tree_client_(client) { |
19 client->AddObserver(this); | 34 client->AddObserver(this); |
20 } | 35 } |
21 | 36 |
22 PointerWatcherEventRouter::~PointerWatcherEventRouter() { | 37 PointerWatcherEventRouter::~PointerWatcherEventRouter() { |
23 if (window_tree_client_) | 38 if (window_tree_client_) |
24 window_tree_client_->RemoveObserver(this); | 39 window_tree_client_->RemoveObserver(this); |
25 } | 40 } |
26 | 41 |
27 void PointerWatcherEventRouter::AddPointerWatcher(PointerWatcher* watcher, | 42 void PointerWatcherEventRouter::AddPointerWatcher(PointerWatcher* watcher, |
28 bool want_moves) { | 43 bool wants_moves) { |
29 // Pointer watchers cannot be added multiple times. | 44 // Pointer watchers cannot be added multiple times. |
30 DCHECK(!pointer_watchers_.HasObserver(watcher)); | 45 DCHECK(!move_watchers_.HasObserver(watcher)); |
31 // TODO(jamescook): Support adding pointer watchers with different | 46 DCHECK(!non_move_watchers_.HasObserver(watcher)); |
32 // |want_moves| values by tracking whether the set as a whole wants moves. | 47 if (wants_moves) { |
33 // This will involve sending observed move events to a subset of the | 48 move_watchers_.AddObserver(watcher); |
34 // watchers. (crbug.com/627146) | 49 if (event_types_ != EventTypes::MOVE_EVENTS) { |
35 DCHECK(!HasPointerWatcher() || want_moves == pointer_watcher_want_moves_); | 50 event_types_ = EventTypes::MOVE_EVENTS; |
36 pointer_watcher_want_moves_ = want_moves; | 51 const bool wants_moves = true; |
37 | 52 window_tree_client_->StartPointerWatcher(wants_moves); |
38 bool had_watcher = HasPointerWatcher(); | 53 } |
39 pointer_watchers_.AddObserver(watcher); | 54 } else { |
40 if (!had_watcher) { | 55 non_move_watchers_.AddObserver(watcher); |
41 // First PointerWatcher added, start the watcher on the window server. | 56 if (event_types_ == EventTypes::NONE) { |
42 window_tree_client_->StartPointerWatcher(want_moves); | 57 event_types_ = EventTypes::NON_MOVE_EVENTS; |
| 58 const bool wants_moves = false; |
| 59 window_tree_client_->StartPointerWatcher(wants_moves); |
| 60 } |
43 } | 61 } |
44 } | 62 } |
45 | 63 |
46 void PointerWatcherEventRouter::RemovePointerWatcher(PointerWatcher* watcher) { | 64 void PointerWatcherEventRouter::RemovePointerWatcher(PointerWatcher* watcher) { |
47 DCHECK(pointer_watchers_.HasObserver(watcher)); | 65 if (non_move_watchers_.HasObserver(watcher)) { |
48 pointer_watchers_.RemoveObserver(watcher); | 66 non_move_watchers_.RemoveObserver(watcher); |
49 if (!HasPointerWatcher()) { | 67 } else { |
50 // Last PointerWatcher removed, stop the watcher on the window server. | 68 DCHECK(move_watchers_.HasObserver(watcher)); |
51 window_tree_client_->StopPointerWatcher(); | 69 move_watchers_.RemoveObserver(watcher); |
52 pointer_watcher_want_moves_ = false; | 70 } |
| 71 const EventTypes types = DetermineEventTypes(); |
| 72 if (types == event_types_) |
| 73 return; |
| 74 |
| 75 event_types_ = types; |
| 76 switch (types) { |
| 77 case EventTypes::NONE: |
| 78 window_tree_client_->StopPointerWatcher(); |
| 79 break; |
| 80 case EventTypes::NON_MOVE_EVENTS: |
| 81 window_tree_client_->StartPointerWatcher(false); |
| 82 break; |
| 83 case EventTypes::MOVE_EVENTS: |
| 84 // It isn't possible to remove an observer and transition to wanting move |
| 85 // events. This could only happen if there is a bug in the add logic. |
| 86 NOTREACHED(); |
| 87 break; |
53 } | 88 } |
54 } | 89 } |
55 | 90 |
56 void PointerWatcherEventRouter::OnPointerEventObserved( | 91 void PointerWatcherEventRouter::OnPointerEventObserved( |
57 const ui::PointerEvent& event, | 92 const ui::PointerEvent& event, |
58 ui::Window* target) { | 93 ui::Window* target) { |
59 Widget* target_widget = nullptr; | 94 Widget* target_widget = nullptr; |
60 if (target) { | 95 if (target) { |
61 ui::Window* window = target; | 96 ui::Window* window = target; |
62 while (window && !target_widget) { | 97 while (window && !target_widget) { |
63 target_widget = NativeWidgetMus::GetWidgetForWindow(target); | 98 target_widget = NativeWidgetMus::GetWidgetForWindow(target); |
64 window = window->parent(); | 99 window = window->parent(); |
65 } | 100 } |
66 } | 101 } |
67 | 102 |
68 // The mojo input events type converter uses the event root_location field | 103 // The mojo input events type converter uses the event root_location field |
69 // to store screen coordinates. Screen coordinates really should be returned | 104 // to store screen coordinates. Screen coordinates really should be returned |
70 // separately. See http://crbug.com/608547 | 105 // separately. See http://crbug.com/608547 |
71 gfx::Point location_in_screen = event.AsLocatedEvent()->root_location(); | 106 gfx::Point location_in_screen = event.AsLocatedEvent()->root_location(); |
72 FOR_EACH_OBSERVER( | 107 FOR_EACH_OBSERVER( |
73 PointerWatcher, pointer_watchers_, | 108 PointerWatcher, move_watchers_, |
74 OnPointerEventObserved(event, location_in_screen, target_widget)); | 109 OnPointerEventObserved(event, location_in_screen, target_widget)); |
| 110 if (event.type() != ui::ET_POINTER_MOVED) { |
| 111 FOR_EACH_OBSERVER( |
| 112 PointerWatcher, non_move_watchers_, |
| 113 OnPointerEventObserved(event, location_in_screen, target_widget)); |
| 114 } |
75 } | 115 } |
76 | 116 |
77 bool PointerWatcherEventRouter::HasPointerWatcher() { | 117 PointerWatcherEventRouter::EventTypes |
78 // Check to see if we really have any observers left. This doesn't use | 118 PointerWatcherEventRouter::DetermineEventTypes() { |
79 // base::ObserverList<>::might_have_observers() because that returns true | 119 if (HasPointerWatcher(&move_watchers_)) |
80 // during iteration over the list even when the last observer is removed. | 120 return EventTypes::MOVE_EVENTS; |
81 base::ObserverList<PointerWatcher>::Iterator iterator(&pointer_watchers_); | 121 |
82 return !!iterator.GetNext(); | 122 if (HasPointerWatcher(&non_move_watchers_)) |
| 123 return EventTypes::NON_MOVE_EVENTS; |
| 124 |
| 125 return EventTypes::NONE; |
83 } | 126 } |
84 | 127 |
85 void PointerWatcherEventRouter::OnWindowTreeCaptureChanged( | 128 void PointerWatcherEventRouter::OnWindowTreeCaptureChanged( |
86 ui::Window* gained_capture, | 129 ui::Window* gained_capture, |
87 ui::Window* lost_capture) { | 130 ui::Window* lost_capture) { |
88 FOR_EACH_OBSERVER(PointerWatcher, pointer_watchers_, OnMouseCaptureChanged()); | 131 FOR_EACH_OBSERVER(PointerWatcher, move_watchers_, OnMouseCaptureChanged()); |
| 132 FOR_EACH_OBSERVER(PointerWatcher, non_move_watchers_, |
| 133 OnMouseCaptureChanged()); |
89 } | 134 } |
90 | 135 |
91 void PointerWatcherEventRouter::OnDidDestroyClient( | 136 void PointerWatcherEventRouter::OnDidDestroyClient( |
92 ui::WindowTreeClient* client) { | 137 ui::WindowTreeClient* client) { |
93 DCHECK(!pointer_watchers_.might_have_observers()); | 138 // We expect that all observers have been removed by this time. |
| 139 DCHECK_EQ(event_types_, EventTypes::NONE); |
94 DCHECK_EQ(client, window_tree_client_); | 140 DCHECK_EQ(client, window_tree_client_); |
95 window_tree_client_->RemoveObserver(this); | 141 window_tree_client_->RemoveObserver(this); |
96 window_tree_client_ = nullptr; | 142 window_tree_client_ = nullptr; |
97 } | 143 } |
98 | 144 |
99 } // namespace views | 145 } // namespace views |
OLD | NEW |