|  | // 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 "components/exo/sub_surface.h" | 
|  |  | 
|  | #include "base/logging.h" | 
|  | #include "base/trace_event/trace_event.h" | 
|  | #include "base/trace_event/trace_event_argument.h" | 
|  | #include "components/exo/surface.h" | 
|  |  | 
|  | namespace exo { | 
|  |  | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  | // SubSurface, public: | 
|  |  | 
|  | SubSurface::SubSurface(Surface* surface, Surface* parent) | 
|  | : surface_(surface), parent_(parent), is_synchronized_(true) { | 
|  | surface_->SetSurfaceDelegate(this); | 
|  | surface_->AddSurfaceObserver(this); | 
|  | parent_->AddSurfaceObserver(this); | 
|  | parent_->AddSubSurface(surface_); | 
|  | } | 
|  |  | 
|  | SubSurface::~SubSurface() { | 
|  | if (surface_) { | 
|  | if (parent_) | 
|  | parent_->RemoveSubSurface(surface_); | 
|  | surface_->SetSurfaceDelegate(nullptr); | 
|  | surface_->RemoveSurfaceObserver(this); | 
|  | } | 
|  | if (parent_) | 
|  | parent_->RemoveSurfaceObserver(this); | 
|  | } | 
|  |  | 
|  | void SubSurface::SetPosition(const gfx::Point& position) { | 
|  | TRACE_EVENT1("exo", "SubSurface::SetPosition", "position", | 
|  | position.ToString()); | 
|  |  | 
|  | if (!parent_ || !surface_) | 
|  | return; | 
|  |  | 
|  | parent_->SetSubSurfacePosition(surface_, position); | 
|  | } | 
|  |  | 
|  | void SubSurface::PlaceAbove(Surface* reference) { | 
|  | TRACE_EVENT1("exo", "SubSurface::PlaceAbove", "reference", | 
|  | reference->AsTracedValue()); | 
|  |  | 
|  | if (!parent_ || !surface_) | 
|  | return; | 
|  |  | 
|  | if (reference == surface_) { | 
|  | DLOG(WARNING) << "Client tried to place sub-surface above itself"; | 
|  | return; | 
|  | } | 
|  |  | 
|  | parent_->PlaceSubSurfaceAbove(surface_, reference); | 
|  | } | 
|  |  | 
|  | void SubSurface::PlaceBelow(Surface* sibling) { | 
|  | TRACE_EVENT1("exo", "SubSurface::PlaceBelow", "sibling", | 
|  | sibling->AsTracedValue()); | 
|  |  | 
|  | if (!parent_ || !surface_) | 
|  | return; | 
|  |  | 
|  | if (sibling == surface_) { | 
|  | DLOG(WARNING) << "Client tried to place sub-surface below itself"; | 
|  | return; | 
|  | } | 
|  |  | 
|  | parent_->PlaceSubSurfaceBelow(surface_, sibling); | 
|  | } | 
|  |  | 
|  | void SubSurface::SetCommitBehavior(bool synchronized) { | 
|  | TRACE_EVENT1("exo", "SubSurface::SetCommitBehavior", "synchronized", | 
|  | synchronized); | 
|  |  | 
|  | is_synchronized_ = synchronized; | 
|  | } | 
|  |  | 
|  | scoped_refptr<base::trace_event::TracedValue> SubSurface::AsTracedValue() | 
|  | const { | 
|  | scoped_refptr<base::trace_event::TracedValue> value = | 
|  | new base::trace_event::TracedValue; | 
|  | value->SetBoolean("is_synchronized", is_synchronized_); | 
|  | return value; | 
|  | } | 
|  |  | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  | // SurfaceDelegate overrides: | 
|  |  | 
|  | void SubSurface::OnSurfaceCommit() { | 
|  | // Early out if commit should be synchronized with parent. | 
|  | if (IsSurfaceSynchronized()) | 
|  | return; | 
|  |  | 
|  | surface_->CommitSurfaceHierarchy(); | 
|  | } | 
|  |  | 
|  | bool SubSurface::IsSurfaceSynchronized() const { | 
|  | // A sub-surface is effectively synchronized if either its parent is | 
|  | // synchronized or itself is in synchronized mode. | 
|  | if (is_synchronized_) | 
|  | return true; | 
|  |  | 
|  | return parent_ ? parent_->IsSynchronized() : false; | 
|  | } | 
|  |  | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  | // SurfaceObserver overrides: | 
|  |  | 
|  | void SubSurface::OnSurfaceDestroying(Surface* surface) { | 
|  | surface->RemoveSurfaceObserver(this); | 
|  | if (surface == parent_) { | 
|  | parent_ = nullptr; | 
|  | return; | 
|  | } | 
|  | DCHECK(surface == surface_); | 
|  | if (parent_) | 
|  | parent_->RemoveSubSurface(surface_); | 
|  | surface_ = nullptr; | 
|  | } | 
|  |  | 
|  | }  // namespace exo |