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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/gfx/screen_win.cc
diff --git a/ui/gfx/screen_win.cc b/ui/gfx/screen_win.cc
index 3199f7acaacdd2b15c3dca37d09014dc418c2d00..53fbdb73f57027cdeff0240bcace46acf6aff8d9 100644
--- a/ui/gfx/screen_win.cc
+++ b/ui/gfx/screen_win.cc
@@ -14,89 +14,179 @@
#include "base/strings/utf_string_conversions.h"
#include "base/win/win_util.h"
#include "ui/gfx/display.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/point_conversions.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/safe_integer_conversions.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/win/dpi.h"
+#include "ui/gfx/win/rect_util.h"
namespace {
-MONITORINFOEX GetMonitorInfoForMonitor(HMONITOR monitor) {
- MONITORINFOEX monitor_info;
- ZeroMemory(&monitor_info, sizeof(MONITORINFOEX));
- monitor_info.cbSize = sizeof(monitor_info);
- GetMonitorInfo(monitor, &monitor_info);
- return monitor_info;
-}
-
-gfx::Display GetDisplay(const MONITORINFOEX& monitor_info) {
- int64_t id =
- static_cast<int64_t>(base::Hash(base::WideToUTF8(monitor_info.szDevice)));
- gfx::Rect bounds = gfx::Rect(monitor_info.rcMonitor);
- gfx::Display display(id);
- display.set_bounds(gfx::win::ScreenToDIPRect(bounds));
- display.set_work_area(
- gfx::win::ScreenToDIPRect(gfx::Rect(monitor_info.rcWork)));
- display.SetScaleAndBounds(gfx::GetDPIScale(), bounds);
-
+gfx::Display::Rotation GetRotationForDevice(const wchar_t* device_name) {
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(device_name, ENUM_CURRENT_SETTINGS, &mode)) {
switch (mode.dmDisplayOrientation) {
case DMDO_DEFAULT:
- display.set_rotation(gfx::Display::ROTATE_0);
- break;
+ return gfx::Display::ROTATE_0;
case DMDO_90:
- display.set_rotation(gfx::Display::ROTATE_90);
- break;
+ return gfx::Display::ROTATE_90;
case DMDO_180:
- display.set_rotation(gfx::Display::ROTATE_180);
- break;
+ return gfx::Display::ROTATE_180;
case DMDO_270:
- display.set_rotation(gfx::Display::ROTATE_270);
- break;
+ return gfx::Display::ROTATE_270;
default:
NOTREACHED();
}
}
-
- return display;
+ return gfx::Display::ROTATE_0;
}
-BOOL CALLBACK EnumMonitorCallback(HMONITOR monitor,
- HDC hdc,
- LPRECT rect,
- LPARAM data) {
- std::vector<gfx::Display>* all_displays =
- reinterpret_cast<std::vector<gfx::Display>*>(data);
- DCHECK(all_displays);
+// 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());
+ return gfx::ScaleToFlooredPoint(point - from_origin_vector, scale_factor) +
+ to_origin_vector;
+}
- MONITORINFOEX monitor_info = GetMonitorInfoForMonitor(monitor);
- gfx::Display display = GetDisplay(monitor_info);
- all_displays->push_back(display);
- return TRUE;
+// Returns the NativeScreen. For all intents and purposes, this screen provides
+// the source of truth for displays in Windows.
+gfx::ScreenWin* GetNativeScreenWin() {
+ return static_cast<gfx::ScreenWin*>(gfx::Screen::GetNativeScreen());
}
-std::vector<gfx::Display> GetDisplays() {
- std::vector<gfx::Display> displays;
- EnumDisplayMonitors(NULL, NULL, EnumMonitorCallback,
- reinterpret_cast<LPARAM>(&displays));
- return displays;
+// static
+MONITORINFOEX MonitorInfoFromHMONITOR(HMONITOR monitor) {
+ MONITORINFOEX monitor_info;
+ ::ZeroMemory(&monitor_info, sizeof(monitor_info));
+ monitor_info.cbSize = sizeof(monitor_info);
+ ::GetMonitorInfo(monitor, &monitor_info);
+ return monitor_info;
}
} // namespace
namespace gfx {
+class ScreenWin::DisplayWin {
+ public:
+ explicit DisplayWin();
+ explicit DisplayWin(const DisplayInfo& display_info);
+ DisplayWin(const DisplayWin& ref, const DisplayInfo& display_info);
+
+ const Display& display() const { return display_; }
+ const Rect& physical_bounds() const { return pixel_bounds_; }
+
+ private:
+ Display display_;
+ Rect pixel_bounds_;
+};
+
ScreenWin::ScreenWin()
: singleton_hwnd_observer_(new SingletonHwndObserver(
base::Bind(&ScreenWin::OnWndProc, base::Unretained(this)))),
- displays_(GetDisplays()) {
-}
+ display_wins_(GetDisplayWins()) {}
ScreenWin::~ScreenWin() {}
+// static
+Point ScreenWin::ScreenToDIPPoint(const Point& pixel_point) {
+ DisplayWin display_win = GetDisplayNearestScreenPoint(pixel_point);
+ Display display = display_win.display();
+ return ScalePointRelative(display_win.physical_bounds().origin(),
+ display.bounds().origin(),
+ 1.0f / display.device_scale_factor(),
+ pixel_point);
+}
+
+// static
+Point ScreenWin::DIPToScreenPoint(const Point& dip_point) {
+ DisplayWin display_win = GetDisplayNearestDIPPoint(dip_point);
+ Display display = display_win.display();
+ return ScalePointRelative(display.bounds().origin(),
+ display_win.physical_bounds().origin(),
+ display.device_scale_factor(),
+ dip_point);
+}
+
+
+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 =
+ GetDisplayNearestScreenRect(pixel_bounds).display().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 =
+ GetDisplayNearestDIPRect(dip_bounds).display().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));
+}
+
HWND ScreenWin::GetHWNDFromNativeView(NativeView window) const {
NOTREACHED();
return NULL;
@@ -107,11 +197,45 @@ NativeWindow ScreenWin::GetNativeWindowFromHWND(HWND hwnd) const {
return NULL;
}
+ScreenWin::DisplayInfo::DisplayInfo(HMONITOR monitor,
+ float device_scale_factor) :
+ device_scale_factor_(device_scale_factor){
+ MONITORINFOEX monitor_info;
+ ::ZeroMemory(&monitor_info, sizeof(monitor_info));
+ monitor_info.cbSize = sizeof(monitor_info);
+ ::GetMonitorInfo(monitor, &monitor_info);
+ InitializeFromMonitorInfo(monitor_info);
+}
+
+ScreenWin::DisplayInfo::DisplayInfo(const MONITORINFOEX& monitor_info,
+ gfx::Display::Rotation rotation,
+ float device_scale_factor)
+ : rotation_(rotation),
+ device_scale_factor_(device_scale_factor) {
+ InitializeFromMonitorInfo(monitor_info);
+}
+
+void ScreenWin::DisplayInfo::InitializeFromMonitorInfo(
+ const MONITORINFOEX& monitor_info) {
+ id_ = ScreenWin::HashDeviceName(monitor_info.szDevice);
+ screen_rect_ = gfx::Rect(monitor_info.rcMonitor);
+ screen_work_rect_ = gfx::Rect(monitor_info.rcWork);
+ rotation_ = GetRotationForDevice(monitor_info.szDevice);
+}
+
+ScreenWin::ScreenWin(const std::vector<ScreenWin::DisplayInfo>& display_infos) {
+ display_wins_ = GetDisplaysFromDisplayInfos(display_infos);
+}
+
+int64_t ScreenWin::HashDeviceName(const wchar_t* device_name) {
+ return static_cast<int64_t>(base::Hash(base::WideToUTF8(device_name)));
+}
+
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() {
@@ -121,7 +245,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()));
}
@@ -130,7 +254,11 @@ int ScreenWin::GetNumDisplays() const {
}
std::vector<gfx::Display> ScreenWin::GetAllDisplays() const {
- return displays_;
+ std::vector<gfx::Display> displays;
+ for (const DisplayWin& display_win : display_wins_) {
+ displays.push_back(display_win.display());
+ }
+ return displays;
}
gfx::Display ScreenWin::GetDisplayNearestWindow(gfx::NativeView window) const {
@@ -141,41 +269,24 @@ gfx::Display ScreenWin::GetDisplayNearestWindow(gfx::NativeView window) const {
// scaling factor.
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).display();
}
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)).display();
}
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 GetDisplayNearestScreenRect(match_rect).display();
}
gfx::Display ScreenWin::GetPrimaryDisplay() const {
- MONITORINFOEX mi = GetMonitorInfoForMonitor(
- MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY));
- gfx::Display display = GetDisplay(mi);
+ Display display =
+ GetDisplayWin(MonitorInfoFromHMONITOR(MonitorFromWindow(
+ NULL, MONITOR_DEFAULTTOPRIMARY))).display();
// 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());
}
@@ -190,6 +301,205 @@ void ScreenWin::RemoveObserver(DisplayObserver* observer) {
change_notifier_.RemoveObserver(observer);
}
+gfx::Rect ScreenWin::ScreenToDIPRectInWindow(
+ NativeView view, const gfx::Rect& screen_rect) const {
+ HWND hwnd = view ? GetHWNDFromNativeView(view) : NULL;
+ return ScreenWin::ScreenToDIPRect(hwnd, screen_rect);
+}
+
+gfx::Rect ScreenWin::DIPToScreenRectInWindow(NativeView view,
+ const gfx::Rect& dip_rect) const {
+ HWND hwnd = view ? GetHWNDFromNativeView(view) : NULL;
+ return ScreenWin::DIPToScreenRect(hwnd, dip_rect);
+}
+
+ScreenWin::DisplayWin::DisplayWin() = default;
+
+ScreenWin::DisplayWin::DisplayWin(const DisplayInfo& display_info)
+ : display_(display_info.id()),
+ pixel_bounds_(display_info.screen_rect()) {
+ float scale_factor = display_info.device_scale_factor();
+ display_.set_device_scale_factor(scale_factor);
+ display_.set_work_area(
+ gfx::ScaleToEnclosedRect(display_info.screen_work_rect(),
+ 1.0f / scale_factor));
+ display_.set_bounds(gfx::ScaleToEnclosedRect(display_info.screen_rect(),
+ 1.0f / scale_factor));
+}
+
+ScreenWin::DisplayWin::DisplayWin(const DisplayWin& ref,
+ const DisplayInfo& display_info)
+ : display_(display_info.id()),
+ pixel_bounds_(display_info.screen_rect()) {
+ float scale_factor = display_info.device_scale_factor();
+ display_.set_device_scale_factor(scale_factor);
+ const gfx::Insets pixel_insets =
+ display_info.screen_rect().InsetsFrom(display_info.screen_work_rect());
+ const gfx::Insets scaled_insets = pixel_insets.Scale(1.0f / scale_factor,
+ 1.0f / scale_factor);
+ const gfx::Rect scaled_bounds =
+ gfx::win::ScaleAndPositionRect(ref.display_.bounds(),
+ ref.physical_bounds(),
+ display_info.screen_rect(),
+ scale_factor);
+ display_.set_bounds(scaled_bounds);
+ gfx::Rect scaled_work_area(scaled_bounds);
+ scaled_work_area.Inset(scaled_insets);
+ display_.set_work_area(scaled_work_area);
+}
+
+// static
+ScreenWin::DisplayWin ScreenWin::GetDisplayNearestHWND(HWND hwnd) {
+ ScreenWin* screen = GetNativeScreenWin();
+ return screen->GetDisplayWin(screen->MonitorInfoFromWindow(hwnd));
+}
+
+// static
+ScreenWin::DisplayWin ScreenWin::GetDisplayNearestScreenRect(
+ const Rect& screen_rect) {
+ ScreenWin* screen = GetNativeScreenWin();
+ return screen->GetDisplayWin(screen->MonitorInfoFromScreenRect(screen_rect));
+}
+
+// static
+ScreenWin::DisplayWin ScreenWin::GetDisplayNearestScreenPoint(
+ const Point& screen_point) {
+ ScreenWin* screen = GetNativeScreenWin();
+ return screen->GetDisplayWin(
+ screen->MonitorInfoFromScreenPoint(screen_point));
+}
+
+// static
+ScreenWin::DisplayWin ScreenWin::GetDisplayNearestDIPRect(
+ const Rect& dip_rect) {
+ ScreenWin* screen = GetNativeScreenWin();
+ DisplayWin closest_display_win;
+ int64_t closest_distance_squared = INT64_MAX;
+ for (const DisplayWin& display_win : screen->display_wins_) {
+ Display display = display_win.display();
+ gfx::Rect dip_bounds = display.bounds();
+ int64_t distance_squared =
+ gfx::win::SquaredDistanceBetweenRects(dip_rect, dip_bounds);
+ if (distance_squared == 0) {
+ return display_win;
+ } else if (distance_squared < closest_distance_squared) {
+ closest_distance_squared = distance_squared;
+ closest_display_win = display_win;
+ }
+ }
+ return closest_display_win;
+}
+
+// static
+ScreenWin::DisplayWin ScreenWin::GetDisplayNearestDIPPoint(
+ const Point& dip_point) {
+ ScreenWin* screen = GetNativeScreenWin();
+ DisplayWin primary_display_win;
+ for (const DisplayWin& display_win : screen->display_wins_) {
+ Display display = display_win.display();
+ gfx::Rect dip_bounds = display.bounds();
+ if (dip_bounds.Contains(dip_point))
+ return display_win;
+ else if (dip_bounds.origin().IsOrigin())
+ primary_display_win = display_win;
+ }
+ return primary_display_win;
+}
+
+// static
+float ScreenWin::GetScaleFactorForHWND(HWND hwnd) {
+ DCHECK(hwnd);
+ ScreenWin* screen = GetNativeScreenWin();
+ HWND rootHwnd = screen->GetRootWindow(hwnd);
+ return GetDisplayNearestHWND(rootHwnd).display().device_scale_factor();
+}
+
+// static
+float ScreenWin::GetScaleFactorForScreenPoint(const Point& screen_point) {
+ Display display = GetDisplayNearestScreenPoint(screen_point).display();
+ return display.device_scale_factor();
+}
+
+// static
+std::vector<ScreenWin::DisplayInfo>::const_iterator
+ScreenWin::FindTouchingDisplayInfo(
+ const DisplayWin& display_win,
+ const std::vector<DisplayInfo>& display_infos) {
+ auto end = display_infos.end();
+ for (auto display_info = display_infos.begin();
+ display_info != end;
+ display_info++) {
+ gfx::win::RectEdge edge = gfx::win::RectTouch(display_win.physical_bounds(),
+ display_info->screen_rect());
+ if (edge != gfx::win::RectEdge::NONE) {
+ return display_info;
+ }
+ }
+ return end;
+}
+
+// static
+std::vector<ScreenWin::DisplayWin> ScreenWin::GetDisplaysFromDisplayInfos(
+ const std::vector<ScreenWin::DisplayInfo>& display_infos) {
+ std::vector<DisplayInfo> display_infos_remaining = display_infos;
+
+ // Seed the primary display to layout all the other displays.
+ std::vector<DisplayWin> display_wins;
+ for (auto current = display_infos_remaining.begin();
+ current != display_infos_remaining.end();
+ current++) {
+ if (current->screen_rect().origin().IsOrigin()) {
+ display_wins.push_back(DisplayWin(*current));
+ display_infos_remaining.erase(current);
+ break;
+ }
+ }
+
+ // Scale touching display_infos relative to each other.
+ size_t display_infos_at_cycle_start = 0;
+ while ((display_infos_remaining.size() > 0) &&
+ (display_infos_remaining.size() != display_infos_at_cycle_start)) {
+ display_infos_at_cycle_start = display_infos_remaining.size();
+ for (const DisplayWin& display_win : display_wins) {
+ auto display_info = FindTouchingDisplayInfo(display_win,
+ display_infos_remaining);
+ if (display_info != display_infos_remaining.end()) {
+ display_wins.push_back(DisplayWin(display_win, *display_info));
+ display_infos_remaining.erase(display_info);
+ break;
+ }
+ }
+ }
+
+ // Under Windows DPI virtualization, not all display_infos touch, so scale
+ // the remaining display infos relative to the origin.
+ for (const DisplayInfo& display_info : display_infos_remaining) {
+ display_wins.push_back(DisplayWin(display_info));
+ }
+
+ return display_wins;
+}
+
+// static
+std::vector<ScreenWin::DisplayWin> ScreenWin::GetDisplayWins() {
+ std::vector<DisplayInfo> display_infos;
+ EnumDisplayMonitors(NULL, NULL, EnumMonitorCallback,
+ reinterpret_cast<LPARAM>(&display_infos));
+ return GetDisplaysFromDisplayInfos(display_infos);
+}
+
+// static
+BOOL CALLBACK ScreenWin::EnumMonitorCallback(HMONITOR monitor,
+ HDC hdc,
+ LPRECT rect,
+ LPARAM data) {
+ std::vector<DisplayInfo>* display_infos =
+ reinterpret_cast<std::vector<DisplayInfo>*>(data);
+ DCHECK(display_infos);
+ display_infos->push_back(DisplayInfo(monitor, gfx::GetDPIScale()));
+ return TRUE;
+}
+
void ScreenWin::OnWndProc(HWND hwnd,
UINT message,
WPARAM wparam,
@@ -197,20 +507,45 @@ void ScreenWin::OnWndProc(HWND hwnd,
if (message != WM_DISPLAYCHANGE)
return;
- std::vector<gfx::Display> old_displays = displays_;
- displays_ = GetDisplays();
+ std::vector<gfx::Display> old_displays = GetAllDisplays();
+ display_wins_ = GetDisplayWins();
+ std::vector<gfx::Display> new_displays = GetAllDisplays();
- change_notifier_.NotifyDisplaysChanged(old_displays, displays_);
+ change_notifier_.NotifyDisplaysChanged(old_displays, new_displays);
}
-// static
-std::vector<gfx::Display> ScreenWin::GetDisplaysForMonitorInfos(
- const std::vector<MONITORINFOEX>& monitor_infos) {
- std::vector<gfx::Display> displays;
- for (const MONITORINFOEX& monitor_info : monitor_infos)
- displays.push_back(GetDisplay(monitor_info));
+MONITORINFOEX ScreenWin::MonitorInfoFromScreenPoint(
+ const gfx::Point& screen_point) const {
+ POINT initial_loc = { screen_point.x(), screen_point.y() };
+ return MonitorInfoFromHMONITOR(::MonitorFromPoint(initial_loc,
+ MONITOR_DEFAULTTONEAREST));
+}
- return displays;
+MONITORINFOEX ScreenWin::MonitorInfoFromScreenRect(const gfx::Rect& screen_rect)
+ const {
+ RECT win_rect = screen_rect.ToRECT();
+ return MonitorInfoFromHMONITOR(::MonitorFromRect(&win_rect,
+ MONITOR_DEFAULTTONEAREST));
+}
+
+MONITORINFOEX ScreenWin::MonitorInfoFromWindow(HWND hwnd) const {
+ return MonitorInfoFromHMONITOR(::MonitorFromWindow(hwnd,
+ MONITOR_DEFAULTTONEAREST));
+}
+
+HWND ScreenWin::GetRootWindow(HWND hwnd) const {
+ return GetAncestor(hwnd, GA_ROOT);
+}
+
+ScreenWin::DisplayWin ScreenWin::GetDisplayWin(
+ const MONITORINFOEX& monitor_info) const {
+ int64_t id = HashDeviceName(monitor_info.szDevice);
+ for (const DisplayWin& display_win : display_wins_) {
+ if (display_win.display().id() == id)
+ return display_win;
+ }
+ NOTREACHED();
+ return DisplayWin();
}
} // namespace gfx
« 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