OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/display/win/screen_win.h" | 5 #include "ui/display/win/screen_win.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
13 #include "ui/display/display.h" | 13 #include "ui/display/display.h" |
14 #include "ui/display/manager/display_layout.h" | 14 #include "ui/display/manager/display_layout.h" |
15 #include "ui/display/manager/display_layout_builder.h" | 15 #include "ui/display/manager/display_layout_builder.h" |
16 #include "ui/display/win/display_info.h" | 16 #include "ui/display/win/display_info.h" |
17 #include "ui/display/win/dpi.h" | 17 #include "ui/display/win/dpi.h" |
18 #include "ui/display/win/scaling_util.h" | 18 #include "ui/display/win/scaling_util.h" |
19 #include "ui/display/win/screen_win_display.h" | 19 #include "ui/display/win/screen_win_display.h" |
20 #include "ui/gfx/geometry/point.h" | 20 #include "ui/gfx/geometry/point.h" |
21 #include "ui/gfx/geometry/point_conversions.h" | |
22 #include "ui/gfx/geometry/rect.h" | 21 #include "ui/gfx/geometry/rect.h" |
23 #include "ui/gfx/geometry/rect_conversions.h" | 22 #include "ui/gfx/geometry/size.h" |
24 #include "ui/gfx/geometry/size_conversions.h" | 23 #include "ui/gfx/geometry/vector2d.h" |
25 | 24 |
26 namespace display { | 25 namespace display { |
27 namespace win { | 26 namespace win { |
28 namespace { | 27 namespace { |
29 | 28 |
| 29 // TODO(robliao): http://crbug.com/615514 Remove when ScreenWin usage is |
| 30 // resolved with Desktop Aura and WindowTreeHost. |
| 31 ScreenWin* g_screen_win_instance = nullptr; |
| 32 |
30 std::vector<DisplayInfo> FindAndRemoveTouchingDisplayInfos( | 33 std::vector<DisplayInfo> FindAndRemoveTouchingDisplayInfos( |
31 const DisplayInfo& ref_display_info, | 34 const DisplayInfo& ref_display_info, |
32 std::vector<DisplayInfo>* display_infos) { | 35 std::vector<DisplayInfo>* display_infos) { |
33 std::vector<DisplayInfo> touching_display_infos; | 36 std::vector<DisplayInfo> touching_display_infos; |
34 display_infos->erase( | 37 display_infos->erase( |
35 std::remove_if(display_infos->begin(), display_infos->end(), | 38 std::remove_if(display_infos->begin(), display_infos->end(), |
36 [&touching_display_infos, ref_display_info]( | 39 [&touching_display_infos, ref_display_info]( |
37 const DisplayInfo& display_info) { | 40 const DisplayInfo& display_info) { |
38 if (DisplayInfosTouch(ref_display_info, display_info)) { | 41 if (DisplayInfosTouch(ref_display_info, display_info)) { |
39 touching_display_infos.push_back(display_info); | 42 touching_display_infos.push_back(display_info); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 return monitor_info; | 137 return monitor_info; |
135 } | 138 } |
136 | 139 |
137 BOOL CALLBACK EnumMonitorCallback(HMONITOR monitor, | 140 BOOL CALLBACK EnumMonitorCallback(HMONITOR monitor, |
138 HDC hdc, | 141 HDC hdc, |
139 LPRECT rect, | 142 LPRECT rect, |
140 LPARAM data) { | 143 LPARAM data) { |
141 std::vector<DisplayInfo>* display_infos = | 144 std::vector<DisplayInfo>* display_infos = |
142 reinterpret_cast<std::vector<DisplayInfo>*>(data); | 145 reinterpret_cast<std::vector<DisplayInfo>*>(data); |
143 DCHECK(display_infos); | 146 DCHECK(display_infos); |
| 147 // TODO(robliao): When ready, replace the GetDPIScale with GetDpiForMonitor |
| 148 // to get the actual DPI for the HMONITOR. |
144 display_infos->push_back(DisplayInfo(MonitorInfoFromHMONITOR(monitor), | 149 display_infos->push_back(DisplayInfo(MonitorInfoFromHMONITOR(monitor), |
145 GetDPIScale())); | 150 GetDPIScale())); |
146 return TRUE; | 151 return TRUE; |
147 } | 152 } |
148 | 153 |
149 std::vector<DisplayInfo> GetDisplayInfosFromSystem() { | 154 std::vector<DisplayInfo> GetDisplayInfosFromSystem() { |
150 std::vector<DisplayInfo> display_infos; | 155 std::vector<DisplayInfo> display_infos; |
151 EnumDisplayMonitors(nullptr, nullptr, EnumMonitorCallback, | 156 EnumDisplayMonitors(nullptr, nullptr, EnumMonitorCallback, |
152 reinterpret_cast<LPARAM>(&display_infos)); | 157 reinterpret_cast<LPARAM>(&display_infos)); |
153 DCHECK_EQ(static_cast<size_t>(::GetSystemMetrics(SM_CMONITORS)), | 158 DCHECK_EQ(static_cast<size_t>(::GetSystemMetrics(SM_CMONITORS)), |
154 display_infos.size()); | 159 display_infos.size()); |
155 return display_infos; | 160 return display_infos; |
156 } | 161 } |
157 | 162 |
| 163 // Returns a point in |to_origin|'s coordinates and position scaled by |
| 164 // |scale_factor|. |
| 165 gfx::Point ScalePointRelative(const gfx::Point& from_origin, |
| 166 const gfx::Point& to_origin, |
| 167 const float scale_factor, |
| 168 const gfx::Point& point) { |
| 169 gfx::Vector2d from_origin_vector(from_origin.x(), from_origin.y()); |
| 170 gfx::Vector2d to_origin_vector(to_origin.x(), to_origin.y()); |
| 171 gfx::Point scaled_relative_point( |
| 172 gfx::ScaleToFlooredPoint(point - from_origin_vector, scale_factor)); |
| 173 return scaled_relative_point + to_origin_vector; |
| 174 } |
| 175 |
158 } // namespace | 176 } // namespace |
159 | 177 |
160 ScreenWin::ScreenWin() { | 178 ScreenWin::ScreenWin() { |
| 179 DCHECK(!g_screen_win_instance); |
| 180 g_screen_win_instance = this; |
161 Initialize(); | 181 Initialize(); |
162 } | 182 } |
163 | 183 |
164 ScreenWin::~ScreenWin() = default; | 184 ScreenWin::~ScreenWin() { |
| 185 DCHECK_EQ(g_screen_win_instance, this); |
| 186 g_screen_win_instance = nullptr; |
| 187 } |
165 | 188 |
166 // static | 189 // static |
167 gfx::Point ScreenWin::ScreenToDIPPoint(const gfx::Point& pixel_point) { | 190 gfx::Point ScreenWin::ScreenToDIPPoint(const gfx::Point& pixel_point) { |
168 return ScaleToFlooredPoint(pixel_point, 1.0f / GetDPIScale()); | 191 const ScreenWinDisplay screen_win_display = |
| 192 GetScreenWinDisplayVia(&ScreenWin::GetScreenWinDisplayNearestScreenPoint, |
| 193 pixel_point); |
| 194 const display::Display display = screen_win_display.display(); |
| 195 return ScalePointRelative(screen_win_display.pixel_bounds().origin(), |
| 196 display.bounds().origin(), |
| 197 1.0f / display.device_scale_factor(), |
| 198 pixel_point); |
169 } | 199 } |
170 | 200 |
171 // static | 201 // static |
172 gfx::Point ScreenWin::DIPToScreenPoint(const gfx::Point& dip_point) { | 202 gfx::Point ScreenWin::DIPToScreenPoint(const gfx::Point& dip_point) { |
173 return ScaleToFlooredPoint(dip_point, GetDPIScale()); | 203 const ScreenWinDisplay screen_win_display = |
| 204 GetScreenWinDisplayVia(&ScreenWin::GetScreenWinDisplayNearestDIPPoint, |
| 205 dip_point); |
| 206 const display::Display display = screen_win_display.display(); |
| 207 return ScalePointRelative(display.bounds().origin(), |
| 208 screen_win_display.pixel_bounds().origin(), |
| 209 display.device_scale_factor(), |
| 210 dip_point); |
174 } | 211 } |
175 | 212 |
176 // static | 213 // static |
177 gfx::Point ScreenWin::ClientToDIPPoint(HWND hwnd, | 214 gfx::Point ScreenWin::ClientToDIPPoint(HWND hwnd, |
178 const gfx::Point& client_point) { | 215 const gfx::Point& client_point) { |
179 // TODO(robliao): Get the scale factor from |hwnd|. | 216 return ScaleToFlooredPoint(client_point, 1.0f / GetScaleFactorForHWND(hwnd)); |
180 return ScreenToDIPPoint(client_point); | |
181 } | 217 } |
182 | 218 |
183 // static | 219 // static |
184 gfx::Point ScreenWin::DIPToClientPoint(HWND hwnd, const gfx::Point& dip_point) { | 220 gfx::Point ScreenWin::DIPToClientPoint(HWND hwnd, const gfx::Point& dip_point) { |
185 // TODO(robliao): Get the scale factor from |hwnd|. | 221 float scale_factor = GetScaleFactorForHWND(hwnd); |
186 return DIPToScreenPoint(dip_point); | 222 return ScaleToFlooredPoint(dip_point, scale_factor); |
187 } | 223 } |
188 | 224 |
189 // static | 225 // static |
190 gfx::Rect ScreenWin::ScreenToDIPRect(HWND hwnd, const gfx::Rect& pixel_bounds) { | 226 gfx::Rect ScreenWin::ScreenToDIPRect(HWND hwnd, const gfx::Rect& pixel_bounds) { |
191 // It's important we scale the origin and size separately. If we instead | 227 float scale_factor = hwnd ? |
192 // calculated the size from the floored origin and ceiled right the size could | 228 GetScaleFactorForHWND(hwnd) : |
193 // vary depending upon where the two points land. That would cause problems | 229 GetScreenWinDisplayVia( |
194 // for the places this code is used (in particular mapping from native window | 230 &ScreenWin::GetScreenWinDisplayNearestScreenRect, pixel_bounds). |
195 // bounds to DIPs). | 231 display().device_scale_factor(); |
196 return gfx::Rect(ScreenToDIPPoint(pixel_bounds.origin()), | 232 gfx::Rect dip_rect = ScaleToEnclosingRect(pixel_bounds, 1.0f / scale_factor); |
197 ScreenToDIPSize(hwnd, pixel_bounds.size())); | 233 dip_rect.set_origin(ScreenToDIPPoint(pixel_bounds.origin())); |
| 234 return dip_rect; |
198 } | 235 } |
199 | 236 |
200 // static | 237 // static |
201 gfx::Rect ScreenWin::DIPToScreenRect(HWND hwnd, const gfx::Rect& dip_bounds) { | 238 gfx::Rect ScreenWin::DIPToScreenRect(HWND hwnd, const gfx::Rect& dip_bounds) { |
202 // See comment in ScreenToDIPRect for why we calculate size like this. | 239 float scale_factor = hwnd ? |
203 return gfx::Rect(DIPToScreenPoint(dip_bounds.origin()), | 240 GetScaleFactorForHWND(hwnd) : |
204 DIPToScreenSize(hwnd, dip_bounds.size())); | 241 GetScreenWinDisplayVia( |
| 242 &ScreenWin::GetScreenWinDisplayNearestDIPRect, dip_bounds).display(). |
| 243 device_scale_factor(); |
| 244 gfx::Rect screen_rect = ScaleToEnclosingRect(dip_bounds, scale_factor); |
| 245 screen_rect.set_origin(DIPToScreenPoint(dip_bounds.origin())); |
| 246 return screen_rect; |
205 } | 247 } |
206 | 248 |
207 // static | 249 // static |
208 gfx::Rect ScreenWin::ClientToDIPRect(HWND hwnd, const gfx::Rect& pixel_bounds) { | 250 gfx::Rect ScreenWin::ClientToDIPRect(HWND hwnd, const gfx::Rect& pixel_bounds) { |
209 return ScreenToDIPRect(hwnd, pixel_bounds); | 251 return ScaleToEnclosingRect(pixel_bounds, 1.0f / GetScaleFactorForHWND(hwnd)); |
210 } | 252 } |
211 | 253 |
212 // static | 254 // static |
213 gfx::Rect ScreenWin::DIPToClientRect(HWND hwnd, const gfx::Rect& dip_bounds) { | 255 gfx::Rect ScreenWin::DIPToClientRect(HWND hwnd, const gfx::Rect& dip_bounds) { |
214 return DIPToScreenRect(hwnd, dip_bounds); | 256 return ScaleToEnclosingRect(dip_bounds, GetScaleFactorForHWND(hwnd)); |
215 } | 257 } |
216 | 258 |
217 // static | 259 // static |
218 gfx::Size ScreenWin::ScreenToDIPSize(HWND hwnd, | 260 gfx::Size ScreenWin::ScreenToDIPSize(HWND hwnd, |
219 const gfx::Size& size_in_pixels) { | 261 const gfx::Size& size_in_pixels) { |
220 // Always ceil sizes. Otherwise we may be leaving off part of the bounds. | 262 // Always ceil sizes. Otherwise we may be leaving off part of the bounds. |
221 // TODO(robliao): Get the scale factor from |hwnd|. | 263 return ScaleToCeiledSize(size_in_pixels, 1.0f / GetScaleFactorForHWND(hwnd)); |
222 return ScaleToCeiledSize(size_in_pixels, 1.0f / GetDPIScale()); | |
223 } | 264 } |
224 | 265 |
225 // static | 266 // static |
226 gfx::Size ScreenWin::DIPToScreenSize(HWND hwnd, const gfx::Size& dip_size) { | 267 gfx::Size ScreenWin::DIPToScreenSize(HWND hwnd, const gfx::Size& dip_size) { |
| 268 float scale_factor = GetScaleFactorForHWND(hwnd); |
227 // Always ceil sizes. Otherwise we may be leaving off part of the bounds. | 269 // Always ceil sizes. Otherwise we may be leaving off part of the bounds. |
228 // TODO(robliao): Get the scale factor from |hwnd|. | 270 return ScaleToCeiledSize(dip_size, scale_factor); |
229 return ScaleToCeiledSize(dip_size, GetDPIScale()); | |
230 } | 271 } |
231 | 272 |
232 HWND ScreenWin::GetHWNDFromNativeView(gfx::NativeView window) const { | 273 HWND ScreenWin::GetHWNDFromNativeView(gfx::NativeView window) const { |
233 NOTREACHED(); | 274 NOTREACHED(); |
234 return nullptr; | 275 return nullptr; |
235 } | 276 } |
236 | 277 |
237 gfx::NativeWindow ScreenWin::GetNativeWindowFromHWND(HWND hwnd) const { | 278 gfx::NativeWindow ScreenWin::GetNativeWindowFromHWND(HWND hwnd) const { |
238 NOTREACHED(); | 279 NOTREACHED(); |
239 return nullptr; | 280 return nullptr; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 } | 340 } |
300 | 341 |
301 void ScreenWin::AddObserver(display::DisplayObserver* observer) { | 342 void ScreenWin::AddObserver(display::DisplayObserver* observer) { |
302 change_notifier_.AddObserver(observer); | 343 change_notifier_.AddObserver(observer); |
303 } | 344 } |
304 | 345 |
305 void ScreenWin::RemoveObserver(display::DisplayObserver* observer) { | 346 void ScreenWin::RemoveObserver(display::DisplayObserver* observer) { |
306 change_notifier_.RemoveObserver(observer); | 347 change_notifier_.RemoveObserver(observer); |
307 } | 348 } |
308 | 349 |
| 350 gfx::Rect ScreenWin::ScreenToDIPRectInWindow( |
| 351 gfx::NativeView view, const gfx::Rect& screen_rect) const { |
| 352 HWND hwnd = view ? GetHWNDFromNativeView(view) : nullptr; |
| 353 return ScreenToDIPRect(hwnd, screen_rect); |
| 354 } |
| 355 |
| 356 gfx::Rect ScreenWin::DIPToScreenRectInWindow(gfx::NativeView view, |
| 357 const gfx::Rect& dip_rect) const { |
| 358 HWND hwnd = view ? GetHWNDFromNativeView(view) : nullptr; |
| 359 return DIPToScreenRect(hwnd, dip_rect); |
| 360 } |
| 361 |
309 void ScreenWin::UpdateFromDisplayInfos( | 362 void ScreenWin::UpdateFromDisplayInfos( |
310 const std::vector<DisplayInfo>& display_infos) { | 363 const std::vector<DisplayInfo>& display_infos) { |
311 screen_win_displays_ = DisplayInfosToScreenWinDisplays(display_infos); | 364 screen_win_displays_ = DisplayInfosToScreenWinDisplays(display_infos); |
312 } | 365 } |
313 | 366 |
314 void ScreenWin::Initialize() { | 367 void ScreenWin::Initialize() { |
315 singleton_hwnd_observer_.reset( | 368 singleton_hwnd_observer_.reset( |
316 new gfx::SingletonHwndObserver( | 369 new gfx::SingletonHwndObserver( |
317 base::Bind(&ScreenWin::OnWndProc, base::Unretained(this)))); | 370 base::Bind(&ScreenWin::OnWndProc, base::Unretained(this)))); |
318 UpdateFromDisplayInfos(GetDisplayInfosFromSystem()); | 371 UpdateFromDisplayInfos(GetDisplayInfosFromSystem()); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 ScreenWinDisplay ScreenWin::GetScreenWinDisplayNearestScreenRect( | 415 ScreenWinDisplay ScreenWin::GetScreenWinDisplayNearestScreenRect( |
363 const gfx::Rect& screen_rect) const { | 416 const gfx::Rect& screen_rect) const { |
364 return GetScreenWinDisplay(MonitorInfoFromScreenRect(screen_rect)); | 417 return GetScreenWinDisplay(MonitorInfoFromScreenRect(screen_rect)); |
365 } | 418 } |
366 | 419 |
367 ScreenWinDisplay ScreenWin::GetScreenWinDisplayNearestScreenPoint( | 420 ScreenWinDisplay ScreenWin::GetScreenWinDisplayNearestScreenPoint( |
368 const gfx::Point& screen_point) const { | 421 const gfx::Point& screen_point) const { |
369 return GetScreenWinDisplay(MonitorInfoFromScreenPoint(screen_point)); | 422 return GetScreenWinDisplay(MonitorInfoFromScreenPoint(screen_point)); |
370 } | 423 } |
371 | 424 |
| 425 ScreenWinDisplay ScreenWin::GetScreenWinDisplayNearestDIPPoint( |
| 426 const gfx::Point& dip_point) const { |
| 427 ScreenWinDisplay primary_screen_win_display; |
| 428 for (const auto& screen_win_display : screen_win_displays_) { |
| 429 display::Display display = screen_win_display.display(); |
| 430 const gfx::Rect dip_bounds = display.bounds(); |
| 431 if (dip_bounds.Contains(dip_point)) |
| 432 return screen_win_display; |
| 433 else if (dip_bounds.origin().IsOrigin()) |
| 434 primary_screen_win_display = screen_win_display; |
| 435 } |
| 436 return primary_screen_win_display; |
| 437 } |
| 438 |
| 439 ScreenWinDisplay ScreenWin::GetScreenWinDisplayNearestDIPRect( |
| 440 const gfx::Rect& dip_rect) const { |
| 441 ScreenWinDisplay closest_screen_win_display; |
| 442 int64_t closest_distance_squared = INT64_MAX; |
| 443 for (const auto& screen_win_display : screen_win_displays_) { |
| 444 display::Display display = screen_win_display.display(); |
| 445 gfx::Rect dip_bounds = display.bounds(); |
| 446 int64_t distance_squared = SquaredDistanceBetweenRects(dip_rect, |
| 447 dip_bounds); |
| 448 if (distance_squared == 0) { |
| 449 return screen_win_display; |
| 450 } else if (distance_squared < closest_distance_squared) { |
| 451 closest_distance_squared = distance_squared; |
| 452 closest_screen_win_display = screen_win_display; |
| 453 } |
| 454 } |
| 455 return closest_screen_win_display; |
| 456 } |
| 457 |
372 ScreenWinDisplay ScreenWin::GetPrimaryScreenWinDisplay() const { | 458 ScreenWinDisplay ScreenWin::GetPrimaryScreenWinDisplay() const { |
373 MONITORINFOEX monitor_info = MonitorInfoFromWindow(nullptr, | 459 MONITORINFOEX monitor_info = MonitorInfoFromWindow(nullptr, |
374 MONITOR_DEFAULTTOPRIMARY); | 460 MONITOR_DEFAULTTOPRIMARY); |
375 ScreenWinDisplay screen_win_display = GetScreenWinDisplay(monitor_info); | 461 ScreenWinDisplay screen_win_display = GetScreenWinDisplay(monitor_info); |
376 display::Display display = screen_win_display.display(); | 462 display::Display display = screen_win_display.display(); |
377 // The Windows primary monitor is defined to have an origin of (0, 0). | 463 // The Windows primary monitor is defined to have an origin of (0, 0). |
378 DCHECK_EQ(0, display.bounds().origin().x()); | 464 DCHECK_EQ(0, display.bounds().origin().x()); |
379 DCHECK_EQ(0, display.bounds().origin().y()); | 465 DCHECK_EQ(0, display.bounds().origin().y()); |
380 return screen_win_display; | 466 return screen_win_display; |
381 } | 467 } |
382 | 468 |
383 ScreenWinDisplay ScreenWin::GetScreenWinDisplay( | 469 ScreenWinDisplay ScreenWin::GetScreenWinDisplay( |
384 const MONITORINFOEX& monitor_info) const { | 470 const MONITORINFOEX& monitor_info) const { |
385 int64_t id = DisplayInfo::DeviceIdFromDeviceName(monitor_info.szDevice); | 471 int64_t id = DisplayInfo::DeviceIdFromDeviceName(monitor_info.szDevice); |
386 for (const auto& screen_win_display : screen_win_displays_) { | 472 for (const auto& screen_win_display : screen_win_displays_) { |
387 if (screen_win_display.display().id() == id) | 473 if (screen_win_display.display().id() == id) |
388 return screen_win_display; | 474 return screen_win_display; |
389 } | 475 } |
390 // There is 1:1 correspondence between MONITORINFOEX and ScreenWinDisplay. | 476 // There is 1:1 correspondence between MONITORINFOEX and ScreenWinDisplay. |
391 // If we make it here, it means we have no displays and we should hand out the | 477 // If we make it here, it means we have no displays and we should hand out the |
392 // default display. | 478 // default display. |
393 DCHECK_EQ(screen_win_displays_.size(), 0u); | 479 DCHECK_EQ(screen_win_displays_.size(), 0u); |
394 return ScreenWinDisplay(); | 480 return ScreenWinDisplay(); |
395 } | 481 } |
396 | 482 |
| 483 // static |
| 484 float ScreenWin::GetScaleFactorForHWND(HWND hwnd) { |
| 485 if (!g_screen_win_instance) |
| 486 return ScreenWinDisplay().display().device_scale_factor(); |
| 487 |
| 488 DCHECK(hwnd); |
| 489 HWND rootHwnd = g_screen_win_instance->GetRootWindow(hwnd); |
| 490 ScreenWinDisplay screen_win_display = |
| 491 g_screen_win_instance->GetScreenWinDisplayNearestHWND(rootHwnd); |
| 492 return screen_win_display.display().device_scale_factor(); |
| 493 } |
| 494 |
| 495 // static |
| 496 template <typename Getter, typename GetterType> |
| 497 ScreenWinDisplay ScreenWin::GetScreenWinDisplayVia(Getter getter, |
| 498 GetterType value) { |
| 499 if (!g_screen_win_instance) |
| 500 return ScreenWinDisplay(); |
| 501 |
| 502 return (g_screen_win_instance->*getter)(value); |
| 503 } |
| 504 |
397 } // namespace win | 505 } // namespace win |
398 } // namespace display | 506 } // namespace display |
OLD | NEW |