Files
firefox/widget/nsIPrintDialogService.idl
Stephen A Pohl 5f15185120 Bug 2035195: Migrate the system print dialog off runModal and remove nsCocoaUtils::PrepareForNativeAppModalDialog. r=Thinker,mac-reviewers,win-reviewers,bradwerth,handyman
This builds on bug 1909546, which migrated the file picker off the same nested-runModal pattern. After this change there are no more callers of PrepareForNativeAppModalDialog / CleanUpAfterNativeAppModalDialog on macOS, so the helpers are removed along with their internal state.

The print dialog service interface (nsIPrintDialogService) is converted to an asynchronous, Promise-returning shape: showPrintDialog and showPageSetupDialog now return a Promise that resolves with undefined when the user accepts the dialog and rejects with NS_ERROR_ABORT (or another nsresult on failure) when they don't. Native synchronous behavior on Windows and GTK is preserved by resolving/rejecting the promise inline before returning from the synchronous native call; no behavior change is intended on either platform. Both methods now also assert NS_IsMainThread().

On macOS, the native print dialog and page setup dialog are presented as window-modal sheets on the parent NSWindow, replacing the application-modal -[NSPrintPanel runModal] and -[NSPageLayout runModalWithPrintInfo:] calls. Because the modern block-based sheet API (-beginSheetUsingPrintInfo:onWindow:completionHandler:) is only available on macOS 14+, this patch wraps the older delegate-based sheet API (-beginSheetWithPrintInfo:modalForWindow:delegate:didEndSelector: contextInfo:) in MozPrintPanelDidEndAdapter, a small self-owning helper that translates the didEnd: callback into a block. The completion block resolves or rejects the promise after extracting settings from NSPrintInfo (pages-per-sheet move, accessory export, SetFromPrintInfo); the synchronous portion of the entry point returns immediately after kicking off the sheet, with the promise still pending.

The Windows ShowPageSetupDialog uses MakeScopeExit to keep its early-exit format: a single scope-exit guard resolves or rejects the promise based on a tracked nsresult, so the body can keep using `if (NS_FAILED(rv)) return NS_OK;` rather than threading promise calls through every error path.

The JS callers in toolkit/components/printing/content/printUtils.js (handleSystemPrintDialog and showPageSetup) are now simple `await svc.showPrintDialog(...)` / `.catch(e => dump(...))` calls. Behavior in print.js is unchanged because _showPrintDialog already awaits handleSystemPrintDialog.

With the helpers gone, nsMenuUtilsX::GetStandardEditMenuItem (whose only caller was the menu-bar swap inside PrepareForNativeAppModalDialog) is removed as well. The original motivation for that menu swap (bug 372571 - keyboard shortcuts inside the macOS file picker) is preserved automatically because window-modal sheets leave the parent window's edit menu live.

Side benefits:
* Two concurrent system print requests on the same parent no longer produce a nested -runModal stack; AppKit queues them as sheets on that window.
* The brittle NSApp.mainMenu mutation that has accumulated four patches in the last 18 months (bugs 1765391, 1941595, 1959023, 1947539) is gone.
* The dialogs match modern macOS UX (Safari, Pages, Preview).

Differential Revision: https://phabricator.services.mozilla.com/D297547
2026-05-13 02:40:42 +00:00

65 lines
2.6 KiB
Plaintext

/* 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/. */
/* Doc interface here */
#include "nsISupports.idl"
#include "nsIWebProgressListener.idl"
#include "nsIPrintSettings.idl"
#include "nsIObserver.idl"
interface mozIDOMWindowProxy;
/**
* Service for opening native print dialogs provided by the operating system.
* (The widget code may customize the dialog.)
*/
[scriptable, uuid(eaec573e-3c6a-4c6b-861e-32da6a962c68)]
interface nsIPrintDialogService : nsISupports
{
/**
* Initialize the service.
*/
void init();
/**
* Show the print dialog asynchronously.
*
* @param aParent A DOM window the dialog will be parented to.
* @param aHaveSelection A boolean indicating whether the document to be
* printed has some selected text, which is used to
* determine whether the "Print selection only" radio
* button is enabled in the print settings dialog.
* @param aPrintSettings On entry, this contains initial settings for the
* print dialog. If the returned promise resolves,
* the settings have been updated with the user's
* choices.
* @return A promise that resolves with undefined when the user accepts the
* dialog. The promise rejects with NS_ERROR_ABORT when the user
* cancels, or with another nsresult if the dialog itself fails to
* display or its result cannot be applied to the supplied
* settings. Callers must invoke this on the main thread; the
* promise is also resolved/rejected on the main thread.
*/
[implicit_jscontext]
Promise showPrintDialog(in mozIDOMWindowProxy aParent,
in boolean aHaveSelection,
in nsIPrintSettings aPrintSettings);
/**
* Show the page setup dialog asynchronously.
*
* @param aParent A DOM window the dialog will be parented to.
* @param aPrintSettings On entry, this contains initial settings for the
* page setup dialog. If the returned promise
* resolves, the settings have been updated with the
* user's choices.
* @return A promise with the same resolve/reject semantics as
* showPrintDialog above.
*/
[implicit_jscontext]
Promise showPageSetupDialog(in mozIDOMWindowProxy aParent,
in nsIPrintSettings aPrintSettings);
};