Skip to content

Commit

Permalink
Restored printing windows context for builds without preview.
Browse files Browse the repository at this point in the history
This is code placed into separate file that was removed in https://codereview.chromium.org/478183005

Code is still used by CEF.

BUG=374321
NOTRY=true

Review URL: https://codereview.chromium.org/557663002

Cr-Commit-Position: refs/heads/master@{#293992}
  • Loading branch information
vitalybuka authored and Commit bot committed Sep 9, 2014
1 parent 75844fd commit f9d0c0c
Show file tree
Hide file tree
Showing 6 changed files with 507 additions and 35 deletions.
8 changes: 5 additions & 3 deletions printing/printing.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
'backend/print_backend_consts.cc',
'backend/print_backend_consts.h',
'backend/print_backend_dummy.cc',
'backend/print_backend_win.cc',
'backend/printing_info_win.cc',
'backend/printing_info_win.h',
'emf_win.cc',
Expand Down Expand Up @@ -78,6 +79,10 @@
'printed_pages_source.h',
'printing_context.cc',
'printing_context.h',
'printing_context_system_dialog_win.cc',
'printing_context_system_dialog_win.h',
'printing_context_win.cc',
'printing_context_win.h',
'printing_utils.cc',
'printing_utils.h',
'units.cc',
Expand Down Expand Up @@ -120,9 +125,6 @@
'sources': [
'backend/win_helper.cc',
'backend/win_helper.h',
'backend/print_backend_win.cc',
'printing_context_win.cc',
'printing_context_win.h',
],
}],
['chromeos==1',{
Expand Down
269 changes: 269 additions & 0 deletions printing/printing_context_system_dialog_win.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "printing/printing_context_system_dialog_win.h"

#include "base/message_loop/message_loop.h"
#include "printing/backend/win_helper.h"
#include "printing/print_settings_initializer_win.h"
#include "skia/ext/platform_device.h"

namespace printing {

PrintingContextSytemDialogWin::PrintingContextSytemDialogWin(Delegate* delegate)
: PrintingContextWin(delegate), dialog_box_(NULL) {
}

PrintingContextSytemDialogWin::~PrintingContextSytemDialogWin() {
}

void PrintingContextSytemDialogWin::AskUserForSettings(
int max_pages,
bool has_selection,
const PrintSettingsCallback& callback) {
DCHECK(!in_print_job_);
dialog_box_dismissed_ = false;

HWND window = GetRootWindow(delegate_->GetParentView());
DCHECK(window);

// Show the OS-dependent dialog box.
// If the user press
// - OK, the settings are reset and reinitialized with the new settings. OK
// is
// returned.
// - Apply then Cancel, the settings are reset and reinitialized with the
// new
// settings. CANCEL is returned.
// - Cancel, the settings are not changed, the previous setting, if it was
// initialized before, are kept. CANCEL is returned.
// On failure, the settings are reset and FAILED is returned.
PRINTDLGEX dialog_options = {sizeof(PRINTDLGEX)};
dialog_options.hwndOwner = window;
// Disable options we don't support currently.
// TODO(maruel): Reuse the previously loaded settings!
dialog_options.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE |
PD_NOCURRENTPAGE | PD_HIDEPRINTTOFILE;
if (!has_selection)
dialog_options.Flags |= PD_NOSELECTION;

PRINTPAGERANGE ranges[32];
dialog_options.nStartPage = START_PAGE_GENERAL;
if (max_pages) {
// Default initialize to print all the pages.
memset(ranges, 0, sizeof(ranges));
ranges[0].nFromPage = 1;
ranges[0].nToPage = max_pages;
dialog_options.nPageRanges = 1;
dialog_options.nMaxPageRanges = arraysize(ranges);
dialog_options.nMinPage = 1;
dialog_options.nMaxPage = max_pages;
dialog_options.lpPageRanges = ranges;
} else {
// No need to bother, we don't know how many pages are available.
dialog_options.Flags |= PD_NOPAGENUMS;
}

if (ShowPrintDialog(&dialog_options) != S_OK) {
ResetSettings();
callback.Run(FAILED);
}

// TODO(maruel): Support PD_PRINTTOFILE.
callback.Run(ParseDialogResultEx(dialog_options));
}

void PrintingContextSytemDialogWin::Cancel() {
PrintingContextWin::Cancel();
if (dialog_box_) {
DestroyWindow(dialog_box_);
dialog_box_dismissed_ = true;
}
}

HRESULT PrintingContextSytemDialogWin::ShowPrintDialog(PRINTDLGEX* options) {
// Note that this cannot use ui::BaseShellDialog as the print dialog is
// system modal: opening it from a background thread can cause Windows to
// get the wrong Z-order which will make the print dialog appear behind the
// browser frame (but still being modal) so neither the browser frame nor
// the print dialog will get any input. See http://crbug.com/342697
// http://crbug.com/180997 for details.
base::MessageLoop::ScopedNestableTaskAllower allow(
base::MessageLoop::current());

return PrintDlgEx(options);
}

bool PrintingContextSytemDialogWin::InitializeSettings(
const DEVMODE& dev_mode,
const std::wstring& new_device_name,
const PRINTPAGERANGE* ranges,
int number_ranges,
bool selection_only) {
DCHECK(GetDeviceCaps(context(), CLIPCAPS));
DCHECK(GetDeviceCaps(context(), RASTERCAPS) & RC_STRETCHDIB);
DCHECK(GetDeviceCaps(context(), RASTERCAPS) & RC_BITMAP64);
// Some printers don't advertise these.
// DCHECK(GetDeviceCaps(context(), RASTERCAPS) & RC_SCALING);
// DCHECK(GetDeviceCaps(context(), SHADEBLENDCAPS) & SB_CONST_ALPHA);
// DCHECK(GetDeviceCaps(context(), SHADEBLENDCAPS) & SB_PIXEL_ALPHA);

// StretchDIBits() support is needed for printing.
if (!(GetDeviceCaps(context(), RASTERCAPS) & RC_STRETCHDIB) ||
!(GetDeviceCaps(context(), RASTERCAPS) & RC_BITMAP64)) {
NOTREACHED();
ResetSettings();
return false;
}

DCHECK(!in_print_job_);
DCHECK(context());
PageRanges ranges_vector;
if (!selection_only) {
// Convert the PRINTPAGERANGE array to a PrintSettings::PageRanges vector.
ranges_vector.reserve(number_ranges);
for (int i = 0; i < number_ranges; ++i) {
PageRange range;
// Transfer from 1-based to 0-based.
range.from = ranges[i].nFromPage - 1;
range.to = ranges[i].nToPage - 1;
ranges_vector.push_back(range);
}
}

settings_.set_ranges(ranges_vector);
settings_.set_device_name(new_device_name);
settings_.set_selection_only(selection_only);
PrintSettingsInitializerWin::InitPrintSettings(
context(), dev_mode, &settings_);

return true;
}

PrintingContext::Result PrintingContextSytemDialogWin::ParseDialogResultEx(
const PRINTDLGEX& dialog_options) {
// If the user clicked OK or Apply then Cancel, but not only Cancel.
if (dialog_options.dwResultAction != PD_RESULT_CANCEL) {
// Start fresh.
ResetSettings();

DEVMODE* dev_mode = NULL;
if (dialog_options.hDevMode) {
dev_mode =
reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode));
DCHECK(dev_mode);
}

std::wstring device_name;
if (dialog_options.hDevNames) {
DEVNAMES* dev_names =
reinterpret_cast<DEVNAMES*>(GlobalLock(dialog_options.hDevNames));
DCHECK(dev_names);
if (dev_names) {
device_name = reinterpret_cast<const wchar_t*>(dev_names) +
dev_names->wDeviceOffset;
GlobalUnlock(dialog_options.hDevNames);
}
}

bool success = false;
if (dev_mode && !device_name.empty()) {
set_context(dialog_options.hDC);
PRINTPAGERANGE* page_ranges = NULL;
DWORD num_page_ranges = 0;
bool print_selection_only = false;
if (dialog_options.Flags & PD_PAGENUMS) {
page_ranges = dialog_options.lpPageRanges;
num_page_ranges = dialog_options.nPageRanges;
}
if (dialog_options.Flags & PD_SELECTION) {
print_selection_only = true;
}
success = InitializeSettings(*dev_mode,
device_name,
page_ranges,
num_page_ranges,
print_selection_only);
}

if (!success && dialog_options.hDC) {
DeleteDC(dialog_options.hDC);
set_context(NULL);
}

if (dev_mode) {
GlobalUnlock(dialog_options.hDevMode);
}
} else {
if (dialog_options.hDC) {
DeleteDC(dialog_options.hDC);
}
}

if (dialog_options.hDevMode != NULL)
GlobalFree(dialog_options.hDevMode);
if (dialog_options.hDevNames != NULL)
GlobalFree(dialog_options.hDevNames);

switch (dialog_options.dwResultAction) {
case PD_RESULT_PRINT:
return context() ? OK : FAILED;
case PD_RESULT_APPLY:
return context() ? CANCEL : FAILED;
case PD_RESULT_CANCEL:
return CANCEL;
default:
return FAILED;
}
}

PrintingContext::Result PrintingContextSytemDialogWin::ParseDialogResult(
const PRINTDLG& dialog_options) {
// If the user clicked OK or Apply then Cancel, but not only Cancel.
// Start fresh.
ResetSettings();

DEVMODE* dev_mode = NULL;
if (dialog_options.hDevMode) {
dev_mode = reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode));
DCHECK(dev_mode);
}

