15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "stdafx.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "win8/metro_driver/print_handler.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.graphics.display.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/safe_numerics.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/app/chrome_command_ids.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "win8/metro_driver/chrome_app_view.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "win8/metro_driver/winrt_utils.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef winfoundtn::ITypedEventHandler<
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wingfx::Printing::PrintManager*,
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wingfx::Printing::PrintTaskRequestedEventArgs*> PrintRequestedHandler;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef winfoundtn::ITypedEventHandler<
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wingfx::Printing::PrintTask*,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wingfx::Printing::PrintTaskCompletedEventArgs*> PrintTaskCompletedHandler;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef winfoundtn::ITypedEventHandler<
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wingfx::Printing::PrintTask*, IInspectable*> PrintTaskInspectableHandler;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef winfoundtn::ITypedEventHandler<
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wingfx::Printing::PrintTask*,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wingfx::Printing::PrintTaskProgressingEventArgs*>
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintTaskProgressingHandler;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace metro_driver {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)mswr::ComPtr<PrintDocumentSource> PrintHandler::current_document_source_;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrintHandler::printing_enabled_ = false;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::Lock* PrintHandler::lock_ = NULL;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::Thread* PrintHandler::thread_ = NULL;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintHandler::PrintHandler() {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(lock_ == NULL);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lock_ = new  base::Lock();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_ == NULL);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_ = new base::Thread("Metro Print Handler");
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_->Start();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrintHandler::~PrintHandler() {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearPrintTask();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(current_document_source_.Get() == NULL);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get all pending tasks to complete cleanly by Stopping the thread.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // They should complete quickly since current_document_source_ is NULL.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_ != NULL);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_->IsRunning());
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_->Stop();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete thread_;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_ = NULL;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(lock_ != NULL);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete lock_;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lock_ = NULL;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT PrintHandler::Initialize(winui::Core::ICoreWindow* window) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register for Print notifications.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mswr::ComPtr<wingfx::Printing::IPrintManagerStatic> print_mgr_static;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = winrt_utils::CreateActivationFactory(
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RuntimeClass_Windows_Graphics_Printing_PrintManager,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      print_mgr_static.GetAddressOf());
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to create PrintManagerStatic " << std::hex << hr;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hr;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mswr::ComPtr<wingfx::Printing::IPrintManager> print_mgr;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = print_mgr_static->GetForCurrentView(&print_mgr);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to get PrintManager for current view " << std::hex
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << hr;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hr;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = print_mgr->add_PrintTaskRequested(
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mswr::Callback<PrintRequestedHandler>(
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this, &PrintHandler::OnPrintRequested).Get(),
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &print_requested_token_);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(ERROR, FAILED(hr)) << "Failed to register PrintTaskRequested "
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            << std::hex << hr;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mswr::ComPtr<wingfx::Display::IDisplayPropertiesStatics> display_properties;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = winrt_utils::CreateActivationFactory(
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RuntimeClass_Windows_Graphics_Display_DisplayProperties,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      display_properties.GetAddressOf());
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to create DisplayPropertiesStatics " << std::hex
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << hr;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hr;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = display_properties->add_LogicalDpiChanged(
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mswr::Callback<
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          wingfx::Display::IDisplayPropertiesEventHandler,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          PrintHandler>(this, &PrintHandler::LogicalDpiChanged).Get(),
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &dpi_change_token_);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(ERROR, FAILED(hr)) << "Failed to register LogicalDpiChanged "
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            << std::hex << hr;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This flag adds support for surfaces with a different color channel
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ordering than the API default. It is recommended usage, and is required
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for compatibility with Direct2D.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UINT creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_DEBUG)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  creation_flags |= D3D11_CREATE_DEVICE_DEBUG;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This array defines the set of DirectX hardware feature levels we support.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The ordering MUST be preserved. All applications are assumed to support
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 9.1 unless otherwise stated by the application, which is not our case.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  D3D_FEATURE_LEVEL feature_levels[] = {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    D3D_FEATURE_LEVEL_11_1,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    D3D_FEATURE_LEVEL_11_0,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    D3D_FEATURE_LEVEL_10_1,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    D3D_FEATURE_LEVEL_10_0,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    D3D_FEATURE_LEVEL_9_3,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    D3D_FEATURE_LEVEL_9_2,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    D3D_FEATURE_LEVEL_9_1 };
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mswr::ComPtr<ID3D11Device> device;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mswr::ComPtr<ID3D11DeviceContext> context;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = D3D11CreateDevice(
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL,  // Specify null to use the default adapter.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      D3D_DRIVER_TYPE_HARDWARE,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0,  // Leave as 0 unless software device.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      creation_flags,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      feature_levels,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ARRAYSIZE(feature_levels),
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      D3D11_SDK_VERSION,  // Must always use this value in Metro apps.
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &device,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL,  // Returns feature level of device created.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &context);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (hr == DXGI_ERROR_UNSUPPORTED) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The hardware is not supported, try a reference driver instead.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hr = D3D11CreateDevice(
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NULL,  // Specify null to use the default adapter.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        D3D_DRIVER_TYPE_REFERENCE,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        0,  // Leave as 0 unless software device.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        creation_flags,
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        feature_levels,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ARRAYSIZE(feature_levels),
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        D3D11_SDK_VERSION,  // Must always use this value in Metro apps.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &device,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NULL,  // Returns feature level of device created.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &context);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to create D3D11 device/context " << std::hex << hr;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hr;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = device.As(&directx_context_.d3d_device);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to QI D3D11 device " << std::hex << hr;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hr;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  D2D1_FACTORY_OPTIONS options;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS));
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_DEBUG)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         __uuidof(ID2D1Factory1),
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         &options,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         &directx_context_.d2d_factory);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to create D2D1 factory " << std::hex << hr;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hr;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mswr::ComPtr<IDXGIDevice> dxgi_device;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = directx_context_.d3d_device.As(&dxgi_device);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to QI for IDXGIDevice " << std::hex << hr;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hr;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = directx_context_.d2d_factory->CreateDevice(
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dxgi_device.Get(), &directx_context_.d2d_device);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to Create D2DDevice " << std::hex << hr;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hr;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = directx_context_.d2d_device->CreateDeviceContext(
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &directx_context_.d2d_context);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to Create D2DDeviceContext " << std::hex << hr;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hr;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = CoCreateInstance(CLSID_WICImagingFactory,
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        NULL,
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        CLSCTX_INPROC_SERVER,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        IID_PPV_ARGS(&directx_context_.wic_factory));
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to CoCreate WICImagingFactory " << std::hex << hr;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hr;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hr;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintHandler::EnablePrinting(bool printing_enabled) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_->message_loop()->PostTask(
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&PrintHandler::OnEnablePrinting, printing_enabled));
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintHandler::SetPageCount(size_t page_count) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_->message_loop()->PostTask(
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&PrintHandler::OnSetPageCount, page_count));
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintHandler::AddPage(size_t page_number, IStream* metafile_stream) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_->message_loop()->PostTask(
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&PrintHandler::OnAddPage,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 page_number,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 mswr::ComPtr<IStream>(metafile_stream)));
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintHandler::ShowPrintUI() {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post the print UI request over to the metro thread.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(globals.appview_msg_loop != NULL);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool posted = globals.appview_msg_loop->PostTask(
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&metro_driver::PrintHandler::OnShowPrintUI));
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(posted);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT PrintHandler::OnPrintRequested(
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wingfx::Printing::IPrintManager* print_mgr,
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wingfx::Printing::IPrintTaskRequestedEventArgs* event_args) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << __FUNCTION__;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = S_OK;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (printing_enabled_) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mswr::ComPtr<wingfx::Printing::IPrintTaskRequest> print_request;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hr = event_args->get_Request(print_request.GetAddressOf());
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FAILED(hr)) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Failed to get the Print Task request " << std::hex << hr;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return hr;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mswrw::HString title;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    title.Attach(MakeHString(L"Printing"));
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hr = print_request->CreatePrintTask(
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        title.Get(),
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mswr::Callback<
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            wingfx::Printing::IPrintTaskSourceRequestedHandler,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PrintHandler>(this, &PrintHandler::OnPrintTaskSourceRequest).Get(),
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print_task_.GetAddressOf());
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FAILED(hr)) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Failed to create the Print Task " << std::hex << hr;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return hr;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hr = print_task_->add_Completed(
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mswr::Callback<PrintTaskCompletedHandler>(
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            this, &PrintHandler::OnCompleted).Get(), &print_completed_token_);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG_IF(ERROR, FAILED(hr)) << "Failed to create the Print Task " << std::hex
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              << hr;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hr;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT PrintHandler::OnPrintTaskSourceRequest(
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wingfx::Printing::IPrintTaskSourceRequestedArgs* args) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << __FUNCTION__;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mswr::ComPtr<PrintDocumentSource> print_document_source;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = mswr::MakeAndInitialize<PrintDocumentSource>(
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &print_document_source, directx_context_, lock_);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to create document source " << std::hex << hr;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hr;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print_document_source->ResetDpi(GetLogicalDpi());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mswr::ComPtr<wingfx::Printing::IPrintDocumentSource> print_source;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = print_document_source.As(&print_source);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to cast document Source " << std::hex << hr;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hr;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = args->SetSource(print_source.Get());
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to set document Source " << std::hex << hr;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hr;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_->message_loop()->PostTask(
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&PrintHandler::SetPrintDocumentSource,
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 print_document_source));
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hr;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT PrintHandler::OnCompleted(
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wingfx::Printing::IPrintTask* task,
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wingfx::Printing::IPrintTaskCompletedEventArgs* args) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << __FUNCTION__;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(globals.appview_msg_loop->BelongsToCurrentThread());
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearPrintTask();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_->message_loop()->PostTask(
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&PrintHandler::ReleasePrintDocumentSource));
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return S_OK;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintHandler::ClearPrintTask() {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!print_task_.Get())
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = print_task_->remove_Completed(print_completed_token_);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(ERROR, FAILED(hr)) << "Failed to remove completed event from Task "
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            << std::hex << hr;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print_task_.Reset();
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)float PrintHandler::GetLogicalDpi() {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mswr::ComPtr<wingfx::Display::IDisplayPropertiesStatics> display_properties;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = winrt_utils::CreateActivationFactory(
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RuntimeClass_Windows_Graphics_Display_DisplayProperties,
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      display_properties.GetAddressOf());
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FAILED(hr)) {
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to get display properties " << std::hex << hr;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0.0;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FLOAT dpi = 0.0;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hr = display_properties->get_LogicalDpi(&dpi);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(ERROR, FAILED(hr)) << "Failed to get Logical DPI " << std::hex << hr;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dpi;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT PrintHandler::LogicalDpiChanged(IInspectable *sender) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << __FUNCTION__;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thread_->message_loop()->PostTask(
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&PrintHandler::OnLogicalDpiChanged, GetLogicalDpi()));
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return S_OK;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintHandler::OnLogicalDpiChanged(float dpi) {
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == thread_->message_loop());
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No need to protect the access to the static variable,
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // since it's set/released in this same thread.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_document_source_.Get() != NULL)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_document_source_->ResetDpi(dpi);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintHandler::SetPrintDocumentSource(
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const mswr::ComPtr<PrintDocumentSource>& print_document_source) {
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == thread_->message_loop());
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(current_document_source_.Get() == NULL);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Protect against the other thread which might try to access it.
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(*lock_);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_document_source_ = print_document_source;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start generating the images to print.
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(mad): Use a registered message with more information about the print
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // request, and at a more appropriate time too, and maybe one page at a time.
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::PostMessageW(globals.host_windows.front().first,
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 WM_SYSCOMMAND,
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 IDC_PRINT_TO_DESTINATION,
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 0);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintHandler::ReleasePrintDocumentSource() {
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == thread_->message_loop());
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mswr::ComPtr<PrintDocumentSource> print_document_source;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Must wait for other thread to be done with the pointer first.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(*lock_);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_document_source_.Swap(print_document_source);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This may happen before we get a chance to set the value.
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (print_document_source.Get() != NULL)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    print_document_source->Abort();
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintHandler::OnEnablePrinting(bool printing_enabled) {
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == thread_->message_loop());
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock lock(*lock_);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printing_enabled_ = printing_enabled;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't abort if we are being disabled since we may be finishing a previous
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // print request which was valid and should be finished. We just need to
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // prevent any new print requests. And don't assert that we are NOT printing
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if we are becoming enabled since we may be finishing a long print while
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we got disabled and then enabled again...
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintHandler::OnSetPageCount(size_t page_count) {
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == thread_->message_loop());
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No need to protect the access to the static variable,
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // since it's set/released in this same thread.
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_document_source_.Get() != NULL)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_document_source_->SetPageCount(page_count);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintHandler::OnAddPage(size_t page_number,
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             mswr::ComPtr<IStream> metafile_stream) {
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == thread_->message_loop());
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No need to protect the access to the static variable,
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // since it's set/released in this same thread.
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_document_source_.Get() != NULL)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_document_source_->AddPage(page_number, metafile_stream.Get());
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintHandler::OnShowPrintUI() {
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(globals.appview_msg_loop->BelongsToCurrentThread());
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mswr::ComPtr<wingfx::Printing::IPrintManagerStatic> print_mgr_static;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = winrt_utils::CreateActivationFactory(
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RuntimeClass_Windows_Graphics_Printing_PrintManager,
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      print_mgr_static.GetAddressOf());
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SUCCEEDED(hr)) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(print_mgr_static.Get() != NULL);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that passing NULL to ShowPrintUIAsync crashes,
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // so we need to setup a temp pointer.
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mswr::ComPtr<winfoundtn::IAsyncOperation<bool>> unused_async_op;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hr = print_mgr_static->ShowPrintUIAsync(unused_async_op.GetAddressOf());
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG_IF(ERROR, FAILED(hr)) << "Failed to ShowPrintUIAsync "
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              << std::hex << std::showbase << hr;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to create PrintManagerStatic "
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << std::hex << std::showbase << hr;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace metro_driver
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MetroEnablePrinting(BOOL printing_enabled) {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  metro_driver::PrintHandler::EnablePrinting(!!printing_enabled);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MetroSetPrintPageCount(size_t page_count) {
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << __FUNCTION__ << " Page count: " << page_count;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  metro_driver::PrintHandler::SetPageCount(page_count);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MetroSetPrintPageContent(size_t page_number,
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              void* data,
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              size_t data_size) {
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << __FUNCTION__ << " Page number: " << page_number;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(data != NULL);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(data_size > 0);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mswr::ComPtr<IStream> metafile_stream;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = ::CreateStreamOnHGlobal(
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL, TRUE, metafile_stream.GetAddressOf());
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (metafile_stream.Get() != NULL) {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ULONG bytes_written = 0;
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hr = metafile_stream->Write(data,
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                base::checked_numeric_cast<ULONG>(data_size),
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                &bytes_written);
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG_IF(ERROR, FAILED(hr)) << "Failed to Write to Stream " << std::hex << hr;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(bytes_written == data_size);
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    metro_driver::PrintHandler::AddPage(page_number, metafile_stream.Get());
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Failed to CreateStreamOnHGlobal " << std::hex << hr;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MetroShowPrintUI() {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  metro_driver::PrintHandler::ShowPrintUI();
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
491