[SyncFS] Build indexes from FileTracker entries on disk.
[chromium-blink-merge.git] / ui / gfx / win / hwnd_util.cc
blob050aa9b733f0be41796de2e034520d90756caae4
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/hwnd_util.h"
7 #include "base/i18n/rtl.h"
8 #include "base/strings/string_util.h"
9 #include "base/win/metro.h"
10 #include "base/win/win_util.h"
11 #include "ui/gfx/point.h"
12 #include "ui/gfx/rect.h"
13 #include "ui/gfx/size.h"
15 namespace gfx {
17 namespace {
19 // Adjust the window to fit.
20 void AdjustWindowToFit(HWND hwnd, const RECT& bounds, bool fit_to_monitor) {
21 if (fit_to_monitor) {
22 // Get the monitor.
23 HMONITOR hmon = MonitorFromRect(&bounds, MONITOR_DEFAULTTONEAREST);
24 if (hmon) {
25 MONITORINFO mi;
26 mi.cbSize = sizeof(mi);
27 GetMonitorInfo(hmon, &mi);
28 Rect window_rect(bounds);
29 Rect monitor_rect(mi.rcWork);
30 Rect new_window_rect = window_rect;
31 new_window_rect.AdjustToFit(monitor_rect);
32 if (new_window_rect != window_rect) {
33 // Window doesn't fit on monitor, move and possibly resize.
34 SetWindowPos(hwnd, 0, new_window_rect.x(), new_window_rect.y(),
35 new_window_rect.width(), new_window_rect.height(),
36 SWP_NOACTIVATE | SWP_NOZORDER);
37 return;
39 // Else fall through.
40 } else {
41 NOTREACHED() << "Unable to find default monitor";
42 // Fall through.
44 } // Else fall through.
46 // The window is not being fit to monitor, or the window fits on the monitor
47 // as is, or we have no monitor info; reset the bounds.
48 ::SetWindowPos(hwnd, 0, bounds.left, bounds.top,
49 bounds.right - bounds.left, bounds.bottom - bounds.top,
50 SWP_NOACTIVATE | SWP_NOZORDER);
53 // Turn off optimizations for these functions so they show up in crash reports.
54 MSVC_DISABLE_OPTIMIZE();
56 void CrashOutOfMemory() {
57 PLOG(FATAL);
60 void CrashAccessDenied() {
61 PLOG(FATAL);
64 // Crash isn't one of the ones we commonly see.
65 void CrashOther() {
66 PLOG(FATAL);
69 MSVC_ENABLE_OPTIMIZE();
71 } // namespace
73 base::string16 GetClassName(HWND window) {
74 // GetClassNameW will return a truncated result (properly null terminated) if
75 // the given buffer is not large enough. So, it is not possible to determine
76 // that we got the entire class name if the result is exactly equal to the
77 // size of the buffer minus one.
78 DWORD buffer_size = MAX_PATH;
79 while (true) {
80 std::wstring output;
81 DWORD size_ret =
82 GetClassNameW(window, WriteInto(&output, buffer_size), buffer_size);
83 if (size_ret == 0)
84 break;
85 if (size_ret < (buffer_size - 1)) {
86 output.resize(size_ret);
87 return output;
89 buffer_size *= 2;
91 return std::wstring(); // error
94 #pragma warning(push)
95 #pragma warning(disable:4312 4244)
97 WNDPROC SetWindowProc(HWND hwnd, WNDPROC proc) {
98 // The reason we don't return the SetwindowLongPtr() value is that it returns
99 // the orignal window procedure and not the current one. I don't know if it is
100 // a bug or an intended feature.
101 WNDPROC oldwindow_proc =
102 reinterpret_cast<WNDPROC>(GetWindowLongPtr(hwnd, GWLP_WNDPROC));
103 SetWindowLongPtr(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(proc));
104 return oldwindow_proc;
107 void* SetWindowUserData(HWND hwnd, void* user_data) {
108 return
109 reinterpret_cast<void*>(SetWindowLongPtr(hwnd, GWLP_USERDATA,
110 reinterpret_cast<LONG_PTR>(user_data)));
113 void* GetWindowUserData(HWND hwnd) {
114 DWORD process_id = 0;
115 DWORD thread_id = GetWindowThreadProcessId(hwnd, &process_id);
116 // A window outside the current process needs to be ignored.
117 if (process_id != ::GetCurrentProcessId())
118 return NULL;
119 return reinterpret_cast<void*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
122 #pragma warning(pop)
124 bool DoesWindowBelongToActiveWindow(HWND window) {
125 DCHECK(window);
126 HWND top_window = ::GetAncestor(window, GA_ROOT);
127 if (!top_window)
128 return false;
130 HWND active_top_window = ::GetAncestor(::GetForegroundWindow(), GA_ROOT);
131 return (top_window == active_top_window);
134 void CenterAndSizeWindow(HWND parent,
135 HWND window,
136 const Size& pref) {
137 DCHECK(window && pref.width() > 0 && pref.height() > 0);
139 // Calculate the ideal bounds.
140 RECT window_bounds;
141 RECT center_bounds = {0};
142 if (parent) {
143 // If there is a parent, center over the parents bounds.
144 ::GetWindowRect(parent, &center_bounds);
147 if (::IsRectEmpty(&center_bounds)) {
148 // No parent or no parent rect. Center over the monitor the window is on.
149 HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONEAREST);
150 if (monitor) {
151 MONITORINFO mi = {0};
152 mi.cbSize = sizeof(mi);
153 GetMonitorInfo(monitor, &mi);
154 center_bounds = mi.rcWork;
155 } else {
156 NOTREACHED() << "Unable to get default monitor";
160 window_bounds.left = center_bounds.left;
161 if (pref.width() < (center_bounds.right - center_bounds.left)) {
162 window_bounds.left +=
163 (center_bounds.right - center_bounds.left - pref.width()) / 2;
165 window_bounds.right = window_bounds.left + pref.width();
167 window_bounds.top = center_bounds.top;
168 if (pref.height() < (center_bounds.bottom - center_bounds.top)) {
169 window_bounds.top +=
170 (center_bounds.bottom - center_bounds.top - pref.height()) / 2;
172 window_bounds.bottom = window_bounds.top + pref.height();
174 // If we're centering a child window, we are positioning in client
175 // coordinates, and as such we need to offset the target rectangle by the
176 // position of the parent window.
177 if (::GetWindowLong(window, GWL_STYLE) & WS_CHILD) {
178 DCHECK(parent && ::GetParent(window) == parent);
179 POINT topleft = { window_bounds.left, window_bounds.top };
180 ::MapWindowPoints(HWND_DESKTOP, parent, &topleft, 1);
181 window_bounds.left = topleft.x;
182 window_bounds.top = topleft.y;
183 window_bounds.right = window_bounds.left + pref.width();
184 window_bounds.bottom = window_bounds.top + pref.height();
187 AdjustWindowToFit(window, window_bounds, !parent);
190 void CheckWindowCreated(HWND hwnd) {
191 if (!hwnd) {
192 switch (GetLastError()) {
193 case ERROR_NOT_ENOUGH_MEMORY:
194 CrashOutOfMemory();
195 break;
196 case ERROR_ACCESS_DENIED:
197 CrashAccessDenied();
198 break;
199 default:
200 CrashOther();
201 break;
203 PLOG(FATAL);
207 void ShowSystemMenu(HWND window) {
208 RECT rect;
209 GetWindowRect(window, &rect);
210 Point point = Point(base::i18n::IsRTL() ? rect.right : rect.left, rect.top);
211 static const int kSystemMenuOffset = 10;
212 point.Offset(base::i18n::IsRTL() ? -kSystemMenuOffset : kSystemMenuOffset,
213 kSystemMenuOffset);
214 ShowSystemMenuAtPoint(window, point);
217 void ShowSystemMenuAtPoint(HWND window, const Point& point) {
218 // In the Metro process, we never want to show the system menu.
219 if (base::win::IsMetroProcess())
220 return;
221 UINT flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD;
222 if (base::i18n::IsRTL())
223 flags |= TPM_RIGHTALIGN;
224 HMENU menu = GetSystemMenu(window, FALSE);
225 const int command =
226 TrackPopupMenu(menu, flags, point.x(), point.y(), 0, window, NULL);
227 if (command)
228 SendMessage(window, WM_SYSCOMMAND, command, 0);
231 extern "C" {
232 typedef HWND (*RootWindow)();
235 HWND GetWindowToParentTo(bool get_real_hwnd) {
236 HMODULE metro = base::win::GetMetroModule();
237 if (!metro)
238 return get_real_hwnd ? ::GetDesktopWindow() : HWND_DESKTOP;
239 // In windows 8 metro-mode the root window is not the desktop.
240 RootWindow root_window =
241 reinterpret_cast<RootWindow>(::GetProcAddress(metro, "GetRootWindow"));
242 return root_window();
245 } // namespace gfx