layout/ipc/RenderFrameParent.cpp

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 * vim: sw=2 ts=8 et :
michael@0 3 */
michael@0 4 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 5 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 7
michael@0 8 #include "base/basictypes.h"
michael@0 9
michael@0 10 #include "BasicLayers.h"
michael@0 11 #include "gfx3DMatrix.h"
michael@0 12 #ifdef MOZ_ENABLE_D3D9_LAYER
michael@0 13 # include "LayerManagerD3D9.h"
michael@0 14 #endif //MOZ_ENABLE_D3D9_LAYER
michael@0 15 #include "mozilla/BrowserElementParent.h"
michael@0 16 #include "mozilla/dom/TabParent.h"
michael@0 17 #include "mozilla/layers/APZCTreeManager.h"
michael@0 18 #include "mozilla/layers/CompositorParent.h"
michael@0 19 #include "mozilla/layers/LayerTransactionParent.h"
michael@0 20 #include "nsContentUtils.h"
michael@0 21 #include "nsFrameLoader.h"
michael@0 22 #include "nsIObserver.h"
michael@0 23 #include "nsSubDocumentFrame.h"
michael@0 24 #include "nsView.h"
michael@0 25 #include "nsViewportFrame.h"
michael@0 26 #include "RenderFrameParent.h"
michael@0 27 #include "mozilla/layers/LayerManagerComposite.h"
michael@0 28 #include "mozilla/layers/CompositorChild.h"
michael@0 29 #include "ClientLayerManager.h"
michael@0 30
michael@0 31 typedef nsContentView::ViewConfig ViewConfig;
michael@0 32 using namespace mozilla::dom;
michael@0 33 using namespace mozilla::layers;
michael@0 34
michael@0 35 namespace mozilla {
michael@0 36 namespace layout {
michael@0 37
michael@0 38 typedef FrameMetrics::ViewID ViewID;
michael@0 39 typedef RenderFrameParent::ViewMap ViewMap;
michael@0 40
michael@0 41 // Represents (affine) transforms that are calculated from a content view.
michael@0 42 struct ViewTransform {
michael@0 43 ViewTransform(nsIntPoint aTranslation = nsIntPoint(0, 0), float aXScale = 1, float aYScale = 1)
michael@0 44 : mTranslation(aTranslation)
michael@0 45 , mXScale(aXScale)
michael@0 46 , mYScale(aYScale)
michael@0 47 {}
michael@0 48
michael@0 49 operator gfx3DMatrix() const
michael@0 50 {
michael@0 51 return
michael@0 52 gfx3DMatrix::Translation(mTranslation.x, mTranslation.y, 0) *
michael@0 53 gfx3DMatrix::ScalingMatrix(mXScale, mYScale, 1);
michael@0 54 }
michael@0 55
michael@0 56 nsIntPoint mTranslation;
michael@0 57 float mXScale;
michael@0 58 float mYScale;
michael@0 59 };
michael@0 60
michael@0 61 // Matrix helpers
michael@0 62 // For our simple purposes, these helpers apply to 2D affine transformations
michael@0 63 // that can be represented by a scale and a translation. This makes the math
michael@0 64 // much easier because we only expect the diagonals and the translation
michael@0 65 // coordinates of the matrix to be non-zero.
michael@0 66
michael@0 67 static double GetXScale(const gfx3DMatrix& aTransform)
michael@0 68 {
michael@0 69 return aTransform._11;
michael@0 70 }
michael@0 71
michael@0 72 static double GetYScale(const gfx3DMatrix& aTransform)
michael@0 73 {
michael@0 74 return aTransform._22;
michael@0 75 }
michael@0 76
michael@0 77 static void Scale(gfx3DMatrix& aTransform, double aXScale, double aYScale)
michael@0 78 {
michael@0 79 aTransform._11 *= aXScale;
michael@0 80 aTransform._22 *= aYScale;
michael@0 81 }
michael@0 82
michael@0 83 static void ReverseTranslate(gfx3DMatrix& aTransform, const gfxPoint& aOffset)
michael@0 84 {
michael@0 85 aTransform._41 -= aOffset.x;
michael@0 86 aTransform._42 -= aOffset.y;
michael@0 87 }
michael@0 88
michael@0 89
michael@0 90 static void ApplyTransform(nsRect& aRect,
michael@0 91 gfx3DMatrix& aTransform,
michael@0 92 nscoord auPerDevPixel)
michael@0 93 {
michael@0 94 aRect.x = aRect.x * aTransform._11 + aTransform._41 * auPerDevPixel;
michael@0 95 aRect.y = aRect.y * aTransform._22 + aTransform._42 * auPerDevPixel;
michael@0 96 aRect.width = aRect.width * aTransform._11;
michael@0 97 aRect.height = aRect.height * aTransform._22;
michael@0 98 }
michael@0 99
michael@0 100 static void
michael@0 101 AssertInTopLevelChromeDoc(ContainerLayer* aContainer,
michael@0 102 nsIFrame* aContainedFrame)
michael@0 103 {
michael@0 104 NS_ASSERTION(
michael@0 105 (aContainer->Manager()->GetBackendType() != mozilla::layers::LayersBackend::LAYERS_BASIC) ||
michael@0 106 (aContainedFrame->GetNearestWidget() ==
michael@0 107 static_cast<BasicLayerManager*>(aContainer->Manager())->GetRetainerWidget()),
michael@0 108 "Expected frame to be in top-level chrome document");
michael@0 109 }
michael@0 110
michael@0 111 // Return view for given ID in aMap, nullptr if not found.
michael@0 112 static nsContentView*
michael@0 113 FindViewForId(const ViewMap& aMap, ViewID aId)
michael@0 114 {
michael@0 115 ViewMap::const_iterator iter = aMap.find(aId);
michael@0 116 return iter != aMap.end() ? iter->second : nullptr;
michael@0 117 }
michael@0 118
michael@0 119 // Return the root content view in aMap, nullptr if not found.
michael@0 120 static nsContentView*
michael@0 121 FindRootView(const ViewMap& aMap)
michael@0 122 {
michael@0 123 for (ViewMap::const_iterator iter = aMap.begin(), end = aMap.end();
michael@0 124 iter != end;
michael@0 125 ++iter) {
michael@0 126 if (iter->second->IsRoot())
michael@0 127 return iter->second;
michael@0 128 }
michael@0 129 return nullptr;
michael@0 130 }
michael@0 131
michael@0 132 static const FrameMetrics*
michael@0 133 GetFrameMetrics(Layer* aLayer)
michael@0 134 {
michael@0 135 ContainerLayer* container = aLayer->AsContainerLayer();
michael@0 136 return container ? &container->GetFrameMetrics() : nullptr;
michael@0 137 }
michael@0 138
michael@0 139 /**
michael@0 140 * Gets the layer-pixel offset of aContainerFrame's content rect top-left
michael@0 141 * from the nearest display item reference frame (which we assume will be inducing
michael@0 142 * a ContainerLayer).
michael@0 143 */
michael@0 144 static nsIntPoint
michael@0 145 GetContentRectLayerOffset(nsIFrame* aContainerFrame, nsDisplayListBuilder* aBuilder)
michael@0 146 {
michael@0 147 nscoord auPerDevPixel = aContainerFrame->PresContext()->AppUnitsPerDevPixel();
michael@0 148
michael@0 149 // Offset to the content rect in case we have borders or padding
michael@0 150 // Note that aContainerFrame could be a reference frame itself, so
michael@0 151 // we need to be careful here to ensure that we call ToReferenceFrame
michael@0 152 // on aContainerFrame and not its parent.
michael@0 153 nsPoint frameOffset = aBuilder->ToReferenceFrame(aContainerFrame) +
michael@0 154 (aContainerFrame->GetContentRect().TopLeft() - aContainerFrame->GetPosition());
michael@0 155
michael@0 156 return frameOffset.ToNearestPixels(auPerDevPixel);
michael@0 157 }
michael@0 158
michael@0 159 // Compute the transform of the shadow tree contained by
michael@0 160 // |aContainerFrame| to widget space. We transform because the
michael@0 161 // subprocess layer manager renders to a different top-left than where
michael@0 162 // the shadow tree is drawn here and because a scale can be set on the
michael@0 163 // shadow tree.
michael@0 164 static ViewTransform
michael@0 165 ComputeShadowTreeTransform(nsIFrame* aContainerFrame,
michael@0 166 nsFrameLoader* aRootFrameLoader,
michael@0 167 const FrameMetrics* aMetrics,
michael@0 168 const ViewConfig& aConfig,
michael@0 169 float aTempScaleX = 1.0,
michael@0 170 float aTempScaleY = 1.0)
michael@0 171 {
michael@0 172 // |aMetrics->mViewportScrollOffset| The frame's scroll offset when it was
michael@0 173 // painted, in content document pixels.
michael@0 174 // |aConfig.mScrollOffset| What our user expects, or wants, the
michael@0 175 // frame scroll offset to be in chrome
michael@0 176 // document app units.
michael@0 177 //
michael@0 178 // So we set a compensating translation that moves the content document
michael@0 179 // pixels to where the user wants them to be.
michael@0 180 //
michael@0 181 nscoord auPerDevPixel = aContainerFrame->PresContext()->AppUnitsPerDevPixel();
michael@0 182 nsIntPoint scrollOffset =
michael@0 183 aConfig.mScrollOffset.ToNearestPixels(auPerDevPixel);
michael@0 184 LayerIntPoint metricsScrollOffset = RoundedToInt(aMetrics->GetScrollOffsetInLayerPixels());
michael@0 185
michael@0 186 if (aRootFrameLoader->AsyncScrollEnabled() && !aMetrics->mDisplayPort.IsEmpty()) {
michael@0 187 // Only use asynchronous scrolling if it is enabled and there is a
michael@0 188 // displayport defined. It is useful to have a scroll layer that is
michael@0 189 // synchronously scrolled for identifying a scroll area before it is
michael@0 190 // being actively scrolled.
michael@0 191 nsIntPoint scrollCompensation(
michael@0 192 (scrollOffset.x / aTempScaleX - metricsScrollOffset.x),
michael@0 193 (scrollOffset.y / aTempScaleY - metricsScrollOffset.y));
michael@0 194
michael@0 195 return ViewTransform(-scrollCompensation, aConfig.mXScale, aConfig.mYScale);
michael@0 196 } else {
michael@0 197 return ViewTransform(nsIntPoint(0, 0), 1, 1);
michael@0 198 }
michael@0 199 }
michael@0 200
michael@0 201 // Use shadow layer tree to build display list for the browser's frame.
michael@0 202 static void
michael@0 203 BuildListForLayer(Layer* aLayer,
michael@0 204 nsFrameLoader* aRootFrameLoader,
michael@0 205 const gfx3DMatrix& aTransform,
michael@0 206 nsDisplayListBuilder* aBuilder,
michael@0 207 nsDisplayList& aShadowTree,
michael@0 208 nsIFrame* aSubdocFrame)
michael@0 209 {
michael@0 210 const FrameMetrics* metrics = GetFrameMetrics(aLayer);
michael@0 211
michael@0 212 gfx3DMatrix transform;
michael@0 213
michael@0 214 if (metrics && metrics->IsScrollable()) {
michael@0 215 const ViewID scrollId = metrics->GetScrollId();
michael@0 216
michael@0 217 // We need to figure out the bounds of the scrollable region using the
michael@0 218 // shadow layer tree from the remote process. The metrics viewport is
michael@0 219 // defined based on all the transformations of its parent layers and
michael@0 220 // the scale of the current layer.
michael@0 221
michael@0 222 // Calculate transform for this layer.
michael@0 223 nsContentView* view =
michael@0 224 aRootFrameLoader->GetCurrentRemoteFrame()->GetContentView(scrollId);
michael@0 225 // XXX why don't we include aLayer->GetTransform() in the inverse-scale here?
michael@0 226 // This seems wrong, but it doesn't seem to cause bugs!
michael@0 227 gfx3DMatrix applyTransform = ComputeShadowTreeTransform(
michael@0 228 aSubdocFrame, aRootFrameLoader, metrics, view->GetViewConfig(),
michael@0 229 1 / GetXScale(aTransform), 1 / GetYScale(aTransform));
michael@0 230 gfx3DMatrix layerTransform;
michael@0 231 To3DMatrix(aLayer->GetTransform(), layerTransform);
michael@0 232 transform = applyTransform * layerTransform * aTransform;
michael@0 233
michael@0 234 // As mentioned above, bounds calculation also depends on the scale
michael@0 235 // of this layer.
michael@0 236 gfx3DMatrix tmpTransform = aTransform;
michael@0 237 Scale(tmpTransform, GetXScale(applyTransform), GetYScale(applyTransform));
michael@0 238
michael@0 239 // Calculate rect for this layer based on aTransform.
michael@0 240 nsRect bounds;
michael@0 241 {
michael@0 242 bounds = CSSRect::ToAppUnits(metrics->mViewport);
michael@0 243 nscoord auPerDevPixel = aSubdocFrame->PresContext()->AppUnitsPerDevPixel();
michael@0 244 ApplyTransform(bounds, tmpTransform, auPerDevPixel);
michael@0 245 }
michael@0 246
michael@0 247 aShadowTree.AppendToTop(
michael@0 248 new (aBuilder) nsDisplayRemoteShadow(aBuilder, aSubdocFrame, bounds, scrollId));
michael@0 249
michael@0 250 } else {
michael@0 251 gfx3DMatrix layerTransform;
michael@0 252 To3DMatrix(aLayer->GetTransform(), layerTransform);
michael@0 253 transform = layerTransform * aTransform;
michael@0 254 }
michael@0 255
michael@0 256 for (Layer* child = aLayer->GetFirstChild(); child;
michael@0 257 child = child->GetNextSibling()) {
michael@0 258 BuildListForLayer(child, aRootFrameLoader, transform,
michael@0 259 aBuilder, aShadowTree, aSubdocFrame);
michael@0 260 }
michael@0 261 }
michael@0 262
michael@0 263 // Go down shadow layer tree and apply transformations for scrollable layers.
michael@0 264 static void
michael@0 265 TransformShadowTree(nsDisplayListBuilder* aBuilder, nsFrameLoader* aFrameLoader,
michael@0 266 nsIFrame* aFrame, Layer* aLayer,
michael@0 267 const ViewTransform& aTransform,
michael@0 268 float aTempScaleDiffX = 1.0,
michael@0 269 float aTempScaleDiffY = 1.0)
michael@0 270 {
michael@0 271 LayerComposite* shadow = aLayer->AsLayerComposite();
michael@0 272 shadow->SetShadowClipRect(aLayer->GetClipRect());
michael@0 273 shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
michael@0 274 shadow->SetShadowOpacity(aLayer->GetOpacity());
michael@0 275
michael@0 276 const FrameMetrics* metrics = GetFrameMetrics(aLayer);
michael@0 277
michael@0 278 gfx3DMatrix shadowTransform;
michael@0 279 To3DMatrix(aLayer->GetTransform(), shadowTransform);
michael@0 280 ViewTransform layerTransform = aTransform;
michael@0 281
michael@0 282 if (metrics && metrics->IsScrollable()) {
michael@0 283 const ViewID scrollId = metrics->GetScrollId();
michael@0 284 const nsContentView* view =
michael@0 285 aFrameLoader->GetCurrentRemoteFrame()->GetContentView(scrollId);
michael@0 286 NS_ABORT_IF_FALSE(view, "Array of views should be consistent with layer tree");
michael@0 287 gfx3DMatrix currentTransform;
michael@0 288 To3DMatrix(aLayer->GetTransform(), currentTransform);
michael@0 289
michael@0 290 const ViewConfig& config = view->GetViewConfig();
michael@0 291 // With temporary scale we should compensate translation
michael@0 292 // using temporary scale value
michael@0 293 aTempScaleDiffX *= GetXScale(shadowTransform) * config.mXScale;
michael@0 294 aTempScaleDiffY *= GetYScale(shadowTransform) * config.mYScale;
michael@0 295 ViewTransform viewTransform = ComputeShadowTreeTransform(
michael@0 296 aFrame, aFrameLoader, metrics, view->GetViewConfig(),
michael@0 297 aTempScaleDiffX, aTempScaleDiffY
michael@0 298 );
michael@0 299
michael@0 300 // Apply the layer's own transform *before* the view transform
michael@0 301 shadowTransform = gfx3DMatrix(viewTransform) * currentTransform;
michael@0 302
michael@0 303 layerTransform = viewTransform;
michael@0 304 if (metrics->IsRootScrollable()) {
michael@0 305 // Apply the translation *before* we do the rest of the transforms.
michael@0 306 nsIntPoint offset = GetContentRectLayerOffset(aFrame, aBuilder);
michael@0 307 shadowTransform = shadowTransform *
michael@0 308 gfx3DMatrix::Translation(float(offset.x), float(offset.y), 0.0);
michael@0 309 }
michael@0 310 }
michael@0 311
michael@0 312 if (aLayer->GetIsFixedPosition() &&
michael@0 313 !aLayer->GetParent()->GetIsFixedPosition()) {
michael@0 314 // Alter the shadow transform of fixed position layers in the situation
michael@0 315 // that the view transform's scroll position doesn't match the actual
michael@0 316 // scroll position, due to asynchronous layer scrolling.
michael@0 317 float offsetX = layerTransform.mTranslation.x;
michael@0 318 float offsetY = layerTransform.mTranslation.y;
michael@0 319 ReverseTranslate(shadowTransform, gfxPoint(offsetX, offsetY));
michael@0 320 const nsIntRect* clipRect = shadow->GetShadowClipRect();
michael@0 321 if (clipRect) {
michael@0 322 nsIntRect transformedClipRect(*clipRect);
michael@0 323 transformedClipRect.MoveBy(-offsetX, -offsetY);
michael@0 324 shadow->SetShadowClipRect(&transformedClipRect);
michael@0 325 }
michael@0 326 }
michael@0 327
michael@0 328 // The transform already takes the resolution scale into account. Since we
michael@0 329 // will apply the resolution scale again when computing the effective
michael@0 330 // transform, we must apply the inverse resolution scale here.
michael@0 331 if (ContainerLayer* c = aLayer->AsContainerLayer()) {
michael@0 332 shadowTransform.Scale(1.0f/c->GetPreXScale(),
michael@0 333 1.0f/c->GetPreYScale(),
michael@0 334 1);
michael@0 335 }
michael@0 336 shadowTransform.ScalePost(1.0f/aLayer->GetPostXScale(),
michael@0 337 1.0f/aLayer->GetPostYScale(),
michael@0 338 1);
michael@0 339
michael@0 340 gfx::Matrix4x4 realShadowTransform;
michael@0 341 ToMatrix4x4(shadowTransform, realShadowTransform);
michael@0 342 shadow->SetShadowTransform(realShadowTransform);
michael@0 343 for (Layer* child = aLayer->GetFirstChild();
michael@0 344 child; child = child->GetNextSibling()) {
michael@0 345 TransformShadowTree(aBuilder, aFrameLoader, aFrame, child, layerTransform,
michael@0 346 aTempScaleDiffX, aTempScaleDiffY);
michael@0 347 }
michael@0 348 }
michael@0 349
michael@0 350 static void
michael@0 351 ClearContainer(ContainerLayer* aContainer)
michael@0 352 {
michael@0 353 while (Layer* layer = aContainer->GetFirstChild()) {
michael@0 354 aContainer->RemoveChild(layer);
michael@0 355 }
michael@0 356 }
michael@0 357
michael@0 358 // Return true iff |aManager| is a "temporary layer manager". They're
michael@0 359 // used for small software rendering tasks, like drawWindow. That's
michael@0 360 // currently implemented by a BasicLayerManager without a backing
michael@0 361 // widget, and hence in non-retained mode.
michael@0 362 inline static bool
michael@0 363 IsTempLayerManager(LayerManager* aManager)
michael@0 364 {
michael@0 365 return (mozilla::layers::LayersBackend::LAYERS_BASIC == aManager->GetBackendType() &&
michael@0 366 !static_cast<BasicLayerManager*>(aManager)->IsRetained());
michael@0 367 }
michael@0 368
michael@0 369 // Recursively create a new array of scrollables, preserving any scrollables
michael@0 370 // that are still in the layer tree.
michael@0 371 //
michael@0 372 // aXScale and aYScale are used to calculate any values that need to be in
michael@0 373 // chrome-document CSS pixels and aren't part of the rendering loop, such as
michael@0 374 // the initial scroll offset for a new view.
michael@0 375 static void
michael@0 376 BuildViewMap(ViewMap& oldContentViews, ViewMap& newContentViews,
michael@0 377 nsFrameLoader* aFrameLoader, Layer* aLayer,
michael@0 378 float aXScale = 1, float aYScale = 1,
michael@0 379 float aAccConfigXScale = 1, float aAccConfigYScale = 1)
michael@0 380 {
michael@0 381 ContainerLayer* container = aLayer->AsContainerLayer();
michael@0 382 if (!container)
michael@0 383 return;
michael@0 384 const FrameMetrics metrics = container->GetFrameMetrics();
michael@0 385 const ViewID scrollId = metrics.GetScrollId();
michael@0 386 gfx3DMatrix transform;
michael@0 387 To3DMatrix(aLayer->GetTransform(), transform);
michael@0 388 aXScale *= GetXScale(transform);
michael@0 389 aYScale *= GetYScale(transform);
michael@0 390
michael@0 391 if (metrics.IsScrollable()) {
michael@0 392 nscoord auPerDevPixel = aFrameLoader->GetPrimaryFrameOfOwningContent()
michael@0 393 ->PresContext()->AppUnitsPerDevPixel();
michael@0 394 nscoord auPerCSSPixel = auPerDevPixel * metrics.mDevPixelsPerCSSPixel.scale;
michael@0 395 nsContentView* view = FindViewForId(oldContentViews, scrollId);
michael@0 396 if (view) {
michael@0 397 // View already exists. Be sure to propagate scales for any values
michael@0 398 // that need to be calculated something in chrome-doc CSS pixels.
michael@0 399 ViewConfig config = view->GetViewConfig();
michael@0 400 aXScale *= config.mXScale;
michael@0 401 aYScale *= config.mYScale;
michael@0 402 view->mFrameLoader = aFrameLoader;
michael@0 403 // If scale has changed, then we should update
michael@0 404 // current scroll offset to new scaled value
michael@0 405 if (aAccConfigXScale != view->mParentScaleX ||
michael@0 406 aAccConfigYScale != view->mParentScaleY) {
michael@0 407 float xscroll = 0, yscroll = 0;
michael@0 408 view->GetScrollX(&xscroll);
michael@0 409 view->GetScrollY(&yscroll);
michael@0 410 xscroll = xscroll * (aAccConfigXScale / view->mParentScaleX);
michael@0 411 yscroll = yscroll * (aAccConfigYScale / view->mParentScaleY);
michael@0 412 view->ScrollTo(xscroll, yscroll);
michael@0 413 view->mParentScaleX = aAccConfigXScale;
michael@0 414 view->mParentScaleY = aAccConfigYScale;
michael@0 415 }
michael@0 416 // Collect only config scale values for scroll compensation
michael@0 417 aAccConfigXScale *= config.mXScale;
michael@0 418 aAccConfigYScale *= config.mYScale;
michael@0 419 } else {
michael@0 420 // View doesn't exist, so generate one. We start the view scroll offset at
michael@0 421 // the same position as the framemetric's scroll offset from the layer.
michael@0 422 // The default scale is 1, so no need to propagate scale down.
michael@0 423 ViewConfig config;
michael@0 424 config.mScrollOffset = nsPoint(
michael@0 425 NSIntPixelsToAppUnits(metrics.GetScrollOffset().x, auPerCSSPixel) * aXScale,
michael@0 426 NSIntPixelsToAppUnits(metrics.GetScrollOffset().y, auPerCSSPixel) * aYScale);
michael@0 427 view = new nsContentView(aFrameLoader, scrollId, metrics.mIsRoot, config);
michael@0 428 view->mParentScaleX = aAccConfigXScale;
michael@0 429 view->mParentScaleY = aAccConfigYScale;
michael@0 430 }
michael@0 431
michael@0 432 // I don't know what units mViewportSize is in, hence use ToUnknownRect
michael@0 433 // here to mark the current frontier in type info propagation
michael@0 434 gfx::Rect viewport = metrics.mViewport.ToUnknownRect();
michael@0 435 view->mViewportSize = nsSize(
michael@0 436 NSIntPixelsToAppUnits(viewport.width, auPerDevPixel) * aXScale,
michael@0 437 NSIntPixelsToAppUnits(viewport.height, auPerDevPixel) * aYScale);
michael@0 438 view->mContentSize = nsSize(
michael@0 439 NSFloatPixelsToAppUnits(metrics.mScrollableRect.width, auPerCSSPixel) * aXScale,
michael@0 440 NSFloatPixelsToAppUnits(metrics.mScrollableRect.height, auPerCSSPixel) * aYScale);
michael@0 441
michael@0 442 newContentViews[scrollId] = view;
michael@0 443 }
michael@0 444
michael@0 445 for (Layer* child = aLayer->GetFirstChild();
michael@0 446 child; child = child->GetNextSibling()) {
michael@0 447 BuildViewMap(oldContentViews, newContentViews, aFrameLoader, child,
michael@0 448 aXScale, aYScale, aAccConfigXScale, aAccConfigYScale);
michael@0 449 }
michael@0 450 }
michael@0 451
michael@0 452 static void
michael@0 453 BuildBackgroundPatternFor(ContainerLayer* aContainer,
michael@0 454 Layer* aShadowRoot,
michael@0 455 const ViewConfig& aConfig,
michael@0 456 const gfxRGBA& aColor,
michael@0 457 LayerManager* aManager,
michael@0 458 nsIFrame* aFrame)
michael@0 459 {
michael@0 460 LayerComposite* shadowRoot = aShadowRoot->AsLayerComposite();
michael@0 461 gfx::Matrix t;
michael@0 462 if (!shadowRoot->GetShadowTransform().Is2D(&t)) {
michael@0 463 return;
michael@0 464 }
michael@0 465
michael@0 466 // Get the rect bounding the shadow content, transformed into the
michael@0 467 // same space as |aFrame|
michael@0 468 nsIntRect contentBounds = shadowRoot->GetShadowVisibleRegion().GetBounds();
michael@0 469 gfxRect contentVis(contentBounds.x, contentBounds.y,
michael@0 470 contentBounds.width, contentBounds.height);
michael@0 471 gfxRect localContentVis(gfx::ThebesMatrix(t).Transform(contentVis));
michael@0 472 // Round *in* here because this area is punched out of the background
michael@0 473 localContentVis.RoundIn();
michael@0 474 nsIntRect localIntContentVis(localContentVis.X(), localContentVis.Y(),
michael@0 475 localContentVis.Width(), localContentVis.Height());
michael@0 476
michael@0 477 // Get the frame's rect
michael@0 478 nscoord auPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
michael@0 479 nsIntRect frameRect = aFrame->GetRect().ToOutsidePixels(auPerDevPixel);
michael@0 480
michael@0 481 // If the shadow tree covers the frame rect, don't bother building
michael@0 482 // the background, it wouldn't be visible
michael@0 483 if (localIntContentVis.Contains(frameRect)) {
michael@0 484 return;
michael@0 485 }
michael@0 486 nsRefPtr<ColorLayer> layer = aManager->CreateColorLayer();
michael@0 487 layer->SetColor(aColor);
michael@0 488
michael@0 489 // The visible area of the background is the frame's area minus the
michael@0 490 // content area
michael@0 491 nsIntRegion bgRgn(frameRect);
michael@0 492 bgRgn.Sub(bgRgn, localIntContentVis);
michael@0 493 bgRgn.MoveBy(-frameRect.TopLeft());
michael@0 494 layer->SetVisibleRegion(bgRgn);
michael@0 495
michael@0 496 aContainer->InsertAfter(layer, nullptr);
michael@0 497 }
michael@0 498
michael@0 499 already_AddRefed<LayerManager>
michael@0 500 GetFrom(nsFrameLoader* aFrameLoader)
michael@0 501 {
michael@0 502 nsIDocument* doc = aFrameLoader->GetOwnerDoc();
michael@0 503 return nsContentUtils::LayerManagerForDocument(doc);
michael@0 504 }
michael@0 505
michael@0 506 class RemoteContentController : public GeckoContentController {
michael@0 507 public:
michael@0 508 RemoteContentController(RenderFrameParent* aRenderFrame)
michael@0 509 : mUILoop(MessageLoop::current())
michael@0 510 , mRenderFrame(aRenderFrame)
michael@0 511 , mHaveZoomConstraints(false)
michael@0 512 { }
michael@0 513
michael@0 514 virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) MOZ_OVERRIDE
michael@0 515 {
michael@0 516 // We always need to post requests into the "UI thread" otherwise the
michael@0 517 // requests may get processed out of order.
michael@0 518 mUILoop->PostTask(
michael@0 519 FROM_HERE,
michael@0 520 NewRunnableMethod(this, &RemoteContentController::DoRequestContentRepaint,
michael@0 521 aFrameMetrics));
michael@0 522 }
michael@0 523
michael@0 524 virtual void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
michael@0 525 const uint32_t& aScrollGeneration) MOZ_OVERRIDE
michael@0 526 {
michael@0 527 if (MessageLoop::current() != mUILoop) {
michael@0 528 // We have to send this message from the "UI thread" (main
michael@0 529 // thread).
michael@0 530 mUILoop->PostTask(
michael@0 531 FROM_HERE,
michael@0 532 NewRunnableMethod(this, &RemoteContentController::AcknowledgeScrollUpdate,
michael@0 533 aScrollId, aScrollGeneration));
michael@0 534 return;
michael@0 535 }
michael@0 536 if (mRenderFrame) {
michael@0 537 TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
michael@0 538 browser->AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
michael@0 539 }
michael@0 540 }
michael@0 541
michael@0 542 virtual void HandleDoubleTap(const CSSPoint& aPoint,
michael@0 543 int32_t aModifiers,
michael@0 544 const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE
michael@0 545 {
michael@0 546 if (MessageLoop::current() != mUILoop) {
michael@0 547 // We have to send this message from the "UI thread" (main
michael@0 548 // thread).
michael@0 549 mUILoop->PostTask(
michael@0 550 FROM_HERE,
michael@0 551 NewRunnableMethod(this, &RemoteContentController::HandleDoubleTap,
michael@0 552 aPoint, aModifiers, aGuid));
michael@0 553 return;
michael@0 554 }
michael@0 555 if (mRenderFrame) {
michael@0 556 TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
michael@0 557 browser->HandleDoubleTap(aPoint, aModifiers, aGuid);
michael@0 558 }
michael@0 559 }
michael@0 560
michael@0 561 virtual void HandleSingleTap(const CSSPoint& aPoint,
michael@0 562 int32_t aModifiers,
michael@0 563 const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE
michael@0 564 {
michael@0 565 if (MessageLoop::current() != mUILoop) {
michael@0 566 // We have to send this message from the "UI thread" (main
michael@0 567 // thread).
michael@0 568 mUILoop->PostTask(
michael@0 569 FROM_HERE,
michael@0 570 NewRunnableMethod(this, &RemoteContentController::HandleSingleTap,
michael@0 571 aPoint, aModifiers, aGuid));
michael@0 572 return;
michael@0 573 }
michael@0 574 if (mRenderFrame) {
michael@0 575 TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
michael@0 576 browser->HandleSingleTap(aPoint, aModifiers, aGuid);
michael@0 577 }
michael@0 578 }
michael@0 579
michael@0 580 virtual void HandleLongTap(const CSSPoint& aPoint,
michael@0 581 int32_t aModifiers,
michael@0 582 const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE
michael@0 583 {
michael@0 584 if (MessageLoop::current() != mUILoop) {
michael@0 585 // We have to send this message from the "UI thread" (main
michael@0 586 // thread).
michael@0 587 mUILoop->PostTask(
michael@0 588 FROM_HERE,
michael@0 589 NewRunnableMethod(this, &RemoteContentController::HandleLongTap,
michael@0 590 aPoint, aModifiers, aGuid));
michael@0 591 return;
michael@0 592 }
michael@0 593 if (mRenderFrame) {
michael@0 594 TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
michael@0 595 browser->HandleLongTap(aPoint, aModifiers, aGuid);
michael@0 596 }
michael@0 597 }
michael@0 598
michael@0 599 virtual void HandleLongTapUp(const CSSPoint& aPoint,
michael@0 600 int32_t aModifiers,
michael@0 601 const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE
michael@0 602 {
michael@0 603 if (MessageLoop::current() != mUILoop) {
michael@0 604 // We have to send this message from the "UI thread" (main
michael@0 605 // thread).
michael@0 606 mUILoop->PostTask(
michael@0 607 FROM_HERE,
michael@0 608 NewRunnableMethod(this, &RemoteContentController::HandleLongTapUp,
michael@0 609 aPoint, aModifiers, aGuid));
michael@0 610 return;
michael@0 611 }
michael@0 612 if (mRenderFrame) {
michael@0 613 TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
michael@0 614 browser->HandleLongTapUp(aPoint, aModifiers, aGuid);
michael@0 615 }
michael@0 616 }
michael@0 617
michael@0 618 void ClearRenderFrame() { mRenderFrame = nullptr; }
michael@0 619
michael@0 620 virtual void SendAsyncScrollDOMEvent(bool aIsRoot,
michael@0 621 const CSSRect& aContentRect,
michael@0 622 const CSSSize& aContentSize) MOZ_OVERRIDE
michael@0 623 {
michael@0 624 if (MessageLoop::current() != mUILoop) {
michael@0 625 mUILoop->PostTask(
michael@0 626 FROM_HERE,
michael@0 627 NewRunnableMethod(this,
michael@0 628 &RemoteContentController::SendAsyncScrollDOMEvent,
michael@0 629 aIsRoot, aContentRect, aContentSize));
michael@0 630 return;
michael@0 631 }
michael@0 632 if (mRenderFrame && aIsRoot) {
michael@0 633 TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
michael@0 634 BrowserElementParent::DispatchAsyncScrollEvent(browser, aContentRect,
michael@0 635 aContentSize);
michael@0 636 }
michael@0 637 }
michael@0 638
michael@0 639 virtual void PostDelayedTask(Task* aTask, int aDelayMs) MOZ_OVERRIDE
michael@0 640 {
michael@0 641 MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs);
michael@0 642 }
michael@0 643
michael@0 644 virtual bool GetRootZoomConstraints(ZoomConstraints* aOutConstraints)
michael@0 645 {
michael@0 646 if (mHaveZoomConstraints && aOutConstraints) {
michael@0 647 *aOutConstraints = mZoomConstraints;
michael@0 648 }
michael@0 649 return mHaveZoomConstraints;
michael@0 650 }
michael@0 651
michael@0 652 virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion)
michael@0 653 {
michael@0 654 if (mTouchSensitiveRegion.IsEmpty())
michael@0 655 return false;
michael@0 656
michael@0 657 *aOutRegion = CSSRect::FromAppUnits(mTouchSensitiveRegion.GetBounds());
michael@0 658 return true;
michael@0 659 }
michael@0 660
michael@0 661 virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
michael@0 662 APZStateChange aChange,
michael@0 663 int aArg)
michael@0 664 {
michael@0 665 if (MessageLoop::current() != mUILoop) {
michael@0 666 mUILoop->PostTask(
michael@0 667 FROM_HERE,
michael@0 668 NewRunnableMethod(this, &RemoteContentController::NotifyAPZStateChange,
michael@0 669 aGuid, aChange, aArg));
michael@0 670 return;
michael@0 671 }
michael@0 672 if (mRenderFrame) {
michael@0 673 TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
michael@0 674 browser->NotifyAPZStateChange(aGuid.mScrollId, aChange, aArg);
michael@0 675 }
michael@0 676 }
michael@0 677
michael@0 678 // Methods used by RenderFrameParent to set fields stored here.
michael@0 679
michael@0 680 void SaveZoomConstraints(const ZoomConstraints& aConstraints)
michael@0 681 {
michael@0 682 mHaveZoomConstraints = true;
michael@0 683 mZoomConstraints = aConstraints;
michael@0 684 }
michael@0 685
michael@0 686 void SetTouchSensitiveRegion(const nsRegion& aRegion)
michael@0 687 {
michael@0 688 mTouchSensitiveRegion = aRegion;
michael@0 689 }
michael@0 690 private:
michael@0 691 void DoRequestContentRepaint(const FrameMetrics& aFrameMetrics)
michael@0 692 {
michael@0 693 if (mRenderFrame) {
michael@0 694 TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
michael@0 695 browser->UpdateFrame(aFrameMetrics);
michael@0 696 }
michael@0 697 }
michael@0 698
michael@0 699 MessageLoop* mUILoop;
michael@0 700 RenderFrameParent* mRenderFrame;
michael@0 701
michael@0 702 bool mHaveZoomConstraints;
michael@0 703 ZoomConstraints mZoomConstraints;
michael@0 704 nsRegion mTouchSensitiveRegion;
michael@0 705 };
michael@0 706
michael@0 707 RenderFrameParent::RenderFrameParent()
michael@0 708 : mLayersId(0)
michael@0 709 , mFrameLoaderDestroyed(false)
michael@0 710 , mBackgroundColor(gfxRGBA(1, 1, 1))
michael@0 711 {
michael@0 712 }
michael@0 713
michael@0 714 void
michael@0 715 RenderFrameParent::Init(nsFrameLoader* aFrameLoader,
michael@0 716 ScrollingBehavior aScrollingBehavior,
michael@0 717 TextureFactoryIdentifier* aTextureFactoryIdentifier,
michael@0 718 uint64_t* aId)
michael@0 719 {
michael@0 720 mFrameLoader = aFrameLoader;
michael@0 721
michael@0 722 *aId = 0;
michael@0 723
michael@0 724 nsRefPtr<LayerManager> lm = GetFrom(mFrameLoader);
michael@0 725 // Perhaps the document containing this frame currently has no presentation?
michael@0 726 if (lm && lm->GetBackendType() == LayersBackend::LAYERS_CLIENT) {
michael@0 727 *aTextureFactoryIdentifier =
michael@0 728 static_cast<ClientLayerManager*>(lm.get())->GetTextureFactoryIdentifier();
michael@0 729 } else {
michael@0 730 *aTextureFactoryIdentifier = TextureFactoryIdentifier();
michael@0 731 }
michael@0 732
michael@0 733 if (lm && lm->GetRoot() && lm->GetRoot()->AsContainerLayer()) {
michael@0 734 ViewID rootScrollId = lm->GetRoot()->AsContainerLayer()->GetFrameMetrics().GetScrollId();
michael@0 735 if (rootScrollId != FrameMetrics::NULL_SCROLL_ID) {
michael@0 736 mContentViews[rootScrollId] = new nsContentView(aFrameLoader, rootScrollId, true);
michael@0 737 }
michael@0 738 }
michael@0 739
michael@0 740 if (CompositorParent::CompositorLoop()) {
michael@0 741 // Our remote frame will push layers updates to the compositor,
michael@0 742 // and we'll keep an indirect reference to that tree.
michael@0 743 *aId = mLayersId = CompositorParent::AllocateLayerTreeId();
michael@0 744 if (lm && lm->GetBackendType() == LayersBackend::LAYERS_CLIENT) {
michael@0 745 ClientLayerManager *clientManager = static_cast<ClientLayerManager*>(lm.get());
michael@0 746 clientManager->GetRemoteRenderer()->SendNotifyChildCreated(mLayersId);
michael@0 747 }
michael@0 748 if (aScrollingBehavior == ASYNC_PAN_ZOOM) {
michael@0 749 mContentController = new RemoteContentController(this);
michael@0 750 CompositorParent::SetControllerForLayerTree(mLayersId, mContentController);
michael@0 751 }
michael@0 752 }
michael@0 753 // Set a default RenderFrameParent
michael@0 754 mFrameLoader->SetCurrentRemoteFrame(this);
michael@0 755 }
michael@0 756
michael@0 757 APZCTreeManager*
michael@0 758 RenderFrameParent::GetApzcTreeManager()
michael@0 759 {
michael@0 760 // We can't get a ref to the APZCTreeManager until after the child is
michael@0 761 // created and the static getter knows which CompositorParent is
michael@0 762 // instantiated with this layers ID. That's why try to fetch it when
michael@0 763 // we first need it and cache the result.
michael@0 764 if (!mApzcTreeManager) {
michael@0 765 mApzcTreeManager = CompositorParent::GetAPZCTreeManager(mLayersId);
michael@0 766 }
michael@0 767 return mApzcTreeManager.get();
michael@0 768 }
michael@0 769
michael@0 770 RenderFrameParent::~RenderFrameParent()
michael@0 771 {}
michael@0 772
michael@0 773 void
michael@0 774 RenderFrameParent::Destroy()
michael@0 775 {
michael@0 776 size_t numChildren = ManagedPLayerTransactionParent().Length();
michael@0 777 NS_ABORT_IF_FALSE(0 == numChildren || 1 == numChildren,
michael@0 778 "render frame must only have 0 or 1 layer manager");
michael@0 779
michael@0 780 if (numChildren) {
michael@0 781 LayerTransactionParent* layers =
michael@0 782 static_cast<LayerTransactionParent*>(ManagedPLayerTransactionParent()[0]);
michael@0 783 layers->Destroy();
michael@0 784 }
michael@0 785
michael@0 786 mFrameLoaderDestroyed = true;
michael@0 787 }
michael@0 788
michael@0 789 nsContentView*
michael@0 790 RenderFrameParent::GetContentView(ViewID aId)
michael@0 791 {
michael@0 792 return FindViewForId(mContentViews, aId);
michael@0 793 }
michael@0 794
michael@0 795 nsContentView*
michael@0 796 RenderFrameParent::GetRootContentView()
michael@0 797 {
michael@0 798 return FindRootView(mContentViews);
michael@0 799 }
michael@0 800
michael@0 801 void
michael@0 802 RenderFrameParent::ContentViewScaleChanged(nsContentView* aView)
michael@0 803 {
michael@0 804 // Since the scale has changed for a view, it and its descendents need their
michael@0 805 // shadow-space attributes updated. It's easiest to rebuild the view map.
michael@0 806 BuildViewMap();
michael@0 807 }
michael@0 808
michael@0 809 void
michael@0 810 RenderFrameParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
michael@0 811 const TargetConfig& aTargetConfig,
michael@0 812 bool aIsFirstPaint,
michael@0 813 bool aScheduleComposite)
michael@0 814 {
michael@0 815 // View map must only contain views that are associated with the current
michael@0 816 // shadow layer tree. We must always update the map when shadow layers
michael@0 817 // are updated.
michael@0 818 BuildViewMap();
michael@0 819
michael@0 820 TriggerRepaint();
michael@0 821 }
michael@0 822
michael@0 823 already_AddRefed<Layer>
michael@0 824 RenderFrameParent::BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 825 nsIFrame* aFrame,
michael@0 826 LayerManager* aManager,
michael@0 827 const nsIntRect& aVisibleRect,
michael@0 828 nsDisplayItem* aItem,
michael@0 829 const ContainerLayerParameters& aContainerParameters)
michael@0 830 {
michael@0 831 NS_ABORT_IF_FALSE(aFrame,
michael@0 832 "makes no sense to have a shadow tree without a frame");
michael@0 833 NS_ABORT_IF_FALSE(!mContainer ||
michael@0 834 IsTempLayerManager(aManager) ||
michael@0 835 mContainer->Manager() == aManager,
michael@0 836 "retaining manager changed out from under us ... HELP!");
michael@0 837
michael@0 838 if (IsTempLayerManager(aManager) ||
michael@0 839 (mContainer && mContainer->Manager() != aManager)) {
michael@0 840 // This can happen if aManager is a "temporary" manager, or if the
michael@0 841 // widget's layer manager changed out from under us. We need to
michael@0 842 // FIXME handle the former case somehow, probably with an API to
michael@0 843 // draw a manager's subtree. The latter is bad bad bad, but the
michael@0 844 // the NS_ABORT_IF_FALSE() above will flag it. Returning nullptr
michael@0 845 // here will just cause the shadow subtree not to be rendered.
michael@0 846 NS_WARNING("Remote iframe not rendered");
michael@0 847 return nullptr;
michael@0 848 }
michael@0 849
michael@0 850 uint64_t id = GetLayerTreeId();
michael@0 851 if (0 != id) {
michael@0 852 MOZ_ASSERT(!GetRootLayer());
michael@0 853
michael@0 854 nsRefPtr<Layer> layer =
michael@0 855 (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem));
michael@0 856 if (!layer) {
michael@0 857 layer = aManager->CreateRefLayer();
michael@0 858 }
michael@0 859 if (!layer) {
michael@0 860 // Probably a temporary layer manager that doesn't know how to
michael@0 861 // use ref layers.
michael@0 862 return nullptr;
michael@0 863 }
michael@0 864 static_cast<RefLayer*>(layer.get())->SetReferentId(id);
michael@0 865 nsIntPoint offset = GetContentRectLayerOffset(aFrame, aBuilder);
michael@0 866 layer->SetVisibleRegion(aVisibleRect - offset);
michael@0 867 // We can only have an offset if we're a child of an inactive
michael@0 868 // container, but our display item is LAYER_ACTIVE_FORCE which
michael@0 869 // forces all layers above to be active.
michael@0 870 MOZ_ASSERT(aContainerParameters.mOffset == nsIntPoint());
michael@0 871 gfx::Matrix4x4 m;
michael@0 872 m.Translate(offset.x, offset.y, 0.0);
michael@0 873 // Remote content can't be repainted by us, so we multiply down
michael@0 874 // the resolution that our container expects onto our container.
michael@0 875 m.Scale(aContainerParameters.mXScale, aContainerParameters.mYScale, 1.0);
michael@0 876 layer->SetBaseTransform(m);
michael@0 877
michael@0 878 return layer.forget();
michael@0 879 }
michael@0 880
michael@0 881 if (mContainer) {
michael@0 882 ClearContainer(mContainer);
michael@0 883 mContainer->SetPreScale(1.0f, 1.0f);
michael@0 884 mContainer->SetPostScale(1.0f, 1.0f);
michael@0 885 mContainer->SetInheritedScale(1.0f, 1.0f);
michael@0 886 }
michael@0 887
michael@0 888 Layer* shadowRoot = GetRootLayer();
michael@0 889 if (!shadowRoot) {
michael@0 890 mContainer = nullptr;
michael@0 891 return nullptr;
michael@0 892 }
michael@0 893
michael@0 894 NS_ABORT_IF_FALSE(!shadowRoot || shadowRoot->Manager() == aManager,
michael@0 895 "retaining manager changed out from under us ... HELP!");
michael@0 896
michael@0 897 // Wrap the shadow layer tree in mContainer.
michael@0 898 if (!mContainer) {
michael@0 899 mContainer = aManager->CreateContainerLayer();
michael@0 900 }
michael@0 901 NS_ABORT_IF_FALSE(!mContainer->GetFirstChild(),
michael@0 902 "container of shadow tree shouldn't have a 'root' here");
michael@0 903
michael@0 904 mContainer->InsertAfter(shadowRoot, nullptr);
michael@0 905
michael@0 906 AssertInTopLevelChromeDoc(mContainer, aFrame);
michael@0 907 ViewTransform transform;
michael@0 908 TransformShadowTree(aBuilder, mFrameLoader, aFrame, shadowRoot, transform);
michael@0 909 mContainer->SetClipRect(nullptr);
michael@0 910
michael@0 911 if (mFrameLoader->AsyncScrollEnabled()) {
michael@0 912 const nsContentView* view = GetRootContentView();
michael@0 913 BuildBackgroundPatternFor(mContainer,
michael@0 914 shadowRoot,
michael@0 915 view->GetViewConfig(),
michael@0 916 mBackgroundColor,
michael@0 917 aManager, aFrame);
michael@0 918 }
michael@0 919 mContainer->SetVisibleRegion(aVisibleRect);
michael@0 920
michael@0 921 return nsRefPtr<Layer>(mContainer).forget();
michael@0 922 }
michael@0 923
michael@0 924 void
michael@0 925 RenderFrameParent::OwnerContentChanged(nsIContent* aContent)
michael@0 926 {
michael@0 927 NS_ABORT_IF_FALSE(mFrameLoader->GetOwnerContent() == aContent,
michael@0 928 "Don't build new map if owner is same!");
michael@0 929 BuildViewMap();
michael@0 930 }
michael@0 931
michael@0 932 void
michael@0 933 RenderFrameParent::NotifyInputEvent(WidgetInputEvent& aEvent,
michael@0 934 ScrollableLayerGuid* aOutTargetGuid)
michael@0 935 {
michael@0 936 if (GetApzcTreeManager()) {
michael@0 937 GetApzcTreeManager()->ReceiveInputEvent(aEvent, aOutTargetGuid);
michael@0 938 }
michael@0 939 }
michael@0 940
michael@0 941 void
michael@0 942 RenderFrameParent::ActorDestroy(ActorDestroyReason why)
michael@0 943 {
michael@0 944 if (mLayersId != 0) {
michael@0 945 CompositorParent::DeallocateLayerTreeId(mLayersId);
michael@0 946 if (mContentController) {
michael@0 947 // Stop our content controller from requesting repaints of our
michael@0 948 // content.
michael@0 949 mContentController->ClearRenderFrame();
michael@0 950 // TODO: notify the compositor?
michael@0 951 }
michael@0 952 }
michael@0 953
michael@0 954 if (mFrameLoader && mFrameLoader->GetCurrentRemoteFrame() == this) {
michael@0 955 // XXX this might cause some weird issues ... we'll just not
michael@0 956 // redraw the part of the window covered by this until the "next"
michael@0 957 // remote frame has a layer-tree transaction. For
michael@0 958 // why==NormalShutdown, we'll definitely want to do something
michael@0 959 // better, especially as nothing guarantees another Update() from
michael@0 960 // the "next" remote layer tree.
michael@0 961 mFrameLoader->SetCurrentRemoteFrame(nullptr);
michael@0 962 }
michael@0 963 mFrameLoader = nullptr;
michael@0 964 }
michael@0 965
michael@0 966 bool
michael@0 967 RenderFrameParent::RecvNotifyCompositorTransaction()
michael@0 968 {
michael@0 969 TriggerRepaint();
michael@0 970 return true;
michael@0 971 }
michael@0 972
michael@0 973 bool
michael@0 974 RenderFrameParent::RecvUpdateHitRegion(const nsRegion& aRegion)
michael@0 975 {
michael@0 976 mTouchRegion = aRegion;
michael@0 977 if (mContentController) {
michael@0 978 // Tell the content controller about the touch-sensitive region, so
michael@0 979 // that it can provide it to APZ. This is required for APZ to do
michael@0 980 // correct hit testing for a remote 'mozpasspointerevents' iframe
michael@0 981 // until bug 928833 is fixed.
michael@0 982 mContentController->SetTouchSensitiveRegion(aRegion);
michael@0 983 }
michael@0 984 return true;
michael@0 985 }
michael@0 986
michael@0 987 PLayerTransactionParent*
michael@0 988 RenderFrameParent::AllocPLayerTransactionParent()
michael@0 989 {
michael@0 990 if (!mFrameLoader || mFrameLoaderDestroyed) {
michael@0 991 return nullptr;
michael@0 992 }
michael@0 993 nsRefPtr<LayerManager> lm = GetFrom(mFrameLoader);
michael@0 994 LayerTransactionParent* result = new LayerTransactionParent(lm->AsLayerManagerComposite(), this, 0);
michael@0 995 result->AddIPDLReference();
michael@0 996 return result;
michael@0 997 }
michael@0 998
michael@0 999 bool
michael@0 1000 RenderFrameParent::DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers)
michael@0 1001 {
michael@0 1002 static_cast<LayerTransactionParent*>(aLayers)->ReleaseIPDLReference();
michael@0 1003 return true;
michael@0 1004 }
michael@0 1005
michael@0 1006 void
michael@0 1007 RenderFrameParent::BuildViewMap()
michael@0 1008 {
michael@0 1009 ViewMap newContentViews;
michael@0 1010 // BuildViewMap assumes we have a primary frame, which may not be the case.
michael@0 1011 if (GetRootLayer() && mFrameLoader->GetPrimaryFrameOfOwningContent()) {
michael@0 1012 // Some of the content views in our hash map may no longer be active. To
michael@0 1013 // tag them as inactive and to remove any chance of them using a dangling
michael@0 1014 // pointer, we set mContentView to nullptr.
michael@0 1015 //
michael@0 1016 // BuildViewMap will restore mFrameLoader if the content view is still
michael@0 1017 // in our hash table.
michael@0 1018
michael@0 1019 for (ViewMap::const_iterator iter = mContentViews.begin();
michael@0 1020 iter != mContentViews.end();
michael@0 1021 ++iter) {
michael@0 1022 iter->second->mFrameLoader = nullptr;
michael@0 1023 }
michael@0 1024
michael@0 1025 mozilla::layout::BuildViewMap(mContentViews, newContentViews, mFrameLoader, GetRootLayer());
michael@0 1026 }
michael@0 1027
michael@0 1028 // Here, we guarantee that *only* the root view is preserved in
michael@0 1029 // case we couldn't build a new view map above. This is important because
michael@0 1030 // the content view map should only contain the root view and content
michael@0 1031 // views that are present in the layer tree.
michael@0 1032 if (newContentViews.empty()) {
michael@0 1033 nsContentView* rootView = FindRootView(mContentViews);
michael@0 1034 if (rootView)
michael@0 1035 newContentViews[rootView->GetId()] = rootView;
michael@0 1036 }
michael@0 1037
michael@0 1038 mContentViews = newContentViews;
michael@0 1039 }
michael@0 1040
michael@0 1041 void
michael@0 1042 RenderFrameParent::TriggerRepaint()
michael@0 1043 {
michael@0 1044 mFrameLoader->SetCurrentRemoteFrame(this);
michael@0 1045
michael@0 1046 nsIFrame* docFrame = mFrameLoader->GetPrimaryFrameOfOwningContent();
michael@0 1047 if (!docFrame) {
michael@0 1048 // Bad, but nothing we can do about it (XXX/cjones: or is there?
michael@0 1049 // maybe bug 589337?). When the new frame is created, we'll
michael@0 1050 // probably still be the current render frame and will get to draw
michael@0 1051 // our content then. Or, we're shutting down and this update goes
michael@0 1052 // to /dev/null.
michael@0 1053 return;
michael@0 1054 }
michael@0 1055
michael@0 1056 docFrame->InvalidateLayer(nsDisplayItem::TYPE_REMOTE);
michael@0 1057 }
michael@0 1058
michael@0 1059 LayerTransactionParent*
michael@0 1060 RenderFrameParent::GetShadowLayers() const
michael@0 1061 {
michael@0 1062 const InfallibleTArray<PLayerTransactionParent*>& shadowParents = ManagedPLayerTransactionParent();
michael@0 1063 NS_ABORT_IF_FALSE(shadowParents.Length() <= 1,
michael@0 1064 "can only support at most 1 LayerTransactionParent");
michael@0 1065 return (shadowParents.Length() == 1) ?
michael@0 1066 static_cast<LayerTransactionParent*>(shadowParents[0]) : nullptr;
michael@0 1067 }
michael@0 1068
michael@0 1069 uint64_t
michael@0 1070 RenderFrameParent::GetLayerTreeId() const
michael@0 1071 {
michael@0 1072 return mLayersId;
michael@0 1073 }
michael@0 1074
michael@0 1075 Layer*
michael@0 1076 RenderFrameParent::GetRootLayer() const
michael@0 1077 {
michael@0 1078 LayerTransactionParent* shadowLayers = GetShadowLayers();
michael@0 1079 return shadowLayers ? shadowLayers->GetRoot() : nullptr;
michael@0 1080 }
michael@0 1081
michael@0 1082 void
michael@0 1083 RenderFrameParent::BuildDisplayList(nsDisplayListBuilder* aBuilder,
michael@0 1084 nsSubDocumentFrame* aFrame,
michael@0 1085 const nsRect& aDirtyRect,
michael@0 1086 const nsDisplayListSet& aLists)
michael@0 1087 {
michael@0 1088 // We're the subdoc for <browser remote="true"> and it has
michael@0 1089 // painted content. Display its shadow layer tree.
michael@0 1090 DisplayListClipState::AutoSaveRestore clipState(aBuilder);
michael@0 1091
michael@0 1092 nsPoint offset = aBuilder->ToReferenceFrame(aFrame);
michael@0 1093 nsRect bounds = aFrame->EnsureInnerView()->GetBounds() + offset;
michael@0 1094 clipState.ClipContentDescendants(bounds);
michael@0 1095
michael@0 1096 Layer* container = GetRootLayer();
michael@0 1097 if (aBuilder->IsForEventDelivery() && container) {
michael@0 1098 ViewTransform offset =
michael@0 1099 ViewTransform(GetContentRectLayerOffset(aFrame, aBuilder));
michael@0 1100 BuildListForLayer(container, mFrameLoader, offset,
michael@0 1101 aBuilder, *aLists.Content(), aFrame);
michael@0 1102 } else {
michael@0 1103 aLists.Content()->AppendToTop(
michael@0 1104 new (aBuilder) nsDisplayRemote(aBuilder, aFrame, this));
michael@0 1105 }
michael@0 1106 }
michael@0 1107
michael@0 1108 void
michael@0 1109 RenderFrameParent::ZoomToRect(uint32_t aPresShellId, ViewID aViewId,
michael@0 1110 const CSSRect& aRect)
michael@0 1111 {
michael@0 1112 if (GetApzcTreeManager()) {
michael@0 1113 GetApzcTreeManager()->ZoomToRect(ScrollableLayerGuid(mLayersId, aPresShellId, aViewId),
michael@0 1114 aRect);
michael@0 1115 }
michael@0 1116 }
michael@0 1117
michael@0 1118 void
michael@0 1119 RenderFrameParent::ContentReceivedTouch(const ScrollableLayerGuid& aGuid,
michael@0 1120 bool aPreventDefault)
michael@0 1121 {
michael@0 1122 if (aGuid.mLayersId != mLayersId) {
michael@0 1123 // Guard against bad data from hijacked child processes
michael@0 1124 NS_ERROR("Unexpected layers id in ContentReceivedTouch; dropping message...");
michael@0 1125 return;
michael@0 1126 }
michael@0 1127 if (GetApzcTreeManager()) {
michael@0 1128 GetApzcTreeManager()->ContentReceivedTouch(aGuid, aPreventDefault);
michael@0 1129 }
michael@0 1130 }
michael@0 1131
michael@0 1132 void
michael@0 1133 RenderFrameParent::UpdateZoomConstraints(uint32_t aPresShellId,
michael@0 1134 ViewID aViewId,
michael@0 1135 bool aIsRoot,
michael@0 1136 const ZoomConstraints& aConstraints)
michael@0 1137 {
michael@0 1138 if (mContentController && aIsRoot) {
michael@0 1139 mContentController->SaveZoomConstraints(aConstraints);
michael@0 1140 }
michael@0 1141 if (GetApzcTreeManager()) {
michael@0 1142 GetApzcTreeManager()->UpdateZoomConstraints(ScrollableLayerGuid(mLayersId, aPresShellId, aViewId),
michael@0 1143 aConstraints);
michael@0 1144 }
michael@0 1145 }
michael@0 1146
michael@0 1147 bool
michael@0 1148 RenderFrameParent::HitTest(const nsRect& aRect)
michael@0 1149 {
michael@0 1150 return mTouchRegion.Contains(aRect);
michael@0 1151 }
michael@0 1152
michael@0 1153 } // namespace layout
michael@0 1154 } // namespace mozilla
michael@0 1155
michael@0 1156 already_AddRefed<Layer>
michael@0 1157 nsDisplayRemote::BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 1158 LayerManager* aManager,
michael@0 1159 const ContainerLayerParameters& aContainerParameters)
michael@0 1160 {
michael@0 1161 int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
michael@0 1162 nsIntRect visibleRect = GetVisibleRect().ToNearestPixels(appUnitsPerDevPixel);
michael@0 1163 visibleRect += aContainerParameters.mOffset;
michael@0 1164 nsRefPtr<Layer> layer = mRemoteFrame->BuildLayer(aBuilder, mFrame, aManager, visibleRect, this, aContainerParameters);
michael@0 1165 return layer.forget();
michael@0 1166 }
michael@0 1167
michael@0 1168 void
michael@0 1169 nsDisplayRemote::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
michael@0 1170 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
michael@0 1171 {
michael@0 1172 if (mRemoteFrame->HitTest(aRect)) {
michael@0 1173 aOutFrames->AppendElement(mFrame);
michael@0 1174 }
michael@0 1175 }
michael@0 1176
michael@0 1177 void
michael@0 1178 nsDisplayRemoteShadow::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
michael@0 1179 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
michael@0 1180 {
michael@0 1181 // If we are here, then rects have intersected.
michael@0 1182 //
michael@0 1183 // XXX I think iframes and divs can be rounded like anything else but we don't
michael@0 1184 // cover that case here.
michael@0 1185 //
michael@0 1186 if (aState->mShadows) {
michael@0 1187 aState->mShadows->AppendElement(mId);
michael@0 1188 }
michael@0 1189 }

mercurial