Cronet: Remove redundant success checks and waits in tests.
[chromium-blink-merge.git] / ui / gfx / win / window_impl.cc
blobb0c4fa7ad34349c7e10bb7a5663d13287ee65cec
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.
5 #include "ui/gfx/win/window_impl.h"
7 #include <list>
9 #include "base/bind.h"
10 #include "base/debug/alias.h"
11 #include "base/memory/singleton.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/synchronization/lock.h"
14 #include "base/win/wrapped_window_proc.h"
15 #include "ui/gfx/win/hwnd_util.h"
17 namespace gfx {
19 static const DWORD kWindowDefaultChildStyle =
20 WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
21 static const DWORD kWindowDefaultStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
22 static const DWORD kWindowDefaultExStyle = 0;
24 ///////////////////////////////////////////////////////////////////////////////
25 // WindowImpl class tracking.
27 // Several external scripts rely explicitly on this base class name for
28 // acquiring the window handle and will break if this is modified!
29 // static
30 const wchar_t* const WindowImpl::kBaseClassName = L"Chrome_WidgetWin_";
32 // WindowImpl class information used for registering unique windows.
33 struct ClassInfo {
34 UINT style;
35 HICON icon;
37 ClassInfo(int style, HICON icon)
38 : style(style),
39 icon(icon) {}
41 // Compares two ClassInfos. Returns true if all members match.
42 bool Equals(const ClassInfo& other) const {
43 return (other.style == style && other.icon == icon);
47 // WARNING: this class may be used on multiple threads.
48 class ClassRegistrar {
49 public:
50 ~ClassRegistrar();
52 static ClassRegistrar* GetInstance();
54 void UnregisterClasses();
56 // Returns the atom identifying the class matching |class_info|,
57 // creating and registering a new class if the class is not yet known.
58 ATOM RetrieveClassAtom(const ClassInfo& class_info);
60 private:
61 // Represents a registered window class.
62 struct RegisteredClass {
63 RegisteredClass(const ClassInfo& info,
64 const base::string16& name,
65 ATOM atom,
66 HINSTANCE instance);
68 // Info used to create the class.
69 ClassInfo info;
71 // The name given to the window class
72 base::string16 name;
74 // The atom identifying the window class.
75 ATOM atom;
77 // The handle of the module containing the window proceedure.
78 HMODULE instance;
81 ClassRegistrar();
82 friend struct DefaultSingletonTraits<ClassRegistrar>;
84 typedef std::list<RegisteredClass> RegisteredClasses;
85 RegisteredClasses registered_classes_;
87 // Counter of how many classes have been registered so far.
88 int registered_count_;
90 base::Lock lock_;
92 DISALLOW_COPY_AND_ASSIGN(ClassRegistrar);
95 ClassRegistrar::~ClassRegistrar() {}
97 // static
98 ClassRegistrar* ClassRegistrar::GetInstance() {
99 return Singleton<ClassRegistrar,
100 LeakySingletonTraits<ClassRegistrar> >::get();
103 void ClassRegistrar::UnregisterClasses() {
104 for (RegisteredClasses::iterator i = registered_classes_.begin();
105 i != registered_classes_.end(); ++i) {
106 if (UnregisterClass(MAKEINTATOM(i->atom), i->instance)) {
107 registered_classes_.erase(i);
108 } else {
109 LOG(ERROR) << "Failed to unregister class " << i->name
110 << ". Error = " << GetLastError();
115 ATOM ClassRegistrar::RetrieveClassAtom(const ClassInfo& class_info) {
116 base::AutoLock auto_lock(lock_);
117 for (RegisteredClasses::const_iterator i = registered_classes_.begin();
118 i != registered_classes_.end(); ++i) {
119 if (class_info.Equals(i->info))
120 return i->atom;
123 // No class found, need to register one.
124 base::string16 name = base::string16(WindowImpl::kBaseClassName) +
125 base::IntToString16(registered_count_++);
127 WNDCLASSEX window_class;
128 base::win::InitializeWindowClass(
129 name.c_str(),
130 &base::win::WrappedWindowProc<WindowImpl::WndProc>,
131 class_info.style,
134 NULL,
135 reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)),
136 NULL,
137 class_info.icon,
138 class_info.icon,
139 &window_class);
140 HMODULE instance = window_class.hInstance;
141 ATOM atom = RegisterClassEx(&window_class);
142 CHECK(atom) << GetLastError();
144 registered_classes_.push_back(RegisteredClass(
145 class_info, name, atom, instance));
147 return atom;
150 ClassRegistrar::RegisteredClass::RegisteredClass(const ClassInfo& info,
151 const base::string16& name,
152 ATOM atom,
153 HMODULE instance)
154 : info(info),
155 name(name),
156 atom(atom),
157 instance(instance) {}
159 ClassRegistrar::ClassRegistrar() : registered_count_(0) {}
162 ///////////////////////////////////////////////////////////////////////////////
163 // WindowImpl, public
165 WindowImpl::WindowImpl()
166 : window_style_(0),
167 window_ex_style_(kWindowDefaultExStyle),
168 class_style_(CS_DBLCLKS),
169 hwnd_(NULL),
170 got_create_(false),
171 got_valid_hwnd_(false),
172 destroyed_(NULL) {
175 WindowImpl::~WindowImpl() {
176 if (destroyed_)
177 *destroyed_ = true;
178 ClearUserData();
181 // static
182 void WindowImpl::UnregisterClassesAtExit() {
183 base::AtExitManager::RegisterTask(
184 base::Bind(&ClassRegistrar::UnregisterClasses,
185 base::Unretained(ClassRegistrar::GetInstance())));
188 void WindowImpl::Init(HWND parent, const Rect& bounds) {
189 if (window_style_ == 0)
190 window_style_ = parent ? kWindowDefaultChildStyle : kWindowDefaultStyle;
192 if (parent == HWND_DESKTOP) {
193 // Only non-child windows can have HWND_DESKTOP (0) as their parent.
194 CHECK((window_style_ & WS_CHILD) == 0);
195 parent = GetWindowToParentTo(false);
196 } else if (parent == ::GetDesktopWindow()) {
197 // Any type of window can have the "Desktop Window" as their parent.
198 parent = GetWindowToParentTo(true);
199 } else if (parent != HWND_MESSAGE) {
200 CHECK(::IsWindow(parent));
203 int x, y, width, height;
204 if (bounds.IsEmpty()) {
205 x = y = width = height = CW_USEDEFAULT;
206 } else {
207 x = bounds.x();
208 y = bounds.y();
209 width = bounds.width();
210 height = bounds.height();
213 ATOM atom = GetWindowClassAtom();
214 bool destroyed = false;
215 destroyed_ = &destroyed;
216 HWND hwnd = CreateWindowEx(window_ex_style_,
217 reinterpret_cast<wchar_t*>(atom), NULL,
218 window_style_, x, y, width, height,
219 parent, NULL, NULL, this);
221 // First nccalcszie (during CreateWindow) for captioned windows is
222 // deliberately ignored so force a second one here to get the right
223 // non-client set up.
224 if (hwnd && (window_style_ & WS_CAPTION)) {
225 SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
226 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE |
227 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW);
230 if (!hwnd_ && GetLastError() == 0) {
231 base::debug::Alias(&destroyed);
232 base::debug::Alias(&hwnd);
233 bool got_create = got_create_;
234 base::debug::Alias(&got_create);
235 bool got_valid_hwnd = got_valid_hwnd_;
236 base::debug::Alias(&got_valid_hwnd);
237 WNDCLASSEX class_info;
238 memset(&class_info, 0, sizeof(WNDCLASSEX));
239 class_info.cbSize = sizeof(WNDCLASSEX);
240 BOOL got_class = GetClassInfoEx(GetModuleHandle(NULL),
241 reinterpret_cast<wchar_t*>(atom),
242 &class_info);
243 base::debug::Alias(&got_class);
244 bool procs_match = got_class && class_info.lpfnWndProc ==
245 base::win::WrappedWindowProc<&WindowImpl::WndProc>;
246 base::debug::Alias(&procs_match);
247 CHECK(false);
249 if (!destroyed)
250 destroyed_ = NULL;
252 CheckWindowCreated(hwnd_);
254 // The window procedure should have set the data for us.
255 CHECK_EQ(this, GetWindowUserData(hwnd));
258 HICON WindowImpl::GetDefaultWindowIcon() const {
259 return NULL;
262 LRESULT WindowImpl::OnWndProc(UINT message, WPARAM w_param, LPARAM l_param) {
263 LRESULT result = 0;
265 HWND hwnd = hwnd_;
266 if (message == WM_NCDESTROY)
267 hwnd_ = NULL;
269 // Handle the message if it's in our message map; otherwise, let the system
270 // handle it.
271 if (!ProcessWindowMessage(hwnd, message, w_param, l_param, result))
272 result = DefWindowProc(hwnd, message, w_param, l_param);
274 return result;
277 void WindowImpl::ClearUserData() {
278 if (::IsWindow(hwnd_))
279 gfx::SetWindowUserData(hwnd_, NULL);
282 // static
283 LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd,
284 UINT message,
285 WPARAM w_param,
286 LPARAM l_param) {
287 if (message == WM_NCCREATE) {
288 CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(l_param);
289 WindowImpl* window = reinterpret_cast<WindowImpl*>(cs->lpCreateParams);
290 DCHECK(window);
291 gfx::SetWindowUserData(hwnd, window);
292 window->hwnd_ = hwnd;
293 window->got_create_ = true;
294 if (hwnd)
295 window->got_valid_hwnd_ = true;
296 return TRUE;
299 WindowImpl* window = reinterpret_cast<WindowImpl*>(GetWindowUserData(hwnd));
300 if (!window)
301 return 0;
303 return window->OnWndProc(message, w_param, l_param);
306 ATOM WindowImpl::GetWindowClassAtom() {
307 HICON icon = GetDefaultWindowIcon();
308 ClassInfo class_info(initial_class_style(), icon);
309 return ClassRegistrar::GetInstance()->RetrieveClassAtom(class_info);
312 } // namespace gfx