Bug 1763990: Don't order popups in front of native context menus on macOS. r=mstange

Differential Revision: https://phabricator.services.mozilla.com/D168625
This commit is contained in:
Stephen A Pohl 2023-02-02 22:13:54 +00:00
parent 7769d3635e
commit 1058fb4fa4
6 changed files with 18 additions and 27 deletions

View file

@ -894,7 +894,11 @@ bool nsXULPopupManager::ShowPopupAsNativeMenu(nsIContent* aPopup, int32_t aXPos,
mNativeMenu = menu; mNativeMenu = menu;
mNativeMenu->AddObserver(this); mNativeMenu->AddObserver(this);
mNativeMenu->ShowAsContextMenu(presContext, CSSIntPoint(aXPos, aYPos)); nsIFrame* frame = presContext->PresShell()->GetCurrentEventFrame();
if (!frame) {
frame = presContext->PresShell()->GetRootFrame();
}
mNativeMenu->ShowAsContextMenu(frame, CSSIntPoint(aXPos, aYPos));
// While the native menu is open, it consumes mouseup events. // While the native menu is open, it consumes mouseup events.
// Clear any :active state, mouse capture state and drag tracking now. // Clear any :active state, mouse capture state and drag tracking now.

View file

@ -9,6 +9,7 @@
#include "nsISupportsImpl.h" #include "nsISupportsImpl.h"
#include "Units.h" #include "Units.h"
class nsIFrame;
class nsPresContext; class nsPresContext;
namespace mozilla { namespace mozilla {
@ -29,7 +30,7 @@ class NativeMenu {
// Show this menu as a context menu at the specified position. // Show this menu as a context menu at the specified position.
// This call assumes that the popupshowing event for the root popup has // This call assumes that the popupshowing event for the root popup has
// already been sent and "approved", i.e. preventDefault() was not called. // already been sent and "approved", i.e. preventDefault() was not called.
virtual void ShowAsContextMenu(nsPresContext* aPc, virtual void ShowAsContextMenu(nsIFrame* aClickedFrame,
const CSSIntPoint& aPosition) = 0; const CSSIntPoint& aPosition) = 0;
// Close the menu and synchronously fire popuphiding / popuphidden events. // Close the menu and synchronously fire popuphiding / popuphidden events.

View file

@ -29,7 +29,7 @@ class NativeMenuMac : public NativeMenu,
explicit NativeMenuMac(dom::Element* aElement); explicit NativeMenuMac(dom::Element* aElement);
// NativeMenu // NativeMenu
void ShowAsContextMenu(nsPresContext*, const CSSIntPoint& aPosition) override; void ShowAsContextMenu(nsIFrame* aClickedFrame, const CSSIntPoint& aPosition) override;
bool Close() override; bool Close() override;
void ActivateItem(dom::Element* aItemElement, Modifiers aModifiers, int16_t aButton, void ActivateItem(dom::Element* aItemElement, Modifiers aModifiers, int16_t aButton,
ErrorResult& aRv) override; ErrorResult& aRv) override;

View file

@ -224,23 +224,8 @@ void NativeMenuMac::OnMenuClosed(dom::Element* aPopupElement) {
} }
} }
static NSView* NativeViewForContent(nsIContent* aContent) { static NSView* NativeViewForFrame(nsIFrame* aFrame) {
dom::Document* doc = aContent->GetUncomposedDoc(); nsIWidget* widget = aFrame->GetNearestWidget();
if (!doc) {
return nil;
}
PresShell* presShell = doc->GetPresShell();
if (!presShell) {
return nil;
}
nsIFrame* frame = presShell->GetRootFrame();
if (!frame) {
return nil;
}
nsIWidget* widget = frame->GetNearestWidget();
return (NSView*)widget->GetNativeData(NS_NATIVE_WIDGET); return (NSView*)widget->GetNativeData(NS_NATIVE_WIDGET);
} }
@ -252,15 +237,16 @@ static NSAppearance* NativeAppearanceForContent(nsIContent* aContent) {
return NSAppearanceForColorScheme(LookAndFeel::ColorSchemeForFrame(f)); return NSAppearanceForColorScheme(LookAndFeel::ColorSchemeForFrame(f));
} }
void NativeMenuMac::ShowAsContextMenu(nsPresContext* aPc, const CSSIntPoint& aPosition) { void NativeMenuMac::ShowAsContextMenu(nsIFrame* aClickedFrame, const CSSIntPoint& aPosition) {
nsPresContext* pc = aClickedFrame->PresContext();
auto cssToDesktopScale = auto cssToDesktopScale =
aPc->CSSToDevPixelScale() / aPc->DeviceContext()->GetDesktopToDeviceScale(); pc->CSSToDevPixelScale() / pc->DeviceContext()->GetDesktopToDeviceScale();
const DesktopPoint desktopPoint = aPosition * cssToDesktopScale; const DesktopPoint desktopPoint = aPosition * cssToDesktopScale;
mMenu->PopupShowingEventWasSentAndApprovedExternally(); mMenu->PopupShowingEventWasSentAndApprovedExternally();
NSMenu* menu = mMenu->NativeNSMenu(); NSMenu* menu = mMenu->NativeNSMenu();
NSView* view = NativeViewForContent(mMenu->Content()); NSView* view = NativeViewForFrame(aClickedFrame);
NSAppearance* appearance = NativeAppearanceForContent(mMenu->Content()); NSAppearance* appearance = NativeAppearanceForContent(mMenu->Content());
NSPoint locationOnScreen = nsCocoaUtils::GeckoPointToCocoaPoint(desktopPoint); NSPoint locationOnScreen = nsCocoaUtils::GeckoPointToCocoaPoint(desktopPoint);

View file

@ -355,12 +355,12 @@ NativeMenuGtk::~NativeMenuGtk() {
RefPtr<dom::Element> NativeMenuGtk::Element() { return mMenuModel->Element(); } RefPtr<dom::Element> NativeMenuGtk::Element() { return mMenuModel->Element(); }
void NativeMenuGtk::ShowAsContextMenu(nsPresContext* aPc, void NativeMenuGtk::ShowAsContextMenu(nsIFrame* aClickedFrame,
const CSSIntPoint& aPosition) { const CSSIntPoint& aPosition) {
if (mMenuModel->IsShowing()) { if (mMenuModel->IsShowing()) {
return; return;
} }
RefPtr<nsIWidget> widget = aPc->GetRootWidget(); RefPtr<nsIWidget> widget = aClickedFrame->PresContext()->GetRootWidget();
if (NS_WARN_IF(!widget)) { if (NS_WARN_IF(!widget)) {
// XXX Do we need to close menus here? // XXX Do we need to close menus here?
return; return;
@ -372,7 +372,7 @@ void NativeMenuGtk::ShowAsContextMenu(nsPresContext* aPc,
auto* geckoWin = static_cast<nsWindow*>(widget.get()); auto* geckoWin = static_cast<nsWindow*>(widget.get());
// The position needs to be relative to our window. // The position needs to be relative to our window.
auto pos = (aPosition * aPc->CSSToDevPixelScale()) - auto pos = (aPosition * aClickedFrame->PresContext()->CSSToDevPixelScale()) -
geckoWin->WidgetToScreenOffset(); geckoWin->WidgetToScreenOffset();
auto gdkPos = geckoWin->DevicePixelsToGdkPointRoundDown( auto gdkPos = geckoWin->DevicePixelsToGdkPointRoundDown(
LayoutDeviceIntPoint::Round(pos)); LayoutDeviceIntPoint::Round(pos));

View file

@ -30,7 +30,7 @@ class NativeMenuGtk : public NativeMenu {
// NativeMenu // NativeMenu
MOZ_CAN_RUN_SCRIPT_BOUNDARY void ShowAsContextMenu( MOZ_CAN_RUN_SCRIPT_BOUNDARY void ShowAsContextMenu(
nsPresContext*, const CSSIntPoint& aPosition) override; nsIFrame* aClickedFrame, const CSSIntPoint& aPosition) override;
bool Close() override; bool Close() override;
void ActivateItem(dom::Element* aItemElement, Modifiers aModifiers, void ActivateItem(dom::Element* aItemElement, Modifiers aModifiers,
int16_t aButton, ErrorResult& aRv) override; int16_t aButton, ErrorResult& aRv) override;