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"
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
*>;
23 GestureManager::GestureAndConnectionId
MakeGestureAndConnectionId(
24 const ServerView
* view
,
25 uint32_t gesture_id
) {
26 return (static_cast<GestureManager::GestureAndConnectionId
>(
27 view
->id().connection_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
) {
37 const ServerView
* view
= deepest
;
39 if (view
->properties().count(mojo::kViewManagerKeyWantsTouchEvents
)) {
40 if (!result
.empty() &&
41 result
.back()->id().connection_id
== view
->id().connection_id
) {
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.
51 result
.push_back(deepest
);
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();
68 // GestureStateChange ----------------------------------------------------------
70 GestureStateChange::GestureStateChange()
71 : chosen_gesture(GestureManager::kInvalidGestureId
) {
74 GestureStateChange::~GestureStateChange() {
77 // ViewIterator ----------------------------------------------------------------
79 // Used to iterate over a set of views.
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
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();
107 current_
= views_
.begin() + index
;
110 current_
= views_
.end();
114 bool contains(const ServerView
* view
) const {
115 return std::find(views_
.begin(), views_
.end(), view
) != views_
.end();
120 Views::iterator current_
;
122 DISALLOW_COPY_AND_ASSIGN(ViewIterator
);
125 // PointerAndView --------------------------------------------------------------
127 struct GestureManager::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
134 bool operator<(const PointerAndView
& other
) const;
137 const ServerView
* view
;
140 // Gesture ---------------------------------------------------------------------
142 // Gesture maintains the set of pointers and views it is attached to.
143 class GestureManager::Gesture
{
145 enum State
{ STATE_INITIAL
, STATE_CANCELED
, STATE_CHOSEN
};
147 explicit Gesture(uint32_t id
);
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_
;
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
{
194 Pointer(GestureManager
* gesture_manager
,
196 const mojo::Event
& event
,
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
217 void ProcessEvent(const mojo::Event
& event
);
220 // Corresponds to the type of event we're dispatching.
222 // We're dispatching the initial down.
225 // We're dispatching a 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_
;
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
261 mojo::EventPtr pending_event_
;
263 DISALLOW_COPY_AND_ASSIGN(Pointer
);
266 GestureManager::Pointer::Pointer(GestureManager
* gesture_manager
,
268 const mojo::Event
& event
,
270 : gesture_manager_(gesture_manager
),
271 pointer_id_(pointer_id
),
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.
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.
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_
) {
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
)
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
;
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;
353 gesture_manager_
->ChooseGesture(to_choose
, this, view
);
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
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())
372 // If we're got all the responses, check if there is only one valid
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.
379 MovePendingToCurrentAndProcess();
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
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
) {
410 gesture_manager_
->CancelGesture(g
, this, pair
.first
);
414 while (!view_iter_
.at_end()) {
415 ForwardCurrentEvent();
416 view_iter_
.advance();
418 if (ScheduleDeleteIfNecessary())
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;
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())
459 current_event_
= nullptr;
463 void GestureManager::Pointer::ChooseGestureIfPossible() {
464 if (was_chosen_or_canceled_
)
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
)
475 gesture_to_choose
= gesture
;
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);
493 // ScheduledDeleteProcessor ---------------------------------------------------
495 class GestureManager::ScheduledDeleteProcessor
{
497 explicit ScheduledDeleteProcessor(GestureManager
* manager
)
498 : manager_(manager
) {}
500 ~ScheduledDeleteProcessor() { manager_
->pointers_to_delete_
.clear(); }
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 --------------------------------------------------------------
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
)
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
;
558 const ServerView
* deepest
= FindDeepestVisibleView(root_view_
, location
);
559 Views
targets(GetTouchTargets(deepest
));
563 scoped_ptr
<Pointer
> pointer(
564 new Pointer(this, event
.pointer_data
->pointer_id
, event
, targets
));
565 active_pointers_
.push_back(pointer
.Pass());
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.
577 pointer
->ProcessEvent(event
);
587 scoped_ptr
<ChangeMap
> GestureManager::SetGestures(
588 const ServerView
* view
,
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
);
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
)
619 void GestureManager::PointerHasNoGestures(Pointer
* pointer
) {
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
];
632 gesture
= new Gesture(gesture_id
);
633 gesture_map_
[gesture_and_connection_id
] = gesture
;
638 void GestureManager::AttachGesture(Gesture
* gesture
,
640 const ServerView
* view
) {
641 gesture
->Attach(pointer
, view
);
644 void GestureManager::DetachGesture(Gesture
* gesture
,
646 const ServerView
* view
) {
647 gesture
->Detach(pointer
, view
);
648 if (gesture
->pointers_and_views().empty()) {
649 gesture_map_
.erase(MakeGestureAndConnectionId(view
, gesture
->id()));
654 void GestureManager::CancelGesture(Gesture
* gesture
,
656 const ServerView
* view
) {
657 if (gesture
->state() == Gesture::STATE_CANCELED
)
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(
664 if (pointer_and_view
.pointer
!= pointer
)
665 pointer_and_view
.pointer
->GestureCanceled(gesture
);
669 void GestureManager::ChooseGesture(Gesture
* gesture
,
671 const ServerView
* view
) {
672 if (gesture
->state() == Gesture::STATE_CHOSEN
) {
673 // This happens when |pointer| is supplied a gesture that is already
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
);
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
==
684 (*current_change_
)[pointer_and_view
.view
].chosen_gesture
==
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
) {
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