OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "ui/gfx/screen_win.h" | |
6 | |
7 #include <windows.h> | |
8 | |
9 #include "base/hash.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" | |
15 | |
16 namespace { | |
17 | |
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); | |
23 return monitor_info; | |
24 } | |
25 | |
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); | |
33 | |
34 DEVMODE mode; | |
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, | |
40 &mode)) { | |
41 switch (mode.dmDisplayOrientation) { | |
42 case DMDO_DEFAULT: | |
43 display.set_rotation(gfx::Display::ROTATE_0); | |
44 break; | |
45 case DMDO_90: | |
46 display.set_rotation(gfx::Display::ROTATE_90); | |
47 break; | |
48 case DMDO_180: | |
49 display.set_rotation(gfx::Display::ROTATE_180); | |
50 break; | |
51 case DMDO_270: | |
52 display.set_rotation(gfx::Display::ROTATE_270); | |
53 break; | |
54 default: | |
55 NOTREACHED(); | |
56 } | |
57 } | |
58 | |
59 return display; | |
60 } | |
61 | |
62 BOOL CALLBACK EnumMonitorCallback(HMONITOR monitor, | |
63 HDC hdc, | |
64 LPRECT rect, | |
65 LPARAM data) { | |
66 std::vector<gfx::Display>* all_displays = | |
67 reinterpret_cast<std::vector<gfx::Display>*>(data); | |
68 DCHECK(all_displays); | |
69 | |
70 MONITORINFOEX monitor_info = GetMonitorInfoForMonitor(monitor); | |
71 gfx::Display display = GetDisplay(monitor_info); | |
72 all_displays->push_back(display); | |
73 return TRUE; | |
74 } | |
75 | |
76 std::vector<gfx::Display> GetDisplays() { | |
77 std::vector<gfx::Display> displays; | |
78 EnumDisplayMonitors(NULL, NULL, EnumMonitorCallback, | |
79 reinterpret_cast<LPARAM>(&displays)); | |
80 return displays; | |
81 } | |
82 | |
83 } // namespace | |
84 | |
85 namespace gfx { | |
86 | |
87 ScreenWin::ScreenWin() | |
88 : displays_(GetDisplays()) { | |
89 SingletonHwnd::GetInstance()->AddObserver(this); | |
90 } | |
91 | |
92 ScreenWin::~ScreenWin() { | |
93 SingletonHwnd::GetInstance()->RemoveObserver(this); | |
94 } | |
95 | |
96 bool ScreenWin::IsDIPEnabled() { | |
97 return IsInHighDPIMode(); | |
98 } | |
99 | |
100 gfx::Point ScreenWin::GetCursorScreenPoint() { | |
101 POINT pt; | |
102 GetCursorPos(&pt); | |
103 gfx::Point cursor_pos_pixels(pt); | |
104 return gfx::win::ScreenToDIPPoint(cursor_pos_pixels); | |
105 } | |
106 | |
107 gfx::NativeWindow ScreenWin::GetWindowUnderCursor() { | |
108 POINT cursor_loc; | |
109 HWND hwnd = GetCursorPos(&cursor_loc) ? WindowFromPoint(cursor_loc) : NULL; | |
110 return GetNativeWindowFromHWND(hwnd); | |
111 } | |
112 | |
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())); | |
116 } | |
117 | |
118 int ScreenWin::GetNumDisplays() const { | |
119 return GetSystemMetrics(SM_CMONITORS); | |
120 } | |
121 | |
122 std::vector<gfx::Display> ScreenWin::GetAllDisplays() const { | |
123 return displays_; | |
124 } | |
125 | |
126 gfx::Display ScreenWin::GetDisplayNearestWindow(gfx::NativeView window) const { | |
127 HWND window_hwnd = GetHWNDFromNativeView(window); | |
128 if (!window_hwnd) { | |
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 | |
131 // scaling factor. | |
132 return GetPrimaryDisplay(); | |
133 } | |
134 | |
135 MONITORINFOEX monitor_info; | |
136 monitor_info.cbSize = sizeof(monitor_info); | |
137 GetMonitorInfo(MonitorFromWindow(window_hwnd, MONITOR_DEFAULTTONEAREST), | |
138 &monitor_info); | |
139 return GetDisplay(monitor_info); | |
140 } | |
141 | |
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); | |
145 MONITORINFOEX mi; | |
146 ZeroMemory(&mi, sizeof(MONITORINFOEX)); | |
147 mi.cbSize = sizeof(mi); | |
148 if (monitor && GetMonitorInfo(monitor, &mi)) { | |
149 return GetDisplay(mi); | |
150 } | |
151 return gfx::Display(); | |
152 } | |
153 | |
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); | |
159 } | |
160 | |
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()); | |
170 } | |
171 return display; | |
172 } | |
173 | |
174 void ScreenWin::AddObserver(DisplayObserver* observer) { | |
175 change_notifier_.AddObserver(observer); | |
176 } | |
177 | |
178 void ScreenWin::RemoveObserver(DisplayObserver* observer) { | |
179 change_notifier_.RemoveObserver(observer); | |
180 } | |
181 | |
182 void ScreenWin::OnWndProc(HWND hwnd, | |
183 UINT message, | |
184 WPARAM wparam, | |
185 LPARAM lparam) { | |
186 if (message != WM_DISPLAYCHANGE) | |
187 return; | |
188 | |
189 std::vector<gfx::Display> old_displays = displays_; | |
190 displays_ = GetDisplays(); | |
191 | |
192 change_notifier_.NotifyDisplaysChanged(old_displays, displays_); | |
193 } | |
194 | |
195 HWND ScreenWin::GetHWNDFromNativeView(NativeView window) const { | |
196 NOTREACHED(); | |
197 return NULL; | |
198 } | |
199 | |
200 NativeWindow ScreenWin::GetNativeWindowFromHWND(HWND hwnd) const { | |
201 NOTREACHED(); | |
202 return NULL; | |
203 } | |
204 | |
205 } // namespace gfx | |
OLD | NEW |