| Index: ui/gfx/screen_win.cc
|
| diff --git a/ui/gfx/screen_win.cc b/ui/gfx/screen_win.cc
|
| index f01d40aa833d8a48a92e56ebe3311a8b784b3c40..c411f14d17e7fb05920da9c14385120e7655fe49 100644
|
| --- a/ui/gfx/screen_win.cc
|
| +++ b/ui/gfx/screen_win.cc
|
| @@ -13,33 +13,33 @@
|
| #include "base/strings/utf_string_conversions.h"
|
| #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);
|
| gfx::Display display(id, bounds);
|
| display.set_work_area(gfx::Rect(monitor_info.rcWork));
|
| display.SetScaleAndBounds(gfx::GetDPIScale(), bounds);
|
| + DCHECK(display.device_scale_factor() >= 1.0);
|
|
|
| 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();
|
| + 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()));
|
| + }
|
| + 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()));
|
| + }
|
| + // 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,
|
|
|