From a7c14e2f29831f4bc5eb18e23e55eb6f7a4e3431 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 8 Apr 2024 17:12:12 +0200 Subject: Merging upstream version 115.8.0esr. Signed-off-by: Daniel Baumann --- layout/xul/nsXULPopupManager.cpp | 70 ++++++++++++++++++++++++++++++---------- layout/xul/nsXULPopupManager.h | 11 +++++++ 2 files changed, 64 insertions(+), 17 deletions(-) (limited to 'layout/xul') 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::Detach() { return std::move(mParent); } +void nsXULPopupManager::AddMenuChainItem(UniquePtr 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 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 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 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" @@ -550,6 +551,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 aMatcher) const; + /** * Enable or disable anchor following on the popup if needed. */ @@ -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); + // Removes the chain item from the chain and deletes it. void RemoveMenuChainItem(nsMenuChainItem*); -- cgit v1.2.3