|  | // Copyright 2014 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/window_manager/view_target.h" | 
|  |  | 
|  | #include "mojo/converters/geometry/geometry_type_converters.h" | 
|  | #include "mojo/services/view_manager/public/cpp/view.h" | 
|  | #include "mojo/services/view_manager/public/cpp/view_property.h" | 
|  | #include "services/window_manager/view_targeter.h" | 
|  | #include "services/window_manager/window_manager_app.h" | 
|  | #include "ui/events/event.h" | 
|  | #include "ui/events/event_target_iterator.h" | 
|  | #include "ui/events/event_targeter.h" | 
|  | #include "ui/gfx/geometry/rect.h" | 
|  | #include "ui/gfx/point3_f.h" | 
|  | #include "ui/gfx/transform.h" | 
|  |  | 
|  | namespace window_manager { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | DEFINE_OWNED_VIEW_PROPERTY_KEY(ViewTarget, kViewTargetKey, nullptr); | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | ViewTarget::~ViewTarget() { | 
|  | } | 
|  |  | 
|  | // static | 
|  | ViewTarget* ViewTarget::TargetFromView(mojo::View* view) { | 
|  | if (!view) | 
|  | return nullptr; | 
|  |  | 
|  | ViewTarget* target = view->GetLocalProperty(kViewTargetKey); | 
|  | if (target) | 
|  | return target; | 
|  |  | 
|  | return new ViewTarget(view); | 
|  | } | 
|  |  | 
|  | void ViewTarget::ConvertPointToTarget(const ViewTarget* source, | 
|  | const ViewTarget* target, | 
|  | gfx::Point* point) { | 
|  | // TODO(erg): Do we need to deal with |source| and |target| being in | 
|  | // different trees? | 
|  | DCHECK_EQ(source->GetRoot(), target->GetRoot()); | 
|  | if (source == target) | 
|  | return; | 
|  |  | 
|  | const ViewTarget* root_target = source->GetRoot(); | 
|  | CHECK_EQ(root_target, target->GetRoot()); | 
|  |  | 
|  | if (source != root_target) | 
|  | source->ConvertPointForAncestor(root_target, point); | 
|  | if (target != root_target) | 
|  | target->ConvertPointFromAncestor(root_target, point); | 
|  | } | 
|  |  | 
|  | std::vector<ViewTarget*> ViewTarget::GetChildren() { | 
|  | std::vector<ViewTarget*> targets; | 
|  | for (mojo::View* child : view_->children()) | 
|  | targets.push_back(TargetFromView(child)); | 
|  | return targets; | 
|  | } | 
|  |  | 
|  | const ViewTarget* ViewTarget::GetParent() const { | 
|  | return TargetFromView(view_->parent()); | 
|  | } | 
|  |  | 
|  | gfx::Rect ViewTarget::GetBounds() const { | 
|  | return view_->bounds().To<gfx::Rect>(); | 
|  | } | 
|  |  | 
|  | bool ViewTarget::HasParent() const { | 
|  | return !!view_->parent(); | 
|  | } | 
|  |  | 
|  | bool ViewTarget::IsVisible() const { | 
|  | return view_->visible(); | 
|  | } | 
|  |  | 
|  | const ViewTarget* ViewTarget::GetRoot() const { | 
|  | const ViewTarget* root = this; | 
|  | for (const ViewTarget* parent = this; parent; parent = parent->GetParent()) | 
|  | root = parent; | 
|  | return root; | 
|  | } | 
|  |  | 
|  | scoped_ptr<ViewTargeter> ViewTarget::SetEventTargeter( | 
|  | scoped_ptr<ViewTargeter> targeter) { | 
|  | scoped_ptr<ViewTargeter> old_targeter = targeter_.Pass(); | 
|  | targeter_ = targeter.Pass(); | 
|  | return old_targeter.Pass(); | 
|  | } | 
|  |  | 
|  | bool ViewTarget::CanAcceptEvent(const ui::Event& event) { | 
|  | // We need to make sure that a touch cancel event and any gesture events it | 
|  | // creates can always reach the window. This ensures that we receive a valid | 
|  | // touch / gesture stream. | 
|  | if (event.IsEndingEvent()) | 
|  | return true; | 
|  |  | 
|  | if (!view_->visible()) | 
|  | return false; | 
|  |  | 
|  | // The top-most window can always process an event. | 
|  | if (!view_->parent()) | 
|  | return true; | 
|  |  | 
|  | // In aura, we only accept events if this is a key event or if the user | 
|  | // supplied a TargetHandler, usually the aura::WindowDelegate. Here, we're | 
|  | // just forwarding events to other Views which may be in other processes, so | 
|  | // always accept. | 
|  | return true; | 
|  | } | 
|  |  | 
|  | ui::EventTarget* ViewTarget::GetParentTarget() { | 
|  | return TargetFromView(view_->parent()); | 
|  | } | 
|  |  | 
|  | scoped_ptr<ui::EventTargetIterator> ViewTarget::GetChildIterator() { | 
|  | return scoped_ptr<ui::EventTargetIterator>( | 
|  | new ui::CopyingEventTargetIteratorImpl<ViewTarget>(GetChildren())); | 
|  | } | 
|  |  | 
|  | ui::EventTargeter* ViewTarget::GetEventTargeter() { | 
|  | return targeter_.get(); | 
|  | } | 
|  |  | 
|  | void ViewTarget::ConvertEventToTarget(ui::EventTarget* target, | 
|  | ui::LocatedEvent* event) { | 
|  | event->ConvertLocationToTarget(this, static_cast<ViewTarget*>(target)); | 
|  | } | 
|  |  | 
|  | ViewTarget::ViewTarget(mojo::View* view_to_wrap) : view_(view_to_wrap) { | 
|  | DCHECK(view_->GetLocalProperty(kViewTargetKey) == nullptr); | 
|  | view_->SetLocalProperty(kViewTargetKey, this); | 
|  | } | 
|  |  | 
|  | bool ViewTarget::ConvertPointForAncestor(const ViewTarget* ancestor, | 
|  | gfx::Point* point) const { | 
|  | gfx::Vector2d offset; | 
|  | bool result = GetTargetOffsetRelativeTo(ancestor, &offset); | 
|  | *point += offset; | 
|  | return result; | 
|  | } | 
|  |  | 
|  | bool ViewTarget::ConvertPointFromAncestor(const ViewTarget* ancestor, | 
|  | gfx::Point* point) const { | 
|  | gfx::Vector2d offset; | 
|  | bool result = GetTargetOffsetRelativeTo(ancestor, &offset); | 
|  | *point -= offset; | 
|  | return result; | 
|  | } | 
|  |  | 
|  | bool ViewTarget::GetTargetOffsetRelativeTo(const ViewTarget* ancestor, | 
|  | gfx::Vector2d* offset) const { | 
|  | const ViewTarget* v = this; | 
|  | for (; v && v != ancestor; v = v->GetParent()) { | 
|  | gfx::Rect bounds = v->GetBounds(); | 
|  | *offset += gfx::Vector2d(bounds.x(), bounds.y()); | 
|  | } | 
|  | return v == ancestor; | 
|  | } | 
|  |  | 
|  | }  // namespace window_manager |