Index: services/ui/input_manager/input_dispatcher_impl.cc |
diff --git a/services/ui/input_manager/input_dispatcher_impl.cc b/services/ui/input_manager/input_dispatcher_impl.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a4a4201a2090ef240cc53e16fdf750119e5b32fa |
--- /dev/null |
+++ b/services/ui/input_manager/input_dispatcher_impl.cc |
@@ -0,0 +1,129 @@ |
+// Copyright 2016 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 "services/ui/input_manager/input_dispatcher_impl.h" |
+ |
+#include "base/bind.h" |
+#include "base/logging.h" |
+#include "base/message_loop/message_loop.h" |
+#include "mojo/services/geometry/cpp/geometry_util.h" |
+#include "mojo/services/gfx/composition/cpp/formatting.h" |
+#include "mojo/services/ui/views/cpp/formatting.h" |
+#include "services/ui/input_manager/input_associate.h" |
+ |
+namespace input_manager { |
+namespace { |
+void TransformEvent(const mojo::Transform& transform, mojo::Event* event) { |
+ if (!event->pointer_data) |
+ return; |
+ mojo::Point point; |
+ point.x = event->pointer_data->x; |
+ point.y = event->pointer_data->y; |
+ point = TransformPoint(transform, point); |
+ event->pointer_data->x = point.x; |
+ event->pointer_data->y = point.y; |
+} |
+} // namespace |
+ |
+InputDispatcherImpl::InputDispatcherImpl( |
+ InputAssociate* associate, |
+ mojo::ui::ViewTreeTokenPtr view_tree_token, |
+ mojo::InterfaceRequest<mojo::ui::InputDispatcher> request) |
+ : associate_(associate), |
+ view_tree_token_(view_tree_token.Pass()), |
+ hit_tester_( |
+ new mojo::ui::ViewTreeHitTesterClient(associate_->inspector(), |
+ view_tree_token_.Clone())), |
+ binding_(this, request.Pass()), |
+ weak_factory_(this) { |
+ DCHECK(associate_); |
+ DCHECK(view_tree_token_); |
+ |
+ binding_.set_connection_error_handler( |
+ base::Bind(&InputAssociate::OnInputDispatcherDied, |
+ base::Unretained(associate_), base::Unretained(this))); |
+} |
+ |
+InputDispatcherImpl::~InputDispatcherImpl() {} |
+ |
+void InputDispatcherImpl::DispatchEvent(mojo::EventPtr event) { |
+ DCHECK(event); |
+ |
+ pending_events_.push(event.Pass()); |
+ if (pending_events_.size() == 1u) |
+ ProcessNextEvent(); |
+} |
+ |
+void InputDispatcherImpl::ProcessNextEvent() { |
+ DCHECK(!pending_events_.empty()); |
+ |
+ do { |
+ const mojo::Event* event = pending_events_.front().get(); |
+ if (event->action == mojo::EventType::POINTER_DOWN) { |
+ DCHECK(event->pointer_data); |
+ auto point = mojo::Point::New(); |
+ point->x = event->pointer_data->x; |
+ point->y = event->pointer_data->y; |
+ DVLOG(1) << "HitTest: point=" << point; |
+ hit_tester_->HitTest(point.Pass(), |
+ base::Bind(&InputDispatcherImpl::OnHitTestResult, |
+ weak_factory_.GetWeakPtr())); |
+ return; |
+ } |
+ DeliverEvent(pending_events_.front().Pass()); |
+ pending_events_.pop(); |
+ } while (!pending_events_.empty()); |
+} |
+ |
+void InputDispatcherImpl::DeliverEvent(mojo::EventPtr event) { |
+ if (focused_view_token_) { |
+ TransformEvent(*focused_view_transform_, event.get()); |
+ associate_->DeliverEvent(focused_view_token_.get(), event.Pass()); |
+ } |
+} |
+ |
+void InputDispatcherImpl::OnHitTestResult( |
+ scoped_ptr<mojo::ui::ResolvedHits> resolved_hits) { |
+ DCHECK(!pending_events_.empty()); |
+ DVLOG(1) << "OnHitTestResult: resolved_hits=" << resolved_hits.get(); |
+ |
+ // TODO(jeffbrown): Flesh out the input protocol so it makes sense to |
+ // look at more than the first hit. |
+ focused_view_token_.reset(); |
+ focused_view_transform_.reset(); |
+ if (resolved_hits && resolved_hits->result()->root) { |
+ mojo::gfx::composition::HitTestResultPtr result = |
+ resolved_hits->TakeResult(); |
+ const mojo::gfx::composition::SceneHit* scene = result->root.get(); |
+ for (;;) { |
+ DCHECK(scene->hits.size()); |
+ if (scene->hits[0]->is_node()) { |
+ auto it = resolved_hits->map().find(scene->scene_token->value); |
+ if (it != resolved_hits->map().end()) { |
+ focused_view_token_ = it->second.Clone(); |
+ focused_view_transform_ = |
+ scene->hits[0]->get_node()->transform.Pass(); |
+ } |
+ break; |
+ } |
+ DCHECK(scene->hits[0]->is_scene()); |
+ scene = scene->hits[0]->get_scene().get(); |
+ } |
+ } |
+ |
+ DVLOG(1) << "OnHitTestResult: focused_view_token_=" << focused_view_token_ |
+ << ", focused_view_transform_=" << focused_view_transform_; |
+ |
+ DeliverEvent(pending_events_.front().Pass()); |
+ pending_events_.pop(); |
+ |
+ if (!pending_events_.empty()) { |
+ // Prevent reentrance from ProcessNextEvent. |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, base::Bind(&InputDispatcherImpl::ProcessNextEvent, |
+ weak_factory_.GetWeakPtr())); |
+ } |
+} |
+ |
+} // namespace input_manager |