Add 'did_proceed' and 'repeat_visit' to ClientMalwareReportRequest to track CTR.
[chromium-blink-merge.git] / components / mus / gesture_manager.cc
blob0b35c9a5bdf36e2e6125f50efad3e72c6b4a03da
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/mus/gesture_manager.h"
7 #include <algorithm>
9 #include "components/mus/gesture_manager_delegate.h"
10 #include "components/mus/public/cpp/keys.h"
11 #include "components/mus/server_view.h"
12 #include "components/mus/view_coordinate_conversions.h"
13 #include "components/mus/view_locator.h"
14 #include "ui/gfx/geometry/point_f.h"
15 #include "ui/mojo/events/input_events.mojom.h"
17 namespace mus {
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(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->location->x,
59 event.pointer_data->location->y);
60 const gfx::PointF target_location(
61 ConvertPointFBetweenViews(view->GetRoot(), view, location));
62 result->pointer_data->location->x = target_location.x();
63 result->pointer_data->location->y = target_location.y();
64 return result.Pass();
67 } // namespace
69 // GestureStateChange ----------------------------------------------------------
71 GestureStateChange::GestureStateChange()
72 : chosen_gesture(GestureManager::kInvalidGestureId) {}
74 GestureStateChange::~GestureStateChange() {}
76 // ViewIterator ----------------------------------------------------------------
78 // Used to iterate over a set of views.
79 class ViewIterator {
80 public:
81 explicit ViewIterator(const Views& views)
82 : views_(views), current_(views_.begin()) {}
84 // Advances to the next view. Returns true if there are no more views (at
85 // the end).
86 bool advance() { return ++current_ != views_.end(); }
88 bool at_end() const { return current_ == views_.end(); }
90 bool empty() const { return views_.empty(); }
92 const ServerView* current() const { return *current_; }
94 void reset_to_beginning() { current_ = views_.begin(); }
96 void remove(const ServerView* view) {
97 Views::iterator iter = std::find(views_.begin(), views_.end(), view);
98 DCHECK(iter != views_.end());
99 if (iter == current_) {
100 current_ = views_.erase(current_);
101 } else if (!at_end()) {
102 size_t index = current_ - views_.begin();
103 if (current_ > iter)
104 index--;
105 views_.erase(iter);
106 current_ = views_.begin() + index;
107 } else {
108 views_.erase(iter);
109 current_ = views_.end();
113 bool contains(const ServerView* view) const {
114 return std::find(views_.begin(), views_.end(), view) != views_.end();
117 private:
118 Views views_;
119 Views::iterator current_;
121 DISALLOW_COPY_AND_ASSIGN(ViewIterator);
124 // PointerAndView --------------------------------------------------------------
126 struct GestureManager::PointerAndView {
127 PointerAndView();
128 PointerAndView(Pointer* pointer, const ServerView* view);
130 // Compares two PointerAndView instances based on pointer id, then view id.
131 // This is really only interesting for unit tests so that they get a known
132 // order of events.
133 bool operator<(const PointerAndView& other) const;
135 Pointer* pointer;
136 const ServerView* view;
139 // Gesture ---------------------------------------------------------------------
141 // Gesture maintains the set of pointers and views it is attached to.
142 class GestureManager::Gesture {
143 public:
144 enum State { STATE_INITIAL, STATE_CANCELED, STATE_CHOSEN };
146 explicit Gesture(uint32_t id);
147 ~Gesture();
149 uint32_t id() const { return id_; }
151 void Attach(Pointer* pointer, const ServerView* view);
152 void Detach(Pointer* pointer, const ServerView* view);
154 void set_state(State state) { state_ = state; }
155 State state() const { return state_; }
157 const std::set<PointerAndView>& pointers_and_views() const {
158 return pointers_and_views_;
161 private:
162 const uint32_t id_;
163 State state_;
164 std::set<PointerAndView> pointers_and_views_;
166 DISALLOW_COPY_AND_ASSIGN(Gesture);
169 GestureManager::Gesture::Gesture(uint32_t id)
170 : id_(id), state_(STATE_INITIAL) {}
172 GestureManager::Gesture::~Gesture() {}
174 void GestureManager::Gesture::Attach(Pointer* pointer, const ServerView* view) {
175 pointers_and_views_.insert(PointerAndView(pointer, view));
178 void GestureManager::Gesture::Detach(Pointer* pointer, const ServerView* view) {
179 pointers_and_views_.erase(PointerAndView(pointer, view));
182 // Pointer ---------------------------------------------------------------------
184 // Pointer manages the state associated with a particular pointer from the time
185 // of the POINTER_DOWN to the time of the POINTER_UP (or POINTER_CANCEL). This
186 // state includes a mapping from view to the set of gestures the view is
187 // interested in. It also manages choosing gestures at the appropriate point as
188 // well as which view to dispatch to and the events to dispatch.
189 // See description in GestureManager for more.
190 class GestureManager::Pointer {
191 public:
192 Pointer(GestureManager* gesture_manager,
193 int32_t pointer_id,
194 const mojo::Event& event,
195 const Views& views);
196 ~Pointer();
198 int32_t pointer_id() const { return pointer_id_; }
199 bool was_chosen_or_canceled() const { return was_chosen_or_canceled_; }
201 // Sets the set of gestures for this pointer.
202 void SetGestures(const ServerView* view,
203 uint32_t chosen_gesture_id,
204 const std::set<uint32_t>& possible_gesture_ids,
205 const std::set<uint32_t>& canceled_ids);
207 // Called when a Gesture we contain has been canceled.
208 void GestureCanceled(Gesture* gesture);
210 // Called when a Gesture we contain has been chosen.
211 void GestureChosen(Gesture* gesture, const ServerView* view);
213 // Process a move or up event. This may delay processing if we're waiting for
214 // previous results.
215 void ProcessEvent(const mojo::Event& event);
217 private:
218 // Corresponds to the type of event we're dispatching.
219 enum Phase {
220 // We're dispatching the initial down.
221 PHASE_DOWN,
223 // We're dispatching a move.
224 PHASE_MOVE,
227 // Sends the event for the current phase to the delegate.
228 void ForwardCurrentEvent();
230 // Moves |pending_event_| to |current_event_| and notifies the delegate.
231 void MovePendingToCurrentAndProcess();
233 // If |was_chosen_or_canceled_| is false and there is only one possible
234 // gesture and it is in the initial state, choose it. Otherwise do nothing.
235 void ChooseGestureIfPossible();
237 bool ScheduleDeleteIfNecessary();
239 GestureManager* gesture_manager_;
240 const int32_t pointer_id_;
241 Phase phase_;
243 // Used to iterate over the set of views that potentially have gestures.
244 ViewIterator view_iter_;
246 // Maps from the view to the set of possible gestures for the view.
247 std::map<const ServerView*, std::set<Gesture*>> view_to_gestures_;
249 Gesture* chosen_gesture_;
251 bool was_chosen_or_canceled_;
253 // The event we're processing. When initially created this is the supplied
254 // down event. When in PHASE_MOVE this is a move event.
255 mojo::EventPtr current_event_;
257 // Incoming events (move or up) are added here while while waiting for
258 // responses.
259 mojo::EventPtr pending_event_;
261 DISALLOW_COPY_AND_ASSIGN(Pointer);
264 GestureManager::Pointer::Pointer(GestureManager* gesture_manager,
265 int32_t pointer_id,
266 const mojo::Event& event,
267 const Views& views)
268 : gesture_manager_(gesture_manager),
269 pointer_id_(pointer_id),
270 phase_(PHASE_DOWN),
271 view_iter_(views),
272 chosen_gesture_(nullptr),
273 was_chosen_or_canceled_(false),
274 current_event_(event.Clone()) {
275 ForwardCurrentEvent();
278 GestureManager::Pointer::~Pointer() {
279 for (auto& pair : view_to_gestures_) {
280 for (Gesture* gesture : pair.second)
281 gesture_manager_->DetachGesture(gesture, this, pair.first);
285 void GestureManager::Pointer::SetGestures(
286 const ServerView* view,
287 uint32_t chosen_gesture_id,
288 const std::set<uint32_t>& possible_gesture_ids,
289 const std::set<uint32_t>& canceled_gesture_ids) {
290 if (!view_iter_.contains(view)) {
291 // We don't know about this view.
292 return;
295 // True if this is the view we're waiting for a response from.
296 const bool was_waiting_on =
297 (!was_chosen_or_canceled_ &&
298 (!view_iter_.at_end() && view_iter_.current() == view));
300 if (possible_gesture_ids.empty()) {
301 // The view no longer wants to be notified.
302 for (Gesture* gesture : view_to_gestures_[view])
303 gesture_manager_->DetachGesture(gesture, this, view);
304 view_to_gestures_.erase(view);
305 view_iter_.remove(view);
306 if (view_iter_.empty()) {
307 gesture_manager_->PointerHasNoGestures(this);
308 // WARNING: we've been deleted.
309 return;
311 } else {
312 if (was_waiting_on)
313 view_iter_.advance();
315 Gesture* to_choose = nullptr;
316 std::set<Gesture*> gestures;
317 for (auto gesture_id : possible_gesture_ids) {
318 Gesture* gesture = gesture_manager_->GetGesture(view, gesture_id);
319 gesture_manager_->AttachGesture(gesture, this, view);
320 gestures.insert(gesture);
321 if (gesture->state() == Gesture::STATE_CHOSEN &&
322 !was_chosen_or_canceled_) {
323 to_choose = gesture;
327 // Give preference to the supplied |chosen_gesture_id|.
328 if (!was_chosen_or_canceled_ && chosen_gesture_id != kInvalidGestureId) {
329 Gesture* gesture = gesture_manager_->GetGesture(view, chosen_gesture_id);
330 if (gesture->state() != Gesture::STATE_CANCELED)
331 to_choose = gesture;
333 DCHECK(possible_gesture_ids.count(gesture->id()));
334 gesture_manager_->AttachGesture(gesture, this, view);
337 // Tell GestureManager of any Gestures we're no longer associated with.
338 std::set<Gesture*> removed_gestures;
339 std::set_difference(
340 view_to_gestures_[view].begin(), view_to_gestures_[view].end(),
341 gestures.begin(), gestures.end(),
342 std::inserter(removed_gestures, removed_gestures.begin()));
343 view_to_gestures_[view].swap(gestures);
344 for (Gesture* gesture : removed_gestures)
345 gesture_manager_->DetachGesture(gesture, this, view);
347 if (chosen_gesture_ && removed_gestures.count(chosen_gesture_))
348 chosen_gesture_ = nullptr;
350 if (to_choose) {
351 gesture_manager_->ChooseGesture(to_choose, this, view);
352 } else {
353 // Choosing a gesture implicitly cancels all other gestures. If we didn't
354 // choose a gesture we need to update the state of any newly added
355 // gestures.
356 for (Gesture* gesture : gestures) {
357 if (gesture != chosen_gesture_ &&
358 (was_chosen_or_canceled_ ||
359 canceled_gesture_ids.count(gesture->id()))) {
360 gesture_manager_->CancelGesture(gesture, this, view);
366 if (was_waiting_on && !was_chosen_or_canceled_) {
367 if (view_iter_.at_end()) {
368 if (ScheduleDeleteIfNecessary())
369 return;
370 // If we're got all the responses, check if there is only one valid
371 // gesture.
372 ChooseGestureIfPossible();
373 if (!was_chosen_or_canceled_) {
374 // There is more than one valid gesture and none chosen. Continue
375 // synchronous dispatch of move events.
376 phase_ = PHASE_MOVE;
377 MovePendingToCurrentAndProcess();
379 } else {
380 ForwardCurrentEvent();
382 } else if (!was_chosen_or_canceled_ && phase_ != PHASE_DOWN) {
383 // We weren't waiting on this view but we're in the move phase. The set of
384 // gestures may have changed such that we only have one valid gesture. Check
385 // for that.
386 ChooseGestureIfPossible();
390 void GestureManager::Pointer::GestureCanceled(Gesture* gesture) {
391 if (was_chosen_or_canceled_ && gesture == chosen_gesture_) {
392 chosen_gesture_ = nullptr;
393 // No need to cancel other gestures as they are already canceled by virtue
394 // of us having been chosen.
395 } else if (!was_chosen_or_canceled_ && phase_ == PHASE_MOVE) {
396 ChooseGestureIfPossible();
400 void GestureManager::Pointer::GestureChosen(Gesture* gesture,
401 const ServerView* view) {
402 DCHECK(!was_chosen_or_canceled_);
403 was_chosen_or_canceled_ = true;
404 chosen_gesture_ = gesture;
405 for (auto& pair : view_to_gestures_) {
406 for (Gesture* g : pair.second) {
407 if (g != gesture)
408 gesture_manager_->CancelGesture(g, this, pair.first);
412 while (!view_iter_.at_end()) {
413 ForwardCurrentEvent();
414 view_iter_.advance();
416 if (ScheduleDeleteIfNecessary())
417 return;
418 phase_ = PHASE_MOVE;
419 MovePendingToCurrentAndProcess();
422 void GestureManager::Pointer::ProcessEvent(const mojo::Event& event) {
423 // |event| is either a move or up. In either case it has the new coordinates
424 // and is safe to replace the existing one with.
425 pending_event_ = event.Clone();
426 if (was_chosen_or_canceled_) {
427 MovePendingToCurrentAndProcess();
428 } else if (view_iter_.at_end()) {
429 view_iter_.reset_to_beginning();
430 MovePendingToCurrentAndProcess();
432 // The else case is we are waiting on a response from a view before we
433 // continue dispatching. When we get the response for the last view in the
434 // stack we'll move pending to current and start dispatching it.
437 void GestureManager::Pointer::ForwardCurrentEvent() {
438 DCHECK(!view_iter_.at_end());
439 const ServerView* view = view_iter_.current();
440 gesture_manager_->delegate_->ProcessEvent(
441 view, CloneEventForView(*current_event_, view), was_chosen_or_canceled_);
444 void GestureManager::Pointer::MovePendingToCurrentAndProcess() {
445 if (!pending_event_.get()) {
446 current_event_ = nullptr;
447 return;
449 current_event_ = pending_event_.Pass();
450 view_iter_.reset_to_beginning();
451 ForwardCurrentEvent();
452 if (was_chosen_or_canceled_) {
453 while (view_iter_.advance())
454 ForwardCurrentEvent();
455 if (ScheduleDeleteIfNecessary())
456 return;
457 current_event_ = nullptr;
461 void GestureManager::Pointer::ChooseGestureIfPossible() {
462 if (was_chosen_or_canceled_)
463 return;
465 Gesture* gesture_to_choose = nullptr;
466 const ServerView* view = nullptr;
467 for (auto& pair : view_to_gestures_) {
468 for (Gesture* gesture : pair.second) {
469 if (gesture->state() == Gesture::STATE_INITIAL) {
470 if (gesture_to_choose)
471 return;
472 view = pair.first;
473 gesture_to_choose = gesture;
477 if (view)
478 gesture_manager_->ChooseGesture(gesture_to_choose, this, view);
481 bool GestureManager::Pointer::ScheduleDeleteIfNecessary() {
482 if (current_event_ &&
483 (current_event_->action == mojo::EVENT_TYPE_POINTER_UP ||
484 current_event_->action == mojo::EVENT_TYPE_POINTER_CANCEL)) {
485 gesture_manager_->ScheduleDelete(this);
486 return true;
488 return false;
491 // ScheduledDeleteProcessor ---------------------------------------------------
493 class GestureManager::ScheduledDeleteProcessor {
494 public:
495 explicit ScheduledDeleteProcessor(GestureManager* manager)
496 : manager_(manager) {}
498 ~ScheduledDeleteProcessor() { manager_->pointers_to_delete_.clear(); }
500 private:
501 GestureManager* manager_;
503 DISALLOW_COPY_AND_ASSIGN(ScheduledDeleteProcessor);
506 // PointerAndView --------------------------------------------------------------
508 GestureManager::PointerAndView::PointerAndView()
509 : pointer(nullptr), view(nullptr) {}
511 GestureManager::PointerAndView::PointerAndView(Pointer* pointer,
512 const ServerView* view)
513 : pointer(pointer), view(view) {}
515 bool GestureManager::PointerAndView::operator<(
516 const PointerAndView& other) const {
517 if (other.pointer->pointer_id() == pointer->pointer_id())
518 return view->id().connection_id < other.view->id().connection_id;
519 return pointer->pointer_id() < other.pointer->pointer_id();
522 // GestureManager --------------------------------------------------------------
524 // static
525 const uint32_t GestureManager::kInvalidGestureId = 0u;
527 GestureManager::GestureManager(GestureManagerDelegate* delegate,
528 const ServerView* root)
529 : delegate_(delegate), root_view_(root) {}
531 GestureManager::~GestureManager() {
532 // Explicitly delete the pointers first as this may result in calling back to
533 // us to cleanup and delete gestures.
534 active_pointers_.clear();
537 bool GestureManager::ProcessEvent(const mojo::Event& event) {
538 if (!event.pointer_data)
539 return false;
541 ScheduledDeleteProcessor delete_processor(this);
542 const gfx::Point location(static_cast<int>(event.pointer_data->location->x),
543 static_cast<int>(event.pointer_data->location->y));
544 switch (event.action) {
545 case mojo::EVENT_TYPE_POINTER_DOWN: {
546 if (GetPointerById(event.pointer_data->pointer_id)) {
547 DVLOG(1) << "received more than one down for a pointer without a "
548 << "corresponding up, id=" << event.pointer_data->pointer_id;
549 NOTREACHED();
550 return true;
553 const ServerView* deepest = FindDeepestVisibleView(root_view_, location);
554 Views targets(GetTouchTargets(deepest));
555 if (targets.empty())
556 return true;
558 scoped_ptr<Pointer> pointer(
559 new Pointer(this, event.pointer_data->pointer_id, event, targets));
560 active_pointers_.push_back(pointer.Pass());
561 return true;
564 case mojo::EVENT_TYPE_POINTER_CANCEL:
565 case mojo::EVENT_TYPE_POINTER_MOVE:
566 case mojo::EVENT_TYPE_POINTER_UP: {
567 Pointer* pointer = GetPointerById(event.pointer_data->pointer_id);
568 // We delete a pointer when it has no gestures, so it's possible to get
569 // here with no gestures. Additionally there is no need to explicitly
570 // delete |pointer| as it'll tell us when it's ready to be deleted.
571 if (pointer)
572 pointer->ProcessEvent(event);
573 return true;
576 default:
577 break;
579 return false;
582 scoped_ptr<ChangeMap> GestureManager::SetGestures(
583 const ServerView* view,
584 int32_t pointer_id,
585 uint32_t chosen_gesture_id,
586 const std::set<uint32_t>& possible_gesture_ids,
587 const std::set<uint32_t>& canceled_gesture_ids) {
588 // TODO(sky): caller should validate ids and make sure possible contains
589 // canceled and chosen.
590 DCHECK(!canceled_gesture_ids.count(kInvalidGestureId));
591 DCHECK(!possible_gesture_ids.count(kInvalidGestureId));
592 DCHECK(chosen_gesture_id == kInvalidGestureId ||
593 possible_gesture_ids.count(chosen_gesture_id));
594 DCHECK(chosen_gesture_id == kInvalidGestureId ||
595 !canceled_gesture_ids.count(chosen_gesture_id));
596 ScheduledDeleteProcessor delete_processor(this);
597 Pointer* pointer = GetPointerById(pointer_id);
598 current_change_.reset(new ChangeMap);
599 if (pointer) {
600 pointer->SetGestures(view, chosen_gesture_id, possible_gesture_ids,
601 canceled_gesture_ids);
603 return current_change_.Pass();
606 GestureManager::Pointer* GestureManager::GetPointerById(int32_t pointer_id) {
607 for (Pointer* pointer : active_pointers_) {
608 if (pointer->pointer_id() == pointer_id)
609 return pointer;
611 return nullptr;
614 void GestureManager::PointerHasNoGestures(Pointer* pointer) {
615 auto iter =
616 std::find(active_pointers_.begin(), active_pointers_.end(), pointer);
617 CHECK(iter != active_pointers_.end());
618 active_pointers_.erase(iter);
621 GestureManager::Gesture* GestureManager::GetGesture(const ServerView* view,
622 uint32_t gesture_id) {
623 GestureAndConnectionId gesture_and_connection_id =
624 MakeGestureAndConnectionId(view, gesture_id);
625 Gesture* gesture = gesture_map_[gesture_and_connection_id];
626 if (!gesture) {
627 gesture = new Gesture(gesture_id);
628 gesture_map_[gesture_and_connection_id] = gesture;
630 return gesture;
633 void GestureManager::AttachGesture(Gesture* gesture,
634 Pointer* pointer,
635 const ServerView* view) {
636 gesture->Attach(pointer, view);
639 void GestureManager::DetachGesture(Gesture* gesture,
640 Pointer* pointer,
641 const ServerView* view) {
642 gesture->Detach(pointer, view);
643 if (gesture->pointers_and_views().empty()) {
644 gesture_map_.erase(MakeGestureAndConnectionId(view, gesture->id()));
645 delete gesture;
649 void GestureManager::CancelGesture(Gesture* gesture,
650 Pointer* pointer,
651 const ServerView* view) {
652 if (gesture->state() == Gesture::STATE_CANCELED)
653 return;
655 gesture->set_state(Gesture::STATE_CANCELED);
656 for (auto& pointer_and_view : gesture->pointers_and_views()) {
657 (*current_change_)[pointer_and_view.view].canceled_gestures.insert(
658 gesture->id());
659 if (pointer_and_view.pointer != pointer)
660 pointer_and_view.pointer->GestureCanceled(gesture);
664 void GestureManager::ChooseGesture(Gesture* gesture,
665 Pointer* pointer,
666 const ServerView* view) {
667 if (gesture->state() == Gesture::STATE_CHOSEN) {
668 // This happens when |pointer| is supplied a gesture that is already
669 // chosen.
670 DCHECK((*current_change_)[view].chosen_gesture == kInvalidGestureId ||
671 (*current_change_)[view].chosen_gesture == gesture->id());
672 (*current_change_)[view].chosen_gesture = gesture->id();
673 pointer->GestureChosen(gesture, view);
674 } else {
675 gesture->set_state(Gesture::STATE_CHOSEN);
676 for (auto& pointer_and_view : gesture->pointers_and_views()) {
677 DCHECK((*current_change_)[pointer_and_view.view].chosen_gesture ==
678 kInvalidGestureId ||
679 (*current_change_)[pointer_and_view.view].chosen_gesture ==
680 gesture->id());
681 (*current_change_)[pointer_and_view.view].chosen_gesture = gesture->id();
682 pointer_and_view.pointer->GestureChosen(gesture, view);
687 void GestureManager::ScheduleDelete(Pointer* pointer) {
688 auto iter =
689 std::find(active_pointers_.begin(), active_pointers_.end(), pointer);
690 if (iter != active_pointers_.end()) {
691 active_pointers_.weak_erase(iter);
692 pointers_to_delete_.push_back(pointer);
696 } // namespace mus