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
3 // found in the LICENSE file.
5 #include "ui/gfx/screen_win.h"
10 #include "base/logging.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/win/win_util.h"
13 #include "ui/gfx/display.h"
14 #include "ui/gfx/win/dpi.h"
18 MONITORINFOEX
GetMonitorInfoForMonitor(HMONITOR monitor
) {
19 MONITORINFOEX monitor_info
;
20 ZeroMemory(&monitor_info
, sizeof(MONITORINFOEX
));
21 monitor_info
.cbSize
= sizeof(monitor_info
);
22 GetMonitorInfo(monitor
, &monitor_info
);
26 gfx::Display
GetDisplay(MONITORINFOEX
& monitor_info
) {
27 int64 id
= static_cast<int64
>(
28 base::Hash(base::WideToUTF8(monitor_info
.szDevice
)));
29 gfx::Rect bounds
= gfx::Rect(monitor_info
.rcMonitor
);
30 gfx::Display
display(id
, bounds
);
31 display
.set_work_area(gfx::Rect(monitor_info
.rcWork
));
32 display
.SetScaleAndBounds(gfx::win::GetDeviceScaleFactor(), bounds
);
35 memset(&mode
, 0, sizeof(DEVMODE
));
36 mode
.dmSize
= sizeof(DEVMODE
);
37 mode
.dmDriverExtra
= 0;
38 if (EnumDisplaySettings(monitor_info
.szDevice
,
39 ENUM_CURRENT_SETTINGS
,
41 switch (mode
.dmDisplayOrientation
) {
43 display
.set_rotation(gfx::Display::ROTATE_0
);
46 display
.set_rotation(gfx::Display::ROTATE_90
);
49 display
.set_rotation(gfx::Display::ROTATE_180
);
52 display
.set_rotation(gfx::Display::ROTATE_270
);
62 BOOL CALLBACK
EnumMonitorCallback(HMONITOR monitor
,
66 std::vector
<gfx::Display
>* all_displays
=
67 reinterpret_cast<std::vector
<gfx::Display
>*>(data
);
70 MONITORINFOEX monitor_info
= GetMonitorInfoForMonitor(monitor
);
71 gfx::Display display
= GetDisplay(monitor_info
);
72 all_displays
->push_back(display
);
76 std::vector
<gfx::Display
> GetDisplays() {
77 std::vector
<gfx::Display
> displays
;
78 EnumDisplayMonitors(NULL
, NULL
, EnumMonitorCallback
,
79 reinterpret_cast<LPARAM
>(&displays
));
87 ScreenWin::ScreenWin()
88 : displays_(GetDisplays()) {
89 SingletonHwnd::GetInstance()->AddObserver(this);
92 ScreenWin::~ScreenWin() {
93 SingletonHwnd::GetInstance()->RemoveObserver(this);
96 bool ScreenWin::IsDIPEnabled() {
97 return IsInHighDPIMode();
100 gfx::Point
ScreenWin::GetCursorScreenPoint() {
103 gfx::Point
cursor_pos_pixels(pt
);
104 return gfx::win::ScreenToDIPPoint(cursor_pos_pixels
);
107 gfx::NativeWindow
ScreenWin::GetWindowUnderCursor() {
109 HWND hwnd
= GetCursorPos(&cursor_loc
) ? WindowFromPoint(cursor_loc
) : NULL
;
110 return GetNativeWindowFromHWND(hwnd
);
113 gfx::NativeWindow
ScreenWin::GetWindowAtScreenPoint(const gfx::Point
& point
) {
114 gfx::Point point_in_pixels
= gfx::win::DIPToScreenPoint(point
);
115 return GetNativeWindowFromHWND(WindowFromPoint(point_in_pixels
.ToPOINT()));
118 int ScreenWin::GetNumDisplays() const {
119 return GetSystemMetrics(SM_CMONITORS
);
122 std::vector
<gfx::Display
> ScreenWin::GetAllDisplays() const {
126 gfx::Display
ScreenWin::GetDisplayNearestWindow(gfx::NativeView window
) const {
127 HWND window_hwnd
= GetHWNDFromNativeView(window
);
129 // When |window| isn't rooted to a display, we should just return the
130 // default display so we get some correct display information like the
132 return GetPrimaryDisplay();
135 MONITORINFOEX monitor_info
;
136 monitor_info
.cbSize
= sizeof(monitor_info
);
137 GetMonitorInfo(MonitorFromWindow(window_hwnd
, MONITOR_DEFAULTTONEAREST
),
139 return GetDisplay(monitor_info
);
142 gfx::Display
ScreenWin::GetDisplayNearestPoint(const gfx::Point
& point
) const {
143 POINT initial_loc
= { point
.x(), point
.y() };
144 HMONITOR monitor
= MonitorFromPoint(initial_loc
, MONITOR_DEFAULTTONEAREST
);
146 ZeroMemory(&mi
, sizeof(MONITORINFOEX
));
147 mi
.cbSize
= sizeof(mi
);
148 if (monitor
&& GetMonitorInfo(monitor
, &mi
)) {
149 return GetDisplay(mi
);
151 return gfx::Display();
154 gfx::Display
ScreenWin::GetDisplayMatching(const gfx::Rect
& match_rect
) const {
155 RECT other_bounds_rect
= match_rect
.ToRECT();
156 MONITORINFOEX monitor_info
= GetMonitorInfoForMonitor(MonitorFromRect(
157 &other_bounds_rect
, MONITOR_DEFAULTTONEAREST
));
158 return GetDisplay(monitor_info
);
161 gfx::Display
ScreenWin::GetPrimaryDisplay() const {
162 MONITORINFOEX mi
= GetMonitorInfoForMonitor(
163 MonitorFromWindow(NULL
, MONITOR_DEFAULTTOPRIMARY
));
164 gfx::Display display
= GetDisplay(mi
);
165 // TODO(kevers|girard): Test if these checks can be reintroduced for high-DIP
166 // once more of the app is DIP-aware.
167 if (!(IsInHighDPIMode() || IsHighDPIEnabled())) {
168 DCHECK_EQ(GetSystemMetrics(SM_CXSCREEN
), display
.size().width());
169 DCHECK_EQ(GetSystemMetrics(SM_CYSCREEN
), display
.size().height());
174 void ScreenWin::AddObserver(DisplayObserver
* observer
) {
175 change_notifier_
.AddObserver(observer
);
178 void ScreenWin::RemoveObserver(DisplayObserver
* observer
) {
179 change_notifier_
.RemoveObserver(observer
);
182 void ScreenWin::OnWndProc(HWND hwnd
,
186 if (message
!= WM_DISPLAYCHANGE
)
189 std::vector
<gfx::Display
> old_displays
= displays_
;
190 displays_
= GetDisplays();
192 change_notifier_
.NotifyDisplaysChanged(old_displays
, displays_
);
195 HWND
ScreenWin::GetHWNDFromNativeView(NativeView window
) const {
200 NativeWindow
ScreenWin::GetNativeWindowFromHWND(HWND hwnd
) const {