Chromium Code Reviews| 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..658b608090380b04b8406d04c5723090d95bced3 |
| --- /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()); |
| + |
| + const mojo::Event* event = pending_events_.front().get(); |
| + if (event->action != mojo::EventType::POINTER_DOWN) { |
| + DeliverNextEvent(); |
| + return; |
| + } |
| + |
| + 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())); |
| +} |
| + |
| +void InputDispatcherImpl::DeliverNextEvent() { |
| + DCHECK(!pending_events_.empty()); |
| + |
| + mojo::EventPtr event = pending_events_.front().Pass(); |
| + pending_events_.pop(); |
| + |
| + if (focused_view_token_) { |
| + TransformEvent(*focused_view_transform_, event.get()); |
| + associate_->DeliverEvent(focused_view_token_.get(), event.Pass()); |
| + } |
| + |
| + if (!pending_events_.empty()) { |
| + base::MessageLoop::current()->PostTask( |
| + FROM_HERE, base::Bind(&InputDispatcherImpl::ProcessNextEvent, |
| + weak_factory_.GetWeakPtr())); |
|
abarth
2016/03/09 04:17:37
Interesting.
jeffbrown
2016/03/09 19:38:50
This was to prevent reentrance when called from On
|
| + } |
| +} |
| + |
| +void InputDispatcherImpl::OnHitTestResult( |
| + scoped_ptr<mojo::ui::ResolvedHits> resolved_hits) { |
| + 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(); |
|
abarth
2016/03/09 04:17:37
I see, you're just delivering to the most specific
jeffbrown
2016/03/09 19:38:50
Acknowledged.
|
| + } |
| + } |
| + |
| + DVLOG(1) << "OnHitTestResult: focused_view_token_=" << focused_view_token_ |
| + << ", focused_view_transform_=" << focused_view_transform_; |
| + |
| + DeliverNextEvent(); |
| +} |
| + |
| +} // namespace input_manager |