Bug 1303051 - Printing Issue: Page Setup not being respected since upgrade to 48.01 on Mac; r=mconley draft
authorHaik Aftandilian <haftandilian@mozilla.com>
Wed, 09 Nov 2016 17:37:40 -0800
changeset 436905 baa2a5865b29db8914fca1242af59674f9630c8e
parent 433311 3b80868f7a8fe0361918a814fbbbfb9308ae0c0a
child 536481 8c4e07b7dca5c74613777a4714f58c9e382bf67e
push id35241
push userhaftandilian@mozilla.com
push dateThu, 10 Nov 2016 02:06:48 +0000
reviewersmconley
bugs1303051
milestone52.0a1
Bug 1303051 - Printing Issue: Page Setup not being respected since upgrade to 48.01 on Mac; r=mconley Adds serialization of native print settings values so that correct page size, scaling, orientation are sent to the child after the print dialog is displayed. Changes the Mac print dialog code to load native print settings from the "print.macosx.pagesetup-2" pref and ignore what is passed in. Overwrites the scaling percentage specified in the print dialog when "Ignore Scaling and Shrink to Fit Page Width" is checked. Scaling on Nightly (remote printing) needs more work to be done in a follow up bug. MozReview-Commit-ID: B12ZeHuiYFJ
embedding/components/printingui/ipc/PPrintingTypes.ipdlh
widget/cocoa/nsPrintDialogX.mm
widget/cocoa/nsPrintOptionsX.h
widget/cocoa/nsPrintOptionsX.mm
widget/cocoa/nsPrintSettingsX.h
widget/cocoa/nsPrintSettingsX.mm
--- a/embedding/components/printingui/ipc/PPrintingTypes.ipdlh
+++ b/embedding/components/printingui/ipc/PPrintingTypes.ipdlh
@@ -100,12 +100,25 @@ struct PrintData {
   /** TODO: Is there an "unsigned short" primitive? **/
   short pagesAcross;
   short pagesDown;
   double printTime;
   bool detailedErrorReporting;
   nsString faxNumber;
   bool addHeaderAndFooter;
   bool fileNameExtensionHidden;
+  /*
+   * Holds the scaling factor from the Print dialog when shrink
+   * to fit is not used. This is needed by the child when it
+   * isn't using remote printing. When shrink to fit is enabled
+   * (default), print dialog code ensures this value is 1.0.
+   */
+  float scalingFactor;
+  /*
+   * Scaling factor for converting from OS X native paper size
+   * units to inches.
+   */
+  float widthScale;
+  float heightScale;
 };
 
 } // namespace embedding
 } // namespace mozilla
