[SyncFS] Build indexes from FileTracker entries on disk.
[chromium-blink-merge.git] / ui / gfx / win / window_impl.cc
blobff9fe57cf9dd8e5a2e21a6ea270c8c995e276084
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/debug/alias.h"
10 #include "base/memory/singleton.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/synchronization/lock.h"
13 #include "base/win/wrapped_window_proc.h"
14 #include "ui/gfx/win/hwnd_util.h"
16 namespace gfx {
18 static const DWORD kWindowDefaultChildStyle =
19 WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
20 static const DWORD kWindowDefaultStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
21 static const DWORD kWindowDefaultExStyle = 0;
23 ///////////////////////////////////////////////////////////////////////////////
24 // WindowImpl class tracking.
26 // Several external scripts rely explicitly on this base class name for
27 // acquiring the window handle and will break if this is modified!
28 // static
29 const wchar_t* const WindowImpl::kBaseClassName = L"Chrome_WidgetWin_";
31 // WindowImpl class information used for registering unique windows.
32 struct ClassInfo {
33 UINT style;
34 HICON icon;
36 ClassInfo(int style, HICON icon)
37 : style(style),
38 icon(icon) {}
40 // Compares two ClassInfos. Returns true if all members match.
41 bool Equals(const ClassInfo& other) const {
42 return (other.style == style && other.icon == icon);
46 // WARNING: this class may be used on multiple threads.
47 class ClassRegistrar {
48 public:
49 ~ClassRegistrar();
51 static ClassRegistrar* GetInstance();
53 // Returns the atom identifying the class matching |class_info|,
54 // creating and registering a new class if the class is not yet known.
55 ATOM RetrieveClassAtom(const ClassInfo& class_info);
57 private:
58 // Represents a registered window class.
59 struct RegisteredClass {
60 RegisteredClass(const ClassInfo& info, ATOM atom);
62 // Info used to create the class.
63 ClassInfo info;
65 // The atom identifying the window class.
66 ATOM atom;
69 ClassRegistrar();
70 friend struct DefaultSingletonTraits<ClassRegistrar>;
72 typedef std::list<RegisteredClass> RegisteredClasses;
73 RegisteredClasses registered_classes_;
75 // Counter of how many classes have been registered so far.
76 int registered_count_;
78 base::Lock lock_;
80 DISALLOW_COPY_AND_ASSIGN(ClassRegistrar);
83 ClassRegistrar::~ClassRegistrar() {}
85 // static
86 ClassRegistrar* ClassRegistrar::GetInstance() {
87 return Singleton<ClassRegistrar,
88 LeakySingletonTraits<ClassRegistrar> >::get();
91 ATOM ClassRegistrar::RetrieveClassAtom(const ClassInfo& class_info) {
92 base::AutoLock auto_lock(lock_);
93 for (RegisteredClasses::const_iterator i = registered_classes_.begin();
94 i != registered_classes_.end(); ++i) {
95 if (class_info.Equals(i->info))
96 return i->atom;
99 // No class found, need to register one.
100 base::string16 name = base::string16(WindowImpl::kBaseClassName) +
101 base::IntToString16(registered_count_++);
103 WNDCLASSEX window_class;
104 base::win::InitializeWindowClass(
105 name.c_str(),
106 &base::win::WrappedWindowProc<WindowImpl::WndProc>,
107 class_info.style,
110 NULL,
111 reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)),
112 NULL,
113 class_info.icon,
114 class_info.icon,
115 &window_class);
116 HMODULE instance = window_class.hInstance;
117 ATOM atom = RegisterClassEx(&window_class);
118 CHECK(atom) << GetLastError();
120 registered_classes_.push_back(RegisteredClass(class_info, atom));
122 return atom;
125 ClassRegistrar::RegisteredClass::RegisteredClass(const ClassInfo& info,
126 ATOM atom)
127 : info(info),
128 atom(atom) {}
130 ClassRegistrar::ClassRegistrar() : registered_count_(0) {}
133 ///////////////////////////////////////////////////////////////////////////////
134 // WindowImpl, public
136 WindowImpl::WindowImpl()
137 : window_style_(0),
138 window_ex_style_(kWindowDefaultExStyle),
139 class_style_(CS_DBLCLKS),
140 hwnd_(NULL),
141 got_create_(false),
142 got_valid_hwnd_(false),
143 destroyed_(NULL) {
146 WindowImpl::~WindowImpl() {
147 if (destroyed_)
148 *destroyed_ = true;
149 ClearUserData();
152 void WindowImpl::Init(HWND parent, const Rect& bounds) {
153 if (window_style_ == 0)
154 window_style_ = parent ? kWindowDefaultChildStyle : kWindowDefaultStyle;
156 if (parent == HWND_DESKTOP) {
157 // Only non-child windows can have HWND_DESKTOP (0) as their parent.
158 CHECK((window_style_ & WS_CHILD) == 0);
159 parent = GetWindowToParentTo(false);
160 } else if (parent == ::GetDesktopWindow()) {
161 // Any type of window can have the "Desktop Window" as their parent.
162 parent = GetWindowToParentTo(true);
163 } else if (parent != HWND_MESSAGE) {
164 CHECK(::IsWindow(parent));
167 int x, y, width, height;
168 if (bounds.IsEmpty()) {
169 x = y = width = height = CW_USEDEFAULT;
170 } else {
171 x = bounds.x();
172 y = bounds.y();
173 width = bounds.width();
174 height = bounds.height();
177 ATOM atom = GetWindowClassAtom();
178 bool destroyed = false;
179 destroyed_ = &destroyed;
180 HWND hwnd = CreateWindowEx(window_ex_style_,
181 reinterpret_cast<wchar_t*>(atom), NULL,
182 window_style_, x, y, width, height,
183 parent, NULL, NULL, this);
185 // First nccalcszie (during CreateWindow) for captioned windows is
186 // deliberately ignored so force a second one here to get the right
187 // non-client set up.
188 if (hwnd && (window_style_ & WS_CAPTION)) {
189 SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
190 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE |
191 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW);
194 if (!hwnd_ && GetLastError() == 0) {
195 base::debug::Alias(&destroyed);
196 base::debug::Alias(&hwnd);
197 bool got_create = got_create_;
198 base::debug::Alias(&got_create);
199 bool got_valid_hwnd = got_valid_hwnd_;
200 base::debug::Alias(&got_valid_hwnd);
201 WNDCLASSEX class_info;
202 memset(&class_info, 0, sizeof(WNDCLASSEX));
203 class_info.cbSize = sizeof(WNDCLASSEX);
204 BOOL got_class = GetClassInfoEx(GetModuleHandle(NULL),
205 reinterpret_cast<wchar_t*>(atom),
206 &class_info);
207 base::debug::Alias(&got_class);
208 bool procs_match = got_class && class_info.lpfnWndProc ==
209 base::win::WrappedWindowProc<&WindowImpl::WndProc>;
210 base::debug::Alias(&procs_match);
211 CHECK(false);
213 if (!destroyed)
214 destroyed_ = NULL;
216 CheckWindowCreated(hwnd_);
218 // The window procedure should have set the data for us.
219 CHECK_EQ(this, GetWindowUserData(hwnd));
222 HICON WindowImpl::GetDefaultWindowIcon() const {
223 return NULL;
226 LRESULT WindowImpl::OnWndProc(UINT message, WPARAM w_param, LPARAM l_param) {
227 LRESULT result = 0;
229 HWND hwnd = hwnd_;
230 if (message == WM_NCDESTROY)
231 hwnd_ = NULL;
233 // Handle the message if it's in our message map; otherwise, let the system
234 // handle it.
235 if (!ProcessWindowMessage(hwnd, message, w_param, l_param, result))
236 result = DefWindowProc(hwnd, message, w_param, l_param);
238 return result;
241 void WindowImpl::ClearUserData() {
242 if (::IsWindow(hwnd_))
243 gfx::SetWindowUserData(hwnd_, NULL);
246 // static
247 LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd,
248 UINT message,
249 WPARAM w_param,
250 LPARAM l_param) {
251 if (message == WM_NCCREATE) {
252 CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(l_param);
253 WindowImpl* window = reinterpret_cast<WindowImpl*>(cs->lpCreateParams);
254 DCHECK(window);
255 gfx::SetWindowUserData(hwnd, window);
256 window->hwnd_ = hwnd;
257 window->got_create_ = true;
258 if (hwnd)
259 window->got_valid_hwnd_ = true;
260 return TRUE;
263 WindowImpl* window = reinterpret_cast<WindowImpl*>(GetWindowUserData(hwnd));
264 if (!window)
265 return 0;
267 return window->OnWndProc(message, w_param, l_param);
270 ATOM WindowImpl::GetWindowClassAtom() {
271 HICON icon = GetDefaultWindowIcon();
272 ClassInfo class_info(initial_class_style(), icon);
273 return ClassRegistrar::GetInstance()->RetrieveClassAtom(class_info);
276 } // namespace gfx