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::GetDPIScale(), 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 gfx::Point
ScreenWin::GetCursorScreenPoint() {
99 gfx::Point
cursor_pos_pixels(pt
);
100 return gfx::win::ScreenToDIPPoint(cursor_pos_pixels
);
103 gfx::NativeWindow
ScreenWin::GetWindowUnderCursor() {
105 HWND hwnd
= GetCursorPos(&cursor_loc
) ? WindowFromPoint(cursor_loc
) : NULL
;
106 return GetNativeWindowFromHWND(hwnd
);
109 gfx::NativeWindow
ScreenWin::GetWindowAtScreenPoint(const gfx::Point
& point
) {
110 gfx::Point point_in_pixels
= gfx::win::DIPToScreenPoint(point
);
111 return GetNativeWindowFromHWND(WindowFromPoint(point_in_pixels
.ToPOINT()));
114 int ScreenWin::GetNumDisplays() const {
115 return GetSystemMetrics(SM_CMONITORS
);
118 std::vector
<gfx::Display
> ScreenWin::GetAllDisplays() const {
122 gfx::Display
ScreenWin::GetDisplayNearestWindow(gfx::NativeView window
) const {
123 HWND window_hwnd
= GetHWNDFromNativeView(window
);
125 // When |window| isn't rooted to a display, we should just return the
126 // default display so we get some correct display information like the
128 return GetPrimaryDisplay();
131 MONITORINFOEX monitor_info
;
132 monitor_info
.cbSize
= sizeof(monitor_info
);
133 GetMonitorInfo(MonitorFromWindow(window_hwnd
, MONITOR_DEFAULTTONEAREST
),
135 return GetDisplay(monitor_info
);
138 gfx::Display
ScreenWin::GetDisplayNearestPoint(const gfx::Point
& point
) const {
139 POINT initial_loc
= { point
.x(), point
.y() };
140 HMONITOR monitor
= MonitorFromPoint(initial_loc
, MONITOR_DEFAULTTONEAREST
);
142 ZeroMemory(&mi
, sizeof(MONITORINFOEX
));
143 mi
.cbSize
= sizeof(mi
);
144 if (monitor
&& GetMonitorInfo(monitor
, &mi
)) {
145 return GetDisplay(mi
);
147 return gfx::Display();
150 gfx::Display
ScreenWin::GetDisplayMatching(const gfx::Rect
& match_rect
) const {
151 RECT other_bounds_rect
= match_rect
.ToRECT();
152 MONITORINFOEX monitor_info
= GetMonitorInfoForMonitor(MonitorFromRect(
153 &other_bounds_rect
, MONITOR_DEFAULTTONEAREST
));
154 return GetDisplay(monitor_info
);
157 gfx::Display
ScreenWin::GetPrimaryDisplay() const {
158 MONITORINFOEX mi
= GetMonitorInfoForMonitor(
159 MonitorFromWindow(NULL
, MONITOR_DEFAULTTOPRIMARY
));
160 gfx::Display display
= GetDisplay(mi
);
161 // TODO(kevers|girard): Test if these checks can be reintroduced for high-DIP
162 // once more of the app is DIP-aware.
163 if (GetDPIScale() == 1.0) {
164 DCHECK_EQ(GetSystemMetrics(SM_CXSCREEN
), display
.size().width());
165 DCHECK_EQ(GetSystemMetrics(SM_CYSCREEN
), display
.size().height());
170 void ScreenWin::AddObserver(DisplayObserver
* observer
) {
171 change_notifier_
.AddObserver(observer
);
174 void ScreenWin::RemoveObserver(DisplayObserver
* observer
) {
175 change_notifier_
.RemoveObserver(observer
);
178 void ScreenWin::OnWndProc(HWND hwnd
,
182 if (message
!= WM_DISPLAYCHANGE
)
185 std::vector
<gfx::Display
> old_displays
= displays_
;
186 displays_
= GetDisplays();
188 change_notifier_
.NotifyDisplaysChanged(old_displays
, displays_
);
191 HWND
ScreenWin::GetHWNDFromNativeView(NativeView window
) const {
196 NativeWindow
ScreenWin::GetNativeWindowFromHWND(HWND hwnd
) const {