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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "stdafx.h"
6 #include "win8/metro_driver/print_handler.h"
7
8 #include <windows.graphics.display.h>
9
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "chrome/app/chrome_command_ids.h"
13 #include "win8/metro_driver/chrome_app_view.h"
14 #include "win8/metro_driver/winrt_utils.h"
15
16 namespace {
17
18 typedef winfoundtn::ITypedEventHandler<
19 wingfx::Printing::PrintManager*,
20 wingfx::Printing::PrintTaskRequestedEventArgs*> PrintRequestedHandler;
21
22 typedef winfoundtn::ITypedEventHandler<
23 wingfx::Printing::PrintTask*,
24 wingfx::Printing::PrintTaskCompletedEventArgs*> PrintTaskCompletedHandler;
25
26 typedef winfoundtn::ITypedEventHandler<
27 wingfx::Printing::PrintTask*, IInspectable*> PrintTaskInspectableHandler;
28
29 typedef winfoundtn::ITypedEventHandler<
30 wingfx::Printing::PrintTask*,
31 wingfx::Printing::PrintTaskProgressingEventArgs*>
32 PrintTaskProgressingHandler;
33
34 } // namespace
35
36 namespace metro_driver {
37
38 mswr::ComPtr<PrintDocumentSource> PrintHandler::current_document_source_;
39 bool PrintHandler::printing_enabled_ = false;
40 base::Lock* PrintHandler::lock_ = NULL;
41 base::Thread* PrintHandler::thread_ = NULL;
42
43 PrintHandler::PrintHandler() {
44 DCHECK(lock_ == NULL);
45 lock_ = new base::Lock();
46
47 DCHECK(thread_ == NULL);
48 thread_ = new base::Thread("Metro Print Handler");
49 thread_->Start();
50 }
51
52 PrintHandler::~PrintHandler() {
53 ClearPrintTask();
54 DCHECK(current_document_source_.Get() == NULL);
55
56 // Get all pending tasks to complete cleanly by Stopping the thread.
57 // They should complete quickly since current_document_source_ is NULL.
58 DCHECK(thread_ != NULL);
59 DCHECK(thread_->IsRunning());
60 thread_->Stop();
61 delete thread_;
62 thread_ = NULL;
63
64 DCHECK(lock_ != NULL);
65 delete lock_;
66 lock_ = NULL;
67 }
68
69 HRESULT PrintHandler::Initialize(winui::Core::ICoreWindow* window) {
70 // Register for Print notifications.
71 mswr::ComPtr<wingfx::Printing::IPrintManagerStatic> print_mgr_static;
72 HRESULT hr = winrt_utils::CreateActivationFactory(
73 RuntimeClass_Windows_Graphics_Printing_PrintManager,
74 print_mgr_static.GetAddressOf());
75 if (FAILED(hr)) {
76 LOG(ERROR) << "Failed to create PrintManagerStatic " << std::hex << hr;
77 return hr;
78 }
79
80 mswr::ComPtr<wingfx::Printing::IPrintManager> print_mgr;
81 hr = print_mgr_static->GetForCurrentView(&print_mgr);
82 if (FAILED(hr)) {
83 LOG(ERROR) << "Failed to get PrintManager for current view " << std::hex
84 << hr;
85 return hr;
86 }
87
88 hr = print_mgr->add_PrintTaskRequested(
89 mswr::Callback<PrintRequestedHandler>(
90 this, &PrintHandler::OnPrintRequested).Get(),
91 &print_requested_token_);
92 LOG_IF(ERROR, FAILED(hr)) << "Failed to register PrintTaskRequested "
93 << std::hex << hr;
94
95 mswr::ComPtr<wingfx::Display::IDisplayPropertiesStatics> display_properties;
96 hr = winrt_utils::CreateActivationFactory(
97 RuntimeClass_Windows_Graphics_Display_DisplayProperties,
98 display_properties.GetAddressOf());
99 if (FAILED(hr)) {
100 LOG(ERROR) << "Failed to create DisplayPropertiesStatics " << std::hex
101 << hr;
102 return hr;
103 }
104
105 hr = display_properties->add_LogicalDpiChanged(
106 mswr::Callback<
107 wingfx::Display::IDisplayPropertiesEventHandler,
108 PrintHandler>(this, &PrintHandler::LogicalDpiChanged).Get(),
109 &dpi_change_token_);
110 LOG_IF(ERROR, FAILED(hr)) << "Failed to register LogicalDpiChanged "
111 << std::hex << hr;
112
113 // This flag adds support for surfaces with a different color channel
114 // ordering than the API default. It is recommended usage, and is required
115 // for compatibility with Direct2D.
116 UINT creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
117 #if defined(_DEBUG)
118 creation_flags |= D3D11_CREATE_DEVICE_DEBUG;
119 #endif
120
121 // This array defines the set of DirectX hardware feature levels we support.
122 // The ordering MUST be preserved. All applications are assumed to support
123 // 9.1 unless otherwise stated by the application, which is not our case.
124 D3D_FEATURE_LEVEL feature_levels[] = {
125 D3D_FEATURE_LEVEL_11_1,
126 D3D_FEATURE_LEVEL_11_0,
127 D3D_FEATURE_LEVEL_10_1,
128 D3D_FEATURE_LEVEL_10_0,
129 D3D_FEATURE_LEVEL_9_3,
130 D3D_FEATURE_LEVEL_9_2,
131 D3D_FEATURE_LEVEL_9_1 };
132
133 mswr::ComPtr<ID3D11Device> device;
134 mswr::ComPtr<ID3D11DeviceContext> context;
135 hr = D3D11CreateDevice(
136 NULL, // Specify null to use the default adapter.
137 D3D_DRIVER_TYPE_HARDWARE,
138 0, // Leave as 0 unless software device.
139 creation_flags,
140 feature_levels,
141 ARRAYSIZE(feature_levels),
142 D3D11_SDK_VERSION, // Must always use this value in Metro apps.
143 &device,
144 NULL, // Returns feature level of device created.
145 &context);
146 if (hr == DXGI_ERROR_UNSUPPORTED) {
147 // The hardware is not supported, try a reference driver instead.
148 hr = D3D11CreateDevice(
149 NULL, // Specify null to use the default adapter.
150 D3D_DRIVER_TYPE_REFERENCE,
151 0, // Leave as 0 unless software device.
152 creation_flags,
153 feature_levels,
154 ARRAYSIZE(feature_levels),
155 D3D11_SDK_VERSION, // Must always use this value in Metro apps.
156 &device,
157 NULL, // Returns feature level of device created.
158 &context);
159 }
160 if (FAILED(hr)) {
161 LOG(ERROR) << "Failed to create D3D11 device/context " << std::hex << hr;
162 return hr;
163 }
164
165 hr = device.As(&directx_context_.d3d_device);
166 if (FAILED(hr)) {
167 LOG(ERROR) << "Failed to QI D3D11 device " << std::hex << hr;
168 return hr;
169 }
170
171 D2D1_FACTORY_OPTIONS options;
172 ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS));
173
174 #if defined(_DEBUG)
175 options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
176 #endif
177
178 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED,
179 __uuidof(ID2D1Factory1),
180 &options,
181 &directx_context_.d2d_factory);
182 if (FAILED(hr)) {
183 LOG(ERROR) << "Failed to create D2D1 factory " << std::hex << hr;
184 return hr;
185 }
186
187 mswr::ComPtr<IDXGIDevice> dxgi_device;
188 hr = directx_context_.d3d_device.As(&dxgi_device);
189 if (FAILED(hr)) {
190 LOG(ERROR) << "Failed to QI for IDXGIDevice " << std::hex << hr;
191 return hr;
192 }
193
194 hr = directx_context_.d2d_factory->CreateDevice(
195 dxgi_device.Get(), &directx_context_.d2d_device);
196 if (FAILED(hr)) {
197 LOG(ERROR) << "Failed to Create D2DDevice " << std::hex << hr;
198 return hr;
199 }
200
201 hr = directx_context_.d2d_device->CreateDeviceContext(
202 D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
203 &directx_context_.d2d_context);
204 if (FAILED(hr)) {
205 LOG(ERROR) << "Failed to Create D2DDeviceContext " << std::hex << hr;
206 return hr;
207 }
208
209 hr = CoCreateInstance(CLSID_WICImagingFactory,
210 NULL,
211 CLSCTX_INPROC_SERVER,
212 IID_PPV_ARGS(&directx_context_.wic_factory));
213 if (FAILED(hr)) {
214 LOG(ERROR) << "Failed to CoCreate WICImagingFactory " << std::hex << hr;
215 return hr;
216 }
217 return hr;
218 }
219
220 void PrintHandler::EnablePrinting(bool printing_enabled) {
221 thread_->message_loop()->PostTask(
222 FROM_HERE,
223 base::Bind(&PrintHandler::OnEnablePrinting, printing_enabled));
224 }
225
226 void PrintHandler::SetPageCount(size_t page_count) {
227 thread_->message_loop()->PostTask(
228 FROM_HERE,
229 base::Bind(&PrintHandler::OnSetPageCount, page_count));
230 }
231
232 void PrintHandler::AddPage(size_t page_number, IStream* metafile_stream) {
233 thread_->message_loop()->PostTask(
234 FROM_HERE,
235 base::Bind(&PrintHandler::OnAddPage,
236 page_number,
237 mswr::ComPtr<IStream>(metafile_stream)));
238 }
239
240 void PrintHandler::ShowPrintUI() {
241 // Post the print UI request over to the metro thread.
242 DCHECK(globals.appview_msg_loop != NULL);
243 bool posted = globals.appview_msg_loop->PostTask(
244 FROM_HERE, base::Bind(&metro_driver::PrintHandler::OnShowPrintUI));
245 DCHECK(posted);
246 }
247
248 HRESULT PrintHandler::OnPrintRequested(
249 wingfx::Printing::IPrintManager* print_mgr,
250 wingfx::Printing::IPrintTaskRequestedEventArgs* event_args) {
251 DVLOG(1) << __FUNCTION__;
252
253 HRESULT hr = S_OK;
254 if (printing_enabled_) {
255 mswr::ComPtr<wingfx::Printing::IPrintTaskRequest> print_request;
256 hr = event_args->get_Request(print_request.GetAddressOf());
257 if (FAILED(hr)) {
258 LOG(ERROR) << "Failed to get the Print Task request " << std::hex << hr;
259 return hr;
260 }
261
262 mswrw::HString title;
263 title.Attach(MakeHString(L"Printing"));
264 hr = print_request->CreatePrintTask(
265 title.Get(),
266 mswr::Callback<
267 wingfx::Printing::IPrintTaskSourceRequestedHandler,
268 PrintHandler>(this, &PrintHandler::OnPrintTaskSourceRequest).Get(),
269 print_task_.GetAddressOf());
270 if (FAILED(hr)) {
271 LOG(ERROR) << "Failed to create the Print Task " << std::hex << hr;
272 return hr;
273 }
274
275 hr = print_task_->add_Completed(
276 mswr::Callback<PrintTaskCompletedHandler>(
277 this, &PrintHandler::OnCompleted).Get(), &print_completed_token_);
278 LOG_IF(ERROR, FAILED(hr)) << "Failed to create the Print Task " << std::hex
279 << hr;
280 }
281 return hr;
282 }
283
284 HRESULT PrintHandler::OnPrintTaskSourceRequest(
285 wingfx::Printing::IPrintTaskSourceRequestedArgs* args) {
286 DVLOG(1) << __FUNCTION__;
287 mswr::ComPtr<PrintDocumentSource> print_document_source;
288 HRESULT hr = mswr::MakeAndInitialize<PrintDocumentSource>(
289 &print_document_source, directx_context_, lock_);
290 if (FAILED(hr)) {
291 LOG(ERROR) << "Failed to create document source " << std::hex << hr;
292 return hr;
293 }
294
295 print_document_source->ResetDpi(GetLogicalDpi());
296
297 mswr::ComPtr<wingfx::Printing::IPrintDocumentSource> print_source;
298 hr = print_document_source.As(&print_source);
299 if (FAILED(hr)) {
300 LOG(ERROR) << "Failed to cast document Source " << std::hex << hr;
301 return hr;
302 }
303
304 hr = args->SetSource(print_source.Get());
305 if (FAILED(hr)) {
306 LOG(ERROR) << "Failed to set document Source " << std::hex << hr;
307 return hr;
308 }
309
310 thread_->message_loop()->PostTask(
311 FROM_HERE,
312 base::Bind(&PrintHandler::SetPrintDocumentSource,
313 print_document_source));
314
315 return hr;
316 }
317
318 HRESULT PrintHandler::OnCompleted(
319 wingfx::Printing::IPrintTask* task,
320 wingfx::Printing::IPrintTaskCompletedEventArgs* args) {
321 DVLOG(1) << __FUNCTION__;
322 DCHECK(globals.appview_msg_loop->BelongsToCurrentThread());
323 ClearPrintTask();
324 thread_->message_loop()->PostTask(
325 FROM_HERE,
326 base::Bind(&PrintHandler::ReleasePrintDocumentSource));
327
328 return S_OK;
329 }
330
331 void PrintHandler::ClearPrintTask() {
332 if (!print_task_.Get())
333 return;
334
335 HRESULT hr = print_task_->remove_Completed(print_completed_token_);
336 LOG_IF(ERROR, FAILED(hr)) << "Failed to remove completed event from Task "
337 << std::hex << hr;
338 print_task_.Reset();
339 }
340
341 float PrintHandler::GetLogicalDpi() {
342 mswr::ComPtr<wingfx::Display::IDisplayPropertiesStatics> display_properties;
343 HRESULT hr = winrt_utils::CreateActivationFactory(
344 RuntimeClass_Windows_Graphics_Display_DisplayProperties,
345 display_properties.GetAddressOf());
346 if (FAILED(hr)) {
347 LOG(ERROR) << "Failed to get display properties " << std::hex << hr;
348 return 0.0;
349 }
350
351 FLOAT dpi = 0.0;
352 hr = display_properties->get_LogicalDpi(&dpi);
353 LOG_IF(ERROR, FAILED(hr)) << "Failed to get Logical DPI " << std::hex << hr;
354
355 return dpi;
356 }
357
358 HRESULT PrintHandler::LogicalDpiChanged(IInspectable *sender) {
359 DVLOG(1) << __FUNCTION__;
360 thread_->message_loop()->PostTask(
361 FROM_HERE,
362 base::Bind(&PrintHandler::OnLogicalDpiChanged, GetLogicalDpi()));
363 return S_OK;
364 }
365
366 void PrintHandler::OnLogicalDpiChanged(float dpi) {
367 DCHECK(MessageLoop::current() == thread_->message_loop());
368 // No need to protect the access to the static variable,
369 // since it's set/released in this same thread.
370 if (current_document_source_.Get() != NULL)
371 current_document_source_->ResetDpi(dpi);
372 }
373
374 void PrintHandler::SetPrintDocumentSource(
375 const mswr::ComPtr<PrintDocumentSource>& print_document_source) {
376 DCHECK(MessageLoop::current() == thread_->message_loop());
377 DCHECK(current_document_source_.Get() == NULL);
378 {
379 // Protect against the other thread which might try to access it.
380 base::AutoLock lock(*lock_);
381 current_document_source_ = print_document_source;
382 }
383 // Start generating the images to print.
384 // TODO(mad): Use a registered message with more information about the print
385 // request, and at a more appropriate time too, and maybe one page at a time.
386 ::PostMessageW(globals.host_windows.front().first,
387 WM_SYSCOMMAND,
388 IDC_PRINT_TO_DESTINATION,
389 0);
390 }
391
392 void PrintHandler::ReleasePrintDocumentSource() {
393 DCHECK(MessageLoop::current() == thread_->message_loop());
394 mswr::ComPtr<PrintDocumentSource> print_document_source;
395 {
396 // Must wait for other thread to be done with the pointer first.
397 base::AutoLock lock(*lock_);
398 current_document_source_.Swap(print_document_source);
399 }
400 // This may happen before we get a chance to set the value.
401 if (print_document_source.Get() != NULL)
402 print_document_source->Abort();
403 }
404
405 void PrintHandler::OnEnablePrinting(bool printing_enabled) {
406 DCHECK(MessageLoop::current() == thread_->message_loop());
407 base::AutoLock lock(*lock_);
408 printing_enabled_ = printing_enabled;
409 // Don't abort if we are being disabled since we may be finishing a previous
410 // print request which was valid and should be finished. We just need to
411 // prevent any new print requests. And don't assert that we are NOT printing
412 // if we are becoming enabled since we may be finishing a long print while
413 // we got disabled and then enabled again...
414 }
415
416 void PrintHandler::OnSetPageCount(size_t page_count) {
417 DCHECK(MessageLoop::current() == thread_->message_loop());
418 // No need to protect the access to the static variable,
419 // since it's set/released in this same thread.
420 if (current_document_source_.Get() != NULL)
421 current_document_source_->SetPageCount(page_count);
422 }
423
424 void PrintHandler::OnAddPage(size_t page_number,
425 mswr::ComPtr<IStream> metafile_stream) {
426 DCHECK(MessageLoop::current() == thread_->message_loop());
427 // No need to protect the access to the static variable,
428 // since it's set/released in this same thread.
429 if (current_document_source_.Get() != NULL)
430 current_document_source_->AddPage(page_number, metafile_stream.Get());
431 }
432
433 void PrintHandler::OnShowPrintUI() {
434 DCHECK(globals.appview_msg_loop->BelongsToCurrentThread());
435 mswr::ComPtr<wingfx::Printing::IPrintManagerStatic> print_mgr_static;
436 HRESULT hr = winrt_utils::CreateActivationFactory(
437 RuntimeClass_Windows_Graphics_Printing_PrintManager,
438 print_mgr_static.GetAddressOf());
439 if (SUCCEEDED(hr)) {
440 DCHECK(print_mgr_static.Get() != NULL);
441 // Note that passing NULL to ShowPrintUIAsync crashes,
442 // so we need to setup a temp pointer.
443 mswr::ComPtr<winfoundtn::IAsyncOperation<bool>> unused_async_op;
444 hr = print_mgr_static->ShowPrintUIAsync(unused_async_op.GetAddressOf());
445 LOG_IF(ERROR, FAILED(hr)) << "Failed to ShowPrintUIAsync "
446 << std::hex << std::showbase << hr;
447 } else {
448 LOG(ERROR) << "Failed to create PrintManagerStatic "
449 << std::hex << std::showbase << hr;
450 }
451 }
452
453 } // namespace metro_driver
454
455 void MetroEnablePrinting(BOOL printing_enabled) {
456 metro_driver::PrintHandler::EnablePrinting(!!printing_enabled);
457 }
458
459 void MetroSetPrintPageCount(size_t page_count) {
460 DVLOG(1) << __FUNCTION__ << " Page count: " << page_count;
461 metro_driver::PrintHandler::SetPageCount(page_count);
462 }
463
464 void MetroSetPrintPageContent(size_t page_number,
465 void* data,
466 size_t data_size) {
467 DVLOG(1) << __FUNCTION__ << " Page number: " << page_number;
468 DCHECK(data != NULL);
469 DCHECK(data_size > 0);
470 mswr::ComPtr<IStream> metafile_stream;
471 HRESULT hr = ::CreateStreamOnHGlobal(
472 NULL, TRUE, metafile_stream.GetAddressOf());
473 if (metafile_stream.Get() != NULL) {
474 ULONG bytes_written = 0;
475 hr = metafile_stream->Write(data, data_size, &bytes_written);
476 LOG_IF(ERROR, FAILED(hr)) << "Failed to Write to Stream " << std::hex << hr;
477 DCHECK(bytes_written == data_size);
478
479 metro_driver::PrintHandler::AddPage(page_number, metafile_stream.Get());
480 } else {
481 NOTREACHED() << "Failed to CreateStreamOnHGlobal " << std::hex << hr;
482 }
483 }
484
485 void MetroShowPrintUI() {
486 metro_driver::PrintHandler::ShowPrintUI();
487 }
OLDNEW
« 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