screen_win.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen_win.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/hash.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/strings/utf_string_conversions.h"
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/win/win_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/display.h"
14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/win/dpi.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)MONITORINFOEX GetMonitorInfoForMonitor(HMONITOR monitor) {
1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  MONITORINFOEX monitor_info;
2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ZeroMemory(&monitor_info, sizeof(MONITORINFOEX));
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  monitor_info.cbSize = sizeof(monitor_info);
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::win::GetMonitorInfoWrapper(monitor, &monitor_info);
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return monitor_info;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)gfx::Display GetDisplay(MONITORINFOEX& monitor_info) {
2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // TODO(oshima): Implement Observer.
2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int64 id = static_cast<int64>(base::Hash(WideToUTF8(monitor_info.szDevice)));
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect bounds = gfx::Rect(monitor_info.rcMonitor);
3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  gfx::Display display(id, bounds);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  display.set_work_area(gfx::Rect(monitor_info.rcWork));
3258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  display.SetScaleAndBounds(gfx::win::GetDeviceScaleFactor(), bounds);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return display;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)BOOL CALLBACK EnumMonitorCallback(HMONITOR monitor,
3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                  HDC hdc,
3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                  LPRECT rect,
3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                  LPARAM data) {
4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::vector<gfx::Display>* all_displays =
4158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      reinterpret_cast<std::vector<gfx::Display>*>(data);
4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DCHECK(all_displays);
4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  MONITORINFOEX monitor_info = GetMonitorInfoForMonitor(monitor);
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  gfx::Display display = GetDisplay(monitor_info);
4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  all_displays->push_back(display);
4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return TRUE;
4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScreenWin::ScreenWin() {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScreenWin::~ScreenWin() {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ScreenWin::IsDIPEnabled() {
6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return IsInHighDPIMode();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Point ScreenWin::GetCursorScreenPoint() {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  POINT pt;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetCursorPos(&pt);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gfx::Point(pt);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
70424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)gfx::NativeWindow ScreenWin::GetWindowUnderCursor() {
71424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  POINT cursor_loc;
72424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  HWND hwnd = GetCursorPos(&cursor_loc) ? WindowFromPoint(cursor_loc) : NULL;
73424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return GetNativeWindowFromHWND(hwnd);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
76424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)gfx::NativeWindow ScreenWin::GetWindowAtScreenPoint(const gfx::Point& point) {
77424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return GetNativeWindowFromHWND(WindowFromPoint(point.ToPOINT()));
78424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
79424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int ScreenWin::GetNumDisplays() const {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetSystemMetrics(SM_CMONITORS);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)std::vector<gfx::Display> ScreenWin::GetAllDisplays() const {
8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::vector<gfx::Display> all_displays;
8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EnumDisplayMonitors(NULL, NULL, EnumMonitorCallback,
8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                      reinterpret_cast<LPARAM>(&all_displays));
8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return all_displays;
89424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
90424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Display ScreenWin::GetDisplayNearestWindow(gfx::NativeView window) const {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HWND window_hwnd = GetHWNDFromNativeView(window);
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!window_hwnd) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // When |window| isn't rooted to a display, we should just return the
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // default display so we get some correct display information like the
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // scaling factor.
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return GetPrimaryDisplay();
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  MONITORINFOEX monitor_info;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  monitor_info.cbSize = sizeof(monitor_info);
1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::win::GetMonitorInfoWrapper(
1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      MonitorFromWindow(window_hwnd, MONITOR_DEFAULTTONEAREST), &monitor_info);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetDisplay(monitor_info);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Display ScreenWin::GetDisplayNearestPoint(const gfx::Point& point) const {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  POINT initial_loc = { point.x(), point.y() };
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HMONITOR monitor = MonitorFromPoint(initial_loc, MONITOR_DEFAULTTONEAREST);
11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  MONITORINFOEX mi;
11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ZeroMemory(&mi, sizeof(MONITORINFOEX));
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mi.cbSize = sizeof(mi);
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (monitor && base::win::GetMonitorInfoWrapper(monitor, &mi)) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetDisplay(mi);
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gfx::Display();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Display ScreenWin::GetDisplayMatching(const gfx::Rect& match_rect) const {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RECT other_bounds_rect = match_rect.ToRECT();
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  MONITORINFOEX monitor_info = GetMonitorInfoForMonitor(MonitorFromRect(
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &other_bounds_rect, MONITOR_DEFAULTTONEAREST));
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetDisplay(monitor_info);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Display ScreenWin::GetPrimaryDisplay() const {
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  MONITORINFOEX mi = GetMonitorInfoForMonitor(
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Display display = GetDisplay(mi);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(kevers|girard): Test if these checks can be reintroduced for high-DIP
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // once more of the app is DIP-aware.
13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!IsInHighDPIMode()) {
1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DCHECK_EQ(GetSystemMetrics(SM_CXSCREEN), display.size().width());
1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DCHECK_EQ(GetSystemMetrics(SM_CYSCREEN), display.size().height());
1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return display;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ScreenWin::AddObserver(DisplayObserver* observer) {
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(oshima): crbug.com/122863.
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ScreenWin::RemoveObserver(DisplayObserver* observer) {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(oshima): crbug.com/122863.
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HWND ScreenWin::GetHWNDFromNativeView(NativeView window) const {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return window;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // USE_AURA
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeWindow ScreenWin::GetNativeWindowFromHWND(HWND hwnd) const {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return hwnd;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // USE_AURA
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(USE_AURA)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Screen* CreateNativeScreen() {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ScreenWin;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !USE_AURA
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
172