Chromium Code Reviews| 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 |