Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1268)

Unified Diff: win8/metro_driver/print_handler.cc

Issue 10875008: Integrate the Windows 8 code into the Chromium tree. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove conflicting OWNERS file. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « win8/metro_driver/print_handler.h ('k') | win8/metro_driver/run_all_unittests.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: win8/metro_driver/print_handler.cc
diff --git a/win8/metro_driver/print_handler.cc b/win8/metro_driver/print_handler.cc
new file mode 100644
index 0000000000000000000000000000000000000000..dce321aedc6ef525506a7c0b6a10ac635713e9ad
--- /dev/null
+++ b/win8/metro_driver/print_handler.cc
@@ -0,0 +1,487 @@
+// Copyright (c) 2012 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 "stdafx.h"
+#include "win8/metro_driver/print_handler.h"
+
+#include <windows.graphics.display.h>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "win8/metro_driver/chrome_app_view.h"
+#include "win8/metro_driver/winrt_utils.h"
+
+namespace {
+
+typedef winfoundtn::ITypedEventHandler<
+ wingfx::Printing::PrintManager*,
+ wingfx::Printing::PrintTaskRequestedEventArgs*> PrintRequestedHandler;
+
+typedef winfoundtn::ITypedEventHandler<
+ wingfx::Printing::PrintTask*,
+ wingfx::Printing::PrintTaskCompletedEventArgs*> PrintTaskCompletedHandler;
+
+typedef winfoundtn::ITypedEventHandler<
+ wingfx::Printing::PrintTask*, IInspectable*> PrintTaskInspectableHandler;
+
+typedef winfoundtn::ITypedEventHandler<
+ wingfx::Printing::PrintTask*,
+ wingfx::Printing::PrintTaskProgressingEventArgs*>
+ PrintTaskProgressingHandler;
+
+} // namespace
+
+namespace metro_driver {
+
+mswr::ComPtr<PrintDocumentSource> PrintHandler::current_document_source_;
+bool PrintHandler::printing_enabled_ = false;
+base::Lock* PrintHandler::lock_ = NULL;
+base::Thread* PrintHandler::thread_ = NULL;
+
+PrintHandler::PrintHandler() {
+ DCHECK(lock_ == NULL);
+ lock_ = new base::Lock();
+
+ DCHECK(thread_ == NULL);
+ thread_ = new base::Thread("Metro Print Handler");
+ thread_->Start();
+}
+
+PrintHandler::~PrintHandler() {
+ ClearPrintTask();
+ DCHECK(current_document_source_.Get() == NULL);
+
+ // Get all pending tasks to complete cleanly by Stopping the thread.
+ // They should complete quickly since current_document_source_ is NULL.
+ DCHECK(thread_ != NULL);
+ DCHECK(thread_->IsRunning());
+ thread_->Stop();
+ delete thread_;
+ thread_ = NULL;
+
+ DCHECK(lock_ != NULL);
+ delete lock_;
+ lock_ = NULL;
+}
+
+HRESULT PrintHandler::Initialize(winui::Core::ICoreWindow* window) {
+ // Register for Print notifications.
+ mswr::ComPtr<wingfx::Printing::IPrintManagerStatic> print_mgr_static;
+ HRESULT hr = winrt_utils::CreateActivationFactory(
+ RuntimeClass_Windows_Graphics_Printing_PrintManager,
+ print_mgr_static.GetAddressOf());
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to create PrintManagerStatic " << std::hex << hr;
+ return hr;
+ }
+
+ mswr::ComPtr<wingfx::Printing::IPrintManager> print_mgr;
+ hr = print_mgr_static->GetForCurrentView(&print_mgr);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to get PrintManager for current view " << std::hex
+ << hr;
+ return hr;
+ }
+
+ hr = print_mgr->add_PrintTaskRequested(
+ mswr::Callback<PrintRequestedHandler>(
+ this, &PrintHandler::OnPrintRequested).Get(),
+ &print_requested_token_);
+ LOG_IF(ERROR, FAILED(hr)) << "Failed to register PrintTaskRequested "
+ << std::hex << hr;
+
+ mswr::ComPtr<wingfx::Display::IDisplayPropertiesStatics> display_properties;
+ hr = winrt_utils::CreateActivationFactory(
+ RuntimeClass_Windows_Graphics_Display_DisplayProperties,
+ display_properties.GetAddressOf());
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to create DisplayPropertiesStatics " << std::hex
+ << hr;
+ return hr;
+ }
+
+ hr = display_properties->add_LogicalDpiChanged(
+ mswr::Callback<
+ wingfx::Display::IDisplayPropertiesEventHandler,
+ PrintHandler>(this, &PrintHandler::LogicalDpiChanged).Get(),
+ &dpi_change_token_);
+ LOG_IF(ERROR, FAILED(hr)) << "Failed to register LogicalDpiChanged "
+ << std::hex << hr;
+
+ // This flag adds support for surfaces with a different color channel
+ // ordering than the API default. It is recommended usage, and is required
+ // for compatibility with Direct2D.
+ UINT creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
+#if defined(_DEBUG)
+ creation_flags |= D3D11_CREATE_DEVICE_DEBUG;
+#endif
+
+ // This array defines the set of DirectX hardware feature levels we support.
+ // The ordering MUST be preserved. All applications are assumed to support
+ // 9.1 unless otherwise stated by the application, which is not our case.
+ D3D_FEATURE_LEVEL feature_levels[] = {
+ D3D_FEATURE_LEVEL_11_1,
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0,
+ D3D_FEATURE_LEVEL_9_3,
+ D3D_FEATURE_LEVEL_9_2,
+ D3D_FEATURE_LEVEL_9_1 };
+
+ mswr::ComPtr<ID3D11Device> device;
+ mswr::ComPtr<ID3D11DeviceContext> context;
+ hr = D3D11CreateDevice(
+ NULL, // Specify null to use the default adapter.
+ D3D_DRIVER_TYPE_HARDWARE,
+ 0, // Leave as 0 unless software device.
+ creation_flags,
+ feature_levels,
+ ARRAYSIZE(feature_levels),
+ D3D11_SDK_VERSION, // Must always use this value in Metro apps.
+ &device,
+ NULL, // Returns feature level of device created.
+ &context);
+ if (hr == DXGI_ERROR_UNSUPPORTED) {
+ // The hardware is not supported, try a reference driver instead.
+ hr = D3D11CreateDevice(
+ NULL, // Specify null to use the default adapter.
+ D3D_DRIVER_TYPE_REFERENCE,
+ 0, // Leave as 0 unless software device.
+ creation_flags,
+ feature_levels,
+ ARRAYSIZE(feature_levels),
+ D3D11_SDK_VERSION, // Must always use this value in Metro apps.
+ &device,
+ NULL, // Returns feature level of device created.
+ &context);
+ }
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to create D3D11 device/context " << std::hex << hr;
+ return hr;
+ }
+
+ hr = device.As(&directx_context_.d3d_device);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to QI D3D11 device " << std::hex << hr;
+ return hr;
+ }
+
+ D2D1_FACTORY_OPTIONS options;
+ ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS));
+
+#if defined(_DEBUG)
+ options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
+#endif
+
+ hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED,
+ __uuidof(ID2D1Factory1),
+ &options,
+ &directx_context_.d2d_factory);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to create D2D1 factory " << std::hex << hr;
+ return hr;
+ }
+
+ mswr::ComPtr<IDXGIDevice> dxgi_device;
+ hr = directx_context_.d3d_device.As(&dxgi_device);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to QI for IDXGIDevice " << std::hex << hr;
+ return hr;
+ }
+
+ hr = directx_context_.d2d_factory->CreateDevice(
+ dxgi_device.Get(), &directx_context_.d2d_device);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to Create D2DDevice " << std::hex << hr;
+ return hr;
+ }
+
+ hr = directx_context_.d2d_device->CreateDeviceContext(
+ D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
+ &directx_context_.d2d_context);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to Create D2DDeviceContext " << std::hex << hr;
+ return hr;
+ }
+
+ hr = CoCreateInstance(CLSID_WICImagingFactory,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_PPV_ARGS(&directx_context_.wic_factory));
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to CoCreate WICImagingFactory " << std::hex << hr;
+ return hr;
+ }
+ return hr;
+}
+
+void PrintHandler::EnablePrinting(bool printing_enabled) {
+ thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&PrintHandler::OnEnablePrinting, printing_enabled));
+}
+
+void PrintHandler::SetPageCount(size_t page_count) {
+ thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&PrintHandler::OnSetPageCount, page_count));
+}
+
+void PrintHandler::AddPage(size_t page_number, IStream* metafile_stream) {
+ thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&PrintHandler::OnAddPage,
+ page_number,
+ mswr::ComPtr<IStream>(metafile_stream)));
+}
+
+void PrintHandler::ShowPrintUI() {
+ // Post the print UI request over to the metro thread.
+ DCHECK(globals.appview_msg_loop != NULL);
+ bool posted = globals.appview_msg_loop->PostTask(
+ FROM_HERE, base::Bind(&metro_driver::PrintHandler::OnShowPrintUI));
+ DCHECK(posted);
+}
+
+HRESULT PrintHandler::OnPrintRequested(
+ wingfx::Printing::IPrintManager* print_mgr,
+ wingfx::Printing::IPrintTaskRequestedEventArgs* event_args) {
+ DVLOG(1) << __FUNCTION__;
+
+ HRESULT hr = S_OK;
+ if (printing_enabled_) {
+ mswr::ComPtr<wingfx::Printing::IPrintTaskRequest> print_request;
+ hr = event_args->get_Request(print_request.GetAddressOf());
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to get the Print Task request " << std::hex << hr;
+ return hr;
+ }
+
+ mswrw::HString title;
+ title.Attach(MakeHString(L"Printing"));
+ hr = print_request->CreatePrintTask(
+ title.Get(),
+ mswr::Callback<
+ wingfx::Printing::IPrintTaskSourceRequestedHandler,
+ PrintHandler>(this, &PrintHandler::OnPrintTaskSourceRequest).Get(),
+ print_task_.GetAddressOf());
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to create the Print Task " << std::hex << hr;
+ return hr;
+ }
+
+ hr = print_task_->add_Completed(
+ mswr::Callback<PrintTaskCompletedHandler>(
+ this, &PrintHandler::OnCompleted).Get(), &print_completed_token_);
+ LOG_IF(ERROR, FAILED(hr)) << "Failed to create the Print Task " << std::hex
+ << hr;
+ }
+ return hr;
+}
+
+HRESULT PrintHandler::OnPrintTaskSourceRequest(
+ wingfx::Printing::IPrintTaskSourceRequestedArgs* args) {
+ DVLOG(1) << __FUNCTION__;
+ mswr::ComPtr<PrintDocumentSource> print_document_source;
+ HRESULT hr = mswr::MakeAndInitialize<PrintDocumentSource>(
+ &print_document_source, directx_context_, lock_);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to create document source " << std::hex << hr;
+ return hr;
+ }
+
+ print_document_source->ResetDpi(GetLogicalDpi());
+
+ mswr::ComPtr<wingfx::Printing::IPrintDocumentSource> print_source;
+ hr = print_document_source.As(&print_source);
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to cast document Source " << std::hex << hr;
+ return hr;
+ }
+
+ hr = args->SetSource(print_source.Get());
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to set document Source " << std::hex << hr;
+ return hr;
+ }
+
+ thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&PrintHandler::SetPrintDocumentSource,
+ print_document_source));
+
+ return hr;
+}
+
+HRESULT PrintHandler::OnCompleted(
+ wingfx::Printing::IPrintTask* task,
+ wingfx::Printing::IPrintTaskCompletedEventArgs* args) {
+ DVLOG(1) << __FUNCTION__;
+ DCHECK(globals.appview_msg_loop->BelongsToCurrentThread());
+ ClearPrintTask();
+ thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&PrintHandler::ReleasePrintDocumentSource));
+
+ return S_OK;
+}
+
+void PrintHandler::ClearPrintTask() {
+ if (!print_task_.Get())
+ return;
+
+ HRESULT hr = print_task_->remove_Completed(print_completed_token_);
+ LOG_IF(ERROR, FAILED(hr)) << "Failed to remove completed event from Task "
+ << std::hex << hr;
+ print_task_.Reset();
+}
+
+float PrintHandler::GetLogicalDpi() {
+ mswr::ComPtr<wingfx::Display::IDisplayPropertiesStatics> display_properties;
+ HRESULT hr = winrt_utils::CreateActivationFactory(
+ RuntimeClass_Windows_Graphics_Display_DisplayProperties,
+ display_properties.GetAddressOf());
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed to get display properties " << std::hex << hr;
+ return 0.0;
+ }
+
+ FLOAT dpi = 0.0;
+ hr = display_properties->get_LogicalDpi(&dpi);
+ LOG_IF(ERROR, FAILED(hr)) << "Failed to get Logical DPI " << std::hex << hr;
+
+ return dpi;
+}
+
+HRESULT PrintHandler::LogicalDpiChanged(IInspectable *sender) {
+ DVLOG(1) << __FUNCTION__;
+ thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&PrintHandler::OnLogicalDpiChanged, GetLogicalDpi()));
+ return S_OK;
+}
+
+void PrintHandler::OnLogicalDpiChanged(float dpi) {
+ DCHECK(MessageLoop::current() == thread_->message_loop());
+ // No need to protect the access to the static variable,
+ // since it's set/released in this same thread.
+ if (current_document_source_.Get() != NULL)
+ current_document_source_->ResetDpi(dpi);
+}
+
+void PrintHandler::SetPrintDocumentSource(
+ const mswr::ComPtr<PrintDocumentSource>& print_document_source) {
+ DCHECK(MessageLoop::current() == thread_->message_loop());
+ DCHECK(current_document_source_.Get() == NULL);
+ {
+ // Protect against the other thread which might try to access it.
+ base::AutoLock lock(*lock_);
+ current_document_source_ = print_document_source;
+ }
+ // Start generating the images to print.
+ // TODO(mad): Use a registered message with more information about the print
+ // request, and at a more appropriate time too, and maybe one page at a time.
+ ::PostMessageW(globals.host_windows.front().first,
+ WM_SYSCOMMAND,
+ IDC_PRINT_TO_DESTINATION,
+ 0);
+}
+
+void PrintHandler::ReleasePrintDocumentSource() {
+ DCHECK(MessageLoop::current() == thread_->message_loop());
+ mswr::ComPtr<PrintDocumentSource> print_document_source;
+ {
+ // Must wait for other thread to be done with the pointer first.
+ base::AutoLock lock(*lock_);
+ current_document_source_.Swap(print_document_source);
+ }
+ // This may happen before we get a chance to set the value.
+ if (print_document_source.Get() != NULL)
+ print_document_source->Abort();
+}
+
+void PrintHandler::OnEnablePrinting(bool printing_enabled) {
+ DCHECK(MessageLoop::current() == thread_->message_loop());
+ base::AutoLock lock(*lock_);
+ printing_enabled_ = printing_enabled;
+ // Don't abort if we are being disabled since we may be finishing a previous
+ // print request which was valid and should be finished. We just need to
+ // prevent any new print requests. And don't assert that we are NOT printing
+ // if we are becoming enabled since we may be finishing a long print while
+ // we got disabled and then enabled again...
+}
+
+void PrintHandler::OnSetPageCount(size_t page_count) {
+ DCHECK(MessageLoop::current() == thread_->message_loop());
+ // No need to protect the access to the static variable,
+ // since it's set/released in this same thread.
+ if (current_document_source_.Get() != NULL)
+ current_document_source_->SetPageCount(page_count);
+}
+
+void PrintHandler::OnAddPage(size_t page_number,
+ mswr::ComPtr<IStream> metafile_stream) {
+ DCHECK(MessageLoop::current() == thread_->message_loop());
+ // No need to protect the access to the static variable,
+ // since it's set/released in this same thread.
+ if (current_document_source_.Get() != NULL)
+ current_document_source_->AddPage(page_number, metafile_stream.Get());
+}
+
+void PrintHandler::OnShowPrintUI() {
+ DCHECK(globals.appview_msg_loop->BelongsToCurrentThread());
+ mswr::ComPtr<wingfx::Printing::IPrintManagerStatic> print_mgr_static;
+ HRESULT hr = winrt_utils::CreateActivationFactory(
+ RuntimeClass_Windows_Graphics_Printing_PrintManager,
+ print_mgr_static.GetAddressOf());
+ if (SUCCEEDED(hr)) {
+ DCHECK(print_mgr_static.Get() != NULL);
+ // Note that passing NULL to ShowPrintUIAsync crashes,
+ // so we need to setup a temp pointer.
+ mswr::ComPtr<winfoundtn::IAsyncOperation<bool>> unused_async_op;
+ hr = print_mgr_static->ShowPrintUIAsync(unused_async_op.GetAddressOf());
+ LOG_IF(ERROR, FAILED(hr)) << "Failed to ShowPrintUIAsync "
+ << std::hex << std::showbase << hr;
+ } else {
+ LOG(ERROR) << "Failed to create PrintManagerStatic "
+ << std::hex << std::showbase << hr;
+ }
+}
+
+} // namespace metro_driver
+
+void MetroEnablePrinting(BOOL printing_enabled) {
+ metro_driver::PrintHandler::EnablePrinting(!!printing_enabled);
+}
+
+void MetroSetPrintPageCount(size_t page_count) {
+ DVLOG(1) << __FUNCTION__ << " Page count: " << page_count;
+ metro_driver::PrintHandler::SetPageCount(page_count);
+}
+
+void MetroSetPrintPageContent(size_t page_number,
+ void* data,
+ size_t data_size) {
+ DVLOG(1) << __FUNCTION__ << " Page number: " << page_number;
+ DCHECK(data != NULL);
+ DCHECK(data_size > 0);
+ mswr::ComPtr<IStream> metafile_stream;
+ HRESULT hr = ::CreateStreamOnHGlobal(
+ NULL, TRUE, metafile_stream.GetAddressOf());
+ if (metafile_stream.Get() != NULL) {
+ ULONG bytes_written = 0;
+ hr = metafile_stream->Write(data, data_size, &bytes_written);
+ LOG_IF(ERROR, FAILED(hr)) << "Failed to Write to Stream " << std::hex << hr;
+ DCHECK(bytes_written == data_size);
+
+ metro_driver::PrintHandler::AddPage(page_number, metafile_stream.Get());
+ } else {
+ NOTREACHED() << "Failed to CreateStreamOnHGlobal " << std::hex << hr;
+ }
+}
+
+void MetroShowPrintUI() {
+ metro_driver::PrintHandler::ShowPrintUI();
+}
« no previous file with comments | « win8/metro_driver/print_handler.h ('k') | win8/metro_driver/run_all_unittests.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698