1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/ipc/RenderFrameParent.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1189 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * vim: sw=2 ts=8 et : 1.6 + */ 1.7 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.10 + 1.11 +#include "base/basictypes.h" 1.12 + 1.13 +#include "BasicLayers.h" 1.14 +#include "gfx3DMatrix.h" 1.15 +#ifdef MOZ_ENABLE_D3D9_LAYER 1.16 +# include "LayerManagerD3D9.h" 1.17 +#endif //MOZ_ENABLE_D3D9_LAYER 1.18 +#include "mozilla/BrowserElementParent.h" 1.19 +#include "mozilla/dom/TabParent.h" 1.20 +#include "mozilla/layers/APZCTreeManager.h" 1.21 +#include "mozilla/layers/CompositorParent.h" 1.22 +#include "mozilla/layers/LayerTransactionParent.h" 1.23 +#include "nsContentUtils.h" 1.24 +#include "nsFrameLoader.h" 1.25 +#include "nsIObserver.h" 1.26 +#include "nsSubDocumentFrame.h" 1.27 +#include "nsView.h" 1.28 +#include "nsViewportFrame.h" 1.29 +#include "RenderFrameParent.h" 1.30 +#include "mozilla/layers/LayerManagerComposite.h" 1.31 +#include "mozilla/layers/CompositorChild.h" 1.32 +#include "ClientLayerManager.h" 1.33 + 1.34 +typedef nsContentView::ViewConfig ViewConfig; 1.35 +using namespace mozilla::dom; 1.36 +using namespace mozilla::layers; 1.37 + 1.38 +namespace mozilla { 1.39 +namespace layout { 1.40 + 1.41 +typedef FrameMetrics::ViewID ViewID; 1.42 +typedef RenderFrameParent::ViewMap ViewMap; 1.43 + 1.44 +// Represents (affine) transforms that are calculated from a content view. 1.45 +struct ViewTransform { 1.46 + ViewTransform(nsIntPoint aTranslation = nsIntPoint(0, 0), float aXScale = 1, float aYScale = 1) 1.47 + : mTranslation(aTranslation) 1.48 + , mXScale(aXScale) 1.49 + , mYScale(aYScale) 1.50 + {} 1.51 + 1.52 + operator gfx3DMatrix() const 1.53 + { 1.54 + return 1.55 + gfx3DMatrix::Translation(mTranslation.x, mTranslation.y, 0) * 1.56 + gfx3DMatrix::ScalingMatrix(mXScale, mYScale, 1); 1.57 + } 1.58 + 1.59 + nsIntPoint mTranslation; 1.60 + float mXScale; 1.61 + float mYScale; 1.62 +}; 1.63 + 1.64 +// Matrix helpers 1.65 +// For our simple purposes, these helpers apply to 2D affine transformations 1.66 +// that can be represented by a scale and a translation. This makes the math 1.67 +// much easier because we only expect the diagonals and the translation 1.68 +// coordinates of the matrix to be non-zero. 1.69 + 1.70 +static double GetXScale(const gfx3DMatrix& aTransform) 1.71 +{ 1.72 + return aTransform._11; 1.73 +} 1.74 + 1.75 +static double GetYScale(const gfx3DMatrix& aTransform) 1.76 +{ 1.77 + return aTransform._22; 1.78 +} 1.79 + 1.80 +static void Scale(gfx3DMatrix& aTransform, double aXScale, double aYScale) 1.81 +{ 1.82 + aTransform._11 *= aXScale; 1.83 + aTransform._22 *= aYScale; 1.84 +} 1.85 + 1.86 +static void ReverseTranslate(gfx3DMatrix& aTransform, const gfxPoint& aOffset) 1.87 +{ 1.88 + aTransform._41 -= aOffset.x; 1.89 + aTransform._42 -= aOffset.y; 1.90 +} 1.91 + 1.92 + 1.93 +static void ApplyTransform(nsRect& aRect, 1.94 + gfx3DMatrix& aTransform, 1.95 + nscoord auPerDevPixel) 1.96 +{ 1.97 + aRect.x = aRect.x * aTransform._11 + aTransform._41 * auPerDevPixel; 1.98 + aRect.y = aRect.y * aTransform._22 + aTransform._42 * auPerDevPixel; 1.99 + aRect.width = aRect.width * aTransform._11; 1.100 + aRect.height = aRect.height * aTransform._22; 1.101 +} 1.102 + 1.103 +static void 1.104 +AssertInTopLevelChromeDoc(ContainerLayer* aContainer, 1.105 + nsIFrame* aContainedFrame) 1.106 +{ 1.107 + NS_ASSERTION( 1.108 + (aContainer->Manager()->GetBackendType() != mozilla::layers::LayersBackend::LAYERS_BASIC) || 1.109 + (aContainedFrame->GetNearestWidget() == 1.110 + static_cast<BasicLayerManager*>(aContainer->Manager())->GetRetainerWidget()), 1.111 + "Expected frame to be in top-level chrome document"); 1.112 +} 1.113 + 1.114 +// Return view for given ID in aMap, nullptr if not found. 1.115 +static nsContentView* 1.116 +FindViewForId(const ViewMap& aMap, ViewID aId) 1.117 +{ 1.118 + ViewMap::const_iterator iter = aMap.find(aId); 1.119 + return iter != aMap.end() ? iter->second : nullptr; 1.120 +} 1.121 + 1.122 +// Return the root content view in aMap, nullptr if not found. 1.123 +static nsContentView* 1.124 +FindRootView(const ViewMap& aMap) 1.125 +{ 1.126 + for (ViewMap::const_iterator iter = aMap.begin(), end = aMap.end(); 1.127 + iter != end; 1.128 + ++iter) { 1.129 + if (iter->second->IsRoot()) 1.130 + return iter->second; 1.131 + } 1.132 + return nullptr; 1.133 +} 1.134 + 1.135 +static const FrameMetrics* 1.136 +GetFrameMetrics(Layer* aLayer) 1.137 +{ 1.138 + ContainerLayer* container = aLayer->AsContainerLayer(); 1.139 + return container ? &container->GetFrameMetrics() : nullptr; 1.140 +} 1.141 + 1.142 +/** 1.143 + * Gets the layer-pixel offset of aContainerFrame's content rect top-left 1.144 + * from the nearest display item reference frame (which we assume will be inducing 1.145 + * a ContainerLayer). 1.146 + */ 1.147 +static nsIntPoint 1.148 +GetContentRectLayerOffset(nsIFrame* aContainerFrame, nsDisplayListBuilder* aBuilder) 1.149 +{ 1.150 + nscoord auPerDevPixel = aContainerFrame->PresContext()->AppUnitsPerDevPixel(); 1.151 + 1.152 + // Offset to the content rect in case we have borders or padding 1.153 + // Note that aContainerFrame could be a reference frame itself, so 1.154 + // we need to be careful here to ensure that we call ToReferenceFrame 1.155 + // on aContainerFrame and not its parent. 1.156 + nsPoint frameOffset = aBuilder->ToReferenceFrame(aContainerFrame) + 1.157 + (aContainerFrame->GetContentRect().TopLeft() - aContainerFrame->GetPosition()); 1.158 + 1.159 + return frameOffset.ToNearestPixels(auPerDevPixel); 1.160 +} 1.161 + 1.162 +// Compute the transform of the shadow tree contained by 1.163 +// |aContainerFrame| to widget space. We transform because the 1.164 +// subprocess layer manager renders to a different top-left than where 1.165 +// the shadow tree is drawn here and because a scale can be set on the 1.166 +// shadow tree. 1.167 +static ViewTransform 1.168 +ComputeShadowTreeTransform(nsIFrame* aContainerFrame, 1.169 + nsFrameLoader* aRootFrameLoader, 1.170 + const FrameMetrics* aMetrics, 1.171 + const ViewConfig& aConfig, 1.172 + float aTempScaleX = 1.0, 1.173 + float aTempScaleY = 1.0) 1.174 +{ 1.175 + // |aMetrics->mViewportScrollOffset| The frame's scroll offset when it was 1.176 + // painted, in content document pixels. 1.177 + // |aConfig.mScrollOffset| What our user expects, or wants, the 1.178 + // frame scroll offset to be in chrome 1.179 + // document app units. 1.180 + // 1.181 + // So we set a compensating translation that moves the content document 1.182 + // pixels to where the user wants them to be. 1.183 + // 1.184 + nscoord auPerDevPixel = aContainerFrame->PresContext()->AppUnitsPerDevPixel(); 1.185 + nsIntPoint scrollOffset = 1.186 + aConfig.mScrollOffset.ToNearestPixels(auPerDevPixel); 1.187 + LayerIntPoint metricsScrollOffset = RoundedToInt(aMetrics->GetScrollOffsetInLayerPixels()); 1.188 + 1.189 + if (aRootFrameLoader->AsyncScrollEnabled() && !aMetrics->mDisplayPort.IsEmpty()) { 1.190 + // Only use asynchronous scrolling if it is enabled and there is a 1.191 + // displayport defined. It is useful to have a scroll layer that is 1.192 + // synchronously scrolled for identifying a scroll area before it is 1.193 + // being actively scrolled. 1.194 + nsIntPoint scrollCompensation( 1.195 + (scrollOffset.x / aTempScaleX - metricsScrollOffset.x), 1.196 + (scrollOffset.y / aTempScaleY - metricsScrollOffset.y)); 1.197 + 1.198 + return ViewTransform(-scrollCompensation, aConfig.mXScale, aConfig.mYScale); 1.199 + } else { 1.200 + return ViewTransform(nsIntPoint(0, 0), 1, 1); 1.201 + } 1.202 +} 1.203 + 1.204 +// Use shadow layer tree to build display list for the browser's frame. 1.205 +static void 1.206 +BuildListForLayer(Layer* aLayer, 1.207 + nsFrameLoader* aRootFrameLoader, 1.208 + const gfx3DMatrix& aTransform, 1.209 + nsDisplayListBuilder* aBuilder, 1.210 + nsDisplayList& aShadowTree, 1.211 + nsIFrame* aSubdocFrame) 1.212 +{ 1.213 + const FrameMetrics* metrics = GetFrameMetrics(aLayer); 1.214 + 1.215 + gfx3DMatrix transform; 1.216 + 1.217 + if (metrics && metrics->IsScrollable()) { 1.218 + const ViewID scrollId = metrics->GetScrollId(); 1.219 + 1.220 + // We need to figure out the bounds of the scrollable region using the 1.221 + // shadow layer tree from the remote process. The metrics viewport is 1.222 + // defined based on all the transformations of its parent layers and 1.223 + // the scale of the current layer. 1.224 + 1.225 + // Calculate transform for this layer. 1.226 + nsContentView* view = 1.227 + aRootFrameLoader->GetCurrentRemoteFrame()->GetContentView(scrollId); 1.228 + // XXX why don't we include aLayer->GetTransform() in the inverse-scale here? 1.229 + // This seems wrong, but it doesn't seem to cause bugs! 1.230 + gfx3DMatrix applyTransform = ComputeShadowTreeTransform( 1.231 + aSubdocFrame, aRootFrameLoader, metrics, view->GetViewConfig(), 1.232 + 1 / GetXScale(aTransform), 1 / GetYScale(aTransform)); 1.233 + gfx3DMatrix layerTransform; 1.234 + To3DMatrix(aLayer->GetTransform(), layerTransform); 1.235 + transform = applyTransform * layerTransform * aTransform; 1.236 + 1.237 + // As mentioned above, bounds calculation also depends on the scale 1.238 + // of this layer. 1.239 + gfx3DMatrix tmpTransform = aTransform; 1.240 + Scale(tmpTransform, GetXScale(applyTransform), GetYScale(applyTransform)); 1.241 + 1.242 + // Calculate rect for this layer based on aTransform. 1.243 + nsRect bounds; 1.244 + { 1.245 + bounds = CSSRect::ToAppUnits(metrics->mViewport); 1.246 + nscoord auPerDevPixel = aSubdocFrame->PresContext()->AppUnitsPerDevPixel(); 1.247 + ApplyTransform(bounds, tmpTransform, auPerDevPixel); 1.248 + } 1.249 + 1.250 + aShadowTree.AppendToTop( 1.251 + new (aBuilder) nsDisplayRemoteShadow(aBuilder, aSubdocFrame, bounds, scrollId)); 1.252 + 1.253 + } else { 1.254 + gfx3DMatrix layerTransform; 1.255 + To3DMatrix(aLayer->GetTransform(), layerTransform); 1.256 + transform = layerTransform * aTransform; 1.257 + } 1.258 + 1.259 + for (Layer* child = aLayer->GetFirstChild(); child; 1.260 + child = child->GetNextSibling()) { 1.261 + BuildListForLayer(child, aRootFrameLoader, transform, 1.262 + aBuilder, aShadowTree, aSubdocFrame); 1.263 + } 1.264 +} 1.265 + 1.266 +// Go down shadow layer tree and apply transformations for scrollable layers. 1.267 +static void 1.268 +TransformShadowTree(nsDisplayListBuilder* aBuilder, nsFrameLoader* aFrameLoader, 1.269 + nsIFrame* aFrame, Layer* aLayer, 1.270 + const ViewTransform& aTransform, 1.271 + float aTempScaleDiffX = 1.0, 1.272 + float aTempScaleDiffY = 1.0) 1.273 +{ 1.274 + LayerComposite* shadow = aLayer->AsLayerComposite(); 1.275 + shadow->SetShadowClipRect(aLayer->GetClipRect()); 1.276 + shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion()); 1.277 + shadow->SetShadowOpacity(aLayer->GetOpacity()); 1.278 + 1.279 + const FrameMetrics* metrics = GetFrameMetrics(aLayer); 1.280 + 1.281 + gfx3DMatrix shadowTransform; 1.282 + To3DMatrix(aLayer->GetTransform(), shadowTransform); 1.283 + ViewTransform layerTransform = aTransform; 1.284 + 1.285 + if (metrics && metrics->IsScrollable()) { 1.286 + const ViewID scrollId = metrics->GetScrollId(); 1.287 + const nsContentView* view = 1.288 + aFrameLoader->GetCurrentRemoteFrame()->GetContentView(scrollId); 1.289 + NS_ABORT_IF_FALSE(view, "Array of views should be consistent with layer tree"); 1.290 + gfx3DMatrix currentTransform; 1.291 + To3DMatrix(aLayer->GetTransform(), currentTransform); 1.292 + 1.293 + const ViewConfig& config = view->GetViewConfig(); 1.294 + // With temporary scale we should compensate translation 1.295 + // using temporary scale value 1.296 + aTempScaleDiffX *= GetXScale(shadowTransform) * config.mXScale; 1.297 + aTempScaleDiffY *= GetYScale(shadowTransform) * config.mYScale; 1.298 + ViewTransform viewTransform = ComputeShadowTreeTransform( 1.299 + aFrame, aFrameLoader, metrics, view->GetViewConfig(), 1.300 + aTempScaleDiffX, aTempScaleDiffY 1.301 + ); 1.302 + 1.303 + // Apply the layer's own transform *before* the view transform 1.304 + shadowTransform = gfx3DMatrix(viewTransform) * currentTransform; 1.305 + 1.306 + layerTransform = viewTransform; 1.307 + if (metrics->IsRootScrollable()) { 1.308 + // Apply the translation *before* we do the rest of the transforms. 1.309 + nsIntPoint offset = GetContentRectLayerOffset(aFrame, aBuilder); 1.310 + shadowTransform = shadowTransform * 1.311 + gfx3DMatrix::Translation(float(offset.x), float(offset.y), 0.0); 1.312 + } 1.313 + } 1.314 + 1.315 + if (aLayer->GetIsFixedPosition() && 1.316 + !aLayer->GetParent()->GetIsFixedPosition()) { 1.317 + // Alter the shadow transform of fixed position layers in the situation 1.318 + // that the view transform's scroll position doesn't match the actual 1.319 + // scroll position, due to asynchronous layer scrolling. 1.320 + float offsetX = layerTransform.mTranslation.x; 1.321 + float offsetY = layerTransform.mTranslation.y; 1.322 + ReverseTranslate(shadowTransform, gfxPoint(offsetX, offsetY)); 1.323 + const nsIntRect* clipRect = shadow->GetShadowClipRect(); 1.324 + if (clipRect) { 1.325 + nsIntRect transformedClipRect(*clipRect); 1.326 + transformedClipRect.MoveBy(-offsetX, -offsetY); 1.327 + shadow->SetShadowClipRect(&transformedClipRect); 1.328 + } 1.329 + } 1.330 + 1.331 + // The transform already takes the resolution scale into account. Since we 1.332 + // will apply the resolution scale again when computing the effective 1.333 + // transform, we must apply the inverse resolution scale here. 1.334 + if (ContainerLayer* c = aLayer->AsContainerLayer()) { 1.335 + shadowTransform.Scale(1.0f/c->GetPreXScale(), 1.336 + 1.0f/c->GetPreYScale(), 1.337 + 1); 1.338 + } 1.339 + shadowTransform.ScalePost(1.0f/aLayer->GetPostXScale(), 1.340 + 1.0f/aLayer->GetPostYScale(), 1.341 + 1); 1.342 + 1.343 + gfx::Matrix4x4 realShadowTransform; 1.344 + ToMatrix4x4(shadowTransform, realShadowTransform); 1.345 + shadow->SetShadowTransform(realShadowTransform); 1.346 + for (Layer* child = aLayer->GetFirstChild(); 1.347 + child; child = child->GetNextSibling()) { 1.348 + TransformShadowTree(aBuilder, aFrameLoader, aFrame, child, layerTransform, 1.349 + aTempScaleDiffX, aTempScaleDiffY); 1.350 + } 1.351 +} 1.352 + 1.353 +static void 1.354 +ClearContainer(ContainerLayer* aContainer) 1.355 +{ 1.356 + while (Layer* layer = aContainer->GetFirstChild()) { 1.357 + aContainer->RemoveChild(layer); 1.358 + } 1.359 +} 1.360 + 1.361 +// Return true iff |aManager| is a "temporary layer manager". They're 1.362 +// used for small software rendering tasks, like drawWindow. That's 1.363 +// currently implemented by a BasicLayerManager without a backing 1.364 +// widget, and hence in non-retained mode. 1.365 +inline static bool 1.366 +IsTempLayerManager(LayerManager* aManager) 1.367 +{ 1.368 + return (mozilla::layers::LayersBackend::LAYERS_BASIC == aManager->GetBackendType() && 1.369 + !static_cast<BasicLayerManager*>(aManager)->IsRetained()); 1.370 +} 1.371 + 1.372 +// Recursively create a new array of scrollables, preserving any scrollables 1.373 +// that are still in the layer tree. 1.374 +// 1.375 +// aXScale and aYScale are used to calculate any values that need to be in 1.376 +// chrome-document CSS pixels and aren't part of the rendering loop, such as 1.377 +// the initial scroll offset for a new view. 1.378 +static void 1.379 +BuildViewMap(ViewMap& oldContentViews, ViewMap& newContentViews, 1.380 + nsFrameLoader* aFrameLoader, Layer* aLayer, 1.381 + float aXScale = 1, float aYScale = 1, 1.382 + float aAccConfigXScale = 1, float aAccConfigYScale = 1) 1.383 +{ 1.384 + ContainerLayer* container = aLayer->AsContainerLayer(); 1.385 + if (!container) 1.386 + return; 1.387 + const FrameMetrics metrics = container->GetFrameMetrics(); 1.388 + const ViewID scrollId = metrics.GetScrollId(); 1.389 + gfx3DMatrix transform; 1.390 + To3DMatrix(aLayer->GetTransform(), transform); 1.391 + aXScale *= GetXScale(transform); 1.392 + aYScale *= GetYScale(transform); 1.393 + 1.394 + if (metrics.IsScrollable()) { 1.395 + nscoord auPerDevPixel = aFrameLoader->GetPrimaryFrameOfOwningContent() 1.396 + ->PresContext()->AppUnitsPerDevPixel(); 1.397 + nscoord auPerCSSPixel = auPerDevPixel * metrics.mDevPixelsPerCSSPixel.scale; 1.398 + nsContentView* view = FindViewForId(oldContentViews, scrollId); 1.399 + if (view) { 1.400 + // View already exists. Be sure to propagate scales for any values 1.401 + // that need to be calculated something in chrome-doc CSS pixels. 1.402 + ViewConfig config = view->GetViewConfig(); 1.403 + aXScale *= config.mXScale; 1.404 + aYScale *= config.mYScale; 1.405 + view->mFrameLoader = aFrameLoader; 1.406 + // If scale has changed, then we should update 1.407 + // current scroll offset to new scaled value 1.408 + if (aAccConfigXScale != view->mParentScaleX || 1.409 + aAccConfigYScale != view->mParentScaleY) { 1.410 + float xscroll = 0, yscroll = 0; 1.411 + view->GetScrollX(&xscroll); 1.412 + view->GetScrollY(&yscroll); 1.413 + xscroll = xscroll * (aAccConfigXScale / view->mParentScaleX); 1.414 + yscroll = yscroll * (aAccConfigYScale / view->mParentScaleY); 1.415 + view->ScrollTo(xscroll, yscroll); 1.416 + view->mParentScaleX = aAccConfigXScale; 1.417 + view->mParentScaleY = aAccConfigYScale; 1.418 + } 1.419 + // Collect only config scale values for scroll compensation 1.420 + aAccConfigXScale *= config.mXScale; 1.421 + aAccConfigYScale *= config.mYScale; 1.422 + } else { 1.423 + // View doesn't exist, so generate one. We start the view scroll offset at 1.424 + // the same position as the framemetric's scroll offset from the layer. 1.425 + // The default scale is 1, so no need to propagate scale down. 1.426 + ViewConfig config; 1.427 + config.mScrollOffset = nsPoint( 1.428 + NSIntPixelsToAppUnits(metrics.GetScrollOffset().x, auPerCSSPixel) * aXScale, 1.429 + NSIntPixelsToAppUnits(metrics.GetScrollOffset().y, auPerCSSPixel) * aYScale); 1.430 + view = new nsContentView(aFrameLoader, scrollId, metrics.mIsRoot, config); 1.431 + view->mParentScaleX = aAccConfigXScale; 1.432 + view->mParentScaleY = aAccConfigYScale; 1.433 + } 1.434 + 1.435 + // I don't know what units mViewportSize is in, hence use ToUnknownRect 1.436 + // here to mark the current frontier in type info propagation 1.437 + gfx::Rect viewport = metrics.mViewport.ToUnknownRect(); 1.438 + view->mViewportSize = nsSize( 1.439 + NSIntPixelsToAppUnits(viewport.width, auPerDevPixel) * aXScale, 1.440 + NSIntPixelsToAppUnits(viewport.height, auPerDevPixel) * aYScale); 1.441 + view->mContentSize = nsSize( 1.442 + NSFloatPixelsToAppUnits(metrics.mScrollableRect.width, auPerCSSPixel) * aXScale, 1.443 + NSFloatPixelsToAppUnits(metrics.mScrollableRect.height, auPerCSSPixel) * aYScale); 1.444 + 1.445 + newContentViews[scrollId] = view; 1.446 + } 1.447 + 1.448 + for (Layer* child = aLayer->GetFirstChild(); 1.449 + child; child = child->GetNextSibling()) { 1.450 + BuildViewMap(oldContentViews, newContentViews, aFrameLoader, child, 1.451 + aXScale, aYScale, aAccConfigXScale, aAccConfigYScale); 1.452 + } 1.453 +} 1.454 + 1.455 +static void 1.456 +BuildBackgroundPatternFor(ContainerLayer* aContainer, 1.457 + Layer* aShadowRoot, 1.458 + const ViewConfig& aConfig, 1.459 + const gfxRGBA& aColor, 1.460 + LayerManager* aManager, 1.461 + nsIFrame* aFrame) 1.462 +{ 1.463 + LayerComposite* shadowRoot = aShadowRoot->AsLayerComposite(); 1.464 + gfx::Matrix t; 1.465 + if (!shadowRoot->GetShadowTransform().Is2D(&t)) { 1.466 + return; 1.467 + } 1.468 + 1.469 + // Get the rect bounding the shadow content, transformed into the 1.470 + // same space as |aFrame| 1.471 + nsIntRect contentBounds = shadowRoot->GetShadowVisibleRegion().GetBounds(); 1.472 + gfxRect contentVis(contentBounds.x, contentBounds.y, 1.473 + contentBounds.width, contentBounds.height); 1.474 + gfxRect localContentVis(gfx::ThebesMatrix(t).Transform(contentVis)); 1.475 + // Round *in* here because this area is punched out of the background 1.476 + localContentVis.RoundIn(); 1.477 + nsIntRect localIntContentVis(localContentVis.X(), localContentVis.Y(), 1.478 + localContentVis.Width(), localContentVis.Height()); 1.479 + 1.480 + // Get the frame's rect 1.481 + nscoord auPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel(); 1.482 + nsIntRect frameRect = aFrame->GetRect().ToOutsidePixels(auPerDevPixel); 1.483 + 1.484 + // If the shadow tree covers the frame rect, don't bother building 1.485 + // the background, it wouldn't be visible 1.486 + if (localIntContentVis.Contains(frameRect)) { 1.487 + return; 1.488 + } 1.489 + nsRefPtr<ColorLayer> layer = aManager->CreateColorLayer(); 1.490 + layer->SetColor(aColor); 1.491 + 1.492 + // The visible area of the background is the frame's area minus the 1.493 + // content area 1.494 + nsIntRegion bgRgn(frameRect); 1.495 + bgRgn.Sub(bgRgn, localIntContentVis); 1.496 + bgRgn.MoveBy(-frameRect.TopLeft()); 1.497 + layer->SetVisibleRegion(bgRgn); 1.498 + 1.499 + aContainer->InsertAfter(layer, nullptr); 1.500 +} 1.501 + 1.502 +already_AddRefed<LayerManager> 1.503 +GetFrom(nsFrameLoader* aFrameLoader) 1.504 +{ 1.505 + nsIDocument* doc = aFrameLoader->GetOwnerDoc(); 1.506 + return nsContentUtils::LayerManagerForDocument(doc); 1.507 +} 1.508 + 1.509 +class RemoteContentController : public GeckoContentController { 1.510 +public: 1.511 + RemoteContentController(RenderFrameParent* aRenderFrame) 1.512 + : mUILoop(MessageLoop::current()) 1.513 + , mRenderFrame(aRenderFrame) 1.514 + , mHaveZoomConstraints(false) 1.515 + { } 1.516 + 1.517 + virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) MOZ_OVERRIDE 1.518 + { 1.519 + // We always need to post requests into the "UI thread" otherwise the 1.520 + // requests may get processed out of order. 1.521 + mUILoop->PostTask( 1.522 + FROM_HERE, 1.523 + NewRunnableMethod(this, &RemoteContentController::DoRequestContentRepaint, 1.524 + aFrameMetrics)); 1.525 + } 1.526 + 1.527 + virtual void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId, 1.528 + const uint32_t& aScrollGeneration) MOZ_OVERRIDE 1.529 + { 1.530 + if (MessageLoop::current() != mUILoop) { 1.531 + // We have to send this message from the "UI thread" (main 1.532 + // thread). 1.533 + mUILoop->PostTask( 1.534 + FROM_HERE, 1.535 + NewRunnableMethod(this, &RemoteContentController::AcknowledgeScrollUpdate, 1.536 + aScrollId, aScrollGeneration)); 1.537 + return; 1.538 + } 1.539 + if (mRenderFrame) { 1.540 + TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager()); 1.541 + browser->AcknowledgeScrollUpdate(aScrollId, aScrollGeneration); 1.542 + } 1.543 + } 1.544 + 1.545 + virtual void HandleDoubleTap(const CSSPoint& aPoint, 1.546 + int32_t aModifiers, 1.547 + const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE 1.548 + { 1.549 + if (MessageLoop::current() != mUILoop) { 1.550 + // We have to send this message from the "UI thread" (main 1.551 + // thread). 1.552 + mUILoop->PostTask( 1.553 + FROM_HERE, 1.554 + NewRunnableMethod(this, &RemoteContentController::HandleDoubleTap, 1.555 + aPoint, aModifiers, aGuid)); 1.556 + return; 1.557 + } 1.558 + if (mRenderFrame) { 1.559 + TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager()); 1.560 + browser->HandleDoubleTap(aPoint, aModifiers, aGuid); 1.561 + } 1.562 + } 1.563 + 1.564 + virtual void HandleSingleTap(const CSSPoint& aPoint, 1.565 + int32_t aModifiers, 1.566 + const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE 1.567 + { 1.568 + if (MessageLoop::current() != mUILoop) { 1.569 + // We have to send this message from the "UI thread" (main 1.570 + // thread). 1.571 + mUILoop->PostTask( 1.572 + FROM_HERE, 1.573 + NewRunnableMethod(this, &RemoteContentController::HandleSingleTap, 1.574 + aPoint, aModifiers, aGuid)); 1.575 + return; 1.576 + } 1.577 + if (mRenderFrame) { 1.578 + TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager()); 1.579 + browser->HandleSingleTap(aPoint, aModifiers, aGuid); 1.580 + } 1.581 + } 1.582 + 1.583 + virtual void HandleLongTap(const CSSPoint& aPoint, 1.584 + int32_t aModifiers, 1.585 + const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE 1.586 + { 1.587 + if (MessageLoop::current() != mUILoop) { 1.588 + // We have to send this message from the "UI thread" (main 1.589 + // thread). 1.590 + mUILoop->PostTask( 1.591 + FROM_HERE, 1.592 + NewRunnableMethod(this, &RemoteContentController::HandleLongTap, 1.593 + aPoint, aModifiers, aGuid)); 1.594 + return; 1.595 + } 1.596 + if (mRenderFrame) { 1.597 + TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager()); 1.598 + browser->HandleLongTap(aPoint, aModifiers, aGuid); 1.599 + } 1.600 + } 1.601 + 1.602 + virtual void HandleLongTapUp(const CSSPoint& aPoint, 1.603 + int32_t aModifiers, 1.604 + const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE 1.605 + { 1.606 + if (MessageLoop::current() != mUILoop) { 1.607 + // We have to send this message from the "UI thread" (main 1.608 + // thread). 1.609 + mUILoop->PostTask( 1.610 + FROM_HERE, 1.611 + NewRunnableMethod(this, &RemoteContentController::HandleLongTapUp, 1.612 + aPoint, aModifiers, aGuid)); 1.613 + return; 1.614 + } 1.615 + if (mRenderFrame) { 1.616 + TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager()); 1.617 + browser->HandleLongTapUp(aPoint, aModifiers, aGuid); 1.618 + } 1.619 + } 1.620 + 1.621 + void ClearRenderFrame() { mRenderFrame = nullptr; } 1.622 + 1.623 + virtual void SendAsyncScrollDOMEvent(bool aIsRoot, 1.624 + const CSSRect& aContentRect, 1.625 + const CSSSize& aContentSize) MOZ_OVERRIDE 1.626 + { 1.627 + if (MessageLoop::current() != mUILoop) { 1.628 + mUILoop->PostTask( 1.629 + FROM_HERE, 1.630 + NewRunnableMethod(this, 1.631 + &RemoteContentController::SendAsyncScrollDOMEvent, 1.632 + aIsRoot, aContentRect, aContentSize)); 1.633 + return; 1.634 + } 1.635 + if (mRenderFrame && aIsRoot) { 1.636 + TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager()); 1.637 + BrowserElementParent::DispatchAsyncScrollEvent(browser, aContentRect, 1.638 + aContentSize); 1.639 + } 1.640 + } 1.641 + 1.642 + virtual void PostDelayedTask(Task* aTask, int aDelayMs) MOZ_OVERRIDE 1.643 + { 1.644 + MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs); 1.645 + } 1.646 + 1.647 + virtual bool GetRootZoomConstraints(ZoomConstraints* aOutConstraints) 1.648 + { 1.649 + if (mHaveZoomConstraints && aOutConstraints) { 1.650 + *aOutConstraints = mZoomConstraints; 1.651 + } 1.652 + return mHaveZoomConstraints; 1.653 + } 1.654 + 1.655 + virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion) 1.656 + { 1.657 + if (mTouchSensitiveRegion.IsEmpty()) 1.658 + return false; 1.659 + 1.660 + *aOutRegion = CSSRect::FromAppUnits(mTouchSensitiveRegion.GetBounds()); 1.661 + return true; 1.662 + } 1.663 + 1.664 + virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid, 1.665 + APZStateChange aChange, 1.666 + int aArg) 1.667 + { 1.668 + if (MessageLoop::current() != mUILoop) { 1.669 + mUILoop->PostTask( 1.670 + FROM_HERE, 1.671 + NewRunnableMethod(this, &RemoteContentController::NotifyAPZStateChange, 1.672 + aGuid, aChange, aArg)); 1.673 + return; 1.674 + } 1.675 + if (mRenderFrame) { 1.676 + TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager()); 1.677 + browser->NotifyAPZStateChange(aGuid.mScrollId, aChange, aArg); 1.678 + } 1.679 + } 1.680 + 1.681 + // Methods used by RenderFrameParent to set fields stored here. 1.682 + 1.683 + void SaveZoomConstraints(const ZoomConstraints& aConstraints) 1.684 + { 1.685 + mHaveZoomConstraints = true; 1.686 + mZoomConstraints = aConstraints; 1.687 + } 1.688 + 1.689 + void SetTouchSensitiveRegion(const nsRegion& aRegion) 1.690 + { 1.691 + mTouchSensitiveRegion = aRegion; 1.692 + } 1.693 +private: 1.694 + void DoRequestContentRepaint(const FrameMetrics& aFrameMetrics) 1.695 + { 1.696 + if (mRenderFrame) { 1.697 + TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager()); 1.698 + browser->UpdateFrame(aFrameMetrics); 1.699 + } 1.700 + } 1.701 + 1.702 + MessageLoop* mUILoop; 1.703 + RenderFrameParent* mRenderFrame; 1.704 + 1.705 + bool mHaveZoomConstraints; 1.706 + ZoomConstraints mZoomConstraints; 1.707 + nsRegion mTouchSensitiveRegion; 1.708 +}; 1.709 + 1.710 +RenderFrameParent::RenderFrameParent() 1.711 + : mLayersId(0) 1.712 + , mFrameLoaderDestroyed(false) 1.713 + , mBackgroundColor(gfxRGBA(1, 1, 1)) 1.714 +{ 1.715 +} 1.716 + 1.717 +void 1.718 +RenderFrameParent::Init(nsFrameLoader* aFrameLoader, 1.719 + ScrollingBehavior aScrollingBehavior, 1.720 + TextureFactoryIdentifier* aTextureFactoryIdentifier, 1.721 + uint64_t* aId) 1.722 +{ 1.723 + mFrameLoader = aFrameLoader; 1.724 + 1.725 + *aId = 0; 1.726 + 1.727 + nsRefPtr<LayerManager> lm = GetFrom(mFrameLoader); 1.728 + // Perhaps the document containing this frame currently has no presentation? 1.729 + if (lm && lm->GetBackendType() == LayersBackend::LAYERS_CLIENT) { 1.730 + *aTextureFactoryIdentifier = 1.731 + static_cast<ClientLayerManager*>(lm.get())->GetTextureFactoryIdentifier(); 1.732 + } else { 1.733 + *aTextureFactoryIdentifier = TextureFactoryIdentifier(); 1.734 + } 1.735 + 1.736 + if (lm && lm->GetRoot() && lm->GetRoot()->AsContainerLayer()) { 1.737 + ViewID rootScrollId = lm->GetRoot()->AsContainerLayer()->GetFrameMetrics().GetScrollId(); 1.738 + if (rootScrollId != FrameMetrics::NULL_SCROLL_ID) { 1.739 + mContentViews[rootScrollId] = new nsContentView(aFrameLoader, rootScrollId, true); 1.740 + } 1.741 + } 1.742 + 1.743 + if (CompositorParent::CompositorLoop()) { 1.744 + // Our remote frame will push layers updates to the compositor, 1.745 + // and we'll keep an indirect reference to that tree. 1.746 + *aId = mLayersId = CompositorParent::AllocateLayerTreeId(); 1.747 + if (lm && lm->GetBackendType() == LayersBackend::LAYERS_CLIENT) { 1.748 + ClientLayerManager *clientManager = static_cast<ClientLayerManager*>(lm.get()); 1.749 + clientManager->GetRemoteRenderer()->SendNotifyChildCreated(mLayersId); 1.750 + } 1.751 + if (aScrollingBehavior == ASYNC_PAN_ZOOM) { 1.752 + mContentController = new RemoteContentController(this); 1.753 + CompositorParent::SetControllerForLayerTree(mLayersId, mContentController); 1.754 + } 1.755 + } 1.756 + // Set a default RenderFrameParent 1.757 + mFrameLoader->SetCurrentRemoteFrame(this); 1.758 +} 1.759 + 1.760 +APZCTreeManager* 1.761 +RenderFrameParent::GetApzcTreeManager() 1.762 +{ 1.763 + // We can't get a ref to the APZCTreeManager until after the child is 1.764 + // created and the static getter knows which CompositorParent is 1.765 + // instantiated with this layers ID. That's why try to fetch it when 1.766 + // we first need it and cache the result. 1.767 + if (!mApzcTreeManager) { 1.768 + mApzcTreeManager = CompositorParent::GetAPZCTreeManager(mLayersId); 1.769 + } 1.770 + return mApzcTreeManager.get(); 1.771 +} 1.772 + 1.773 +RenderFrameParent::~RenderFrameParent() 1.774 +{} 1.775 + 1.776 +void 1.777 +RenderFrameParent::Destroy() 1.778 +{ 1.779 + size_t numChildren = ManagedPLayerTransactionParent().Length(); 1.780 + NS_ABORT_IF_FALSE(0 == numChildren || 1 == numChildren, 1.781 + "render frame must only have 0 or 1 layer manager"); 1.782 + 1.783 + if (numChildren) { 1.784 + LayerTransactionParent* layers = 1.785 + static_cast<LayerTransactionParent*>(ManagedPLayerTransactionParent()[0]); 1.786 + layers->Destroy(); 1.787 + } 1.788 + 1.789 + mFrameLoaderDestroyed = true; 1.790 +} 1.791 + 1.792 +nsContentView* 1.793 +RenderFrameParent::GetContentView(ViewID aId) 1.794 +{ 1.795 + return FindViewForId(mContentViews, aId); 1.796 +} 1.797 + 1.798 +nsContentView* 1.799 +RenderFrameParent::GetRootContentView() 1.800 +{ 1.801 + return FindRootView(mContentViews); 1.802 +} 1.803 + 1.804 +void 1.805 +RenderFrameParent::ContentViewScaleChanged(nsContentView* aView) 1.806 +{ 1.807 + // Since the scale has changed for a view, it and its descendents need their 1.808 + // shadow-space attributes updated. It's easiest to rebuild the view map. 1.809 + BuildViewMap(); 1.810 +} 1.811 + 1.812 +void 1.813 +RenderFrameParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree, 1.814 + const TargetConfig& aTargetConfig, 1.815 + bool aIsFirstPaint, 1.816 + bool aScheduleComposite) 1.817 +{ 1.818 + // View map must only contain views that are associated with the current 1.819 + // shadow layer tree. We must always update the map when shadow layers 1.820 + // are updated. 1.821 + BuildViewMap(); 1.822 + 1.823 + TriggerRepaint(); 1.824 +} 1.825 + 1.826 +already_AddRefed<Layer> 1.827 +RenderFrameParent::BuildLayer(nsDisplayListBuilder* aBuilder, 1.828 + nsIFrame* aFrame, 1.829 + LayerManager* aManager, 1.830 + const nsIntRect& aVisibleRect, 1.831 + nsDisplayItem* aItem, 1.832 + const ContainerLayerParameters& aContainerParameters) 1.833 +{ 1.834 + NS_ABORT_IF_FALSE(aFrame, 1.835 + "makes no sense to have a shadow tree without a frame"); 1.836 + NS_ABORT_IF_FALSE(!mContainer || 1.837 + IsTempLayerManager(aManager) || 1.838 + mContainer->Manager() == aManager, 1.839 + "retaining manager changed out from under us ... HELP!"); 1.840 + 1.841 + if (IsTempLayerManager(aManager) || 1.842 + (mContainer && mContainer->Manager() != aManager)) { 1.843 + // This can happen if aManager is a "temporary" manager, or if the 1.844 + // widget's layer manager changed out from under us. We need to 1.845 + // FIXME handle the former case somehow, probably with an API to 1.846 + // draw a manager's subtree. The latter is bad bad bad, but the 1.847 + // the NS_ABORT_IF_FALSE() above will flag it. Returning nullptr 1.848 + // here will just cause the shadow subtree not to be rendered. 1.849 + NS_WARNING("Remote iframe not rendered"); 1.850 + return nullptr; 1.851 + } 1.852 + 1.853 + uint64_t id = GetLayerTreeId(); 1.854 + if (0 != id) { 1.855 + MOZ_ASSERT(!GetRootLayer()); 1.856 + 1.857 + nsRefPtr<Layer> layer = 1.858 + (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem)); 1.859 + if (!layer) { 1.860 + layer = aManager->CreateRefLayer(); 1.861 + } 1.862 + if (!layer) { 1.863 + // Probably a temporary layer manager that doesn't know how to 1.864 + // use ref layers. 1.865 + return nullptr; 1.866 + } 1.867 + static_cast<RefLayer*>(layer.get())->SetReferentId(id); 1.868 + nsIntPoint offset = GetContentRectLayerOffset(aFrame, aBuilder); 1.869 + layer->SetVisibleRegion(aVisibleRect - offset); 1.870 + // We can only have an offset if we're a child of an inactive 1.871 + // container, but our display item is LAYER_ACTIVE_FORCE which 1.872 + // forces all layers above to be active. 1.873 + MOZ_ASSERT(aContainerParameters.mOffset == nsIntPoint()); 1.874 + gfx::Matrix4x4 m; 1.875 + m.Translate(offset.x, offset.y, 0.0); 1.876 + // Remote content can't be repainted by us, so we multiply down 1.877 + // the resolution that our container expects onto our container. 1.878 + m.Scale(aContainerParameters.mXScale, aContainerParameters.mYScale, 1.0); 1.879 + layer->SetBaseTransform(m); 1.880 + 1.881 + return layer.forget(); 1.882 + } 1.883 + 1.884 + if (mContainer) { 1.885 + ClearContainer(mContainer); 1.886 + mContainer->SetPreScale(1.0f, 1.0f); 1.887 + mContainer->SetPostScale(1.0f, 1.0f); 1.888 + mContainer->SetInheritedScale(1.0f, 1.0f); 1.889 + } 1.890 + 1.891 + Layer* shadowRoot = GetRootLayer(); 1.892 + if (!shadowRoot) { 1.893 + mContainer = nullptr; 1.894 + return nullptr; 1.895 + } 1.896 + 1.897 + NS_ABORT_IF_FALSE(!shadowRoot || shadowRoot->Manager() == aManager, 1.898 + "retaining manager changed out from under us ... HELP!"); 1.899 + 1.900 + // Wrap the shadow layer tree in mContainer. 1.901 + if (!mContainer) { 1.902 + mContainer = aManager->CreateContainerLayer(); 1.903 + } 1.904 + NS_ABORT_IF_FALSE(!mContainer->GetFirstChild(), 1.905 + "container of shadow tree shouldn't have a 'root' here"); 1.906 + 1.907 + mContainer->InsertAfter(shadowRoot, nullptr); 1.908 + 1.909 + AssertInTopLevelChromeDoc(mContainer, aFrame); 1.910 + ViewTransform transform; 1.911 + TransformShadowTree(aBuilder, mFrameLoader, aFrame, shadowRoot, transform); 1.912 + mContainer->SetClipRect(nullptr); 1.913 + 1.914 + if (mFrameLoader->AsyncScrollEnabled()) { 1.915 + const nsContentView* view = GetRootContentView(); 1.916 + BuildBackgroundPatternFor(mContainer, 1.917 + shadowRoot, 1.918 + view->GetViewConfig(), 1.919 + mBackgroundColor, 1.920 + aManager, aFrame); 1.921 + } 1.922 + mContainer->SetVisibleRegion(aVisibleRect); 1.923 + 1.924 + return nsRefPtr<Layer>(mContainer).forget(); 1.925 +} 1.926 + 1.927 +void 1.928 +RenderFrameParent::OwnerContentChanged(nsIContent* aContent) 1.929 +{ 1.930 + NS_ABORT_IF_FALSE(mFrameLoader->GetOwnerContent() == aContent, 1.931 + "Don't build new map if owner is same!"); 1.932 + BuildViewMap(); 1.933 +} 1.934 + 1.935 +void 1.936 +RenderFrameParent::NotifyInputEvent(WidgetInputEvent& aEvent, 1.937 + ScrollableLayerGuid* aOutTargetGuid) 1.938 +{ 1.939 + if (GetApzcTreeManager()) { 1.940 + GetApzcTreeManager()->ReceiveInputEvent(aEvent, aOutTargetGuid); 1.941 + } 1.942 +} 1.943 + 1.944 +void 1.945 +RenderFrameParent::ActorDestroy(ActorDestroyReason why) 1.946 +{ 1.947 + if (mLayersId != 0) { 1.948 + CompositorParent::DeallocateLayerTreeId(mLayersId); 1.949 + if (mContentController) { 1.950 + // Stop our content controller from requesting repaints of our 1.951 + // content. 1.952 + mContentController->ClearRenderFrame(); 1.953 + // TODO: notify the compositor? 1.954 + } 1.955 + } 1.956 + 1.957 + if (mFrameLoader && mFrameLoader->GetCurrentRemoteFrame() == this) { 1.958 + // XXX this might cause some weird issues ... we'll just not 1.959 + // redraw the part of the window covered by this until the "next" 1.960 + // remote frame has a layer-tree transaction. For 1.961 + // why==NormalShutdown, we'll definitely want to do something 1.962 + // better, especially as nothing guarantees another Update() from 1.963 + // the "next" remote layer tree. 1.964 + mFrameLoader->SetCurrentRemoteFrame(nullptr); 1.965 + } 1.966 + mFrameLoader = nullptr; 1.967 +} 1.968 + 1.969 +bool 1.970 +RenderFrameParent::RecvNotifyCompositorTransaction() 1.971 +{ 1.972 + TriggerRepaint(); 1.973 + return true; 1.974 +} 1.975 + 1.976 +bool 1.977 +RenderFrameParent::RecvUpdateHitRegion(const nsRegion& aRegion) 1.978 +{ 1.979 + mTouchRegion = aRegion; 1.980 + if (mContentController) { 1.981 + // Tell the content controller about the touch-sensitive region, so 1.982 + // that it can provide it to APZ. This is required for APZ to do 1.983 + // correct hit testing for a remote 'mozpasspointerevents' iframe 1.984 + // until bug 928833 is fixed. 1.985 + mContentController->SetTouchSensitiveRegion(aRegion); 1.986 + } 1.987 + return true; 1.988 +} 1.989 + 1.990 +PLayerTransactionParent* 1.991 +RenderFrameParent::AllocPLayerTransactionParent() 1.992 +{ 1.993 + if (!mFrameLoader || mFrameLoaderDestroyed) { 1.994 + return nullptr; 1.995 + } 1.996 + nsRefPtr<LayerManager> lm = GetFrom(mFrameLoader); 1.997 + LayerTransactionParent* result = new LayerTransactionParent(lm->AsLayerManagerComposite(), this, 0); 1.998 + result->AddIPDLReference(); 1.999 + return result; 1.1000 +} 1.1001 + 1.1002 +bool 1.1003 +RenderFrameParent::DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) 1.1004 +{ 1.1005 + static_cast<LayerTransactionParent*>(aLayers)->ReleaseIPDLReference(); 1.1006 + return true; 1.1007 +} 1.1008 + 1.1009 +void 1.1010 +RenderFrameParent::BuildViewMap() 1.1011 +{ 1.1012 + ViewMap newContentViews; 1.1013 + // BuildViewMap assumes we have a primary frame, which may not be the case. 1.1014 + if (GetRootLayer() && mFrameLoader->GetPrimaryFrameOfOwningContent()) { 1.1015 + // Some of the content views in our hash map may no longer be active. To 1.1016 + // tag them as inactive and to remove any chance of them using a dangling 1.1017 + // pointer, we set mContentView to nullptr. 1.1018 + // 1.1019 + // BuildViewMap will restore mFrameLoader if the content view is still 1.1020 + // in our hash table. 1.1021 + 1.1022 + for (ViewMap::const_iterator iter = mContentViews.begin(); 1.1023 + iter != mContentViews.end(); 1.1024 + ++iter) { 1.1025 + iter->second->mFrameLoader = nullptr; 1.1026 + } 1.1027 + 1.1028 + mozilla::layout::BuildViewMap(mContentViews, newContentViews, mFrameLoader, GetRootLayer()); 1.1029 + } 1.1030 + 1.1031 + // Here, we guarantee that *only* the root view is preserved in 1.1032 + // case we couldn't build a new view map above. This is important because 1.1033 + // the content view map should only contain the root view and content 1.1034 + // views that are present in the layer tree. 1.1035 + if (newContentViews.empty()) { 1.1036 + nsContentView* rootView = FindRootView(mContentViews); 1.1037 + if (rootView) 1.1038 + newContentViews[rootView->GetId()] = rootView; 1.1039 + } 1.1040 + 1.1041 + mContentViews = newContentViews; 1.1042 +} 1.1043 + 1.1044 +void 1.1045 +RenderFrameParent::TriggerRepaint() 1.1046 +{ 1.1047 + mFrameLoader->SetCurrentRemoteFrame(this); 1.1048 + 1.1049 + nsIFrame* docFrame = mFrameLoader->GetPrimaryFrameOfOwningContent(); 1.1050 + if (!docFrame) { 1.1051 + // Bad, but nothing we can do about it (XXX/cjones: or is there? 1.1052 + // maybe bug 589337?). When the new frame is created, we'll 1.1053 + // probably still be the current render frame and will get to draw 1.1054 + // our content then. Or, we're shutting down and this update goes 1.1055 + // to /dev/null. 1.1056 + return; 1.1057 + } 1.1058 + 1.1059 + docFrame->InvalidateLayer(nsDisplayItem::TYPE_REMOTE); 1.1060 +} 1.1061 + 1.1062 +LayerTransactionParent* 1.1063 +RenderFrameParent::GetShadowLayers() const 1.1064 +{ 1.1065 + const InfallibleTArray<PLayerTransactionParent*>& shadowParents = ManagedPLayerTransactionParent(); 1.1066 + NS_ABORT_IF_FALSE(shadowParents.Length() <= 1, 1.1067 + "can only support at most 1 LayerTransactionParent"); 1.1068 + return (shadowParents.Length() == 1) ? 1.1069 + static_cast<LayerTransactionParent*>(shadowParents[0]) : nullptr; 1.1070 +} 1.1071 + 1.1072 +uint64_t 1.1073 +RenderFrameParent::GetLayerTreeId() const 1.1074 +{ 1.1075 + return mLayersId; 1.1076 +} 1.1077 + 1.1078 +Layer* 1.1079 +RenderFrameParent::GetRootLayer() const 1.1080 +{ 1.1081 + LayerTransactionParent* shadowLayers = GetShadowLayers(); 1.1082 + return shadowLayers ? shadowLayers->GetRoot() : nullptr; 1.1083 +} 1.1084 + 1.1085 +void 1.1086 +RenderFrameParent::BuildDisplayList(nsDisplayListBuilder* aBuilder, 1.1087 + nsSubDocumentFrame* aFrame, 1.1088 + const nsRect& aDirtyRect, 1.1089 + const nsDisplayListSet& aLists) 1.1090 +{ 1.1091 + // We're the subdoc for <browser remote="true"> and it has 1.1092 + // painted content. Display its shadow layer tree. 1.1093 + DisplayListClipState::AutoSaveRestore clipState(aBuilder); 1.1094 + 1.1095 + nsPoint offset = aBuilder->ToReferenceFrame(aFrame); 1.1096 + nsRect bounds = aFrame->EnsureInnerView()->GetBounds() + offset; 1.1097 + clipState.ClipContentDescendants(bounds); 1.1098 + 1.1099 + Layer* container = GetRootLayer(); 1.1100 + if (aBuilder->IsForEventDelivery() && container) { 1.1101 + ViewTransform offset = 1.1102 + ViewTransform(GetContentRectLayerOffset(aFrame, aBuilder)); 1.1103 + BuildListForLayer(container, mFrameLoader, offset, 1.1104 + aBuilder, *aLists.Content(), aFrame); 1.1105 + } else { 1.1106 + aLists.Content()->AppendToTop( 1.1107 + new (aBuilder) nsDisplayRemote(aBuilder, aFrame, this)); 1.1108 + } 1.1109 +} 1.1110 + 1.1111 +void 1.1112 +RenderFrameParent::ZoomToRect(uint32_t aPresShellId, ViewID aViewId, 1.1113 + const CSSRect& aRect) 1.1114 +{ 1.1115 + if (GetApzcTreeManager()) { 1.1116 + GetApzcTreeManager()->ZoomToRect(ScrollableLayerGuid(mLayersId, aPresShellId, aViewId), 1.1117 + aRect); 1.1118 + } 1.1119 +} 1.1120 + 1.1121 +void 1.1122 +RenderFrameParent::ContentReceivedTouch(const ScrollableLayerGuid& aGuid, 1.1123 + bool aPreventDefault) 1.1124 +{ 1.1125 + if (aGuid.mLayersId != mLayersId) { 1.1126 + // Guard against bad data from hijacked child processes 1.1127 + NS_ERROR("Unexpected layers id in ContentReceivedTouch; dropping message..."); 1.1128 + return; 1.1129 + } 1.1130 + if (GetApzcTreeManager()) { 1.1131 + GetApzcTreeManager()->ContentReceivedTouch(aGuid, aPreventDefault); 1.1132 + } 1.1133 +} 1.1134 + 1.1135 +void 1.1136 +RenderFrameParent::UpdateZoomConstraints(uint32_t aPresShellId, 1.1137 + ViewID aViewId, 1.1138 + bool aIsRoot, 1.1139 + const ZoomConstraints& aConstraints) 1.1140 +{ 1.1141 + if (mContentController && aIsRoot) { 1.1142 + mContentController->SaveZoomConstraints(aConstraints); 1.1143 + } 1.1144 + if (GetApzcTreeManager()) { 1.1145 + GetApzcTreeManager()->UpdateZoomConstraints(ScrollableLayerGuid(mLayersId, aPresShellId, aViewId), 1.1146 + aConstraints); 1.1147 + } 1.1148 +} 1.1149 + 1.1150 +bool 1.1151 +RenderFrameParent::HitTest(const nsRect& aRect) 1.1152 +{ 1.1153 + return mTouchRegion.Contains(aRect); 1.1154 +} 1.1155 + 1.1156 +} // namespace layout 1.1157 +} // namespace mozilla 1.1158 + 1.1159 +already_AddRefed<Layer> 1.1160 +nsDisplayRemote::BuildLayer(nsDisplayListBuilder* aBuilder, 1.1161 + LayerManager* aManager, 1.1162 + const ContainerLayerParameters& aContainerParameters) 1.1163 +{ 1.1164 + int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel(); 1.1165 + nsIntRect visibleRect = GetVisibleRect().ToNearestPixels(appUnitsPerDevPixel); 1.1166 + visibleRect += aContainerParameters.mOffset; 1.1167 + nsRefPtr<Layer> layer = mRemoteFrame->BuildLayer(aBuilder, mFrame, aManager, visibleRect, this, aContainerParameters); 1.1168 + return layer.forget(); 1.1169 +} 1.1170 + 1.1171 +void 1.1172 +nsDisplayRemote::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, 1.1173 + HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) 1.1174 +{ 1.1175 + if (mRemoteFrame->HitTest(aRect)) { 1.1176 + aOutFrames->AppendElement(mFrame); 1.1177 + } 1.1178 +} 1.1179 + 1.1180 +void 1.1181 +nsDisplayRemoteShadow::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, 1.1182 + HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) 1.1183 +{ 1.1184 + // If we are here, then rects have intersected. 1.1185 + // 1.1186 + // XXX I think iframes and divs can be rounded like anything else but we don't 1.1187 + // cover that case here. 1.1188 + // 1.1189 + if (aState->mShadows) { 1.1190 + aState->mShadows->AppendElement(mId); 1.1191 + } 1.1192 +}