std::wstring device_name;
if (dialog_options.hDevNames) {
DEVNAMES* dev_names =
reinterpret_cast<DEVNAMES*>(GlobalLock(dialog_options.hDevNames));
DCHECK(dev_names);
if (dev_names) {
device_name = reinterpret_cast<const wchar_t*>(
reinterpret_cast<const wchar_t*>(dev_names) +
dev_names->wDeviceOffset);
GlobalUnlock(dialog_options.hDevNames);
}
}

bool success = false;
if (dev_mode && !device_name.empty()) {
set_context(dialog_options.hDC);
success = InitializeSettings(*dev_mode, device_name, NULL, 0, false);
}

if (!success && dialog_options.hDC) {
DeleteDC(dialog_options.hDC);
set_context(NULL);
}

if (dev_mode) {
GlobalUnlock(dialog_options.hDevMode);
}

if (dialog_options.hDevMode != NULL)
GlobalFree(dialog_options.hDevMode);
if (dialog_options.hDevNames != NULL)
GlobalFree(dialog_options.hDevNames);

return context() ? OK : FAILED;
}

} // namespace printing
56 changes: 56 additions & 0 deletions printing/printing_context_system_dialog_win.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef PRINTING_PRINTING_CONTEXT_SYSTEM_DIALOG_WIN_H_
#define PRINTING_PRINTING_CONTEXT_SYSTEM_DIALOG_WIN_H_

