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

Side by Side Diff: ui/display/win/screen_win.cc

Issue 2012083002: Multiple DPI Tracking for ScreenWin (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: CR Feedback Created 4 years, 6 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/display/win/screen_win.h ('k') | ui/display/win/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/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
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
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
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
OLDNEW
« no previous file with comments | « ui/display/win/screen_win.h ('k') | ui/display/win/screen_win_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698