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