#include <ocidl.h>
#include <commdlg.h>

#include <string>

#include "printing/printing_context_win.h"
#include "ui/gfx/native_widget_types.h"

namespace printing {

class PRINTING_EXPORT PrintingContextSytemDialogWin
: public PrintingContextWin {
public:
explicit PrintingContextSytemDialogWin(Delegate* delegate);
virtual ~PrintingContextSytemDialogWin();

// PrintingContext implementation.
virtual void AskUserForSettings(
int max_pages,
bool has_selection,
const PrintSettingsCallback& callback) OVERRIDE;
virtual void Cancel() OVERRIDE;

private:
friend class MockPrintingContextWin;

virtual HRESULT ShowPrintDialog(PRINTDLGEX* options);

// Reads the settings from the selected device context. Updates settings_ and
// its margins.
bool InitializeSettings(const DEVMODE& dev_mode,
const std::wstring& new_device_name,
const PRINTPAGERANGE* ranges,
int number_ranges,
bool selection_only);

// Parses the result of a PRINTDLGEX result.
Result ParseDialogResultEx(const PRINTDLGEX& dialog_options);
Result ParseDialogResult(const PRINTDLG& dialog_options);

// The dialog box for the time it is shown.
volatile HWND dialog_box_;

DISALLOW_COPY_AND_ASSIGN(PrintingContextSytemDialogWin);
};

} // namespace printing

#endif // PRINTING_PRINTING_CONTEXT_SYSTEM_DIALOG_WIN_H_
Loading

0 comments on commit f9d0c0c

Please sign in to comment.