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

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: Make DisplayWin Standalone 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
« no previous file with comments | « ui/gfx/screen_win.h ('k') | ui/gfx/screen_win_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 {
83 public:
84 explicit DisplayWin();
85 explicit DisplayWin(const DisplayInfo& display_info);
86 DisplayWin(const DisplayWin& ref, const DisplayInfo& display_info);
87
88 const Display& display() const { return display_; }
89 const Rect& physical_bounds() const { return pixel_bounds_; }
90
91 private:
92 Display display_;
93 Rect pixel_bounds_;
94 };
95
92 ScreenWin::ScreenWin() 96 ScreenWin::ScreenWin()
93 : singleton_hwnd_observer_(new SingletonHwndObserver( 97 : singleton_hwnd_observer_(new SingletonHwndObserver(
94 base::Bind(&ScreenWin::OnWndProc, base::Unretained(this)))), 98 base::Bind(&ScreenWin::OnWndProc, base::Unretained(this)))),
95 displays_(GetDisplays()) { 99 display_wins_(GetDisplayWins()) {}
100
101 ScreenWin::~ScreenWin() {}
102
103 // static
104 Point ScreenWin::ScreenToDIPPoint(const Point& pixel_point) {
105 DisplayWin display_win = GetDisplayNearestScreenPoint(pixel_point);
106 Display display = display_win.display();
107 return ScalePointRelative(display_win.physical_bounds().origin(),
108 display.bounds().origin(),
109 1.0f / display.device_scale_factor(),
110 pixel_point);
96 } 111 }
97 112
98 ScreenWin::~ScreenWin() {} 113 // static
114 Point ScreenWin::DIPToScreenPoint(const Point& dip_point) {
115 DisplayWin display_win = GetDisplayNearestDIPPoint(dip_point);
116 Display display = display_win.display();
117 return ScalePointRelative(display.bounds().origin(),
118 display_win.physical_bounds().origin(),
119 display.device_scale_factor(),
120 dip_point);
121 }
122
123
124 Point ScreenWin::ClientToDIPPoint(HWND hwnd, const Point& client_point) {
125 return ScaleToFlooredPoint(client_point, 1.0f / GetScaleFactorForHWND(hwnd));
126 }
127
128 Point ScreenWin::DIPToClientPoint(HWND hwnd, const Point& dip_point) {
129 return ScaleToFlooredPoint(dip_point, GetScaleFactorForHWND(hwnd));
130 }
131
132 // static
133 Rect ScreenWin::ScreenToDIPRect(HWND hwnd, const Rect& pixel_bounds) {
134 // It's important we scale the origin and size separately. If we instead
135 // calculated the size from the floored origin and ceiled right the size could
136 // vary depending upon where the two points land. That would cause problems
137 // for the places this code is used (in particular mapping from native window
138 // bounds to DIPs).
139 if (hwnd) {
140 return Rect(ScreenToDIPPoint(pixel_bounds.origin()),
141 ScreenToDIPSize(hwnd, pixel_bounds.size()));
142 }
143 float scale_factor =
144 GetDisplayNearestScreenRect(pixel_bounds).display().device_scale_factor();
145 return Rect(ScreenToDIPPoint(pixel_bounds.origin()),
146 ScaleToCeiledSize(pixel_bounds.size(), 1.0f / scale_factor));
147 }
148
149 // static
150 Rect ScreenWin::DIPToScreenRect(HWND hwnd, const Rect& dip_bounds) {
151 // See comment in ScreenToDIPRect for why we calculate size like this.
152 if (hwnd) {
153 return Rect(DIPToScreenPoint(dip_bounds.origin()),
154 DIPToScreenSize(hwnd, dip_bounds.size()));
155 }
156 // Because origins don't change for screen points and scaling factors are
157 // greater than 1, the monitor bounding rect always contains the DIP point.
158 float scale_factor =
159 GetDisplayNearestDIPRect(dip_bounds).display().device_scale_factor();
160 return Rect(DIPToScreenPoint(dip_bounds.origin()),
161 ScaleToCeiledSize(dip_bounds.size(), scale_factor));
162 }
163
164 // static
165 Rect ScreenWin::ClientToDIPRect(HWND hwnd, const Rect& pixel_bounds) {
166 // See comment in ScreenToDIPRect for why we calculate size like this.
167 return Rect(ClientToDIPPoint(hwnd, pixel_bounds.origin()),
168 ScreenToDIPSize(hwnd, pixel_bounds.size()));
169 }
170
171 // static
172 Rect ScreenWin::DIPToClientRect(HWND hwnd, const Rect& dip_bounds) {
173 // See comment in ScreenToDIPRect for why we calculate size like this.
174 return Rect(DIPToClientPoint(hwnd, dip_bounds.origin()),
175 DIPToScreenSize(hwnd, dip_bounds.size()));
176 }
177
178 // static
179 Size ScreenWin::ScreenToDIPSize(HWND hwnd, const Size& size_in_pixels) {
180 // Always ceil sizes. Otherwise we may be leaving off part of the bounds.
181 return ScaleToCeiledSize(size_in_pixels, 1.0f / GetScaleFactorForHWND(hwnd));
182 }
183
184 // static
185 Size ScreenWin::DIPToScreenSize(HWND hwnd, const Size& dip_size) {
186 // Always ceil sizes. Otherwise we may be leaving off part of the bounds.
187 return ScaleToCeiledSize(dip_size, GetScaleFactorForHWND(hwnd));
188 }
99 189
100 HWND ScreenWin::GetHWNDFromNativeView(NativeView window) const { 190 HWND ScreenWin::GetHWNDFromNativeView(NativeView window) const {
101 NOTREACHED(); 191 NOTREACHED();
102 return NULL; 192 return NULL;
103 } 193 }
104 194
105 NativeWindow ScreenWin::GetNativeWindowFromHWND(HWND hwnd) const { 195 NativeWindow ScreenWin::GetNativeWindowFromHWND(HWND hwnd) const {
106 NOTREACHED(); 196 NOTREACHED();
107 return NULL; 197 return NULL;
108 } 198 }
109 199
200 ScreenWin::DisplayInfo::DisplayInfo(HMONITOR monitor,
201 float device_scale_factor) :
202 device_scale_factor_(device_scale_factor){
203 MONITORINFOEX monitor_info;
204 ::ZeroMemory(&monitor_info, sizeof(monitor_info));
205 monitor_info.cbSize = sizeof(monitor_info);
206 ::GetMonitorInfo(monitor, &monitor_info);
207 InitializeFromMonitorInfo(monitor_info);
208 }
209
210 ScreenWin::DisplayInfo::DisplayInfo(const MONITORINFOEX& monitor_info,
211 gfx::Display::Rotation rotation,
212 float device_scale_factor)
213 : rotation_(rotation),
214 device_scale_factor_(device_scale_factor) {
215 InitializeFromMonitorInfo(monitor_info);
216 }
217
218 void ScreenWin::DisplayInfo::InitializeFromMonitorInfo(
219 const MONITORINFOEX& monitor_info) {
220 id_ = ScreenWin::HashDeviceName(monitor_info.szDevice);
221 screen_rect_ = gfx::Rect(monitor_info.rcMonitor);
222 screen_work_rect_ = gfx::Rect(monitor_info.rcWork);
223 rotation_ = GetRotationForDevice(monitor_info.szDevice);
224 }
225
226 ScreenWin::ScreenWin(const std::vector<ScreenWin::DisplayInfo>& display_infos) {
227 display_wins_ = GetDisplaysFromDisplayInfos(display_infos);
228 }
229
230 int64_t ScreenWin::HashDeviceName(const wchar_t* device_name) {
231 return static_cast<int64_t>(base::Hash(base::WideToUTF8(device_name)));
232 }
233
110 gfx::Point ScreenWin::GetCursorScreenPoint() { 234 gfx::Point ScreenWin::GetCursorScreenPoint() {
111 POINT pt; 235 POINT pt;
112 GetCursorPos(&pt); 236 GetCursorPos(&pt);
113 gfx::Point cursor_pos_pixels(pt); 237 gfx::Point cursor_pos_pixels(pt);
114 return gfx::win::ScreenToDIPPoint(cursor_pos_pixels); 238 return ScreenToDIPPoint(cursor_pos_pixels);
115 } 239 }
116 240
117 gfx::NativeWindow ScreenWin::GetWindowUnderCursor() { 241 gfx::NativeWindow ScreenWin::GetWindowUnderCursor() {
118 POINT cursor_loc; 242 POINT cursor_loc;
119 HWND hwnd = GetCursorPos(&cursor_loc) ? WindowFromPoint(cursor_loc) : NULL; 243 HWND hwnd = GetCursorPos(&cursor_loc) ? WindowFromPoint(cursor_loc) : NULL;
120 return GetNativeWindowFromHWND(hwnd); 244 return GetNativeWindowFromHWND(hwnd);
121 } 245 }
122 246
123 gfx::NativeWindow ScreenWin::GetWindowAtScreenPoint(const gfx::Point& point) { 247 gfx::NativeWindow ScreenWin::GetWindowAtScreenPoint(const gfx::Point& point) {
124 gfx::Point point_in_pixels = gfx::win::DIPToScreenPoint(point); 248 gfx::Point point_in_pixels = DIPToScreenPoint(point);
125 return GetNativeWindowFromHWND(WindowFromPoint(point_in_pixels.ToPOINT())); 249 return GetNativeWindowFromHWND(WindowFromPoint(point_in_pixels.ToPOINT()));
126 } 250 }
127 251
128 int ScreenWin::GetNumDisplays() const { 252 int ScreenWin::GetNumDisplays() const {
129 return GetSystemMetrics(SM_CMONITORS); 253 return GetSystemMetrics(SM_CMONITORS);
130 } 254 }
131 255
132 std::vector<gfx::Display> ScreenWin::GetAllDisplays() const { 256 std::vector<gfx::Display> ScreenWin::GetAllDisplays() const {
133 return displays_; 257 std::vector<gfx::Display> displays;
258 for (const DisplayWin& display_win : display_wins_) {
259 displays.push_back(display_win.display());
260 }
261 return displays;
134 } 262 }
135 263
136 gfx::Display ScreenWin::GetDisplayNearestWindow(gfx::NativeView window) const { 264 gfx::Display ScreenWin::GetDisplayNearestWindow(gfx::NativeView window) const {
137 HWND window_hwnd = GetHWNDFromNativeView(window); 265 HWND window_hwnd = GetHWNDFromNativeView(window);
138 if (!window_hwnd) { 266 if (!window_hwnd) {
139 // When |window| isn't rooted to a display, we should just return the 267 // 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 268 // default display so we get some correct display information like the
141 // scaling factor. 269 // scaling factor.
142 return GetPrimaryDisplay(); 270 return GetPrimaryDisplay();
143 } 271 }
144 272 return GetDisplayNearestHWND(window_hwnd).display();
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 } 273 }
151 274
152 gfx::Display ScreenWin::GetDisplayNearestPoint(const gfx::Point& point) const { 275 gfx::Display ScreenWin::GetDisplayNearestPoint(const gfx::Point& point) const {
153 gfx::Point point_in_pixels = gfx::win::DIPToScreenPoint(point); 276 return GetDisplayNearestScreenPoint(DIPToScreenPoint(point)).display();
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 } 277 }
164 278
165 gfx::Display ScreenWin::GetDisplayMatching(const gfx::Rect& match_rect) const { 279 gfx::Display ScreenWin::GetDisplayMatching(const gfx::Rect& match_rect) const {
166 RECT other_bounds_rect = match_rect.ToRECT(); 280 return GetDisplayNearestScreenRect(match_rect).display();
167 MONITORINFOEX monitor_info = GetMonitorInfoForMonitor(MonitorFromRect(
168 &other_bounds_rect, MONITOR_DEFAULTTONEAREST));
169 return GetDisplay(monitor_info);
170 } 281 }
171 282
172 gfx::Display ScreenWin::GetPrimaryDisplay() const { 283 gfx::Display ScreenWin::GetPrimaryDisplay() const {
173 MONITORINFOEX mi = GetMonitorInfoForMonitor( 284 Display display =
174 MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY)); 285 GetDisplayWin(MonitorInfoFromHMONITOR(MonitorFromWindow(
175 gfx::Display display = GetDisplay(mi); 286 NULL, MONITOR_DEFAULTTOPRIMARY))).display();
176 // TODO(kevers|girard): Test if these checks can be reintroduced for high-DIP 287 // TODO(kevers|girard): Test if these checks can be reintroduced for high-DIP
177 // once more of the app is DIP-aware. 288 // once more of the app is DIP-aware.
178 if (GetDPIScale() == 1.0) { 289 if (display.device_scale_factor() == 1.0) {
179 DCHECK_EQ(GetSystemMetrics(SM_CXSCREEN), display.size().width()); 290 DCHECK_EQ(GetSystemMetrics(SM_CXSCREEN), display.size().width());
180 DCHECK_EQ(GetSystemMetrics(SM_CYSCREEN), display.size().height()); 291 DCHECK_EQ(GetSystemMetrics(SM_CYSCREEN), display.size().height());
181 } 292 }
182 return display; 293 return display;
183 } 294 }
184 295
185 void ScreenWin::AddObserver(DisplayObserver* observer) { 296 void ScreenWin::AddObserver(DisplayObserver* observer) {
186 change_notifier_.AddObserver(observer); 297 change_notifier_.AddObserver(observer);
187 } 298 }
188 299
189 void ScreenWin::RemoveObserver(DisplayObserver* observer) { 300 void ScreenWin::RemoveObserver(DisplayObserver* observer) {
190 change_notifier_.RemoveObserver(observer); 301 change_notifier_.RemoveObserver(observer);
191 } 302 }
192 303
304 gfx::Rect ScreenWin::ScreenToDIPRectInWindow(
305 NativeView view, const gfx::Rect& screen_rect) const {
306 HWND hwnd = view ? GetHWNDFromNativeView(view) : NULL;
307 return ScreenWin::ScreenToDIPRect(hwnd, screen_rect);
308 }
309
310 gfx::Rect ScreenWin::DIPToScreenRectInWindow(NativeView view,
311 const gfx::Rect& dip_rect) const {
312 HWND hwnd = view ? GetHWNDFromNativeView(view) : NULL;
313 return ScreenWin::DIPToScreenRect(hwnd, dip_rect);
314 }
315
316 ScreenWin::DisplayWin::DisplayWin() = default;
317
318 ScreenWin::DisplayWin::DisplayWin(const DisplayInfo& display_info)
319 : display_(display_info.id()),
320 pixel_bounds_(display_info.screen_rect()) {
321 float scale_factor = display_info.device_scale_factor();
322 display_.set_device_scale_factor(scale_factor);
323 display_.set_work_area(
324 gfx::ScaleToEnclosedRect(display_info.screen_work_rect(),
325 1.0f / scale_factor));
326 display_.set_bounds(gfx::ScaleToEnclosedRect(display_info.screen_rect(),
327 1.0f / scale_factor));
328 }
329
330 ScreenWin::DisplayWin::DisplayWin(const DisplayWin& ref,
331 const DisplayInfo& display_info)
332 : display_(display_info.id()),
333 pixel_bounds_(display_info.screen_rect()) {
334 float scale_factor = display_info.device_scale_factor();
335 display_.set_device_scale_factor(scale_factor);
336 const gfx::Insets pixel_insets =
337 display_info.screen_rect().InsetsFrom(display_info.screen_work_rect());
338 const gfx::Insets scaled_insets = pixel_insets.Scale(1.0f / scale_factor,
339 1.0f / scale_factor);
340 const gfx::Rect scaled_bounds =
341 gfx::win::ScaleAndPositionRect(ref.display_.bounds(),
342 ref.physical_bounds(),
343 display_info.screen_rect(),
344 scale_factor);
345 display_.set_bounds(scaled_bounds);
346 gfx::Rect scaled_work_area(scaled_bounds);
347 scaled_work_area.Inset(scaled_insets);
348 display_.set_work_area(scaled_work_area);
349 }
350
351 // static
352 ScreenWin::DisplayWin ScreenWin::GetDisplayNearestHWND(HWND hwnd) {
353 ScreenWin* screen = GetNativeScreenWin();
354 return screen->GetDisplayWin(screen->MonitorInfoFromWindow(hwnd));
355 }
356
357 // static
358 ScreenWin::DisplayWin ScreenWin::GetDisplayNearestScreenRect(
359 const Rect& screen_rect) {
360 ScreenWin* screen = GetNativeScreenWin();
361 return screen->GetDisplayWin(screen->MonitorInfoFromScreenRect(screen_rect));
362 }
363
364 // static
365 ScreenWin::DisplayWin ScreenWin::GetDisplayNearestScreenPoint(
366 const Point& screen_point) {
367 ScreenWin* screen = GetNativeScreenWin();
368 return screen->GetDisplayWin(
369 screen->MonitorInfoFromScreenPoint(screen_point));
370 }
371
372 // static
373 ScreenWin::DisplayWin ScreenWin::GetDisplayNearestDIPRect(
374 const Rect& dip_rect) {
375 ScreenWin* screen = GetNativeScreenWin();
376 DisplayWin closest_display_win;
377 int64_t closest_distance_squared = INT64_MAX;
378 for (const DisplayWin& display_win : screen->display_wins_) {
379 Display display = display_win.display();
380 gfx::Rect dip_bounds = display.bounds();
381 int64_t distance_squared =
382 gfx::win::SquaredDistanceBetweenRects(dip_rect, dip_bounds);
383 if (distance_squared == 0) {
384 return display_win;
385 } else if (distance_squared < closest_distance_squared) {
386 closest_distance_squared = distance_squared;
387 closest_display_win = display_win;
388 }
389 }
390 return closest_display_win;
391 }
392
393 // static
394 ScreenWin::DisplayWin ScreenWin::GetDisplayNearestDIPPoint(
395 const Point& dip_point) {
396 ScreenWin* screen = GetNativeScreenWin();
397 DisplayWin primary_display_win;
398 for (const DisplayWin& display_win : screen->display_wins_) {
399 Display display = display_win.display();
400 gfx::Rect dip_bounds = display.bounds();
401 if (dip_bounds.Contains(dip_point))
402 return display_win;
403 else if (dip_bounds.origin().IsOrigin())
404 primary_display_win = display_win;
405 }
406 return primary_display_win;
407 }
408
409 // static
410 float ScreenWin::GetScaleFactorForHWND(HWND hwnd) {
411 DCHECK(hwnd);
412 ScreenWin* screen = GetNativeScreenWin();
413 HWND rootHwnd = screen->GetRootWindow(hwnd);
414 return GetDisplayNearestHWND(rootHwnd).display().device_scale_factor();
415 }
416
417 // static
418 float ScreenWin::GetScaleFactorForScreenPoint(const Point& screen_point) {
419 Display display = GetDisplayNearestScreenPoint(screen_point).display();
420 return display.device_scale_factor();
421 }
422
423 // static
424 std::vector<ScreenWin::DisplayInfo>::const_iterator
425 ScreenWin::FindTouchingDisplayInfo(
426 const DisplayWin& display_win,
427 const std::vector<DisplayInfo>& display_infos) {
428 auto end = display_infos.end();
429 for (auto display_info = display_infos.begin();
430 display_info != end;
431 display_info++) {
432 gfx::win::RectEdge edge = gfx::win::RectTouch(display_win.physical_bounds(),
433 display_info->screen_rect());
434 if (edge != gfx::win::RectEdge::NONE) {
435 return display_info;
436 }
437 }
438 return end;
439 }
440
441 // static
442 std::vector<ScreenWin::DisplayWin> ScreenWin::GetDisplaysFromDisplayInfos(
443 const std::vector<ScreenWin::DisplayInfo>& display_infos) {
444 std::vector<DisplayInfo> display_infos_remaining = display_infos;
445
446 // Seed the primary display to layout all the other displays.
447 std::vector<DisplayWin> display_wins;
448 for (auto current = display_infos_remaining.begin();
449 current != display_infos_remaining.end();
450 current++) {
451 if (current->screen_rect().origin().IsOrigin()) {
452 display_wins.push_back(DisplayWin(*current));
453 display_infos_remaining.erase(current);
454 break;
455 }
456 }
457
458 // Scale touching display_infos relative to each other.
459 size_t display_infos_at_cycle_start = 0;
460 while ((display_infos_remaining.size() > 0) &&
461 (display_infos_remaining.size() != display_infos_at_cycle_start)) {
462 display_infos_at_cycle_start = display_infos_remaining.size();
463 for (const DisplayWin& display_win : display_wins) {
464 auto display_info = FindTouchingDisplayInfo(display_win,
465 display_infos_remaining);
466 if (display_info != display_infos_remaining.end()) {
467 display_wins.push_back(DisplayWin(display_win, *display_info));
468 display_infos_remaining.erase(display_info);
469 break;
470 }
471 }
472 }
473
474 // Under Windows DPI virtualization, not all display_infos touch, so scale
475 // the remaining display infos relative to the origin.
476 for (const DisplayInfo& display_info : display_infos_remaining) {
477 display_wins.push_back(DisplayWin(display_info));
478 }
479
480 return display_wins;
481 }
482
483 // static
484 std::vector<ScreenWin::DisplayWin> ScreenWin::GetDisplayWins() {
485 std::vector<DisplayInfo> display_infos;
486 EnumDisplayMonitors(NULL, NULL, EnumMonitorCallback,
487 reinterpret_cast<LPARAM>(&display_infos));
488 return GetDisplaysFromDisplayInfos(display_infos);
489 }
490
491 // static
492 BOOL CALLBACK ScreenWin::EnumMonitorCallback(HMONITOR monitor,
493 HDC hdc,
494 LPRECT rect,
495 LPARAM data) {
496 std::vector<DisplayInfo>* display_infos =
497 reinterpret_cast<std::vector<DisplayInfo>*>(data);
498 DCHECK(display_infos);
499 display_infos->push_back(DisplayInfo(monitor, gfx::GetDPIScale()));
500 return TRUE;
501 }
502
193 void ScreenWin::OnWndProc(HWND hwnd, 503 void ScreenWin::OnWndProc(HWND hwnd,
194 UINT message, 504 UINT message,
195 WPARAM wparam, 505 WPARAM wparam,
196 LPARAM lparam) { 506 LPARAM lparam) {
197 if (message != WM_DISPLAYCHANGE) 507 if (message != WM_DISPLAYCHANGE)
198 return; 508 return;
199 509
200 std::vector<gfx::Display> old_displays = displays_; 510 std::vector<gfx::Display> old_displays = GetAllDisplays();
201 displays_ = GetDisplays(); 511 display_wins_ = GetDisplayWins();
512 std::vector<gfx::Display> new_displays = GetAllDisplays();
202 513
203 change_notifier_.NotifyDisplaysChanged(old_displays, displays_); 514 change_notifier_.NotifyDisplaysChanged(old_displays, new_displays);
204 } 515 }
205 516
206 // static 517 MONITORINFOEX ScreenWin::MonitorInfoFromScreenPoint(
207 std::vector<gfx::Display> ScreenWin::GetDisplaysForMonitorInfos( 518 const gfx::Point& screen_point) const {
208 const std::vector<MONITORINFOEX>& monitor_infos) { 519 POINT initial_loc = { screen_point.x(), screen_point.y() };
209 std::vector<gfx::Display> displays; 520 return MonitorInfoFromHMONITOR(::MonitorFromPoint(initial_loc,
210 for (const MONITORINFOEX& monitor_info : monitor_infos) 521 MONITOR_DEFAULTTONEAREST));
211 displays.push_back(GetDisplay(monitor_info)); 522 }
212 523
213 return displays; 524 MONITORINFOEX ScreenWin::MonitorInfoFromScreenRect(const gfx::Rect& screen_rect)
525 const {
526 RECT win_rect = screen_rect.ToRECT();
527 return MonitorInfoFromHMONITOR(::MonitorFromRect(&win_rect,
528 MONITOR_DEFAULTTONEAREST));
529 }
530
531 MONITORINFOEX ScreenWin::MonitorInfoFromWindow(HWND hwnd) const {
532 return MonitorInfoFromHMONITOR(::MonitorFromWindow(hwnd,
533 MONITOR_DEFAULTTONEAREST));
534 }
535
536 HWND ScreenWin::GetRootWindow(HWND hwnd) const {
537 return GetAncestor(hwnd, GA_ROOT);
538 }
539
540 ScreenWin::DisplayWin ScreenWin::GetDisplayWin(
541 const MONITORINFOEX& monitor_info) const {
542 int64_t id = HashDeviceName(monitor_info.szDevice);
543 for (const DisplayWin& display_win : display_wins_) {
544 if (display_win.display().id() == id)
545 return display_win;
546 }
547 NOTREACHED();
548 return DisplayWin();
214 } 549 }
215 550
216 } // namespace gfx 551 } // namespace gfx
OLDNEW
« no previous file with comments | « 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