Bug 1655558 - Retrieve the paper margins lazily on Windows. r=jwatt,bobowen
This is no worse than what we were doing. In the future, instead of just querying the margin we may want to query extra information that requires a DC in windows too or what not, for example. Differential Revision: https://phabricator.services.mozilla.com/D85919
This commit is contained in:
@@ -26,7 +26,8 @@ async function run() {
|
||||
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}`);
|
||||
info(`${paper.name}: ${paper.width}x${paper.height}`);
|
||||
|
||||
isnot(paper.name, null, "Paper name should never be null.");
|
||||
isnot(paper.name, "", "Paper name should never be empty.");
|
||||
|
||||
@@ -36,20 +37,24 @@ async 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.");
|
||||
let margin = await paper.unwriteableMargin;
|
||||
margin.QueryInterface(Ci.nsIPaperMargin);
|
||||
|
||||
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.");
|
||||
info(`with margin: ${margin.top} ${margin.right} ${margin.bottom} ${margin.left}`);
|
||||
is(typeof(margin.top), 'number', "Paper unwriteable margin top should be a number.");
|
||||
is(typeof(margin.right), 'number', "Paper unwriteable margin right should be a number.");
|
||||
is(typeof(margin.bottom), 'number', "Paper unwriteable margin bottom should be a number.");
|
||||
is(typeof(margin.left), 'number', "Paper unwriteable margin left should be a number.");
|
||||
|
||||
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.");
|
||||
ok(margin.top >= 0.0, "Paper unwriteable margin top should be greater than or equal to zero.");
|
||||
ok(margin.right >= 0.0, "Paper unwriteable margin right should be greater than or equal to zero.");
|
||||
ok(margin.bottom >= 0.0, "Paper unwriteable bottom right should be greater than or equal to zero.");
|
||||
ok(margin.left >= 0.0, "Paper unwriteable margin left should be greater than or equal to zero.");
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
ok(false, `Shouldn't throw: ${e}`);
|
||||
Cu.reportError(e);
|
||||
}
|
||||
SimpleTest.finish();
|
||||
|
||||
@@ -110,6 +110,7 @@ XPIDL_SOURCES += [
|
||||
'nsIGfxInfo.idl',
|
||||
'nsIGfxInfoDebug.idl',
|
||||
'nsIPaper.idl',
|
||||
'nsIPaperMargin.idl',
|
||||
'nsIPrinter.idl',
|
||||
'nsIPrinterList.idl',
|
||||
'nsIPrintSession.idl',
|
||||
@@ -237,6 +238,7 @@ if CONFIG['MOZ_XUL'] and CONFIG['NS_PRINTING']:
|
||||
UNIFIED_SOURCES += [
|
||||
'nsDeviceContextSpecProxy.cpp',
|
||||
'nsPaper.cpp',
|
||||
'nsPaperMargin.cpp',
|
||||
'nsPrinterBase.cpp',
|
||||
'nsPrintSession.cpp',
|
||||
'nsPrintSettingsService.cpp',
|
||||
|
||||
@@ -23,23 +23,5 @@ interface nsIPaper : nsISupports
|
||||
*/
|
||||
readonly attribute double height;
|
||||
|
||||
/**
|
||||
* The unwritable margin at the top of the paper in points.
|
||||
*/
|
||||
readonly attribute double unwriteableMarginTop;
|
||||
|
||||
/**
|
||||
* The unwritable margin at the bottom of the paper in points.
|
||||
*/
|
||||
readonly attribute double unwriteableMarginBottom;
|
||||
|
||||
/**
|
||||
* The unwritable margin at the left of the paper in points.
|
||||
*/
|
||||
readonly attribute double unwriteableMarginLeft;
|
||||
|
||||
/**
|
||||
* The unwritable margin at the right of the paper in points.
|
||||
*/
|
||||
readonly attribute double unwriteableMarginRight;
|
||||
[implicit_jscontext] readonly attribute Promise unwriteableMargin;
|
||||
};
|
||||
|
||||
16
widget/nsIPaperMargin.idl
Normal file
16
widget/nsIPaperMargin.idl
Normal file
@@ -0,0 +1,16 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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"
|
||||
|
||||
// A margin for a sheet of paper.
|
||||
[builtinclass, scriptable, uuid(0858d1a7-b646-4b15-a1e8-7eb5ab572d0a)]
|
||||
interface nsIPaperMargin : nsISupports
|
||||
{
|
||||
[infallible] readonly attribute double top;
|
||||
[infallible] readonly attribute double right;
|
||||
[infallible] readonly attribute double bottom;
|
||||
[infallible] readonly attribute double left;
|
||||
};
|
||||
@@ -4,8 +4,27 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsPaper.h"
|
||||
#include "nsPaperMargin.h"
|
||||
#include "nsPrinterBase.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsPaper, nsIPaper);
|
||||
using mozilla::ErrorResult;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(nsPaper, mMarginPromise, mPrinter)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPaper)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIPaper)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPaper)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPaper)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPaper)
|
||||
|
||||
nsPaper::nsPaper(nsPrinterBase& aPrinter, const mozilla::PaperInfo& aInfo)
|
||||
: mPrinter(&aPrinter), mInfo(aInfo) {}
|
||||
|
||||
nsPaper::~nsPaper() = default;
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaper::GetName(nsAString& aName) {
|
||||
@@ -16,41 +35,38 @@ nsPaper::GetName(nsAString& aName) {
|
||||
NS_IMETHODIMP
|
||||
nsPaper::GetWidth(double* aWidth) {
|
||||
NS_ENSURE_ARG_POINTER(aWidth);
|
||||
*aWidth = mInfo.mWidth;
|
||||
*aWidth = mInfo.mSize.Width();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaper::GetHeight(double* aHeight) {
|
||||
NS_ENSURE_ARG_POINTER(aHeight);
|
||||
*aHeight = mInfo.mHeight;
|
||||
*aHeight = mInfo.mSize.Height();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaper::GetUnwriteableMarginTop(double* aUnwriteableMarginTop) {
|
||||
NS_ENSURE_ARG_POINTER(aUnwriteableMarginTop);
|
||||
*aUnwriteableMarginTop = mInfo.mUnwriteableMarginTop;
|
||||
return NS_OK;
|
||||
}
|
||||
nsPaper::GetUnwriteableMargin(JSContext* aCx, Promise** aPromise) {
|
||||
if (RefPtr<Promise> existing = mMarginPromise) {
|
||||
existing.forget(aPromise);
|
||||
return NS_OK;
|
||||
}
|
||||
ErrorResult rv;
|
||||
RefPtr<Promise> promise = Promise::Create(xpc::CurrentNativeGlobal(aCx), rv);
|
||||
if (MOZ_UNLIKELY(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaper::GetUnwriteableMarginBottom(double* aUnwriteableMarginBottom) {
|
||||
NS_ENSURE_ARG_POINTER(aUnwriteableMarginBottom);
|
||||
*aUnwriteableMarginBottom = mInfo.mUnwriteableMarginBottom;
|
||||
return NS_OK;
|
||||
}
|
||||
mMarginPromise = promise;
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaper::GetUnwriteableMarginLeft(double* aUnwriteableMarginLeft) {
|
||||
NS_ENSURE_ARG_POINTER(aUnwriteableMarginLeft);
|
||||
*aUnwriteableMarginLeft = mInfo.mUnwriteableMarginLeft;
|
||||
return NS_OK;
|
||||
}
|
||||
if (mInfo.mUnwriteableMargin) {
|
||||
auto margin = mozilla::MakeRefPtr<nsPaperMargin>(*mInfo.mUnwriteableMargin);
|
||||
mMarginPromise->MaybeResolve(margin);
|
||||
} else {
|
||||
mPrinter->QueryMarginsForPaper(*mMarginPromise, mInfo.mPaperId);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaper::GetUnwriteableMarginRight(double* aUnwriteableMarginRight) {
|
||||
NS_ENSURE_ARG_POINTER(aUnwriteableMarginRight);
|
||||
*aUnwriteableMarginRight = mInfo.mUnwriteableMarginRight;
|
||||
promise.forget(aPromise);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -7,52 +7,55 @@
|
||||
#define nsPaper_h__
|
||||
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "nsIPaper.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "nsString.h"
|
||||
|
||||
struct JSContext;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Simple struct that can be used off the main thread to hold all the info from
|
||||
// an nsPaper instance.
|
||||
struct PaperInfo {
|
||||
using MarginDouble = mozilla::gfx::MarginDouble;
|
||||
using SizeDouble = mozilla::gfx::SizeDouble;
|
||||
|
||||
const nsString mName;
|
||||
const double mWidth;
|
||||
const double mHeight;
|
||||
const double mUnwriteableMarginTop;
|
||||
const double mUnwriteableMarginRight;
|
||||
const double mUnwriteableMarginBottom;
|
||||
const double mUnwriteableMarginLeft;
|
||||
|
||||
SizeDouble mSize;
|
||||
|
||||
// The margins may not be known by some back-ends.
|
||||
const Maybe<MarginDouble> mUnwriteableMargin;
|
||||
|
||||
// The paper id from the device, this is only useful on Windows, right now.
|
||||
uint64_t mPaperId{0};
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
class nsPaper final : public nsIPaper {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPAPER
|
||||
nsPaper() = delete;
|
||||
class nsPrinterBase;
|
||||
|
||||
explicit nsPaper(const mozilla::PaperInfo& aInfo) : mInfo(aInfo) {}
|
||||
class nsPaper final : public nsIPaper {
|
||||
using Promise = mozilla::dom::Promise;
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(nsPaper)
|
||||
NS_DECL_NSIPAPER
|
||||
|
||||
nsPaper() = delete;
|
||||
nsPaper(nsPrinterBase&, const mozilla::PaperInfo&);
|
||||
|
||||
private:
|
||||
~nsPaper() = default;
|
||||
~nsPaper();
|
||||
RefPtr<nsPrinterBase> mPrinter;
|
||||
RefPtr<Promise> mMarginPromise;
|
||||
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__ */
|
||||
|
||||
32
widget/nsPaperMargin.cpp
Normal file
32
widget/nsPaperMargin.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/* -*- 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 "nsPaperMargin.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsPaperMargin, nsIPaperMargin)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaperMargin::GetTop(double* aTop) {
|
||||
*aTop = mMargin.top;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaperMargin::GetRight(double* aRight) {
|
||||
*aRight = mMargin.right;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaperMargin::GetBottom(double* aBottom) {
|
||||
*aBottom = mMargin.bottom;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPaperMargin::GetLeft(double* aLeft) {
|
||||
*aLeft = mMargin.left;
|
||||
return NS_OK;
|
||||
}
|
||||
29
widget/nsPaperMargin.h
Normal file
29
widget/nsPaperMargin.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* -*- 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 nsPaperMargin_h_
|
||||
#define nsPaperMargin_h_
|
||||
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsIPaperMargin.h"
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
|
||||
class nsPaperMargin final : public nsIPaperMargin {
|
||||
using MarginDouble = mozilla::gfx::MarginDouble;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPAPERMARGIN
|
||||
|
||||
nsPaperMargin() = delete;
|
||||
|
||||
explicit nsPaperMargin(const MarginDouble& aMargin) : mMargin(aMargin) {}
|
||||
|
||||
private:
|
||||
~nsPaperMargin() = default;
|
||||
const MarginDouble mMargin;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -16,6 +16,10 @@ class nsPrinter final : public nsPrinterBase {
|
||||
bool SupportsDuplex() const final { return false; }
|
||||
bool SupportsColor() const final { return false; }
|
||||
nsTArray<mozilla::PaperInfo> PaperList() const final { return {}; }
|
||||
MarginDouble GetMarginsForPaper(uint64_t) const final {
|
||||
MOZ_ASSERT_UNREACHABLE("We have no paper so this shouldn't be reached");
|
||||
return {};
|
||||
}
|
||||
|
||||
nsPrinter() = delete;
|
||||
|
||||
|
||||
@@ -4,11 +4,15 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsPrinterBase.h"
|
||||
#include "nsPaperMargin.h"
|
||||
#include <utility>
|
||||
#include "nsPrinter.h"
|
||||
#include "nsPaper.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using mozilla::dom::Promise;
|
||||
using mozilla::gfx::MarginDouble;
|
||||
|
||||
template <typename Index, Index Size, typename Value>
|
||||
inline void ImplCycleCollectionTraverse(
|
||||
@@ -30,9 +34,65 @@ inline void ImplCycleCollectionUnlink(
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ResolveOrReject(Promise& aPromise, nsPrinterBase&, T& aResult) {
|
||||
aPromise.MaybeResolve(std::forward<T>(aResult));
|
||||
}
|
||||
|
||||
template <>
|
||||
void ResolveOrReject(Promise& aPromise, nsPrinterBase&,
|
||||
const MarginDouble& aResult) {
|
||||
auto margin = MakeRefPtr<nsPaperMargin>(aResult);
|
||||
aPromise.MaybeResolve(margin);
|
||||
}
|
||||
|
||||
template <>
|
||||
void ResolveOrReject(Promise& aPromise, nsPrinterBase& aPrinter,
|
||||
const nsTArray<PaperInfo>& aResult) {
|
||||
nsTArray<RefPtr<nsPaper>> result;
|
||||
result.SetCapacity(aResult.Length());
|
||||
for (const PaperInfo& info : aResult) {
|
||||
result.AppendElement(MakeRefPtr<nsPaper>(aPrinter, info));
|
||||
}
|
||||
aPromise.MaybeResolve(result);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
void nsPrinterBase::SpawnBackgroundTask(
|
||||
Promise& aPromise, BackgroundTask<T, Args...> aBackgroundTask,
|
||||
Args... aArgs) {
|
||||
auto promiseHolder = MakeRefPtr<nsMainThreadPtrHolder<Promise>>(
|
||||
"nsPrinterBase::SpawnBackgroundTaskPromise", &aPromise);
|
||||
// We actually want to allow to access the printer data from the callback, so
|
||||
// disable strict checking. They should of course only access immutable
|
||||
// members.
|
||||
auto holder = MakeRefPtr<nsMainThreadPtrHolder<nsPrinterBase>>(
|
||||
"nsPrinterBase::SpawnBackgroundTaskPrinter", this, /* strict = */ false);
|
||||
// See
|
||||
// https://stackoverflow.com/questions/47496358/c-lambdas-how-to-capture-variadic-parameter-pack-from-the-upper-scope
|
||||
// about the tuple shenanigans. It could be improved with C++20
|
||||
NS_DispatchBackgroundTask(NS_NewRunnableFunction(
|
||||
"nsPrinterBase::SpawnBackgroundTask",
|
||||
[holder = std::move(holder), promiseHolder = std::move(promiseHolder),
|
||||
aBackgroundTask, aArgs = std::make_tuple(std::forward<Args>(aArgs)...)] {
|
||||
T result = std::apply(
|
||||
[&](auto&&... args) {
|
||||
return (holder->get()->*aBackgroundTask)(args...);
|
||||
},
|
||||
std::move(aArgs));
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
"nsPrinterBase::SpawnBackgroundTaskResolution",
|
||||
[holder = std::move(holder),
|
||||
promiseHolder = std::move(promiseHolder),
|
||||
result = std::move(result)] {
|
||||
ResolveOrReject(*promiseHolder->get(), *holder->get(), result);
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
nsresult nsPrinterBase::AsyncPromiseAttributeGetter(
|
||||
JSContext* aCx, Promise** aResultPromise, AsyncAttribute aAttribute,
|
||||
AsyncAttributeBackgroundTask<T> aBackgroundTask) {
|
||||
BackgroundTask<T, Args...> aBackgroundTask, Args... aArgs) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (RefPtr<Promise> existing = mAsyncAttributePromises[aAttribute]) {
|
||||
existing.forget(aResultPromise);
|
||||
@@ -45,29 +105,10 @@ nsresult nsPrinterBase::AsyncPromiseAttributeGetter(
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
// We actually want to allow to access the printer data from the callback, so
|
||||
// disable strict checking. They should of course only access immutable
|
||||
// members.
|
||||
auto holder = MakeRefPtr<nsMainThreadPtrHolder<nsPrinterBase>>(
|
||||
"nsPrinterBase::AsyncPromiseAttributeGetter", this, /* strict = */ false);
|
||||
NS_DispatchBackgroundTask(NS_NewRunnableFunction(
|
||||
"nsPrinterBase::AsyncPromiseAttributeGetter",
|
||||
[holder = std::move(holder), aAttribute, aBackgroundTask] {
|
||||
T result = (holder->get()->*aBackgroundTask)();
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
"nsPrinterBase::AsyncPromiseAttributeGetterResult",
|
||||
[holder = std::move(holder), result = std::move(result),
|
||||
aAttribute] {
|
||||
nsPrinterBase* printer = holder->get();
|
||||
// There could be no promise, could've been CC'd or what not.
|
||||
if (Promise* p = printer->mAsyncAttributePromises[aAttribute]) {
|
||||
p->MaybeResolve(result);
|
||||
}
|
||||
}));
|
||||
}));
|
||||
RefPtr<Promise> promise = mAsyncAttributePromises[aAttribute];
|
||||
SpawnBackgroundTask(*promise, aBackgroundTask, aArgs...);
|
||||
|
||||
RefPtr<Promise> existing = mAsyncAttributePromises[aAttribute];
|
||||
existing.forget(aResultPromise);
|
||||
promise.forget(aResultPromise);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -92,6 +133,11 @@ NS_IMETHODIMP nsPrinterBase::GetPaperList(JSContext* aCx,
|
||||
&nsPrinterBase::PaperList);
|
||||
}
|
||||
|
||||
void nsPrinterBase::QueryMarginsForPaper(Promise& aPromise, uint64_t aPaperId) {
|
||||
return SpawnBackgroundTask<MarginDouble, uint64_t>(
|
||||
aPromise, &nsPrinterBase::GetMarginsForPaper, aPaperId);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(nsPrinterBase, mAsyncAttributePromises)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPrinterBase)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#ifndef nsPrinterBase_h__
|
||||
#define nsPrinterBase_h__
|
||||
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
#include "nsIPrinter.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
@@ -25,6 +26,7 @@ class Promise;
|
||||
class nsPrinterBase : public nsIPrinter {
|
||||
public:
|
||||
using Promise = mozilla::dom::Promise;
|
||||
using MarginDouble = mozilla::gfx::MarginDouble;
|
||||
|
||||
NS_IMETHOD GetSupportsDuplex(JSContext*, Promise**) final;
|
||||
NS_IMETHOD GetSupportsColor(JSContext*, Promise**) final;
|
||||
@@ -37,6 +39,8 @@ class nsPrinterBase : public nsIPrinter {
|
||||
nsPrinterBase(const nsPrinterBase&) = delete;
|
||||
nsPrinterBase(nsPrinterBase&&) = delete;
|
||||
|
||||
void QueryMarginsForPaper(Promise&, uint64_t aPaperId);
|
||||
|
||||
private:
|
||||
enum class AsyncAttribute {
|
||||
SupportsDuplex = 0,
|
||||
@@ -46,14 +50,18 @@ class nsPrinterBase : public nsIPrinter {
|
||||
Last,
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using AsyncAttributeBackgroundTask = T (nsPrinterBase::*)() const;
|
||||
template <typename T, typename... Args>
|
||||
using BackgroundTask = T (nsPrinterBase::*)(Args...) const;
|
||||
|
||||
// Resolves a promise when a background task finishes.
|
||||
template <typename T, typename... Args>
|
||||
void SpawnBackgroundTask(Promise&, BackgroundTask<T, Args...>, Args... aArgs);
|
||||
|
||||
// Resolves an async attribute via a background task.
|
||||
template <typename T>
|
||||
nsresult AsyncPromiseAttributeGetter(JSContext* aCx, Promise** aResultPromise,
|
||||
AsyncAttribute,
|
||||
AsyncAttributeBackgroundTask<T>);
|
||||
template <typename T, typename... Args>
|
||||
nsresult AsyncPromiseAttributeGetter(JSContext*, Promise**, AsyncAttribute,
|
||||
BackgroundTask<T, Args...>,
|
||||
Args... aArgs);
|
||||
|
||||
protected:
|
||||
nsPrinterBase();
|
||||
@@ -64,6 +72,7 @@ class nsPrinterBase : public nsIPrinter {
|
||||
virtual bool SupportsDuplex() const = 0;
|
||||
virtual bool SupportsColor() const = 0;
|
||||
virtual nsTArray<mozilla::PaperInfo> PaperList() const = 0;
|
||||
virtual MarginDouble GetMarginsForPaper(uint64_t aPaperId) const = 0;
|
||||
|
||||
private:
|
||||
mozilla::EnumeratedArray<AsyncAttribute, AsyncAttribute::Last,
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "nsPaper.h"
|
||||
#include "nsPrinterBase.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
nsPrinterCUPS::nsPrinterCUPS(const nsCUPSShim& aShim, cups_dest_t* aPrinter)
|
||||
: mShim(aShim) {
|
||||
MOZ_ASSERT(aPrinter);
|
||||
@@ -51,7 +53,7 @@ bool nsPrinterCUPS::Supports(const char* option, const char* value) const {
|
||||
mPrinterInfo, option, value);
|
||||
}
|
||||
|
||||
nsTArray<mozilla::PaperInfo> nsPrinterCUPS::PaperList() const {
|
||||
nsTArray<PaperInfo> nsPrinterCUPS::PaperList() const {
|
||||
if (!mPrinterInfo) {
|
||||
return {};
|
||||
}
|
||||
@@ -72,7 +74,7 @@ nsTArray<mozilla::PaperInfo> nsPrinterCUPS::PaperList() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
nsTArray<mozilla::PaperInfo> paperList;
|
||||
nsTArray<PaperInfo> paperList;
|
||||
for (int i = 0; i < paperCount; ++i) {
|
||||
cups_size_t info;
|
||||
int getInfoSucceded = mShim.mCupsGetDestMediaByIndex(
|
||||
@@ -96,14 +98,14 @@ nsTArray<mozilla::PaperInfo> nsPrinterCUPS::PaperList() const {
|
||||
NS_ConvertUTF8toUTF16 name(localizedName);
|
||||
const double kPointsPerHundredthMillimeter = 0.0283465;
|
||||
|
||||
paperList.AppendElement(mozilla::PaperInfo{
|
||||
paperList.AppendElement(PaperInfo{
|
||||
std::move(name),
|
||||
info.width * kPointsPerHundredthMillimeter,
|
||||
info.length * kPointsPerHundredthMillimeter,
|
||||
info.top * kPointsPerHundredthMillimeter,
|
||||
info.right * kPointsPerHundredthMillimeter,
|
||||
info.bottom * kPointsPerHundredthMillimeter,
|
||||
info.left * kPointsPerHundredthMillimeter,
|
||||
{info.width * kPointsPerHundredthMillimeter,
|
||||
info.length * kPointsPerHundredthMillimeter},
|
||||
Some(MarginDouble{info.top * kPointsPerHundredthMillimeter,
|
||||
info.right * kPointsPerHundredthMillimeter,
|
||||
info.bottom * kPointsPerHundredthMillimeter,
|
||||
info.left * kPointsPerHundredthMillimeter}),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,12 @@ class nsPrinterCUPS final : public nsPrinterBase {
|
||||
bool SupportsDuplex() const final;
|
||||
bool SupportsColor() const final;
|
||||
nsTArray<mozilla::PaperInfo> PaperList() const final;
|
||||
MarginDouble GetMarginsForPaper(uint64_t) const final {
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"The CUPS API requires us to always get the margin when fetching the "
|
||||
"paper list so there should be no need to query it separately");
|
||||
return {};
|
||||
}
|
||||
|
||||
nsPrinterCUPS() = delete;
|
||||
|
||||
|
||||
@@ -96,7 +96,6 @@ nsTArray<mozilla::PaperInfo> nsPrinterWin::PaperList() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
static const wchar_t kDriverName[] = L"WINSPOOL";
|
||||
nsTArray<mozilla::PaperInfo> paperList;
|
||||
paperList.SetCapacity(paperNames.Length());
|
||||
for (size_t i = 0; i < paperNames.Length(); ++i) {
|
||||
@@ -112,34 +111,38 @@ nsTArray<mozilla::PaperInfo> nsPrinterWin::PaperList() const {
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// We don't resolve the margins eagerly because they're really expensive (on
|
||||
// the order of seconds for some drivers).
|
||||
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,
|
||||
{width, height},
|
||||
Nothing(),
|
||||
paperIds[i],
|
||||
});
|
||||
}
|
||||
|
||||
return paperList;
|
||||
}
|
||||
|
||||
mozilla::gfx::MarginDouble nsPrinterWin::GetMarginsForPaper(
|
||||
uint64_t aPaperId) const {
|
||||
static const wchar_t kDriverName[] = L"WINSPOOL";
|
||||
// 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 = aPaperId;
|
||||
|
||||
// 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 margin = WinUtils::GetUnwriteableMarginsForDeviceInInches(printerDc);
|
||||
margin.top *= POINTS_PER_INCH_FLOAT;
|
||||
margin.right *= POINTS_PER_INCH_FLOAT;
|
||||
margin.bottom *= POINTS_PER_INCH_FLOAT;
|
||||
margin.left *= POINTS_PER_INCH_FLOAT;
|
||||
return margin;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ class nsPrinterWin final : public nsPrinterBase {
|
||||
bool SupportsDuplex() const final;
|
||||
bool SupportsColor() const final;
|
||||
nsTArray<mozilla::PaperInfo> PaperList() const final;
|
||||
MarginDouble GetMarginsForPaper(uint64_t aId) const final;
|
||||
|
||||
nsPrinterWin() = delete;
|
||||
static already_AddRefed<nsPrinterWin> Create(const nsAString& aName);
|
||||
|
||||
Reference in New Issue
Block a user