screen_win.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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
16namespace {
17
18MONITORINFOEX GetMonitorInfoForMonitor(HMONITOR monitor) {
19  MONITORINFOEX monitor_info;
20  ZeroMemory(&monitor_info, sizeof(MONITORINFOEX));
21  monitor_info.cbSize = sizeof(monitor_info);
22  base::win::GetMonitorInfoWrapper(monitor, &monitor_info);
23  return monitor_info;
24}
25
26gfx::Display GetDisplay(MONITORINFOEX& monitor_info) {
27  // TODO(oshima): Implement Observer.
28  int64 id = static_cast<int64>(base::Hash(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  return display;
34}
35
36BOOL CALLBACK EnumMonitorCallback(HMONITOR monitor,
37                                  HDC hdc,
38                                  LPRECT rect,
39                                  LPARAM data) {
40  std::vector<gfx::Display>* all_displays =
41      reinterpret_cast<std::vector<gfx::Display>*>(data);
42  DCHECK(all_displays);
43
44  MONITORINFOEX monitor_info = GetMonitorInfoForMonitor(monitor);
45  gfx::Display display = GetDisplay(monitor_info);
46  all_displays->push_back(display);
47  return TRUE;
48}
49
50}  // namespace
51
52namespace gfx {
53
54ScreenWin::ScreenWin() {
55}
56
57ScreenWin::~ScreenWin() {
58}
59
60bool ScreenWin::IsDIPEnabled() {
61  return IsInHighDPIMode();
62}
63
64gfx::Point ScreenWin::GetCursorScreenPoint() {
65  POINT pt;
66  GetCursorPos(&pt);
67  return gfx::Point(pt);
68}
69
70gfx::NativeWindow ScreenWin::GetWindowUnderCursor() {
71  POINT cursor_loc;
72  HWND hwnd = GetCursorPos(&cursor_loc) ? WindowFromPoint(cursor_loc) : NULL;
73  return GetNativeWindowFromHWND(hwnd);
74}
75
76gfx::NativeWindow ScreenWin::GetWindowAtScreenPoint(const gfx::Point& point) {
77  return GetNativeWindowFromHWND(WindowFromPoint(point.ToPOINT()));
78}
79
80int ScreenWin::GetNumDisplays() const {
81  return GetSystemMetrics(SM_CMONITORS);
82}
83
84std::vector<gfx::Display> ScreenWin::GetAllDisplays() const {
85  std::vector<gfx::Display> all_displays;
86  EnumDisplayMonitors(NULL, NULL, EnumMonitorCallback,
87                      reinterpret_cast<LPARAM>(&all_displays));
88  return all_displays;
89}
90
91gfx::Display ScreenWin::GetDisplayNearestWindow(gfx::NativeView window) const {
92  HWND window_hwnd = GetHWNDFromNativeView(window);
93  if (!window_hwnd) {
94    // When |window| isn't rooted to a display, we should just return the
95    // default display so we get some correct display information like the
96    // scaling factor.
97    return GetPrimaryDisplay();
98  }
99
100  MONITORINFOEX monitor_info;
101  monitor_info.cbSize = sizeof(monitor_info);
102  base::win::GetMonitorInfoWrapper(
103      MonitorFromWindow(window_hwnd, MONITOR_DEFAULTTONEAREST), &monitor_info);
104  return GetDisplay(monitor_info);
105}
106
107gfx::Display ScreenWin::GetDisplayNearestPoint(const gfx::Point& point) const {
108  POINT initial_loc = { point.x(), point.y() };
109  HMONITOR monitor = MonitorFromPoint(initial_loc, MONITOR_DEFAULTTONEAREST);
110  MONITORINFOEX mi;
111  ZeroMemory(&mi, sizeof(MONITORINFOEX));
112  mi.cbSize = sizeof(mi);
113  if (monitor && base::win::GetMonitorInfoWrapper(monitor, &mi)) {
114    return GetDisplay(mi);
115  }
116  return gfx::Display();
117}
118
119gfx::Display ScreenWin::GetDisplayMatching(const gfx::Rect& match_rect) const {
120  RECT other_bounds_rect = match_rect.ToRECT();
121  MONITORINFOEX monitor_info = GetMonitorInfoForMonitor(MonitorFromRect(
122      &other_bounds_rect, MONITOR_DEFAULTTONEAREST));
123  return GetDisplay(monitor_info);
124}
125
126gfx::Display ScreenWin::GetPrimaryDisplay() const {
127  MONITORINFOEX mi = GetMonitorInfoForMonitor(
128      MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY));
129  gfx::Display display = GetDisplay(mi);
130  // TODO(kevers|girard): Test if these checks can be reintroduced for high-DIP
131  // once more of the app is DIP-aware.
132  if (!IsInHighDPIMode()) {
133    DCHECK_EQ(GetSystemMetrics(SM_CXSCREEN), display.size().width());
134    DCHECK_EQ(GetSystemMetrics(SM_CYSCREEN), display.size().height());
135  }
136  return display;
137}
138
139void ScreenWin::AddObserver(DisplayObserver* observer) {
140  // TODO(oshima): crbug.com/122863.
141}
142
143void ScreenWin::RemoveObserver(DisplayObserver* observer) {
144  // TODO(oshima): crbug.com/122863.
145}
146
147HWND ScreenWin::GetHWNDFromNativeView(NativeView window) const {
148#if defined(USE_AURA)
149  NOTREACHED();
150  return NULL;
151#else
152  return window;
153#endif  // USE_AURA
154}
155
156NativeWindow ScreenWin::GetNativeWindowFromHWND(HWND hwnd) const {
157#if defined(USE_AURA)
158  NOTREACHED();
159  return NULL;
160#else
161  return hwnd;
162#endif  // USE_AURA
163}
164
165#if !defined(USE_AURA)
166Screen* CreateNativeScreen() {
167  return new ScreenWin;
168}
169#endif  // !USE_AURA
170
171}  // namespace gfx
172