screen_win.cc revision 6d86b77056ed63eb6871182f42a9fd5f07550f90
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  gfx::Point cursor_pos_pixels(pt);
69  return gfx::win::ScreenToDIPPoint(cursor_pos_pixels);
70}
71
72gfx::NativeWindow ScreenWin::GetWindowUnderCursor() {
73  POINT cursor_loc;
74  HWND hwnd = GetCursorPos(&cursor_loc) ? WindowFromPoint(cursor_loc) : NULL;
75  return GetNativeWindowFromHWND(hwnd);
76}
77
78gfx::NativeWindow ScreenWin::GetWindowAtScreenPoint(const gfx::Point& point) {
79  gfx::Point point_in_pixels = gfx::win::DIPToScreenPoint(point);
80  return GetNativeWindowFromHWND(WindowFromPoint(point_in_pixels.ToPOINT()));
81}
82
83int ScreenWin::GetNumDisplays() const {
84  return GetSystemMetrics(SM_CMONITORS);
85}
86
87std::vector<gfx::Display> ScreenWin::GetAllDisplays() const {
88  std::vector<gfx::Display> all_displays;
89  EnumDisplayMonitors(NULL, NULL, EnumMonitorCallback,
90                      reinterpret_cast<LPARAM>(&all_displays));
91  return all_displays;
92}
93
94gfx::Display ScreenWin::GetDisplayNearestWindow(gfx::NativeView window) const {
95  HWND window_hwnd = GetHWNDFromNativeView(window);
96  if (!window_hwnd) {
97    // When |window| isn't rooted to a display, we should just return the
98    // default display so we get some correct display information like the
99    // scaling factor.
100    return GetPrimaryDisplay();
101  }
102
103  MONITORINFOEX monitor_info;
104  monitor_info.cbSize = sizeof(monitor_info);
105  GetMonitorInfo(MonitorFromWindow(window_hwnd, MONITOR_DEFAULTTONEAREST),
106                 &monitor_info);
107  return GetDisplay(monitor_info);
108}
109
110gfx::Display ScreenWin::GetDisplayNearestPoint(const gfx::Point& point) const {
111  POINT initial_loc = { point.x(), point.y() };
112  HMONITOR monitor = MonitorFromPoint(initial_loc, MONITOR_DEFAULTTONEAREST);
113  MONITORINFOEX mi;
114  ZeroMemory(&mi, sizeof(MONITORINFOEX));
115  mi.cbSize = sizeof(mi);
116  if (monitor && GetMonitorInfo(monitor, &mi)) {
117    return GetDisplay(mi);
118  }
119  return gfx::Display();
120}
121
122gfx::Display ScreenWin::GetDisplayMatching(const gfx::Rect& match_rect) const {
123  RECT other_bounds_rect = match_rect.ToRECT();
124  MONITORINFOEX monitor_info = GetMonitorInfoForMonitor(MonitorFromRect(
125      &other_bounds_rect, MONITOR_DEFAULTTONEAREST));
126  return GetDisplay(monitor_info);
127}
128
129gfx::Display ScreenWin::GetPrimaryDisplay() const {
130  MONITORINFOEX mi = GetMonitorInfoForMonitor(
131      MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY));
132  gfx::Display display = GetDisplay(mi);
133  // TODO(kevers|girard): Test if these checks can be reintroduced for high-DIP
134  // once more of the app is DIP-aware.
135  if (!(IsInHighDPIMode() || IsHighDPIEnabled())) {
136    DCHECK_EQ(GetSystemMetrics(SM_CXSCREEN), display.size().width());
137    DCHECK_EQ(GetSystemMetrics(SM_CYSCREEN), display.size().height());
138  }
139  return display;
140}
141
142void ScreenWin::AddObserver(DisplayObserver* observer) {
143  // TODO(oshima): crbug.com/122863.
144}
145
146void ScreenWin::RemoveObserver(DisplayObserver* observer) {
147  // TODO(oshima): crbug.com/122863.
148}
149
150HWND ScreenWin::GetHWNDFromNativeView(NativeView window) const {
151  NOTREACHED();
152  return NULL;
153}
154
155NativeWindow ScreenWin::GetNativeWindowFromHWND(HWND hwnd) const {
156  NOTREACHED();
157  return NULL;
158}
159
160}  // namespace gfx
161