Add metrics for tracking LoginDatabase::Init failure.
[chromium-blink-merge.git] / components / view_manager / gesture_manager.cc
blob37bb4b01b4664e72570faa86f6d456b60f6cecc7
1 // Copyright 2015 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 "components/view_manager/gesture_manager.h"
7 #include <algorithm>
9 #include "components/view_manager/gesture_manager_delegate.h"
10 #include "components/view_manager/public/cpp/keys.h"
11 #include "components/view_manager/server_view.h"
12 #include "components/view_manager/view_coordinate_conversions.h"
13 #include "components/view_manager/view_locator.h"
14 #include "ui/gfx/geometry/point_f.h"
15 #include "ui/mojo/events/input_events.mojom.h"
17 namespace view_manager {
19 using Views = std::vector<const ServerView*>;
21 namespace {
23 GestureManager::GestureAndConnectionId MakeGestureAndConnectionId(
24 const ServerView* view,
25 uint32_t gesture_id) {
26 return (static_cast<GestureManager::GestureAndConnectionId>(
27 view->id().connection_id)
28 << 32) |
29 gesture_id;
32 // Returns the views (deepest first) that should receive touch events. This only
33 // returns one view per connection. If multiple views from the same connection
34 // are interested in touch events the shallowest view is returned.
35 Views GetTouchTargets(const ServerView* deepest) {
36 Views result;
37 const ServerView* view = deepest;
38 while (view) {
39 if (view->properties().count(mojo::kViewManagerKeyWantsTouchEvents)) {
40 if (!result.empty() &&
41 result.back()->id().connection_id == view->id().connection_id) {
42 result.pop_back();
44 result.push_back(view);
46 view = view->parent();
48 // TODO(sky): I'm doing this until things are converted. Seems as though we
49 // shouldn't do this long term.
50 if (result.empty())
51 result.push_back(deepest);
52 return result;
55 mojo::EventPtr CloneEventForView(const mojo::Event& event,
56 const ServerView* view) {
57 mojo::EventPtr result(event.Clone());
58 const gfx::PointF location(event.pointer_data->x, event.pointer_data->y);
59 const gfx::PointF target_location(
60 ConvertPointFBetweenViews(view->GetRoot(), view, location));
61 result->pointer_data->x = target_location.x();
62 result->pointer_data->y = target_location.y();
63 return result.Pass();
66 } // namespace
68 // GestureStateChange ----------------------------------------------------------
70 GestureStateChange::GestureStateChange()
71 : chosen_gesture(GestureManager::kInvalidGestureId) {
74 GestureStateChange::~GestureStateChange() {
77 // ViewIterator ----------------------------------------------------------------
79 // Used to iterate over a set of views.
80 class ViewIterator {
81 public:
82 explicit ViewIterator(const Views& views)
83 : views_(views), current_(views_.begin()) {}
85 // Advances to the next view. Returns true if there are no more views (at
86 // the end).
87 bool advance() { return ++current_ != views_.end(); }
89 bool at_end() const { return current_ == views_.end(); }
91 bool empty() const { return views_.empty(); }
93 const ServerView* current() const { return *current_; }
95 void reset_to_beginning() { current_ = views_.begin(); }
97 void remove(const ServerView* view) {
98 Views::iterator iter = std::find(views_.begin(), views_.end(), view);
99 DCHECK(iter != views_.end());
100 if (iter == current_) {
101 current_ = views_.erase(current_);
102 } else if (!at_end()) {
103 size_t index = current_ - views_.begin();
104 if (current_ > iter)
105 index--;
106 views_.erase(iter);
107 current_ = views_.begin() + index;
108 } else {
109 views_.erase(iter);
110 current_ = views_.end();
114 bool contains(const ServerView* view) const {
115 return std::find(views_.begin(), views_.end(), view) != views_.end();
118 private:
119 Views views_;
120 Views::iterator current_;
122 DISALLOW_COPY_AND_ASSIGN(ViewIterator);
125 // PointerAndView --------------------------------------------------------------
127 struct GestureManager::PointerAndView {
128 PointerAndView();
129 PointerAndView(Pointer* pointer, const ServerView* view);
131 // Compares two PointerAndView instances based on pointer id, then view id.
132 // This is really only interesting for unit tests so that they get a known
133 // order of events.
134 bool operator<(const PointerAndView& other) const;
136 Pointer* pointer;
137 const ServerView* view;
140 // Gesture ---------------------------------------------------------------------
142 // Gesture maintains the set of pointers and views it is attached to.
143 class GestureManager::Gesture {
144 public:
145 enum State { STATE_INITIAL, STATE_CANCELED, STATE_CHOSEN };
147 explicit Gesture(uint32_t id);
148 ~Gesture();
150 uint32_t id() const { return id_; }
152 void Attach(Pointer* pointer, const ServerView* view);
153 void Detach(Pointer* pointer, const ServerView* view);
155 void set_state(State state) { state_ = state; }
156 State state() const { return state_; }
158 const std::set<PointerAndView>& pointers_and_views() const {
159 return pointers_and_views_;
162 private:
163 const uint32_t id_;
164 State state_;
165 std::set<PointerAndView> pointers_and_views_;
167 DISALLOW_COPY_AND_ASSIGN(Gesture);
170 GestureManager::Gesture::Gesture(uint32_t id) : id_(id), state_(STATE_INITIAL) {
173 GestureManager::Gesture::~Gesture() {
176 void GestureManager::Gesture::Attach(Pointer* pointer, const ServerView* view) {
177 pointers_and_views_.insert(PointerAndView(pointer, view));
180 void GestureManager::Gesture::Detach(Pointer* pointer, const ServerView* view) {
181 pointers_and_views_.erase(PointerAndView(pointer, view));
184 // Pointer ---------------------------------------------------------------------
186 // Pointer manages the state associated with a particular pointer from the time
187 // of the POINTER_DOWN to the time of the POINTER_UP (or POINTER_CANCEL). This
188 // state includes a mapping from view to the set of gestures the view is
189 // interested in. It also manages choosing gestures at the appropriate point as
190 // well as which view to dispatch to and the events to dispatch.
191 // See description in GestureManager for more.
192 class GestureManager::Pointer {
193 public:
194 Pointer(GestureManager* gesture_manager,
195 int32_t pointer_id,
196 const mojo::Event& event,
197 const Views& views);
198 ~Pointer();
200 int32_t pointer_id() const { return pointer_id_; }
201 bool was_chosen_or_canceled() const { return was_chosen_or_canceled_; }
203 // Sets the set of gestures for this pointer.
204 void SetGestures(const ServerView* view,
205 uint32_t chosen_gesture_id,
206 const std::set<uint32_t>& possible_gesture_ids,
207 const std::set<uint32_t>& canceled_ids);
209 // Called when a Gesture we contain has been canceled.
210 void GestureCanceled(Gesture* gesture);
212 // Called when a Gesture we contain has been chosen.
213 void GestureChosen(Gesture* gesture, const ServerView* view);
215 // Process a move or up event. This may delay processing if we're waiting for
216 // previous results.
217 void ProcessEvent(const mojo::Event& event);
219 private:
220 // Corresponds to the type of event we're dispatching.
221 enum Phase {
222 // We're dispatching the initial down.
223 PHASE_DOWN,
225 // We're dispatching a move.
226 PHASE_MOVE,
229 // Sends the event for the current phase to the delegate.
230 void ForwardCurrentEvent();
232 // Moves |pending_event_| to |current_event_| and notifies the delegate.
233 void MovePendingToCurrentAndProcess();
235 // If |was_chosen_or_canceled_| is false and there is only one possible
236 // gesture and it is in the initial state, choose it. Otherwise do nothing.
237 void ChooseGestureIfPossible();
239 bool ScheduleDeleteIfNecessary();
241 GestureManager* gesture_manager_;
242 const int32_t pointer_id_;
243 Phase phase_;
245 // Used to iterate over the set of views that potentially have gestures.
246 ViewIterator view_iter_;
248 // Maps from the view to the set of possible gestures for the view.
249 std::map<const ServerView*, std::set<Gesture*>> view_to_gestures_;
251 Gesture* chosen_gesture_;
253 bool was_chosen_or_canceled_;
255 // The event we're processing. When initially created this is the supplied
256 // down event. When in PHASE_MOVE this is a move event.
257 mojo::EventPtr current_event_;
259 // Incoming events (move or up) are added here while while waiting for
260 // responses.
261 mojo::EventPtr pending_event_;
263 DISALLOW_COPY_AND_ASSIGN(Pointer);
266 GestureManager::Pointer::Pointer(GestureManager* gesture_manager,
267 int32_t pointer_id,
268 const mojo::Event& event,
269 const Views& views)
270 : gesture_manager_(gesture_manager),
271 pointer_id_(pointer_id),
272 phase_(PHASE_DOWN),
273 view_iter_(views),
274 chosen_gesture_(nullptr),
275 was_chosen_or_canceled_(false),
276 current_event_(event.Clone()) {
277 ForwardCurrentEvent();
280 GestureManager::Pointer::~Pointer() {
281 for (auto& pair : view_to_gestures_) {
282 for (Gesture* gesture : pair.second)
283 gesture_manager_->DetachGesture(gesture, this, pair.first);
287 void GestureManager::Pointer::SetGestures(
288 const ServerView* view,
289 uint32_t chosen_gesture_id,
290 const std::set<uint32_t>& possible_gesture_ids,
291 const std::set<uint32_t>& canceled_gesture_ids) {
292 if (!view_iter_.contains(view)) {
293 // We don't know about this view.
294 return;
297 // True if this is the view we're waiting for a response from.
298 const bool was_waiting_on =
299 (!was_chosen_or_canceled_ &&
300 (!view_iter_.at_end() && view_iter_.current() == view));
302 if (possible_gesture_ids.empty()) {
303 // The view no longer wants to be notified.
304 for (Gesture* gesture : view_to_gestures_[view])
305 gesture_manager_->DetachGesture(gesture, this, view);
306 view_to_gestures_.erase(view);
307 view_iter_.remove(view);
308 if (view_iter_.empty()) {
309 gesture_manager_->PointerHasNoGestures(this);
310 // WARNING: we've been deleted.
311 return;
313 } else {
314 if (was_waiting_on)
315 view_iter_.advance();
317 Gesture* to_choose = nullptr;
318 std::set<Gesture*> gestures;
319 for (auto gesture_id : possible_gesture_ids) {
320 Gesture* gesture = gesture_manager_->GetGesture(view, gesture_id);
321 gesture_manager_->AttachGesture(gesture, this, view);
322 gestures.insert(gesture);
323 if (gesture->state() == Gesture::STATE_CHOSEN &&
324 !was_chosen_or_canceled_) {
325 to_choose = gesture;
329 // Give preference to the supplied |chosen_gesture_id|.
330 if (!was_chosen_or_canceled_ && chosen_gesture_id != kInvalidGestureId) {
331 Gesture* gesture = gesture_manager_->GetGesture(view, chosen_gesture_id);
332 if (gesture->state() != Gesture::STATE_CANCELED)
333 to_choose = gesture;
335 DCHECK(possible_gesture_ids.count(gesture->id()));
336 gesture_manager_->AttachGesture(gesture, this, view);
339 // Tell GestureManager of any Gestures we're no longer associated with.
340 std::set<Gesture*> removed_gestures;
341 std::set_difference(
342 view_to_gestures_[view].begin(), view_to_gestures_[view].end(),
343 gestures.begin(), gestures.end(),
344 std::inserter(removed_gestures, removed_gestures.begin()));
345 view_to_gestures_[view].swap(gestures);
346 for (Gesture* gesture : removed_gestures)
347 gesture_manager_->DetachGesture(gesture, this, view);
349 if (chosen_gesture_ && removed_gestures.count(chosen_gesture_))
350 chosen_gesture_ = nullptr;
352 if (to_choose) {
353 gesture_manager_->ChooseGesture(to_choose, this, view);
354 } else {
355 // Choosing a gesture implicitly cancels all other gestures. If we didn't
356 // choose a gesture we need to update the state of any newly added
357 // gestures.
358 for (Gesture* gesture : gestures) {
359 if (gesture != chosen_gesture_ &&
360 (was_chosen_or_canceled_ ||
361 canceled_gesture_ids.count(gesture->id()))) {
362 gesture_manager_->CancelGesture(gesture, this, view);
368 if (was_waiting_on && !was_chosen_or_canceled_) {
369 if (view_iter_.at_end()) {
370 if (ScheduleDeleteIfNecessary())
371 return;
372 // If we're got all the responses, check if there is only one valid
373 // gesture.
374 ChooseGestureIfPossible();
375 if (!was_chosen_or_canceled_) {
376 // There is more than one valid gesture and none chosen. Continue
377 // synchronous dispatch of move events.
378 phase_ = PHASE_MOVE;
379 MovePendingToCurrentAndProcess();
381 } else {
382 ForwardCurrentEvent();
384 } else if (!was_chosen_or_canceled_ && phase_ != PHASE_DOWN) {
385 // We weren't waiting on this view but we're in the move phase. The set of
386 // gestures may have changed such that we only have one valid gesture. Check
387 // for that.
388 ChooseGestureIfPossible();
392 void GestureManager::Pointer::GestureCanceled(Gesture* gesture) {
393 if (was_chosen_or_canceled_ && gesture == chosen_gesture_) {
394 chosen_gesture_ = nullptr;
395 // No need to cancel other gestures as they are already canceled by virtue
396 // of us having been chosen.
397 } else if (!was_chosen_or_canceled_ && phase_ == PHASE_MOVE) {
398 ChooseGestureIfPossible();
402 void GestureManager::Pointer::GestureChosen(Gesture* gesture,
403 const ServerView* view) {
404 DCHECK(!was_chosen_or_canceled_);
405 was_chosen_or_canceled_ = true;
406 chosen_gesture_ = gesture;
407 for (auto& pair : view_to_gestures_) {
408 for (Gesture* g : pair.second) {
409 if (g != gesture)
410 gesture_manager_->CancelGesture(g, this, pair.first);
414 while (!view_iter_.at_end()) {
415 ForwardCurrentEvent();
416 view_iter_.advance();
418 if (ScheduleDeleteIfNecessary())
419 return;
420 phase_ = PHASE_MOVE;
421 MovePendingToCurrentAndProcess();
424 void GestureManager::Pointer::ProcessEvent(const mojo::Event& event) {
425 // |event| is either a move or up. In either case it has the new coordinates
426 // and is safe to replace the existing one with.
427 pending_event_ = event.Clone();
428 if (was_chosen_or_canceled_) {
429 MovePendingToCurrentAndProcess();
430 } else if (view_iter_.at_end()) {
431 view_iter_.reset_to_beginning();
432 MovePendingToCurrentAndProcess();
434 // The else case is we are waiting on a response from a view before we
435 // continue dispatching. When we get the response for the last view in the
436 // stack we'll move pending to current and start dispatching it.
439 void GestureManager::Pointer::ForwardCurrentEvent() {
440 DCHECK(!view_iter_.at_end());
441 const ServerView* view = view_iter_.current();
442 gesture_manager_->delegate_->ProcessEvent(
443 view, CloneEventForView(*current_event_, view), was_chosen_or_canceled_);
446 void GestureManager::Pointer::MovePendingToCurrentAndProcess() {
447 if (!pending_event_.get()) {
448 current_event_ = nullptr;
449 return;
451 current_event_ = pending_event_.Pass();
452 view_iter_.reset_to_beginning();
453 ForwardCurrentEvent();
454 if (was_chosen_or_canceled_) {
455 while (view_iter_.advance())
456 ForwardCurrentEvent();
457 if (ScheduleDeleteIfNecessary())
458 return;
459 current_event_ = nullptr;
463 void GestureManager::Pointer::ChooseGestureIfPossible() {
464 if (was_chosen_or_canceled_)
465 return;
467 Gesture* gesture_to_choose = nullptr;
468 const ServerView* view = nullptr;
469 for (auto& pair : view_to_gestures_) {
470 for (Gesture* gesture : pair.second) {
471 if (gesture->state() == Gesture::STATE_INITIAL) {
472 if (gesture_to_choose)
473 return;
474 view = pair.first;
475 gesture_to_choose = gesture;
479 if (view)
480 gesture_manager_->ChooseGesture(gesture_to_choose, this, view);
483 bool GestureManager::Pointer::ScheduleDeleteIfNecessary() {
484 if (current_event_ &&
485 (current_event_->action == mojo::EVENT_TYPE_POINTER_UP ||
486 current_event_->action == mojo::EVENT_TYPE_POINTER_CANCEL)) {
487 gesture_manager_->ScheduleDelete(this);
488 return true;
490 return false;
493 // ScheduledDeleteProcessor ---------------------------------------------------
495 class GestureManager::ScheduledDeleteProcessor {
496 public:
497 explicit ScheduledDeleteProcessor(GestureManager* manager)
498 : manager_(manager) {}
500 ~ScheduledDeleteProcessor() { manager_->pointers_to_delete_.clear(); }
502 private:
503 GestureManager* manager_;
505 DISALLOW_COPY_AND_ASSIGN(ScheduledDeleteProcessor);
508 // PointerAndView --------------------------------------------------------------
510 GestureManager::PointerAndView::PointerAndView()
511 : pointer(nullptr), view(nullptr) {
514 GestureManager::PointerAndView::PointerAndView(Pointer* pointer,
515 const ServerView* view)
516 : pointer(pointer), view(view) {
519 bool GestureManager::PointerAndView::operator<(
520 const PointerAndView& other) const {
521 if (other.pointer->pointer_id() == pointer->pointer_id())
522 return view->id().connection_id < other.view->id().connection_id;
523 return pointer->pointer_id() < other.pointer->pointer_id();
526 // GestureManager --------------------------------------------------------------
528 // static
529 const uint32_t GestureManager::kInvalidGestureId = 0u;
531 GestureManager::GestureManager(GestureManagerDelegate* delegate,
532 const ServerView* root)
533 : delegate_(delegate), root_view_(root) {
536 GestureManager::~GestureManager() {
537 // Explicitly delete the pointers first as this may result in calling back to
538 // us to cleanup and delete gestures.
539 active_pointers_.clear();
542 bool GestureManager::ProcessEvent(const mojo::Event& event) {
543 if (!event.pointer_data)
544 return false;
546 ScheduledDeleteProcessor delete_processor(this);
547 const gfx::Point location(static_cast<int>(event.pointer_data->x),
548 static_cast<int>(event.pointer_data->y));
549 switch (event.action) {
550 case mojo::EVENT_TYPE_POINTER_DOWN: {
551 if (GetPointerById(event.pointer_data->pointer_id)) {
552 DVLOG(1) << "received more than one down for a pointer without a "
553 << "corresponding up, id=" << event.pointer_data->pointer_id;
554 NOTREACHED();
555 return true;
558 const ServerView* deepest = FindDeepestVisibleView(root_view_, location);
559 Views targets(GetTouchTargets(deepest));
560 if (targets.empty())
561 return true;
563 scoped_ptr<Pointer> pointer(
564 new Pointer(this, event.pointer_data->pointer_id, event, targets));
565 active_pointers_.push_back(pointer.Pass());
566 return true;
569 case mojo::EVENT_TYPE_POINTER_CANCEL:
570 case mojo::EVENT_TYPE_POINTER_MOVE:
571 case mojo::EVENT_TYPE_POINTER_UP: {
572 Pointer* pointer = GetPointerById(event.pointer_data->pointer_id);
573 // We delete a pointer when it has no gestures, so it's possible to get
574 // here with no gestures. Additionally there is no need to explicitly
575 // delete |pointer| as it'll tell us when it's ready to be deleted.
576 if (pointer)
577 pointer->ProcessEvent(event);
578 return true;
581 default:
582 break;
584 return false;
587 scoped_ptr<ChangeMap> GestureManager::SetGestures(
588 const ServerView* view,
589 int32_t pointer_id,
590 uint32_t chosen_gesture_id,
591 const std::set<uint32_t>& possible_gesture_ids,
592 const std::set<uint32_t>& canceled_gesture_ids) {
593 // TODO(sky): caller should validate ids and make sure possible contains
594 // canceled and chosen.
595 DCHECK(!canceled_gesture_ids.count(kInvalidGestureId));
596 DCHECK(!possible_gesture_ids.count(kInvalidGestureId));
597 DCHECK(chosen_gesture_id == kInvalidGestureId ||
598 possible_gesture_ids.count(chosen_gesture_id));
599 DCHECK(chosen_gesture_id == kInvalidGestureId ||
600 !canceled_gesture_ids.count(chosen_gesture_id));
601 ScheduledDeleteProcessor delete_processor(this);
602 Pointer* pointer = GetPointerById(pointer_id);
603 current_change_.reset(new ChangeMap);
604 if (pointer) {
605 pointer->SetGestures(view, chosen_gesture_id, possible_gesture_ids,
606 canceled_gesture_ids);
608 return current_change_.Pass();
611 GestureManager::Pointer* GestureManager::GetPointerById(int32_t pointer_id) {
612 for (Pointer* pointer : active_pointers_) {
613 if (pointer->pointer_id() == pointer_id)
614 return pointer;
616 return nullptr;
619 void GestureManager::PointerHasNoGestures(Pointer* pointer) {
620 auto iter =
621 std::find(active_pointers_.begin(), active_pointers_.end(), pointer);
622 CHECK(iter != active_pointers_.end());
623 active_pointers_.erase(iter);
626 GestureManager::Gesture* GestureManager::GetGesture(const ServerView* view,
627 uint32_t gesture_id) {
628 GestureAndConnectionId gesture_and_connection_id =
629 MakeGestureAndConnectionId(view, gesture_id);
630 Gesture* gesture = gesture_map_[gesture_and_connection_id];
631 if (!gesture) {
632 gesture = new Gesture(gesture_id);
633 gesture_map_[gesture_and_connection_id] = gesture;
635 return gesture;
638 void GestureManager::AttachGesture(Gesture* gesture,
639 Pointer* pointer,
640 const ServerView* view) {
641 gesture->Attach(pointer, view);
644 void GestureManager::DetachGesture(Gesture* gesture,
645 Pointer* pointer,
646 const ServerView* view) {
647 gesture->Detach(pointer, view);
648 if (gesture->pointers_and_views().empty()) {
649 gesture_map_.erase(MakeGestureAndConnectionId(view, gesture->id()));
650 delete gesture;
654 void GestureManager::CancelGesture(Gesture* gesture,
655 Pointer* pointer,
656 const ServerView* view) {
657 if (gesture->state() == Gesture::STATE_CANCELED)
658 return;
660 gesture->set_state(Gesture::STATE_CANCELED);
661 for (auto& pointer_and_view : gesture->pointers_and_views()) {
662 (*current_change_)[pointer_and_view.view].canceled_gestures.insert(
663 gesture->id());
664 if (pointer_and_view.pointer != pointer)
665 pointer_and_view.pointer->GestureCanceled(gesture);
669 void GestureManager::ChooseGesture(Gesture* gesture,
670 Pointer* pointer,
671 const ServerView* view) {
672 if (gesture->state() == Gesture::STATE_CHOSEN) {
673 // This happens when |pointer| is supplied a gesture that is already
674 // chosen.
675 DCHECK((*current_change_)[view].chosen_gesture == kInvalidGestureId ||
676 (*current_change_)[view].chosen_gesture == gesture->id());
677 (*current_change_)[view].chosen_gesture = gesture->id();
678 pointer->GestureChosen(gesture, view);
679 } else {
680 gesture->set_state(Gesture::STATE_CHOSEN);
681 for (auto& pointer_and_view : gesture->pointers_and_views()) {
682 DCHECK((*current_change_)[pointer_and_view.view].chosen_gesture ==
683 kInvalidGestureId ||
684 (*current_change_)[pointer_and_view.view].chosen_gesture ==
685 gesture->id());
686 (*current_change_)[pointer_and_view.view].chosen_gesture = gesture->id();
687 pointer_and_view.pointer->GestureChosen(gesture, view);
692 void GestureManager::ScheduleDelete(Pointer* pointer) {
693 auto iter =
694 std::find(active_pointers_.begin(), active_pointers_.end(), pointer);
695 if (iter != active_pointers_.end()) {
696 active_pointers_.weak_erase(iter);
697 pointers_to_delete_.push_back(pointer);
701 } // namespace view_manager