author | Kartikaya Gupta <kgupta@mozilla.com> |
Tue, 03 Feb 2015 10:52:51 -0500 | |
changeset 227234 | 93c0418bd4b267ffa2c9e4ba5251c5b9a94c08c7 |
parent 227233 | 5636007e3d1a110bbce81f46b61cee5602249cc1 |
child 227235 | 8b9d38b020e1bb372f8e6d7bcd9e0eac9801f9aa |
push id | 55058 |
push user | kgupta@mozilla.com |
push date | Tue, 03 Feb 2015 15:53:12 +0000 |
treeherder | mozilla-inbound@93c0418bd4b2 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | roc, tn |
bugs | 1126876 |
milestone | 38.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/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -965,17 +965,18 @@ nsDisplayListBuilder::SubtractFromVisibl nsCaret * nsDisplayListBuilder::GetCaret() { nsRefPtr<nsCaret> caret = CurrentPresShellState()->mPresShell->GetCaret(); return caret; } void -nsDisplayListBuilder::EnterPresShell(nsIFrame* aReferenceFrame) +nsDisplayListBuilder::EnterPresShell(nsIFrame* aReferenceFrame, + bool aPointerEventsNoneDoc) { PresShellState* state = mPresShellStates.AppendElement(); state->mPresShell = aReferenceFrame->PresContext()->PresShell(); state->mCaretFrame = nullptr; state->mFirstFrameMarkedForDisplay = mFramesMarkedForDisplay.Length(); state->mPresShell->UpdateCanvasBackground(); @@ -991,16 +992,22 @@ nsDisplayListBuilder::EnterPresShell(nsI mHadToIgnoreSuppression = true; } state->mIsBackgroundOnly = false; } else { state->mIsBackgroundOnly = true; buildCaret = false; } + bool pointerEventsNone = aPointerEventsNoneDoc; + if (IsInSubdocument()) { + pointerEventsNone |= mPresShellStates[mPresShellStates.Length() - 2].mInsidePointerEventsNoneDoc; + } + state->mInsidePointerEventsNoneDoc = pointerEventsNone; + if (!buildCaret) return; nsRefPtr<nsCaret> caret = state->mPresShell->GetCaret(); state->mCaretFrame = caret->GetPaintGeometry(&state->mCaretRect); if (state->mCaretFrame) { mFramesMarkedForDisplay.AppendElement(state->mCaretFrame); MarkFrameForDisplay(state->mCaretFrame, nullptr); @@ -3095,16 +3102,21 @@ nsDisplayEventReceiver::HitTest(nsDispla } void nsDisplayLayerEventRegions::AddFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) { NS_ASSERTION(aBuilder->FindReferenceFrameFor(aFrame) == aBuilder->FindReferenceFrameFor(mFrame), "Reference frame mismatch"); + if (aBuilder->IsInsidePointerEventsNoneDoc()) { + // Somewhere up the parent document chain is a subdocument with pointer- + // events:none set on it (and without a mozpasspointerevents). + return; + } if (!aFrame->GetParent()) { MOZ_ASSERT(aFrame->GetType() == nsGkAtoms::viewportFrame); nsSubDocumentFrame* subdoc = static_cast<nsSubDocumentFrame*>( nsLayoutUtils::GetCrossDocParentFrame(aFrame)); if (subdoc && subdoc->PassPointerEventsToChildren()) { // If this viewport frame is for a subdocument with // mozpasspointerevents, then we don't want to add the viewport itself // to the event regions. Instead we want to add only subframes.
--- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -335,16 +335,20 @@ public: void SetLayerEventRegions(nsDisplayLayerEventRegions* aItem) { mLayerEventRegions = aItem; } bool IsBuildingLayerEventRegions() { return (gfxPrefs::LayoutEventRegionsEnabled() && mMode == PAINTING); } + bool IsInsidePointerEventsNoneDoc() + { + return CurrentPresShellState()->mInsidePointerEventsNoneDoc; + } bool GetAncestorHasTouchEventHandler() { return mAncestorHasTouchEventHandler; } void SetAncestorHasTouchEventHandler(bool aValue) { mAncestorHasTouchEventHandler = aValue; } bool GetAncestorHasScrollEventHandler() { return mAncestorHasScrollEventHandler; } void SetAncestorHasScrollEventHandler(bool aValue) @@ -386,18 +390,21 @@ public: } /** * Get the caret associated with the current presshell. */ nsCaret* GetCaret(); /** * Notify the display list builder that we're entering a presshell. * aReferenceFrame should be a frame in the new presshell. + * aPointerEventsNoneDoc should be set to true if the frame generating this + * document is pointer-events:none without mozpasspointerevents. */ - void EnterPresShell(nsIFrame* aReferenceFrame); + void EnterPresShell(nsIFrame* aReferenceFrame, + bool aPointerEventsNoneDoc = false); /** * For print-preview documents, we sometimes need to build display items for * the same frames multiple times in the same presentation, with different * clipping. Between each such batch of items, call * ResetMarkedFramesForDisplayList to make sure that the results of * MarkFramesForDisplayList do not carry over between batches. */ void ResetMarkedFramesForDisplayList(); @@ -810,16 +817,20 @@ private: const nsRect& aDirtyRect); struct PresShellState { nsIPresShell* mPresShell; nsIFrame* mCaretFrame; nsRect mCaretRect; uint32_t mFirstFrameMarkedForDisplay; bool mIsBackgroundOnly; + // This is a per-document flag turning off event handling for all content + // in the document, and is set when we enter a subdocument for a pointer- + // events:none frame that doesn't have mozpasspointerevents set. + bool mInsidePointerEventsNoneDoc; }; PresShellState* CurrentPresShellState() { NS_ASSERTION(mPresShellStates.Length() > 0, "Someone forgot to enter a presshell"); return &mPresShellStates[mPresShellStates.Length() - 1]; }
--- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -358,31 +358,33 @@ nsSubDocumentFrame::BuildDisplayList(nsD // own layer so we generate a ColorLayer. This is helpful for optimizing // compositing; we can skip compositing the ColorLayer when the // remote content is opaque. WrapBackgroundColorInOwnLayer(aBuilder, this, decorations.BorderBackground()); } decorations.MoveTo(aLists); } - bool passPointerEventsToChildren = false; - if (aBuilder->IsForEventDelivery()) { - passPointerEventsToChildren = PassPointerEventsToChildren(); - // If mozpasspointerevents is set, then we should allow subdocument content - // to handle events even if we're pointer-events:none. - if (pointerEventsNone && !passPointerEventsToChildren) { - return; - } + // We only care about mozpasspointerevents if we're doing hit-testing + // related things. + bool passPointerEventsToChildren = + (aBuilder->IsForEventDelivery() || aBuilder->IsBuildingLayerEventRegions()) + ? PassPointerEventsToChildren() : false; + + // If mozpasspointerevents is set, then we should allow subdocument content + // to handle events even if we're pointer-events:none. + if (aBuilder->IsForEventDelivery() && pointerEventsNone && !passPointerEventsToChildren) { + return; } // If we're passing pointer events to children then we have to descend into // subdocuments no matter what, to determine which parts are transparent for - // elementFromPoint. - if (!mInnerView || - (!aBuilder->GetDescendIntoSubdocuments() && !passPointerEventsToChildren)) { + // hit-testing or event regions. + bool needToDescend = aBuilder->GetDescendIntoSubdocuments() || passPointerEventsToChildren; + if (!mInnerView || !needToDescend) { return; } if (rfp) { rfp->BuildDisplayList(aBuilder, this, aDirtyRect, aLists); return; } @@ -435,17 +437,18 @@ nsSubDocumentFrame::BuildDisplayList(nsD // The ExpandRectToNearlyVisible that the root scroll frame would do gets short // circuited due to us ignoring the root scroll frame, so we do it here. nsIScrollableFrame* rootScrollableFrame = do_QueryFrame(rootScrollFrame); dirty = rootScrollableFrame->ExpandRectToNearlyVisible(dirty); } } } - aBuilder->EnterPresShell(subdocRootFrame); + aBuilder->EnterPresShell(subdocRootFrame, + pointerEventsNone && !passPointerEventsToChildren); } else { dirty = aDirtyRect; } DisplayListClipState::AutoSaveRestore clipState(aBuilder); if (ShouldClipSubdocument()) { clipState.ClipContainingBlockDescendantsToContentBox(aBuilder, this); }