diff options
-rw-r--r-- | printing/DEPS | 1 | ||||
-rw-r--r-- | printing/printing.gyp | 1 | ||||
-rw-r--r-- | printing/printing_context_win.cc | 58 | ||||
-rw-r--r-- | printing/printing_context_win.h | 15 | ||||
-rw-r--r-- | ui/shell_dialogs.gypi | 2 | ||||
-rw-r--r-- | ui/shell_dialogs/base_shell_dialog_win.cc | 4 | ||||
-rw-r--r-- | ui/shell_dialogs/print_settings_dialog_win.cc | 58 | ||||
-rw-r--r-- | ui/shell_dialogs/print_settings_dialog_win.h | 83 |
8 files changed, 198 insertions, 24 deletions
diff --git a/printing/DEPS b/printing/DEPS index 00c20e2..64123b8 100644 --- a/printing/DEPS +++ b/printing/DEPS @@ -7,5 +7,6 @@ include_rules = [ "+ui/base/resource", "+ui/base/text", "+ui/gfx", + "+ui/shell_dialogs", "+win8/util", ] diff --git a/printing/printing.gyp b/printing/printing.gyp index 455786e..c7ff11e 100644 --- a/printing/printing.gyp +++ b/printing/printing.gyp @@ -18,6 +18,7 @@ '../third_party/icu/icu.gyp:icui18n', '../third_party/icu/icu.gyp:icuuc', '../ui/gfx/gfx.gyp:gfx', + '../ui/ui.gyp:shell_dialogs', '../ui/ui.gyp:ui', '../url/url.gyp:url_lib', ], diff --git a/printing/printing_context_win.cc b/printing/printing_context_win.cc index 642ada6..29b2604 100644 --- a/printing/printing_context_win.cc +++ b/printing/printing_context_win.cc @@ -189,11 +189,11 @@ PrintingContextWin::~PrintingContextWin() { ReleaseContext(); } -// TODO(vitalybuka): Implement as ui::BaseShellDialog crbug.com/180997. void PrintingContextWin::AskUserForSettings( gfx::NativeView view, int max_pages, bool has_selection, const PrintSettingsCallback& callback) { DCHECK(!in_print_job_); + // TODO(scottmg): Possibly this has to move into the threaded runner too? if (win8::IsSingleWindowMetroMode()) { // The system dialog can not be opened while running in Metro. // But we can programatically launch the Metro print device charm though. @@ -226,40 +226,40 @@ void PrintingContextWin::AskUserForSettings( // - 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; + PRINTDLGEX* dialog_options = + reinterpret_cast<PRINTDLGEX*>(malloc(sizeof(PRINTDLGEX))); + ZeroMemory(dialog_options, sizeof(PRINTDLGEX)); + dialog_options->lStructSize = 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; + dialog_options->Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE | + PD_NOCURRENTPAGE | PD_HIDEPRINTTOFILE; if (!has_selection) - dialog_options.Flags |= PD_NOSELECTION; + dialog_options->Flags |= PD_NOSELECTION; - PRINTPAGERANGE ranges[32]; - dialog_options.nStartPage = START_PAGE_GENERAL; + const size_t max_page_ranges = 32; + PRINTPAGERANGE* ranges = new PRINTPAGERANGE[max_page_ranges]; + dialog_options->lpPageRanges = ranges; + 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; + dialog_options->nPageRanges = 1; + dialog_options->nMaxPageRanges = max_page_ranges; + dialog_options->nMinPage = 1; + dialog_options->nMaxPage = max_pages; } else { // No need to bother, we don't know how many pages are available. - dialog_options.Flags |= PD_NOPAGENUMS; + dialog_options->Flags |= PD_NOPAGENUMS; } - HRESULT hr = (*print_dialog_func_)(&dialog_options); - if (hr != S_OK) { - ResetSettings(); - callback.Run(FAILED); - } - - // TODO(maruel): Support PD_PRINTTOFILE. - callback.Run(ParseDialogResultEx(dialog_options)); + callback_ = callback; + print_settings_dialog_ = new ui::PrintSettingsDialogWin(this); + print_settings_dialog_->GetPrintSettings( + print_dialog_func_, window, dialog_options); } PrintingContext::Result PrintingContextWin::UseDefaultSettings() { @@ -565,6 +565,20 @@ gfx::NativeDrawingContext PrintingContextWin::context() const { return context_; } +void PrintingContextWin::PrintSettingsConfirmed(PRINTDLGEX* dialog_options) { + // TODO(maruel): Support PD_PRINTTOFILE. + callback_.Run(ParseDialogResultEx(*dialog_options)); + delete [] dialog_options->lpPageRanges; + free(dialog_options); +} + +void PrintingContextWin::PrintSettingsCancelled(PRINTDLGEX* dialog_options) { + ResetSettings(); + callback_.Run(FAILED); + delete [] dialog_options->lpPageRanges; + free(dialog_options); +} + // static BOOL PrintingContextWin::AbortProc(HDC hdc, int nCode) { if (nCode) { diff --git a/printing/printing_context_win.h b/printing/printing_context_win.h index c54b531..06226b2 100644 --- a/printing/printing_context_win.h +++ b/printing/printing_context_win.h @@ -14,10 +14,13 @@ #include "build/build_config.h" #include "printing/printing_context.h" #include "ui/gfx/native_widget_types.h" +#include "ui/shell_dialogs/print_settings_dialog_win.h" namespace printing { -class PRINTING_EXPORT PrintingContextWin : public PrintingContext { +class PRINTING_EXPORT PrintingContextWin + : public PrintingContext, + public ui::PrintSettingsDialogWin::Observer { public: explicit PrintingContextWin(const std::string& app_locale); ~PrintingContextWin(); @@ -41,6 +44,10 @@ class PRINTING_EXPORT PrintingContextWin : public PrintingContext { virtual void ReleaseContext() OVERRIDE; virtual gfx::NativeDrawingContext context() const OVERRIDE; + // PrintSettingsDialogWin::Observer implementation: + virtual void PrintSettingsConfirmed(PRINTDLGEX* dialog_options) OVERRIDE; + virtual void PrintSettingsCancelled(PRINTDLGEX* dialog_options) OVERRIDE; + #if defined(UNIT_TEST) || defined(PRINTING_IMPLEMENTATION) // Sets a fake PrintDlgEx function pointer in tests. void SetPrintDialog(HRESULT (__stdcall *print_dialog_func)(LPPRINTDLGEX)) { @@ -88,6 +95,12 @@ class PRINTING_EXPORT PrintingContextWin : public PrintingContext { // SetPrintDialog() in tests. HRESULT (__stdcall *print_dialog_func_)(LPPRINTDLGEX); + // Where to notify when the dialog is closed. + PrintSettingsCallback callback_; + + // Wrapper around native print dialog that runs it on a background thread. + scoped_refptr<ui::PrintSettingsDialogWin> print_settings_dialog_; + DISALLOW_COPY_AND_ASSIGN(PrintingContextWin); }; diff --git a/ui/shell_dialogs.gypi b/ui/shell_dialogs.gypi index 2675d73..29f676f 100644 --- a/ui/shell_dialogs.gypi +++ b/ui/shell_dialogs.gypi @@ -30,6 +30,8 @@ 'shell_dialogs/gtk/select_file_dialog_impl_kde.cc', 'shell_dialogs/linux_shell_dialog.cc', 'shell_dialogs/linux_shell_dialog.h', + 'shell_dialogs/print_settings_dialog_win.cc', + 'shell_dialogs/print_settings_dialog_win.h', 'shell_dialogs/select_file_dialog.cc', 'shell_dialogs/select_file_dialog.h', 'shell_dialogs/select_file_dialog_android.cc', diff --git a/ui/shell_dialogs/base_shell_dialog_win.cc b/ui/shell_dialogs/base_shell_dialog_win.cc index 9ccd1bb..e121fbf 100644 --- a/ui/shell_dialogs/base_shell_dialog_win.cc +++ b/ui/shell_dialogs/base_shell_dialog_win.cc @@ -30,7 +30,9 @@ BaseShellDialogImpl::RunState BaseShellDialogImpl::BeginRun(HWND owner) { DCHECK(!IsRunningDialogForOwner(owner)); // The owner must be a top level window, otherwise we could end up with two // entries in our map for the same top level window. - DCHECK(!owner || owner == GetAncestor(owner, GA_ROOT)); + // TODO(scottmg): This should be re-enabled when Chrome Frame is removed. + // http://crbug.com/310264 + // DCHECK(!owner || owner == GetAncestor(owner, GA_ROOT)); RunState run_state; run_state.dialog_thread = CreateDialogThread(); run_state.owner = owner; diff --git a/ui/shell_dialogs/print_settings_dialog_win.cc b/ui/shell_dialogs/print_settings_dialog_win.cc new file mode 100644 index 0000000..f3f89b3 --- /dev/null +++ b/ui/shell_dialogs/print_settings_dialog_win.cc @@ -0,0 +1,58 @@ +// Copyright 2013 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 "ui/shell_dialogs/print_settings_dialog_win.h" + +#include "base/bind.h" +#include "base/threading/thread.h" + +#if defined(USE_AURA) +#include "ui/aura/root_window.h" +#endif + +namespace ui { + +PrintSettingsDialogWin::PrintSettingsDialogWin( + PrintSettingsDialogWin::Observer* observer) + : observer_(observer) { +} + +PrintSettingsDialogWin::~PrintSettingsDialogWin() { +} + +void PrintSettingsDialogWin::GetPrintSettings(PrintDialogFunc print_dialog_func, + HWND owning_window, + PRINTDLGEX* dialog_options) { + DCHECK(observer_); + + ExecutePrintSettingsParams execute_params(BeginRun(owning_window), + owning_window, + print_dialog_func, + dialog_options); + execute_params.run_state.dialog_thread->message_loop()->PostTask( + FROM_HERE, + base::Bind( + &PrintSettingsDialogWin::ExecutePrintSettings, this, execute_params)); +} + +void PrintSettingsDialogWin::ExecutePrintSettings( + const ExecutePrintSettingsParams& params) { + HRESULT hr = (*params.print_dialog_func)(params.dialog_options); + params.ui_proxy->PostTask( + FROM_HERE, + base::Bind( + &PrintSettingsDialogWin::PrintSettingsCompleted, this, hr, params)); +} + +void PrintSettingsDialogWin::PrintSettingsCompleted( + HRESULT hresult, + const ExecutePrintSettingsParams& params) { + EndRun(params.run_state); + if (hresult != S_OK) + observer_->PrintSettingsCancelled(params.dialog_options); + else + observer_->PrintSettingsConfirmed(params.dialog_options); +} + +} // namespace ui diff --git a/ui/shell_dialogs/print_settings_dialog_win.h b/ui/shell_dialogs/print_settings_dialog_win.h new file mode 100644 index 0000000..6a1efed --- /dev/null +++ b/ui/shell_dialogs/print_settings_dialog_win.h @@ -0,0 +1,83 @@ +// Copyright 2013 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 UI_SHELL_DIALOGS_PRINT_SETTINGS_DIALOG_WIN_H_ +#define UI_SHELL_DIALOGS_PRINT_SETTINGS_DIALOG_WIN_H_ + +#include <ocidl.h> +#include <commdlg.h> + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/message_loop/message_loop_proxy.h" +#include "ui/shell_dialogs/base_shell_dialog_win.h" +#include "ui/shell_dialogs/shell_dialogs_export.h" + +namespace ui { + +// A thin wrapper around the native window print dialog that uses +// BaseShellDialog to have the dialog run on a background thread. +class SHELL_DIALOGS_EXPORT PrintSettingsDialogWin + : public base::RefCountedThreadSafe<PrintSettingsDialogWin>, + public BaseShellDialogImpl { + public: + class SHELL_DIALOGS_EXPORT Observer { + public: + virtual void PrintSettingsConfirmed(PRINTDLGEX* dialog_options) = 0; + virtual void PrintSettingsCancelled(PRINTDLGEX* dialog_options) = 0; + }; + typedef HRESULT(__stdcall* PrintDialogFunc)(PRINTDLGEX*); + + explicit PrintSettingsDialogWin(Observer* observer); + virtual ~PrintSettingsDialogWin(); + + // Called to open the system print dialog on a background thread. + // |print_dialog_func| should generally be ::PrintDlgEx, however alternate + // functions are used for testing. |owning_window| is the parent HWND, and + // |dialog_options| is passed to |print_dialog_func|. + void GetPrintSettings( + PrintDialogFunc print_dialog_func, + HWND owning_window, + PRINTDLGEX* dialog_options); + + private: + // A struct for holding all the state necessary for displaying the print + // settings dialog. + struct ExecutePrintSettingsParams { + ExecutePrintSettingsParams(RunState run_state, + HWND owner, + PrintDialogFunc print_dialog_func, + PRINTDLGEX* dialog_options) + : run_state(run_state), + owner(owner), + print_dialog_func(print_dialog_func), + dialog_options(dialog_options), + ui_proxy(base::MessageLoopForUI::current()->message_loop_proxy()) {} + + RunState run_state; + HWND owner; + PrintDialogFunc print_dialog_func; + PRINTDLGEX* dialog_options; + scoped_refptr<base::MessageLoopProxy> ui_proxy; + }; + + // Runs the print dialog. Should be run on the the BaseShellDialogImpl thread. + // Posts back to PrintSettingsCompleted on the UI thread on completion. + void ExecutePrintSettings(const ExecutePrintSettingsParams& params); + + // Handler for the result of the print settings dialog. Should be run on the + // UI thread, and notifies the observer of the result of the dialog. + void PrintSettingsCompleted(HRESULT hresult, + const ExecutePrintSettingsParams& params); + + // Observer that's notified when the dialog is confirmed or cancelled. + Observer* observer_; + + DISALLOW_COPY_AND_ASSIGN(PrintSettingsDialogWin); +}; + +} // namespace ui + +#endif // UI_SHELL_DIALOGS_PRINT_SETTINGS_DIALOG_WIN_H_ |