Chromium Code Reviews| Index: ui/gfx/screen_win.cc |
| diff --git a/ui/gfx/screen_win.cc b/ui/gfx/screen_win.cc |
| index f01d40aa833d8a48a92e56ebe3311a8b784b3c40..068461e933d6e7159935625744445d284580c3d8 100644 |
| --- a/ui/gfx/screen_win.cc |
| +++ b/ui/gfx/screen_win.cc |
| @@ -11,21 +11,21 @@ |
| #include "base/hash.h" |
| #include "base/logging.h" |
| #include "base/strings/utf_string_conversions.h" |
| +#include "base/win/scoped_hdc.h" |
|
scottmg
2015/10/28 18:48:21
I don't think this got used.
robliao
2015/10/29 00:30:24
Good catch. I had a plan that used HDC's before bu
|
| #include "base/win/win_util.h" |
| #include "ui/gfx/display.h" |
| +#include "ui/gfx/geometry/point_conversions.h" |
| +#include "ui/gfx/geometry/vector2d.h" |
| #include "ui/gfx/win/dpi.h" |
| namespace { |
| -MONITORINFOEX GetMonitorInfoForMonitor(HMONITOR monitor) { |
| +gfx::Display GetDisplay(HMONITOR monitor) { |
| MONITORINFOEX monitor_info; |
| - ZeroMemory(&monitor_info, sizeof(MONITORINFOEX)); |
| + ::ZeroMemory(&monitor_info, sizeof(monitor_info)); |
| monitor_info.cbSize = sizeof(monitor_info); |
| - GetMonitorInfo(monitor, &monitor_info); |
| - return monitor_info; |
| -} |
| + ::GetMonitorInfo(monitor, &monitor_info); |
| -gfx::Display GetDisplay(MONITORINFOEX& monitor_info) { |
| int64 id = static_cast<int64>( |
| base::Hash(base::WideToUTF8(monitor_info.szDevice))); |
| gfx::Rect bounds = gfx::Rect(monitor_info.rcMonitor); |
| @@ -34,12 +34,12 @@ gfx::Display GetDisplay(MONITORINFOEX& monitor_info) { |
| display.SetScaleAndBounds(gfx::GetDPIScale(), bounds); |
| DEVMODE mode; |
| - memset(&mode, 0, sizeof(DEVMODE)); |
| + ::ZeroMemory(&mode, sizeof(mode)); |
| mode.dmSize = sizeof(DEVMODE); |
| mode.dmDriverExtra = 0; |
| - if (EnumDisplaySettings(monitor_info.szDevice, |
| - ENUM_CURRENT_SETTINGS, |
| - &mode)) { |
| + if (::EnumDisplaySettings(monitor_info.szDevice, |
| + ENUM_CURRENT_SETTINGS, |
| + &mode)) { |
| switch (mode.dmDisplayOrientation) { |
| case DMDO_DEFAULT: |
| display.set_rotation(gfx::Display::ROTATE_0); |
| @@ -69,8 +69,7 @@ BOOL CALLBACK EnumMonitorCallback(HMONITOR monitor, |
| reinterpret_cast<std::vector<gfx::Display>*>(data); |
| DCHECK(all_displays); |
| - MONITORINFOEX monitor_info = GetMonitorInfoForMonitor(monitor); |
| - gfx::Display display = GetDisplay(monitor_info); |
| + gfx::Display display = GetDisplay(monitor); |
| all_displays->push_back(display); |
| return TRUE; |
| } |
| @@ -94,11 +93,102 @@ ScreenWin::ScreenWin() |
| ScreenWin::~ScreenWin() {} |
| +// static |
| +Point ScreenWin::ScreenToDIPPoint(const Point& pixel_point) { |
| + gfx::Display display = GetDisplayNearestScreenPoint(pixel_point); |
| + float device_scale_factor = display.device_scale_factor(); |
| + const Rect& monitor_bounds = display.bounds(); |
| + Vector2d origin(monitor_bounds.x(), monitor_bounds.y()); |
| + |
| + // Monitors are anchored to their physical coordinate regardless of DPI. |
| + return ScaleToFlooredPoint(pixel_point - origin, 1.0f / device_scale_factor) + |
| + origin; |
| +} |
| + |
| +// static |
| +Point ScreenWin::DIPToScreenPoint(const Point& dip_point) { |
| + // Because origins don't change for screen points and scaling factors are |
| + // greater than 1, the monitor bounding rect always contains the DIP point. |
| + gfx::Display display = GetDisplayNearestScreenPoint(dip_point); |
| + float device_scale_factor = display.device_scale_factor(); |
|
scottmg
2015/10/28 18:48:21
DCHECK that device_scale_factor >= 1 (CrOS has som
robliao
2015/10/29 00:30:24
Added the DCHECK where we create the display in Ge
|
| + const Rect& monitor_bounds = display.bounds(); |
| + Vector2d origin(monitor_bounds.x(), monitor_bounds.y()); |
| + |
| + return ScaleToFlooredPoint(dip_point - origin, device_scale_factor) + origin; |
| +} |
| + |
| +// static |
| +Point ScreenWin::ClientToDIPPoint(HWND hwnd, const Point& client_point) { |
| + return ScaleToFlooredPoint(client_point, 1.0f / GetScaleFactorForHWND(hwnd)); |
| +} |
| + |
| +Point ScreenWin::DIPToClientPoint(HWND hwnd, const Point& dip_point) { |
| + return ScaleToFlooredPoint(dip_point, GetScaleFactorForHWND(hwnd)); |
| +} |
| + |
| +// static |
| +Rect ScreenWin::ScreenToDIPRect(HWND hwnd, const 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). |
| + if (hwnd) { |
| + return Rect(ScreenToDIPPoint(pixel_bounds.origin()), |
| + ScreenToDIPSize(hwnd, pixel_bounds.size())); |
|
scottmg
2015/10/28 18:48:21
indent
robliao
2015/10/29 00:30:24
Done.
|
| + } |
| + float scale_factor = |
| + GetDisplayNearestRect(pixel_bounds).device_scale_factor(); |
| + return Rect(ScreenToDIPPoint(pixel_bounds.origin()), |
| + ScaleToCeiledSize(pixel_bounds.size(), 1.0f / scale_factor)); |
| +} |
| + |
| +// static |
| +Rect ScreenWin::DIPToScreenRect(HWND hwnd, const Rect& dip_bounds) { |
| + // See comment in ScreenToDIPRect for why we calculate size like this. |
| + if (hwnd) { |
| + return Rect(DIPToScreenPoint(dip_bounds.origin()), |
| + DIPToScreenSize(hwnd, dip_bounds.size())); |
|
scottmg
2015/10/28 18:48:21
indent
robliao
2015/10/29 00:30:24
Done.
|
| + } |
| + // Because origins don't change for screen points and scaling factors are |
| + // greater than 1, the monitor bounding rect always contains the DIP point. |
| + float scale_factor = |
| + GetDisplayNearestRect(dip_bounds).device_scale_factor(); |
| + return Rect(DIPToScreenPoint(dip_bounds.origin()), |
| + ScaleToCeiledSize(dip_bounds.size(), scale_factor)); |
| +} |
| + |
| +// static |
| +Rect ScreenWin::ClientToDIPRect(HWND hwnd, const Rect& pixel_bounds) { |
| + // See comment in ScreenToDIPRect for why we calculate size like this. |
| + return Rect(ClientToDIPPoint(hwnd, pixel_bounds.origin()), |
| + ScreenToDIPSize(hwnd, pixel_bounds.size())); |
| +} |
| + |
| +// static |
| +Rect ScreenWin::DIPToClientRect(HWND hwnd, const Rect& dip_bounds) { |
| + // See comment in ScreenToDIPRect for why we calculate size like this. |
| + return Rect(DIPToClientPoint(hwnd, dip_bounds.origin()), |
| + DIPToScreenSize(hwnd, dip_bounds.size())); |
| +} |
| + |
| +// static |
| +Size ScreenWin::ScreenToDIPSize(HWND hwnd, const Size& size_in_pixels) { |
| + // Always ceil sizes. Otherwise we may be leaving off part of the bounds. |
| + return ScaleToCeiledSize(size_in_pixels, 1.0f / GetScaleFactorForHWND(hwnd)); |
| +} |
| + |
| +// static |
| +Size ScreenWin::DIPToScreenSize(HWND hwnd, const Size& dip_size) { |
| + // Always ceil sizes. Otherwise we may be leaving off part of the bounds. |
| + return ScaleToCeiledSize(dip_size, GetScaleFactorForHWND(hwnd)); |
| +} |
| + |
| gfx::Point ScreenWin::GetCursorScreenPoint() { |
| POINT pt; |
| GetCursorPos(&pt); |
| gfx::Point cursor_pos_pixels(pt); |
| - return gfx::win::ScreenToDIPPoint(cursor_pos_pixels); |
| + return ScreenToDIPPoint(cursor_pos_pixels); |
| } |
| gfx::NativeWindow ScreenWin::GetWindowUnderCursor() { |
| @@ -108,7 +198,7 @@ gfx::NativeWindow ScreenWin::GetWindowUnderCursor() { |
| } |
| gfx::NativeWindow ScreenWin::GetWindowAtScreenPoint(const gfx::Point& point) { |
| - gfx::Point point_in_pixels = gfx::win::DIPToScreenPoint(point); |
| + gfx::Point point_in_pixels = DIPToScreenPoint(point); |
| return GetNativeWindowFromHWND(WindowFromPoint(point_in_pixels.ToPOINT())); |
| } |
| @@ -129,40 +219,23 @@ gfx::Display ScreenWin::GetDisplayNearestWindow(gfx::NativeView window) const { |
| return GetPrimaryDisplay(); |
| } |
| - MONITORINFOEX monitor_info; |
| - monitor_info.cbSize = sizeof(monitor_info); |
| - GetMonitorInfo(MonitorFromWindow(window_hwnd, MONITOR_DEFAULTTONEAREST), |
| - &monitor_info); |
| - return GetDisplay(monitor_info); |
| + return GetDisplayNearestHWND(window_hwnd); |
| } |
| gfx::Display ScreenWin::GetDisplayNearestPoint(const gfx::Point& point) const { |
| - gfx::Point point_in_pixels = gfx::win::DIPToScreenPoint(point); |
| - POINT initial_loc = { point_in_pixels.x(), point_in_pixels.y() }; |
| - HMONITOR monitor = MonitorFromPoint(initial_loc, MONITOR_DEFAULTTONEAREST); |
| - MONITORINFOEX mi; |
| - ZeroMemory(&mi, sizeof(MONITORINFOEX)); |
| - mi.cbSize = sizeof(mi); |
| - if (monitor && GetMonitorInfo(monitor, &mi)) { |
| - return GetDisplay(mi); |
| - } |
| - return gfx::Display(); |
| + return GetDisplayNearestScreenPoint(DIPToScreenPoint(point)); |
| } |
| gfx::Display ScreenWin::GetDisplayMatching(const gfx::Rect& match_rect) const { |
| - RECT other_bounds_rect = match_rect.ToRECT(); |
| - MONITORINFOEX monitor_info = GetMonitorInfoForMonitor(MonitorFromRect( |
| - &other_bounds_rect, MONITOR_DEFAULTTONEAREST)); |
| - return GetDisplay(monitor_info); |
| + return GetDisplayNearestRect(match_rect); |
| } |
| gfx::Display ScreenWin::GetPrimaryDisplay() const { |
| - MONITORINFOEX mi = GetMonitorInfoForMonitor( |
| - MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY)); |
| - gfx::Display display = GetDisplay(mi); |
| + gfx::Display display = |
| + GetDisplay(MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY)); |
| // TODO(kevers|girard): Test if these checks can be reintroduced for high-DIP |
| // once more of the app is DIP-aware. |
| - if (GetDPIScale() == 1.0) { |
| + if (display.device_scale_factor() == 1.0) { |
| DCHECK_EQ(GetSystemMetrics(SM_CXSCREEN), display.size().width()); |
| DCHECK_EQ(GetSystemMetrics(SM_CYSCREEN), display.size().height()); |
| } |
| @@ -177,6 +250,36 @@ void ScreenWin::RemoveObserver(DisplayObserver* observer) { |
| change_notifier_.RemoveObserver(observer); |
| } |
| +// static |
| +gfx::Display ScreenWin::GetDisplayNearestHWND(HWND hwnd) { |
| + return GetDisplay(::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST)); |
| +} |
| + |
| +// static |
| +gfx::Display ScreenWin::GetDisplayNearestRect(const Rect& rect) { |
| + RECT winRect = rect.ToRECT(); |
| + return GetDisplay(::MonitorFromRect(&winRect, MONITOR_DEFAULTTONEAREST)); |
| +} |
| + |
| +// static |
| +gfx::Display ScreenWin::GetDisplayNearestScreenPoint( |
| + const Point& screen_point) { |
| + POINT initial_loc = { screen_point.x(), screen_point.y() }; |
| + return GetDisplay(::MonitorFromPoint(initial_loc, MONITOR_DEFAULTTONEAREST)); |
| +} |
| + |
| +// static |
| +float ScreenWin::GetScaleFactorForHWND(HWND hwnd) { |
| + DCHECK(hwnd); |
| + HWND hwndTopLevel = GetAncestor(hwnd, GA_ROOT); |
| + return GetDisplayNearestHWND(hwndTopLevel).device_scale_factor(); |
| +} |
| + |
| +// static |
| +float ScreenWin::GetScaleFactorForScreenPoint(const Point& screen_point) { |
| + return GetDisplayNearestScreenPoint(screen_point).device_scale_factor(); |
| +} |
| + |
| void ScreenWin::OnWndProc(HWND hwnd, |
| UINT message, |
| WPARAM wparam, |