OLD | NEW |
---|---|
(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 "ui/gfx/screen_compatible_dc_win.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/memory/singleton.h" | |
9 #include "base/win/wrapped_window_proc.h" | |
10 | |
11 namespace { | |
12 | |
13 // Windows class name to use for the listener window. | |
14 const wchar_t kWindowClassName[] = L"CachedCompatibleDC_Invalidator"; | |
15 | |
16 class CachedCompatibleDC { | |
17 public: | |
18 // Singleton getter. | |
19 static CachedCompatibleDC* GetInstance(); | |
20 | |
21 // Returns the cached screen compatible DC or creates one if needed. | |
22 HDC GetOrCreateCompatibleDC(); | |
23 | |
24 // Deletes the cached DC, called on WM_DISPLAYCHANGE notifications. | |
25 void DeleteCachedCompatibleDC(); | |
26 | |
27 private: | |
28 // Cached device context compatible with the screen. | |
29 HDC compatible_dc_; | |
30 | |
31 // HWND for listening to WM_DISPLAYCHANGE notifications. | |
32 HWND listener_window_; | |
33 | |
34 CachedCompatibleDC(); | |
35 ~CachedCompatibleDC(); | |
36 | |
37 friend struct DefaultSingletonTraits<CachedCompatibleDC>; | |
38 | |
39 DISALLOW_COPY_AND_ASSIGN(CachedCompatibleDC); | |
40 }; | |
41 | |
42 // Windows callback for listening for WM_DISPLAYCHANGE messages. | |
43 LRESULT CALLBACK ListenerWindowProc(HWND hwnd, UINT message, | |
sky
2012/02/03 23:14:42
nit: each param on its own line.
Alexei Svitkine (slow)
2012/02/06 14:37:38
Done.
| |
44 WPARAM wparam, LPARAM lparam) { | |
45 if (message == WM_DISPLAYCHANGE) | |
46 CachedCompatibleDC::GetInstance()->DeleteCachedCompatibleDC(); | |
47 | |
48 return ::DefWindowProc(hwnd, message, wparam, lparam); | |
49 } | |
50 | |
51 // Creates a listener window to handle WM_DISPLAYCHANGE messages. | |
52 HWND CreateListenerWindow() { | |
53 HINSTANCE hinst = 0; | |
54 if (!::GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, | |
55 reinterpret_cast<char*>(&ListenerWindowProc), | |
56 &hinst)) { | |
57 NOTREACHED(); | |
58 } | |
59 | |
60 WNDCLASSEX wc = {0}; | |
61 wc.cbSize = sizeof(wc); | |
62 wc.lpfnWndProc = base::win::WrappedWindowProc<ListenerWindowProc>; | |
63 wc.hInstance = hinst; | |
64 wc.lpszClassName = kWindowClassName; | |
65 ATOM clazz = ::RegisterClassEx(&wc); | |
66 DCHECK(clazz); | |
67 | |
68 return ::CreateWindow(MAKEINTATOM(clazz), 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, | |
69 hinst, 0); | |
70 } | |
71 | |
72 CachedCompatibleDC::CachedCompatibleDC() | |
73 : compatible_dc_(NULL), | |
74 listener_window_(NULL) { | |
75 } | |
76 | |
77 CachedCompatibleDC::~CachedCompatibleDC() { | |
78 DeleteCachedCompatibleDC(); | |
79 if (listener_window_) { | |
80 ::DestroyWindow(listener_window_); | |
81 ::UnregisterClass(kWindowClassName, GetModuleHandle(NULL)); | |
82 } | |
83 } | |
84 | |
85 // static | |
86 CachedCompatibleDC* CachedCompatibleDC::GetInstance() { | |
87 return Singleton<CachedCompatibleDC>::get(); | |
88 } | |
89 | |
90 HDC CachedCompatibleDC::GetOrCreateCompatibleDC() { | |
91 if (!compatible_dc_) { | |
92 compatible_dc_ = ::CreateCompatibleDC(NULL); | |
93 if (!listener_window_) { | |
94 listener_window_ = CreateListenerWindow(); | |
95 DCHECK(listener_window_); | |
sky
2012/02/03 23:14:42
ui::CheckWindowCreated
Alexei Svitkine (slow)
2012/02/06 14:37:38
Done.
| |
96 } | |
97 } | |
98 return compatible_dc_; | |
99 } | |
100 | |
101 void CachedCompatibleDC::DeleteCachedCompatibleDC() { | |
102 if (compatible_dc_) { | |
103 ::DeleteDC(compatible_dc_); | |
104 compatible_dc_ = NULL; | |
105 } | |
106 } | |
107 | |
108 } // namespace | |
109 | |
110 namespace gfx { | |
111 | |
112 ScopedTemporaryScreenCompatibleDC::ScopedTemporaryScreenCompatibleDC() | |
113 : hdc_(CachedCompatibleDC::GetInstance()->GetOrCreateCompatibleDC()) { | |
114 } | |
115 | |
116 ScopedTemporaryScreenCompatibleDC::~ScopedTemporaryScreenCompatibleDC() { | |
117 } | |
118 | |
119 } // namespace gfx | |
OLD | NEW |