diff options
Diffstat (limited to 'layout/xul/nsXULPopupManager.cpp')
-rw-r--r-- | layout/xul/nsXULPopupManager.cpp | 70 |
1 files changed, 53 insertions, 17 deletions
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, |