OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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/win/display_manager.h" | |
6 | |
7 #include <windows.h> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/bind_helpers.h" | |
11 #include "base/lazy_instance.h" | |
12 #include "base/memory/scoped_ptr.h" | |
13 #include "ui/gfx/win/display_info.h" | |
14 #include "ui/gfx/win/display_manager_observer.h" | |
15 #include "ui/gfx/win/dpi.h" | |
16 #include "ui/gfx/win/screen_win_display.h" | |
17 #include "ui/gfx/win/singleton_hwnd_observer.h" | |
18 | |
19 namespace { | |
20 | |
21 // Use Leaky since gfx::ScreenWin is leaked at exit, and LazyInstance instead of | |
22 // Singleton allows for a substitution for testing. | |
23 base::LazyInstance<scoped_ptr<gfx::win::DisplayManager>>::Leaky | |
24 g_display_manager = LAZY_INSTANCE_INITIALIZER; | |
25 | |
26 MONITORINFOEX MonitorInfoFromHMONITOR(HMONITOR monitor) { | |
27 MONITORINFOEX monitor_info; | |
28 ::ZeroMemory(&monitor_info, sizeof(monitor_info)); | |
29 monitor_info.cbSize = sizeof(monitor_info); | |
30 ::GetMonitorInfo(monitor, &monitor_info); | |
31 return monitor_info; | |
32 } | |
33 | |
34 BOOL CALLBACK EnumMonitorCallback(HMONITOR monitor, | |
35 HDC hdc, | |
36 LPRECT rect, | |
37 LPARAM data) { | |
38 std::vector<gfx::win::DisplayInfo>* display_infos = | |
39 reinterpret_cast<std::vector<gfx::win::DisplayInfo>*>(data); | |
40 DCHECK(display_infos); | |
41 display_infos->push_back( | |
42 gfx::win::DisplayInfo(MonitorInfoFromHMONITOR(monitor), | |
43 gfx::GetDPIScale())); | |
44 return TRUE; | |
45 } | |
46 | |
47 std::vector<gfx::win::DisplayInfo> GetDisplayInfosFromSystem() { | |
48 std::vector<gfx::win::DisplayInfo> display_infos; | |
49 EnumDisplayMonitors(NULL, NULL, EnumMonitorCallback, | |
50 reinterpret_cast<LPARAM>(&display_infos)); | |
51 DCHECK_EQ(static_cast<size_t>(::GetSystemMetrics(SM_CMONITORS)), | |
52 display_infos.size()); | |
53 return display_infos; | |
54 } | |
55 | |
56 std::vector<gfx::win::ScreenWinDisplay> DisplayInfosToScreenWinDisplays( | |
57 const std::vector<gfx::win::DisplayInfo>& display_infos) { | |
58 std::vector<gfx::win::ScreenWinDisplay> screen_win_displays; | |
59 for (const auto& display_info : display_infos) | |
60 screen_win_displays.push_back(gfx::win::ScreenWinDisplay(display_info)); | |
61 | |
62 return screen_win_displays; | |
63 } | |
64 | |
65 } // namespace | |
66 | |
67 namespace gfx { | |
68 namespace win { | |
69 | |
70 // static | |
71 DisplayManager* DisplayManager::GetInstance() { | |
72 if (!g_display_manager.Get().get()) { | |
73 g_display_manager.Get().reset(new DisplayManager()); | |
74 g_display_manager.Get()->Initialize(); | |
75 } | |
76 return g_display_manager.Get().get(); | |
77 } | |
78 | |
79 void DisplayManager::Initialize() { | |
80 singleton_hwnd_observer_.reset( | |
81 new gfx::SingletonHwndObserver( | |
82 base::Bind(&DisplayManager::WndProc, base::Unretained(this)))); | |
83 UpdateFromDisplayInfos(GetDisplayInfosFromSystem()); | |
84 } | |
85 | |
86 void DisplayManager::AddObserver(DisplayManagerObserver* observer) { | |
87 observer_list_.AddObserver(observer); | |
88 } | |
89 | |
90 void DisplayManager::RemoveObserver(DisplayManagerObserver* observer) { | |
91 observer_list_.RemoveObserver(observer); | |
92 } | |
93 | |
94 const std::vector<ScreenWinDisplay>& DisplayManager::GetScreenWinDisplays() { | |
95 return screen_win_displays_; | |
96 } | |
97 | |
98 ScreenWinDisplay DisplayManager::GetScreenWinDisplayNearestHWND(HWND hwnd) | |
99 const { | |
100 return GetScreenWinDisplay(MonitorInfoFromWindow(hwnd, | |
101 MONITOR_DEFAULTTONEAREST)); | |
102 } | |
103 | |
104 ScreenWinDisplay DisplayManager::GetScreenWinDisplayNearestScreenRect( | |
105 const Rect& screen_rect) const { | |
106 return GetScreenWinDisplay(MonitorInfoFromScreenRect(screen_rect)); | |
107 } | |
108 | |
109 ScreenWinDisplay DisplayManager::GetScreenWinDisplayNearestScreenPoint( | |
110 const Point& screen_point) const { | |
111 return GetScreenWinDisplay(MonitorInfoFromScreenPoint(screen_point)); | |
112 } | |
113 | |
114 ScreenWinDisplay DisplayManager::GetPrimaryScreenWinDisplay() const { | |
115 MONITORINFOEX monitor_info = MonitorInfoFromWindow(NULL, | |
116 MONITOR_DEFAULTTOPRIMARY); | |
117 ScreenWinDisplay screen_win_display = GetScreenWinDisplay(monitor_info); | |
118 gfx::Display display = screen_win_display.display(); | |
119 // The Windows primary monitor is defined to have an origin of (0, 0). | |
120 DCHECK_EQ(0, display.bounds().origin().x()); | |
121 DCHECK_EQ(0, display.bounds().origin().y()); | |
122 return screen_win_display; | |
123 } | |
124 | |
125 MONITORINFOEX DisplayManager::MonitorInfoFromScreenPoint( | |
126 const gfx::Point& screen_point) const { | |
127 POINT initial_loc = { screen_point.x(), screen_point.y() }; | |
128 return MonitorInfoFromHMONITOR(::MonitorFromPoint(initial_loc, | |
129 MONITOR_DEFAULTTONEAREST)); | |
130 } | |
131 | |
132 MONITORINFOEX DisplayManager::MonitorInfoFromScreenRect( | |
133 const gfx::Rect& screen_rect) const { | |
134 RECT win_rect = screen_rect.ToRECT(); | |
135 return MonitorInfoFromHMONITOR(::MonitorFromRect(&win_rect, | |
136 MONITOR_DEFAULTTONEAREST)); | |
137 } | |
138 | |
139 MONITORINFOEX DisplayManager::MonitorInfoFromWindow( | |
140 HWND hwnd, DWORD default_options) const { | |
141 return MonitorInfoFromHMONITOR(::MonitorFromWindow(hwnd, | |
142 default_options)); | |
oshima
2016/01/30 00:10:33
fit to single line?
robliao
2016/01/30 01:23:52
Done.
| |
143 } | |
144 | |
145 HWND DisplayManager::GetRootWindow(HWND hwnd) const { | |
146 return ::GetAncestor(hwnd, GA_ROOT); | |
147 } | |
148 | |
149 // static | |
150 void DisplayManager::SetInstanceForTesting( | |
151 scoped_ptr<DisplayManager> display_manager) { | |
152 g_display_manager.Get() = std::move(display_manager); | |
153 } | |
154 | |
155 DisplayManager::DisplayManager() = default; | |
156 | |
157 DisplayManager::~DisplayManager() = default; | |
158 | |
159 void DisplayManager::UpdateFromDisplayInfos( | |
160 const std::vector<DisplayInfo>& display_infos) { | |
161 screen_win_displays_ = DisplayInfosToScreenWinDisplays(display_infos); | |
162 } | |
163 | |
164 ScreenWinDisplay DisplayManager::GetScreenWinDisplay( | |
165 const MONITORINFOEX& monitor_info) const { | |
166 int64_t id = DisplayInfo::HashDeviceName(monitor_info.szDevice); | |
167 for (const auto& screen_win_display : screen_win_displays_) { | |
168 if (screen_win_display.display().id() == id) | |
169 return screen_win_display; | |
170 } | |
171 // When the system isn't initialized, it means we're likely under a test. | |
172 DCHECK_EQ(screen_win_displays_.size(), 0u); | |
173 return ScreenWinDisplay(); | |
174 } | |
175 | |
176 void DisplayManager::WndProc(HWND hwnd, | |
177 UINT message, | |
178 WPARAM wparam,LPARAM lparam) { | |
179 if (message != WM_DISPLAYCHANGE) | |
180 return; | |
181 | |
182 std::vector<ScreenWinDisplay> old_displays = screen_win_displays_; | |
183 UpdateFromDisplayInfos(GetDisplayInfosFromSystem()); | |
184 | |
185 FOR_EACH_OBSERVER(DisplayManagerObserver, | |
186 observer_list_, | |
187 OnDisplaysChanged(old_displays, screen_win_displays_)); | |
188 } | |
189 | |
190 } // namespace win | |
191 } // namespace gfx | |
OLD | NEW |