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->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.
// Clear any :active state, mouse capture state and drag tracking now.

View file

@ -9,6 +9,7 @@
#include "nsISupportsImpl.h"
#include "Units.h"
class nsIFrame;
class nsPresContext;
namespace mozilla {
@ -29,7 +30,7 @@ class NativeMenu {
// Show this menu as a context menu at the specified position.
// This call assumes that the popupshowing event for the root popup has
// 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;
// Close the menu and synchronously fire popuphiding / popuphidden events.

View file

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

View file

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

View file

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

View file

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