mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 07:13:20 +00:00
Bug 1811487 - Clean-up popup hide / rollup APIs. r=cmartin,stransky
I'm about to extend them for bug 1811486, where I want to force in some cases the rolled up popups to hide synchronously. These APIs use a ton of boolean arguments that make them error prone, so refactor them a bit to use strongly typed enums and flags. Differential Revision: https://phabricator.services.mozilla.com/D167381
This commit is contained in:
parent
89a7e7fe31
commit
46dd8a0d40
@ -43,8 +43,8 @@ add_task(async function test_PanelMultiView_toggle_with_other_popup() {
|
|||||||
eventTypeToWait: "mouseup",
|
eventTypeToWait: "mouseup",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (AppConstants.platform == "win") {
|
// On Windows and macOS, the operation will close both popups.
|
||||||
// On Windows, the operation will close both popups.
|
if (AppConstants.platform == "win" || AppConstants.platform == "macosx") {
|
||||||
await gCUITestUtils.hidePanelMultiView(PanelUI.panel, clickFn);
|
await gCUITestUtils.hidePanelMultiView(PanelUI.panel, clickFn);
|
||||||
await new Promise(resolve => executeSoon(resolve));
|
await new Promise(resolve => executeSoon(resolve));
|
||||||
|
|
||||||
|
@ -290,14 +290,11 @@ add_task(async function testTabOpenMenulist() {
|
|||||||
await shown;
|
await shown;
|
||||||
ok(gMainMenulist.open, "menulist open");
|
ok(gMainMenulist.open, "menulist open");
|
||||||
let menuHidden = BrowserTestUtils.waitForEvent(popup, "popuphidden");
|
let menuHidden = BrowserTestUtils.waitForEvent(popup, "popuphidden");
|
||||||
let panelHidden = BrowserTestUtils.waitForEvent(gPanel, "popuphidden");
|
|
||||||
EventUtils.synthesizeKey("KEY_Tab");
|
EventUtils.synthesizeKey("KEY_Tab");
|
||||||
await menuHidden;
|
await menuHidden;
|
||||||
ok(!gMainMenulist.open, "menulist closed after Tab");
|
ok(!gMainMenulist.open, "menulist closed after Tab");
|
||||||
// Tab in an open menulist closes the menulist, but also dismisses the panel
|
is(gPanel.state, "open", "Panel should be open");
|
||||||
// above it (bug 1566673). So, we just wait for the panel to hide rather than
|
await hidePopup();
|
||||||
// using hidePopup().
|
|
||||||
await panelHidden;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (AppConstants.platform == "macosx") {
|
if (AppConstants.platform == "macosx") {
|
||||||
@ -327,14 +324,11 @@ if (AppConstants.platform == "macosx") {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let menuHidden = BrowserTestUtils.waitForEvent(popup, "popuphidden");
|
let menuHidden = BrowserTestUtils.waitForEvent(popup, "popuphidden");
|
||||||
let panelHidden = BrowserTestUtils.waitForEvent(gPanel, "popuphidden");
|
|
||||||
EventUtils.synthesizeKey("KEY_Tab");
|
EventUtils.synthesizeKey("KEY_Tab");
|
||||||
await menuHidden;
|
await menuHidden;
|
||||||
ok(!gMainMenulist.open, "menulist closed after Tab");
|
ok(!gMainMenulist.open, "menulist closed after Tab");
|
||||||
// Tab in an open menulist closes the menulist, but also dismisses the panel
|
is(gPanel.state, "open", "Panel should be open");
|
||||||
// above it (bug 1566673). So, we just wait for the panel to hide rather than
|
await hidePopup();
|
||||||
// using hidePopup().
|
|
||||||
await panelHidden;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,9 +95,9 @@ void XULButtonElement::HandleEnterKeyPress(WidgetEvent& aEvent) {
|
|||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
if (XULPopupElement* popup = GetContainingPopupElement()) {
|
if (XULPopupElement* popup = GetContainingPopupElement()) {
|
||||||
if (nsXULPopupManager* pm = nsXULPopupManager::GetInstance()) {
|
if (nsXULPopupManager* pm = nsXULPopupManager::GetInstance()) {
|
||||||
pm->HidePopup(popup, /* aHideChain = */ true,
|
pm->HidePopup(
|
||||||
/* aDeselectMenu = */ true, /* aAsynchronous = */ true,
|
popup, {HidePopupOption::HideChain, HidePopupOption::DeselectMenu,
|
||||||
/* aIsCancel = */ false);
|
HidePopupOption::Async});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -211,7 +211,11 @@ void XULButtonElement::CloseMenuPopup(bool aDeselectMenu) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (auto* popup = GetMenuPopupContent()) {
|
if (auto* popup = GetMenuPopupContent()) {
|
||||||
pm->HidePopup(popup, false, aDeselectMenu, true, false);
|
HidePopupOptions options{HidePopupOption::Async};
|
||||||
|
if (aDeselectMenu) {
|
||||||
|
options += HidePopupOption::DeselectMenu;
|
||||||
|
}
|
||||||
|
pm->HidePopup(popup, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,9 +106,14 @@ void XULPopupElement::OpenPopupAtScreenRect(const nsAString& aPosition,
|
|||||||
|
|
||||||
void XULPopupElement::HidePopup(bool aCancel) {
|
void XULPopupElement::HidePopup(bool aCancel) {
|
||||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||||
if (pm) {
|
if (!pm) {
|
||||||
pm->HidePopup(this, false, true, false, aCancel);
|
return;
|
||||||
}
|
}
|
||||||
|
HidePopupOptions options{HidePopupOption::DeselectMenu};
|
||||||
|
if (aCancel) {
|
||||||
|
options += HidePopupOption::IsRollup;
|
||||||
|
}
|
||||||
|
pm->HidePopup(this, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Modifiers ConvertModifiers(const ActivateMenuItemOptions& aModifiers) {
|
static Modifiers ConvertModifiers(const ActivateMenuItemOptions& aModifiers) {
|
||||||
|
@ -170,7 +170,9 @@ void nsXULPopupListener::ClosePopup() {
|
|||||||
// popup is hidden. Use asynchronous hiding just to be safe so we don't
|
// popup is hidden. Use asynchronous hiding just to be safe so we don't
|
||||||
// fire events during destruction.
|
// fire events during destruction.
|
||||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||||
if (pm) pm->HidePopup(mPopupContent, false, true, true, false);
|
if (pm)
|
||||||
|
pm->HidePopup(mPopupContent,
|
||||||
|
{HidePopupOption::DeselectMenu, HidePopupOption::Async});
|
||||||
mPopupContent = nullptr; // release the popup
|
mPopupContent = nullptr; // release the popup
|
||||||
}
|
}
|
||||||
} // ClosePopup
|
} // ClosePopup
|
||||||
|
@ -207,7 +207,7 @@ nsresult nsMenuBarListener::KeyUp(Event* aKeyEvent) {
|
|||||||
// handle key events when menubar is active and IME should be
|
// handle key events when menubar is active and IME should be
|
||||||
// disabled.
|
// disabled.
|
||||||
if (nsXULPopupManager* pm = nsXULPopupManager::GetInstance()) {
|
if (nsXULPopupManager* pm = nsXULPopupManager::GetInstance()) {
|
||||||
pm->Rollup(0, false, nullptr, nullptr);
|
pm->Rollup({});
|
||||||
}
|
}
|
||||||
// If menubar active state is changed or the menubar is destroyed
|
// If menubar active state is changed or the menubar is destroyed
|
||||||
// during closing the popups, we should do nothing anymore.
|
// during closing the popups, we should do nothing anymore.
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "X11UndefineNone.h"
|
#include "X11UndefineNone.h"
|
||||||
|
#include "nsXULPopupManager.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using mozilla::dom::Document;
|
using mozilla::dom::Document;
|
||||||
@ -2460,7 +2461,8 @@ void nsMenuPopupFrame::CheckForAnchorChange(nsRect& aRect) {
|
|||||||
if (pm) {
|
if (pm) {
|
||||||
// As the caller will be iterating over the open popups, hide
|
// As the caller will be iterating over the open popups, hide
|
||||||
// asyncronously.
|
// asyncronously.
|
||||||
pm->HidePopup(mContent, false, true, true, false);
|
pm->HidePopup(mContent,
|
||||||
|
{HidePopupOption::DeselectMenu, HidePopupOption::Async});
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -278,14 +278,12 @@ nsXULPopupManager* nsXULPopupManager::GetInstance() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool nsXULPopupManager::RollupTooltips() {
|
bool nsXULPopupManager::RollupTooltips() {
|
||||||
return RollupInternal(RollupKind::Tooltip, UINT32_MAX, false, nullptr,
|
return RollupInternal(RollupKind::Tooltip, {}, nullptr);
|
||||||
nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsXULPopupManager::Rollup(uint32_t aCount, bool aFlush,
|
bool nsXULPopupManager::Rollup(const RollupOptions& aOptions,
|
||||||
const LayoutDeviceIntPoint* aPos,
|
|
||||||
nsIContent** aLastRolledUp) {
|
nsIContent** aLastRolledUp) {
|
||||||
return RollupInternal(RollupKind::Menu, aCount, aFlush, aPos, aLastRolledUp);
|
return RollupInternal(RollupKind::Menu, aOptions, aLastRolledUp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsXULPopupManager::RollupNativeMenu() {
|
bool nsXULPopupManager::RollupNativeMenu() {
|
||||||
@ -296,9 +294,8 @@ bool nsXULPopupManager::RollupNativeMenu() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsXULPopupManager::RollupInternal(RollupKind aKind, uint32_t aCount,
|
bool nsXULPopupManager::RollupInternal(RollupKind aKind,
|
||||||
bool aFlush,
|
const RollupOptions& aOptions,
|
||||||
const LayoutDeviceIntPoint* pos,
|
|
||||||
nsIContent** aLastRolledUp) {
|
nsIContent** aLastRolledUp) {
|
||||||
if (aLastRolledUp) {
|
if (aLastRolledUp) {
|
||||||
*aLastRolledUp = nullptr;
|
*aLastRolledUp = nullptr;
|
||||||
@ -349,7 +346,7 @@ bool nsXULPopupManager::RollupInternal(RollupKind aKind, uint32_t aCount,
|
|||||||
// This would be used to allow adjusting the caret position in an
|
// This would be used to allow adjusting the caret position in an
|
||||||
// autocomplete field without hiding the popup for example.
|
// autocomplete field without hiding the popup for example.
|
||||||
bool noRollupOnAnchor =
|
bool noRollupOnAnchor =
|
||||||
(!consume && pos &&
|
(!consume && aOptions.mPoint &&
|
||||||
item->Frame()->GetContent()->AsElement()->AttrValueIs(
|
item->Frame()->GetContent()->AsElement()->AttrValueIs(
|
||||||
kNameSpaceID_None, nsGkAtoms::norolluponanchor, nsGkAtoms::_true,
|
kNameSpaceID_None, nsGkAtoms::norolluponanchor, nsGkAtoms::_true,
|
||||||
eCaseMatters));
|
eCaseMatters));
|
||||||
@ -358,7 +355,7 @@ bool nsXULPopupManager::RollupInternal(RollupKind aKind, uint32_t aCount,
|
|||||||
// when the click was over the anchor. This way, clicking on a menu doesn't
|
// when the click was over the anchor. This way, clicking on a menu doesn't
|
||||||
// reopen the menu.
|
// reopen the menu.
|
||||||
if ((consumeResult == ConsumeOutsideClicks_ParentOnly || noRollupOnAnchor) &&
|
if ((consumeResult == ConsumeOutsideClicks_ParentOnly || noRollupOnAnchor) &&
|
||||||
pos) {
|
aOptions.mPoint) {
|
||||||
nsMenuPopupFrame* popupFrame = item->Frame();
|
nsMenuPopupFrame* popupFrame = item->Frame();
|
||||||
CSSIntRect anchorRect = [&] {
|
CSSIntRect anchorRect = [&] {
|
||||||
if (popupFrame->IsAnchored()) {
|
if (popupFrame->IsAnchored()) {
|
||||||
@ -399,7 +396,8 @@ bool nsXULPopupManager::RollupInternal(RollupKind aKind, uint32_t aCount,
|
|||||||
// event will get consumed, so here only a quick coordinates check is
|
// event will get consumed, so here only a quick coordinates check is
|
||||||
// done rather than a slower complete check of what is at that location.
|
// done rather than a slower complete check of what is at that location.
|
||||||
nsPresContext* presContext = item->Frame()->PresContext();
|
nsPresContext* presContext = item->Frame()->PresContext();
|
||||||
CSSIntPoint posCSSPixels = presContext->DevPixelsToIntCSSPixels(*pos);
|
CSSIntPoint posCSSPixels =
|
||||||
|
presContext->DevPixelsToIntCSSPixels(*aOptions.mPoint);
|
||||||
if (anchorRect.Contains(posCSSPixels)) {
|
if (anchorRect.Contains(posCSSPixels)) {
|
||||||
if (consumeResult == ConsumeOutsideClicks_ParentOnly) {
|
if (consumeResult == ConsumeOutsideClicks_ParentOnly) {
|
||||||
consume = true;
|
consume = true;
|
||||||
@ -415,12 +413,13 @@ bool nsXULPopupManager::RollupInternal(RollupKind aKind, uint32_t aCount,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if a number of popups to close has been specified, determine the last
|
// If a number of popups to close has been specified, determine the last
|
||||||
// popup to close
|
// popup to close.
|
||||||
nsIContent* lastPopup = nullptr;
|
nsIContent* lastPopup = nullptr;
|
||||||
if (aCount != UINT32_MAX) {
|
uint32_t count = aOptions.mCount;
|
||||||
|
if (count && count != UINT32_MAX) {
|
||||||
nsMenuChainItem* last = item;
|
nsMenuChainItem* last = item;
|
||||||
while (--aCount && last->GetParent()) {
|
while (--count && last->GetParent()) {
|
||||||
last = last->GetParent();
|
last = last->GetParent();
|
||||||
}
|
}
|
||||||
if (last) {
|
if (last) {
|
||||||
@ -432,9 +431,12 @@ bool nsXULPopupManager::RollupInternal(RollupKind aKind, uint32_t aCount,
|
|||||||
RefPtr<nsViewManager> viewManager =
|
RefPtr<nsViewManager> viewManager =
|
||||||
presContext->PresShell()->GetViewManager();
|
presContext->PresShell()->GetViewManager();
|
||||||
|
|
||||||
HidePopup(item->Content(), true, true, false, true, lastPopup);
|
HidePopup(item->Content(),
|
||||||
|
{HidePopupOption::HideChain, HidePopupOption::DeselectMenu,
|
||||||
|
HidePopupOption::IsRollup},
|
||||||
|
lastPopup);
|
||||||
|
|
||||||
if (aFlush) {
|
if (aOptions.mFlush == FlushViews::Yes) {
|
||||||
// The popup's visibility doesn't update until the minimize animation
|
// The popup's visibility doesn't update until the minimize animation
|
||||||
// has finished, so call UpdateWidgetGeometry to update it right away.
|
// has finished, so call UpdateWidgetGeometry to update it right away.
|
||||||
viewManager->UpdateWidgetGeometry();
|
viewManager->UpdateWidgetGeometry();
|
||||||
@ -950,7 +952,7 @@ void nsXULPopupManager::OnNativeMenuClosed() {
|
|||||||
// menus.
|
// menus.
|
||||||
// Close the non-native menus now. This matches the HidePopup call in
|
// Close the non-native menus now. This matches the HidePopup call in
|
||||||
// nsXULMenuCommandEvent::Run.
|
// nsXULMenuCommandEvent::Run.
|
||||||
HidePopup(mPopups->Content(), true, false, false, false);
|
HidePopup(mPopups->Content(), {HidePopupOption::HideChain});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1136,9 +1138,8 @@ nsMenuChainItem* nsXULPopupManager::FindPopup(nsIContent* aPopup) const {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsXULPopupManager::HidePopup(nsIContent* aPopup, bool aHideChain,
|
void nsXULPopupManager::HidePopup(nsIContent* aPopup, HidePopupOptions aOptions,
|
||||||
bool aDeselectMenu, bool aAsynchronous,
|
nsIContent* aLastPopup) {
|
||||||
bool aIsCancel, nsIContent* aLastPopup) {
|
|
||||||
if (mNativeMenu && mNativeMenu->Element() == aPopup) {
|
if (mNativeMenu && mNativeMenu->Element() == aPopup) {
|
||||||
RefPtr<NativeMenu> menu = mNativeMenu;
|
RefPtr<NativeMenu> menu = mNativeMenu;
|
||||||
(void)menu->Close();
|
(void)menu->Close();
|
||||||
@ -1152,7 +1153,6 @@ void nsXULPopupManager::HidePopup(nsIContent* aPopup, bool aHideChain,
|
|||||||
|
|
||||||
nsMenuChainItem* foundPopup = FindPopup(aPopup);
|
nsMenuChainItem* foundPopup = FindPopup(aPopup);
|
||||||
|
|
||||||
bool deselectMenu = false;
|
|
||||||
nsCOMPtr<nsIContent> popupToHide, nextPopup, lastPopup;
|
nsCOMPtr<nsIContent> popupToHide, nextPopup, lastPopup;
|
||||||
|
|
||||||
if (foundPopup) {
|
if (foundPopup) {
|
||||||
@ -1160,6 +1160,8 @@ void nsXULPopupManager::HidePopup(nsIContent* aPopup, bool aHideChain,
|
|||||||
// If this is a noautohide panel, remove it but don't close any other
|
// If this is a noautohide panel, remove it but don't close any other
|
||||||
// panels.
|
// panels.
|
||||||
popupToHide = aPopup;
|
popupToHide = aPopup;
|
||||||
|
// XXX This preserves behavior but why is it the right thing to do?
|
||||||
|
aOptions -= HidePopupOption::DeselectMenu;
|
||||||
} else {
|
} else {
|
||||||
// At this point, foundPopup will be set to the found item in the list. If
|
// At this point, foundPopup will be set to the found item in the list. If
|
||||||
// foundPopup is the topmost menu, the one to remove, then there are no
|
// foundPopup is the topmost menu, the one to remove, then there are no
|
||||||
@ -1189,14 +1191,15 @@ void nsXULPopupManager::HidePopup(nsIContent* aPopup, bool aHideChain,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deselectMenu = aDeselectMenu;
|
|
||||||
popupToHide = topMenu->Content();
|
popupToHide = topMenu->Content();
|
||||||
popupFrame = topMenu->Frame();
|
popupFrame = topMenu->Frame();
|
||||||
|
|
||||||
|
const bool hideChain = aOptions.contains(HidePopupOption::HideChain);
|
||||||
|
|
||||||
// Close up another popup if there is one, and we are either hiding the
|
// Close up another popup if there is one, and we are either hiding the
|
||||||
// entire chain or the item to hide isn't the topmost popup.
|
// entire chain or the item to hide isn't the topmost popup.
|
||||||
nsMenuChainItem* parent = topMenu->GetParent();
|
nsMenuChainItem* parent = topMenu->GetParent();
|
||||||
if (parent && (aHideChain || topMenu != foundPopup)) {
|
if (parent && (hideChain || topMenu != foundPopup)) {
|
||||||
while (parent && parent->IsNoAutoHide()) {
|
while (parent && parent->IsNoAutoHide()) {
|
||||||
parent = parent->GetParent();
|
parent = parent->GetParent();
|
||||||
}
|
}
|
||||||
@ -1206,41 +1209,42 @@ void nsXULPopupManager::HidePopup(nsIContent* aPopup, bool aHideChain,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lastPopup = aLastPopup ? aLastPopup : (aHideChain ? nullptr : aPopup);
|
lastPopup = aLastPopup ? aLastPopup : (hideChain ? nullptr : aPopup);
|
||||||
}
|
}
|
||||||
} else if (popupFrame->PopupState() == ePopupPositioning) {
|
} else if (popupFrame->PopupState() == ePopupPositioning) {
|
||||||
// When the popup is in the popuppositioning state, it will not be in the
|
// When the popup is in the popuppositioning state, it will not be in the
|
||||||
// mPopups list. We need another way to find it and make sure it does not
|
// mPopups list. We need another way to find it and make sure it does not
|
||||||
// continue the popup showing process.
|
// continue the popup showing process.
|
||||||
deselectMenu = aDeselectMenu;
|
|
||||||
popupToHide = aPopup;
|
popupToHide = aPopup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popupToHide) {
|
if (!popupToHide) {
|
||||||
nsPopupState state = popupFrame->PopupState();
|
return;
|
||||||
// If the popup is already being hidden, don't attempt to hide it again
|
}
|
||||||
if (state == ePopupHiding) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change the popup state to hiding. Don't set the hiding state if the
|
nsPopupState state = popupFrame->PopupState();
|
||||||
// popup is invisible, otherwise nsMenuPopupFrame::HidePopup will
|
// If the popup is already being hidden, don't attempt to hide it again
|
||||||
// run again. In the invisible state, we just want the events to fire.
|
if (state == ePopupHiding) {
|
||||||
if (state != ePopupInvisible) {
|
return;
|
||||||
popupFrame->SetPopupState(ePopupHiding);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// For menus, popupToHide is always the frontmost item in the list to hide.
|
// Change the popup state to hiding. Don't set the hiding state if the
|
||||||
if (aAsynchronous) {
|
// popup is invisible, otherwise nsMenuPopupFrame::HidePopup will
|
||||||
nsCOMPtr<nsIRunnable> event = new nsXULPopupHidingEvent(
|
// run again. In the invisible state, we just want the events to fire.
|
||||||
popupToHide, nextPopup, lastPopup, popupFrame->GetPopupType(),
|
if (state != ePopupInvisible) {
|
||||||
deselectMenu, aIsCancel);
|
popupFrame->SetPopupState(ePopupHiding);
|
||||||
aPopup->OwnerDoc()->Dispatch(TaskCategory::Other, event.forget());
|
}
|
||||||
} else {
|
|
||||||
RefPtr<nsPresContext> presContext = popupFrame->PresContext();
|
// For menus, popupToHide is always the frontmost item in the list to hide.
|
||||||
FirePopupHidingEvent(popupToHide, nextPopup, lastPopup, presContext,
|
if (aOptions.contains(HidePopupOption::Async)) {
|
||||||
popupFrame->GetPopupType(), deselectMenu, aIsCancel);
|
nsCOMPtr<nsIRunnable> event =
|
||||||
}
|
new nsXULPopupHidingEvent(popupToHide, nextPopup, lastPopup,
|
||||||
|
popupFrame->GetPopupType(), aOptions);
|
||||||
|
aPopup->OwnerDoc()->Dispatch(TaskCategory::Other, event.forget());
|
||||||
|
} else {
|
||||||
|
RefPtr<nsPresContext> presContext = popupFrame->PresContext();
|
||||||
|
FirePopupHidingEvent(popupToHide, nextPopup, lastPopup, presContext,
|
||||||
|
popupFrame->GetPopupType(), aOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1259,7 +1263,7 @@ void nsXULPopupManager::HideMenu(nsIContent* aMenu) {
|
|||||||
if (!popup) {
|
if (!popup) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HidePopup(popup, false, true, false, false);
|
HidePopup(popup, {HidePopupOption::DeselectMenu});
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is used to hide the popup after a transition finishes.
|
// This is used to hide the popup after a transition finishes.
|
||||||
@ -1272,13 +1276,13 @@ class TransitionEnder final : public nsIDOMEventListener {
|
|||||||
virtual ~TransitionEnder() = default;
|
virtual ~TransitionEnder() = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool mDeselectMenu;
|
HidePopupOptions mOptions;
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS(TransitionEnder)
|
NS_DECL_CYCLE_COLLECTION_CLASS(TransitionEnder)
|
||||||
|
|
||||||
TransitionEnder(nsIContent* aContent, bool aDeselectMenu)
|
TransitionEnder(nsIContent* aContent, HidePopupOptions aOptions)
|
||||||
: mContent(aContent), mDeselectMenu(aDeselectMenu) {}
|
: mContent(aContent), mOptions(aOptions) {}
|
||||||
|
|
||||||
MOZ_CAN_RUN_SCRIPT NS_IMETHOD HandleEvent(Event* aEvent) override {
|
MOZ_CAN_RUN_SCRIPT NS_IMETHOD HandleEvent(Event* aEvent) override {
|
||||||
mContent->RemoveSystemEventListener(u"transitionend"_ns, this, false);
|
mContent->RemoveSystemEventListener(u"transitionend"_ns, this, false);
|
||||||
@ -1293,7 +1297,7 @@ class TransitionEnder final : public nsIDOMEventListener {
|
|||||||
// the first one ending.
|
// the first one ending.
|
||||||
if (RefPtr<nsXULPopupManager> pm = nsXULPopupManager::GetInstance()) {
|
if (RefPtr<nsXULPopupManager> pm = nsXULPopupManager::GetInstance()) {
|
||||||
pm->HidePopupCallback(mContent, popupFrame, nullptr, nullptr,
|
pm->HidePopupCallback(mContent, popupFrame, nullptr, nullptr,
|
||||||
popupFrame->GetPopupType(), mDeselectMenu);
|
popupFrame->GetPopupType(), mOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -1310,7 +1314,7 @@ NS_INTERFACE_MAP_END
|
|||||||
NS_IMPL_CYCLE_COLLECTION(TransitionEnder, mContent);
|
NS_IMPL_CYCLE_COLLECTION(TransitionEnder, mContent);
|
||||||
void nsXULPopupManager::HidePopupCallback(
|
void nsXULPopupManager::HidePopupCallback(
|
||||||
nsIContent* aPopup, nsMenuPopupFrame* aPopupFrame, nsIContent* aNextPopup,
|
nsIContent* aPopup, nsMenuPopupFrame* aPopupFrame, nsIContent* aNextPopup,
|
||||||
nsIContent* aLastPopup, PopupType aPopupType, bool aDeselectMenu) {
|
nsIContent* aLastPopup, PopupType aPopupType, HidePopupOptions aOptions) {
|
||||||
if (mCloseTimer && mTimerMenu == aPopupFrame) {
|
if (mCloseTimer && mTimerMenu == aPopupFrame) {
|
||||||
mCloseTimer->Cancel();
|
mCloseTimer->Cancel();
|
||||||
mCloseTimer = nullptr;
|
mCloseTimer = nullptr;
|
||||||
@ -1331,7 +1335,8 @@ void nsXULPopupManager::HidePopupCallback(
|
|||||||
}
|
}
|
||||||
|
|
||||||
AutoWeakFrame weakFrame(aPopupFrame);
|
AutoWeakFrame weakFrame(aPopupFrame);
|
||||||
aPopupFrame->HidePopup(aDeselectMenu, ePopupClosed);
|
aPopupFrame->HidePopup(aOptions.contains(HidePopupOption::DeselectMenu),
|
||||||
|
ePopupClosed);
|
||||||
NS_ENSURE_TRUE_VOID(weakFrame.IsAlive());
|
NS_ENSURE_TRUE_VOID(weakFrame.IsAlive());
|
||||||
|
|
||||||
// send the popuphidden event synchronously. This event has no default
|
// send the popuphidden event synchronously. This event has no default
|
||||||
@ -1369,7 +1374,7 @@ void nsXULPopupManager::HidePopupCallback(
|
|||||||
|
|
||||||
RefPtr<nsPresContext> presContext = popupFrame->PresContext();
|
RefPtr<nsPresContext> presContext = popupFrame->PresContext();
|
||||||
FirePopupHidingEvent(popupToHide, nextPopup, aLastPopup, presContext,
|
FirePopupHidingEvent(popupToHide, nextPopup, aLastPopup, presContext,
|
||||||
foundMenu->GetPopupType(), aDeselectMenu, false);
|
foundMenu->GetPopupType(), aOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1626,10 +1631,12 @@ void nsXULPopupManager::BeginShowingPopup(const PendingPopup& aPendingPopup,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsXULPopupManager::FirePopupHidingEvent(
|
void nsXULPopupManager::FirePopupHidingEvent(nsIContent* aPopup,
|
||||||
nsIContent* aPopup, nsIContent* aNextPopup, nsIContent* aLastPopup,
|
nsIContent* aNextPopup,
|
||||||
nsPresContext* aPresContext, PopupType aPopupType, bool aDeselectMenu,
|
nsIContent* aLastPopup,
|
||||||
bool aIsCancel) {
|
nsPresContext* aPresContext,
|
||||||
|
PopupType aPopupType,
|
||||||
|
HidePopupOptions aOptions) {
|
||||||
nsCOMPtr<nsIContent> popup = aPopup;
|
nsCOMPtr<nsIContent> popup = aPopup;
|
||||||
RefPtr<PresShell> presShell = aPresContext->PresShell();
|
RefPtr<PresShell> presShell = aPresContext->PresShell();
|
||||||
Unused << presShell; // This presShell may be keeping things alive
|
Unused << presShell; // This presShell may be keeping things alive
|
||||||
@ -1700,7 +1707,8 @@ void nsXULPopupManager::FirePopupHidingEvent(
|
|||||||
}
|
}
|
||||||
// If animate="cancel", only show the transition if cancelling the popup
|
// If animate="cancel", only show the transition if cancelling the popup
|
||||||
// or rolling up.
|
// or rolling up.
|
||||||
if (animate.EqualsLiteral("cancel") && !aIsCancel) {
|
if (animate.EqualsLiteral("cancel") &&
|
||||||
|
!aOptions.contains(HidePopupOption::IsRollup)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -1711,13 +1719,13 @@ void nsXULPopupManager::FirePopupHidingEvent(
|
|||||||
// view will be hidden and you won't be able to see it.
|
// view will be hidden and you won't be able to see it.
|
||||||
if (shouldAnimate && AnimationUtils::HasCurrentTransitions(
|
if (shouldAnimate && AnimationUtils::HasCurrentTransitions(
|
||||||
aPopup->AsElement(), PseudoStyleType::NotPseudo)) {
|
aPopup->AsElement(), PseudoStyleType::NotPseudo)) {
|
||||||
RefPtr<TransitionEnder> ender = new TransitionEnder(aPopup, aDeselectMenu);
|
RefPtr<TransitionEnder> ender = new TransitionEnder(aPopup, aOptions);
|
||||||
aPopup->AddSystemEventListener(u"transitionend"_ns, ender, false, false);
|
aPopup->AddSystemEventListener(u"transitionend"_ns, ender, false, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HidePopupCallback(aPopup, popupFrame, aNextPopup, aLastPopup, aPopupType,
|
HidePopupCallback(aPopup, popupFrame, aNextPopup, aLastPopup, aPopupType,
|
||||||
aDeselectMenu);
|
aOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsXULPopupManager::IsPopupOpen(nsIContent* aPopup) {
|
bool nsXULPopupManager::IsPopupOpen(nsIContent* aPopup) {
|
||||||
@ -1939,7 +1947,7 @@ void nsXULPopupManager::PopupDestroyed(nsMenuPopupFrame* aPopup) {
|
|||||||
} else {
|
} else {
|
||||||
// HidePopup will take care of hiding any of its children, so
|
// HidePopup will take care of hiding any of its children, so
|
||||||
// break out afterwards
|
// break out afterwards
|
||||||
HidePopup(child->Content(), false, false, true, false);
|
HidePopup(child->Content(), {HidePopupOption::Async});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2141,7 +2149,7 @@ void nsXULPopupManager::KillMenuTimer() {
|
|||||||
mCloseTimer = nullptr;
|
mCloseTimer = nullptr;
|
||||||
|
|
||||||
if (mTimerMenu->IsOpen()) {
|
if (mTimerMenu->IsOpen()) {
|
||||||
HidePopup(mTimerMenu->GetContent(), false, false, true, false);
|
HidePopup(mTimerMenu->GetContent(), {HidePopupOption::Async});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2378,9 +2386,7 @@ bool nsXULPopupManager::HandleKeyboardNavigationInPopup(
|
|||||||
// close a submenu when Left is pressed
|
// close a submenu when Left is pressed
|
||||||
if (nsMenuPopupFrame* popupFrame =
|
if (nsMenuPopupFrame* popupFrame =
|
||||||
currentItem->GetMenuPopup(FlushType::None)) {
|
currentItem->GetMenuPopup(FlushType::None)) {
|
||||||
HidePopup(popupFrame->GetContent(), /* aHideChain = */ false,
|
HidePopup(popupFrame->GetContent(), {});
|
||||||
/* aDeselectMenu = */ false, /* aAsynchronous = */ false,
|
|
||||||
/* aIsCancel = */ false);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2396,7 +2402,7 @@ bool nsXULPopupManager::HandleKeyboardEventWithKeyCode(
|
|||||||
if (aTopVisibleMenuItem &&
|
if (aTopVisibleMenuItem &&
|
||||||
aTopVisibleMenuItem->GetPopupType() != PopupType::Menu) {
|
aTopVisibleMenuItem->GetPopupType() != PopupType::Menu) {
|
||||||
if (keyCode == KeyboardEvent_Binding::DOM_VK_ESCAPE) {
|
if (keyCode == KeyboardEvent_Binding::DOM_VK_ESCAPE) {
|
||||||
HidePopup(aTopVisibleMenuItem->Content(), false, false, false, true);
|
HidePopup(aTopVisibleMenuItem->Content(), {HidePopupOption::IsRollup});
|
||||||
aKeyEvent->StopPropagation();
|
aKeyEvent->StopPropagation();
|
||||||
aKeyEvent->StopCrossProcessForwarding();
|
aKeyEvent->StopCrossProcessForwarding();
|
||||||
aKeyEvent->PreventDefault();
|
aKeyEvent->PreventDefault();
|
||||||
@ -2412,7 +2418,7 @@ bool nsXULPopupManager::HandleKeyboardEventWithKeyCode(
|
|||||||
// roll up the popup when alt+up/down are pressed within a menulist.
|
// roll up the popup when alt+up/down are pressed within a menulist.
|
||||||
if (aKeyEvent->AltKey() && aTopVisibleMenuItem &&
|
if (aKeyEvent->AltKey() && aTopVisibleMenuItem &&
|
||||||
aTopVisibleMenuItem->Frame()->IsMenuList()) {
|
aTopVisibleMenuItem->Frame()->IsMenuList()) {
|
||||||
Rollup(0, false, nullptr, nullptr);
|
Rollup({});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
@ -2439,7 +2445,7 @@ bool nsXULPopupManager::HandleKeyboardEventWithKeyCode(
|
|||||||
// though in this latter case, a menu didn't actually close, the effect
|
// though in this latter case, a menu didn't actually close, the effect
|
||||||
// ends up being the same. Similar for the tab key below.
|
// ends up being the same. Similar for the tab key below.
|
||||||
if (aTopVisibleMenuItem) {
|
if (aTopVisibleMenuItem) {
|
||||||
HidePopup(aTopVisibleMenuItem->Content(), false, false, false, true);
|
HidePopup(aTopVisibleMenuItem->Content(), {HidePopupOption::IsRollup});
|
||||||
} else if (mActiveMenuBar) {
|
} else if (mActiveMenuBar) {
|
||||||
mActiveMenuBar->MenuClosed();
|
mActiveMenuBar->MenuClosed();
|
||||||
}
|
}
|
||||||
@ -2454,7 +2460,7 @@ bool nsXULPopupManager::HandleKeyboardEventWithKeyCode(
|
|||||||
kNameSpaceID_None, nsGkAtoms::activateontab, nsGkAtoms::_true,
|
kNameSpaceID_None, nsGkAtoms::activateontab, nsGkAtoms::_true,
|
||||||
eCaseMatters)) {
|
eCaseMatters)) {
|
||||||
// Close popups or deactivate menubar when Tab or F10 are pressed
|
// Close popups or deactivate menubar when Tab or F10 are pressed
|
||||||
Rollup(0, false, nullptr, nullptr);
|
Rollup({});
|
||||||
break;
|
break;
|
||||||
} else if (mActiveMenuBar) {
|
} else if (mActiveMenuBar) {
|
||||||
mActiveMenuBar->MenuClosed();
|
mActiveMenuBar->MenuClosed();
|
||||||
@ -2600,7 +2606,7 @@ nsresult nsXULPopupManager::KeyDown(KeyboardEvent* aKeyEvent) {
|
|||||||
// modifiers are already down.
|
// modifiers are already down.
|
||||||
nsMenuChainItem* item = GetTopVisibleMenu();
|
nsMenuChainItem* item = GetTopVisibleMenu();
|
||||||
if (item && !item->Frame()->IsMenuList()) {
|
if (item && !item->Frame()->IsMenuList()) {
|
||||||
Rollup(0, false, nullptr, nullptr);
|
Rollup({});
|
||||||
} else if (mActiveMenuBar) {
|
} else if (mActiveMenuBar) {
|
||||||
mActiveMenuBar->MenuClosed();
|
mActiveMenuBar->MenuClosed();
|
||||||
}
|
}
|
||||||
@ -2663,7 +2669,7 @@ nsXULPopupHidingEvent::Run() {
|
|||||||
nsCOMPtr<nsIContent> nextPopup = mNextPopup;
|
nsCOMPtr<nsIContent> nextPopup = mNextPopup;
|
||||||
nsCOMPtr<nsIContent> lastPopup = mLastPopup;
|
nsCOMPtr<nsIContent> lastPopup = mLastPopup;
|
||||||
pm->FirePopupHidingEvent(popup, nextPopup, lastPopup, presContext,
|
pm->FirePopupHidingEvent(popup, nextPopup, lastPopup, presContext,
|
||||||
mPopupType, mDeselectMenu, mIsRollup);
|
mPopupType, mOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -2816,8 +2822,11 @@ nsXULMenuCommandEvent::Run() {
|
|||||||
|
|
||||||
if (mCloseMenuMode != CloseMenuMode_None) {
|
if (mCloseMenuMode != CloseMenuMode_None) {
|
||||||
if (RefPtr popup = menu->GetContainingPopupElement()) {
|
if (RefPtr popup = menu->GetContainingPopupElement()) {
|
||||||
pm->HidePopup(popup, mCloseMenuMode == CloseMenuMode_Auto, true, false,
|
HidePopupOptions options{HidePopupOption::DeselectMenu};
|
||||||
false);
|
if (mCloseMenuMode == CloseMenuMode_Auto) {
|
||||||
|
options += HidePopupOption::HideChain;
|
||||||
|
}
|
||||||
|
pm->HidePopup(popup, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +161,21 @@ enum nsIgnoreKeys {
|
|||||||
eIgnoreKeys_Shortcuts,
|
eIgnoreKeys_Shortcuts,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class HidePopupOption : uint8_t {
|
||||||
|
// If the entire chain of menus should be closed.
|
||||||
|
HideChain,
|
||||||
|
// If the parent <menu> of the popup should not be deselected. This will not
|
||||||
|
// be set when the menu is closed by pressing the Escape key.
|
||||||
|
DeselectMenu,
|
||||||
|
// If the first popuphiding event should be sent asynchrously. This should
|
||||||
|
// be set if HidePopup is called from a frame.
|
||||||
|
Async,
|
||||||
|
// If this popup is hiding due to being cancelled.
|
||||||
|
IsRollup,
|
||||||
|
};
|
||||||
|
|
||||||
|
using HidePopupOptions = mozilla::EnumSet<HidePopupOption>;
|
||||||
|
|
||||||
#define NS_DIRECTION_IS_INLINE(dir) \
|
#define NS_DIRECTION_IS_INLINE(dir) \
|
||||||
(dir == eNavigationDirection_Start || dir == eNavigationDirection_End)
|
(dir == eNavigationDirection_Start || dir == eNavigationDirection_End)
|
||||||
#define NS_DIRECTION_IS_BLOCK(dir) \
|
#define NS_DIRECTION_IS_BLOCK(dir) \
|
||||||
@ -280,14 +295,13 @@ class nsXULPopupHidingEvent : public mozilla::Runnable {
|
|||||||
public:
|
public:
|
||||||
nsXULPopupHidingEvent(nsIContent* aPopup, nsIContent* aNextPopup,
|
nsXULPopupHidingEvent(nsIContent* aPopup, nsIContent* aNextPopup,
|
||||||
nsIContent* aLastPopup, PopupType aPopupType,
|
nsIContent* aLastPopup, PopupType aPopupType,
|
||||||
bool aDeselectMenu, bool aIsCancel)
|
HidePopupOptions aOptions)
|
||||||
: mozilla::Runnable("nsXULPopupHidingEvent"),
|
: mozilla::Runnable("nsXULPopupHidingEvent"),
|
||||||
mPopup(aPopup),
|
mPopup(aPopup),
|
||||||
mNextPopup(aNextPopup),
|
mNextPopup(aNextPopup),
|
||||||
mLastPopup(aLastPopup),
|
mLastPopup(aLastPopup),
|
||||||
mPopupType(aPopupType),
|
mPopupType(aPopupType),
|
||||||
mDeselectMenu(aDeselectMenu),
|
mOptions(aOptions) {
|
||||||
mIsRollup(aIsCancel) {
|
|
||||||
NS_ASSERTION(aPopup,
|
NS_ASSERTION(aPopup,
|
||||||
"null popup supplied to nsXULPopupHidingEvent constructor");
|
"null popup supplied to nsXULPopupHidingEvent constructor");
|
||||||
// aNextPopup and aLastPopup may be null
|
// aNextPopup and aLastPopup may be null
|
||||||
@ -300,8 +314,7 @@ class nsXULPopupHidingEvent : public mozilla::Runnable {
|
|||||||
nsCOMPtr<nsIContent> mNextPopup;
|
nsCOMPtr<nsIContent> mNextPopup;
|
||||||
nsCOMPtr<nsIContent> mLastPopup;
|
nsCOMPtr<nsIContent> mLastPopup;
|
||||||
PopupType mPopupType;
|
PopupType mPopupType;
|
||||||
bool mDeselectMenu;
|
HidePopupOptions mOptions;
|
||||||
bool mIsRollup;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// this class is used for dispatching popuppositioned events asynchronously.
|
// this class is used for dispatching popuppositioned events asynchronously.
|
||||||
@ -375,9 +388,8 @@ class nsXULPopupManager final : public nsIDOMEventListener,
|
|||||||
|
|
||||||
// nsIRollupListener
|
// nsIRollupListener
|
||||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
bool Rollup(uint32_t aCount, bool aFlush,
|
bool Rollup(const RollupOptions&,
|
||||||
const mozilla::LayoutDeviceIntPoint* aPos,
|
nsIContent** aLastRolledUp = nullptr) override;
|
||||||
nsIContent** aLastRolledUp) override;
|
|
||||||
bool ShouldRollupOnMouseWheelEvent() override;
|
bool ShouldRollupOnMouseWheelEvent() override;
|
||||||
bool ShouldConsumeOnMouseWheelEvent() override;
|
bool ShouldConsumeOnMouseWheelEvent() override;
|
||||||
bool ShouldRollupOnMouseActivate() override;
|
bool ShouldRollupOnMouseActivate() override;
|
||||||
@ -389,8 +401,7 @@ class nsXULPopupManager final : public nsIDOMEventListener,
|
|||||||
|
|
||||||
enum class RollupKind { Tooltip, Menu };
|
enum class RollupKind { Tooltip, Menu };
|
||||||
MOZ_CAN_RUN_SCRIPT
|
MOZ_CAN_RUN_SCRIPT
|
||||||
bool RollupInternal(RollupKind, uint32_t aCount, bool aFlush,
|
bool RollupInternal(RollupKind, const RollupOptions&,
|
||||||
const mozilla::LayoutDeviceIntPoint* pos,
|
|
||||||
nsIContent** aLastRolledUp);
|
nsIContent** aLastRolledUp);
|
||||||
|
|
||||||
// NativeMenu::Observer
|
// NativeMenu::Observer
|
||||||
@ -507,21 +518,10 @@ class nsXULPopupManager final : public nsIDOMEventListener,
|
|||||||
/*
|
/*
|
||||||
* Hide a popup aPopup. If the popup is in a <menu>, then also inform the
|
* Hide a popup aPopup. If the popup is in a <menu>, then also inform the
|
||||||
* menu that the popup is being hidden.
|
* menu that the popup is being hidden.
|
||||||
*
|
|
||||||
* aHideChain - true if the entire chain of menus should be closed. If false,
|
|
||||||
* only this popup is closed.
|
|
||||||
* aDeselectMenu - true if the parent <menu> of the popup should be
|
|
||||||
* deselected. This will be false when the menu is closed by
|
|
||||||
* pressing the Escape key.
|
|
||||||
* aAsynchronous - true if the first popuphiding event should be sent
|
|
||||||
* asynchrously. This should be true if HidePopup is called
|
|
||||||
* from a frame.
|
|
||||||
* aIsCancel - true if this popup is hiding due to being cancelled.
|
|
||||||
* aLastPopup - optional popup to close last when hiding a chain of menus.
|
* aLastPopup - optional popup to close last when hiding a chain of menus.
|
||||||
* If null, then all popups will be closed.
|
* If null, then all popups will be closed.
|
||||||
*/
|
*/
|
||||||
void HidePopup(nsIContent* aPopup, bool aHideChain, bool aDeselectMenu,
|
void HidePopup(nsIContent* aPopup, HidePopupOptions,
|
||||||
bool aAsynchronous, bool aIsCancel,
|
|
||||||
nsIContent* aLastPopup = nullptr);
|
nsIContent* aLastPopup = nullptr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -754,7 +754,7 @@ class nsXULPopupManager final : public nsIDOMEventListener,
|
|||||||
bool aSelectFirstItem);
|
bool aSelectFirstItem);
|
||||||
MOZ_CAN_RUN_SCRIPT void HidePopupCallback(
|
MOZ_CAN_RUN_SCRIPT void HidePopupCallback(
|
||||||
nsIContent* aPopup, nsMenuPopupFrame* aPopupFrame, nsIContent* aNextPopup,
|
nsIContent* aPopup, nsMenuPopupFrame* aPopupFrame, nsIContent* aNextPopup,
|
||||||
nsIContent* aLastPopup, PopupType aPopupType, bool aDeselectMenu);
|
nsIContent* aLastPopup, PopupType aPopupType, HidePopupOptions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trigger frame construction and reflow in the popup, fire a popupshowing
|
* Trigger frame construction and reflow in the popup, fire a popupshowing
|
||||||
@ -786,14 +786,13 @@ class nsXULPopupManager final : public nsIDOMEventListener,
|
|||||||
* aLastPopup - the last popup in the chain to hide
|
* aLastPopup - the last popup in the chain to hide
|
||||||
* aPresContext - nsPresContext for the popup's frame
|
* aPresContext - nsPresContext for the popup's frame
|
||||||
* aPopupType - the PopupType of the frame.
|
* aPopupType - the PopupType of the frame.
|
||||||
* aDeselectMenu - true to unhighlight the menu when hiding it
|
* aOptions - the relevant options to hide the popup. Only a subset is looked
|
||||||
* aIsCancel - true if this popup is hiding due to being cancelled.
|
* at.
|
||||||
*/
|
*/
|
||||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
void FirePopupHidingEvent(nsIContent* aPopup, nsIContent* aNextPopup,
|
void FirePopupHidingEvent(nsIContent* aPopup, nsIContent* aNextPopup,
|
||||||
nsIContent* aLastPopup, nsPresContext* aPresContext,
|
nsIContent* aLastPopup, nsPresContext* aPresContext,
|
||||||
PopupType aPopupType, bool aDeselectMenu,
|
PopupType aPopupType, HidePopupOptions aOptions);
|
||||||
bool aIsCancel);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle keyboard navigation within a menu popup specified by aItem.
|
* Handle keyboard navigation within a menu popup specified by aItem.
|
||||||
|
@ -474,7 +474,7 @@ void nsXULTooltipListener::LaunchTooltip() {
|
|||||||
nsresult nsXULTooltipListener::HideTooltip() {
|
nsresult nsXULTooltipListener::HideTooltip() {
|
||||||
if (nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip)) {
|
if (nsCOMPtr<nsIContent> currentTooltip = do_QueryReferent(mCurrentTooltip)) {
|
||||||
if (nsXULPopupManager* pm = nsXULPopupManager::GetInstance()) {
|
if (nsXULPopupManager* pm = nsXULPopupManager::GetInstance()) {
|
||||||
pm->HidePopup(currentTooltip, false, false, false, false);
|
pm->HidePopup(currentTooltip, {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1058,9 +1058,8 @@ void nsView::DynamicToolbarOffsetChanged(ScreenIntCoord aOffset) {
|
|||||||
|
|
||||||
bool nsView::RequestWindowClose(nsIWidget* aWidget) {
|
bool nsView::RequestWindowClose(nsIWidget* aWidget) {
|
||||||
if (mFrame && IsPopupWidget(aWidget) && mFrame->IsMenuPopupFrame()) {
|
if (mFrame && IsPopupWidget(aWidget) && mFrame->IsMenuPopupFrame()) {
|
||||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
if (nsXULPopupManager* pm = nsXULPopupManager::GetInstance()) {
|
||||||
if (pm) {
|
pm->HidePopup(mFrame->GetContent(), {HidePopupOption::DeselectMenu});
|
||||||
pm->HidePopup(mFrame->GetContent(), false, true, false, false);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2397,56 +2397,57 @@ NSEvent* gLastDragMouseDownEvent = nil; // [strong]
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
|
nsCOMPtr<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
|
||||||
if (rollupWidget) {
|
if (!rollupWidget) {
|
||||||
NSWindow* currentPopup = static_cast<NSWindow*>(rollupWidget->GetNativeData(NS_NATIVE_WINDOW));
|
return consumeEvent;
|
||||||
if (!nsCocoaUtils::IsEventOverWindow(theEvent, currentPopup)) {
|
}
|
||||||
// event is not over the rollup window, default is to roll up
|
|
||||||
bool shouldRollup = true;
|
|
||||||
|
|
||||||
// check to see if scroll/zoom events should roll up the popup
|
NSWindow* currentPopup = static_cast<NSWindow*>(rollupWidget->GetNativeData(NS_NATIVE_WINDOW));
|
||||||
if (isWheelTypeEvent) {
|
if (nsCocoaUtils::IsEventOverWindow(theEvent, currentPopup)) {
|
||||||
shouldRollup = rollupListener->ShouldRollupOnMouseWheelEvent();
|
return consumeEvent;
|
||||||
// consume scroll events that aren't over the popup
|
}
|
||||||
// unless the popup is an arrow panel
|
|
||||||
consumeEvent = rollupListener->ShouldConsumeOnMouseWheelEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we're dealing with menus, we probably have submenus and
|
// Check to see if scroll/zoom events should roll up the popup
|
||||||
// we don't want to rollup if the click is in a parent menu of
|
if (isWheelTypeEvent) {
|
||||||
// the current submenu
|
// consume scroll events that aren't over the popup unless the popup is an
|
||||||
uint32_t popupsToRollup = UINT32_MAX;
|
// arrow panel.
|
||||||
AutoTArray<nsIWidget*, 5> widgetChain;
|
consumeEvent = rollupListener->ShouldConsumeOnMouseWheelEvent();
|
||||||
uint32_t sameTypeCount = rollupListener->GetSubmenuWidgetChain(&widgetChain);
|
if (!rollupListener->ShouldRollupOnMouseWheelEvent()) {
|
||||||
for (uint32_t i = 0; i < widgetChain.Length(); i++) {
|
return consumeEvent;
|
||||||
nsIWidget* widget = widgetChain[i];
|
|
||||||
NSWindow* currWindow = (NSWindow*)widget->GetNativeData(NS_NATIVE_WINDOW);
|
|
||||||
if (nsCocoaUtils::IsEventOverWindow(theEvent, currWindow)) {
|
|
||||||
// don't roll up if the mouse event occurred within a menu of the
|
|
||||||
// same type. If the mouse event occurred in a menu higher than
|
|
||||||
// that, roll up, but pass the number of popups to Rollup so
|
|
||||||
// that only those of the same type close up.
|
|
||||||
if (i < sameTypeCount) {
|
|
||||||
shouldRollup = false;
|
|
||||||
} else {
|
|
||||||
popupsToRollup = sameTypeCount;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldRollup) {
|
|
||||||
if ([theEvent type] == NSEventTypeLeftMouseDown) {
|
|
||||||
NSPoint point = [NSEvent mouseLocation];
|
|
||||||
FlipCocoaScreenCoordinate(point);
|
|
||||||
LayoutDeviceIntPoint devPoint = mGeckoChild->CocoaPointsToDevPixels(point);
|
|
||||||
consumeEvent = (BOOL)rollupListener->Rollup(popupsToRollup, true, &devPoint, nullptr);
|
|
||||||
} else {
|
|
||||||
consumeEvent = (BOOL)rollupListener->Rollup(popupsToRollup, true, nullptr, nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if we're dealing with menus, we probably have submenus and
|
||||||
|
// we don't want to rollup if the click is in a parent menu of
|
||||||
|
// the current submenu
|
||||||
|
uint32_t popupsToRollup = UINT32_MAX;
|
||||||
|
AutoTArray<nsIWidget*, 5> widgetChain;
|
||||||
|
uint32_t sameTypeCount = rollupListener->GetSubmenuWidgetChain(&widgetChain);
|
||||||
|
for (uint32_t i = 0; i < widgetChain.Length(); i++) {
|
||||||
|
nsIWidget* widget = widgetChain[i];
|
||||||
|
NSWindow* currWindow = (NSWindow*)widget->GetNativeData(NS_NATIVE_WINDOW);
|
||||||
|
if (nsCocoaUtils::IsEventOverWindow(theEvent, currWindow)) {
|
||||||
|
// don't roll up if the mouse event occurred within a menu of the
|
||||||
|
// same type. If the mouse event occurred in a menu higher than
|
||||||
|
// that, roll up, but pass the number of popups to Rollup so
|
||||||
|
// that only those of the same type close up.
|
||||||
|
if (i < sameTypeCount) {
|
||||||
|
return consumeEvent;
|
||||||
|
}
|
||||||
|
popupsToRollup = sameTypeCount;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LayoutDeviceIntPoint devPoint;
|
||||||
|
nsIRollupListener::RollupOptions rollupOptions{popupsToRollup,
|
||||||
|
nsIRollupListener::FlushViews::Yes};
|
||||||
|
if ([theEvent type] == NSEventTypeLeftMouseDown) {
|
||||||
|
NSPoint point = [NSEvent mouseLocation];
|
||||||
|
FlipCocoaScreenCoordinate(point);
|
||||||
|
devPoint = mGeckoChild->CocoaPointsToDevPixels(point);
|
||||||
|
rollupOptions.mPoint = &devPoint;
|
||||||
|
}
|
||||||
|
consumeEvent = (BOOL)rollupListener->Rollup(rollupOptions);
|
||||||
return consumeEvent;
|
return consumeEvent;
|
||||||
|
|
||||||
NS_OBJC_END_TRY_BLOCK_RETURN(NO);
|
NS_OBJC_END_TRY_BLOCK_RETURN(NO);
|
||||||
|
@ -120,7 +120,7 @@ static void RollUpPopups() {
|
|||||||
|
|
||||||
nsCOMPtr<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
|
nsCOMPtr<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
|
||||||
if (!rollupWidget) return;
|
if (!rollupWidget) return;
|
||||||
rollupListener->Rollup(0, true, nullptr, nullptr);
|
rollupListener->Rollup({0, nsIRollupListener::FlushViews::Yes});
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCocoaWindow::nsCocoaWindow()
|
nsCocoaWindow::nsCocoaWindow()
|
||||||
|
@ -1159,7 +1159,7 @@ void nsMenuX::Dump(uint32_t aIndent) const {
|
|||||||
if (rollupListener) {
|
if (rollupListener) {
|
||||||
nsCOMPtr<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
|
nsCOMPtr<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
|
||||||
if (rollupWidget) {
|
if (rollupWidget) {
|
||||||
rollupListener->Rollup(0, true, nullptr, nullptr);
|
rollupListener->Rollup({0, nsIRollupListener::FlushViews::Yes});
|
||||||
[menu cancelTracking];
|
[menu cancelTracking];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ void nsToolkit::MonitorAllProcessMouseEvents() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rollupListener->Rollup(0, false, nullptr, nullptr);
|
rollupListener->Rollup({});
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -625,7 +625,7 @@ void nsWindow::Destroy() {
|
|||||||
if (rollupListener) {
|
if (rollupListener) {
|
||||||
nsCOMPtr<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
|
nsCOMPtr<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
|
||||||
if (static_cast<nsIWidget*>(this) == rollupWidget) {
|
if (static_cast<nsIWidget*>(this) == rollupWidget) {
|
||||||
rollupListener->Rollup(0, false, nullptr, nullptr);
|
rollupListener->Rollup({});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4017,7 +4017,7 @@ gboolean nsWindow::OnConfigureEvent(GtkWidget* aWidget,
|
|||||||
// This check avoids unwanted rollup on spurious configure events from
|
// This check avoids unwanted rollup on spurious configure events from
|
||||||
// Cygwin/X (bug 672103).
|
// Cygwin/X (bug 672103).
|
||||||
if (mBounds.x != screenBounds.x || mBounds.y != screenBounds.y) {
|
if (mBounds.x != screenBounds.x || mBounds.y != screenBounds.y) {
|
||||||
CheckForRollup(0, 0, false, true);
|
RollupAllMenus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4782,7 +4782,7 @@ void nsWindow::OnContainerFocusOutEvent(GdkEventFocus* aEvent) {
|
|||||||
}();
|
}();
|
||||||
|
|
||||||
if (shouldRollupMenus) {
|
if (shouldRollupMenus) {
|
||||||
CheckForRollup(0, 0, false, true);
|
RollupAllMenus();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RefPtr pm = nsXULPopupManager::GetInstance()) {
|
if (RefPtr pm = nsXULPopupManager::GetInstance()) {
|
||||||
@ -7407,53 +7407,52 @@ bool nsWindow::CheckForRollup(gdouble aMouseX, gdouble aMouseY, bool aIsWheel,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool retVal = false;
|
|
||||||
auto* currentPopup =
|
auto* currentPopup =
|
||||||
(GdkWindow*)rollupWidget->GetNativeData(NS_NATIVE_WINDOW);
|
(GdkWindow*)rollupWidget->GetNativeData(NS_NATIVE_WINDOW);
|
||||||
if (aAlwaysRollup || !is_mouse_in_window(currentPopup, aMouseX, aMouseY)) {
|
if (!aAlwaysRollup && is_mouse_in_window(currentPopup, aMouseX, aMouseY)) {
|
||||||
bool rollup = true;
|
return false;
|
||||||
if (aIsWheel) {
|
}
|
||||||
rollup = rollupListener->ShouldRollupOnMouseWheelEvent();
|
bool retVal = false;
|
||||||
retVal = rollupListener->ShouldConsumeOnMouseWheelEvent();
|
if (aIsWheel) {
|
||||||
|
retVal = rollupListener->ShouldConsumeOnMouseWheelEvent();
|
||||||
|
if (!rollupListener->ShouldRollupOnMouseWheelEvent()) {
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
// if we're dealing with menus, we probably have submenus and
|
}
|
||||||
// we don't want to rollup if the click is in a parent menu of
|
LayoutDeviceIntPoint point;
|
||||||
// the current submenu
|
nsIRollupListener::RollupOptions options{0,
|
||||||
uint32_t popupsToRollup = UINT32_MAX;
|
nsIRollupListener::FlushViews::Yes};
|
||||||
if (!aAlwaysRollup) {
|
// if we're dealing with menus, we probably have submenus and
|
||||||
AutoTArray<nsIWidget*, 5> widgetChain;
|
// we don't want to rollup if the click is in a parent menu of
|
||||||
uint32_t sameTypeCount =
|
// the current submenu
|
||||||
rollupListener->GetSubmenuWidgetChain(&widgetChain);
|
if (!aAlwaysRollup) {
|
||||||
for (unsigned long i = 0; i < widgetChain.Length(); ++i) {
|
AutoTArray<nsIWidget*, 5> widgetChain;
|
||||||
nsIWidget* widget = widgetChain[i];
|
uint32_t sameTypeCount =
|
||||||
auto* currWindow = (GdkWindow*)widget->GetNativeData(NS_NATIVE_WINDOW);
|
rollupListener->GetSubmenuWidgetChain(&widgetChain);
|
||||||
if (is_mouse_in_window(currWindow, aMouseX, aMouseY)) {
|
for (unsigned long i = 0; i < widgetChain.Length(); ++i) {
|
||||||
// don't roll up if the mouse event occurred within a
|
nsIWidget* widget = widgetChain[i];
|
||||||
// menu of the same type. If the mouse event occurred
|
auto* currWindow = (GdkWindow*)widget->GetNativeData(NS_NATIVE_WINDOW);
|
||||||
// in a menu higher than that, roll up, but pass the
|
if (is_mouse_in_window(currWindow, aMouseX, aMouseY)) {
|
||||||
// number of popups to Rollup so that only those of the
|
// Don't roll up if the mouse event occurred within a menu of the same
|
||||||
// same type close up.
|
// type.
|
||||||
if (i < sameTypeCount) {
|
// If the mouse event occurred in a menu higher than that, roll up, but
|
||||||
rollup = false;
|
// pass the number of popups to Rollup so that only those of the same
|
||||||
} else {
|
// type close up.
|
||||||
popupsToRollup = sameTypeCount;
|
if (i < sameTypeCount) {
|
||||||
}
|
return retVal;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} // foreach parent menu widget
|
options.mCount = sameTypeCount;
|
||||||
} // if rollup listener knows about menus
|
break;
|
||||||
|
}
|
||||||
// if we've determined that we should still rollup, do it.
|
} // foreach parent menu widget
|
||||||
bool usePoint = !aIsWheel && !aAlwaysRollup;
|
if (!aIsWheel) {
|
||||||
LayoutDeviceIntPoint point;
|
|
||||||
if (usePoint) {
|
|
||||||
point = GdkEventCoordsToDevicePixels(aMouseX, aMouseY);
|
point = GdkEventCoordsToDevicePixels(aMouseX, aMouseY);
|
||||||
|
options.mPoint = &point;
|
||||||
}
|
}
|
||||||
if (rollup &&
|
}
|
||||||
rollupListener->Rollup(popupsToRollup, true,
|
|
||||||
usePoint ? &point : nullptr, nullptr)) {
|
if (rollupListener->Rollup(options)) {
|
||||||
retVal = true;
|
retVal = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
@ -504,7 +504,8 @@ class nsWindow final : public nsBaseWidget {
|
|||||||
const mozilla::LayoutDeviceIntPoint& aRefPoint);
|
const mozilla::LayoutDeviceIntPoint& aRefPoint);
|
||||||
bool CheckForRollup(gdouble aMouseX, gdouble aMouseY, bool aIsWheel,
|
bool CheckForRollup(gdouble aMouseX, gdouble aMouseY, bool aIsWheel,
|
||||||
bool aAlwaysRollup);
|
bool aAlwaysRollup);
|
||||||
void CheckForRollupDuringGrab() { CheckForRollup(0, 0, false, true); }
|
void RollupAllMenus() { CheckForRollup(0, 0, false, true); }
|
||||||
|
void CheckForRollupDuringGrab() { RollupAllMenus(); }
|
||||||
|
|
||||||
bool GetDragInfo(mozilla::WidgetMouseEvent* aMouseEvent, GdkWindow** aWindow,
|
bool GetDragInfo(mozilla::WidgetMouseEvent* aMouseEvent, GdkWindow** aWindow,
|
||||||
gint* aButton, gint* aRootX, gint* aRootY);
|
gint* aButton, gint* aRootX, gint* aRootY);
|
||||||
|
@ -567,7 +567,7 @@ nsBaseDragService::EndDragSession(bool aDoneDrag, uint32_t aKeyModifiers) {
|
|||||||
if (mDragPopup) {
|
if (mDragPopup) {
|
||||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||||
if (pm) {
|
if (pm) {
|
||||||
pm->HidePopup(mDragPopup, false, true, false, false);
|
pm->HidePopup(mDragPopup, {HidePopupOption::DeselectMenu});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,26 +16,29 @@ class nsIWidget;
|
|||||||
|
|
||||||
class nsIRollupListener {
|
class nsIRollupListener {
|
||||||
public:
|
public:
|
||||||
|
enum class FlushViews : bool { No, Yes };
|
||||||
|
struct RollupOptions {
|
||||||
|
// aCount is the number of popups in a chain to close. If this is
|
||||||
|
// zero, then all popups are closed.
|
||||||
|
uint32_t mCount = 0;
|
||||||
|
// If this is true, then views should be flushed after the rollup.
|
||||||
|
FlushViews mFlush = FlushViews::No;
|
||||||
|
// This is the mouse pointer position where the event that triggered the
|
||||||
|
// rollup occurred, which may be nullptr.
|
||||||
|
const mozilla::LayoutDeviceIntPoint* mPoint = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the object to rollup, optionally returning the node that
|
* Notifies the object to rollup, optionally returning the node that
|
||||||
* was just rolled up.
|
* was just rolled up in aLastRolledUp, if non-null.
|
||||||
*
|
*
|
||||||
* If aFlush is true, then views should be flushed after the rollup.
|
* aLastRolledUp is not addrefed.
|
||||||
*
|
|
||||||
* aPoint is the mouse pointer position where the event that triggered the
|
|
||||||
* rollup occurred, which may be nullptr.
|
|
||||||
*
|
|
||||||
* aCount is the number of popups in a chain to close. If this is
|
|
||||||
* UINT32_MAX, then all popups are closed.
|
|
||||||
* If aLastRolledUp is non-null, it will be set to the last rolled up popup,
|
|
||||||
* if this is supported. aLastRolledUp is not addrefed.
|
|
||||||
*
|
*
|
||||||
* Returns true if the event that the caller is processing should be consumed.
|
* Returns true if the event that the caller is processing should be consumed.
|
||||||
*/
|
*/
|
||||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
virtual bool Rollup(uint32_t aCount, bool aFlush,
|
virtual bool Rollup(const RollupOptions&,
|
||||||
const mozilla::LayoutDeviceIntPoint* aPoint,
|
nsIContent** aLastRolledUp = nullptr) = 0;
|
||||||
nsIContent** aLastRolledUp) = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asks the RollupListener if it should rollup on mouse wheel events
|
* Asks the RollupListener if it should rollup on mouse wheel events
|
||||||
|
@ -7415,7 +7415,7 @@ void nsWindow::OnDestroy() {
|
|||||||
rollupWidget = rollupListener->GetRollupWidget();
|
rollupWidget = rollupListener->GetRollupWidget();
|
||||||
}
|
}
|
||||||
if (this == rollupWidget) {
|
if (this == rollupWidget) {
|
||||||
if (rollupListener) rollupListener->Rollup(0, false, nullptr, nullptr);
|
rollupListener->Rollup({});
|
||||||
CaptureRollupEvents(false);
|
CaptureRollupEvents(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8410,6 +8410,11 @@ bool nsWindow::DealWithPopups(HWND aWnd, UINT aMessage, WPARAM aWParam,
|
|||||||
// Only need to deal with the last rollup for left mouse down events.
|
// Only need to deal with the last rollup for left mouse down events.
|
||||||
NS_ASSERTION(!nsAutoRollup::GetLastRollup(), "last rollup is null");
|
NS_ASSERTION(!nsAutoRollup::GetLastRollup(), "last rollup is null");
|
||||||
|
|
||||||
|
nsIRollupListener::RollupOptions rollupOptions{
|
||||||
|
popupsToRollup,
|
||||||
|
nsIRollupListener::FlushViews::Yes,
|
||||||
|
};
|
||||||
|
|
||||||
if (nativeMessage == WM_TOUCH || nativeMessage == WM_LBUTTONDOWN ||
|
if (nativeMessage == WM_TOUCH || nativeMessage == WM_LBUTTONDOWN ||
|
||||||
nativeMessage == WM_POINTERDOWN) {
|
nativeMessage == WM_POINTERDOWN) {
|
||||||
LayoutDeviceIntPoint pos;
|
LayoutDeviceIntPoint pos;
|
||||||
@ -8427,13 +8432,12 @@ bool nsWindow::DealWithPopups(HWND aWnd, UINT aMessage, WPARAM aWParam,
|
|||||||
pos = LayoutDeviceIntPoint(pt.x, pt.y);
|
pos = LayoutDeviceIntPoint(pt.x, pt.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIContent* lastRollup;
|
rollupOptions.mPoint = &pos;
|
||||||
consumeRollupEvent =
|
nsIContent* lastRollup = nullptr;
|
||||||
rollupListener->Rollup(popupsToRollup, true, &pos, &lastRollup);
|
consumeRollupEvent = rollupListener->Rollup(rollupOptions, &lastRollup);
|
||||||
nsAutoRollup::SetLastRollup(lastRollup);
|
nsAutoRollup::SetLastRollup(lastRollup);
|
||||||
} else {
|
} else {
|
||||||
consumeRollupEvent =
|
consumeRollupEvent = rollupListener->Rollup(rollupOptions);
|
||||||
rollupListener->Rollup(popupsToRollup, true, nullptr, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell hook to stop processing messages
|
// Tell hook to stop processing messages
|
||||||
|
Loading…
Reference in New Issue
Block a user