diff options
Diffstat (limited to 'layout')
-rw-r--r-- | layout/generic/ReflowInput.cpp | 3 | ||||
-rw-r--r-- | layout/generic/ReflowInput.h | 5 | ||||
-rw-r--r-- | layout/generic/nsColumnSetFrame.cpp | 2 | ||||
-rw-r--r-- | layout/generic/nsImageMap.cpp | 4 | ||||
-rw-r--r-- | layout/xul/nsXULPopupManager.cpp | 70 | ||||
-rw-r--r-- | layout/xul/nsXULPopupManager.h | 11 |
6 files changed, 75 insertions, 20 deletions
diff --git a/layout/generic/ReflowInput.cpp b/layout/generic/ReflowInput.cpp index 2f91f5f65c..c8b01fff19 100644 --- a/layout/generic/ReflowInput.cpp +++ b/layout/generic/ReflowInput.cpp @@ -304,7 +304,8 @@ bool ReflowInput::ShouldReflowAllKids() const { // frames NS_FRAME_CONTAINS_RELATIVE_BSIZE is marked on. return mFrame->HasAnyStateBits(NS_FRAME_IS_DIRTY) || IsIResize() || (IsBResize() && - mFrame->HasAnyStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE)); + mFrame->HasAnyStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE)) || + mFlags.mIsInLastColumnBalancingReflow; } void ReflowInput::SetComputedISize(nscoord aComputedISize, diff --git a/layout/generic/ReflowInput.h b/layout/generic/ReflowInput.h index 0b7f64b543..370ccc1af2 100644 --- a/layout/generic/ReflowInput.h +++ b/layout/generic/ReflowInput.h @@ -503,6 +503,11 @@ struct ReflowInput : public SizeComputationInput { // nsColumnSetFrame is balancing columns bool mIsColumnBalancing : 1; + // We have an ancestor nsColumnSetFrame performing the last column balancing + // reflow. The available block-size of the last column might become + // unconstrained. + bool mIsInLastColumnBalancingReflow : 1; + // True if ColumnSetWrapperFrame has a constrained block-size, and is going // to consume all of its block-size in this fragment. This bit is passed to // nsColumnSetFrame to determine whether to give up balancing and create diff --git a/layout/generic/nsColumnSetFrame.cpp b/layout/generic/nsColumnSetFrame.cpp index 699afaece7..ec349e9ab4 100644 --- a/layout/generic/nsColumnSetFrame.cpp +++ b/layout/generic/nsColumnSetFrame.cpp @@ -662,6 +662,8 @@ nsColumnSetFrame::ColumnBalanceData nsColumnSetFrame::ReflowColumns( }(); kidReflowInput.mFlags.mTableIsSplittable = false; kidReflowInput.mFlags.mIsColumnBalancing = aConfig.mIsBalancing; + kidReflowInput.mFlags.mIsInLastColumnBalancingReflow = + aConfig.mIsLastBalancingReflow; kidReflowInput.mBreakType = ReflowInput::BreakType::Column; // We need to reflow any float placeholders, even if our column block-size diff --git a/layout/generic/nsImageMap.cpp b/layout/generic/nsImageMap.cpp index 8ddd9338f2..ce621fb6be 100644 --- a/layout/generic/nsImageMap.cpp +++ b/layout/generic/nsImageMap.cpp @@ -467,7 +467,7 @@ void PolyArea::Draw(nsIFrame* aFrame, DrawTarget& aDrawTarget, Point p1(pc->CSSPixelsToDevPixels(mCoords[0]), pc->CSSPixelsToDevPixels(mCoords[1])); Point p2, p1snapped, p2snapped; - for (int32_t i = 2; i < mNumCoords; i += 2) { + for (int32_t i = 2; i < mNumCoords - 1; i += 2) { p2.x = pc->CSSPixelsToDevPixels(mCoords[i]); p2.y = pc->CSSPixelsToDevPixels(mCoords[i + 1]); p1snapped = p1; @@ -493,7 +493,7 @@ void PolyArea::GetRect(nsIFrame* aFrame, nsRect& aRect) { nscoord x1, x2, y1, y2, xtmp, ytmp; x1 = x2 = nsPresContext::CSSPixelsToAppUnits(mCoords[0]); y1 = y2 = nsPresContext::CSSPixelsToAppUnits(mCoords[1]); - for (int32_t i = 2; i < mNumCoords; i += 2) { + for (int32_t i = 2; i < mNumCoords - 1; i += 2) { xtmp = nsPresContext::CSSPixelsToAppUnits(mCoords[i]); ytmp = nsPresContext::CSSPixelsToAppUnits(mCoords[i + 1]); x1 = x1 < xtmp ? x1 : xtmp; diff --git a/layout/xul/nsXULPopupManager.cpp b/layout/xul/nsXULPopupManager.cpp index fb881b86eb..79ea7d0470 100644 --- a/layout/xul/nsXULPopupManager.cpp +++ b/layout/xul/nsXULPopupManager.cpp @@ -55,6 +55,7 @@ #include "mozilla/MouseEvents.h" #include "mozilla/PresShell.h" #include "mozilla/Services.h" +#include "mozilla/StaticPrefs_layout.h" #include "mozilla/StaticPrefs_ui.h" #include "mozilla/widget/nsAutoRollup.h" #include "mozilla/widget/NativeMenuSupport.h" @@ -209,7 +210,43 @@ UniquePtr<nsMenuChainItem> nsMenuChainItem::Detach() { return std::move(mParent); } +void nsXULPopupManager::AddMenuChainItem(UniquePtr<nsMenuChainItem> aItem) { + PopupType popupType = aItem->Frame()->GetPopupType(); + if (StaticPrefs::layout_cursor_disable_for_popups() && + popupType != PopupType::Tooltip) { + if (nsPresContext* rootPC = + aItem->Frame()->PresContext()->GetRootPresContext()) { + if (nsCOMPtr<nsIWidget> rootWidget = rootPC->GetRootWidget()) { + rootWidget->SetCustomCursorAllowed(false); + } + } + } + + // popups normally hide when an outside click occurs. Panels may use + // the noautohide attribute to disable this behaviour. It is expected + // that the application will hide these popups manually. The tooltip + // listener will handle closing the tooltip also. + nsIContent* oldmenu = nullptr; + if (mPopups) { + oldmenu = mPopups->Element(); + } + aItem->SetParent(std::move(mPopups)); + mPopups = std::move(aItem); + SetCaptureState(oldmenu); +} + void nsXULPopupManager::RemoveMenuChainItem(nsMenuChainItem* aItem) { + nsPresContext* rootPC = aItem->Frame()->PresContext()->GetRootPresContext(); + auto matcher = [&](nsMenuChainItem* aChainItem) -> bool { + return aChainItem != aItem && + rootPC == aChainItem->Frame()->PresContext()->GetRootPresContext(); + }; + if (rootPC && !FirstMatchingPopup(matcher)) { + if (nsCOMPtr<nsIWidget> rootWidget = rootPC->GetRootWidget()) { + rootWidget->SetCustomCursorAllowed(true); + } + } + auto parent = aItem->Detach(); if (auto* child = aItem->GetChild()) { MOZ_ASSERT(aItem != mPopups, @@ -225,6 +262,17 @@ void nsXULPopupManager::RemoveMenuChainItem(nsMenuChainItem* aItem) { } } +nsMenuChainItem* nsXULPopupManager::FirstMatchingPopup( + mozilla::FunctionRef<bool(nsMenuChainItem*)> aMatcher) const { + for (nsMenuChainItem* popup = mPopups.get(); popup; + popup = popup->GetParent()) { + if (aMatcher(popup)) { + return popup; + } + } + return nullptr; +} + void nsMenuChainItem::UpdateFollowAnchor() { mFollowAnchor = mFrame->ShouldFollowAnchor(mCurrentRect); } @@ -1140,17 +1188,7 @@ void nsXULPopupManager::ShowPopupCallback(Element* aPopup, item->UpdateFollowAnchor(); - // popups normally hide when an outside click occurs. Panels may use - // the noautohide attribute to disable this behaviour. It is expected - // that the application will hide these popups manually. The tooltip - // listener will handle closing the tooltip also. - nsIContent* oldmenu = nullptr; - if (mPopups) { - oldmenu = mPopups->Element(); - } - item->SetParent(std::move(mPopups)); - mPopups = std::move(item); - SetCaptureState(oldmenu); + AddMenuChainItem(std::move(item)); NS_ENSURE_TRUE_VOID(weakFrame.IsAlive()); RefPtr popup = &aPopupFrame->PopupElement(); @@ -1166,12 +1204,10 @@ void nsXULPopupManager::ShowPopupCallback(Element* aPopup, } nsMenuChainItem* nsXULPopupManager::FindPopup(Element* aPopup) const { - for (nsMenuChainItem* item = mPopups.get(); item; item = item->GetParent()) { - if (item->Frame()->GetContent() == aPopup) { - return item; - } - } - return nullptr; + auto matcher = [&](nsMenuChainItem* aItem) -> bool { + return aItem->Frame()->GetContent() == aPopup; + }; + return FirstMatchingPopup(matcher); } void nsXULPopupManager::HidePopup(Element* aPopup, HidePopupOptions aOptions, diff --git a/layout/xul/nsXULPopupManager.h b/layout/xul/nsXULPopupManager.h index d056322deb..78d2b2648c 100644 --- a/layout/xul/nsXULPopupManager.h +++ b/layout/xul/nsXULPopupManager.h @@ -23,6 +23,7 @@ #include "nsIObserver.h" #include "nsThreadUtils.h" #include "mozilla/Attributes.h" +#include "mozilla/FunctionRef.h" #include "mozilla/widget/InitData.h" #include "mozilla/widget/NativeMenu.h" @@ -551,6 +552,13 @@ class nsXULPopupManager final : public nsIDOMEventListener, void UpdatePopupPositions(nsRefreshDriver* aRefreshDriver); /** + * Get the first nsMenuChainItem that is matched by the matching callback + * function provided. + */ + nsMenuChainItem* FirstMatchingPopup( + mozilla::FunctionRef<bool(nsMenuChainItem*)> aMatcher) const; + + /** * Enable or disable anchor following on the popup if needed. */ void UpdateFollowAnchor(nsMenuPopupFrame* aPopup); @@ -733,6 +741,9 @@ class nsXULPopupManager final : public nsIDOMEventListener, return GetRollupItem(RollupKind::Menu); } + // Add the chain item to the chain and update mPopups to point to it. + void AddMenuChainItem(mozilla::UniquePtr<nsMenuChainItem>); + // Removes the chain item from the chain and deletes it. void RemoveMenuChainItem(nsMenuChainItem*); |