--- a/widget/cocoa/nsPrintDialogX.mm
+++ b/widget/cocoa/nsPrintDialogX.mm
@@ -2,16 +2,17 @@
 /* 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 "mozilla/ArrayUtils.h"
 
 #include "nsPrintDialogX.h"
 #include "nsIPrintSettings.h"
+#include "nsIPrintSettingsService.h"
 #include "nsPrintSettingsX.h"
 #include "nsCOMPtr.h"
 #include "nsQueryObject.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIWebProgressListener.h"
 #include "nsIStringBundle.h"
 #include "nsIWebBrowserPrint.h"
 #include "nsCRT.h"
@@ -44,16 +45,19 @@ nsPrintDialogServiceX::Show(nsPIDOMWindo
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   NS_PRECONDITION(aSettings, "aSettings must not be null");
 
   RefPtr<nsPrintSettingsX> settingsX(do_QueryObject(aSettings));
   if (!settingsX)
     return NS_ERROR_FAILURE;
 
+  nsCOMPtr<nsIPrintSettingsService> printSettingsSvc
+    = do_GetService("@mozilla.org/gfx/printsettings-service;1");
+
   // Set the print job title
   char16_t** docTitles;
   uint32_t titleCount;
   nsresult rv = aWebBrowserPrint->EnumerateDocumentNames(&titleCount, &docTitles);
   if (NS_SUCCEEDED(rv) && titleCount > 0) {
     CFStringRef cfTitleString = CFStringCreateWithCharacters(NULL, reinterpret_cast<const UniChar*>(docTitles[0]),
                                                              NS_strlen(docTitles[0]));
     if (cfTitleString) {
@@ -63,16 +67,19 @@ nsPrintDialogServiceX::Show(nsPIDOMWindo
     for (int32_t i = titleCount - 1; i >= 0; i--) {
       free(docTitles[i]);
     }
     free(docTitles);
     docTitles = NULL;
     titleCount = 0;
   }
 
+  // Read default print settings from prefs
+  printSettingsSvc->InitPrintSettingsFromPrefs(settingsX, true,
+    nsIPrintSettings::kInitSaveNativeData);
   NSPrintInfo* printInfo = settingsX->GetCocoaPrintInfo();
 
   // Put the print info into the current print operation, since that's where
   // [panel runModal] will look for it. We create the view because otherwise
   // we'll get unrelated warnings printed to the console.
   NSView* tmpView = [[NSView alloc] init];
   NSPrintOperation* printOperation = [NSPrintOperation printOperationWithView:tmpView printInfo:printInfo];
   [NSPrintOperation setCurrentOperation:printOperation];
@@ -92,28 +99,60 @@ nsPrintDialogServiceX::Show(nsPIDOMWindo
   nsCocoaUtils::PrepareForNativeAppModalDialog();
   int button = [panel runModal];
   nsCocoaUtils::CleanUpAfterNativeAppModalDialog();
 
   NSPrintInfo* copy = [[[NSPrintOperation currentOperation] printInfo] copy];
   if (!copy) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
-  settingsX->SetCocoaPrintInfo(copy);
-  [copy release];
 
   [NSPrintOperation setCurrentOperation:nil];
   [tmpView release];
 
   if (button != NSFileHandlingPanelOKButton)
     return NS_ERROR_ABORT;
 
+  settingsX->SetCocoaPrintInfo(copy);
+  settingsX->InitUnwriteableMargin();
+
+  // Save settings unless saving is pref'd off
+  if (Preferences::GetBool("print.save_print_settings", false)) {
+    printSettingsSvc->SavePrintSettingsToPrefs(settingsX, true,
+      nsIPrintSettings::kInitSaveNativeData);
+  }
+
+  // Get coordinate space resolution for converting paper size units to inches
+  NSWindow *win = [[NSApplication sharedApplication] mainWindow];
+  if (win) {
+    NSDictionary *devDesc = [win deviceDescription];
+    if (devDesc) {
+      NSSize res = [[devDesc objectForKey: NSDeviceResolution] sizeValue];
+      float scale = [win backingScaleFactor];
+      if (scale > 0) {
+        settingsX->SetInchesScale(res.width / scale, res.height / scale);
+      }
+    }
+  }
+
   // Export settings.
   [viewController exportSettings];
 
+  // If "ignore scaling" is checked, overwrite scaling factor with 1.
+  bool isShrinkToFitChecked;
+  settingsX->GetShrinkToFit(&isShrinkToFitChecked);
+  if (isShrinkToFitChecked) {
+    NSMutableDictionary* dict = [copy dictionary];
+    if (dict) {
+      [dict setObject: [NSNumber numberWithFloat: 1]
+               forKey: NSPrintScalingFactor];
+    }
+  }
+  [copy release];
+
   int16_t pageRange;
   aSettings->GetPrintRange(&pageRange);
   if (pageRange != nsIPrintSettings::kRangeSelection) {
     PMPrintSettings nativePrintSettings = settingsX->GetPMPrintSettings();
     UInt32 firstPage, lastPage;
     OSStatus status = ::PMGetFirstPage(nativePrintSettings, &firstPage);
     if (status == noErr) {
       status = ::PMGetLastPage(nativePrintSettings, &lastPage);
--- a/widget/cocoa/nsPrintOptionsX.h
+++ b/widget/cocoa/nsPrintOptionsX.h
@@ -17,16 +17,23 @@ namespace embedding
 } // namespace mozilla
 
 class nsPrintOptionsX : public nsPrintOptions
 {
 public:
              nsPrintOptionsX();
   virtual    ~nsPrintOptionsX();
 
+  /*
+   * These serialize and deserialize methods are not symmetrical in that
+   * printSettingsX != deserialize(serialize(printSettingsX)). This is because
+   * the native print settings stored in the nsPrintSettingsX's NSPrintInfo
+   * object are not fully serialized. Only the values needed for successful
+   * printing are.
+   */
   NS_IMETHODIMP SerializeToPrintData(nsIPrintSettings* aSettings,
                                      nsIWebBrowserPrint* aWBP,
                                      mozilla::embedding::PrintData* data);
   NS_IMETHODIMP DeserializeToPrintSettings(const mozilla::embedding::PrintData& data,
                                            nsIPrintSettings* settings);
 
 protected:
   nsresult   _CreatePrintSettings(nsIPrintSettings **_retval);
--- a/widget/cocoa/nsPrintOptionsX.mm
+++ b/widget/cocoa/nsPrintOptionsX.mm
@@ -4,16 +4,29 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsCOMPtr.h"
 #include "nsQueryObject.h"
 #include "nsIServiceManager.h"
 #include "nsPrintOptionsX.h"
 #include "nsPrintSettingsX.h"
 
