summaryrefslogtreecommitdiffstats
path: root/layout/xul/nsXULPopupManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layout/xul/nsXULPopupManager.cpp')
-rw-r--r--layout/xul/nsXULPopupManager.cpp70
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,