mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 16:55:40 +00:00
Bug 1655558 - Retrieve paper information from CUPS, and convert paperList to an async attribute. r=jwatt
This builds on top of bug 1656146 to compute the page information on a background task, and return it via a promise. Co-Authored-By: Erik Nordin <enordin@mozilla.com> Differential Revision: https://phabricator.services.mozilla.com/D85865
This commit is contained in:
parent
ba8d99b8aa
commit
6d5ce8f732
@ -8,7 +8,7 @@
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function run() {
|
||||
async function run() {
|
||||
try {
|
||||
let printerList = Cc["@mozilla.org/gfx/printerlist;1"].getService(
|
||||
Ci.nsIPrinterList
|
||||
@ -16,10 +16,17 @@ function run() {
|
||||
if (printerList.printers.length == 0) {
|
||||
ok(true, "There were no printers to iterate through.");
|
||||
}
|
||||
printerList.printers.forEach(printer => {
|
||||
|
||||
for (let printer of printerList.printers) {
|
||||
isnot(printer.name, null, "Printer name should never be null.");
|
||||
isnot(printer.name, "", "Printer name should never be empty.");
|
||||
printer.paperList.forEach(paper => {
|
||||
info(printer.name);
|
||||
|
||||
let paperList = await printer.paperList;
|
||||
for (let paper of paperList) {
|
||||
paper.QueryInterface(Ci.nsIPaper);
|
||||
|
||||
info(`${paper.name}: ${paper.width}x${paper.height} with margin: ${paper.unwriteableMarginTop} ${paper.unwriteableMarginRight} ${paper.unwriteableMarginBottom} ${paper.unwriteableMarginLeft}`);
|
||||
isnot(paper.name, null, "Paper name should never be null.");
|
||||
isnot(paper.name, "", "Paper name should never be empty.");
|
||||
|
||||
@ -28,8 +35,20 @@ function run() {
|
||||
|
||||
isnot(paper.height, null, "Paper height should never be null.");
|
||||
ok(paper.height > 0.0, "Paper height should be greater than zero.");
|
||||
});
|
||||
})
|
||||
|
||||
isnot(paper.unwriteableMarginTop, null, "Paper unwriteableMarginTop should never be null.");
|
||||
ok(paper.unwriteableMarginTop >= 0.0, "Paper unwriteableMarginTop should be greater than or equal to zero.");
|
||||
|
||||
isnot(paper.unwriteableMarginBottom, null, "Paper unwriteableMarginBottom should never be null.");
|
||||
ok(paper.unwriteableMarginBottom >= 0.0, "Paper unwriteableMarginBottom should be greater than or equal to zero.");
|
||||
|
||||
isnot(paper.unwriteableMarginLeft, null, "Paper unwriteableMarginLeft should never be null.");
|
||||
ok(paper.unwriteableMarginLeft >= 0.0, "Paper unwriteableMarginLeft should be greater than or equal to zero.");
|
||||
|
||||
isnot(paper.unwriteableMarginRight, null, "Paper unwriteableMarginRight should never be null.");
|
||||
ok(paper.unwriteableMarginRight >= 0.0, "Paper unwriteableMarginRight should be greater than or equal to zero.");
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
@ -47,71 +47,14 @@ static LazyLogModule sDeviceContextSpecXLog("DeviceContextSpecX");
|
||||
|
||||
static nsCUPSShim sCupsShim;
|
||||
|
||||
/**
|
||||
* Retrieves the list of available paper options for a given printer name.
|
||||
*/
|
||||
static nsresult FillPaperListForPrinter(PMPrinter aPrinter,
|
||||
nsTArray<RefPtr<nsIPaper>>& aPaperList) {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
CFArrayRef pmPaperList;
|
||||
aPaperList.ClearAndRetainStorage();
|
||||
OSStatus status = PMPrinterGetPaperList(aPrinter, &pmPaperList);
|
||||
if (status != noErr || !pmPaperList) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
CFIndex paperCount = CFArrayGetCount(pmPaperList);
|
||||
aPaperList.SetCapacity(paperCount);
|
||||
|
||||
for (auto i = 0; i < paperCount; ++i) {
|
||||
PMPaper pmPaper =
|
||||
static_cast<PMPaper>(const_cast<void*>(CFArrayGetValueAtIndex(pmPaperList, i)));
|
||||
|
||||
// The units for width and height are points.
|
||||
double width = 0.0;
|
||||
double height = 0.0;
|
||||
AutoCFRelease<CFStringRef> pmPaperName(nullptr);
|
||||
if (PMPaperGetWidth(pmPaper, &width) != noErr || PMPaperGetHeight(pmPaper, &height) != noErr ||
|
||||
PMPaperCreateLocalizedName(pmPaper, aPrinter, pmPaperName.receive()) != noErr) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsAutoString name;
|
||||
nsCocoaUtils::GetStringForNSString(static_cast<NSString*>(CFStringRef(pmPaperName)), name);
|
||||
|
||||
PMPaperMargins unwriteableMargins;
|
||||
if (PMPaperGetMargins(pmPaper, &unwriteableMargins) != noErr) {
|
||||
// If we can't get unwriteable margins, just default to none.
|
||||
unwriteableMargins.top = 0.0;
|
||||
unwriteableMargins.bottom = 0.0;
|
||||
unwriteableMargins.left = 0.0;
|
||||
unwriteableMargins.right = 0.0;
|
||||
}
|
||||
|
||||
aPaperList.AppendElement(new nsPaper(name, width, height, unwriteableMargins.top,
|
||||
unwriteableMargins.bottom, unwriteableMargins.left,
|
||||
unwriteableMargins.right));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
|
||||
static nsresult CreatePrinter(mozilla::CUPSPrinterList& aCupsPrinterList, PMPrinter aPMPrinter,
|
||||
nsIPrinter** aPrinter) {
|
||||
NS_ENSURE_ARG_POINTER(aPrinter);
|
||||
*aPrinter = nullptr;
|
||||
|
||||
nsTArray<RefPtr<nsIPaper>> paperList;
|
||||
nsresult rv = FillPaperListForPrinter(aPMPrinter, paperList);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NSString* const printerID = static_cast<NSString*>(PMPrinterGetID(aPMPrinter));
|
||||
if (cups_dest_t* const dest = aCupsPrinterList.FindPrinterByName([printerID UTF8String])) {
|
||||
if (RefPtr<nsPrinterCUPS> printer =
|
||||
nsPrinterCUPS::Create(sCupsShim, dest, std::move(paperList))) {
|
||||
if (RefPtr<nsPrinterCUPS> printer = nsPrinterCUPS::Create(sCupsShim, dest)) {
|
||||
printer.forget(aPrinter);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -236,16 +236,12 @@ if CONFIG['MOZ_XUL'] and CONFIG['NS_PRINTING']:
|
||||
]
|
||||
UNIFIED_SOURCES += [
|
||||
'nsDeviceContextSpecProxy.cpp',
|
||||
'nsPaper.cpp',
|
||||
'nsPrinterBase.cpp',
|
||||
'nsPrintSession.cpp',
|
||||
'nsPrintSettingsService.cpp',
|
||||
]
|
||||
|
||||
# The Windows sub-directory has its own implemenation of these.
|
||||
if toolkit != 'windows':
|
||||
UNIFIED_SOURCES += [
|
||||
'nsPaper.cpp',
|
||||
]
|
||||
# These will be unified for all CUPS platforms by Bug 1654678
|
||||
if toolkit == 'cocoa':
|
||||
UNIFIED_SOURCES += [
|
||||
@ -253,6 +249,7 @@ if CONFIG['MOZ_XUL'] and CONFIG['NS_PRINTING']:
|
||||
'nsCUPSShim.cpp',
|
||||
'nsPrinterCUPS.cpp',
|
||||
]
|
||||
|
||||
if toolkit == 'gtk':
|
||||
UNIFIED_SOURCES += [
|
||||
'nsCUPSShim.cpp',
|
||||
|
@ -49,14 +49,19 @@ bool nsCUPSShim::Init() {
|
||||
|
||||
if (!(CUPS_SHIM_LOAD(mCupsAddOption, cupsAddOption) &&
|
||||
CUPS_SHIM_LOAD(mCupsCheckDestSupported, cupsCheckDestSupported) &&
|
||||
CUPS_SHIM_LOAD(mCupsConnectDest, cupsConnectDest) &&
|
||||
CUPS_SHIM_LOAD(mCupsCopyDest, cupsCopyDest) &&
|
||||
CUPS_SHIM_LOAD(mCupsCopyDestInfo, cupsCopyDestInfo) &&
|
||||
CUPS_SHIM_LOAD(mCupsFreeDestInfo, cupsFreeDestInfo) &&
|
||||
CUPS_SHIM_LOAD(mCupsFreeDests, cupsFreeDests) &&
|
||||
CUPS_SHIM_LOAD(mCupsGetDestMediaCount, cupsGetDestMediaCount) &&
|
||||
CUPS_SHIM_LOAD(mCupsGetDestMediaByIndex, cupsGetDestMediaByIndex) &&
|
||||
CUPS_SHIM_LOAD(mCupsGetDest, cupsGetDest) &&
|
||||
CUPS_SHIM_LOAD(mCupsGetDests, cupsGetDests) &&
|
||||
CUPS_SHIM_LOAD(mCupsLocalizeDestMedia, cupsLocalizeDestMedia) &&
|
||||
CUPS_SHIM_LOAD(mCupsPrintFile, cupsPrintFile) &&
|
||||
CUPS_SHIM_LOAD(mCupsTempFd, cupsTempFd))) {
|
||||
CUPS_SHIM_LOAD(mCupsTempFd, cupsTempFd) &&
|
||||
CUPS_SHIM_LOAD(mHttpClose, httpClose))) {
|
||||
#ifndef MOZ_TSAN
|
||||
// With TSan, we cannot unload libcups once we have loaded it because
|
||||
// TSan does not support unloading libraries that are matched from its
|
||||
|
@ -35,14 +35,19 @@ class nsCUPSShim {
|
||||
*/
|
||||
decltype(cupsAddOption)* mCupsAddOption;
|
||||
decltype(cupsCheckDestSupported)* mCupsCheckDestSupported;
|
||||
decltype(cupsConnectDest)* mCupsConnectDest;
|
||||
decltype(cupsCopyDest)* mCupsCopyDest;
|
||||
decltype(cupsCopyDestInfo)* mCupsCopyDestInfo;
|
||||
decltype(cupsFreeDestInfo)* mCupsFreeDestInfo;
|
||||
decltype(cupsFreeDests)* mCupsFreeDests;
|
||||
decltype(cupsGetDestMediaCount)* mCupsGetDestMediaCount;
|
||||
decltype(cupsGetDestMediaByIndex)* mCupsGetDestMediaByIndex;
|
||||
decltype(cupsGetDest)* mCupsGetDest;
|
||||
decltype(cupsGetDests)* mCupsGetDests;
|
||||
decltype(cupsLocalizeDestMedia)* mCupsLocalizeDestMedia;
|
||||
decltype(cupsPrintFile)* mCupsPrintFile;
|
||||
decltype(cupsTempFd)* mCupsTempFd;
|
||||
decltype(httpClose)* mHttpClose;
|
||||
|
||||
private:
|
||||
bool mInited = false;
|
||||
|
@ -15,9 +15,12 @@ interface nsIPrinter : nsISupports
|
||||
readonly attribute AString name;
|
||||
|
||||
/**
|
||||
* The list of available paper sizes.
|
||||
* Returns a Promise that resolves to an array of
|
||||
* nsIPaper instances with the list of available paper
|
||||
* sizes.
|
||||
*/
|
||||
readonly attribute Array<nsIPaper> paperList;
|
||||
[implicit_jscontext]
|
||||
readonly attribute Promise paperList;
|
||||
|
||||
/**
|
||||
* Returns a Promise that resolves to true or false to indicate whether this
|
||||
|
@ -9,48 +9,48 @@ NS_IMPL_ISUPPORTS(nsPaper, nsIPaper);
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaper::GetName(nsAString& aName) {
|
||||
aName = mName;
|
||||
aName = mInfo.mName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaper::GetWidth(double* aWidth) {
|
||||
NS_ENSURE_ARG_POINTER(aWidth);
|
||||
*aWidth = mWidth;
|
||||
*aWidth = mInfo.mWidth;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaper::GetHeight(double* aHeight) {
|
||||
NS_ENSURE_ARG_POINTER(aHeight);
|
||||
*aHeight = mHeight;
|
||||
*aHeight = mInfo.mHeight;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaper::GetUnwriteableMarginTop(double* aUnwriteableMarginTop) {
|
||||
NS_ENSURE_ARG_POINTER(aUnwriteableMarginTop);
|
||||
*aUnwriteableMarginTop = mUnwriteableMarginTop;
|
||||
*aUnwriteableMarginTop = mInfo.mUnwriteableMarginTop;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaper::GetUnwriteableMarginBottom(double* aUnwriteableMarginBottom) {
|
||||
NS_ENSURE_ARG_POINTER(aUnwriteableMarginBottom);
|
||||
*aUnwriteableMarginBottom = mUnwriteableMarginBottom;
|
||||
*aUnwriteableMarginBottom = mInfo.mUnwriteableMarginBottom;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaper::GetUnwriteableMarginLeft(double* aUnwriteableMarginLeft) {
|
||||
NS_ENSURE_ARG_POINTER(aUnwriteableMarginLeft);
|
||||
*aUnwriteableMarginLeft = mUnwriteableMarginLeft;
|
||||
*aUnwriteableMarginLeft = mInfo.mUnwriteableMarginLeft;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaper::GetUnwriteableMarginRight(double* aUnwriteableMarginRight) {
|
||||
NS_ENSURE_ARG_POINTER(aUnwriteableMarginRight);
|
||||
*aUnwriteableMarginRight = mUnwriteableMarginRight;
|
||||
*aUnwriteableMarginRight = mInfo.mUnwriteableMarginRight;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -6,36 +6,53 @@
|
||||
#ifndef nsPaper_h__
|
||||
#define nsPaper_h__
|
||||
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "nsIPaper.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Simple struct that can be used off the main thread to hold all the info from
|
||||
// an nsPaper instance.
|
||||
struct PaperInfo {
|
||||
const nsString mName;
|
||||
const double mWidth;
|
||||
const double mHeight;
|
||||
const double mUnwriteableMarginTop;
|
||||
const double mUnwriteableMarginRight;
|
||||
const double mUnwriteableMarginBottom;
|
||||
const double mUnwriteableMarginLeft;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
class nsPaper final : public nsIPaper {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPAPER
|
||||
nsPaper() = delete;
|
||||
nsPaper(nsAString& aName, double aWidth, double aHeight,
|
||||
double aUnwriteableMarginTop, double aUnwriteableMarginBottom,
|
||||
double aUnwriteableMarginLeft, double aUnwriteableMarginRight)
|
||||
: mName(aName),
|
||||
mWidth(aWidth),
|
||||
mHeight(aHeight),
|
||||
mUnwriteableMarginTop(aUnwriteableMarginTop),
|
||||
mUnwriteableMarginBottom(aUnwriteableMarginBottom),
|
||||
mUnwriteableMarginLeft(aUnwriteableMarginLeft),
|
||||
mUnwriteableMarginRight(aUnwriteableMarginRight) {}
|
||||
|
||||
explicit nsPaper(const mozilla::PaperInfo& aInfo) : mInfo(aInfo) {}
|
||||
|
||||
private:
|
||||
~nsPaper() = default;
|
||||
|
||||
nsString mName;
|
||||
double mWidth;
|
||||
double mHeight;
|
||||
double mUnwriteableMarginTop;
|
||||
double mUnwriteableMarginBottom;
|
||||
double mUnwriteableMarginLeft;
|
||||
double mUnwriteableMarginRight;
|
||||
const mozilla::PaperInfo mInfo;
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Turns this into a JSValue by wrapping it in an nsPaper struct.
|
||||
//
|
||||
// FIXME: If using WebIDL dictionaries we'd get this for ~free...
|
||||
MOZ_MUST_USE inline bool ToJSValue(JSContext* aCx, const PaperInfo& aInfo,
|
||||
JS::MutableHandleValue aValue) {
|
||||
RefPtr<nsPaper> paper = new nsPaper(aInfo);
|
||||
return dom::ToJSValue(aCx, paper, aValue);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* nsPaper_h__ */
|
||||
|
@ -19,9 +19,3 @@ nsPrinter::GetName(nsAString& aName) {
|
||||
aName = mName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrinter::GetPaperList(nsTArray<RefPtr<nsIPaper>>& aPaperList) {
|
||||
aPaperList.Assign(mPaperList);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -7,14 +7,15 @@
|
||||
#define nsPrinter_h__
|
||||
|
||||
#include "nsPrinterBase.h"
|
||||
#include "nsPaper.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsPrinter final : public nsPrinterBase {
|
||||
public:
|
||||
NS_IMETHOD GetName(nsAString& aName) override;
|
||||
NS_IMETHOD GetPaperList(nsTArray<RefPtr<nsIPaper>>& aPaperList) override;
|
||||
bool SupportsDuplex() const final { return false; }
|
||||
bool SupportsColor() const final { return false; }
|
||||
nsTArray<mozilla::PaperInfo> PaperList() const final { return {}; }
|
||||
|
||||
nsPrinter() = delete;
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "nsPrinterBase.h"
|
||||
#include "nsPrinter.h"
|
||||
#include "nsPaper.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
|
||||
using namespace mozilla;
|
||||
@ -84,7 +85,14 @@ NS_IMETHODIMP nsPrinterBase::GetSupportsColor(JSContext* aCx,
|
||||
&nsPrinterBase::SupportsColor);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(nsPrinterBase, mAsyncAttributePromises, mPaperList)
|
||||
NS_IMETHODIMP nsPrinterBase::GetPaperList(JSContext* aCx,
|
||||
Promise** aResultPromise) {
|
||||
return AsyncPromiseAttributeGetter<nsTArray<PaperInfo>>(
|
||||
aCx, aResultPromise, AsyncAttribute::PaperList,
|
||||
&nsPrinterBase::PaperList);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(nsPrinterBase, mAsyncAttributePromises)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPrinterBase)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIPrinter)
|
||||
|
@ -12,16 +12,23 @@
|
||||
#include "mozilla/EnumeratedArray.h"
|
||||
#include "mozilla/Result.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
namespace mozilla {
|
||||
|
||||
struct PaperInfo;
|
||||
|
||||
namespace dom {
|
||||
class Promise;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
class nsPrinterBase : public nsIPrinter {
|
||||
public:
|
||||
using Promise = mozilla::dom::Promise;
|
||||
|
||||
NS_IMETHOD GetSupportsDuplex(JSContext*, Promise**) final;
|
||||
NS_IMETHOD GetSupportsColor(JSContext*, Promise**) final;
|
||||
NS_IMETHOD GetPaperList(JSContext*, Promise**) final;
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(nsPrinterBase)
|
||||
@ -34,6 +41,7 @@ class nsPrinterBase : public nsIPrinter {
|
||||
enum class AsyncAttribute {
|
||||
SupportsDuplex = 0,
|
||||
SupportsColor,
|
||||
PaperList,
|
||||
// Just a guard.
|
||||
Last,
|
||||
};
|
||||
@ -55,9 +63,7 @@ class nsPrinterBase : public nsIPrinter {
|
||||
// which thread they run on.
|
||||
virtual bool SupportsDuplex() const = 0;
|
||||
virtual bool SupportsColor() const = 0;
|
||||
|
||||
// FIXME: Temporary, should probably be moved to the async attribute stuff.
|
||||
nsTArray<RefPtr<nsIPaper>> mPaperList;
|
||||
virtual nsTArray<mozilla::PaperInfo> PaperList() const = 0;
|
||||
|
||||
private:
|
||||
mozilla::EnumeratedArray<AsyncAttribute, AsyncAttribute::Last,
|
||||
|
@ -4,32 +4,33 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsPrinterCUPS.h"
|
||||
#include "nsPaper.h"
|
||||
#include "nsPrinterBase.h"
|
||||
|
||||
nsPrinterCUPS::nsPrinterCUPS(const nsCUPSShim& aShim, cups_dest_t* aPrinter,
|
||||
nsTArray<RefPtr<nsIPaper>>&& aPaperList)
|
||||
nsPrinterCUPS::nsPrinterCUPS(const nsCUPSShim& aShim, cups_dest_t* aPrinter)
|
||||
: mShim(aShim) {
|
||||
MOZ_ASSERT(aPrinter);
|
||||
MOZ_ASSERT(mShim.IsInitialized());
|
||||
DebugOnly<const int> numCopied = aShim.mCupsCopyDest(aPrinter, 0, &mPrinter);
|
||||
MOZ_ASSERT(numCopied == 1);
|
||||
mPrinterInfo = aShim.mCupsCopyDestInfo(CUPS_HTTP_DEFAULT, mPrinter);
|
||||
mPaperList = std::move(aPaperList);
|
||||
}
|
||||
|
||||
nsPrinterCUPS::~nsPrinterCUPS() {
|
||||
if (mPrinterInfo) {
|
||||
mShim.mCupsFreeDestInfo(mPrinterInfo);
|
||||
mPrinterInfo = nullptr;
|
||||
}
|
||||
if (mPrinter) {
|
||||
mShim.mCupsFreeDests(1, mPrinter);
|
||||
mPrinter = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<nsPrinterCUPS> nsPrinterCUPS::Create(
|
||||
const nsCUPSShim& aShim, cups_dest_t* aPrinter,
|
||||
nsTArray<RefPtr<nsIPaper>>&& aPaperList) {
|
||||
return do_AddRef(new nsPrinterCUPS(aShim, aPrinter, std::move(aPaperList)));
|
||||
already_AddRefed<nsPrinterCUPS> nsPrinterCUPS::Create(const nsCUPSShim& aShim,
|
||||
cups_dest_t* aPrinter) {
|
||||
return do_AddRef(new nsPrinterCUPS(aShim, aPrinter));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -38,12 +39,6 @@ nsPrinterCUPS::GetName(nsAString& aName) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrinterCUPS::GetPaperList(nsTArray<RefPtr<nsIPaper>>& aPaperList) {
|
||||
aPaperList.Assign(mPaperList);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool nsPrinterCUPS::SupportsDuplex() const {
|
||||
return Supports(CUPS_SIDES, CUPS_SIDES_TWO_SIDED_PORTRAIT);
|
||||
}
|
||||
@ -55,3 +50,63 @@ bool nsPrinterCUPS::Supports(const char* option, const char* value) const {
|
||||
return mShim.mCupsCheckDestSupported(CUPS_HTTP_DEFAULT, mPrinter,
|
||||
mPrinterInfo, option, value);
|
||||
}
|
||||
|
||||
nsTArray<mozilla::PaperInfo> nsPrinterCUPS::PaperList() const {
|
||||
if (!mPrinterInfo) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const int paperCount = mShim.mCupsGetDestMediaCount(
|
||||
CUPS_HTTP_DEFAULT, mPrinter, mPrinterInfo, CUPS_MEDIA_FLAGS_DEFAULT);
|
||||
|
||||
// blocking call
|
||||
http_t* connection = mShim.mCupsConnectDest(mPrinter, CUPS_DEST_FLAGS_NONE,
|
||||
/* timeout(ms) */ 5000,
|
||||
/* cancel */ nullptr,
|
||||
/* resource */ nullptr,
|
||||
/* resourcesize */ 0,
|
||||
/* callback */ nullptr,
|
||||
/* user_data */ nullptr);
|
||||
|
||||
if (!connection) {
|
||||
return {};
|
||||
}
|
||||
|
||||
nsTArray<mozilla::PaperInfo> paperList;
|
||||
for (int i = 0; i < paperCount; ++i) {
|
||||
cups_size_t info;
|
||||
int getInfoSucceded = mShim.mCupsGetDestMediaByIndex(
|
||||
CUPS_HTTP_DEFAULT, mPrinter, mPrinterInfo, i, CUPS_MEDIA_FLAGS_DEFAULT,
|
||||
&info);
|
||||
|
||||
if (!getInfoSucceded) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// localizedName is owned by mPrinterInfo.
|
||||
// https://www.cups.org/doc/cupspm.html#cupsLocalizeDestMedia
|
||||
const char* localizedName = mShim.mCupsLocalizeDestMedia(
|
||||
connection, mPrinter, mPrinterInfo, CUPS_MEDIA_FLAGS_DEFAULT, &info);
|
||||
|
||||
if (!localizedName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// XXX Do we actually have the guarantee that this is utf-8?
|
||||
NS_ConvertUTF8toUTF16 name(localizedName);
|
||||
const double kPointsPerHundredthMillimeter = 0.0283465;
|
||||
|
||||
paperList.AppendElement(mozilla::PaperInfo{
|
||||
std::move(name),
|
||||
info.width * kPointsPerHundredthMillimeter,
|
||||
info.length * kPointsPerHundredthMillimeter,
|
||||
info.top * kPointsPerHundredthMillimeter,
|
||||
info.right * kPointsPerHundredthMillimeter,
|
||||
info.bottom * kPointsPerHundredthMillimeter,
|
||||
info.left * kPointsPerHundredthMillimeter,
|
||||
});
|
||||
}
|
||||
|
||||
mShim.mHttpClose(connection);
|
||||
return paperList;
|
||||
}
|
||||
|
@ -16,24 +16,20 @@
|
||||
class nsPrinterCUPS final : public nsPrinterBase {
|
||||
public:
|
||||
NS_IMETHOD GetName(nsAString& aName) override;
|
||||
NS_IMETHOD GetPaperList(nsTArray<RefPtr<nsIPaper>>& aPaperList) override;
|
||||
bool SupportsDuplex() const final;
|
||||
bool SupportsColor() const final;
|
||||
nsTArray<mozilla::PaperInfo> PaperList() const final;
|
||||
|
||||
nsPrinterCUPS() = delete;
|
||||
|
||||
/**
|
||||
* @p aPrinter must not be null.
|
||||
* @todo: Once CUPS-enumeration of paper sizes lands, we can remove the
|
||||
* |aPaperList|.
|
||||
*/
|
||||
static already_AddRefed<nsPrinterCUPS> Create(
|
||||
const nsCUPSShim& aShim, cups_dest_t* aPrinter,
|
||||
nsTArray<RefPtr<nsIPaper>>&& aPaperList);
|
||||
static already_AddRefed<nsPrinterCUPS> Create(const nsCUPSShim& aShim,
|
||||
cups_dest_t* aPrinter);
|
||||
|
||||
private:
|
||||
nsPrinterCUPS(const nsCUPSShim& aShim, cups_dest_t* aPrinter,
|
||||
nsTArray<RefPtr<nsIPaper>>&& aPaperList);
|
||||
nsPrinterCUPS(const nsCUPSShim& aShim, cups_dest_t* aPrinter);
|
||||
|
||||
~nsPrinterCUPS();
|
||||
|
||||
|
@ -123,7 +123,6 @@ SOURCES += [
|
||||
if CONFIG['NS_PRINTING']:
|
||||
UNIFIED_SOURCES += [
|
||||
'nsDeviceContextSpecWin.cpp',
|
||||
'nsPaperWin.cpp',
|
||||
'nsPrintDialogUtil.cpp',
|
||||
'nsPrintDialogWin.cpp',
|
||||
'nsPrinterWin.cpp',
|
||||
|
@ -1,100 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; 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 "nsPaperWin.h"
|
||||
|
||||
#include "nsWindowsHelpers.h"
|
||||
#include "WinUtils.h"
|
||||
|
||||
using namespace mozilla::widget;
|
||||
|
||||
static const wchar_t kDriverName[] = L"WINSPOOL";
|
||||
|
||||
nsPaperWin::nsPaperWin(WORD aId, const nsAString& aName,
|
||||
const nsAString& aPrinterName, double aWidth,
|
||||
double aHeight)
|
||||
: mId(aId),
|
||||
mName(aName),
|
||||
mPrinterName(aPrinterName),
|
||||
mSize(aWidth, aHeight) {}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsPaperWin, nsIPaper);
|
||||
|
||||
void nsPaperWin::EnsureUnwriteableMargin() {
|
||||
if (mUnwriteableMarginRetrieved) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We need a DEVMODE to set the paper size on the context.
|
||||
DEVMODEW devmode = {};
|
||||
devmode.dmSize = sizeof(DEVMODEW);
|
||||
devmode.dmFields = DM_PAPERSIZE;
|
||||
devmode.dmPaperSize = mId;
|
||||
|
||||
// Create an information context, so that we can get margin information.
|
||||
// Note: this blocking call interacts with the driver and can be slow.
|
||||
nsAutoHDC printerDc(
|
||||
::CreateICW(kDriverName, mPrinterName.get(), nullptr, &devmode));
|
||||
|
||||
MarginDouble unWrtMarginInInches =
|
||||
WinUtils::GetUnwriteableMarginsForDeviceInInches(printerDc);
|
||||
mUnwriteableMargin.SizeTo(unWrtMarginInInches.top * POINTS_PER_INCH_FLOAT,
|
||||
unWrtMarginInInches.right * POINTS_PER_INCH_FLOAT,
|
||||
unWrtMarginInInches.bottom * POINTS_PER_INCH_FLOAT,
|
||||
unWrtMarginInInches.left * POINTS_PER_INCH_FLOAT);
|
||||
mUnwriteableMarginRetrieved = true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaperWin::GetName(nsAString& aName) {
|
||||
aName = mName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaperWin::GetWidth(double* aWidth) {
|
||||
MOZ_ASSERT(aWidth);
|
||||
*aWidth = mSize.Width();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaperWin::GetHeight(double* aHeight) {
|
||||
MOZ_ASSERT(aHeight);
|
||||
*aHeight = mSize.Height();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaperWin::GetUnwriteableMarginTop(double* aUnwriteableMarginTop) {
|
||||
MOZ_ASSERT(aUnwriteableMarginTop);
|
||||
EnsureUnwriteableMargin();
|
||||
*aUnwriteableMarginTop = mUnwriteableMargin.top;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaperWin::GetUnwriteableMarginBottom(double* aUnwriteableMarginBottom) {
|
||||
MOZ_ASSERT(aUnwriteableMarginBottom);
|
||||
EnsureUnwriteableMargin();
|
||||
*aUnwriteableMarginBottom = mUnwriteableMargin.bottom;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaperWin::GetUnwriteableMarginLeft(double* aUnwriteableMarginLeft) {
|
||||
MOZ_ASSERT(aUnwriteableMarginLeft);
|
||||
EnsureUnwriteableMargin();
|
||||
*aUnwriteableMarginLeft = mUnwriteableMargin.left;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaperWin::GetUnwriteableMarginRight(double* aUnwriteableMarginRight) {
|
||||
MOZ_ASSERT(aUnwriteableMarginRight);
|
||||
EnsureUnwriteableMargin();
|
||||
*aUnwriteableMarginRight = mUnwriteableMargin.right;
|
||||
return NS_OK;
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; 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/. */
|
||||
|
||||
#ifndef nsPaperWin_h_
|
||||
#define nsPaperWin_h_
|
||||
|
||||
#include "nsIPaper.h"
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsPaperWin final : public nsIPaper {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPAPER
|
||||
nsPaperWin() = delete;
|
||||
nsPaperWin(WORD aId, const nsAString& aName, const nsAString& aPrinterName,
|
||||
double aWidth, double aHeight);
|
||||
|
||||
private:
|
||||
~nsPaperWin() = default;
|
||||
|
||||
void EnsureUnwriteableMargin();
|
||||
|
||||
using SizeDouble = mozilla::gfx::SizeDouble;
|
||||
using MarginDouble = mozilla::gfx::MarginDouble;
|
||||
|
||||
WORD mId;
|
||||
nsString mName;
|
||||
nsString mPrinterName;
|
||||
SizeDouble mSize;
|
||||
MarginDouble mUnwriteableMargin;
|
||||
bool mUnwriteableMarginRetrieved = false;
|
||||
};
|
||||
|
||||
#endif // nsPaperWin_h_
|
@ -9,7 +9,7 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include "mozilla/Array.h"
|
||||
#include "nsPaperWin.h"
|
||||
#include "nsPaper.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
@ -62,11 +62,23 @@ static nsTArray<T> GetDeviceCapabilityArray(const LPWSTR aPrinterName,
|
||||
return caps;
|
||||
}
|
||||
|
||||
nsresult nsPrinterWin::EnsurePaperList() {
|
||||
if (!mPaperList.IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsPrinterWin::GetName(nsAString& aName) {
|
||||
aName.Assign(mName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool nsPrinterWin::SupportsDuplex() const {
|
||||
return ::DeviceCapabilitiesW(mName.get(), nullptr, DC_DUPLEX, nullptr,
|
||||
nullptr) == 1;
|
||||
}
|
||||
|
||||
bool nsPrinterWin::SupportsColor() const {
|
||||
return ::DeviceCapabilitiesW(mName.get(), nullptr, DC_COLORDEVICE, nullptr,
|
||||
nullptr) == 1;
|
||||
}
|
||||
|
||||
nsTArray<mozilla::PaperInfo> nsPrinterWin::PaperList() const {
|
||||
// Paper names are returned in 64 long character buffers.
|
||||
auto paperNames =
|
||||
GetDeviceCapabilityArray<Array<wchar_t, 64>>(mName.get(), DC_PAPERNAMES);
|
||||
@ -81,10 +93,12 @@ nsresult nsPrinterWin::EnsurePaperList() {
|
||||
// Check that we have papers and that the array lengths match.
|
||||
if (!paperNames.Length() || paperNames.Length() != paperIds.Length() ||
|
||||
paperNames.Length() != paperSizes.Length()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
return {};
|
||||
}
|
||||
|
||||
mPaperList.SetCapacity(paperNames.Length());
|
||||
static const wchar_t kDriverName[] = L"WINSPOOL";
|
||||
nsTArray<mozilla::PaperInfo> paperList;
|
||||
paperList.SetCapacity(paperNames.Length());
|
||||
for (size_t i = 0; i < paperNames.Length(); ++i) {
|
||||
// Paper names are null terminated unless they are 64 characters long.
|
||||
auto firstNull =
|
||||
@ -98,37 +112,34 @@ nsresult nsPrinterWin::EnsurePaperList() {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoString paperName(paperNames[i].cbegin(), nameLength);
|
||||
mPaperList.AppendElement(
|
||||
new nsPaperWin(paperIds[i], paperName, mName, width, height));
|
||||
WORD id = paperIds[i];
|
||||
|
||||
// Now get the margin info.
|
||||
// We need a DEVMODE to set the paper size on the context.
|
||||
DEVMODEW devmode = {};
|
||||
devmode.dmSize = sizeof(DEVMODEW);
|
||||
devmode.dmFields = DM_PAPERSIZE;
|
||||
devmode.dmPaperSize = id;
|
||||
|
||||
// Create an information context, so that we can get margin information.
|
||||
// Note: this blocking call interacts with the driver and can be slow.
|
||||
nsAutoHDC printerDc(
|
||||
::CreateICW(kDriverName, mName.get(), nullptr, &devmode));
|
||||
|
||||
auto marginInInches =
|
||||
WinUtils::GetUnwriteableMarginsForDeviceInInches(printerDc);
|
||||
|
||||
nsDependentSubstring name(paperNames[i].cbegin(), nameLength);
|
||||
paperList.AppendElement(mozilla::PaperInfo{
|
||||
nsString(name),
|
||||
width,
|
||||
height,
|
||||
marginInInches.top * POINTS_PER_INCH_FLOAT,
|
||||
marginInInches.right * POINTS_PER_INCH_FLOAT,
|
||||
marginInInches.bottom * POINTS_PER_INCH_FLOAT,
|
||||
marginInInches.left * POINTS_PER_INCH_FLOAT,
|
||||
});
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrinterWin::GetName(nsAString& aName) {
|
||||
aName.Assign(mName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrinterWin::GetPaperList(nsTArray<RefPtr<nsIPaper>>& aPaperList) {
|
||||
nsresult rv = EnsurePaperList();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
aPaperList.Assign(mPaperList);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool nsPrinterWin::SupportsDuplex() const {
|
||||
return ::DeviceCapabilitiesW(mName.get(), nullptr, DC_DUPLEX, nullptr,
|
||||
nullptr) == 1;
|
||||
}
|
||||
|
||||
bool nsPrinterWin::SupportsColor() const {
|
||||
return ::DeviceCapabilitiesW(mName.get(), nullptr, DC_COLORDEVICE, nullptr,
|
||||
nullptr) == 1;
|
||||
return paperList;
|
||||
}
|
||||
|
@ -11,10 +11,10 @@
|
||||
class nsPrinterWin final : public nsPrinterBase {
|
||||
public:
|
||||
NS_IMETHOD GetName(nsAString& aName) override;
|
||||
NS_IMETHOD GetPaperList(nsTArray<RefPtr<nsIPaper>>& aPaperList) override;
|
||||
|
||||
bool SupportsDuplex() const final;
|
||||
bool SupportsColor() const final;
|
||||
nsTArray<mozilla::PaperInfo> PaperList() const final;
|
||||
|
||||
nsPrinterWin() = delete;
|
||||
static already_AddRefed<nsPrinterWin> Create(const nsAString& aName);
|
||||
|
Loading…
Reference in New Issue
Block a user