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