diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index d82a3a987..c9d0a83d0 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -1947,11 +1947,9 @@ if (animate) { requestAnimationFrame(function () { - //this.tabContainer._handleTabTelemetryStart(t, aURI); - // kick the animation off t.setAttribute("fadein", "true"); - }.bind(this)); + }); } return t; @@ -2132,8 +2130,6 @@ return; } - //this.tabContainer._handleTabTelemetryStart(aTab); - this._blurTab(aTab); aTab.style.maxWidth = ""; // ensure that fade-out transition happens aTab.removeAttribute("fadein"); @@ -4529,8 +4525,12 @@ @@ -4757,6 +4754,12 @@ 2) { @@ -4913,16 +4916,19 @@ let scrollButtonWidth = this.mTabstrip._scrollButtonDown.getBoundingClientRect().width; let paddingStart = this.mTabstrip.scrollboxPaddingStart; + let pinnedTabWidth; let width = 0; for (let i = numPinned - 1; i >= 0; i--) { let tab = this.childNodes[i]; - width += tab.getBoundingClientRect().width; + if (!pinnedTabWidth) { + pinnedTabWidth = tab.getBoundingClientRect().width; + } + width += pinnedTabWidth; tab.style.MozMarginStart = - (width + scrollButtonWidth + paddingStart) + "px"; } this.style.MozPaddingStart = width + paddingStart + "px"; - } else { this.removeAttribute("positionpinnedtabs"); @@ -5258,89 +5264,6 @@ - - - - - - - - - - - - 1) { - let averageInterval = 0; - for (let i = 1; i < frameCount; i++) { - averageInterval += intervals[i]; - }; - averageInterval = averageInterval / (frameCount - 1); - - Services.telemetry.getHistogramById("FX_TAB_ANIM_ANY_FRAME_INTERVAL_MS").add(averageInterval); - - if (aTab._recordingTabOpenPlain) { - delete aTab._recordingTabOpenPlain; - // While we do have a telemetry probe NEWTAB_PAGE_ENABLED to monitor newtab preview, it'll be - // easier to overview the data without slicing by it. Hence the additional histograms with _PREVIEW. - let preview = this._browserNewtabpageEnabled ? "_PREVIEW" : ""; - Services.telemetry.getHistogramById("FX_TAB_ANIM_OPEN" + preview + "_FRAME_INTERVAL_MS").add(averageInterval); - } - } -*/ - ]]> - - - @@ -5355,8 +5278,6 @@ var tab = event.target; - //this._handleTabTelemetryEnd(tab); - if (tab.getAttribute("fadein") == "true") { if (tab._fullyOpen) this.adjustTabstrip(); @@ -6389,7 +6310,7 @@ if (val) { this.setAttribute("label", val); this.removeAttribute("inactive"); - this._calcMouseTargetRect(); + this._mouseTargetRect = null; MousePosTracker.addListener(this); } else { this.setAttribute("inactive", "true"); @@ -6405,6 +6326,9 @@ @@ -6429,7 +6353,7 @@ switch (event.type) { case "resize": - this._calcMouseTargetRect(); + this._mouseTargetRect = null; break; } ]]> @@ -6460,7 +6384,7 @@ if (!this.hasAttribute("sizelimit")) { this.setAttribute("sizelimit", "true"); - this._calcMouseTargetRect(); + this._mouseTargetRect = null; } diff --git a/browser/components/uitour/UITour.jsm b/browser/components/uitour/UITour.jsm index 137a81195..3c835bdb0 100644 --- a/browser/components/uitour/UITour.jsm +++ b/browser/components/uitour/UITour.jsm @@ -735,7 +735,12 @@ this.UITour = { } } - this.initForBrowser(browser, window); + // For performance reasons, only call initForBrowser if we did something + // that will require a teardownTourForBrowser call later. + // getConfiguration (called from about:home) doesn't require any future + // uninitialization. + if (action != "getConfiguration") + this.initForBrowser(browser, window); return true; }, diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 080b0302f..e824c9541 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -4890,12 +4890,6 @@ nsGlobalWindow::GetOuterSize(ErrorResult& aError) return nsIntSize(0, 0); } - nsGlobalWindow* rootWindow = - static_cast(GetPrivateRoot()); - if (rootWindow) { - rootWindow->FlushPendingNotifications(Flush_Layout); - } - nsIntSize sizeDevPixels; aError = treeOwnerAsWin->GetSize(&sizeDevPixels.width, &sizeDevPixels.height); if (aError.Failed()) { @@ -5077,11 +5071,7 @@ nsGlobalWindow::GetInnerScreenRect() return nsRect(); } - nsGlobalWindow* rootWindow = - static_cast(GetPrivateRoot()); - if (rootWindow) { - rootWindow->FlushPendingNotifications(Flush_Layout); - } + EnsureSizeUpToDate(); if (!mDocShell) { return nsRect(); diff --git a/dom/events/IMEStateManager.cpp b/dom/events/IMEStateManager.cpp index 96fcf16b3..16b4cddc7 100644 --- a/dom/events/IMEStateManager.cpp +++ b/dom/events/IMEStateManager.cpp @@ -171,6 +171,7 @@ TextCompositionArray* IMEStateManager::sTextCompositions = nullptr; bool IMEStateManager::sInstalledMenuKeyboardListener = false; bool IMEStateManager::sIsGettingNewIMEState = false; bool IMEStateManager::sCheckForIMEUnawareWebApps = false; +bool IMEStateManager::sInputModeSupported = false; bool IMEStateManager::sRemoteHasFocus = false; // static @@ -181,6 +182,11 @@ IMEStateManager::Init() &sCheckForIMEUnawareWebApps, "intl.ime.hack.on_ime_unaware_apps.fire_key_events_for_composition", false); + + Preferences::AddBoolVarCache( + &sInputModeSupported, + "dom.forms.inputmode", + false); } // static @@ -1036,7 +1042,7 @@ IMEStateManager::SetIMEState(const IMEState& aState, context.mHTMLInputType.Assign(nsGkAtoms::textarea->GetUTF16String()); } - if (Preferences::GetBool("dom.forms.inputmode", false) || + if (sInputModeSupported || nsContentUtils::IsChromeDoc(aContent->OwnerDoc())) { aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::inputmode, context.mHTMLInputInputmode); diff --git a/dom/events/IMEStateManager.h b/dom/events/IMEStateManager.h index 1ff31743c..9c2df949e 100644 --- a/dom/events/IMEStateManager.h +++ b/dom/events/IMEStateManager.h @@ -251,6 +251,7 @@ protected: static bool sInstalledMenuKeyboardListener; static bool sIsGettingNewIMEState; static bool sCheckForIMEUnawareWebApps; + static bool sInputModeSupported; static bool sRemoteHasFocus; class MOZ_STACK_CLASS GettingNewIMEStateBlocker final diff --git a/editor/libeditor/DeleteRangeTxn.cpp b/editor/libeditor/DeleteRangeTxn.cpp index 58ce18a97..1b14c5629 100644 --- a/editor/libeditor/DeleteRangeTxn.cpp +++ b/editor/libeditor/DeleteRangeTxn.cpp @@ -65,11 +65,19 @@ DeleteRangeTxn::DoTransaction() MOZ_ASSERT(mRange && mEditor); nsresult res; + // Swap mRange out into a stack variable, so we make sure to null it + // out on return from this function. Once this function returns, we no longer + // need mRange, and keeping it alive in the long term slows down all + // DOM mutations because it's observing them. + // (Modified from bug 1349940.) + RefPtr rangeToDelete; + rangeToDelete.swap(mRange); + // build the child transactions - nsCOMPtr startParent = mRange->GetStartParent(); - int32_t startOffset = mRange->StartOffset(); - nsCOMPtr endParent = mRange->GetEndParent(); - int32_t endOffset = mRange->EndOffset(); + nsCOMPtr startParent = rangeToDelete->GetStartParent(); + int32_t startOffset = rangeToDelete->StartOffset(); + nsCOMPtr endParent = rangeToDelete->GetEndParent(); + int32_t endOffset = rangeToDelete->EndOffset(); MOZ_ASSERT(startParent && endParent); if (startParent == endParent) { @@ -82,7 +90,7 @@ DeleteRangeTxn::DoTransaction() res = CreateTxnsToDeleteContent(startParent, startOffset, nsIEditor::eNext); NS_ENSURE_SUCCESS(res, res); // delete the intervening nodes - res = CreateTxnsToDeleteNodesBetween(); + res = CreateTxnsToDeleteNodesBetween(rangeToDelete); NS_ENSURE_SUCCESS(res, res); // delete the relevant content in the end node res = CreateTxnsToDeleteContent(endParent, endOffset, nsIEditor::ePrevious); @@ -110,16 +118,12 @@ DeleteRangeTxn::DoTransaction() NS_IMETHODIMP DeleteRangeTxn::UndoTransaction() { - MOZ_ASSERT(mRange && mEditor); - return EditAggregateTxn::UndoTransaction(); } NS_IMETHODIMP DeleteRangeTxn::RedoTransaction() { - MOZ_ASSERT(mRange && mEditor); - return EditAggregateTxn::RedoTransaction(); } @@ -211,11 +215,11 @@ DeleteRangeTxn::CreateTxnsToDeleteContent(nsINode* aNode, } nsresult -DeleteRangeTxn::CreateTxnsToDeleteNodesBetween() +DeleteRangeTxn::CreateTxnsToDeleteNodesBetween(nsRange *aRangeToDelete) { nsCOMPtr iter = NS_NewContentSubtreeIterator(); - nsresult res = iter->Init(mRange); + nsresult res = iter->Init(aRangeToDelete); NS_ENSURE_SUCCESS(res, res); while (!iter->IsDone()) { diff --git a/editor/libeditor/DeleteRangeTxn.h b/editor/libeditor/DeleteRangeTxn.h index 680762e21..be713cd44 100644 --- a/editor/libeditor/DeleteRangeTxn.h +++ b/editor/libeditor/DeleteRangeTxn.h @@ -54,7 +54,7 @@ protected: int32_t aStartOffset, int32_t aEndOffset); - nsresult CreateTxnsToDeleteNodesBetween(); + nsresult CreateTxnsToDeleteNodesBetween(nsRange *aRangeToDelete); nsresult CreateTxnsToDeleteContent(nsINode* aParent, int32_t aOffset, @@ -63,6 +63,8 @@ protected: protected: /** p1 in the range */ + /* After bug 1349940, this is only non-null until DoTransaction is called + and we convert it into child transactions. */ RefPtr mRange; /** the editor for this transaction */ diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 2e66c4e18..1404683ef 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -1046,7 +1046,8 @@ public: mContainerBounds(aContainerBounds), mParameters(aParameters), mPaintedLayerDataTree(*this, aBackgroundColor), - mFlattenToSingleLayer(aFlattenToSingleLayer) + mFlattenToSingleLayer(aFlattenToSingleLayer), + mLastDisplayPortAGR(nullptr) { nsPresContext* presContext = aContainerFrame->PresContext(); mAppUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); @@ -1364,6 +1365,12 @@ protected: bool ChooseAnimatedGeometryRoot(const nsDisplayList& aList, AnimatedGeometryRoot **aAnimatedGeometryRoot); + /** + * Get the display port for an AGR. + * The result would be cached for later reusing. + */ + nsRect GetDisplayPortForAnimatedGeometryRoot(AnimatedGeometryRoot* aAnimatedGeometryRoot); + nsDisplayListBuilder* mBuilder; LayerManager* mManager; FrameLayerBuilder* mLayerBuilder; @@ -1420,6 +1427,8 @@ protected: nsDataHashtable, RefPtr> mRecycledMaskImageLayers; + AnimatedGeometryRoot* mLastDisplayPortAGR; + nsRect mLastDisplayPortRect; }; class PaintedDisplayItemLayerUserData : public LayerUserData @@ -3703,6 +3712,34 @@ ContainerState::ChooseAnimatedGeometryRoot(const nsDisplayList& aList, return false; } +nsRect +ContainerState::GetDisplayPortForAnimatedGeometryRoot(AnimatedGeometryRoot* aAnimatedGeometryRoot) +{ +// Faster version of the code from ComputeOpaqueRect (after bug 1331342). + if (mLastDisplayPortAGR == aAnimatedGeometryRoot) { + return mLastDisplayPortRect; + } + + nsIScrollableFrame* sf = nsLayoutUtils::GetScrollableFrameFor(*aAnimatedGeometryRoot); + if (sf == nullptr) { + return nsRect(); + } + + mLastDisplayPortAGR = aAnimatedGeometryRoot; + nsRect& displayport = mLastDisplayPortRect; + + bool usingDisplayport = + nsLayoutUtils::GetDisplayPort((*aAnimatedGeometryRoot)->GetContent(), &displayport); + if (!usingDisplayport) { + // No async scrolling, so all that matters is that the layer contents + // cover the scrollport. + displayport = sf->GetScrollPortRect(); + } + nsIFrame* scrollFrame = do_QueryFrame(sf); + displayport += scrollFrame->GetOffsetToCrossDoc(mContainerReferenceFrame); + return displayport; +} + nsIntRegion ContainerState::ComputeOpaqueRect(nsDisplayItem* aItem, AnimatedGeometryRoot* aAnimatedGeometryRoot, @@ -3740,6 +3777,7 @@ ContainerState::ComputeOpaqueRect(nsDisplayItem* aItem, } opaquePixels = ScaleRegionToInsidePixels(opaqueClipped, snapOpaque); +#if(0) nsIScrollableFrame* sf = nsLayoutUtils::GetScrollableFrameFor(*aAnimatedGeometryRoot); if (sf) { nsRect displayport; @@ -3756,6 +3794,17 @@ ContainerState::ComputeOpaqueRect(nsDisplayItem* aItem, *aOpaqueForAnimatedGeometryRootParent = true; } } +#else +// backbugs from bug 1220466 and bug 1331342 + if (IsInInactiveLayer()) return opaquePixels; + + const nsRect& displayport = + GetDisplayPortForAnimatedGeometryRoot(aAnimatedGeometryRoot); + if (!displayport.IsEmpty() && + opaquePixels.Contains(ScaleRegionToNearestPixels(displayport))) { + *aOpaqueForAnimatedGeometryRootParent = true; + } +#endif // } return opaquePixels; } @@ -4041,11 +4090,11 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList) // clip we care about is the overflow:hidden clip on the scrollbar. mPaintedLayerDataTree.AddingOwnLayer(animatedGeometryRoot->mParentAGR, clipPtr, - uniformColorPtr); + IsInInactiveLayer() ? nullptr : uniformColorPtr); } else if (prerenderedTransform) { mPaintedLayerDataTree.AddingOwnLayer(animatedGeometryRoot, clipPtr, - uniformColorPtr); + IsInInactiveLayer() ? nullptr : uniformColorPtr); } else { // Using itemVisibleRect here isn't perfect. itemVisibleRect can be // larger or smaller than the potential bounds of item's contents in @@ -4056,7 +4105,8 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList) // Time will tell whether this is good enough, or whether we need to do // something more sophisticated here. mPaintedLayerDataTree.AddingOwnLayer(animatedGeometryRoot, - &itemVisibleRect, uniformColorPtr); + &itemVisibleRect, + IsInInactiveLayer() ? nullptr : uniformColorPtr); } mParameters.mBackgroundColor = uniformColor; diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 4a9adc311..a7f85ddb5 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -5444,10 +5444,12 @@ nsTextFrame::ComputeSelectionUnderlineHeight( // the default font size, we should use the actual font size because the // computed value from the default font size can be too thick for the // current font size. - int32_t defaultFontSize = - aPresContext->AppUnitsToDevPixels(nsStyleFont(aPresContext).mFont.size); - gfxFloat fontSize = std::min(gfxFloat(defaultFontSize), - aFontMetrics.emHeight); + nscoord defaultFontSize = aPresContext->GetDefaultFont( + kPresContext_DefaultVariableFont_ID, nullptr)->size; + int32_t zoomedFontSize = aPresContext->AppUnitsToDevPixels( + nsStyleFont::ZoomText(aPresContext, defaultFontSize)); + gfxFloat fontSize = std::min(gfxFloat(zoomedFontSize), + aFontMetrics.emHeight); fontSize = std::max(fontSize, 1.0); return ceil(fontSize / 20); } diff --git a/layout/xul/tree/nsTreeBodyFrame.cpp b/layout/xul/tree/nsTreeBodyFrame.cpp index 3cf7d3807..c8a1d5d78 100644 --- a/layout/xul/tree/nsTreeBodyFrame.cpp +++ b/layout/xul/tree/nsTreeBodyFrame.cpp @@ -909,6 +909,9 @@ nsTreeBodyFrame::CheckOverflow(const ScrollParts& aParts) } } + if (!horizontalOverflowChanged && !verticalOverflowChanged) + return; + nsWeakFrame weakFrame(this); RefPtr presContext = PresContext(); diff --git a/toolkit/content/widgets/autocomplete.xml b/toolkit/content/widgets/autocomplete.xml index c25a13701..fcf35d8b1 100644 --- a/toolkit/content/widgets/autocomplete.xml +++ b/toolkit/content/widgets/autocomplete.xml @@ -1035,12 +1035,17 @@ extends="chrome://global/content/bindings/popup.xml#popup"> this.maxRows) { + // when clearing the selection (val == -1, so selectedItem will be + // null), we want to scroll back to the top. see bug #406194 + this.richlistbox.ensureElementIsVisible( + this.richlistbox.selectedItem || this.richlistbox.firstChild); + } return val; ]]>