diff options
author | tedchoc@chromium.org <tedchoc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-16 03:58:38 +0000 |
---|---|---|
committer | tedchoc@chromium.org <tedchoc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-16 03:58:38 +0000 |
commit | 3ba4cae36f9c80067c103809fa3f65ad18c7f2d5 (patch) | |
tree | d62946f6f8e8a15cc76d37fe8f2c89117a6b35d8 | |
parent | dc87a404f3c9f0d64df6fc208b9857e8d115eba3 (diff) | |
download | chromium_src-3ba4cae36f9c80067c103809fa3f65ad18c7f2d5.zip chromium_src-3ba4cae36f9c80067c103809fa3f65ad18c7f2d5.tar.gz chromium_src-3ba4cae36f9c80067c103809fa3f65ad18c7f2d5.tar.bz2 |
Add support for calculating the position of the top controls in the cc layer.
Provides a means for keeping the top controls in sync with the currently
renderered frame, which will allow us to move the top controls around the
screen.
BUG=161303
Review URL: https://chromiumcodereview.appspot.com/11552009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@177081 0039d316-1c4b-4281-b951-d872f2087c98
28 files changed, 635 insertions, 18 deletions
@@ -280,6 +280,9 @@ 'time_source.h', 'timing_function.cc', 'timing_function.h', + 'top_controls_manager.cc', + 'top_controls_manager.h', + 'top_controls_manager_client.h', 'transferable_resource.cc', 'transferable_resource.h', 'tree_synchronizer.cc', diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index 9b427e2..2c16988 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp @@ -62,6 +62,7 @@ 'tiled_layer_impl_unittest.cc', 'tiled_layer_unittest.cc', 'tiling_data_unittest.cc', + 'top_controls_manager_unittest.cc', 'tree_synchronizer_unittest.cc', 'timing_function_unittest.cc', 'test/fake_web_graphics_context_3d_unittest.cc', diff --git a/cc/compositor_frame_metadata.h b/cc/compositor_frame_metadata.h index 92a48ff..5d9a905 100644 --- a/cc/compositor_frame_metadata.h +++ b/cc/compositor_frame_metadata.h @@ -29,9 +29,10 @@ class CC_EXPORT CompositorFrameMetadata float min_page_scale_factor; float max_page_scale_factor; - // Used to position the Android location top bar, whose precise - // position is computed by the renderer compositor. + // Used to position the Android location top bar and page content, whose + // precise position is computed by the renderer compositor. gfx::Vector2dF location_bar_offset; + gfx::Vector2dF location_bar_content_translation; }; } // namespace cc diff --git a/cc/layer_tree_host.cc b/cc/layer_tree_host.cc index 008e251..b2f930a 100644 --- a/cc/layer_tree_host.cc +++ b/cc/layer_tree_host.cc @@ -28,6 +28,7 @@ #include "cc/switches.h" #include "cc/thread.h" #include "cc/thread_proxy.h" +#include "cc/top_controls_manager.h" #include "cc/tree_synchronizer.h" namespace { @@ -298,6 +299,9 @@ void LayerTreeHost::finishCommitOnImplThread(LayerTreeHostImpl* hostImpl) hostImpl->setPageScaleFactorAndLimits(m_pageScaleFactor, m_minPageScaleFactor, m_maxPageScaleFactor); hostImpl->setDebugState(m_debugState); + if (m_settings.calculateTopControlsPosition && m_topControlsContentLayer && hostImpl->topControlsManager()) + hostImpl->topControlsManager()->set_content_layer_id(m_topControlsContentLayer->id()); + m_commitNumber++; } @@ -436,6 +440,8 @@ void LayerTreeHost::setRootLayer(scoped_refptr<Layer> rootLayer) if (m_hudLayer) m_hudLayer->removeFromParent(); + if (m_topControlsContentLayer) + m_topControlsContentLayer->removeFromParent(); setNeedsFullTreeSync(); } @@ -532,6 +538,22 @@ void LayerTreeHost::updateLayers(ResourceUpdateQueue& queue, size_t memoryAlloca if (memoryAllocationLimitBytes) m_contentsTextureManager->setMaxMemoryLimitBytes(memoryAllocationLimitBytes); + if (m_settings.calculateTopControlsPosition) { + if (!m_topControlsContentLayer) { + m_topControlsContentLayer = Layer::create(); + m_topControlsContentLayer->setIsDrawable(false); + m_topControlsContentLayer->setDebugName("Top Controls Content"); + } + + // Insert a layer that allows the top controls manager to move around + // the content without clobbering/being clobbered by other transforms. + if (!LayerTreeHostCommon::findLayerInSubtree(m_rootLayer.get(), m_topControlsContentLayer->id())) { + m_topControlsContentLayer->setLayerTreeHost(m_rootLayer->layerTreeHost()); + m_topControlsContentLayer->setChildren(m_rootLayer->children()); + m_rootLayer->addChild(m_topControlsContentLayer); + } + } + updateLayers(rootLayer(), queue); } diff --git a/cc/layer_tree_host.h b/cc/layer_tree_host.h index a86bde7..70c8cf4 100644 --- a/cc/layer_tree_host.h +++ b/cc/layer_tree_host.h @@ -247,6 +247,7 @@ private: scoped_refptr<Layer> m_rootLayer; scoped_refptr<HeadsUpDisplayLayer> m_hudLayer; + scoped_refptr<Layer> m_topControlsContentLayer; scoped_ptr<PrioritizedResourceManager> m_contentsTextureManager; scoped_ptr<PrioritizedResource> m_surfaceMemoryPlaceholder; diff --git a/cc/layer_tree_host_impl.cc b/cc/layer_tree_host_impl.cc index 22e08a1..fa0aba2 100644 --- a/cc/layer_tree_host_impl.cc +++ b/cc/layer_tree_host_impl.cc @@ -37,6 +37,7 @@ #include "cc/software_renderer.h" #include "cc/solid_color_draw_quad.h" #include "cc/texture_uploader.h" +#include "cc/top_controls_manager.h" #include "cc/util.h" #include "ui/gfx/size_conversions.h" #include "ui/gfx/vector2d_conversions.h" @@ -155,6 +156,9 @@ LayerTreeHostImpl::LayerTreeHostImpl(const LayerTreeSettings& settings, LayerTre DCHECK(m_proxy->isImplThread()); didVisibilityChange(this, m_visible); + if (settings.calculateTopControlsPosition) + m_topControlsManager = TopControlsManager::Create(this, settings.topControlsHeightPx); + // LTHI always has an active tree. m_activeTree = LayerTreeImpl::create(this); } @@ -230,6 +234,8 @@ void LayerTreeHostImpl::animate(base::TimeTicks monotonicTime, base::Time wallCl animatePageScale(monotonicTime); animateLayers(monotonicTime, wallClockTime); animateScrollbars(monotonicTime); + if (m_topControlsManager) + m_topControlsManager->Animate(monotonicTime); } void LayerTreeHostImpl::manageTiles() @@ -331,6 +337,8 @@ void LayerTreeHostImpl::updateDrawProperties() return; } + if (m_topControlsManager) + m_topControlsManager->UpdateDrawPositions(); activeTree()->UpdateDrawProperties(); if (pendingTree()) pendingTree()->UpdateDrawProperties(); @@ -766,6 +774,10 @@ CompositorFrameMetadata LayerTreeHostImpl::makeCompositorFrameMetadata() const metadata.root_layer_size = contentSize(); metadata.min_page_scale_factor = m_pinchZoomViewport.min_page_scale_factor(); metadata.max_page_scale_factor = m_pinchZoomViewport.max_page_scale_factor(); + if (m_topControlsManager) { + metadata.location_bar_offset = gfx::Vector2dF(0.f, m_topControlsManager->controls_top_offset()); + metadata.location_bar_content_translation = gfx::Vector2dF(0.f, m_topControlsManager->content_top_offset()); + } if (!rootScrollLayer()) return metadata; @@ -899,6 +911,11 @@ static LayerImpl* findScrollLayerForContentLayer(LayerImpl* layerImpl) return 0; } +LayerTreeImpl* LayerTreeHostImpl::activeTree() +{ + return m_activeTree.get(); +} + void LayerTreeHostImpl::createPendingTree() { CHECK(!m_pendingTree); @@ -1102,6 +1119,11 @@ void LayerTreeHostImpl::updateMaxScrollOffset() pendingTree()->UpdateMaxScrollOffset(); } +void LayerTreeHostImpl::setNeedsUpdateDrawProperties() +{ + m_needsUpdateDrawProperties = true; +} + void LayerTreeHostImpl::setNeedsRedraw() { m_client->setNeedsRedrawOnImplThread(); @@ -1117,6 +1139,9 @@ InputHandlerClient::ScrollStatus LayerTreeHostImpl::scrollBegin(gfx::Point viewp { TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBegin"); + if (m_topControlsManager) + m_topControlsManager->ScrollBegin(); + DCHECK(!currentlyScrollingLayer()); clearCurrentlyScrollingLayer(); @@ -1249,6 +1274,9 @@ bool LayerTreeHostImpl::scrollBy(const gfx::Point& viewportPoint, if (m_settings.pageScalePinchZoomEnabled && layerImpl == rootScrollLayer()) viewport = &m_pinchZoomViewport; gfx::Vector2dF appliedDelta; + if (m_topControlsManager && layerImpl == rootScrollLayer()) + pendingDelta = m_topControlsManager->ScrollBy(pendingDelta); + if (m_scrollDeltaIsInViewportSpace) { float scaleFromViewportToScreenSpace = m_deviceScaleFactor; appliedDelta = scrollLayerWithViewportSpaceDelta(viewport, *layerImpl, scaleFromViewportToScreenSpace, viewportPoint, pendingDelta); @@ -1293,6 +1321,8 @@ void LayerTreeHostImpl::clearCurrentlyScrollingLayer() void LayerTreeHostImpl::scrollEnd() { + if (m_topControlsManager) + m_topControlsManager->ScrollEnd(); clearCurrentlyScrollingLayer(); } diff --git a/cc/layer_tree_host_impl.h b/cc/layer_tree_host_impl.h index d3a5858..ad97893 100644 --- a/cc/layer_tree_host_impl.h +++ b/cc/layer_tree_host_impl.h @@ -18,6 +18,7 @@ #include "cc/render_pass_sink.h" #include "cc/renderer.h" #include "cc/tile_manager.h" +#include "cc/top_controls_manager_client.h" #include "skia/ext/refptr.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkPicture.h" @@ -35,6 +36,7 @@ class LayerTreeImpl; class PageScaleAnimation; class RenderPassDrawQuad; class ResourceProvider; +class TopControlsManager; struct RendererCapabilities; struct RenderingStats; @@ -59,7 +61,8 @@ public: class CC_EXPORT LayerTreeHostImpl : public InputHandlerClient, public RendererClient, public TileManagerClient, - public OutputSurfaceClient { + public OutputSurfaceClient, + public TopControlsManagerClient { typedef std::vector<LayerImpl*> LayerList; public: @@ -77,6 +80,11 @@ public: virtual void scheduleAnimation() OVERRIDE; virtual bool haveTouchEventHandlersAt(const gfx::Point&) OVERRIDE; + // TopControlsManagerClient implementation. + virtual LayerTreeImpl* activeTree() OVERRIDE; + virtual void setNeedsUpdateDrawProperties() OVERRIDE; + virtual void setNeedsRedraw() OVERRIDE; + struct CC_EXPORT FrameData : public RenderPassSink { FrameData(); ~FrameData(); @@ -150,7 +158,6 @@ public: void readback(void* pixels, const gfx::Rect&); - LayerTreeImpl* activeTree() { return m_activeTree.get(); } const LayerTreeImpl* activeTree() const { return m_activeTree.get(); } LayerTreeImpl* pendingTree() { return m_pendingTree.get(); } const LayerTreeImpl* pendingTree() const { return m_pendingTree.get(); } @@ -188,9 +195,6 @@ public: bool needsAnimateLayers() const { return !m_animationRegistrar->active_animation_controllers().empty(); } bool needsUpdateDrawProperties() const { return m_needsUpdateDrawProperties; } - void setNeedsUpdateDrawProperties() { m_needsUpdateDrawProperties = true; } - - void setNeedsRedraw(); void renderingStats(RenderingStats*) const; @@ -202,6 +206,7 @@ public: FrameRateCounter* fpsCounter() const { return m_fpsCounter.get(); } DebugRectHistory* debugRectHistory() const { return m_debugRectHistory.get(); } ResourceProvider* resourceProvider() const { return m_resourceProvider.get(); } + TopControlsManager* topControlsManager() const { return m_topControlsManager.get(); } Proxy* proxy() const { return m_proxy; } @@ -318,6 +323,8 @@ private: bool m_pinchGestureActive; gfx::Point m_previousPinchAnchor; + scoped_ptr<TopControlsManager> m_topControlsManager; + scoped_ptr<PageScaleAnimation> m_pageScaleAnimation; // This is used for ticking animations slowly when hidden. diff --git a/cc/layer_tree_settings.cc b/cc/layer_tree_settings.cc index 70f2b2c..e0ea66b 100644 --- a/cc/layer_tree_settings.cc +++ b/cc/layer_tree_settings.cc @@ -27,11 +27,13 @@ LayerTreeSettings::LayerTreeSettings() , canUseLCDText(true) , shouldClearRootRenderPass(true) , useLinearFadeScrollbarAnimator(false) + , calculateTopControlsPosition(false) , minimumContentsScale(0.0625f) , lowResContentsScaleFactor(0.125f) , refreshRate(0) , maxPartialTextureUpdates(std::numeric_limits<size_t>::max()) , numRasterThreads(1) + , topControlsHeightPx(0) , defaultTileSize(gfx::Size(256, 256)) , maxUntiledLayerSize(gfx::Size(512, 512)) , minimumOcclusionTrackingSize(gfx::Size(160, 160)) diff --git a/cc/layer_tree_settings.h b/cc/layer_tree_settings.h index 375cbf6..76aa463 100644 --- a/cc/layer_tree_settings.h +++ b/cc/layer_tree_settings.h @@ -30,11 +30,13 @@ class CC_EXPORT LayerTreeSettings { bool canUseLCDText; bool shouldClearRootRenderPass; bool useLinearFadeScrollbarAnimator; + bool calculateTopControlsPosition; float minimumContentsScale; float lowResContentsScaleFactor; double refreshRate; size_t maxPartialTextureUpdates; size_t numRasterThreads; + int topControlsHeightPx; gfx::Size defaultTileSize; gfx::Size maxUntiledLayerSize; gfx::Size minimumOcclusionTrackingSize; diff --git a/cc/switches.cc b/cc/switches.cc index 2cbb459..cba392d 100644 --- a/cc/switches.cc +++ b/cc/switches.cc @@ -24,6 +24,12 @@ const char kEnablePartialSwap[] = "enable-partial-swap"; const char kEnablePerTilePainting[] = "enable-per-tile-painting"; +const char kEnableTopControlsPositionCalculation[] = + "enable-top-controls-position-calculation"; + +// The height of the movable top controls in screen pixels. +const char kTopControlsHeight[] = "top-controls-height"; + // Number of worker threads used to rasterize content. const char kNumRasterThreads[] = "num-raster-threads"; diff --git a/cc/switches.h b/cc/switches.h index e3797bb..e36b01d 100644 --- a/cc/switches.h +++ b/cc/switches.h @@ -21,6 +21,7 @@ CC_EXPORT extern const char kEnableCompositorFrameMessage[]; CC_EXPORT extern const char kEnableImplSidePainting[]; CC_EXPORT extern const char kEnablePartialSwap[]; CC_EXPORT extern const char kEnablePerTilePainting[]; +CC_EXPORT extern const char kEnableTopControlsPositionCalculation[]; CC_EXPORT extern const char kJankInsteadOfCheckerboard[]; CC_EXPORT extern const char kNumRasterThreads[]; CC_EXPORT extern const char kShowPropertyChangedRects[]; @@ -30,6 +31,7 @@ CC_EXPORT extern const char kShowReplicaScreenSpaceRects[]; CC_EXPORT extern const char kShowOccludingRects[]; CC_EXPORT extern const char kShowNonOccludingRects[]; CC_EXPORT extern const char kTraceOverdraw[]; +CC_EXPORT extern const char kTopControlsHeight[]; } // namespace switches } // namespace cc diff --git a/cc/top_controls_manager.cc b/cc/top_controls_manager.cc new file mode 100644 index 0000000..cdb59e9 --- /dev/null +++ b/cc/top_controls_manager.cc @@ -0,0 +1,194 @@ +// Copyright 2013 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 "cc/top_controls_manager.h" + +#include <algorithm> + +#include "base/logging.h" +#include "base/time.h" +#include "cc/keyframed_animation_curve.h" +#include "cc/layer_tree_impl.h" +#include "cc/timing_function.h" +#include "cc/top_controls_manager_client.h" +#include "ui/gfx/transform.h" +#include "ui/gfx/vector2d_f.h" + +namespace cc { +namespace { +// These constants were chosen empirically for their visually pleasant behavior. +// Contact tedchoc@chromium.org for questions about changing these values. +const float kShowHideThreshold = 0.75f; +const int64 kShowHideMaxDurationMs = 250; +} + +// static +scoped_ptr<TopControlsManager> TopControlsManager::Create( + TopControlsManagerClient* client, float top_controls_height) { + return make_scoped_ptr(new TopControlsManager(client, top_controls_height)); +} + +TopControlsManager::TopControlsManager(TopControlsManagerClient* client, + float top_controls_height) + : client_(client), + content_layer_id_(0), + is_overlay_mode_(false), + top_controls_height_(top_controls_height), + controls_top_offset_(0), + content_top_offset_(top_controls_height), + previous_root_scroll_offset_(0.f), + scroll_readjustment_enabled_(false), + is_showing_animation_(false) { + CHECK(client_); +} + +TopControlsManager::~TopControlsManager() { +} + +void TopControlsManager::UpdateDrawPositions() { + if (!RootScrollLayer()) + return; + + // If the scroll position has changed underneath us (i.e. a javascript + // scroll), then simulate a scroll that covers the delta. + float scroll_total_y = RootScrollLayerTotalScrollY(); + if (scroll_readjustment_enabled_ + && scroll_total_y != previous_root_scroll_offset_) { + ScrollBy(gfx::Vector2dF(0, scroll_total_y - previous_root_scroll_offset_)); + StartAnimationIfNecessary(); + previous_root_scroll_offset_ = RootScrollLayerTotalScrollY(); + } + + float offset_top = is_overlay_mode_ ? 0 : content_top_offset_; + + LayerImpl* content_layer = + client_->activeTree()->FindActiveTreeLayerById(content_layer_id_); + DCHECK(content_layer); + if (content_layer) { + gfx::Transform transform; + transform.Translate(0, offset_top); + content_layer->setTransform(transform); + } + + // TODO(tedchoc): Adjust fixed position layers as well. +} + +void TopControlsManager::ScrollBegin() { + ResetAnimations(); + scroll_readjustment_enabled_ = false; +} + +gfx::Vector2dF TopControlsManager::ScrollBy( + const gfx::Vector2dF pending_delta) { + ResetAnimations(); + return ScrollInternal(pending_delta); +} + +gfx::Vector2dF TopControlsManager::ScrollInternal( + const gfx::Vector2dF pending_delta) { + float scroll_total_y = RootScrollLayerTotalScrollY(); + float scroll_delta_y = pending_delta.y(); + + float previous_controls_offset = controls_top_offset_; + float previous_content_offset = content_top_offset_; + bool previous_was_overlay = is_overlay_mode_; + + controls_top_offset_ -= scroll_delta_y; + controls_top_offset_ = std::min( + std::max(controls_top_offset_, -top_controls_height_), 0.f); + + if (scroll_total_y > 0 || (scroll_total_y == 0 + && content_top_offset_ < scroll_delta_y)) { + is_overlay_mode_ = true; + content_top_offset_ = 0; + } else if (scroll_total_y <= 0 && (scroll_delta_y < 0 + || (scroll_delta_y > 0 && content_top_offset_ > 0))) { + is_overlay_mode_ = false; + content_top_offset_ -= scroll_delta_y; + } + content_top_offset_ = std::max( + std::min(content_top_offset_, + controls_top_offset_ + top_controls_height_), 0.f); + + gfx::Vector2dF applied_delta; + if (!previous_was_overlay) + applied_delta.set_y(previous_content_offset - content_top_offset_); + + if (is_overlay_mode_ != previous_was_overlay + || previous_controls_offset != controls_top_offset_ + || previous_content_offset != content_top_offset_) { + client_->setNeedsRedraw(); + client_->setNeedsUpdateDrawProperties(); + } + + return pending_delta - applied_delta; +} + +void TopControlsManager::ScrollEnd() { + StartAnimationIfNecessary(); + previous_root_scroll_offset_ = RootScrollLayerTotalScrollY(); + scroll_readjustment_enabled_ = true; +} + +void TopControlsManager::Animate(base::TimeTicks monotonic_time) { + if (!top_controls_animation_ || !RootScrollLayer()) + return; + + double time = (monotonic_time - base::TimeTicks()).InMillisecondsF(); + float new_offset = top_controls_animation_->getValue(time); + gfx::Vector2dF scroll_vector(0.f, -(new_offset - controls_top_offset_)); + ScrollInternal(scroll_vector); + client_->setNeedsRedraw(); + + if ((is_showing_animation_ && new_offset >= 0) || + (!is_showing_animation_ && new_offset <= -top_controls_height_)) { + top_controls_animation_.reset(); + StartAnimationIfNecessary(); + } +} + +void TopControlsManager::ResetAnimations() { + if (top_controls_animation_) + top_controls_animation_.reset(); +} + +LayerImpl* TopControlsManager::RootScrollLayer() { + return client_->activeTree()->root_scroll_layer(); +} + +float TopControlsManager::RootScrollLayerTotalScrollY() { + LayerImpl* layer = RootScrollLayer(); + if (!layer) + return 0; + gfx::Vector2dF scroll_total = layer->scrollOffset() + layer->scrollDelta(); + return scroll_total.y(); +} + +void TopControlsManager::SetupAnimation(bool show_controls) { + top_controls_animation_ = KeyframedFloatAnimationCurve::create(); + double start_time = + (base::TimeTicks::Now() - base::TimeTicks()).InMillisecondsF(); + top_controls_animation_->addKeyframe( + FloatKeyframe::create(start_time, controls_top_offset_, + scoped_ptr<TimingFunction>())); + float max_ending_offset = (show_controls ? 1 : -1) * top_controls_height_; + top_controls_animation_->addKeyframe( + FloatKeyframe::create(start_time + kShowHideMaxDurationMs, + controls_top_offset_ + max_ending_offset, + EaseTimingFunction::create())); + is_showing_animation_ = show_controls; +} + +void TopControlsManager::StartAnimationIfNecessary() { + float scroll_total_y = RootScrollLayerTotalScrollY(); + + if (controls_top_offset_ != 0 + && controls_top_offset_ != -top_controls_height_) { + SetupAnimation( + controls_top_offset_ >= -(top_controls_height_ * kShowHideThreshold)); + client_->setNeedsRedraw(); + } +} + +} // namespace cc diff --git a/cc/top_controls_manager.h b/cc/top_controls_manager.h new file mode 100644 index 0000000..37d1670 --- /dev/null +++ b/cc/top_controls_manager.h @@ -0,0 +1,77 @@ +// Copyright 2013 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. + +#ifndef CC_TOP_CONTROLS_MANAGER_H_ +#define CC_TOP_CONTROLS_MANAGER_H_ + +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "cc/layer_impl.h" +#include "ui/gfx/size.h" +#include "ui/gfx/vector2d_f.h" + +namespace base { +class TimeTicks; +} + +namespace cc { + +class KeyframedFloatAnimationCurve; +class LayerTreeImpl; +class TopControlsManagerClient; + +// Manages the position of the top controls. +class CC_EXPORT TopControlsManager { + public: + static scoped_ptr<TopControlsManager> Create(TopControlsManagerClient* client, + float top_controls_height); + virtual ~TopControlsManager(); + + void set_content_layer_id(int id) { content_layer_id_ = id; } + float controls_top_offset() { return controls_top_offset_; } + float content_top_offset() { return content_top_offset_; } + float is_overlay_mode() { return is_overlay_mode_; } + KeyframedFloatAnimationCurve* animation() { + return top_controls_animation_.get(); + } + + void UpdateDrawPositions(); + + void ScrollBegin(); + gfx::Vector2dF ScrollBy(const gfx::Vector2dF pending_delta); + void ScrollEnd(); + + void Animate(base::TimeTicks monotonic_time); + + protected: + TopControlsManager(TopControlsManagerClient* client, + float top_controls_height); + + private: + gfx::Vector2dF ScrollInternal(const gfx::Vector2dF pending_delta); + void ResetAnimations(); + LayerImpl* RootScrollLayer(); + float RootScrollLayerTotalScrollY(); + void SetupAnimation(bool show_controls); + void StartAnimationIfNecessary(); + + TopControlsManagerClient* client_; // The client manages the lifecycle of + // this. + + scoped_ptr<KeyframedFloatAnimationCurve> top_controls_animation_; + int content_layer_id_; + bool is_showing_animation_; + bool is_overlay_mode_; + float controls_top_offset_; + float content_top_offset_; + float top_controls_height_; + bool scroll_readjustment_enabled_; + float previous_root_scroll_offset_; + + DISALLOW_COPY_AND_ASSIGN(TopControlsManager); +}; + +} // namespace cc + +#endif // CC_TOP_CONTROLS_MANAGER_H_ diff --git a/cc/top_controls_manager_client.h b/cc/top_controls_manager_client.h new file mode 100644 index 0000000..f5a34f3 --- /dev/null +++ b/cc/top_controls_manager_client.h @@ -0,0 +1,24 @@ +// Copyright 2013 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. + +#ifndef CC_TOP_CONTROLS_MANAGER_CLIENT_H_ +#define CC_TOP_CONTROLS_MANAGER_CLIENT_H_ + +namespace cc { + +class LayerTreeImpl; + +class CC_EXPORT TopControlsManagerClient { + public: + virtual void setNeedsRedraw() = 0; + virtual void setNeedsUpdateDrawProperties() = 0; + virtual LayerTreeImpl* activeTree() = 0; + + protected: + virtual ~TopControlsManagerClient() {} +}; + +} // namespace cc + +#endif // CC_TOP_CONTROLS_MANAGER_CLIENT_H_ diff --git a/cc/top_controls_manager_unittest.cc b/cc/top_controls_manager_unittest.cc new file mode 100644 index 0000000..d081042 --- /dev/null +++ b/cc/top_controls_manager_unittest.cc @@ -0,0 +1,203 @@ +// Copyright 2013 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 "cc/top_controls_manager.h" + +#include "base/memory/scoped_ptr.h" +#include "base/time.h" +#include "cc/layer_impl.h" +#include "cc/layer_tree_impl.h" +#include "cc/test/fake_impl_proxy.h" +#include "cc/test/fake_layer_tree_host_impl.h" +#include "cc/top_controls_manager_client.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/vector2d_f.h" + +namespace cc { +namespace { + +static const float kTopControlsHeight = 100; + +class MockTopControlsManagerClient : public TopControlsManagerClient { + public: + MockTopControlsManagerClient() + : host_impl_(&proxy_), + redraw_needed_(false), + update_draw_properties_needed_(false) { + active_tree_ = LayerTreeImpl::create(&host_impl_); + root_scroll_layer_ = LayerImpl::create(active_tree_.get(), 1); + active_tree_->set_root_scroll_layer(root_scroll_layer_.get()); + } + + virtual ~MockTopControlsManagerClient() {} + + virtual void setNeedsRedraw() OVERRIDE { + redraw_needed_ = true; + } + + virtual void setNeedsUpdateDrawProperties() OVERRIDE { + update_draw_properties_needed_ = true; + } + + virtual LayerTreeImpl* activeTree() OVERRIDE { + return active_tree_.get(); + } + + TopControlsManager* manager() { + if (!manager_) + manager_ = TopControlsManager::Create(this, kTopControlsHeight); + return manager_.get(); + } + + LayerImpl* rootScrollLayer() { + return root_scroll_layer_.get(); + } + + private: + FakeImplProxy proxy_; + FakeLayerTreeHostImpl host_impl_; + scoped_ptr<LayerTreeImpl> active_tree_; + scoped_ptr<LayerImpl> root_scroll_layer_; + scoped_ptr<TopControlsManager> manager_; + bool redraw_needed_; + bool update_draw_properties_needed_; +}; + +TEST(TopControlsManagerTest, overlayModeDetection) { + MockTopControlsManagerClient client; + TopControlsManager* manager = client.manager(); + client.rootScrollLayer()->setScrollDelta(gfx::Vector2dF(0.f, 0.f)); + + gfx::Vector2dF remaining_scroll = manager->ScrollBy( + gfx::Vector2dF(0.f, 30.f)); + EXPECT_EQ(0.f, remaining_scroll.y()); + EXPECT_EQ(-30.f, manager->controls_top_offset()); + EXPECT_EQ(70.f, manager->content_top_offset()); + EXPECT_FALSE(manager->is_overlay_mode()); + client.rootScrollLayer()->setScrollDelta( + client.rootScrollLayer()->scrollDelta() + remaining_scroll); + + remaining_scroll = manager->ScrollBy(gfx::Vector2dF(0.f, 69.f)); + EXPECT_EQ(0.f, remaining_scroll.y()); + EXPECT_EQ(-99.f, manager->controls_top_offset()); + EXPECT_EQ(1.f, manager->content_top_offset()); + EXPECT_FALSE(manager->is_overlay_mode()); + client.rootScrollLayer()->setScrollDelta( + client.rootScrollLayer()->scrollDelta() + remaining_scroll); + + remaining_scroll = manager->ScrollBy(gfx::Vector2dF(0.f, -20.f)); + EXPECT_EQ(0.f, remaining_scroll.y()); + EXPECT_EQ(-79.f, manager->controls_top_offset()); + EXPECT_EQ(21.f, manager->content_top_offset()); + EXPECT_FALSE(manager->is_overlay_mode()); + client.rootScrollLayer()->setScrollDelta( + client.rootScrollLayer()->scrollDelta() + remaining_scroll); + + // Scroll to the toggle point + remaining_scroll = manager->ScrollBy(gfx::Vector2dF(0.f, 21.f)); + EXPECT_EQ(0.f, remaining_scroll.y()); + EXPECT_EQ(-100.f, manager->controls_top_offset()); + EXPECT_EQ(0.f, manager->content_top_offset()); + EXPECT_FALSE(manager->is_overlay_mode()); + client.rootScrollLayer()->setScrollDelta( + client.rootScrollLayer()->scrollDelta() + remaining_scroll); + + remaining_scroll = manager->ScrollBy(gfx::Vector2dF(0.f, 1.f)); + EXPECT_EQ(1.f, remaining_scroll.y()); + EXPECT_EQ(-100.f, manager->controls_top_offset()); + EXPECT_EQ(0.f, manager->content_top_offset()); + EXPECT_TRUE(manager->is_overlay_mode()); + client.rootScrollLayer()->setScrollDelta( + client.rootScrollLayer()->scrollDelta() + remaining_scroll); + + remaining_scroll = manager->ScrollBy(gfx::Vector2dF(0.f, -1.f)); + EXPECT_EQ(-1.f, remaining_scroll.y()); + EXPECT_EQ(-99.f, manager->controls_top_offset()); + EXPECT_EQ(0.f, manager->content_top_offset()); + EXPECT_TRUE(manager->is_overlay_mode()); + client.rootScrollLayer()->setScrollDelta( + client.rootScrollLayer()->scrollDelta() + remaining_scroll); + + remaining_scroll = manager->ScrollBy(gfx::Vector2dF(0.f, -50.f)); + EXPECT_EQ(-50.f, remaining_scroll.y()); + EXPECT_EQ(-49.f, manager->controls_top_offset()); + EXPECT_EQ(50.f, manager->content_top_offset()); + EXPECT_FALSE(manager->is_overlay_mode()); + client.rootScrollLayer()->setScrollDelta( + client.rootScrollLayer()->scrollDelta() + remaining_scroll); + + remaining_scroll = manager->ScrollBy(gfx::Vector2dF(0.f, -50.f)); + EXPECT_EQ(0.f, manager->controls_top_offset()); + EXPECT_EQ(100.f, manager->content_top_offset()); + EXPECT_FALSE(manager->is_overlay_mode()); + client.rootScrollLayer()->setScrollDelta( + client.rootScrollLayer()->scrollDelta() + remaining_scroll); +} + +TEST(TopControlsManagerTest, partialShownHideAnimation) { + MockTopControlsManagerClient client; + TopControlsManager* manager = client.manager(); + client.rootScrollLayer()->setScrollOffset(gfx::Vector2d(0, 300)); + manager->ScrollBy(gfx::Vector2dF(0.f, 300.f)); + EXPECT_EQ(-100.f, manager->controls_top_offset()); + EXPECT_EQ(0.f, manager->content_top_offset()); + EXPECT_TRUE(manager->is_overlay_mode()); + + client.rootScrollLayer()->setScrollOffset(gfx::Vector2d(0, 270)); + manager->ScrollBy(gfx::Vector2dF(0.f, -15.f)); + EXPECT_EQ(-85.f, manager->controls_top_offset()); + EXPECT_EQ(0.f, manager->content_top_offset()); + EXPECT_TRUE(manager->is_overlay_mode()); + + manager->ScrollEnd(); + EXPECT_TRUE(manager->animation()); + + base::TimeTicks time = base::TimeTicks::Now(); + float previous_offset = manager->controls_top_offset(); + while(manager->animation()) { + time = base::TimeDelta::FromMicroseconds(100) + time; + manager->Animate(time); + EXPECT_LT(manager->controls_top_offset(), previous_offset); + previous_offset = manager->controls_top_offset(); + } + EXPECT_FALSE(manager->animation()); + EXPECT_EQ(-100.f, manager->controls_top_offset()); + EXPECT_EQ(0.f, manager->content_top_offset()); + EXPECT_TRUE(manager->is_overlay_mode()); +} + +TEST(TopControlsManagerTest, partialShownShowAnimation) { + MockTopControlsManagerClient client; + TopControlsManager* manager = client.manager(); + client.rootScrollLayer()->setScrollOffset(gfx::Vector2d(0, 300)); + manager->ScrollBy(gfx::Vector2dF(0.f, 300.f)); + EXPECT_EQ(-100.f, manager->controls_top_offset()); + EXPECT_EQ(0.f, manager->content_top_offset()); + EXPECT_TRUE(manager->is_overlay_mode()); + + client.rootScrollLayer()->setScrollOffset(gfx::Vector2d(0, 230)); + manager->ScrollBy(gfx::Vector2dF(0.f, -70.f)); + EXPECT_EQ(-30.f, manager->controls_top_offset()); + EXPECT_EQ(0.f, manager->content_top_offset()); + EXPECT_TRUE(manager->is_overlay_mode()); + + manager->ScrollEnd(); + EXPECT_TRUE(manager->animation()); + + base::TimeTicks time = base::TimeTicks::Now(); + float previous_offset = manager->controls_top_offset(); + while(manager->animation()) { + time = base::TimeDelta::FromMicroseconds(100) + time; + manager->Animate(time); + EXPECT_GT(manager->controls_top_offset(), previous_offset); + previous_offset = manager->controls_top_offset(); + } + EXPECT_FALSE(manager->animation()); + EXPECT_EQ(0.f, manager->controls_top_offset()); + EXPECT_EQ(0.f, manager->content_top_offset()); + EXPECT_TRUE(manager->is_overlay_mode()); +} + +} // namespace +} // namespace cc diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index beb8bd3..f48bb5a 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc @@ -173,6 +173,8 @@ void CompositorImpl::SetVisible(bool visible) { cc::LayerTreeSettings settings; settings.refreshRate = 60.0; settings.implSidePainting = false; + settings.calculateTopControlsPosition = false; + settings.topControlsHeightPx = 0; // Do not clear the framebuffer when rendering into external GL contexts // like Android View System's. diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index d3bdd80..7c6759ab104 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -853,6 +853,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( cc::switches::kEnableCompositorFrameMessage, cc::switches::kEnableImplSidePainting, cc::switches::kEnablePartialSwap, + cc::switches::kEnableTopControlsPositionCalculation, cc::switches::kNumRasterThreads, cc::switches::kShowPropertyChangedRects, cc::switches::kShowSurfaceDamageRects, @@ -861,6 +862,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( cc::switches::kShowNonOccludingRects, cc::switches::kShowOccludingRects, cc::switches::kTraceOverdraw, + cc::switches::kTopControlsHeight, }; renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames, arraysize(kSwitchNames)); diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 3a79854..2716c2e 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc @@ -1522,7 +1522,9 @@ void RenderWidgetHostImpl::OnSwapCompositorFrame( frame.metadata.page_scale_factor, frame.metadata.min_page_scale_factor, frame.metadata.max_page_scale_factor, - gfx::ToCeiledSize(content_size)); + gfx::ToCeiledSize(content_size), + frame.metadata.location_bar_offset, + frame.metadata.location_bar_content_translation); } #endif } diff --git a/content/browser/renderer_host/render_widget_host_impl_android.cc b/content/browser/renderer_host/render_widget_host_impl_android.cc index 92f8477..0ea5b2f 100644 --- a/content/browser/renderer_host/render_widget_host_impl_android.cc +++ b/content/browser/renderer_host/render_widget_host_impl_android.cc @@ -4,6 +4,7 @@ #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/port/browser/render_widget_host_view_port.h" +#include "ui/gfx/vector2d_f.h" namespace content { @@ -18,7 +19,9 @@ void RenderWidgetHostImpl::OnUpdateFrameInfo( page_scale_factor, min_page_scale_factor, max_page_scale_factor, - content_size); + content_size, + gfx::Vector2dF(), + gfx::Vector2dF()); } } // namespace content diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index 13e2461..11d66e2 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc @@ -597,7 +597,9 @@ void RenderWidgetHostViewAndroid::UpdateFrameInfo( float page_scale_factor, float min_page_scale_factor, float max_page_scale_factor, - const gfx::Size& content_size) { + const gfx::Size& content_size, + const gfx::Vector2dF& controls_offset, + const gfx::Vector2dF& content_offset) { if (content_view_core_) { content_view_core_->UpdateContentSize(content_size.width(), content_size.height()); @@ -606,6 +608,8 @@ void RenderWidgetHostViewAndroid::UpdateFrameInfo( content_view_core_->UpdateScrollOffsetAndPageScaleFactor(scroll_offset.x(), scroll_offset.y(), page_scale_factor); + content_view_core_->UpdateOffsetsForFullscreen(controls_offset.y(), + content_offset.y()); } } diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h index 3c21cb8..5ff8298 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.h +++ b/content/browser/renderer_host/render_widget_host_view_android.h @@ -16,6 +16,7 @@ #include "third_party/skia/include/core/SkColor.h" #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h" #include "ui/gfx/size.h" +#include "ui/gfx/vector2d_f.h" struct ViewHostMsg_TextInputState_Params; @@ -134,7 +135,9 @@ class RenderWidgetHostViewAndroid : public RenderWidgetHostViewBase { float page_scale_factor, float min_page_scale_factor, float max_page_scale_factor, - const gfx::Size& content_size) OVERRIDE; + const gfx::Size& content_size, + const gfx::Vector2dF& controls_offset, + const gfx::Vector2dF& content_offset) OVERRIDE; virtual void ShowDisambiguationPopup(const gfx::Rect& target_rect, const SkBitmap& zoomed_bitmap) OVERRIDE; diff --git a/content/browser/renderer_host/render_widget_host_view_guest.cc b/content/browser/renderer_host/render_widget_host_view_guest.cc index 9619730..0b503da 100644 --- a/content/browser/renderer_host/render_widget_host_view_guest.cc +++ b/content/browser/renderer_host/render_widget_host_view_guest.cc @@ -372,7 +372,9 @@ void RenderWidgetHostViewGuest::UpdateFrameInfo( float page_scale_factor, float min_page_scale_factor, float max_page_scale_factor, - const gfx::Size& content_size) { + const gfx::Size& content_size, + const gfx::Vector2dF& controls_offset, + const gfx::Vector2dF& content_offset) { NOTIMPLEMENTED(); } diff --git a/content/browser/renderer_host/render_widget_host_view_guest.h b/content/browser/renderer_host/render_widget_host_view_guest.h index 9b9c95f..a58c0e7 100644 --- a/content/browser/renderer_host/render_widget_host_view_guest.h +++ b/content/browser/renderer_host/render_widget_host_view_guest.h @@ -11,8 +11,8 @@ #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/common/content_export.h" #include "ui/gfx/native_widget_types.h" -#include "ui/gfx/point.h" #include "ui/gfx/rect.h" +#include "ui/gfx/vector2d_f.h" #include "webkit/glue/webcursor.h" #if defined(TOOLKIT_GTK) @@ -159,7 +159,9 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest float page_scale_factor, float min_page_scale_factor, float max_page_scale_factor, - const gfx::Size& content_size) OVERRIDE; + const gfx::Size& content_size, + const gfx::Vector2dF& controls_offset, + const gfx::Vector2dF& content_offset) OVERRIDE; virtual void HasTouchEventHandlers(bool need_touch_events) OVERRIDE; #endif // defined(OS_ANDROID) diff --git a/content/browser/renderer_host/test_render_view_host.h b/content/browser/renderer_host/test_render_view_host.h index 90d4866..47719069 100644 --- a/content/browser/renderer_host/test_render_view_host.h +++ b/content/browser/renderer_host/test_render_view_host.h @@ -15,6 +15,7 @@ #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/public/common/page_transition_types.h" #include "content/public/test/test_renderer_host.h" +#include "ui/gfx/vector2d_f.h" // This file provides a testing framework for mocking out the RenderProcessHost // layer. It allows you to test RenderViewHost, WebContentsImpl, @@ -153,7 +154,9 @@ class TestRenderWidgetHostView : public RenderWidgetHostViewBase { float page_scale_factor, float min_page_scale_factor, float max_page_scale_factor, - const gfx::Size& content_size) OVERRIDE {} + const gfx::Size& content_size, + const gfx::Vector2dF& controls_offset, + const gfx::Vector2dF& content_offset) OVERRIDE {} virtual void HasTouchEventHandlers(bool need_touch_events) OVERRIDE {} #elif defined(OS_WIN) && !defined(USE_AURA) virtual void WillWmDestroy() OVERRIDE; diff --git a/content/common/cc_messages.h b/content/common/cc_messages.h index e0ee85d..1a7bcc0 100644 --- a/content/common/cc_messages.h +++ b/content/common/cc_messages.h @@ -233,6 +233,7 @@ IPC_STRUCT_TRAITS_BEGIN(cc::CompositorFrameMetadata) IPC_STRUCT_TRAITS_MEMBER(min_page_scale_factor) IPC_STRUCT_TRAITS_MEMBER(max_page_scale_factor) IPC_STRUCT_TRAITS_MEMBER(location_bar_offset) + IPC_STRUCT_TRAITS_MEMBER(location_bar_content_translation) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(cc::GLFrameData) diff --git a/content/port/browser/render_widget_host_view_port.h b/content/port/browser/render_widget_host_view_port.h index ad1dfcd..248681e 100644 --- a/content/port/browser/render_widget_host_view_port.h +++ b/content/port/browser/render_widget_host_view_port.h @@ -237,7 +237,9 @@ class CONTENT_EXPORT RenderWidgetHostViewPort : public RenderWidgetHostView { float page_scale_factor, float min_page_scale_factor, float max_page_scale_factor, - const gfx::Size& content_size) = 0; + const gfx::Size& content_size, + const gfx::Vector2dF& controls_offset, + const gfx::Vector2dF& content_offset) = 0; virtual void HasTouchEventHandlers(bool need_touch_events) = 0; #endif diff --git a/content/public/android/java/src/org/chromium/content/common/CommandLine.java b/content/public/android/java/src/org/chromium/content/common/CommandLine.java index a84215f6..08ca81b 100644 --- a/content/public/android/java/src/org/chromium/content/common/CommandLine.java +++ b/content/public/android/java/src/org/chromium/content/common/CommandLine.java @@ -64,8 +64,9 @@ public abstract class CommandLine { public static final String DEFAULT_TILE_WIDTH = "default-tile-width"; public static final String DEFAULT_TILE_HEIGHT = "default-tile-height"; - // Whether fullscreen should be disabled. - public static final String DISABLE_FULLSCREEN = "disable-fullscreen"; + // Whether to enable the auto-hiding top controls. + public static final String ENABLE_TOP_CONTROLS_POSITION_CALCULATION + = "enable-top-controls-position-calculation"; // The height of the movable top controls. public static final String TOP_CONTROLS_HEIGHT = "top-controls-height"; diff --git a/webkit/compositor_bindings/web_layer_tree_view_impl.cc b/webkit/compositor_bindings/web_layer_tree_view_impl.cc index e42a3c7..219a4b0 100644 --- a/webkit/compositor_bindings/web_layer_tree_view_impl.cc +++ b/webkit/compositor_bindings/web_layer_tree_view_impl.cc @@ -5,6 +5,7 @@ #include "web_layer_tree_view_impl.h" #include "base/command_line.h" +#include "base/string_number_conversions.h" #include "cc/font_atlas.h" #include "cc/input_handler.h" #include "cc/layer.h" @@ -51,6 +52,20 @@ bool WebLayerTreeViewImpl::initialize(const WebLayerTreeView::Settings& webSetti settings.initialDebugState.showPlatformLayerTree = webSettings.showPlatformLayerTree; settings.initialDebugState.showDebugBorders = webSettings.showDebugBorders; settings.implSidePainting = CommandLine::ForCurrentProcess()->HasSwitch(cc::switches::kEnableImplSidePainting); + + settings.calculateTopControlsPosition = CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableTopControlsPositionCalculation); + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTopControlsHeight)) { + std::string controls_height_str = + CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kTopControlsHeight); + int controls_height; + if (base::StringToInt(controls_height_str, &controls_height) && controls_height > 0) + settings.topControlsHeightPx = controls_height; + } + if (settings.calculateTopControlsPosition && (settings.topControlsHeightPx <= 0 || !settings.compositorFrameMessage)) { + DCHECK(false) << "Top controls repositioning enabled without valid height or compositorFrameMessage set."; + settings.calculateTopControlsPosition = false; + } + m_layerTreeHost = LayerTreeHost::create(this, settings, implThread.Pass()); if (!m_layerTreeHost.get()) return false; |