From 20ac714bf880ab7e3762428c7154d1c81b5188ba Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Wed, 17 Jul 2019 19:00:33 -0400
Subject: fixed bad compare for nahimic log displays on startup
---
src/shared/util.cpp | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 223 insertions(+)
(limited to 'src/shared/util.cpp')
diff --git a/src/shared/util.cpp b/src/shared/util.cpp
index eacd1f88..8c4a3f17 100644
--- a/src/shared/util.cpp
+++ b/src/shared/util.cpp
@@ -39,6 +39,7 @@ along with Mod Organizer. If not, see .
#include
#include
#include
+#include
#pragma comment(lib, "Wbemuuid.lib")
@@ -864,6 +865,196 @@ private:
};
+class DisplayEnumerator
+{
+public:
+ DisplayEnumerator()
+ : m_GetDpiForMonitor(nullptr)
+ {
+ m_shcore.reset(LoadLibraryW(L"Shcore.dll"));
+
+ if (m_shcore) {
+ // windows 8.1+ only
+ m_GetDpiForMonitor = reinterpret_cast(
+ GetProcAddress(m_shcore.get(), "GetDpiForMonitor"));
+ }
+
+ // gets all monitors and the device they're running on
+ getDisplayDevices();
+ }
+
+ std::vector&& displays() &&
+ {
+ return std::move(m_displays);
+ }
+
+ const std::vector& displays() const &
+ {
+ return m_displays;
+ }
+
+private:
+ using GetDpiForMonitorFunction =
+ HRESULT WINAPI (HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*);
+
+ std::unique_ptr m_shcore;
+ GetDpiForMonitorFunction* m_GetDpiForMonitor;
+ std::vector m_displays;
+
+ void getDisplayDevices()
+ {
+ // don't bother if it goes over 100
+ for (int i=0; i<100; ++i) {
+ DISPLAY_DEVICEW device = {};
+ device.cb = sizeof(device);
+
+ if (!EnumDisplayDevicesW(nullptr, i, &device, 0)) {
+ // no more
+ break;
+ }
+
+ // EnumDisplayDevices() seems to be returning a lot of devices that are
+ // not actually monitors, but those don't have the
+ // DISPLAY_DEVICE_ATTACHED_TO_DESKTOP bit set
+ if ((device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) == 0) {
+ continue;
+ }
+
+ m_displays.push_back(createDisplay(device));
+ }
+ }
+
+ Metrics::Display createDisplay(const DISPLAY_DEVICEW& device)
+ {
+ Metrics::Display d;
+
+ d.adapter = QString::fromWCharArray(device.DeviceString);
+ d.monitor = QString::fromWCharArray(device.DeviceName);
+ d.primary = (device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE);
+
+ getDisplaySettings(device.DeviceName, d);
+ getDpi(d);
+
+ return d;
+ }
+
+ void getDisplaySettings(const wchar_t* monitorName, Metrics::Display& d)
+ {
+ DEVMODEW dm = {};
+ dm.dmSize = sizeof(dm);
+
+ if (!EnumDisplaySettingsW(monitorName, ENUM_CURRENT_SETTINGS, &dm)) {
+ log::error("EnumDisplaySettings() failed for '{}'", d.monitor);
+ return;
+ }
+
+ // all these fields should be available
+
+ if (dm.dmFields & DM_DISPLAYFREQUENCY) {
+ d.refreshRate = dm.dmDisplayFrequency;
+ }
+
+ if (dm.dmFields & DM_PELSWIDTH) {
+ d.resX = dm.dmPelsWidth;
+ }
+
+ if (dm.dmFields & DM_PELSHEIGHT) {
+ d.resY = dm.dmPelsHeight;
+ }
+ }
+
+ void getDpi(Metrics::Display& d)
+ {
+ if (!m_GetDpiForMonitor) {
+ // this happens on windows 7, get the desktop dpi instead
+ getDesktopDpi(d);
+ return;
+ }
+
+ // there's no way to get an HMONITOR from a device name, so all monitors
+ // will have to be enumerated and their name checked
+ HMONITOR hm = findMonitor(d.monitor);
+ if (!hm) {
+ log::error("can't get dpi for monitor '{}', not found", d.monitor);
+ return;
+ }
+
+ UINT dpiX=0, dpiY=0;
+ const auto r = m_GetDpiForMonitor(hm, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
+
+ if (FAILED(r)) {
+ log::error(
+ "GetDpiForMonitor() failed for '{}', {}",
+ d.monitor, formatSystemMessageQ(r));
+
+ return;
+ }
+
+ // dpiX and dpiY are always identical, as per the documentation
+ d.dpi = dpiX;
+ }
+
+ void getDesktopDpi(Metrics::Display& d)
+ {
+ // desktop dc
+ HDC dc = GetDC(0);
+
+ if (!dc) {
+ const auto e = GetLastError();
+ log::error("can't get desktop DC, {}", formatSystemMessageQ(e));
+ return;
+ }
+
+ d.dpi = GetDeviceCaps(dc, LOGPIXELSX);
+
+ ReleaseDC(0, dc);
+ }
+
+ HMONITOR findMonitor(const QString& name)
+ {
+ // passed to the enumeration callback
+ struct Data
+ {
+ DisplayEnumerator* self;
+ QString name;
+ HMONITOR hm;
+ };
+
+ Data data = {this, name, 0};
+
+ // for each monitor
+ EnumDisplayMonitors(0, nullptr, [](HMONITOR hm, HDC, RECT*, LPARAM lp) {
+ auto& data = *reinterpret_cast(lp);
+
+ MONITORINFOEX mi = {};
+ mi.cbSize = sizeof(mi);
+
+ // monitor info will include the name
+ if (!GetMonitorInfoW(hm, &mi)) {
+ const auto e = GetLastError();
+ log::error(
+ "GetMonitorInfo() failed for '{}', {}",
+ data.name, formatSystemMessageQ(e));
+
+ // error for this monitor, but continue
+ return TRUE;
+ }
+
+ if (QString::fromWCharArray(mi.szDevice) == data.name) {
+ // found, stop
+ data.hm = hm;
+ return FALSE;
+ }
+
+ // not found, continue to the next monitor
+ return TRUE;
+ }, reinterpret_cast(&data));
+
+ return data.hm;
+ }
+};
+
+
Environment::Environment()
{
m_modules = getLoadedModules();
@@ -885,6 +1076,11 @@ const std::vector& Environment::securityProducts() const
return m_security;
}
+const Metrics& Environment::metrics() const
+{
+ return m_metrics;
+}
+
void Environment::dump() const
{
log::debug("windows: {}", windowsInfo().toString());
@@ -902,6 +1098,11 @@ void Environment::dump() const
for (const auto& m : loadedModules()) {
log::debug(" . {}", m.toString());
}
+
+ log::debug("displays:");
+ for (const auto& d : m_metrics.displays()) {
+ log::debug(" . {}", d.toString());
+ }
}
std::vector Environment::getLoadedModules() const
@@ -1137,6 +1338,28 @@ std::optional Environment::getWindowsFirewall() const
}
+Metrics::Metrics()
+{
+ m_displays = DisplayEnumerator().displays();
+}
+
+const std::vector& Metrics::displays() const
+{
+ return m_displays;
+}
+
+QString Metrics::Display::toString() const
+{
+ return QString("%1*%2 %3hz dpi=%4 on %5%6")
+ .arg(resX)
+ .arg(resY)
+ .arg(refreshRate)
+ .arg(dpi)
+ .arg(adapter)
+ .arg(primary ? " (primary)" : "");
+}
+
+
Module::Module(QString path, std::size_t fileSize)
: m_path(std::move(path)), m_fileSize(fileSize)
{
--
cgit v1.3.1