Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(228)

Unified Diff: mojo/services/view_manager/gesture_manager.cc

Issue 1092033003: Pulls display related changes from mojo to chrome (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mojo/services/view_manager/gesture_manager.h ('k') | mojo/services/view_manager/gesture_manager_delegate.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/services/view_manager/gesture_manager.cc
diff --git a/mojo/services/view_manager/gesture_manager.cc b/mojo/services/view_manager/gesture_manager.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1b312bd6b0e4d9c1567df0aff3b6f20fdaa4e26d
--- /dev/null
+++ b/mojo/services/view_manager/gesture_manager.cc
@@ -0,0 +1,701 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/services/view_manager/gesture_manager.h"
+
+#include <algorithm>
+
+#include "mojo/services/view_manager/gesture_manager_delegate.h"
+#include "mojo/services/view_manager/server_view.h"
+#include "mojo/services/view_manager/view_coordinate_conversions.h"
+#include "mojo/services/view_manager/view_locator.h"
+#include "third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom.h"
+#include "third_party/mojo_services/src/view_manager/public/cpp/keys.h"
+#include "ui/gfx/geometry/point_f.h"
+
+namespace view_manager {
+
+using Views = std::vector<const ServerView*>;
+
+namespace {
+
+GestureManager::GestureAndConnectionId MakeGestureAndConnectionId(
+ const ServerView* view,
+ uint32_t gesture_id) {
+ return (static_cast<GestureManager::GestureAndConnectionId>(
+ view->id().connection_id)
+ << 32) |
+ gesture_id;
+}
+
+// Returns the views (deepest first) that should receive touch events. This only
+// returns one view per connection. If multiple views from the same connection
+// are interested in touch events the shallowest view is returned.
+Views GetTouchTargets(const ServerView* deepest) {
+ Views result;
+ const ServerView* view = deepest;
+ while (view) {
+ if (view->properties().count(mojo::kViewManagerKeyWantsTouchEvents)) {
+ if (!result.empty() &&
+ result.back()->id().connection_id == view->id().connection_id) {
+ result.pop_back();
+ }
+ result.push_back(view);
+ }
+ view = view->parent();
+ }
+ // TODO(sky): I'm doing this until things are converted. Seems as though we
+ // shouldn't do this long term.
+ if (result.empty())
+ result.push_back(deepest);
+ return result;
+}
+
+mojo::EventPtr CloneEventForView(const mojo::Event& event,
+ const ServerView* view) {
+ mojo::EventPtr result(event.Clone());
+ const gfx::PointF location(event.pointer_data->x, event.pointer_data->y);
+ const gfx::PointF target_location(
+ ConvertPointFBetweenViews(view->GetRoot(), view, location));
+ result->pointer_data->x = target_location.x();
+ result->pointer_data->y = target_location.y();
+ return result.Pass();
+}
+
+} // namespace
+
+// GestureStateChange ----------------------------------------------------------
+
+GestureStateChange::GestureStateChange()
+ : chosen_gesture(GestureManager::kInvalidGestureId) {
+}
+
+GestureStateChange::~GestureStateChange() {
+}
+
+// ViewIterator ----------------------------------------------------------------
+
+// Used to iterate over a set of views.
+class ViewIterator {
+ public:
+ explicit ViewIterator(const Views& views)
+ : views_(views), current_(views_.begin()) {}
+
+ // Advances to the next view. Returns true if there are no more views (at
+ // the end).
+ bool advance() { return ++current_ != views_.end(); }
+
+ bool at_end() const { return current_ == views_.end(); }
+
+ bool empty() const { return views_.empty(); }
+
+ const ServerView* current() const { return *current_; }
+
+ void reset_to_beginning() { current_ = views_.begin(); }
+
+ void remove(const ServerView* view) {
+ Views::iterator iter = std::find(views_.begin(), views_.end(), view);
+ DCHECK(iter != views_.end());
+ if (iter == current_) {
+ current_ = views_.erase(current_);
+ } else if (!at_end()) {
+ size_t index = current_ - views_.begin();
+ if (current_ > iter)
+ index--;
+ views_.erase(iter);
+ current_ = views_.begin() + index;
+ } else {
+ views_.erase(iter);
+ current_ = views_.end();
+ }
+ }
+
+ bool contains(const ServerView* view) const {
+ return std::find(views_.begin(), views_.end(), view) != views_.end();
+ }
+
+ private:
+ Views views_;
+ Views::iterator current_;
+
+ DISALLOW_COPY_AND_ASSIGN(ViewIterator);
+};
+
+// PointerAndView --------------------------------------------------------------
+
+struct GestureManager::PointerAndView {
+ PointerAndView();
+ PointerAndView(Pointer* pointer, const ServerView* view);
+
+ // Compares two PointerAndView instances based on pointer id, then view id.
+ // This is really only interesting for unit tests so that they get a known
+ // order of events.
+ bool operator<(const PointerAndView& other) const;
+
+ Pointer* pointer;
+ const ServerView* view;
+};
+
+// Gesture ---------------------------------------------------------------------
+
+// Gesture maintains the set of pointers and views it is attached to.
+class GestureManager::Gesture {
+ public:
+ enum State { STATE_INITIAL, STATE_CANCELED, STATE_CHOSEN };
+
+ explicit Gesture(uint32_t id);
+ ~Gesture();
+
+ uint32_t id() const { return id_; }
+
+ void Attach(Pointer* pointer, const ServerView* view);
+ void Detach(Pointer* pointer, const ServerView* view);
+
+ void set_state(State state) { state_ = state; }
+ State state() const { return state_; }
+
+ const std::set<PointerAndView>& pointers_and_views() const {
+ return pointers_and_views_;
+ }
+
+ private:
+ const uint32_t id_;
+ State state_;
+ std::set<PointerAndView> pointers_and_views_;
+
+ DISALLOW_COPY_AND_ASSIGN(Gesture);
+};
+
+GestureManager::Gesture::Gesture(uint32_t id) : id_(id), state_(STATE_INITIAL) {
+}
+
+GestureManager::Gesture::~Gesture() {
+}
+
+void GestureManager::Gesture::Attach(Pointer* pointer, const ServerView* view) {
+ pointers_and_views_.insert(PointerAndView(pointer, view));
+}
+
+void GestureManager::Gesture::Detach(Pointer* pointer, const ServerView* view) {
+ pointers_and_views_.erase(PointerAndView(pointer, view));
+}
+
+// Pointer ---------------------------------------------------------------------
+
+// Pointer manages the state associated with a particular pointer from the time
+// of the POINTER_DOWN to the time of the POINTER_UP (or POINTER_CANCEL). This
+// state includes a mapping from view to the set of gestures the view is
+// interested in. It also manages choosing gestures at the appropriate point as
+// well as which view to dispatch to and the events to dispatch.
+// See description in GestureManager for more.
+class GestureManager::Pointer {
+ public:
+ Pointer(GestureManager* gesture_manager,
+ int32_t pointer_id,
+ const mojo::Event& event,
+ const Views& views);
+ ~Pointer();
+
+ int32_t pointer_id() const { return pointer_id_; }
+ bool was_chosen_or_canceled() const { return was_chosen_or_canceled_; }
+
+ // Sets the set of gestures for this pointer.
+ void SetGestures(const ServerView* view,
+ uint32_t chosen_gesture_id,
+ const std::set<uint32_t>& possible_gesture_ids,
+ const std::set<uint32_t>& canceled_ids);
+
+ // Called when a Gesture we contain has been canceled.
+ void GestureCanceled(Gesture* gesture);
+
+ // Called when a Gesture we contain has been chosen.
+ void GestureChosen(Gesture* gesture, const ServerView* view);
+
+ // Process a move or up event. This may delay processing if we're waiting for
+ // previous results.
+ void ProcessEvent(const mojo::Event& event);
+
+ private:
+ // Corresponds to the type of event we're dispatching.
+ enum Phase {
+ // We're dispatching the initial down.
+ PHASE_DOWN,
+
+ // We're dispatching a move.
+ PHASE_MOVE,
+ };
+
+ // Sends the event for the current phase to the delegate.
+ void ForwardCurrentEvent();
+
+ // Moves |pending_event_| to |current_event_| and notifies the delegate.
+ void MovePendingToCurrentAndProcess();
+
+ // If |was_chosen_or_canceled_| is false and there is only one possible
+ // gesture and it is in the initial state, choose it. Otherwise do nothing.
+ void ChooseGestureIfPossible();
+
+ bool ScheduleDeleteIfNecessary();
+
+ GestureManager* gesture_manager_;
+ const int32_t pointer_id_;
+ Phase phase_;
+
+ // Used to iterate over the set of views that potentially have gestures.
+ ViewIterator view_iter_;
+
+ // Maps from the view to the set of possible gestures for the view.
+ std::map<const ServerView*, std::set<Gesture*>> view_to_gestures_;
+
+ Gesture* chosen_gesture_;
+
+ bool was_chosen_or_canceled_;
+
+ // The event we're processing. When initially created this is the supplied
+ // down event. When in PHASE_MOVE this is a move event.
+ mojo::EventPtr current_event_;
+
+ // Incoming events (move or up) are added here while while waiting for
+ // responses.
+ mojo::EventPtr pending_event_;
+
+ DISALLOW_COPY_AND_ASSIGN(Pointer);
+};
+
+GestureManager::Pointer::Pointer(GestureManager* gesture_manager,
+ int32_t pointer_id,
+ const mojo::Event& event,
+ const Views& views)
+ : gesture_manager_(gesture_manager),
+ pointer_id_(pointer_id),
+ phase_(PHASE_DOWN),
+ view_iter_(views),
+ chosen_gesture_(nullptr),
+ was_chosen_or_canceled_(false),
+ current_event_(event.Clone()) {
+ ForwardCurrentEvent();
+}
+
+GestureManager::Pointer::~Pointer() {
+ for (auto& pair : view_to_gestures_) {
+ for (Gesture* gesture : pair.second)
+ gesture_manager_->DetachGesture(gesture, this, pair.first);
+ }
+}
+
+void GestureManager::Pointer::SetGestures(
+ const ServerView* view,
+ uint32_t chosen_gesture_id,
+ const std::set<uint32_t>& possible_gesture_ids,
+ const std::set<uint32_t>& canceled_gesture_ids) {
+ if (!view_iter_.contains(view)) {
+ // We don't know about this view.
+ return;
+ }
+
+ // True if this is the view we're waiting for a response from.
+ const bool was_waiting_on =
+ (!was_chosen_or_canceled_ &&
+ (!view_iter_.at_end() && view_iter_.current() == view));
+
+ if (possible_gesture_ids.empty()) {
+ // The view no longer wants to be notified.
+ for (Gesture* gesture : view_to_gestures_[view])
+ gesture_manager_->DetachGesture(gesture, this, view);
+ view_to_gestures_.erase(view);
+ view_iter_.remove(view);
+ if (view_iter_.empty()) {
+ gesture_manager_->PointerHasNoGestures(this);
+ // WARNING: we've been deleted.
+ return;
+ }
+ } else {
+ if (was_waiting_on)
+ view_iter_.advance();
+
+ Gesture* to_choose = nullptr;
+ std::set<Gesture*> gestures;
+ for (auto gesture_id : possible_gesture_ids) {
+ Gesture* gesture = gesture_manager_->GetGesture(view, gesture_id);
+ gesture_manager_->AttachGesture(gesture, this, view);
+ gestures.insert(gesture);
+ if (gesture->state() == Gesture::STATE_CHOSEN &&
+ !was_chosen_or_canceled_) {
+ to_choose = gesture;
+ }
+ }
+
+ // Give preference to the supplied |chosen_gesture_id|.
+ if (!was_chosen_or_canceled_ && chosen_gesture_id != kInvalidGestureId) {
+ Gesture* gesture = gesture_manager_->GetGesture(view, chosen_gesture_id);
+ if (gesture->state() != Gesture::STATE_CANCELED)
+ to_choose = gesture;
+
+ DCHECK(possible_gesture_ids.count(gesture->id()));
+ gesture_manager_->AttachGesture(gesture, this, view);
+ }
+
+ // Tell GestureManager of any Gestures we're no longer associated with.
+ std::set<Gesture*> removed_gestures;
+ std::set_difference(
+ view_to_gestures_[view].begin(), view_to_gestures_[view].end(),
+ gestures.begin(), gestures.end(),
+ std::inserter(removed_gestures, removed_gestures.begin()));
+ view_to_gestures_[view].swap(gestures);
+ for (Gesture* gesture : removed_gestures)
+ gesture_manager_->DetachGesture(gesture, this, view);
+
+ if (chosen_gesture_ && removed_gestures.count(chosen_gesture_))
+ chosen_gesture_ = nullptr;
+
+ if (to_choose) {
+ gesture_manager_->ChooseGesture(to_choose, this, view);
+ } else {
+ // Choosing a gesture implicitly cancels all other gestures. If we didn't
+ // choose a gesture we need to update the state of any newly added
+ // gestures.
+ for (Gesture* gesture : gestures) {
+ if (gesture != chosen_gesture_ &&
+ (was_chosen_or_canceled_ ||
+ canceled_gesture_ids.count(gesture->id()))) {
+ gesture_manager_->CancelGesture(gesture, this, view);
+ }
+ }
+ }
+ }
+
+ if (was_waiting_on && !was_chosen_or_canceled_) {
+ if (view_iter_.at_end()) {
+ if (ScheduleDeleteIfNecessary())
+ return;
+ // If we're got all the responses, check if there is only one valid
+ // gesture.
+ ChooseGestureIfPossible();
+ if (!was_chosen_or_canceled_) {
+ // There is more than one valid gesture and none chosen. Continue
+ // synchronous dispatch of move events.
+ phase_ = PHASE_MOVE;
+ MovePendingToCurrentAndProcess();
+ }
+ } else {
+ ForwardCurrentEvent();
+ }
+ } else if (!was_chosen_or_canceled_ && phase_ != PHASE_DOWN) {
+ // We weren't waiting on this view but we're in the move phase. The set of
+ // gestures may have changed such that we only have one valid gesture. Check
+ // for that.
+ ChooseGestureIfPossible();
+ }
+}
+
+void GestureManager::Pointer::GestureCanceled(Gesture* gesture) {
+ if (was_chosen_or_canceled_ && gesture == chosen_gesture_) {
+ chosen_gesture_ = nullptr;
+ // No need to cancel other gestures as they are already canceled by virtue
+ // of us having been chosen.
+ } else if (!was_chosen_or_canceled_ && phase_ == PHASE_MOVE) {
+ ChooseGestureIfPossible();
+ }
+}
+
+void GestureManager::Pointer::GestureChosen(Gesture* gesture,
+ const ServerView* view) {
+ DCHECK(!was_chosen_or_canceled_);
+ was_chosen_or_canceled_ = true;
+ chosen_gesture_ = gesture;
+ for (auto& pair : view_to_gestures_) {
+ for (Gesture* g : pair.second) {
+ if (g != gesture)
+ gesture_manager_->CancelGesture(g, this, pair.first);
+ }
+ }
+
+ while (!view_iter_.at_end()) {
+ ForwardCurrentEvent();
+ view_iter_.advance();
+ }
+ if (ScheduleDeleteIfNecessary())
+ return;
+ phase_ = PHASE_MOVE;
+ MovePendingToCurrentAndProcess();
+}
+
+void GestureManager::Pointer::ProcessEvent(const mojo::Event& event) {
+ // |event| is either a move or up. In either case it has the new coordinates
+ // and is safe to replace the existing one with.
+ pending_event_ = event.Clone();
+ if (was_chosen_or_canceled_) {
+ MovePendingToCurrentAndProcess();
+ } else if (view_iter_.at_end()) {
+ view_iter_.reset_to_beginning();
+ MovePendingToCurrentAndProcess();
+ }
+ // The else case is we are waiting on a response from a view before we
+ // continue dispatching. When we get the response for the last view in the
+ // stack we'll move pending to current and start dispatching it.
+}
+
+void GestureManager::Pointer::ForwardCurrentEvent() {
+ DCHECK(!view_iter_.at_end());
+ const ServerView* view = view_iter_.current();
+ gesture_manager_->delegate_->ProcessEvent(
+ view, CloneEventForView(*current_event_, view), was_chosen_or_canceled_);
+}
+
+void GestureManager::Pointer::MovePendingToCurrentAndProcess() {
+ if (!pending_event_.get()) {
+ current_event_ = nullptr;
+ return;
+ }
+ current_event_ = pending_event_.Pass();
+ view_iter_.reset_to_beginning();
+ ForwardCurrentEvent();
+ if (was_chosen_or_canceled_) {
+ while (view_iter_.advance())
+ ForwardCurrentEvent();
+ if (ScheduleDeleteIfNecessary())
+ return;
+ current_event_ = nullptr;
+ }
+}
+
+void GestureManager::Pointer::ChooseGestureIfPossible() {
+ if (was_chosen_or_canceled_)
+ return;
+
+ Gesture* gesture_to_choose = nullptr;
+ const ServerView* view = nullptr;
+ for (auto& pair : view_to_gestures_) {
+ for (Gesture* gesture : pair.second) {
+ if (gesture->state() == Gesture::STATE_INITIAL) {
+ if (gesture_to_choose)
+ return;
+ view = pair.first;
+ gesture_to_choose = gesture;
+ }
+ }
+ }
+ if (view)
+ gesture_manager_->ChooseGesture(gesture_to_choose, this, view);
+}
+
+bool GestureManager::Pointer::ScheduleDeleteIfNecessary() {
+ if (current_event_ &&
+ (current_event_->action == mojo::EVENT_TYPE_POINTER_UP ||
+ current_event_->action == mojo::EVENT_TYPE_POINTER_CANCEL)) {
+ gesture_manager_->ScheduleDelete(this);
+ return true;
+ }
+ return false;
+}
+
+// ScheduledDeleteProcessor ---------------------------------------------------
+
+class GestureManager::ScheduledDeleteProcessor {
+ public:
+ explicit ScheduledDeleteProcessor(GestureManager* manager)
+ : manager_(manager) {}
+
+ ~ScheduledDeleteProcessor() { manager_->pointers_to_delete_.clear(); }
+
+ private:
+ GestureManager* manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScheduledDeleteProcessor);
+};
+
+// PointerAndView --------------------------------------------------------------
+
+GestureManager::PointerAndView::PointerAndView()
+ : pointer(nullptr), view(nullptr) {
+}
+
+GestureManager::PointerAndView::PointerAndView(Pointer* pointer,
+ const ServerView* view)
+ : pointer(pointer), view(view) {
+}
+
+bool GestureManager::PointerAndView::operator<(
+ const PointerAndView& other) const {
+ if (other.pointer->pointer_id() == pointer->pointer_id())
+ return view->id().connection_id < other.view->id().connection_id;
+ return pointer->pointer_id() < other.pointer->pointer_id();
+}
+
+// GestureManager --------------------------------------------------------------
+
+// static
+const uint32_t GestureManager::kInvalidGestureId = 0u;
+
+GestureManager::GestureManager(GestureManagerDelegate* delegate,
+ const ServerView* root)
+ : delegate_(delegate), root_view_(root) {
+}
+
+GestureManager::~GestureManager() {
+ // Explicitly delete the pointers first as this may result in calling back to
+ // us to cleanup and delete gestures.
+ active_pointers_.clear();
+}
+
+bool GestureManager::ProcessEvent(const mojo::Event& event) {
+ if (!event.pointer_data)
+ return false;
+
+ ScheduledDeleteProcessor delete_processor(this);
+ const gfx::Point location(static_cast<int>(event.pointer_data->x),
+ static_cast<int>(event.pointer_data->y));
+ switch (event.action) {
+ case mojo::EVENT_TYPE_POINTER_DOWN: {
+ if (GetPointerById(event.pointer_data->pointer_id)) {
+ DVLOG(1) << "received more than one down for a pointer without a "
+ << "corresponding up, id=" << event.pointer_data->pointer_id;
+ NOTREACHED();
+ return true;
+ }
+
+ const ServerView* deepest = FindDeepestVisibleView(root_view_, location);
+ Views targets(GetTouchTargets(deepest));
+ if (targets.empty())
+ return true;
+
+ scoped_ptr<Pointer> pointer(
+ new Pointer(this, event.pointer_data->pointer_id, event, targets));
+ active_pointers_.push_back(pointer.Pass());
+ return true;
+ }
+
+ case mojo::EVENT_TYPE_POINTER_CANCEL:
+ case mojo::EVENT_TYPE_POINTER_MOVE:
+ case mojo::EVENT_TYPE_POINTER_UP: {
+ Pointer* pointer = GetPointerById(event.pointer_data->pointer_id);
+ // We delete a pointer when it has no gestures, so it's possible to get
+ // here with no gestures. Additionally there is no need to explicitly
+ // delete |pointer| as it'll tell us when it's ready to be deleted.
+ if (pointer)
+ pointer->ProcessEvent(event);
+ return true;
+ }
+
+ default:
+ break;
+ }
+ return false;
+}
+
+scoped_ptr<ChangeMap> GestureManager::SetGestures(
+ const ServerView* view,
+ int32_t pointer_id,
+ uint32_t chosen_gesture_id,
+ const std::set<uint32_t>& possible_gesture_ids,
+ const std::set<uint32_t>& canceled_gesture_ids) {
+ // TODO(sky): caller should validate ids and make sure possible contains
+ // canceled and chosen.
+ DCHECK(!canceled_gesture_ids.count(kInvalidGestureId));
+ DCHECK(!possible_gesture_ids.count(kInvalidGestureId));
+ DCHECK(chosen_gesture_id == kInvalidGestureId ||
+ possible_gesture_ids.count(chosen_gesture_id));
+ DCHECK(chosen_gesture_id == kInvalidGestureId ||
+ !canceled_gesture_ids.count(chosen_gesture_id));
+ ScheduledDeleteProcessor delete_processor(this);
+ Pointer* pointer = GetPointerById(pointer_id);
+ current_change_.reset(new ChangeMap);
+ if (pointer) {
+ pointer->SetGestures(view, chosen_gesture_id, possible_gesture_ids,
+ canceled_gesture_ids);
+ }
+ return current_change_.Pass();
+}
+
+GestureManager::Pointer* GestureManager::GetPointerById(int32_t pointer_id) {
+ for (Pointer* pointer : active_pointers_) {
+ if (pointer->pointer_id() == pointer_id)
+ return pointer;
+ }
+ return nullptr;
+}
+
+void GestureManager::PointerHasNoGestures(Pointer* pointer) {
+ auto iter =
+ std::find(active_pointers_.begin(), active_pointers_.end(), pointer);
+ CHECK(iter != active_pointers_.end());
+ active_pointers_.erase(iter);
+}
+
+GestureManager::Gesture* GestureManager::GetGesture(const ServerView* view,
+ uint32_t gesture_id) {
+ GestureAndConnectionId gesture_and_connection_id =
+ MakeGestureAndConnectionId(view, gesture_id);
+ Gesture* gesture = gesture_map_[gesture_and_connection_id];
+ if (!gesture) {
+ gesture = new Gesture(gesture_id);
+ gesture_map_[gesture_and_connection_id] = gesture;
+ }
+ return gesture;
+}
+
+void GestureManager::AttachGesture(Gesture* gesture,
+ Pointer* pointer,
+ const ServerView* view) {
+ gesture->Attach(pointer, view);
+}
+
+void GestureManager::DetachGesture(Gesture* gesture,
+ Pointer* pointer,
+ const ServerView* view) {
+ gesture->Detach(pointer, view);
+ if (gesture->pointers_and_views().empty()) {
+ gesture_map_.erase(MakeGestureAndConnectionId(view, gesture->id()));
+ delete gesture;
+ }
+}
+
+void GestureManager::CancelGesture(Gesture* gesture,
+ Pointer* pointer,
+ const ServerView* view) {
+ if (gesture->state() == Gesture::STATE_CANCELED)
+ return;
+
+ gesture->set_state(Gesture::STATE_CANCELED);
+ for (auto& pointer_and_view : gesture->pointers_and_views()) {
+ (*current_change_)[pointer_and_view.view].canceled_gestures.insert(
+ gesture->id());
+ if (pointer_and_view.pointer != pointer)
+ pointer_and_view.pointer->GestureCanceled(gesture);
+ }
+}
+
+void GestureManager::ChooseGesture(Gesture* gesture,
+ Pointer* pointer,
+ const ServerView* view) {
+ if (gesture->state() == Gesture::STATE_CHOSEN) {
+ // This happens when |pointer| is supplied a gesture that is already
+ // chosen.
+ DCHECK((*current_change_)[view].chosen_gesture == kInvalidGestureId ||
+ (*current_change_)[view].chosen_gesture == gesture->id());
+ (*current_change_)[view].chosen_gesture = gesture->id();
+ pointer->GestureChosen(gesture, view);
+ } else {
+ gesture->set_state(Gesture::STATE_CHOSEN);
+ for (auto& pointer_and_view : gesture->pointers_and_views()) {
+ DCHECK((*current_change_)[pointer_and_view.view].chosen_gesture ==
+ kInvalidGestureId ||
+ (*current_change_)[pointer_and_view.view].chosen_gesture ==
+ gesture->id());
+ (*current_change_)[pointer_and_view.view].chosen_gesture = gesture->id();
+ pointer_and_view.pointer->GestureChosen(gesture, view);
+ }
+ }
+}
+
+void GestureManager::ScheduleDelete(Pointer* pointer) {
+ auto iter =
+ std::find(active_pointers_.begin(), active_pointers_.end(), pointer);
+ if (iter != active_pointers_.end()) {
+ active_pointers_.weak_erase(iter);
+ pointers_to_delete_.push_back(pointer);
+ }
+}
+
+} // namespace view_manager
« no previous file with comments | « mojo/services/view_manager/gesture_manager.h ('k') | mojo/services/view_manager/gesture_manager_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698