Chromium Code Reviews| Index: ui/display/win/screen_win.cc |
| diff --git a/ui/display/win/screen_win.cc b/ui/display/win/screen_win.cc |
| index 654059ce32228515e73d3a9a895d786d4d708976..d839b1ff6b827275cae9529145264efd9fa29f8f 100644 |
| --- a/ui/display/win/screen_win.cc |
| +++ b/ui/display/win/screen_win.cc |
| @@ -18,15 +18,16 @@ |
| #include "ui/display/win/scaling_util.h" |
| #include "ui/display/win/screen_win_display.h" |
| #include "ui/gfx/geometry/point.h" |
| -#include "ui/gfx/geometry/point_conversions.h" |
| #include "ui/gfx/geometry/rect.h" |
| -#include "ui/gfx/geometry/rect_conversions.h" |
| -#include "ui/gfx/geometry/size_conversions.h" |
| +#include "ui/gfx/geometry/size.h" |
| +#include "ui/gfx/geometry/vector2d.h" |
| namespace display { |
| namespace win { |
| namespace { |
| +ScreenWin* g_screen_win_instance = nullptr; |
|
oshima
2016/05/26 21:52:58
nit: screen_win_instance_
https://www.chromium.or
robliao
2016/05/26 22:28:47
https://google.github.io/styleguide/cppguide.html#
oshima
2016/05/26 22:54:47
which I'm trying to fix when I see it to be more c
robliao
2016/05/26 23:19:24
As commonly used, a global variable doesn't guaran
oshima
2016/05/26 23:43:13
extenral linkage has nothing to do with g_ naming.
robliao
2016/05/27 00:47:13
Can you cite the rule you're discussing in those t
oshima
2016/05/27 02:02:04
First of all, google style guide has *no recommend
robliao
2016/05/27 17:15:30
Please note that the reference you cited from the
|
| + |
| std::vector<DisplayInfo> FindAndRemoveTouchingDisplayInfos( |
| const DisplayInfo& ref_display_info, |
| std::vector<DisplayInfo>* display_infos) { |
| @@ -141,6 +142,8 @@ BOOL CALLBACK EnumMonitorCallback(HMONITOR monitor, |
| std::vector<DisplayInfo>* display_infos = |
| reinterpret_cast<std::vector<DisplayInfo>*>(data); |
| DCHECK(display_infos); |
| + // TODO(robliao): When ready, replace the GetDPIScale with GetDpiForMonitor |
| + // to get the actual DPI for the HMONITOR. |
| display_infos->push_back(DisplayInfo(MonitorInfoFromHMONITOR(monitor), |
| GetDPIScale())); |
| return TRUE; |
| @@ -155,78 +158,114 @@ std::vector<DisplayInfo> GetDisplayInfosFromSystem() { |
| return display_infos; |
| } |
| +// Returns a point in |to_origin|'s coordinates and position scaled by |
| +// |scale_factor|. |
| +gfx::Point ScalePointRelative(const gfx::Point& from_origin, |
| + const gfx::Point& to_origin, |
| + const float scale_factor, |
| + const gfx::Point& point) { |
| + gfx::Vector2d from_origin_vector(from_origin.x(), from_origin.y()); |
| + gfx::Vector2d to_origin_vector(to_origin.x(), to_origin.y()); |
| + gfx::Point scaled_relative_point( |
| + gfx::ScaleToFlooredPoint(point - from_origin_vector, scale_factor)); |
| + return scaled_relative_point + to_origin_vector; |
| +} |
| + |
| } // namespace |
| ScreenWin::ScreenWin() { |
| + DCHECK(!g_screen_win_instance); |
| + g_screen_win_instance = this; |
| Initialize(); |
| } |
| -ScreenWin::~ScreenWin() = default; |
| +ScreenWin::~ScreenWin() { |
| + DCHECK(g_screen_win_instance == this); |
|
oshima
2016/05/26 21:52:58
DCHECK_EQ
robliao
2016/05/26 22:28:47
Done.
|
| + g_screen_win_instance = nullptr; |
| +} |
| // static |
| gfx::Point ScreenWin::ScreenToDIPPoint(const gfx::Point& pixel_point) { |
| - return ScaleToFlooredPoint(pixel_point, 1.0f / GetDPIScale()); |
| + const ScreenWinDisplay screen_win_display = |
| + GetScreenWinDisplayVia(&ScreenWin::GetScreenWinDisplayNearestScreenPoint, |
| + pixel_point); |
| + const display::Display display = screen_win_display.display(); |
| + return ScalePointRelative(screen_win_display.pixel_bounds().origin(), |
| + display.bounds().origin(), |
| + 1.0f / display.device_scale_factor(), |
| + pixel_point); |
| } |
| // static |
| gfx::Point ScreenWin::DIPToScreenPoint(const gfx::Point& dip_point) { |
| - return ScaleToFlooredPoint(dip_point, GetDPIScale()); |
| + const ScreenWinDisplay screen_win_display = |
| + GetScreenWinDisplayVia(&ScreenWin::GetScreenWinDisplayNearestDIPPoint, |
| + dip_point); |
| + const display::Display display = screen_win_display.display(); |
| + return ScalePointRelative(display.bounds().origin(), |
| + screen_win_display.pixel_bounds().origin(), |
| + display.device_scale_factor(), |
| + dip_point); |
| } |
| // static |
| gfx::Point ScreenWin::ClientToDIPPoint(HWND hwnd, |
| const gfx::Point& client_point) { |
| - // TODO(robliao): Get the scale factor from |hwnd|. |
| - return ScreenToDIPPoint(client_point); |
| + return ScaleToFlooredPoint(client_point, 1.0f / GetScaleFactorForHWND(hwnd)); |
| } |
| // static |
| gfx::Point ScreenWin::DIPToClientPoint(HWND hwnd, const gfx::Point& dip_point) { |
| - // TODO(robliao): Get the scale factor from |hwnd|. |
| - return DIPToScreenPoint(dip_point); |
| + float scale_factor = GetScaleFactorForHWND(hwnd); |
| + return ScaleToFlooredPoint(dip_point, scale_factor); |
| } |
| // static |
| gfx::Rect ScreenWin::ScreenToDIPRect(HWND hwnd, const gfx::Rect& pixel_bounds) { |
| - // It's important we scale the origin and size separately. If we instead |
| - // calculated the size from the floored origin and ceiled right the size could |
| - // vary depending upon where the two points land. That would cause problems |
| - // for the places this code is used (in particular mapping from native window |
| - // bounds to DIPs). |
| - return gfx::Rect(ScreenToDIPPoint(pixel_bounds.origin()), |
| - ScreenToDIPSize(hwnd, pixel_bounds.size())); |
| + float scale_factor = hwnd ? |
| + GetScaleFactorForHWND(hwnd) : |
| + GetScreenWinDisplayVia( |
| + &ScreenWin::GetScreenWinDisplayNearestScreenRect, pixel_bounds). |
| + display().device_scale_factor(); |
| + gfx::Rect dip_rect = ScaleToEnclosingRect(pixel_bounds, 1.0f / scale_factor); |
| + dip_rect.set_origin(ScreenToDIPPoint(pixel_bounds.origin())); |
| + return dip_rect; |
| } |
| // static |
| gfx::Rect ScreenWin::DIPToScreenRect(HWND hwnd, const gfx::Rect& dip_bounds) { |
| - // See comment in ScreenToDIPRect for why we calculate size like this. |
| - return gfx::Rect(DIPToScreenPoint(dip_bounds.origin()), |
| - DIPToScreenSize(hwnd, dip_bounds.size())); |
| + float scale_factor = hwnd ? |
| + GetScaleFactorForHWND(hwnd) : |
| + GetScreenWinDisplayVia( |
| + &ScreenWin::GetScreenWinDisplayNearestDIPRect, dip_bounds).display(). |
| + device_scale_factor(); |
| + gfx::Rect screen_rect = ScaleToEnclosingRect(dip_bounds, scale_factor); |
| + screen_rect.set_origin(DIPToScreenPoint(dip_bounds.origin())); |
| + return screen_rect; |
| } |
| // static |
| gfx::Rect ScreenWin::ClientToDIPRect(HWND hwnd, const gfx::Rect& pixel_bounds) { |
| - return ScreenToDIPRect(hwnd, pixel_bounds); |
| + return ScaleToEnclosingRect(pixel_bounds, 1.0f / GetScaleFactorForHWND(hwnd)); |
| } |
| // static |
| gfx::Rect ScreenWin::DIPToClientRect(HWND hwnd, const gfx::Rect& dip_bounds) { |
| - return DIPToScreenRect(hwnd, dip_bounds); |
| + return ScaleToEnclosingRect(dip_bounds, GetScaleFactorForHWND(hwnd)); |
| } |
| // static |
| gfx::Size ScreenWin::ScreenToDIPSize(HWND hwnd, |
| const gfx::Size& size_in_pixels) { |
| // Always ceil sizes. Otherwise we may be leaving off part of the bounds. |
| - // TODO(robliao): Get the scale factor from |hwnd|. |
| - return ScaleToCeiledSize(size_in_pixels, 1.0f / GetDPIScale()); |
| + return ScaleToCeiledSize(size_in_pixels, 1.0f / GetScaleFactorForHWND(hwnd)); |
| } |
| // static |
| gfx::Size ScreenWin::DIPToScreenSize(HWND hwnd, const gfx::Size& dip_size) { |
| + float scale_factor = GetScaleFactorForHWND(hwnd); |
| // Always ceil sizes. Otherwise we may be leaving off part of the bounds. |
| - // TODO(robliao): Get the scale factor from |hwnd|. |
| - return ScaleToCeiledSize(dip_size, GetDPIScale()); |
| + return ScaleToCeiledSize(dip_size, scale_factor); |
| } |
| HWND ScreenWin::GetHWNDFromNativeView(gfx::NativeView window) const { |
| @@ -306,6 +345,18 @@ void ScreenWin::RemoveObserver(display::DisplayObserver* observer) { |
| change_notifier_.RemoveObserver(observer); |
| } |
| +gfx::Rect ScreenWin::ScreenToDIPRectInWindow( |
| + gfx::NativeView view, const gfx::Rect& screen_rect) const { |
| + HWND hwnd = view ? GetHWNDFromNativeView(view) : nullptr; |
| + return ScreenToDIPRect(hwnd, screen_rect); |
| +} |
| + |
| +gfx::Rect ScreenWin::DIPToScreenRectInWindow(gfx::NativeView view, |
| + const gfx::Rect& dip_rect) const { |
| + HWND hwnd = view ? GetHWNDFromNativeView(view) : nullptr; |
| + return DIPToScreenRect(hwnd, dip_rect); |
| +} |
| + |
| void ScreenWin::UpdateFromDisplayInfos( |
| const std::vector<DisplayInfo>& display_infos) { |
| screen_win_displays_ = DisplayInfosToScreenWinDisplays(display_infos); |
| @@ -369,6 +420,39 @@ ScreenWinDisplay ScreenWin::GetScreenWinDisplayNearestScreenPoint( |
| return GetScreenWinDisplay(MonitorInfoFromScreenPoint(screen_point)); |
| } |
| +ScreenWinDisplay ScreenWin::GetScreenWinDisplayNearestDIPPoint( |
| + const gfx::Point& dip_point) const { |
| + ScreenWinDisplay primary_screen_win_display; |
| + for (const auto& screen_win_display : screen_win_displays_) { |
| + display::Display display = screen_win_display.display(); |
| + const gfx::Rect dip_bounds = display.bounds(); |
| + if (dip_bounds.Contains(dip_point)) |
| + return screen_win_display; |
| + else if (dip_bounds.origin().IsOrigin()) |
| + primary_screen_win_display = screen_win_display; |
| + } |
| + return primary_screen_win_display; |
| +} |
| + |
| +ScreenWinDisplay ScreenWin::GetScreenWinDisplayNearestDIPRect( |
| + const gfx::Rect& dip_rect) const { |
| + ScreenWinDisplay closest_screen_win_display; |
| + int64_t closest_distance_squared = INT64_MAX; |
| + for (const auto& screen_win_display : screen_win_displays_) { |
| + display::Display display = screen_win_display.display(); |
| + gfx::Rect dip_bounds = display.bounds(); |
| + int64_t distance_squared = SquaredDistanceBetweenRects(dip_rect, |
| + dip_bounds); |
| + if (distance_squared == 0) { |
| + return screen_win_display; |
| + } else if (distance_squared < closest_distance_squared) { |
| + closest_distance_squared = distance_squared; |
| + closest_screen_win_display = screen_win_display; |
| + } |
| + } |
| + return closest_screen_win_display; |
| +} |
| + |
| ScreenWinDisplay ScreenWin::GetPrimaryScreenWinDisplay() const { |
| MONITORINFOEX monitor_info = MonitorInfoFromWindow(nullptr, |
| MONITOR_DEFAULTTOPRIMARY); |
| @@ -394,5 +478,27 @@ ScreenWinDisplay ScreenWin::GetScreenWinDisplay( |
| return ScreenWinDisplay(); |
| } |
| +// static |
| +float ScreenWin::GetScaleFactorForHWND(HWND hwnd) { |
| + if (!g_screen_win_instance) |
|
oshima
2016/05/26 21:52:58
when/how can this happen?
robliao
2016/05/26 22:28:47
This happens in tests that don't use ScreenWin and
oshima
2016/05/26 22:54:47
Shouldn't such tests should create screen object?
robliao
2016/05/26 23:19:24
I don't think we want to force these tests to do t
oshima
2016/05/26 23:43:13
Which test is it? I want to be convinced because w
robliao
2016/05/27 00:47:13
I'll get back to you on this at the patchset that
robliao
2016/05/27 01:39:58
The ash_unittests fail:
https://build.chromium.org
oshima
2016/05/27 02:02:04
The link seems to be obsolete.
robliao
2016/05/27 17:15:30
This is the full list of failures due to either th
robliao
2016/05/27 17:51:34
Since stacks aren't working, you can use this:
htt
|
| + return ScreenWinDisplay().display().device_scale_factor(); |
| + |
| + DCHECK(hwnd); |
| + HWND rootHwnd = g_screen_win_instance->GetRootWindow(hwnd); |
| + ScreenWinDisplay screen_win_display = |
| + g_screen_win_instance->GetScreenWinDisplayNearestHWND(rootHwnd); |
| + return screen_win_display.display().device_scale_factor(); |
| +} |
| + |
| +// static |
| +template <typename Getter, typename GetterType> |
| +ScreenWinDisplay ScreenWin::GetScreenWinDisplayVia(Getter getter, |
| + GetterType value) { |
| + if (!g_screen_win_instance) |
| + return ScreenWinDisplay(); |
| + |
| + return (g_screen_win_instance->*getter)(value); |
| +} |
| + |
| } // namespace win |
| } // namespace display |