Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(397)

Side by Side Diff: ui/gfx/screen_win.cc

Issue 1426933002: Refactor Windows DPI Point, Rect, and Size for Multiple Monitor DPI Awareness (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase to b840e2f Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/gfx/screen_win.h" 5 #include "ui/gfx/screen_win.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/bind_helpers.h" 11 #include "base/bind_helpers.h"
12 #include "base/hash.h" 12 #include "base/hash.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
15 #include "base/win/win_util.h" 15 #include "base/win/win_util.h"
16 #include "ui/gfx/display.h" 16 #include "ui/gfx/display.h"
17 #include "ui/gfx/geometry/insets.h"
18 #include "ui/gfx/geometry/point.h"
19 #include "ui/gfx/geometry/point_conversions.h"
20 #include "ui/gfx/geometry/rect.h"
21 #include "ui/gfx/geometry/safe_integer_conversions.h"
22 #include "ui/gfx/geometry/size.h"
23 #include "ui/gfx/geometry/vector2d.h"
17 #include "ui/gfx/win/dpi.h" 24 #include "ui/gfx/win/dpi.h"
25 #include "ui/gfx/win/rect_util.h"
18 26
19 namespace { 27 namespace {
20 28
21 MONITORINFOEX GetMonitorInfoForMonitor(HMONITOR monitor) { 29 gfx::Display::Rotation GetRotationForDevice(const wchar_t* device_name) {
22 MONITORINFOEX monitor_info;
23 ZeroMemory(&monitor_info, sizeof(MONITORINFOEX));
24 monitor_info.cbSize = sizeof(monitor_info);
25 GetMonitorInfo(monitor, &monitor_info);
26 return monitor_info;
27 }
28
29 gfx::Display GetDisplay(const MONITORINFOEX& monitor_info) {
30 int64_t id =
31 static_cast<int64_t>(base::Hash(base::WideToUTF8(monitor_info.szDevice)));
32 gfx::Rect bounds = gfx::Rect(monitor_info.rcMonitor);
33 gfx::Display display(id);
34 display.set_bounds(gfx::win::ScreenToDIPRect(bounds));
35 display.set_work_area(
36 gfx::win::ScreenToDIPRect(gfx::Rect(monitor_info.rcWork)));
37 display.SetScaleAndBounds(gfx::GetDPIScale(), bounds);
38
39 DEVMODE mode; 30 DEVMODE mode;
40 memset(&mode, 0, sizeof(DEVMODE)); 31 ::ZeroMemory(&mode, sizeof(mode));
41 mode.dmSize = sizeof(DEVMODE); 32 mode.dmSize = sizeof(DEVMODE);
42 mode.dmDriverExtra = 0; 33 mode.dmDriverExtra = 0;
43 if (EnumDisplaySettings(monitor_info.szDevice, 34 if (::EnumDisplaySettings(device_name, ENUM_CURRENT_SETTINGS, &mode)) {
44 ENUM_CURRENT_SETTINGS,
45 &mode)) {
46 switch (mode.dmDisplayOrientation) { 35 switch (mode.dmDisplayOrientation) {
47 case DMDO_DEFAULT: 36 case DMDO_DEFAULT:
48 display.set_rotation(gfx::Display::ROTATE_0); 37 return gfx::Display::ROTATE_0;
49 break;
50 case DMDO_90: 38 case DMDO_90:
51 display.set_rotation(gfx::Display::ROTATE_90); 39 return gfx::Display::ROTATE_90;
52 break;
53 case DMDO_180: 40 case DMDO_180:
54 display.set_rotation(gfx::Display::ROTATE_180); 41 return gfx::Display::ROTATE_180;
55 break;
56 case DMDO_270: 42 case DMDO_270:
57 display.set_rotation(gfx::Display::ROTATE_270); 43 return gfx::Display::ROTATE_270;
58 break;
59 default: 44 default:
60 NOTREACHED(); 45 NOTREACHED();
61 } 46 }
62 } 47 }
63 48 return gfx::Display::ROTATE_0;
64 return display;
65 } 49 }
66 50
67 BOOL CALLBACK EnumMonitorCallback(HMONITOR monitor, 51 // Returns a point in |to_origin|'s coordinates and position scaled by
68 HDC hdc, 52 // |scale_factor|.
69 LPRECT rect, 53 gfx::Point ScalePointRelative(const gfx::Point& from_origin,
70 LPARAM data) { 54 const gfx::Point& to_origin,
71 std::vector<gfx::Display>* all_displays = 55 const float scale_factor,
72 reinterpret_cast<std::vector<gfx::Display>*>(data); 56 const gfx::Point& point) {
73 DCHECK(all_displays); 57 gfx::Vector2d from_origin_vector(from_origin.x(), from_origin.y());
74 58 gfx::Vector2d to_origin_vector(to_origin.x(), to_origin.y());
75 MONITORINFOEX monitor_info = GetMonitorInfoForMonitor(monitor); 59 return gfx::ScaleToFlooredPoint(point - from_origin_vector, scale_factor) +
76 gfx::Display display = GetDisplay(monitor_info); 60 to_origin_vector;
77 all_displays->push_back(display);
78 return TRUE;
79 } 61 }
80 62
81 std::vector<gfx::Display> GetDisplays() { 63 // Returns the NativeScreen. For all intents and purposes, this screen provides
82 std::vector<gfx::Display> displays; 64 // the source of truth for displays in Windows.
83 EnumDisplayMonitors(NULL, NULL, EnumMonitorCallback, 65 gfx::ScreenWin* GetNativeScreenWin() {
84 reinterpret_cast<LPARAM>(&displays)); 66 return static_cast<gfx::ScreenWin*>(gfx::Screen::GetNativeScreen());
85 return displays; 67 }
68
69 // static
70 MONITORINFOEX MonitorInfoFromHMONITOR(HMONITOR monitor) {
71 MONITORINFOEX monitor_info;
72 ::ZeroMemory(&monitor_info, sizeof(monitor_info));
73 monitor_info.cbSize = sizeof(monitor_info);
74 ::GetMonitorInfo(monitor, &monitor_info);
75 return monitor_info;
86 } 76 }
87 77
88 } // namespace 78 } // namespace
89 79
90 namespace gfx { 80 namespace gfx {
91 81
82 class ScreenWin::DisplayWin : public gfx::Display {
83 public:
84 explicit DisplayWin();
85 explicit DisplayWin(const DisplayInfo& display_info);
86 DisplayWin(const DisplayWin& ref, const DisplayInfo& display_info);
87
88 const gfx::Rect& physical_bounds() const { return pixel_bounds_; }
89
90 private:
91 gfx::Rect pixel_bounds_;
92 };
93
92 ScreenWin::ScreenWin() 94 ScreenWin::ScreenWin()
93 : singleton_hwnd_observer_(new SingletonHwndObserver( 95 : singleton_hwnd_observer_(new SingletonHwndObserver(
94 base::Bind(&ScreenWin::OnWndProc, base::Unretained(this)))), 96 base::Bind(&ScreenWin::OnWndProc, base::Unretained(this)))),
95 displays_(GetDisplays()) { 97 displays_(GetDisplays()) {}
98
99 ScreenWin::~ScreenWin() {}
100
101 // static
102 Point ScreenWin::ScreenToDIPPoint(const Point& pixel_point) {
103 DisplayWin display = GetDisplayNearestScreenPoint(pixel_point);
104 return ScalePointRelative(display.physical_bounds().origin(),
105 display.bounds().origin(),
106 1.0f / display.device_scale_factor(),
107 pixel_point);
96 } 108 }
97 109
98 ScreenWin::~ScreenWin() {} 110 // static
111 Point ScreenWin::DIPToScreenPoint(const Point& dip_point) {
112 DisplayWin display = GetDisplayNearestDIPPoint(dip_point);
113 return ScalePointRelative(display.bounds().origin(),
114 display.physical_bounds().origin(),
115 display.device_scale_factor(),
116 dip_point);
117 }
118
119
120 Point ScreenWin::ClientToDIPPoint(HWND hwnd, const Point& client_point) {
121 return ScaleToFlooredPoint(client_point, 1.0f / GetScaleFactorForHWND(hwnd));
122 }
123
124 Point ScreenWin::DIPToClientPoint(HWND hwnd, const Point& dip_point) {
125 return ScaleToFlooredPoint(dip_point, GetScaleFactorForHWND(hwnd));
126 }
127
128 // static
129 Rect ScreenWin::ScreenToDIPRect(HWND hwnd, const Rect& pixel_bounds) {
130 // It's important we scale the origin and size separately. If we instead
131 // calculated the size from the floored origin and ceiled right the size could
132 // vary depending upon where the two points land. That would cause problems
133 // for the places this code is used (in particular mapping from native window
134 // bounds to DIPs).
135 if (hwnd) {
136 return Rect(ScreenToDIPPoint(pixel_bounds.origin()),
137 ScreenToDIPSize(hwnd, pixel_bounds.size()));
138 }
139 float scale_factor =
140 GetDisplayNearestScreenRect(pixel_bounds).device_scale_factor();
141 return Rect(ScreenToDIPPoint(pixel_bounds.origin()),
142 ScaleToCeiledSize(pixel_bounds.size(), 1.0f / scale_factor));
143 }
144
145 // static
146 Rect ScreenWin::DIPToScreenRect(HWND hwnd, const Rect& dip_bounds) {
147 // See comment in ScreenToDIPRect for why we calculate size like this.
148 if (hwnd) {
149 return Rect(DIPToScreenPoint(dip_bounds.origin()),
150 DIPToScreenSize(hwnd, dip_bounds.size()));
151 }
152 // Because origins don't change for screen points and scaling factors are
153 // greater than 1, the monitor bounding rect always contains the DIP point.
154 float scale_factor =
155 GetDisplayNearestDIPRect(dip_bounds).device_scale_factor();
156 return Rect(DIPToScreenPoint(dip_bounds.origin()),
157 ScaleToCeiledSize(dip_bounds.size(), scale_factor));
158 }
159
160 // static
161 Rect ScreenWin::ClientToDIPRect(HWND hwnd, const Rect& pixel_bounds) {
162 // See comment in ScreenToDIPRect for why we calculate size like this.
163 return Rect(ClientToDIPPoint(hwnd, pixel_bounds.origin()),
164 ScreenToDIPSize(hwnd, pixel_bounds.size()));
165 }
166
167 // static
168 Rect ScreenWin::DIPToClientRect(HWND hwnd, const Rect& dip_bounds) {
169 // See comment in ScreenToDIPRect for why we calculate size like this.
170 return Rect(DIPToClientPoint(hwnd, dip_bounds.origin()),
171 DIPToScreenSize(hwnd, dip_bounds.size()));
172 }
173
174 // static
175 Size ScreenWin::ScreenToDIPSize(HWND hwnd, const Size& size_in_pixels) {
176 // Always ceil sizes. Otherwise we may be leaving off part of the bounds.
177 return ScaleToCeiledSize(size_in_pixels, 1.0f / GetScaleFactorForHWND(hwnd));
178 }
179
180 // static
181 Size ScreenWin::DIPToScreenSize(HWND hwnd, const Size& dip_size) {
182 // Always ceil sizes. Otherwise we may be leaving off part of the bounds.
183 return ScaleToCeiledSize(dip_size, GetScaleFactorForHWND(hwnd));
184 }
99 185
100 HWND ScreenWin::GetHWNDFromNativeView(NativeView window) const { 186 HWND ScreenWin::GetHWNDFromNativeView(NativeView window) const {
101 NOTREACHED(); 187 NOTREACHED();
102 return NULL; 188 return NULL;
103 } 189 }
104 190
105 NativeWindow ScreenWin::GetNativeWindowFromHWND(HWND hwnd) const { 191 NativeWindow ScreenWin::GetNativeWindowFromHWND(HWND hwnd) const {
106 NOTREACHED(); 192 NOTREACHED();
107 return NULL; 193 return NULL;
108 } 194 }
109 195
196 ScreenWin::DisplayInfo::DisplayInfo(HMONITOR monitor,
197 float device_scale_factor) :
198 device_scale_factor_(device_scale_factor){
199 MONITORINFOEX monitor_info;
200 ::ZeroMemory(&monitor_info, sizeof(monitor_info));
201 monitor_info.cbSize = sizeof(monitor_info);
202 ::GetMonitorInfo(monitor, &monitor_info);
203 InitializeFromMonitorInfo(monitor_info);
204 }
205
206 ScreenWin::DisplayInfo::DisplayInfo(const MONITORINFOEX& monitor_info,
207 gfx::Display::Rotation rotation,
208 float device_scale_factor)
209 : rotation_(rotation),
210 device_scale_factor_(device_scale_factor) {
211 InitializeFromMonitorInfo(monitor_info);
212 }
213
214 void ScreenWin::DisplayInfo::InitializeFromMonitorInfo(
215 const MONITORINFOEX& monitor_info) {
216 id_ = ScreenWin::HashDeviceName(monitor_info.szDevice);
217 screen_rect_ = gfx::Rect(monitor_info.rcMonitor);
218 screen_work_rect_ = gfx::Rect(monitor_info.rcWork);
219 rotation_ = GetRotationForDevice(monitor_info.szDevice);
220 }
221
222 ScreenWin::ScreenWin(const std::vector<ScreenWin::DisplayInfo>& display_infos) {
223 displays_ = GetDisplaysFromDisplayInfos(display_infos);
224 }
225
226 int64_t ScreenWin::HashDeviceName(const wchar_t* device_name) {
227 return static_cast<int64_t>(base::Hash(base::WideToUTF8(device_name)));
228 }
229
110 gfx::Point ScreenWin::GetCursorScreenPoint() { 230 gfx::Point ScreenWin::GetCursorScreenPoint() {
111 POINT pt; 231 POINT pt;
112 GetCursorPos(&pt); 232 GetCursorPos(&pt);
113 gfx::Point cursor_pos_pixels(pt); 233 gfx::Point cursor_pos_pixels(pt);
114 return gfx::win::ScreenToDIPPoint(cursor_pos_pixels); 234 return ScreenToDIPPoint(cursor_pos_pixels);
115 } 235 }
116 236
117 gfx::NativeWindow ScreenWin::GetWindowUnderCursor() { 237 gfx::NativeWindow ScreenWin::GetWindowUnderCursor() {
118 POINT cursor_loc; 238 POINT cursor_loc;
119 HWND hwnd = GetCursorPos(&cursor_loc) ? WindowFromPoint(cursor_loc) : NULL; 239 HWND hwnd = GetCursorPos(&cursor_loc) ? WindowFromPoint(cursor_loc) : NULL;
120 return GetNativeWindowFromHWND(hwnd); 240 return GetNativeWindowFromHWND(hwnd);
121 } 241 }
122 242
123 gfx::NativeWindow ScreenWin::GetWindowAtScreenPoint(const gfx::Point& point) { 243 gfx::NativeWindow ScreenWin::GetWindowAtScreenPoint(const gfx::Point& point) {
124 gfx::Point point_in_pixels = gfx::win::DIPToScreenPoint(point); 244 gfx::Point point_in_pixels = DIPToScreenPoint(point);
125 return GetNativeWindowFromHWND(WindowFromPoint(point_in_pixels.ToPOINT())); 245 return GetNativeWindowFromHWND(WindowFromPoint(point_in_pixels.ToPOINT()));
126 } 246 }
127 247
128 int ScreenWin::GetNumDisplays() const { 248 int ScreenWin::GetNumDisplays() const {
129 return GetSystemMetrics(SM_CMONITORS); 249 return GetSystemMetrics(SM_CMONITORS);
130 } 250 }
131 251
132 std::vector<gfx::Display> ScreenWin::GetAllDisplays() const { 252 std::vector<gfx::Display> ScreenWin::GetAllDisplays() const {
133 return displays_; 253 std::vector<gfx::Display> displays;
254 for (const DisplayWin& display : displays_) {
255 displays.push_back(display);
256 }
257 return displays;
134 } 258 }
135 259
136 gfx::Display ScreenWin::GetDisplayNearestWindow(gfx::NativeView window) const { 260 gfx::Display ScreenWin::GetDisplayNearestWindow(gfx::NativeView window) const {
137 HWND window_hwnd = GetHWNDFromNativeView(window); 261 HWND window_hwnd = GetHWNDFromNativeView(window);
138 if (!window_hwnd) { 262 if (!window_hwnd) {
139 // When |window| isn't rooted to a display, we should just return the 263 // When |window| isn't rooted to a display, we should just return the
140 // default display so we get some correct display information like the 264 // default display so we get some correct display information like the
141 // scaling factor. 265 // scaling factor.
142 return GetPrimaryDisplay(); 266 return GetPrimaryDisplay();
143 } 267 }
144 268 return GetDisplayNearestHWND(window_hwnd);
145 MONITORINFOEX monitor_info;
146 monitor_info.cbSize = sizeof(monitor_info);
147 GetMonitorInfo(MonitorFromWindow(window_hwnd, MONITOR_DEFAULTTONEAREST),
148 &monitor_info);
149 return GetDisplay(monitor_info);
150 } 269 }
151 270
152 gfx::Display ScreenWin::GetDisplayNearestPoint(const gfx::Point& point) const { 271 gfx::Display ScreenWin::GetDisplayNearestPoint(const gfx::Point& point) const {
153 gfx::Point point_in_pixels = gfx::win::DIPToScreenPoint(point); 272 return GetDisplayNearestScreenPoint(DIPToScreenPoint(point));
154 POINT initial_loc = { point_in_pixels.x(), point_in_pixels.y() };
155 HMONITOR monitor = MonitorFromPoint(initial_loc, MONITOR_DEFAULTTONEAREST);
156 MONITORINFOEX mi;
157 ZeroMemory(&mi, sizeof(MONITORINFOEX));
158 mi.cbSize = sizeof(mi);
159 if (monitor && GetMonitorInfo(monitor, &mi)) {
160 return GetDisplay(mi);
161 }
162 return gfx::Display();
163 } 273 }
164 274
165 gfx::Display ScreenWin::GetDisplayMatching(const gfx::Rect& match_rect) const { 275 gfx::Display ScreenWin::GetDisplayMatching(const gfx::Rect& match_rect) const {
166 RECT other_bounds_rect = match_rect.ToRECT(); 276 return GetDisplayNearestScreenRect(match_rect);
167 MONITORINFOEX monitor_info = GetMonitorInfoForMonitor(MonitorFromRect(
168 &other_bounds_rect, MONITOR_DEFAULTTONEAREST));
169 return GetDisplay(monitor_info);
170 } 277 }
171 278
172 gfx::Display ScreenWin::GetPrimaryDisplay() const { 279 gfx::Display ScreenWin::GetPrimaryDisplay() const {
173 MONITORINFOEX mi = GetMonitorInfoForMonitor( 280 DisplayWin display = GetDisplayWin(MonitorInfoFromHMONITOR(MonitorFromWindow(
174 MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY)); 281 NULL, MONITOR_DEFAULTTOPRIMARY)));
175 gfx::Display display = GetDisplay(mi);
176 // TODO(kevers|girard): Test if these checks can be reintroduced for high-DIP 282 // TODO(kevers|girard): Test if these checks can be reintroduced for high-DIP
177 // once more of the app is DIP-aware. 283 // once more of the app is DIP-aware.
178 if (GetDPIScale() == 1.0) { 284 if (display.device_scale_factor() == 1.0) {
179 DCHECK_EQ(GetSystemMetrics(SM_CXSCREEN), display.size().width()); 285 DCHECK_EQ(GetSystemMetrics(SM_CXSCREEN), display.size().width());
180 DCHECK_EQ(GetSystemMetrics(SM_CYSCREEN), display.size().height()); 286 DCHECK_EQ(GetSystemMetrics(SM_CYSCREEN), display.size().height());
181 } 287 }
182 return display; 288 return display;
183 } 289 }
184 290
185 void ScreenWin::AddObserver(DisplayObserver* observer) { 291 void ScreenWin::AddObserver(DisplayObserver* observer) {
186 change_notifier_.AddObserver(observer); 292 change_notifier_.AddObserver(observer);
187 } 293 }
188 294
189 void ScreenWin::RemoveObserver(DisplayObserver* observer) { 295 void ScreenWin::RemoveObserver(DisplayObserver* observer) {
190 change_notifier_.RemoveObserver(observer); 296 change_notifier_.RemoveObserver(observer);
191 } 297 }
192 298
299 gfx::Rect ScreenWin::ScreenToDIPRectInWindow(
300 NativeView view, const gfx::Rect& screen_rect) const {
301 HWND hwnd = view ? GetHWNDFromNativeView(view) : NULL;
302 return ScreenWin::ScreenToDIPRect(hwnd, screen_rect);
303 }
304
305 gfx::Rect ScreenWin::DIPToScreenRectInWindow(NativeView view,
306 const gfx::Rect& dip_rect) const {
307 HWND hwnd = view ? GetHWNDFromNativeView(view) : NULL;
308 return ScreenWin::DIPToScreenRect(hwnd, dip_rect);
309 }
310
311 ScreenWin::DisplayWin::DisplayWin() : gfx::Display() {}
312
313 ScreenWin::DisplayWin::DisplayWin(const DisplayInfo& display_info)
314 : gfx::Display(display_info.id()),
315 pixel_bounds_(display_info.screen_rect()) {
316 float scale_factor = display_info.device_scale_factor();
317 set_device_scale_factor(scale_factor);
318 set_work_area(gfx::ScaleToEnclosedRect(display_info.screen_work_rect(),
319 1.0f / scale_factor));
320 set_bounds(gfx::ScaleToEnclosedRect(display_info.screen_rect(),
321 1.0f / scale_factor));
322 }
323
324 ScreenWin::DisplayWin::DisplayWin(const DisplayWin& ref,
325 const DisplayInfo& display_info)
326 : gfx::Display(display_info.id()),
327 pixel_bounds_(display_info.screen_rect()) {
328 float scale_factor = display_info.device_scale_factor();
329 set_device_scale_factor(scale_factor);
330 const gfx::Insets pixel_insets =
331 display_info.screen_rect().InsetsFrom(display_info.screen_work_rect());
332 const gfx::Insets scaled_insets = pixel_insets.Scale(1.0f / scale_factor,
333 1.0f / scale_factor);
334 const gfx::Rect scaled_bounds =
335 gfx::win::ScaleAndPositionRect(ref.bounds(),
336 ref.physical_bounds(),
337 display_info.screen_rect(),
338 scale_factor);
339 set_bounds(scaled_bounds);
340 gfx::Rect scaled_work_area(scaled_bounds);
341 scaled_work_area.Inset(scaled_insets);
342 set_work_area(scaled_work_area);
343 }
344
345 // static
346 ScreenWin::DisplayWin ScreenWin::GetDisplayNearestHWND(HWND hwnd) {
347 ScreenWin* screen = GetNativeScreenWin();
348 return screen->GetDisplayWin(screen->MonitorInfoFromWindow(hwnd));
349 }
350
351 // static
352 ScreenWin::DisplayWin ScreenWin::GetDisplayNearestScreenRect(
353 const Rect& screen_rect) {
354 ScreenWin* screen = GetNativeScreenWin();
355 return screen->GetDisplayWin(screen->MonitorInfoFromScreenRect(screen_rect));
356 }
357
358 // static
359 ScreenWin::DisplayWin ScreenWin::GetDisplayNearestScreenPoint(
360 const Point& screen_point) {
361 ScreenWin* screen = GetNativeScreenWin();
362 return screen->GetDisplayWin(
363 screen->MonitorInfoFromScreenPoint(screen_point));
364 }
365
366 // static
367 ScreenWin::DisplayWin ScreenWin::GetDisplayNearestDIPRect(
368 const Rect& dip_rect) {
369 ScreenWin* screen = GetNativeScreenWin();
370 DisplayWin closest_display;
371 int64_t closest_distance_squared = INT64_MAX;
372 for (const DisplayWin& display : screen->displays_) {
373 gfx::Rect dip_bounds = display.bounds();
374 int64_t distance_squared =
375 gfx::win::SquaredDistanceBetweenRects(dip_rect, dip_bounds);
376 if (distance_squared == 0) {
377 return display;
378 } else if (distance_squared < closest_distance_squared) {
379 closest_distance_squared = distance_squared;
380 closest_display = display;
381 }
382 }
383 return closest_display;
384 }
385
386 // static
387 ScreenWin::DisplayWin ScreenWin::GetDisplayNearestDIPPoint(
388 const Point& dip_point) {
389 ScreenWin* screen = GetNativeScreenWin();
390 DisplayWin primary_display;
391 for (const DisplayWin& display : screen->displays_) {
392 gfx::Rect dip_bounds = display.bounds();
393 if (dip_bounds.Contains(dip_point))
394 return display;
395 else if (dip_bounds.origin().IsOrigin())
396 primary_display = display;
397 }
398 return primary_display;
399 }
400
401 // static
402 float ScreenWin::GetScaleFactorForHWND(HWND hwnd) {
403 DCHECK(hwnd);
404 ScreenWin* screen = GetNativeScreenWin();
405 HWND rootHwnd = screen->GetRootWindow(hwnd);
406 return GetDisplayNearestHWND(rootHwnd).device_scale_factor();
407 }
408
409 // static
410 float ScreenWin::GetScaleFactorForScreenPoint(const Point& screen_point) {
411 return GetDisplayNearestScreenPoint(screen_point).device_scale_factor();
412 }
413
414 // static
415 std::vector<ScreenWin::DisplayInfo>::const_iterator
416 ScreenWin::FindTouchingDisplayInfo(
417 const DisplayWin& display, const std::vector<DisplayInfo>& display_infos) {
418 auto end = display_infos.end();
419 for (auto display_info = display_infos.begin();
420 display_info != end;
421 display_info++) {
422 gfx::win::RectEdge edge = gfx::win::RectTouch(display.physical_bounds(),
423 display_info->screen_rect());
424 if (edge != gfx::win::RectEdge::NONE) {
425 return display_info;
426 }
427 }
428 return end;
429 }
430
431 // static
432 std::vector<ScreenWin::DisplayWin> ScreenWin::GetDisplaysFromDisplayInfos(
433 const std::vector<ScreenWin::DisplayInfo>& display_infos) {
434 std::vector<DisplayInfo> display_infos_remaining = display_infos;
435
436 // Seed the primary display to layout all the other displays.
437 std::vector<DisplayWin> displays;
438 for (auto current = display_infos_remaining.begin();
439 current != display_infos_remaining.end();
440 current++) {
441 if (current->screen_rect().origin().IsOrigin()) {
442 displays.push_back(DisplayWin(*current));
443 display_infos_remaining.erase(current);
444 break;
445 }
446 }
447
448 // Scale touching display_infos relative to each other.
449 size_t display_infos_at_cycle_start = 0;
450 while ((display_infos_remaining.size() > 0) &&
451 (display_infos_remaining.size() != display_infos_at_cycle_start)) {
452 display_infos_at_cycle_start = display_infos_remaining.size();
453 for (const DisplayWin& display : displays) {
454 auto display_info = FindTouchingDisplayInfo(display,
455 display_infos_remaining);
456 if (display_info != display_infos_remaining.end()) {
457 displays.push_back(DisplayWin(display, *display_info));
458 display_infos_remaining.erase(display_info);
459 break;
460 }
461 }
462 }
463
464 // Under Windows DPI virtualization, not all display_infos touch, so scale
465 // the remaining display infos relative to the origin.
466 for (const DisplayInfo& display_info : display_infos_remaining) {
467 displays.push_back(DisplayWin(display_info));
468 }
469
470 return displays;
471 }
472
473 // static
474 std::vector<ScreenWin::DisplayWin> ScreenWin::GetDisplays() {
475 std::vector<DisplayInfo> display_infos;
476 EnumDisplayMonitors(NULL, NULL, EnumMonitorCallback,
477 reinterpret_cast<LPARAM>(&display_infos));
478 return GetDisplaysFromDisplayInfos(display_infos);
479 }
480
481 // static
482 BOOL CALLBACK ScreenWin::EnumMonitorCallback(HMONITOR monitor,
483 HDC hdc,
484 LPRECT rect,
485 LPARAM data) {
486 std::vector<DisplayInfo>* display_infos =
487 reinterpret_cast<std::vector<DisplayInfo>*>(data);
488 DCHECK(display_infos);
489 display_infos->push_back(DisplayInfo(monitor, gfx::GetDPIScale()));
490 return TRUE;
491 }
492
193 void ScreenWin::OnWndProc(HWND hwnd, 493 void ScreenWin::OnWndProc(HWND hwnd,
194 UINT message, 494 UINT message,
195 WPARAM wparam, 495 WPARAM wparam,
196 LPARAM lparam) { 496 LPARAM lparam) {
197 if (message != WM_DISPLAYCHANGE) 497 if (message != WM_DISPLAYCHANGE)
198 return; 498 return;
199 499
200 std::vector<gfx::Display> old_displays = displays_; 500 std::vector<gfx::Display> old_displays = GetAllDisplays();
201 displays_ = GetDisplays(); 501 displays_ = GetDisplays();
502 std::vector<gfx::Display> new_displays = GetAllDisplays();
202 503
203 change_notifier_.NotifyDisplaysChanged(old_displays, displays_); 504 change_notifier_.NotifyDisplaysChanged(old_displays, new_displays);
204 } 505 }
205 506
206 // static 507 MONITORINFOEX ScreenWin::MonitorInfoFromScreenPoint(
207 std::vector<gfx::Display> ScreenWin::GetDisplaysForMonitorInfos( 508 const gfx::Point& screen_point) const {
208 const std::vector<MONITORINFOEX>& monitor_infos) { 509 POINT initial_loc = { screen_point.x(), screen_point.y() };
209 std::vector<gfx::Display> displays; 510 return MonitorInfoFromHMONITOR(::MonitorFromPoint(initial_loc,
210 for (const MONITORINFOEX& monitor_info : monitor_infos) 511 MONITOR_DEFAULTTONEAREST));
211 displays.push_back(GetDisplay(monitor_info)); 512 }
212 513
213 return displays; 514 MONITORINFOEX ScreenWin::MonitorInfoFromScreenRect(const gfx::Rect& screen_rect)
515 const {
516 RECT win_rect = screen_rect.ToRECT();
517 return MonitorInfoFromHMONITOR(::MonitorFromRect(&win_rect,
518 MONITOR_DEFAULTTONEAREST));
519 }
520
521 MONITORINFOEX ScreenWin::MonitorInfoFromWindow(HWND hwnd) const {
522 return MonitorInfoFromHMONITOR(::MonitorFromWindow(hwnd,
523 MONITOR_DEFAULTTONEAREST));
524 }
525
526 HWND ScreenWin::GetRootWindow(HWND hwnd) const {
527 return GetAncestor(hwnd, GA_ROOT);
528 }
529
530 ScreenWin::DisplayWin ScreenWin::GetDisplayWin(
531 const MONITORINFOEX& monitor_info) const {
532 int64_t id = HashDeviceName(monitor_info.szDevice);
533 for (const DisplayWin& display : displays_) {
534 if (display.id() == id)
535 return display;
536 }
537 NOTREACHED();
538 return DisplayWin();
214 } 539 }
215 540
216 } // namespace gfx 541 } // namespace gfx
OLDNEW
« ui/gfx/display.h ('K') | « ui/gfx/screen_win.h ('k') | ui/gfx/screen_win_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698