Home | History | Annotate | Download | only in gfx
      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 
     16 namespace {
     17 
     18 MONITORINFOEX 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 
     26 gfx::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 
     36 BOOL 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 
     52 namespace gfx {
     53 
     54 ScreenWin::ScreenWin() {
     55 }
     56 
     57 ScreenWin::~ScreenWin() {
     58 }
     59 
     60 bool ScreenWin::IsDIPEnabled() {
     61   return IsInHighDPIMode();
     62 }
     63 
     64 gfx::Point ScreenWin::GetCursorScreenPoint() {
     65   POINT pt;
     66   GetCursorPos(&pt);
     67   return gfx::Point(pt);
     68 }
     69 
     70 gfx::NativeWindow ScreenWin::GetWindowUnderCursor() {
     71   POINT cursor_loc;
     72   HWND hwnd = GetCursorPos(&cursor_loc) ? WindowFromPoint(cursor_loc) : NULL;
     73   return GetNativeWindowFromHWND(hwnd);
     74 }
     75 
     76 gfx::NativeWindow ScreenWin::GetWindowAtScreenPoint(const gfx::Point& point) {
     77   return GetNativeWindowFromHWND(WindowFromPoint(point.ToPOINT()));
     78 }
     79 
     80 int ScreenWin::GetNumDisplays() const {
     81   return GetSystemMetrics(SM_CMONITORS);
     82 }
     83 
     84 std::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 
     91 gfx::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 
    107 gfx::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 
    119 gfx::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 
    126 gfx::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 
    139 void ScreenWin::AddObserver(DisplayObserver* observer) {
    140   // TODO(oshima): crbug.com/122863.
    141 }
    142 
    143 void ScreenWin::RemoveObserver(DisplayObserver* observer) {
    144   // TODO(oshima): crbug.com/122863.
    145 }
    146 
    147 HWND 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 
    156 NativeWindow 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)
    166 Screen* CreateNativeScreen() {
    167   return new ScreenWin;
    168 }
    169 #endif  // !USE_AURA
    170 
    171 }  // namespace gfx
    172