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