diff --git a/app/build.sh b/app/build.sh index eb9ecd43fe..3de6bbabcb 100755 --- a/app/build.sh +++ b/app/build.sh @@ -498,8 +498,8 @@ if [ $BUILD_MAC == 1 ]; then xz -d --stdout "$CALLDIR/mac/zotero.xz" > "$CONTENTSDIR/MacOS/zotero" chmod 755 "$CONTENTSDIR/MacOS/zotero" - # TEMP: Modified versions of some Firefox components for Big Sur, placed in xulrunner/MacOS - #cp "$MAC_RUNTIME_PATH/../MacOS/"{libc++.1.dylib,libnss3.dylib,XUL} "$CONTENTSDIR/MacOS/" + # TEMP: Custom version of XUL with some backported Mozilla bug fixes + cp "$MAC_RUNTIME_PATH/../MacOS/XUL" "$CONTENTSDIR/MacOS/" # Use our own updater, because Mozilla's requires updates signed by Mozilla cd "$CONTENTSDIR/MacOS" diff --git a/app/config.sh b/app/config.sh index c66701031f..e1c53dcf3d 100644 --- a/app/config.sh +++ b/app/config.sh @@ -7,7 +7,8 @@ GECKO_VERSION_WIN="115.9.1esr" RUST_VERSION=1.69.0 # URL prefix for custom builds of Firefox components -custom_components_url="https://download.zotero.org/dev/" +custom_components_url="https://download.zotero.org/dev/firefox-components/" +custom_components_hash_mac="bec8e3adebf8d5021f1f35fd2c65d752d4979839cbdd1ee1aa4b1d3d5ba0953b" APP_NAME="Zotero" APP_ID="zotero\@zotero.org" diff --git a/app/mac/build-and-unify b/app/mac/build-and-unify index 4f4bc9435a..6d8f4b4256 100755 --- a/app/mac/build-and-unify +++ b/app/mac/build-and-unify @@ -56,6 +56,9 @@ cp x64/$fx_app_name/Contents/MacOS/firefox zotero xz zotero mv zotero.xz "$APP_ROOT_DIR/mac/zotero.xz" +# TEMP: Copy a unified XUL for now +cp x64/$fx_app_name/Contents/MacOS/XUL "$APP_ROOT_DIR/mac/XUL" + # Uncomment to build updater #cd x64/$fx_app_name/Contents/MacOS/ #"$APP_ROOT_DIR/mac/updater_renamer" diff --git a/app/mac/mozilla-115.patch b/app/mac/mozilla-115.patch index 815d34220a..9caeccf0cc 100644 --- a/app/mac/mozilla-115.patch +++ b/app/mac/mozilla-115.patch @@ -34,6 +34,122 @@ diff --git a/browser/app/nsBrowserApp.cpp b/browser/app/nsBrowserApp.cpp appDataFile = argv[2]; char appEnv[MAXPATHLEN]; +diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp +--- a/layout/base/PresShell.cpp ++++ b/layout/base/PresShell.cpp +@@ -11529,18 +11529,17 @@ static nsIWidget* GetPresContextContaine + return mainWidget; + } + + static bool IsTopLevelWidget(nsIWidget* aWidget) { + using WindowType = mozilla::widget::WindowType; + + auto windowType = aWidget->GetWindowType(); + return windowType == WindowType::TopLevel || +- windowType == WindowType::Dialog || windowType == WindowType::Popup || +- windowType == WindowType::Sheet; ++ windowType == WindowType::Dialog || windowType == WindowType::Popup; + } + + PresShell::WindowSizeConstraints PresShell::GetWindowSizeConstraints() { + nsSize minSize(0, 0); + nsSize maxSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + nsIFrame* rootFrame = FrameConstructor()->GetRootElementStyleFrame(); + if (!rootFrame || !mPresContext) { + return {minSize, maxSize}; +diff --git a/layout/xul/nsXULTooltipListener.cpp b/layout/xul/nsXULTooltipListener.cpp +--- a/layout/xul/nsXULTooltipListener.cpp ++++ b/layout/xul/nsXULTooltipListener.cpp +@@ -365,53 +365,56 @@ nsresult nsXULTooltipListener::ShowToolt + + // get the tooltip content designated for the target node + nsCOMPtr tooltipNode; + GetTooltipFor(sourceNode, getter_AddRefs(tooltipNode)); + if (!tooltipNode || sourceNode == tooltipNode) + return NS_ERROR_FAILURE; // the target node doesn't need a tooltip + + // set the node in the document that triggered the tooltip and show it +- if (tooltipNode->GetComposedDoc() && +- nsContentUtils::IsChromeDoc(tooltipNode->GetComposedDoc())) { +- // Make sure the target node is still attached to some document. +- // It might have been deleted. +- if (sourceNode->IsInComposedDoc()) { +- if (!mIsSourceTree) { +- mLastTreeRow = -1; +- mLastTreeCol = nullptr; +- } ++ // Make sure the document still has focus. ++ auto* doc = tooltipNode->GetComposedDoc(); ++ if (!doc || !nsContentUtils::IsChromeDoc(doc) || ++ !doc->HasFocus(IgnoreErrors())) { ++ return NS_OK; ++ } ++ // Make sure the target node is still attached to some document. ++ // It might have been deleted. ++ if (sourceNode->IsInComposedDoc()) { ++ if (!mIsSourceTree) { ++ mLastTreeRow = -1; ++ mLastTreeCol = nullptr; ++ } + +- mCurrentTooltip = do_GetWeakReference(tooltipNode); +- LaunchTooltip(); +- mTargetNode = nullptr; +- +- nsCOMPtr currentTooltip = do_QueryReferent(mCurrentTooltip); +- if (!currentTooltip) return NS_OK; ++ mCurrentTooltip = do_GetWeakReference(tooltipNode); ++ LaunchTooltip(); ++ mTargetNode = nullptr; + +- // listen for popuphidden on the tooltip node, so that we can +- // be sure DestroyPopup is called even if someone else closes the tooltip +- currentTooltip->AddSystemEventListener(u"popuphiding"_ns, this, false, +- false); ++ nsCOMPtr currentTooltip = do_QueryReferent(mCurrentTooltip); ++ if (!currentTooltip) return NS_OK; ++ ++ // listen for popuphidden on the tooltip node, so that we can ++ // be sure DestroyPopup is called even if someone else closes the tooltip ++ currentTooltip->AddSystemEventListener(u"popuphiding"_ns, this, false, ++ false); + +- // listen for mousedown, mouseup, keydown, and mouse events at +- // document level +- if (Document* doc = sourceNode->GetComposedDoc()) { +- // Probably, we should listen to untrusted events for hiding tooltips +- // on content since tooltips might disturb something of web +- // applications. If we don't specify the aWantsUntrusted of +- // AddSystemEventListener(), the event target sets it to TRUE if the +- // target is in content. +- doc->AddSystemEventListener(u"wheel"_ns, this, true); +- doc->AddSystemEventListener(u"mousedown"_ns, this, true); +- doc->AddSystemEventListener(u"mouseup"_ns, this, true); +- doc->AddSystemEventListener(u"keydown"_ns, this, true); +- } +- mSourceNode = nullptr; ++ // listen for mousedown, mouseup, keydown, and mouse events at ++ // document level ++ if (Document* doc = sourceNode->GetComposedDoc()) { ++ // Probably, we should listen to untrusted events for hiding tooltips ++ // on content since tooltips might disturb something of web ++ // applications. If we don't specify the aWantsUntrusted of ++ // AddSystemEventListener(), the event target sets it to TRUE if the ++ // target is in content. ++ doc->AddSystemEventListener(u"wheel"_ns, this, true); ++ doc->AddSystemEventListener(u"mousedown"_ns, this, true); ++ doc->AddSystemEventListener(u"mouseup"_ns, this, true); ++ doc->AddSystemEventListener(u"keydown"_ns, this, true); + } ++ mSourceNode = nullptr; + } + + return NS_OK; + } + + static void SetTitletipLabel(XULTreeElement* aTree, Element* aTooltip, + int32_t aRow, nsTreeColumn* aCol) { + nsCOMPtr view = aTree->GetView(); diff --git a/python/mozbuild/mozbuild/action/unpack_dmg.py b/python/mozbuild/mozbuild/action/unpack_dmg.py --- a/python/mozbuild/mozbuild/action/unpack_dmg.py +++ b/python/mozbuild/mozbuild/action/unpack_dmg.py @@ -58,6 +174,1191 @@ diff --git a/python/mozbuild/mozbuild/action/unpack_dmg.py b/python/mozbuild/moz if __name__ == "__main__": +diff --git a/widget/InitData.h b/widget/InitData.h +--- a/widget/InitData.h ++++ b/widget/InitData.h +@@ -12,17 +12,16 @@ + + namespace mozilla::widget { + + // Window types + enum class WindowType : uint8_t { + TopLevel, // default top level window + Dialog, // top level window but usually handled differently + // by the OS +- Sheet, // MacOSX sheet (special dialog class) + Popup, // used for combo boxes, etc + Child, // child windows (contained inside a window on the + // desktop (has no border)) + Invisible, // windows that are invisible or offscreen + }; + + // Popup types for WindowType::Popup + enum class PopupType : uint8_t { +diff --git a/widget/cocoa/moz.build b/widget/cocoa/moz.build +--- a/widget/cocoa/moz.build ++++ b/widget/cocoa/moz.build +@@ -6,22 +6,16 @@ + + with Files("**"): + BUG_COMPONENT = ("Core", "Widget: Cocoa") + SCHEDULES.exclusive = ["macosx"] + + with Files("*TextInput*"): + BUG_COMPONENT = ("Core", "DOM: UI Events & Focus Handling") + +-XPIDL_SOURCES += [ +- "nsPIWidgetCocoa.idl", +-] +- +-XPIDL_MODULE = "widget_cocoa" +- + EXPORTS += [ + "CFTypeRefPtr.h", + "DesktopBackgroundImage.h", + "MediaHardwareKeysEventSourceMac.h", + "MediaHardwareKeysEventSourceMacMediaCenter.h", + "mozView.h", + "nsBidiKeyboard.h", + "nsChangeObserver.h", +diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm +--- a/widget/cocoa/nsChildView.mm ++++ b/widget/cocoa/nsChildView.mm +@@ -1678,29 +1678,23 @@ void nsChildView::UpdateThemeGeometries( + + if (![[mView window] isKindOfClass:[ToolbarWindow class]]) return; + + // Update unified toolbar height and sheet attachment position. + int32_t windowWidth = mBounds.width; + int32_t titlebarBottom = FindTitlebarBottom(aThemeGeometries, windowWidth); + int32_t unifiedToolbarBottom = + FindUnifiedToolbarBottom(aThemeGeometries, windowWidth, titlebarBottom); +- int32_t toolboxBottom = FindFirstRectOfType(aThemeGeometries, eThemeGeometryTypeToolbox).YMost(); + + ToolbarWindow* win = (ToolbarWindow*)[mView window]; + int32_t titlebarHeight = + [win drawsContentsIntoWindowFrame] ? 0 : CocoaPointsToDevPixels([win titlebarHeight]); + int32_t devUnifiedHeight = titlebarHeight + unifiedToolbarBottom; + [win setUnifiedToolbarHeight:DevPixelsToCocoaPoints(devUnifiedHeight)]; + +- int32_t sheetPositionDevPx = std::max(toolboxBottom, unifiedToolbarBottom); +- NSPoint sheetPositionView = {0, DevPixelsToCocoaPoints(sheetPositionDevPx)}; +- NSPoint sheetPositionWindow = [mView convertPoint:sheetPositionView toView:nil]; +- [win setSheetAttachmentPosition:sheetPositionWindow.y]; +- + // Update titlebar control offsets. + LayoutDeviceIntRect windowButtonRect = + FindFirstRectOfType(aThemeGeometries, eThemeGeometryTypeWindowButtons); + [win placeWindowButtons:[mView convertRect:DevPixelsToCocoaPoints(windowButtonRect) toView:nil]]; + } + + static Maybe ThemeGeometryTypeToVibrancyType( + nsITheme::ThemeGeometryType aThemeGeometryType) { +@@ -4899,24 +4893,16 @@ BOOL ChildViewMouseTracker::WindowAccept + return WindowAcceptsEvent([aWindow parentWindow], aEvent, aView, aIsClickThrough); + + case WindowType::TopLevel: + case WindowType::Dialog: + if ([aWindow attachedSheet]) return NO; + + topLevelWindow = aWindow; + break; +- case WindowType::Sheet: { +- nsIWidget* parentWidget = windowWidget->GetSheetWindowParent(); +- if (!parentWidget) return YES; +- +- topLevelWindow = (NSWindow*)parentWidget->GetNativeData(NS_NATIVE_WINDOW); +- break; +- } +- + default: + return YES; + } + + if (!topLevelWindow || ([topLevelWindow isMainWindow] && !aIsClickThrough) || + [aEvent type] == NSEventTypeOtherMouseDown || + (([aEvent modifierFlags] & NSEventModifierFlagCommand) != 0 && + [aEvent type] != NSEventTypeMouseMoved)) +diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h +--- a/widget/cocoa/nsCocoaWindow.h ++++ b/widget/cocoa/nsCocoaWindow.h +@@ -7,17 +7,16 @@ + #define nsCocoaWindow_h_ + + #undef DARWIN + + #import + + #include "mozilla/RefPtr.h" + #include "nsBaseWidget.h" +-#include "nsPIWidgetCocoa.h" + #include "nsCocoaUtils.h" + #include "nsTouchBar.h" + #include + #include + + class nsCocoaWindow; + class nsChildView; + class nsMenuBarX; +@@ -191,60 +190,53 @@ typedef struct _nsCocoaWindowList { + // destroyed by updateTitlebarView. + MOZTitlebarView* mTitlebarView; // [STRONG] + // mFullscreenTitlebarTracker attaches an invisible rectangle to the system + // title bar. This allows us to detect when the title bar is showing in + // fullscreen. + FullscreenTitlebarTracker* mFullscreenTitlebarTracker; + + CGFloat mUnifiedToolbarHeight; +- CGFloat mSheetAttachmentPosition; + CGFloat mMenuBarHeight; + /* Store the height of the titlebar when this window is initialized. The + titlebarHeight getter returns 0 when in fullscreen, which is not useful in + some cases. */ + CGFloat mInitialTitlebarHeight; + NSRect mWindowButtonsRect; + } + - (void)setUnifiedToolbarHeight:(CGFloat)aHeight; + - (CGFloat)unifiedToolbarHeight; + - (CGFloat)titlebarHeight; + - (NSRect)titlebarRect; + - (void)setTitlebarNeedsDisplay; + - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState; +-- (void)setSheetAttachmentPosition:(CGFloat)aY; +-- (CGFloat)sheetAttachmentPosition; + - (void)placeWindowButtons:(NSRect)aRect; + - (NSRect)windowButtonsRect; + - (void)windowMainStateChanged; + @end + +-class nsCocoaWindow final : public nsBaseWidget, public nsPIWidgetCocoa { ++class nsCocoaWindow final : public nsBaseWidget { + private: + typedef nsBaseWidget Inherited; + + public: + nsCocoaWindow(); + +- NS_DECL_ISUPPORTS_INHERITED +- NS_DECL_NSPIWIDGETCOCOA; // semicolon for clang-format bug 1629756 +- + [[nodiscard]] virtual nsresult Create(nsIWidget* aParent, nsNativeWidget aNativeParent, + const DesktopIntRect& aRect, InitData* = nullptr) override; + + [[nodiscard]] virtual nsresult Create(nsIWidget* aParent, nsNativeWidget aNativeParent, + const LayoutDeviceIntRect& aRect, + InitData* = nullptr) override; + + virtual void Destroy() override; + + virtual void Show(bool aState) override; + virtual bool NeedsRecreateToReshow() override; + +- virtual nsIWidget* GetSheetWindowParent(void) override; + virtual void Enable(bool aState) override; + virtual bool IsEnabled() const override; + virtual void SetModal(bool aState) override; + virtual void SetFakeModal(bool aState) override; + virtual bool IsRunningAppModal() override; + virtual bool IsVisible() const override; + virtual void SetFocus(Raise, mozilla::dom::CallerType aCallerType) override; + virtual LayoutDeviceIntPoint WidgetToScreenOffset() override; +@@ -393,47 +385,45 @@ class nsCocoaWindow final : public nsBas + virtual ~nsCocoaWindow(); + + nsresult CreateNativeWindow(const NSRect& aRect, BorderStyle aBorderStyle, bool aRectIsFrameRect, + bool aIsPrivateBrowsing); + nsresult CreatePopupContentView(const LayoutDeviceIntRect& aRect, InitData*); + void DestroyNativeWindow(); + void UpdateBounds(); + int32_t GetWorkspaceID(); ++ void SendSetZLevelEvent(); + + void DoResize(double aX, double aY, double aWidth, double aHeight, bool aRepaint, + bool aConstrainToCurrentScreen); + + void UpdateFullscreenState(bool aFullScreen, bool aNativeMode); + nsresult DoMakeFullScreen(bool aFullScreen, bool aUseSystemTransition); + + virtual already_AddRefed AllocateChildPopupWidget() override { + return nsIWidget::CreateTopLevelWindow(); + } + + nsIWidget* mParent; // if we're a popup, this is our parent [WEAK] + nsIWidget* mAncestorLink; // link to traverse ancestors [WEAK] + BaseWindow* mWindow; // our cocoa window [STRONG] + WindowDelegate* mDelegate; // our delegate for processing window msgs [STRONG] + RefPtr mMenuBar; +- NSWindow* mSheetWindowParent; // if this is a sheet, this is the NSWindow it's attached to + nsChildView* mPopupContentView; // if this is a popup, this is its content widget + // if this is a toplevel window, and there is any ongoing fullscreen + // transition, it is the animation object. + NSAnimation* mFullscreenTransitionAnimation; + mozilla::StyleWindowShadow mShadowStyle; + + CGFloat mBackingScaleFactor; + CGFloat mAspectRatio; + + WindowAnimationType mAnimationType; + + bool mWindowMadeHere; // true if we created the window, false for embedding +- bool mSheetNeedsShow; // if this is a sheet, are we waiting to be shown? +- // this is used for sibling sheet contention only + nsSizeMode mSizeMode; + bool mInFullScreenMode; + // Whether we are currently using native fullscreen. It could be false because + // we are in the emulated fullscreen where we do not use the native fullscreen. + bool mInNativeFullScreenMode; + + mozilla::Maybe mTransitionCurrent; + std::queue mTransitionsPending; +diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm +--- a/widget/cocoa/nsCocoaWindow.mm ++++ b/widget/cocoa/nsCocoaWindow.mm +@@ -30,16 +30,17 @@ + #include "nsMenuUtilsX.h" + #include "nsStyleConsts.h" + #include "nsNativeThemeColors.h" + #include "nsNativeThemeCocoa.h" + #include "nsChildView.h" + #include "nsCocoaFeatures.h" + #include "nsIScreenManager.h" + #include "nsIWidgetListener.h" ++#include "nsXULPopupManager.h" + #include "SDKDeclarations.h" + #include "VibrancyManager.h" + #include "nsPresContext.h" + #include "nsDocShell.h" + + #include "gfxPlatform.h" + #include "qcms.h" + +@@ -99,28 +100,27 @@ typedef enum { + static NSString* const CGSSpaceIDKey = @"ManagedSpaceID"; + static NSString* const CGSSpacesKey = @"Spaces"; + extern CGSConnection _CGSDefaultConnection(void); + extern CGError CGSSetWindowTransform(CGSConnection cid, CGSWindow wid, CGAffineTransform transform); + } + + #define NS_APPSHELLSERVICE_CONTRACTID "@mozilla.org/appshell/appShellService;1" + +-NS_IMPL_ISUPPORTS_INHERITED(nsCocoaWindow, Inherited, nsPIWidgetCocoa) +- +-// A note on testing to see if your object is a sheet... +-// |mWindowType == WindowType::Sheet| is true if your gecko nsIWidget is a sheet +-// widget - whether or not the sheet is showing. |[mWindow isSheet]| will return +-// true *only when the sheet is actually showing*. Choose your test wisely. +- + static void RollUpPopups( + nsIRollupListener::AllowAnimations aAllowAnimations = nsIRollupListener::AllowAnimations::Yes) { ++ if (RefPtr pm = nsXULPopupManager::GetInstance()) { ++ pm->RollupTooltips(); ++ } ++ + nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener(); +- NS_ENSURE_TRUE_VOID(rollupListener); +- ++ ++ if (!rollupListener) { ++ return; ++ } + if (rollupListener->RollupNativeMenu()) { + return; + } + + nsCOMPtr rollupWidget = rollupListener->GetRollupWidget(); + if (!rollupWidget) { + return; + } +@@ -129,24 +129,22 @@ static void RollUpPopups( + rollupListener->Rollup(options); + } + + nsCocoaWindow::nsCocoaWindow() + : mParent(nullptr), + mAncestorLink(nullptr), + mWindow(nil), + mDelegate(nil), +- mSheetWindowParent(nil), + mPopupContentView(nil), + mFullscreenTransitionAnimation(nil), + mShadowStyle(StyleWindowShadow::Default), + mBackingScaleFactor(0.0), + mAnimationType(nsIWidget::eGenericWindowAnimation), + mWindowMadeHere(false), +- mSheetNeedsShow(false), + mSizeMode(nsSizeMode_Normal), + mInFullScreenMode(false), + mInNativeFullScreenMode(false), + mIgnoreOcclusionCount(0), + mHasStartedNativeFullscreen(false), + mModal(false), + mFakeModal(false), + mIsAnimationSuppressed(false), +@@ -431,25 +429,16 @@ nsresult nsCocoaWindow::CreateNativeWind + features |= NSWindowStyleMaskClosable; + } + } + break; + case WindowType::TopLevel: + case WindowType::Dialog: + features = WindowMaskForBorderStyle(aBorderStyle); + break; +- case WindowType::Sheet: +- if (mParent->GetWindowType() != WindowType::Invisible && +- aBorderStyle & BorderStyle::ResizeH) { +- features = NSWindowStyleMaskResizable; +- } else { +- features = NSWindowStyleMaskMiniaturizable; +- } +- features |= NSWindowStyleMaskTitled; +- break; + default: + NS_ERROR("Unhandled window type!"); + return NS_ERROR_FAILURE; + } + + NSRect contentRect; + + if (aRectIsFrameRect) { +@@ -650,24 +639,16 @@ void nsCocoaWindow::Destroy() { + if (mInNativeFullScreenMode) { + DestroyNativeWindow(); + } else if (mWindow) { + nsCocoaUtils::HideOSChromeOnScreen(false); + } + } + } + +-nsIWidget* nsCocoaWindow::GetSheetWindowParent(void) { +- if (mWindowType != WindowType::Sheet) return nullptr; +- nsCocoaWindow* parent = static_cast(mParent); +- while (parent && (parent->mWindowType == WindowType::Sheet)) +- parent = static_cast(parent->mParent); +- return parent; +-} +- + void* nsCocoaWindow::GetNativeData(uint32_t aDataType) { + NS_OBJC_BEGIN_TRY_BLOCK_RETURN; + + void* retVal = nullptr; + + switch (aDataType) { + // to emulate how windows works, we always have to return a NSView + // for NS_NATIVE_WIDGET +@@ -707,17 +688,17 @@ void* nsCocoaWindow::GetNativeData(uint3 + return retVal; + + NS_OBJC_END_TRY_BLOCK_RETURN(nullptr); + } + + bool nsCocoaWindow::IsVisible() const { + NS_OBJC_BEGIN_TRY_BLOCK_RETURN; + +- return (mWindow && ([mWindow isVisibleOrBeingShown] || mSheetNeedsShow)); ++ return mWindow && mWindow.isVisibleOrBeingShown; + + NS_OBJC_END_TRY_BLOCK_RETURN(false); + } + + void nsCocoaWindow::SetModal(bool aState) { + NS_OBJC_BEGIN_TRY_IGNORE_BLOCK; + + if (!mWindow) return; +@@ -734,64 +715,60 @@ void nsCocoaWindow::SetModal(bool aState + ++gXULModalLevel; + // When a non-sheet window gets "set modal", make the window(s) that it + // appears over behave as they should. We can't rely on native methods to + // do this, for the following reason: The OS runs modal non-sheet windows + // in an event loop (using [NSApplication runModalForWindow:] or similar + // methods) that's incompatible with the modal event loop in AppWindow:: + // ShowModal() (each of these event loops is "exclusive", and can't run at + // the same time as other (similar) event loops). +- if (mWindowType != WindowType::Sheet) { +- while (ancestor) { +- if (ancestor->mNumModalDescendents++ == 0) { +- NSWindow* aWindow = ancestor->GetCocoaWindow(); +- if (ancestor->mWindowType != WindowType::Invisible) { +- [[aWindow standardWindowButton:NSWindowCloseButton] setEnabled:NO]; +- [[aWindow standardWindowButton:NSWindowMiniaturizeButton] setEnabled:NO]; +- [[aWindow standardWindowButton:NSWindowZoomButton] setEnabled:NO]; +- } ++ while (ancestor) { ++ if (ancestor->mNumModalDescendents++ == 0) { ++ NSWindow* aWindow = ancestor->GetCocoaWindow(); ++ if (ancestor->mWindowType != WindowType::Invisible) { ++ [[aWindow standardWindowButton:NSWindowCloseButton] setEnabled:NO]; ++ [[aWindow standardWindowButton:NSWindowMiniaturizeButton] setEnabled:NO]; ++ [[aWindow standardWindowButton:NSWindowZoomButton] setEnabled:NO]; + } +- ancestor = static_cast(ancestor->mParent); + } +- [mWindow setLevel:NSModalPanelWindowLevel]; +- nsCocoaWindowList* windowList = new nsCocoaWindowList; +- if (windowList) { +- windowList->window = this; // Don't ADDREF +- windowList->prev = gGeckoAppModalWindowList; +- gGeckoAppModalWindowList = windowList; +- } ++ ancestor = static_cast(ancestor->mParent); ++ } ++ [mWindow setLevel:NSModalPanelWindowLevel]; ++ nsCocoaWindowList* windowList = new nsCocoaWindowList; ++ if (windowList) { ++ windowList->window = this; // Don't ADDREF ++ windowList->prev = gGeckoAppModalWindowList; ++ gGeckoAppModalWindowList = windowList; + } + } else { + --gXULModalLevel; + NS_ASSERTION(gXULModalLevel >= 0, "Mismatched call to nsCocoaWindow::SetModal(false)!"); +- if (mWindowType != WindowType::Sheet) { +- while (ancestor) { +- if (--ancestor->mNumModalDescendents == 0) { +- NSWindow* aWindow = ancestor->GetCocoaWindow(); +- if (ancestor->mWindowType != WindowType::Invisible) { +- [[aWindow standardWindowButton:NSWindowCloseButton] setEnabled:YES]; +- [[aWindow standardWindowButton:NSWindowMiniaturizeButton] setEnabled:YES]; +- [[aWindow standardWindowButton:NSWindowZoomButton] setEnabled:YES]; +- } ++ while (ancestor) { ++ if (--ancestor->mNumModalDescendents == 0) { ++ NSWindow* aWindow = ancestor->GetCocoaWindow(); ++ if (ancestor->mWindowType != WindowType::Invisible) { ++ [[aWindow standardWindowButton:NSWindowCloseButton] setEnabled:YES]; ++ [[aWindow standardWindowButton:NSWindowMiniaturizeButton] setEnabled:YES]; ++ [[aWindow standardWindowButton:NSWindowZoomButton] setEnabled:YES]; + } +- NS_ASSERTION(ancestor->mNumModalDescendents >= 0, "Widget hierarchy changed while modal!"); +- ancestor = static_cast(ancestor->mParent); + } +- if (gGeckoAppModalWindowList) { +- NS_ASSERTION(gGeckoAppModalWindowList->window == this, +- "Widget hierarchy changed while modal!"); +- nsCocoaWindowList* saved = gGeckoAppModalWindowList; +- gGeckoAppModalWindowList = gGeckoAppModalWindowList->prev; +- delete saved; // "window" not ADDREFed +- } +- if (mWindowType == WindowType::Popup) +- SetPopupWindowLevel(); +- else +- [mWindow setLevel:NSNormalWindowLevel]; ++ NS_ASSERTION(ancestor->mNumModalDescendents >= 0, "Widget hierarchy changed while modal!"); ++ ancestor = static_cast(ancestor->mParent); + } ++ if (gGeckoAppModalWindowList) { ++ NS_ASSERTION(gGeckoAppModalWindowList->window == this, ++ "Widget hierarchy changed while modal!"); ++ nsCocoaWindowList* saved = gGeckoAppModalWindowList; ++ gGeckoAppModalWindowList = gGeckoAppModalWindowList->prev; ++ delete saved; // "window" not ADDREFed ++ } ++ if (mWindowType == WindowType::Popup) ++ SetPopupWindowLevel(); ++ else ++ [mWindow setLevel:NSNormalWindowLevel]; + } + + NS_OBJC_END_TRY_IGNORE_BLOCK; + } + + void nsCocoaWindow::SetFakeModal(bool aState) { + mFakeModal = aState; + SetModal(aState); +@@ -800,32 +777,28 @@ void nsCocoaWindow::SetFakeModal(bool aS + bool nsCocoaWindow::IsRunningAppModal() { return [NSApp _isRunningAppModal]; } + + // Hide or show this window + void nsCocoaWindow::Show(bool bState) { + NS_OBJC_BEGIN_TRY_IGNORE_BLOCK; + + if (!mWindow) return; + +- if (!mSheetNeedsShow) { +- // Early exit if our current visibility state is already the requested state. +- if (bState == ([mWindow isVisible] || [mWindow isBeingShown])) { +- return; +- } ++ // Early exit if our current visibility state is already the requested state. ++ if (bState == ([mWindow isVisible] || [mWindow isBeingShown])) { ++ return; + } + + [mWindow setBeingShown:bState]; + if (bState && !mWasShown) { + mWasShown = true; + } + +- nsIWidget* parentWidget = mParent; +- nsCOMPtr piParentWidget(do_QueryInterface(parentWidget)); + NSWindow* nativeParentWindow = +- (parentWidget) ? (NSWindow*)parentWidget->GetNativeData(NS_NATIVE_WINDOW) : nil; ++ mParent ? (NSWindow*)mParent->GetNativeData(NS_NATIVE_WINDOW) : nil; + + if (bState && !mBounds.IsEmpty()) { + // If we had set the activationPolicy to accessory, then right now we won't + // have a dock icon. Make sure that we undo that and show a dock icon now that + // we're going to show a window. + if ([NSApp activationPolicy] != NSApplicationActivationPolicyRegular) { + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + PR_SetEnv("MOZ_APP_NO_DOCK="); +@@ -838,87 +811,17 @@ void nsCocoaWindow::Show(bool bState) { + } + } + + if (mPopupContentView) { + // Ensure our content view is visible. We never need to hide it. + mPopupContentView->Show(true); + } + +- if (mWindowType == WindowType::Sheet) { +- // bail if no parent window (its basically what we do in Carbon) +- if (!nativeParentWindow || !piParentWidget) return; +- +- NSWindow* topNonSheetWindow = nativeParentWindow; +- +- // If this sheet is the child of another sheet, hide the parent so that +- // this sheet can be displayed. Leave the parent mSheetNeedsShow alone, +- // that is only used to handle sibling sheet contention. The parent will +- // return once there are no more child sheets. +- bool parentIsSheet = false; +- if (NS_SUCCEEDED(piParentWidget->GetIsSheet(&parentIsSheet)) && parentIsSheet) { +- piParentWidget->GetSheetWindowParent(&topNonSheetWindow); +-#ifdef MOZ_THUNDERBIRD +- [NSApp endSheet:nativeParentWindow]; +-#else +- [nativeParentWindow.sheetParent endSheet:nativeParentWindow]; +-#endif +- } +- +- nsCOMPtr sheetShown; +- if (NS_SUCCEEDED(piParentWidget->GetChildSheet(true, getter_AddRefs(sheetShown))) && +- (!sheetShown || sheetShown == this)) { +- // If this sheet is already the sheet actually being shown, don't +- // tell it to show again. Otherwise the number of calls to +-#ifdef MOZ_THUNDERBIRD +- // [NSApp beginSheet...] won't match up with [NSApp endSheet...]. +-#else +- // [NSWindow beginSheet...] won't match up with [NSWindow endSheet...]. +-#endif +- if (![mWindow isVisible]) { +- mSheetNeedsShow = false; +- mSheetWindowParent = topNonSheetWindow; +-#ifdef MOZ_THUNDERBIRD +- // Only set contextInfo if our parent isn't a sheet. +- NSWindow* contextInfo = parentIsSheet ? nil : mSheetWindowParent; +- [TopLevelWindowData deactivateInWindow:mSheetWindowParent]; +- [NSApp beginSheet:mWindow +- modalForWindow:mSheetWindowParent +- modalDelegate:mDelegate +- didEndSelector:@selector(didEndSheet:returnCode:contextInfo:) +- contextInfo:contextInfo]; +-#else +- NSWindow* sheet = mWindow; +- NSWindow* nonSheetParent = parentIsSheet ? nil : mSheetWindowParent; +- [TopLevelWindowData deactivateInWindow:mSheetWindowParent]; +- [mSheetWindowParent beginSheet:sheet +- completionHandler:^(NSModalResponse returnCode) { +- // Note: 'nonSheetParent' (if it is set) is the window that is the parent +- // of the sheet. If it's set, 'nonSheetParent' is always the top- level +- // window, not another sheet itself. But 'nonSheetParent' is nil if our +- // parent window is also a sheet -- in that case we shouldn't send the +- // top-level window any activate events (because it's our parent window +- // that needs to get these events, not the top-level window). +- [TopLevelWindowData deactivateInWindow:sheet]; +- [sheet orderOut:nil]; +- if (nonSheetParent) { +- [TopLevelWindowData activateInWindow:nonSheetParent]; +- } +- }]; +-#endif +- [TopLevelWindowData activateInWindow:mWindow]; +- SendSetZLevelEvent(); +- } +- } else { +- // A sibling of this sheet is active, don't show this sheet yet. +- // When the active sheet hides, its brothers and sisters that have +- // mSheetNeedsShow set will have their opportunities to display. +- mSheetNeedsShow = true; +- } +- } else if (mWindowType == WindowType::Popup) { ++ if (mWindowType == WindowType::Popup) { + // For reasons that aren't yet clear, calls to [NSWindow orderFront:] or + // [NSWindow makeKeyAndOrderFront:] can sometimes trigger "Error (1000) + // creating CGSWindow", which in turn triggers an internal inconsistency + // NSException. These errors shouldn't be fatal. So we need to wrap + // calls to ...orderFront: in TRY blocks. See bmo bug 470864. + NS_OBJC_BEGIN_TRY_IGNORE_BLOCK; + [[mWindow contentView] setNeedsDisplay:YES]; + [mWindow orderFront:nil]; +@@ -974,120 +877,30 @@ void nsCocoaWindow::Show(bool bState) { + SendSetZLevelEvent(); + } + } else { + // roll up any popups if a top-level window is going away + if (mWindowType == WindowType::TopLevel || mWindowType == WindowType::Dialog) { + RollUpPopups(); + } + +- // now get rid of the window/sheet +- if (mWindowType == WindowType::Sheet) { +- if (mSheetNeedsShow) { +- // This is an attempt to hide a sheet that never had a chance to +- // be shown. There's nothing to do other than make sure that it +- // won't show. +- mSheetNeedsShow = false; +- } else { +- // get sheet's parent *before* hiding the sheet (which breaks the linkage) +- NSWindow* sheetParent = mSheetWindowParent; +- +- // hide the sheet +-#ifdef MOZ_THUNDERBIRD +- [NSApp endSheet:mWindow]; +-#else +- [mSheetWindowParent endSheet:mWindow]; +-#endif +- [TopLevelWindowData deactivateInWindow:mWindow]; +- +- nsCOMPtr siblingSheetToShow; +- bool parentIsSheet = false; +- +- if (nativeParentWindow && piParentWidget && +- NS_SUCCEEDED( +- piParentWidget->GetChildSheet(false, getter_AddRefs(siblingSheetToShow))) && +- siblingSheetToShow) { +- // First, give sibling sheets an opportunity to show. +- siblingSheetToShow->Show(true); +- } else if (nativeParentWindow && piParentWidget && +- NS_SUCCEEDED(piParentWidget->GetIsSheet(&parentIsSheet)) && parentIsSheet) { +-#ifdef MOZ_THUNDERBIRD +- // Only set contextInfo if the parent of the parent sheet we're about +- // to restore isn't itself a sheet. +- NSWindow* contextInfo = sheetParent; +-#else +- // Only set nonSheetGrandparent if the parent of the parent sheet we're about +- // to restore isn't itself a sheet. +- NSWindow* nonSheetGrandparent = sheetParent; +-#endif +- nsIWidget* grandparentWidget = nil; +- if (NS_SUCCEEDED(piParentWidget->GetRealParent(&grandparentWidget)) && +- grandparentWidget) { +- nsCOMPtr piGrandparentWidget(do_QueryInterface(grandparentWidget)); +- bool grandparentIsSheet = false; +- if (piGrandparentWidget && +- NS_SUCCEEDED(piGrandparentWidget->GetIsSheet(&grandparentIsSheet)) && +- grandparentIsSheet) { +-#ifdef MOZ_THUNDERBIRD +- contextInfo = nil; +-#else +- nonSheetGrandparent = nil; +-#endif +- } +- } +- // If there are no sibling sheets, but the parent is a sheet, restore +- // it. It wasn't sent any deactivate events when it was hidden, so +- // don't call through Show, just let the OS put it back up. +-#ifdef MOZ_THUNDERBIRD +- [NSApp beginSheet:nativeParentWindow +- modalForWindow:sheetParent +- modalDelegate:[nativeParentWindow delegate] +- didEndSelector:@selector(didEndSheet:returnCode:contextInfo:) +- contextInfo:contextInfo]; +-#else +- [nativeParentWindow beginSheet:sheetParent +- completionHandler:^(NSModalResponse returnCode) { +- // Note: 'nonSheetGrandparent' (if it is set) is the window that is the +- // parent of sheetParent. If it's set, 'nonSheetGrandparent' is always the +- // top-level window, not another sheet itself. But 'nonSheetGrandparent' +- // is nil if our parent window is also a sheet -- in that case we shouldn't +- // send the top-level window any activate events (because it's our parent +- // window that needs to get these events, not the top-level window). +- [TopLevelWindowData deactivateInWindow:sheetParent]; +- [sheetParent orderOut:nil]; +- if (nonSheetGrandparent) { +- [TopLevelWindowData activateInWindow:nonSheetGrandparent]; +- } +- }]; +-#endif +- } else { +- // Sheet, that was hard. No more siblings or parents, going back +- // to a real window. +- NS_OBJC_BEGIN_TRY_IGNORE_BLOCK; +- [sheetParent makeKeyAndOrderFront:nil]; +- NS_OBJC_END_TRY_IGNORE_BLOCK; +- } +- SendSetZLevelEvent(); +- } +- } else { +- // If the window is a popup window with a parent window we need to +- // unhook it here before ordering it out. When you order out the child +- // of a window it hides the parent window. +- if (mWindowType == WindowType::Popup && nativeParentWindow) +- [nativeParentWindow removeChildWindow:mWindow]; +- +- [mWindow orderOut:nil]; +- +- // If our popup window is a non-native context menu, tell the OS (and +- // other programs) that a menu has closed. +- if ([mWindow isKindOfClass:[PopupWindow class]] && [(PopupWindow*)mWindow isContextMenu]) { +- [[NSDistributedNotificationCenter defaultCenter] +- postNotificationName:@"com.apple.HIToolbox.endMenuTrackingNotification" +- object:@"org.mozilla.gecko.PopupWindow"]; +- } ++ // If the window is a popup window with a parent window we need to ++ // unhook it here before ordering it out. When you order out the child ++ // of a window it hides the parent window. ++ if (mWindowType == WindowType::Popup && nativeParentWindow) ++ [nativeParentWindow removeChildWindow:mWindow]; ++ ++ [mWindow orderOut:nil]; ++ ++ // If our popup window is a non-native context menu, tell the OS (and ++ // other programs) that a menu has closed. ++ if ([mWindow isKindOfClass:[PopupWindow class]] && [(PopupWindow*)mWindow isContextMenu]) { ++ [[NSDistributedNotificationCenter defaultCenter] ++ postNotificationName:@"com.apple.HIToolbox.endMenuTrackingNotification" ++ object:@"org.mozilla.gecko.PopupWindow"]; + } + } + + [mWindow setBeingShown:NO]; + + NS_OBJC_END_TRY_IGNORE_BLOCK; + } + +@@ -2136,59 +1949,22 @@ void nsCocoaWindow::Invalidate(const Lay + // a drop, to a drag enter/leave, or a drag over event. The actual event + // is passed in |aMessage| and is passed along to our event hanlder so Gecko + // knows about it. + bool nsCocoaWindow::DragEvent(unsigned int aMessage, mozilla::gfx::Point aMouseGlobal, + UInt16 aKeyModifiers) { + return false; + } + +-NS_IMETHODIMP nsCocoaWindow::SendSetZLevelEvent() { +- nsWindowZ placement = nsWindowZTop; +- nsCOMPtr actualBelow; +- if (mWidgetListener) ++void nsCocoaWindow::SendSetZLevelEvent() { ++ if (mWidgetListener) { ++ nsWindowZ placement = nsWindowZTop; ++ nsCOMPtr actualBelow; + mWidgetListener->ZLevelChanged(true, &placement, nullptr, getter_AddRefs(actualBelow)); +- return NS_OK; +-} +- +-NS_IMETHODIMP nsCocoaWindow::GetChildSheet(bool aShown, nsIWidget** _retval) { +- nsIWidget* child = GetFirstChild(); +- +- while (child) { +- if (child->GetWindowType() == WindowType::Sheet) { +- // if it's a sheet, it must be an nsCocoaWindow +- nsCocoaWindow* cocoaWindow = static_cast(child); +- if (cocoaWindow->mWindow && ((aShown && [cocoaWindow->mWindow isVisible]) || +- (!aShown && cocoaWindow->mSheetNeedsShow))) { +- nsCOMPtr widget = cocoaWindow; +- widget.forget(_retval); +- return NS_OK; +- } +- } +- child = child->GetNextSibling(); + } +- +- *_retval = nullptr; +- +- return NS_OK; +-} +- +-NS_IMETHODIMP nsCocoaWindow::GetRealParent(nsIWidget** parent) { +- *parent = mParent; +- return NS_OK; +-} +- +-NS_IMETHODIMP nsCocoaWindow::GetIsSheet(bool* isSheet) { +- mWindowType == WindowType::Sheet ? * isSheet = true : * isSheet = false; +- return NS_OK; +-} +- +-NS_IMETHODIMP nsCocoaWindow::GetSheetWindowParent(NSWindow** sheetWindowParent) { +- *sheetWindowParent = mSheetWindowParent; +- return NS_OK; + } + + // Invokes callback and ProcessEvent methods on Event Listener object + nsresult nsCocoaWindow::DispatchEvent(WidgetGUIEvent* event, nsEventStatus& aStatus) { + aStatus = nsEventStatus_eIgnore; + + nsCOMPtr kungFuDeathGrip(event->mWidget); + mozilla::Unused << kungFuDeathGrip; // Not used within this function +@@ -3030,19 +2806,17 @@ void nsCocoaWindow::CocoaWindowDidResize + + - (void)windowDidBecomeKey:(NSNotification*)aNotification { + NS_OBJC_BEGIN_TRY_IGNORE_BLOCK; + + RollUpPopups(); + ChildViewMouseTracker::ReEvaluateMouseEnterState(); + + NSWindow* window = [aNotification object]; +- if ([window isSheet]) [WindowDelegate paintMenubarForWindow:window]; +- +- nsChildView* mainChildView = ++ auto* mainChildView = + static_cast([[(BaseWindow*)window mainChildView] widget]); + if (mainChildView) { + if (mainChildView->GetInputContext().IsPasswordEditor()) { + TextInputHandler::EnableSecureEventInput(); + } else { + TextInputHandler::EnsureSecureEventInputDisabled(); + } + } +@@ -3051,22 +2825,16 @@ void nsCocoaWindow::CocoaWindowDidResize + } + + - (void)windowDidResignKey:(NSNotification*)aNotification { + NS_OBJC_BEGIN_TRY_IGNORE_BLOCK; + + RollUpPopups(nsIRollupListener::AllowAnimations::No); + + ChildViewMouseTracker::ReEvaluateMouseEnterState(); +- +- // If a sheet just resigned key then we should paint the menu bar +- // for whatever window is now main. +- NSWindow* window = [aNotification object]; +- if ([window isSheet]) [WindowDelegate paintMenubarForWindow:[NSApp mainWindow]]; +- + TextInputHandler::EnsureSecureEventInputDisabled(); + + NS_OBJC_END_TRY_IGNORE_BLOCK; + } + + - (void)windowWillMove:(NSNotification*)aNotification { + RollUpPopups(); + } +@@ -3105,42 +2873,16 @@ void nsCocoaWindow::CocoaWindowDidResize + + - (BOOL)windowShouldZoom:(NSWindow*)window toFrame:(NSRect)proposedFrame { + if (!mHasEverBeenZoomed && [window isZoomed]) return NO; // See bug 429954. + + mHasEverBeenZoomed = YES; + return YES; + } + +-- (NSRect)window:(NSWindow*)window willPositionSheet:(NSWindow*)sheet usingRect:(NSRect)rect { +- if ([window isKindOfClass:[ToolbarWindow class]]) { +- rect.origin.y = [(ToolbarWindow*)window sheetAttachmentPosition]; +- } +- return rect; +-} +- +-#ifdef MOZ_THUNDERBIRD +-- (void)didEndSheet:(NSWindow*)sheet returnCode:(int)returnCode contextInfo:(void*)contextInfo { +- NS_OBJC_BEGIN_TRY_ABORT_BLOCK; +- +- // Note: 'contextInfo' (if it is set) is the window that is the parent of +- // the sheet. The value of contextInfo is determined in +- // nsCocoaWindow::Show(). If it's set, 'contextInfo' is always the top- +- // level window, not another sheet itself. But 'contextInfo' is nil if +- // our parent window is also a sheet -- in that case we shouldn't send +- // the top-level window any activate events (because it's our parent +- // window that needs to get these events, not the top-level window). +- [TopLevelWindowData deactivateInWindow:sheet]; +- [sheet orderOut:self]; +- if (contextInfo) [TopLevelWindowData activateInWindow:(NSWindow*)contextInfo]; +- +- NS_OBJC_END_TRY_ABORT_BLOCK; +-} +-#endif +- + - (void)windowDidChangeBackingProperties:(NSNotification*)aNotification { + NS_OBJC_BEGIN_TRY_IGNORE_BLOCK; + + NSWindow* window = (NSWindow*)[aNotification object]; + + if ([window respondsToSelector:@selector(backingScaleFactor)]) { + CGFloat oldFactor = + [[[aNotification userInfo] objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue]; +@@ -3787,17 +3529,16 @@ static const NSString* kStateWantsTitleD + NSRect contentRect = frameRect; + + if ((self = [super initWithContentRect:contentRect + styleMask:aStyle + backing:aBufferingType + defer:aFlag])) { + mTitlebarView = nil; + mUnifiedToolbarHeight = 22.0f; +- mSheetAttachmentPosition = aChildViewRect.size.height; + mWindowButtonsRect = NSZeroRect; + mInitialTitlebarHeight = [self titlebarHeight]; + + [self setTitlebarAppearsTransparent:YES]; + #if !defined(MAC_OS_VERSION_11_0) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_VERSION_11_0 + if (nsCocoaFeatures::OnBigSurOrLater()) { + #else + if (@available(macOS 11.0, *)) { +@@ -4014,24 +3755,16 @@ static bool ShouldShiftByMenubarHeightIn + [self updateTitlebarView]; + } + + - (void)setWantsTitleDrawn:(BOOL)aDrawTitle { + [super setWantsTitleDrawn:aDrawTitle]; + [self setTitlebarNeedsDisplay]; + } + +-- (void)setSheetAttachmentPosition:(CGFloat)aY { +- mSheetAttachmentPosition = aY; +-} +- +-- (CGFloat)sheetAttachmentPosition { +- return mSheetAttachmentPosition; +-} +- + - (void)placeWindowButtons:(NSRect)aRect { + if (!NSEqualRects(mWindowButtonsRect, aRect)) { + mWindowButtonsRect = aRect; + [self reflowTitlebarElements]; + } + } + + - (NSRect)windowButtonsRect { +diff --git a/widget/cocoa/nsMenuX.h b/widget/cocoa/nsMenuX.h +--- a/widget/cocoa/nsMenuX.h ++++ b/widget/cocoa/nsMenuX.h +@@ -181,17 +181,18 @@ class nsMenuX final : public nsMenuParen + already_AddRefed GetMenuPopupContent(); + void WillInsertChild(const MenuChild& aChild); + void WillRemoveChild(const MenuChild& aChild); + void AddMenuChild(MenuChild&& aChild); + void InsertMenuChild(MenuChild&& aChild); + void RemoveMenuChild(const MenuChild& aChild); + mozilla::Maybe CreateMenuChild(nsIContent* aContent); + RefPtr CreateMenuItem(nsIContent* aMenuItemContent); +- GeckoNSMenu* CreateMenuWithGeckoString(nsString& aMenuTitle); ++ GeckoNSMenu* CreateMenuWithGeckoString(nsString& aMenuTitle, ++ bool aShowServices); + void DidFirePopupShowing(); + + // Find the index at which aChild needs to be inserted into mMenuChildren such that mMenuChildren + // remains in correct content order, i.e. the order in mMenuChildren is the same as the order of + // the DOM children of our . + size_t FindInsertionIndex(const MenuChild& aChild); + + // Calculates the index at which aChild's NSMenuItem should be inserted into our NSMenu. +diff --git a/widget/cocoa/nsMenuX.mm b/widget/cocoa/nsMenuX.mm +--- a/widget/cocoa/nsMenuX.mm ++++ b/widget/cocoa/nsMenuX.mm +@@ -89,20 +89,24 @@ nsMenuX::nsMenuX(nsMenuParentX* aParent, + + mMenuDelegate = [[MenuDelegate alloc] initWithGeckoMenu:this]; + mMenuDelegate.menuIsInMenubar = mMenuGroupOwner->GetMenuBar() != nullptr; + + if (!nsMenuBarX::sNativeEventTarget) { + nsMenuBarX::sNativeEventTarget = [[NativeMenuItemTarget alloc] init]; + } + ++ bool shouldShowServices = false; + if (mContent->IsElement()) { + mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::label, mLabel); ++ ++ shouldShowServices = ++ mContent->AsElement()->HasAttr(nsGkAtoms::showservicesmenu); + } +- mNativeMenu = CreateMenuWithGeckoString(mLabel); ++ mNativeMenu = CreateMenuWithGeckoString(mLabel, shouldShowServices); + + // register this menu to be notified when changes are made to our content object + NS_ASSERTION(mMenuGroupOwner, "No menu owner given, must have one"); + mMenuGroupOwner->RegisterForContentChanges(mContent, this); + + mVisible = !nsMenuUtilsX::NodeIsHiddenOrCollapsed(mContent); + + NSString* newCocoaLabelString = nsMenuUtilsX::GetTruncatedCocoaLabel(mLabel); +@@ -773,28 +777,33 @@ nsresult nsMenuX::SetEnabled(bool aIsEna + } + + nsresult nsMenuX::GetEnabled(bool* aIsEnabled) { + NS_ENSURE_ARG_POINTER(aIsEnabled); + *aIsEnabled = mIsEnabled; + return NS_OK; + } + +-GeckoNSMenu* nsMenuX::CreateMenuWithGeckoString(nsString& aMenuTitle) { ++GeckoNSMenu* nsMenuX::CreateMenuWithGeckoString(nsString& aMenuTitle, ++ bool aShowServices) { + NS_OBJC_BEGIN_TRY_ABORT_BLOCK; + + NSString* title = [NSString stringWithCharacters:(UniChar*)aMenuTitle.get() + length:aMenuTitle.Length()]; + GeckoNSMenu* myMenu = [[GeckoNSMenu alloc] initWithTitle:title]; + myMenu.delegate = mMenuDelegate; + + // We don't want this menu to auto-enable menu items because then Cocoa + // overrides our decisions and things get incorrectly enabled/disabled. + myMenu.autoenablesItems = NO; + ++ // Only show "Services", "Autofill" and similar entries provided by macOS ++ // if our caller wants them: ++ myMenu.allowsContextMenuPlugIns = aShowServices; ++ + // we used to install Carbon event handlers here, but since NSMenu* doesn't + // create its underlying MenuRef until just before display, we delay until + // that happens. Now we install the event handlers when Cocoa notifies + // us that a menu is about to display - see the Cocoa MenuDelegate class. + + return myMenu; + + NS_OBJC_END_TRY_ABORT_BLOCK; +diff --git a/widget/cocoa/nsNativeThemeCocoa.mm b/widget/cocoa/nsNativeThemeCocoa.mm +--- a/widget/cocoa/nsNativeThemeCocoa.mm ++++ b/widget/cocoa/nsNativeThemeCocoa.mm +@@ -387,19 +387,18 @@ static BOOL FrameIsInActiveWindow(nsIFra + if ([win isSheet]) { + return [win isKeyWindow]; + } + return [win isMainWindow] && ![win attachedSheet]; + } + + // Toolbar controls and content controls respond to different window + // activeness states. +-static BOOL IsActive(nsIFrame* aFrame, BOOL aIsToolbarControl) { +- if (aIsToolbarControl) return [NativeWindowForFrame(aFrame) isMainWindow]; +- return FrameIsInActiveWindow(aFrame); ++static BOOL IsActiveToolbarControl(nsIFrame* aFrame) { ++ return NativeWindowForFrame(aFrame).isMainWindow; + } + + static bool IsInSourceList(nsIFrame* aFrame) { + for (nsIFrame* frame = aFrame->GetParent(); frame; + frame = nsLayoutUtils::GetCrossDocParentFrameInProcess(frame)) { + if (frame->StyleDisplay()->EffectiveAppearance() == StyleAppearance::MozMacSourceList) { + return true; + } +@@ -2397,17 +2396,17 @@ Maybe ns + return Some(WidgetInfo::Toolbar(isMain)); + } + + case StyleAppearance::MozWindowTitlebar: { + return Nothing(); + } + + case StyleAppearance::Statusbar: +- return Some(WidgetInfo::StatusBar(IsActive(aFrame, YES))); ++ return Some(WidgetInfo::StatusBar(IsActiveToolbarControl(aFrame))); + + case StyleAppearance::MenulistButton: + case StyleAppearance::Menulist: { + ControlParams controlParams = ComputeControlParams(aFrame, elementState); + controlParams.pressed = IsOpenButton(aFrame); + DropdownParams params; + params.controlParams = controlParams; + params.pullsDown = false; +diff --git a/widget/cocoa/nsPIWidgetCocoa.idl b/widget/cocoa/nsPIWidgetCocoa.idl +--- a/widget/cocoa/nsPIWidgetCocoa.idl ++++ b/widget/cocoa/nsPIWidgetCocoa.idl +@@ -1,37 +0,0 @@ +-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +-/* This Source Code Form is subject to the terms of the Mozilla Public +- * License, v. 2.0. If a copy of the MPL was not distributed with this +- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +- +-#include "nsISupports.idl" +- +-interface nsIWidget; +- +-[ptr] native NSWindowPtr(NSWindow); +- +-// +-// nsPIWidgetCocoa +-// +-// A private interface (unfrozen, private to the widget implementation) that +-// gives us access to some extra features on a widget/window. +-// +-[uuid(f75ff69e-3a51-419e-bd29-042f804bc2ed)] +-interface nsPIWidgetCocoa : nsISupports +-{ +- void SendSetZLevelEvent(); +- +- // Find the displayed child sheet (if aShown) or a child sheet that +- // wants to be displayed (if !aShown) +- nsIWidget GetChildSheet(in boolean aShown); +- +- // Get the parent widget (if any) StandardCreate() was called with. +- nsIWidget GetRealParent(); +- +- // If the object implementing this interface is a sheet, this will return the +- // native NSWindow it is attached to +- readonly attribute NSWindowPtr sheetWindowParent; +- +- // True if window is a sheet +- readonly attribute boolean isSheet; +- +-}; // nsPIWidgetCocoa +diff --git a/widget/cocoa/nsWindowMap.mm b/widget/cocoa/nsWindowMap.mm +--- a/widget/cocoa/nsWindowMap.mm ++++ b/widget/cocoa/nsWindowMap.mm +@@ -160,17 +160,17 @@ + // only child widgets (nsChildView objects)). (The notification is sent + // to windowBecameKey: or windowBecameMain: below.) + // + // For use with clients that (like Firefox) do use top-level widgets (and + // have NSWindow delegates of class WindowDelegate). + + (void)activateInWindow:(NSWindow*)aWindow { + NS_OBJC_BEGIN_TRY_IGNORE_BLOCK; + +- WindowDelegate* delegate = (WindowDelegate*)[aWindow delegate]; ++ WindowDelegate* delegate = (WindowDelegate*)aWindow.delegate; + if (!delegate || ![delegate isKindOfClass:[WindowDelegate class]]) return; + + if ([delegate toplevelActiveState]) return; + [delegate sendToplevelActivateEvents]; + + NS_OBJC_END_TRY_IGNORE_BLOCK; + } + +diff --git a/widget/headless/HeadlessWidget.cpp b/widget/headless/HeadlessWidget.cpp +--- a/widget/headless/HeadlessWidget.cpp ++++ b/widget/headless/HeadlessWidget.cpp +@@ -155,20 +155,19 @@ void HeadlessWidget::GetCompositorWidget + mozilla::widget::CompositorWidgetInitData* aInitData) { + *aInitData = + mozilla::widget::HeadlessCompositorWidgetInitData(GetClientSize()); + } + + nsIWidget* HeadlessWidget::GetTopLevelWidget() { return mTopLevel; } + + void HeadlessWidget::RaiseWindow() { +- MOZ_ASSERT(mWindowType == WindowType::TopLevel || +- mWindowType == WindowType::Dialog || +- mWindowType == WindowType::Sheet, +- "Raising a non-toplevel window."); ++ MOZ_ASSERT( ++ mWindowType == WindowType::TopLevel || mWindowType == WindowType::Dialog, ++ "Raising a non-toplevel window."); + + // Do nothing if this is the currently active window. + RefPtr activeWindow = GetActiveWindow(); + if (activeWindow == this) { + return; + } + + // Raise the window to the top of the stack. +@@ -199,17 +198,17 @@ void HeadlessWidget::Show(bool aState) { + + LOG(("HeadlessWidget::Show [%p] state %d\n", (void*)this, aState)); + + // Top-level window and dialogs are activated/raised when shown. + // NB: alwaysontop windows are generally used for peripheral indicators, + // so we don't focus them by default. + if (aState && !mAlwaysOnTop && + (mWindowType == WindowType::TopLevel || +- mWindowType == WindowType::Dialog || mWindowType == WindowType::Sheet)) { ++ mWindowType == WindowType::Dialog)) { + RaiseWindow(); + } + + ApplySizeModeSideEffects(); + } + + bool HeadlessWidget::IsVisible() const { return mVisible; } + diff --git a/xpcom/build/BinaryPath.h b/xpcom/build/BinaryPath.h --- a/xpcom/build/BinaryPath.h +++ b/xpcom/build/BinaryPath.h @@ -148,3 +1449,60 @@ diff --git a/xpcom/build/BinaryPath.h b/xpcom/build/BinaryPath.h nsresult rv = GetW(exePath); # else char exePath[MAXPATHLEN]; +diff --git a/xpcom/ds/StaticAtoms.py b/xpcom/ds/StaticAtoms.py +--- a/xpcom/ds/StaticAtoms.py ++++ b/xpcom/ds/StaticAtoms.py +@@ -1141,16 +1141,17 @@ STATIC_ATOMS = [ + Atom("self", "self"), + Atom("seltype", "seltype"), + Atom("setcookie", "set-cookie"), + Atom("setter", "setter"), + Atom("shadow", "shadow"), + Atom("shape", "shape"), + Atom("show", "show"), + Atom("showcaret", "showcaret"), ++ Atom("showservicesmenu", "showservicesmenu"), + Atom("sibling", "sibling"), + Atom("simple", "simple"), + Atom("simp_chinese_formal", "simp-chinese-formal"), + Atom("simp_chinese_informal", "simp-chinese-informal"), + Atom("single", "single"), + Atom("size", "size"), + Atom("sizes", "sizes"), + Atom("sizemode", "sizemode"), +diff --git a/xpfe/appshell/nsAppShellService.cpp b/xpfe/appshell/nsAppShellService.cpp +--- a/xpfe/appshell/nsAppShellService.cpp ++++ b/xpfe/appshell/nsAppShellService.cpp +@@ -590,32 +590,16 @@ nsresult nsAppShellService::JustCreateTo + nsIWebBrowserChrome::CHROME_TITLEBAR | + nsIWebBrowserChrome::CHROME_STATUSBAR; + if (widgetInitData.mWindowType == widget::WindowType::Dialog && + ((aChromeMask & pipMask) == pipMask) && !(aChromeMask & barMask)) { + widgetInitData.mPIPWindow = true; + } + #endif + +-#ifdef XP_MACOSX +- // Mac OS X sheet support +- // Adding CHROME_OPENAS_CHROME to sheetMask makes modal windows opened from +- // nsGlobalWindow::ShowModalDialog() be dialogs (not sheets), while modal +- // windows opened from nsPromptService::DoDialog() still are sheets. This +- // fixes bmo bug 395465 (see nsCocoaWindow::StandardCreate() and +- // nsCocoaWindow::SetModal()). +- uint32_t sheetMask = nsIWebBrowserChrome::CHROME_OPENAS_DIALOG | +- nsIWebBrowserChrome::CHROME_MODAL | +- nsIWebBrowserChrome::CHROME_OPENAS_CHROME; +- if (parent && (parent != mHiddenWindow) && +- ((aChromeMask & sheetMask) == sheetMask)) { +- widgetInitData.mWindowType = widget::WindowType::Sheet; +- } +-#endif +- + #if defined(XP_WIN) + if (widgetInitData.mWindowType == widget::WindowType::TopLevel || + widgetInitData.mWindowType == widget::WindowType::Dialog) + widgetInitData.mClipChildren = true; + #endif + + // note default chrome overrides other OS chrome settings, but + // not internal chrome diff --git a/app/scripts/fetch_xulrunner b/app/scripts/fetch_xulrunner index 2b57bfbc22..2b94c4deeb 100755 --- a/app/scripts/fetch_xulrunner +++ b/app/scripts/fetch_xulrunner @@ -355,6 +355,10 @@ function modify_omni { } popupset.appendChild(this._autoScrollPopup);' chrome/toolkit/content/global/elements/browser-custom-element.js + # Show Services menu on input fields + # (JS part of https://hg.mozilla.org/mozilla-central/rev/defc298879844981e7c1817f13e3fc2caf84f148 for input boxes) + replace_line '' '' chrome/toolkit/content/global/elements/moz-input-box.js + zip -qr9XD omni.ja * mv omni.ja .. cd .. @@ -409,18 +413,33 @@ if [ $BUILD_MAC == 1 ]; then hdiutil detach -quiet /Volumes/Firefox fi - # Download custom components - #echo - #rm -rf MacOS - #if [ -e "Firefox $GECKO_VERSION MacOS.zip" ]; then - # echo "Using Firefox $GECKO_VERSION MacOS.zip" - # unzip "Firefox $GECKO_VERSION MacOS.zip" - #else - # echo "Downloading Firefox $GECKO_VERSION MacOS.zip" - # curl -o MacOS.zip "${custom_components_url}Firefox%20$GECKO_VERSION%20MacOS.zip" - # unzip MacOS.zip - #fi - #echo + # Download custom components (e.g., XUL), as an xz-compressed tarball of the MacOS folder with + # custom files in it + echo + rm -rf MacOS + if [ -n "$custom_components_hash_mac" ]; then + if [ -e "Firefox $GECKO_VERSION MacOS.zip" ]; then + echo "Using Firefox $GECKO_VERSION MacOS.zip" + unzip "Firefox $GECKO_VERSION MacOS.zip" + else + echo "Downloading custom Firefox components" + echo + curl -o MacOS.tar.xz "${custom_components_url}mac/$custom_components_hash_mac.tar.xz" + + # Verify hash + if [[ "`uname`" = "Darwin" ]]; then + shasum=sha256sum + else + shasum=shasum + fi + echo + echo "$custom_components_hash_mac MacOS.tar.xz" | $shasum -c - + echo + + tar xvf MacOS.tar.xz + fi + echo + fi pushd Firefox.app/Contents/Resources modify_omni mac