author | Kan-Ru Chen (陳侃如) <kanru@kanru.info> |
Tue, 13 Aug 2013 15:56:57 +0800 | |
changeset 156255 | ce94c5f1ad3f6de9206e89192a6b4faa064969e0 |
parent 156254 | 95da71532621656886d1adf99a0649b48ae185b8 |
child 156256 | 7bb10d5dfca26e13f32013c0269eb21ba4ea1523 |
push id | 407 |
push user | lsblakk@mozilla.com |
push date | Tue, 03 Dec 2013 03:32:50 +0000 |
treeherder | mozilla-release@babf8c9ebc52 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | roc |
bugs | 845169 |
milestone | 26.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -2067,16 +2067,23 @@ nsFrameLoader::TryRemoteBrowser() nsCOMPtr<nsIDOMChromeWindow> rootChromeWin = do_QueryInterface(rootWin); NS_ABORT_IF_FALSE(rootChromeWin, "How did we not get a chrome window here?"); nsCOMPtr<nsIBrowserDOMWindow> browserDOMWin; rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin)); mRemoteBrowser->SetBrowserDOMWindow(browserDOMWin); mContentParent = mRemoteBrowser->Manager(); + + if (mOwnerContent->AttrValueIs(kNameSpaceID_None, + nsGkAtoms::mozpasspointerevents, + nsGkAtoms::_true, + eCaseMatters)) { + unused << mRemoteBrowser->SendSetUpdateHitRegion(true); + } } return true; } mozilla::dom::PBrowserParent* nsFrameLoader::GetRemoteBrowser() { return mRemoteBrowser;
--- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -400,16 +400,23 @@ child: /** * Sent by the chrome process when it no longer wants this remote * <browser>. The child side cleans up in response, then * finalizing its death by sending back __delete__() to the * parent. */ Destroy(); + + /** + * Tell the child side if it has to update it's touchable region + * to the parent. + */ + SetUpdateHitRegion(bool aEnabled); + /* * FIXME: write protocol! state LIVE: send LoadURL goto LIVE; //etc. send Destroy goto DYING;
--- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -289,16 +289,17 @@ TabChild::TabChild(ContentChild* aManage , mAppPackageFileDescriptorRecved(false) , mOldViewportWidth(0.0f) , mLastBackgroundColor(NS_RGB(255, 255, 255)) , mDidFakeShow(false) , mNotified(false) , mContentDocumentIsDisplayed(false) , mTriedBrowserInit(false) , mOrientation(eScreenOrientation_PortraitPrimary) + , mUpdateHitRegion(false) { printf("creating %d!\n", NS_IsMainThread()); } NS_IMETHODIMP TabChild::HandleEvent(nsIDOMEvent* aEvent) { nsAutoString eventType; @@ -2137,16 +2138,23 @@ TabChild::RecvDestroy() } // XXX what other code in ~TabChild() should we be running here? DestroyWindow(); return Send__delete__(this); } +bool +TabChild::RecvSetUpdateHitRegion(const bool& aEnabled) +{ + mUpdateHitRegion = aEnabled; + return true; +} + PRenderFrameChild* TabChild::AllocPRenderFrameChild(ScrollingBehavior* aScrolling, TextureFactoryIdentifier* aTextureFactoryIdentifier, uint64_t* aLayersId) { return new RenderFrameChild(); } @@ -2348,16 +2356,22 @@ TabChild::MakeVisible() void TabChild::MakeHidden() { if (mWidget) { mWidget->Show(false); } } +void +TabChild::UpdateHitRegion(const nsRegion& aRegion) +{ + mRemoteFrame->SendUpdateHitRegion(aRegion); +} + NS_IMETHODIMP TabChild::GetMessageManager(nsIContentFrameMessageManager** aResult) { if (mTabChildGlobal) { NS_ADDREF(*aResult = mTabChildGlobal); return NS_OK; } *aResult = nullptr;
--- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -335,22 +335,27 @@ public: nsICachedFileDescriptorListener* aCallback); void CancelCachedFileDescriptorCallback( const nsAString& aPath, nsICachedFileDescriptorListener* aCallback); ContentChild* Manager() { return mManager; } + bool GetUpdateHitRegion() { return mUpdateHitRegion; } + + void UpdateHitRegion(const nsRegion& aRegion); + protected: virtual PRenderFrameChild* AllocPRenderFrameChild(ScrollingBehavior* aScrolling, TextureFactoryIdentifier* aTextureFactoryIdentifier, uint64_t* aLayersId) MOZ_OVERRIDE; virtual bool DeallocPRenderFrameChild(PRenderFrameChild* aFrame) MOZ_OVERRIDE; virtual bool RecvDestroy() MOZ_OVERRIDE; + virtual bool RecvSetUpdateHitRegion(const bool& aEnabled) MOZ_OVERRIDE; nsEventStatus DispatchWidgetEvent(nsGUIEvent& event); virtual PIndexedDBChild* AllocPIndexedDBChild(const nsCString& aASCIIOrigin, bool* /* aAllowed */); virtual bool DeallocPIndexedDBChild(PIndexedDBChild* aActor); @@ -466,16 +471,17 @@ private: float mOldViewportWidth; nscolor mLastBackgroundColor; ScrollingBehavior mScrolling; bool mDidFakeShow; bool mNotified; bool mContentDocumentIsDisplayed; bool mTriedBrowserInit; ScreenOrientation mOrientation; + bool mUpdateHitRegion; DISALLOW_EVIL_CONSTRUCTORS(TabChild); }; inline TabChild* GetTabChildFrom(nsIDocShell* aDocShell) { nsCOMPtr<nsITabChild> tc = do_GetInterface(aDocShell);
--- a/ipc/glue/IPCMessageUtils.h +++ b/ipc/glue/IPCMessageUtils.h @@ -758,44 +758,49 @@ struct ParamTraits<nsIntRect> { return (ReadParam(msg, iter, &result->x) && ReadParam(msg, iter, &result->y) && ReadParam(msg, iter, &result->width) && ReadParam(msg, iter, &result->height)); } }; -template<> -struct ParamTraits<nsIntRegion> +template<typename Region, typename Rect, typename Iter> +struct RegionParamTraits { - typedef nsIntRegion paramType; + typedef Region paramType; static void Write(Message* msg, const paramType& param) { - nsIntRegionRectIterator it(param); - while (const nsIntRect* r = it.Next()) + Iter it(param); + while (const Rect* r = it.Next()) WriteParam(msg, *r); // empty rects are sentinel values because nsRegions will never // contain them - WriteParam(msg, nsIntRect()); + WriteParam(msg, Rect()); } static bool Read(const Message* msg, void** iter, paramType* result) { - nsIntRect rect; + Rect rect; while (ReadParam(msg, iter, &rect)) { if (rect.IsEmpty()) return true; result->Or(*result, rect); } return false; } }; template<> +struct ParamTraits<nsIntRegion> + : RegionParamTraits<nsIntRegion, nsIntRect, nsIntRegionRectIterator> +{}; + +template<> struct ParamTraits<nsIntSize> { typedef nsIntSize paramType; static void Write(Message* msg, const paramType& param) { WriteParam(msg, param.width); WriteParam(msg, param.height); @@ -984,16 +989,21 @@ struct ParamTraits<nsRect> return (ReadParam(msg, iter, &result->x) && ReadParam(msg, iter, &result->y) && ReadParam(msg, iter, &result->width) && ReadParam(msg, iter, &result->height)); } }; template<> +struct ParamTraits<nsRegion> + : RegionParamTraits<nsRegion, nsRect, nsRegionRectIterator> +{}; + +template<> struct ParamTraits<nsID> { typedef nsID paramType; static void Write(Message* aMsg, const paramType& aParam) { WriteParam(aMsg, aParam.m0); WriteParam(aMsg, aParam.m1);
--- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -35,16 +35,17 @@ #include "nsThemeConstants.h" #include "LayerTreeInvalidation.h" #include "imgIContainer.h" #include "nsIInterfaceRequestorUtils.h" #include "BasicLayers.h" #include "nsBoxFrame.h" #include "nsViewportFrame.h" +#include "nsSubDocumentFrame.h" #include "nsSVGEffects.h" #include "nsSVGElement.h" #include "nsSVGClipPathFrame.h" #include "GeckoProfiler.h" #include "nsAnimationManager.h" #include "nsTransitionManager.h" #include "nsViewManager.h" #include "ImageLayers.h" @@ -1265,16 +1266,27 @@ GetMouseThrough(const nsIFrame* aFrame) } else if (frame->GetStateBits() & NS_FRAME_MOUSE_THROUGH_NEVER) { return false; } frame = frame->GetParentBox(); } return false; } +static bool +IsFrameReceivingPointerEvents(nsIFrame* aFrame) +{ + nsSubDocumentFrame* frame = do_QueryFrame(aFrame); + if (frame && frame->PassPointerEventsToChildren()) { + return true; + } + return NS_STYLE_POINTER_EVENTS_NONE != + aFrame->StyleVisibility()->GetEffectivePointerEvents(aFrame); +} + // A list of frames, and their z depth. Used for sorting // the results of hit testing. struct FramesWithDepth { FramesWithDepth(float aDepth) : mDepth(aDepth) {} @@ -1347,18 +1359,17 @@ void nsDisplayList::HitTest(nsDisplayLis // We may have just finished a run of consecutive preserve-3d transforms, // so flush these into the destination array before processing our frame list. FlushFramesArray(temp, aOutFrames); } for (uint32_t j = 0; j < outFrames.Length(); j++) { nsIFrame *f = outFrames.ElementAt(j); // Handle the XUL 'mousethrough' feature and 'pointer-events'. - if (!GetMouseThrough(f) && - f->StyleVisibility()->GetEffectivePointerEvents(f) != NS_STYLE_POINTER_EVENTS_NONE) { + if (!GetMouseThrough(f) && IsFrameReceivingPointerEvents(f)) { writeFrames->AppendElement(f); } } } } // Clear any remaining preserve-3d transforms. FlushFramesArray(temp, aOutFrames); NS_ASSERTION(aState->mItemBuffer.Length() == uint32_t(itemBufferStart),
--- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -5484,16 +5484,57 @@ public: mShell->GetPresContext()->NotifyDidPaintForSubtree(mFlags); } private: PresShell* mShell; uint32_t mFlags; }; +class AutoUpdateHitRegion +{ +public: + AutoUpdateHitRegion(PresShell* aShell, nsIFrame* aFrame) + : mShell(aShell), mFrame(aFrame) + { + } + ~AutoUpdateHitRegion() + { + if (XRE_GetProcessType() != GeckoProcessType_Content || + !mFrame || !mShell) { + return; + } + TabChild* tabChild = GetTabChildFrom(mShell); + if (!tabChild || !tabChild->GetUpdateHitRegion()) { + return; + } + nsRegion region; + nsDisplayListBuilder builder(mFrame, + nsDisplayListBuilder::EVENT_DELIVERY, + /* aBuildCert= */ false); + nsDisplayList list; + nsAutoTArray<nsIFrame*, 100> outFrames; + nsDisplayItem::HitTestState hitTestState; + nsRect bounds = mShell->GetPresContext()->GetVisibleArea(); + builder.EnterPresShell(mFrame, bounds); + mFrame->BuildDisplayListForStackingContext(&builder, bounds, &list); + builder.LeavePresShell(mFrame, bounds); + list.HitTest(&builder, bounds, &hitTestState, &outFrames); + list.DeleteAll(); + for (int32_t i = outFrames.Length() - 1; i >= 0; --i) { + region.Or(region, nsLayoutUtils::TransformFrameRectToAncestor( + outFrames[i], nsRect(nsPoint(0, 0), outFrames[i]->GetSize()), mFrame)); + } + tabChild->UpdateHitRegion(region); + } +private: + PresShell* mShell; + nsIFrame* mFrame; +}; + void PresShell::Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion, uint32_t aFlags) { PROFILER_LABEL("Paint", "PresShell::Paint"); NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell"); NS_ASSERTION(aViewToPaint, "null view"); @@ -5515,16 +5556,17 @@ PresShell::Paint(nsView* aViewToP NS_ASSERTION(layerManager, "Must be in paint event"); bool shouldInvalidate = layerManager->NeedsWidgetInvalidation(); uint32_t didPaintFlags = aFlags; if (!shouldInvalidate) { didPaintFlags |= PAINT_COMPOSITE; } nsAutoNotifyDidPaint notifyDidPaint(this, didPaintFlags); + AutoUpdateHitRegion updateHitRegion(this, frame); // Whether or not we should set first paint when painting is // suppressed is debatable. For now we'll do it because // B2G relies on first paint to configure the viewport and // we only want to do that when we have real content to paint. // See Bug 798245 if (mIsFirstPaint && !mPaintingSuppressed) { layerManager->SetIsFirstPaint();
--- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -298,17 +298,21 @@ nsSubDocumentFrame::BuildDisplayList(nsD if (!IsVisibleForPainting(aBuilder)) return; // If mozpasspointerevents is set, then we should allow subdocument content // to handle events even if we're pointer-events:none. if (aBuilder->IsForEventDelivery() && !PassPointerEventsToChildren()) return; - DisplayBorderBackgroundOutline(aBuilder, aLists); + // If we are pointer-events:none then we don't need to HitTest background + if (!aBuilder->IsForEventDelivery() || + StyleVisibility()->mPointerEvents != NS_STYLE_POINTER_EVENTS_NONE) { + DisplayBorderBackgroundOutline(aBuilder, aLists); + } if (!mInnerView) return; nsFrameLoader* frameLoader = FrameLoader(); if (frameLoader) { RenderFrameParent* rfp = frameLoader->GetCurrentRemoteFrame(); if (rfp) {
--- a/layout/generic/nsSubDocumentFrame.h +++ b/layout/generic/nsSubDocumentFrame.h @@ -102,16 +102,22 @@ public: } bool ShouldClampScrollPosition() { nsFrameLoader* frameLoader = FrameLoader(); return !frameLoader || frameLoader->ShouldClampScrollPosition(); } + /** + * Return true if pointer event hit-testing should be allowed to target + * content in the subdocument. + */ + bool PassPointerEventsToChildren(); + protected: friend class AsyncFrameInit; // Helper method to look up the HTML marginwidth & marginheight attributes nsIntSize GetMarginAttributes(); nsFrameLoader* FrameLoader(); @@ -130,22 +136,16 @@ protected: * and our sub-document has an intrinsic size. The frame returned is the * frame for the document element of the document we're embedding. * * Called "Obtain*" and not "Get*" because of comment on GetDocShell that * says it should be called ObtainDocShell because of it's side effects. */ nsIFrame* ObtainIntrinsicSizeFrame(); - /** - * Return true if pointer event hit-testing should be allowed to target - * content in the subdocument. - */ - bool PassPointerEventsToChildren(); - nsRefPtr<nsFrameLoader> mFrameLoader; nsView* mInnerView; bool mIsInline; bool mPostedReflowCallback; bool mDidCreateDoc; bool mCallingShow; };
--- a/layout/ipc/PRenderFrame.ipdl +++ b/layout/ipc/PRenderFrame.ipdl @@ -3,16 +3,20 @@ */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ include protocol PBrowser; include protocol PLayerTransaction; +include "nsRegion.h"; + +using nsRegion; + namespace mozilla { namespace layout { /** * PRenderFrame (in the layout sense of "frame") represents one web * "page". It's used to graft content processes' layer trees into * chrome's rendering path. The lifetime of a PRenderFrame is tied to * its PresShell in the child process. @@ -39,22 +43,26 @@ parent: */ async PLayerTransaction(); async NotifyCompositorTransaction(); async CancelDefaultPanZoom(); async DetectScrollableSubframe(); + async UpdateHitRegion(nsRegion aRegion); + async __delete__(); state EMPTY_OR_DIRECT_COMPOSITOR: recv PLayerTransaction goto HAVE_CONTENT; recv NotifyCompositorTransaction goto EMPTY_OR_DIRECT_COMPOSITOR; + recv UpdateHitRegion goto EMPTY_OR_DIRECT_COMPOSITOR; recv __delete__; state HAVE_CONTENT: recv NotifyCompositorTransaction goto HAVE_CONTENT; + recv UpdateHitRegion goto HAVE_CONTENT; recv __delete__; }; } // namespace layout } // namespace mozilla
--- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -857,16 +857,23 @@ bool RenderFrameParent::RecvDetectScrollableSubframe() { if (GetApzcTreeManager()) { GetApzcTreeManager()->DetectScrollableSubframe(ScrollableLayerGuid(mLayersId)); } return true; } +bool +RenderFrameParent::RecvUpdateHitRegion(const nsRegion& aRegion) +{ + mTouchRegion = aRegion; + return true; +} + PLayerTransactionParent* RenderFrameParent::AllocPLayerTransactionParent() { if (!mFrameLoader || mFrameLoaderDestroyed) { return nullptr; } nsRefPtr<LayerManager> lm = GetFrom(mFrameLoader); return new LayerTransactionParent(lm->AsLayerManagerComposite(), this, 0); @@ -1002,31 +1009,45 @@ void RenderFrameParent::UpdateZoomConstraints(bool aAllowZoom, float aMinZoom, float aMaxZoom) { if (GetApzcTreeManager()) { GetApzcTreeManager()->UpdateZoomConstraints(ScrollableLayerGuid(mLayersId), aAllowZoom, aMinZoom, aMaxZoom); } } +bool +RenderFrameParent::HitTest(const nsRect& aRect) +{ + return mTouchRegion.Contains(aRect); +} + } // namespace layout } // namespace mozilla already_AddRefed<Layer> nsDisplayRemote::BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager, const ContainerParameters& aContainerParameters) { int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel(); nsIntRect visibleRect = GetVisibleRect().ToNearestPixels(appUnitsPerDevPixel); visibleRect += aContainerParameters.mOffset; nsRefPtr<Layer> layer = mRemoteFrame->BuildLayer(aBuilder, mFrame, aManager, visibleRect, this, aContainerParameters); return layer.forget(); } +void +nsDisplayRemote::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, + HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) +{ + if (mRemoteFrame->HitTest(aRect)) { + aOutFrames->AppendElement(mFrame); + } +} void nsDisplayRemoteShadow::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) { // If we are here, then rects have intersected. // // XXX I think iframes and divs can be rounded like anything else but we don't
--- a/layout/ipc/RenderFrameParent.h +++ b/layout/ipc/RenderFrameParent.h @@ -99,24 +99,28 @@ public: void NotifyDimensionsChanged(ScreenIntSize size); void ZoomToRect(const CSSRect& aRect); void ContentReceivedTouch(bool aPreventDefault); void UpdateZoomConstraints(bool aAllowZoom, float aMinZoom, float aMaxZoom); + bool HitTest(const nsRect& aRect); + protected: void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; virtual bool RecvNotifyCompositorTransaction() MOZ_OVERRIDE; virtual bool RecvCancelDefaultPanZoom() MOZ_OVERRIDE; virtual bool RecvDetectScrollableSubframe() MOZ_OVERRIDE; + virtual bool RecvUpdateHitRegion(const nsRegion& aRegion) MOZ_OVERRIDE; + virtual PLayerTransactionParent* AllocPLayerTransactionParent() MOZ_OVERRIDE; virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) MOZ_OVERRIDE; private: void BuildViewMap(); void TriggerRepaint(); void DispatchEventForPanZoomController(const InputEvent& aEvent); @@ -155,16 +159,18 @@ private: // Destroy() so that less code needs to be special-cased for after // Destroy(). // // It's possible for mFrameLoader==null and // mFrameLoaderDestroyed==false. bool mFrameLoaderDestroyed; // this is gfxRGBA because that's what ColorLayer wants. gfxRGBA mBackgroundColor; + + nsRegion mTouchRegion; }; } // namespace layout } // namespace mozilla /** * A DisplayRemote exists solely to graft a child process's shadow * layer tree (for a given RenderFrameParent) into its parent @@ -185,16 +191,19 @@ public: LayerManager* aManager, const ContainerParameters& aParameters) MOZ_OVERRIDE { return mozilla::LAYER_ACTIVE_FORCE; } virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager, const ContainerParameters& aContainerParameters) MOZ_OVERRIDE; + void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, + HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE; + NS_DISPLAY_DECL_NAME("Remote", TYPE_REMOTE) private: RenderFrameParent* mRemoteFrame; }; /** * nsDisplayRemoteShadow is a way of adding display items for frames in a