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

Side by Side Diff: win8/metro_driver/print_handler.cc

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