+// The constants for paper orientation were renamed in 10.9. __MAC_10_9 is
+// defined on OS X 10.9 and later. Although 10.8 and earlier are not supported
+// at this time, this allows for building on those older OS versions. The
+// values are consistent across OS versions so the rename does not affect
+// runtime, just compilation.
+#ifdef __MAC_10_9
+#define NS_PAPER_ORIENTATION_PORTRAIT   (NSPaperOrientationPortrait)
+#define NS_PAPER_ORIENTATION_LANDSCAPE  (NSPaperOrientationLandscape)
+#else
+#define NS_PAPER_ORIENTATION_PORTRAIT   (NSPortraitOrientation)
+#define NS_PAPER_ORIENTATION_LANDSCAPE  (NSLandscapeOrientation)
+#endif
+
 using namespace mozilla::embedding;
 
 nsPrintOptionsX::nsPrintOptionsX()
 {
 }
 
 nsPrintOptionsX::~nsPrintOptionsX()
 {
@@ -85,16 +98,48 @@ nsPrintOptionsX::SerializeToPrintData(ns
     data->printTime() = timestamp;
   }
 
   NSString* disposition = [dict objectForKey: NSPrintJobDisposition];
   if (disposition) {
     nsCocoaUtils::GetStringForNSString(disposition, data->disposition());
   }
 
+  NSString* paperName = [dict objectForKey: NSPrintPaperName];
+  if (paperName) {
+    nsCocoaUtils::GetStringForNSString(paperName, data->paperName());
+  }
+
+  float scalingFactor = [[dict objectForKey: NSPrintScalingFactor] floatValue];
+  data->scalingFactor() = scalingFactor;
+
+  int32_t orientation;
+  if ([printInfo orientation] == NS_PAPER_ORIENTATION_PORTRAIT) {
+    orientation = nsIPrintSettings::kPortraitOrientation;
+  } else {
+    orientation = nsIPrintSettings::kLandscapeOrientation;
+  }
+  data->orientation() = orientation;
+
+  NSSize paperSize = [printInfo paperSize];
+  float widthScale, heightScale;
+  settingsX->GetInchesScale(&widthScale, &heightScale);
+  if (orientation == nsIPrintSettings::kLandscapeOrientation) {
+    // switch widths and heights
+    data->widthScale() = heightScale;
+    data->heightScale() = widthScale;
+    data->paperWidth() = paperSize.height / heightScale;
+    data->paperHeight() = paperSize.width / widthScale;
+  } else {
+    data->widthScale() = widthScale;
+    data->heightScale() = heightScale;
+    data->paperWidth() = paperSize.width / widthScale;
+    data->paperHeight() = paperSize.height / heightScale;
+  }
+
   data->numCopies() = [[dict objectForKey: NSPrintCopies] intValue];
   data->printAllPages() = [[dict objectForKey: NSPrintAllPages] boolValue];
   data->startPageRange() = [[dict objectForKey: NSPrintFirstPage] intValue];
   data->endPageRange() = [[dict objectForKey: NSPrintLastPage] intValue];
   data->mustCollate() = [[dict objectForKey: NSPrintMustCollate] boolValue];
   data->printReversed() = [[dict objectForKey: NSPrintReversePageOrder] boolValue];
   data->pagesAcross() = [[dict objectForKey: NSPrintPagesAcross] unsignedShortValue];
   data->pagesDown() = [[dict objectForKey: NSPrintPagesDown] unsignedShortValue];
@@ -163,16 +208,38 @@ nsPrintOptionsX::DeserializeToPrintSetti
   [newPrintInfoDict setObject: [NSNumber numberWithBool: data.mustCollate()]
                     forKey: NSPrintMustCollate];
   [newPrintInfoDict setObject: [NSNumber numberWithBool: data.printReversed()]
                     forKey: NSPrintReversePageOrder];
 
   [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.disposition())
                     forKey: NSPrintJobDisposition];
 
+  [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.paperName())
+                    forKey: NSPrintPaperName];
+
+  [newPrintInfoDict setObject: [NSNumber numberWithFloat: data.scalingFactor()]
+                    forKey: NSPrintScalingFactor];
+
+  CGFloat width = data.paperWidth() * data.widthScale();
+  CGFloat height = data.paperHeight() * data.heightScale();
+  [newPrintInfoDict setObject: [NSValue valueWithSize:NSMakeSize(width,height)]
+                    forKey: NSPrintPaperSize];
+
+  int paperOrientation;
+  if (data.orientation() == nsIPrintSettings::kPortraitOrientation) {
+    paperOrientation = NS_PAPER_ORIENTATION_PORTRAIT;
+    settings->SetOrientation(nsIPrintSettings::kPortraitOrientation);
+  } else {
+    paperOrientation = NS_PAPER_ORIENTATION_LANDSCAPE;
+    settings->SetOrientation(nsIPrintSettings::kLandscapeOrientation);
+  }
+  [newPrintInfoDict setObject: [NSNumber numberWithInt:paperOrientation]
+                    forKey: NSPrintOrientation];
+
   [newPrintInfoDict setObject: [NSNumber numberWithShort: data.pagesAcross()]
                     forKey: NSPrintPagesAcross];
   [newPrintInfoDict setObject: [NSNumber numberWithShort: data.pagesDown()]
                     forKey: NSPrintPagesDown];
   [newPrintInfoDict setObject: [NSNumber numberWithBool: data.detailedErrorReporting()]
                     forKey: NSPrintDetailedErrorReporting];
   [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.faxNumber())
                     forKey: NSPrintFaxNumber];
