/ src / common / Display / monitors.cpp
monitors.cpp
  1  #include "monitors.h"
  2  
  3  #include <algorithm>
  4  
  5  Box MonitorInfo::GetScreenSize(const bool includeNonWorkingArea) const
  6  {
  7      return includeNonWorkingArea ? Box{ info.rcMonitor } : Box{ info.rcWork };
  8  }
  9  
 10  bool MonitorInfo::IsPrimary() const
 11  {
 12      return static_cast<bool>(info.dwFlags & MONITORINFOF_PRIMARY);
 13  }
 14  
 15  MonitorInfo::MonitorInfo(HMONITOR h) :
 16      handle{ h }
 17  {
 18      info.cbSize = sizeof(MONITORINFOEX);
 19      GetMonitorInfoW(handle, &info);
 20  }
 21  
 22  static BOOL CALLBACK GetDisplaysEnumCb(HMONITOR monitor, HDC /*hdc*/, LPRECT /*rect*/, LPARAM data)
 23  {
 24      auto* monitors = reinterpret_cast<std::vector<MonitorInfo>*>(data);
 25      monitors->emplace_back(monitor);
 26      return true;
 27  };
 28  
 29  std::vector<MonitorInfo> MonitorInfo::GetMonitors(bool includeNonWorkingArea)
 30  {
 31      std::vector<MonitorInfo> monitors;
 32      EnumDisplayMonitors(nullptr, nullptr, GetDisplaysEnumCb, reinterpret_cast<LPARAM>(&monitors));
 33      std::sort(begin(monitors), end(monitors), [=](const MonitorInfo& lhs, const MonitorInfo& rhs) {
 34          const auto lhsSize = lhs.GetScreenSize(includeNonWorkingArea);
 35          const auto rhsSize = rhs.GetScreenSize(includeNonWorkingArea);
 36  
 37          return lhsSize < rhsSize;
 38      });
 39      return monitors;
 40  }
 41  
 42  MonitorInfo MonitorInfo::GetPrimaryMonitor()
 43  {
 44      auto monitors = MonitorInfo::GetMonitors(false);
 45      if (monitors.size() > 1)
 46      {
 47          for (auto monitor : monitors)
 48          {
 49              if (monitor.IsPrimary())
 50                  return monitor;
 51          }
 52      }
 53      return monitors[0];
 54  }
 55  
 56  MonitorInfo MonitorInfo::GetFromWindow(const HWND window)
 57  {
 58      auto monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
 59      return MonitorInfo::MonitorInfo(monitor);
 60  }
 61  
 62  MonitorInfo MonitorInfo::GetFromPoint(int32_t x, int32_t y)
 63  {
 64      auto monitor = MonitorFromPoint(POINT{ x, y }, MONITOR_DEFAULTTONULL);
 65      return MonitorInfo::MonitorInfo(monitor);
 66  }
 67  
 68  MonitorInfo::Size MonitorInfo::GetSize(const MONITORINFOEX& monitorInfoEx)
 69  {
 70      Size size = {};
 71  
 72      auto device_name = PCTSTR(monitorInfoEx.szDevice);
 73  
 74      auto hdc = CreateDC(device_name, nullptr, nullptr, nullptr);
 75      size.width_mm = static_cast<float>(GetDeviceCaps(hdc, HORZSIZE));
 76      size.height_mm = static_cast<float>(GetDeviceCaps(hdc, VERTSIZE));
 77      if (hdc != nullptr)
 78      {
 79          ReleaseDC(nullptr, hdc);
 80      }
 81  
 82      auto monitor = &monitorInfoEx.rcMonitor;
 83      size.width_logical = static_cast<uint32_t>(monitor->right - monitor->left);
 84      size.height_logical = static_cast<uint32_t>(monitor->bottom - monitor->top);
 85  
 86      DEVMODE dev_mode = { .dmSize = sizeof DEVMODE };
 87      if (EnumDisplaySettingsEx(device_name, ENUM_CURRENT_SETTINGS, &dev_mode, EDS_RAWMODE))
 88      {
 89          size.width_physical = dev_mode.dmPelsWidth;
 90          size.height_physical = dev_mode.dmPelsHeight;
 91      }
 92  
 93      return size;
 94  }
 95  
 96  MonitorInfo::Size MonitorInfo::GetSize() const
 97  {
 98      if (this->handle)
 99      {
100          return MonitorInfo::GetSize(this->info);
101      }
102      else
103      {
104          return MonitorInfo::Size{};
105      }
106  }