--- a/widget/cocoa/nsPrintSettingsX.h
+++ b/widget/cocoa/nsPrintSettingsX.h
@@ -26,31 +26,39 @@ public:
   virtual nsresult ReadPageFormatFromPrefs();
   virtual nsresult WritePageFormatToPrefs();
 
   PMPrintSettings GetPMPrintSettings();
   PMPrintSession GetPMPrintSession();
   PMPageFormat GetPMPageFormat();
   void SetPMPageFormat(PMPageFormat aPageFormat);
 
+  // Re-initialize mUnwriteableMargin with values from mPageFormat.
+  // Should be called whenever mPageFormat is initialized or overwritten.
+  nsresult InitUnwriteableMargin();
+
+  void SetInchesScale(float aWidthScale, float aHeightScale);
+  void GetInchesScale(float *aWidthScale, float *aHeightScale);
+
 protected:
   virtual ~nsPrintSettingsX();
 
   nsPrintSettingsX(const nsPrintSettingsX& src);
   nsPrintSettingsX& operator=(const nsPrintSettingsX& rhs);
 
   nsresult _Clone(nsIPrintSettings **_retval) override;
   nsresult _Assign(nsIPrintSettings *aPS) override;
 
-  // Re-initialize mUnwriteableMargin with values from mPageFormat.
-  // Should be called whenever mPageFormat is initialized or overwritten.
-  nsresult InitUnwriteableMargin();
-
   // The out param has a ref count of 1 on return so caller needs to PMRelase() when done.
   OSStatus CreateDefaultPageFormat(PMPrintSession aSession, PMPageFormat& outFormat);
   OSStatus CreateDefaultPrintSettings(PMPrintSession aSession, PMPrintSettings& outSettings);
 
   NSPrintInfo* mPrintInfo;
+
+  // Scaling factors used to convert the NSPrintInfo
+  // paper size units to inches
+  float mWidthScale;
+  float mHeightScale;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsPrintSettingsX, NS_PRINTSETTINGSX_IID)
 
 #endif // nsPrintSettingsX_h_
--- a/widget/cocoa/nsPrintSettingsX.mm
+++ b/widget/cocoa/nsPrintSettingsX.mm
@@ -11,24 +11,27 @@
 
 #include "nsCocoaUtils.h"
 
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 
 #define MAC_OS_X_PAGE_SETUP_PREFNAME    "print.macosx.pagesetup-2"
+#define COCOA_PAPER_UNITS_PER_INCH      72.0
 
 NS_IMPL_ISUPPORTS_INHERITED(nsPrintSettingsX, nsPrintSettings, nsPrintSettingsX)
 
 nsPrintSettingsX::nsPrintSettingsX()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   mPrintInfo = [[NSPrintInfo sharedPrintInfo] copy];
+  mWidthScale = COCOA_PAPER_UNITS_PER_INCH;
+  mHeightScale = COCOA_PAPER_UNITS_PER_INCH;
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 nsPrintSettingsX::nsPrintSettingsX(const nsPrintSettingsX& src)
 {
   *this = src;
 }
@@ -195,8 +198,21 @@ nsPrintSettingsX::GetPMPageFormat()
 void
 nsPrintSettingsX::SetPMPageFormat(PMPageFormat aPageFormat)
 {
   PMPageFormat oldPageFormat = GetPMPageFormat();
   ::PMCopyPageFormat(aPageFormat, oldPageFormat);
   [mPrintInfo updateFromPMPageFormat];
 }
 
+void
+nsPrintSettingsX::SetInchesScale(float aWidthScale, float aHeightScale)
+{
+  mWidthScale = aWidthScale;
+  mHeightScale = aHeightScale;
+}
+
+void
+nsPrintSettingsX::GetInchesScale(float *aWidthScale, float *aHeightScale)
+{
+  *aWidthScale = mWidthScale;
+  *aHeightScale = mHeightScale;
+}