From b52c89c93353d1c9b7a596f2c379f92399bd61c8 Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Sat, 13 Nov 2021 14:12:19 +0100 Subject: [PATCH] Fix mixed scaling issues (again) Now we no longer trust Qt and use the data we get from the Windows api directly. Move monitor query function into util to be used later in the main app, because we also must user the correct values there. --- ScreenPlayUtil/CMakeLists.txt | 5 ++ .../inc/public/ScreenPlayUtil/util.h | 42 ++++++++++++++++ ScreenPlayWallpaper/CMakeLists.txt | 1 - ScreenPlayWallpaper/src/winwindow.cpp | 48 ++----------------- 4 files changed, 52 insertions(+), 44 deletions(-) diff --git a/ScreenPlayUtil/CMakeLists.txt b/ScreenPlayUtil/CMakeLists.txt index a2f171b9..3047e2dc 100644 --- a/ScreenPlayUtil/CMakeLists.txt +++ b/ScreenPlayUtil/CMakeLists.txt @@ -26,3 +26,8 @@ target_include_directories( PRIVATE src/) target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core) + +if(WIN32) + # Used for query windows monitor data + target_link_libraries(${PROJECT_NAME} PUBLIC shcore.lib) +endif() diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/util.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/util.h index 11396b85..6005a462 100644 --- a/ScreenPlayUtil/inc/public/ScreenPlayUtil/util.h +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/util.h @@ -33,6 +33,17 @@ ****************************************************************************/ #pragma once + +#include + +#if defined(Q_OS_WIN) +// Must be first! +#include + +#include "WinUser.h" +#include +#endif + #include "ScreenPlayUtil/contenttypes.h" #include #include @@ -41,6 +52,37 @@ #include namespace ScreenPlayUtil { +#if defined(Q_OS_WIN) +struct WinMonitorStats { + std::vector iMonitors; + std::vector hMonitors; + std::vector hdcMonitors; + std::vector rcMonitors; + std::vector scaleFactor; + std::vector> sizes; + + static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, + LPARAM pData) + { + WinMonitorStats* pThis = reinterpret_cast(pData); + auto scaleFactor = DEVICE_SCALE_FACTOR::DEVICE_SCALE_FACTOR_INVALID; + GetScaleFactorForMonitor(hMon, &scaleFactor); + + UINT x = 0; + UINT y = 0; + GetDpiForMonitor(hMon, MONITOR_DPI_TYPE::MDT_RAW_DPI, &x, &y); + pThis->sizes.push_back({ x, y }); + pThis->scaleFactor.push_back(scaleFactor); + pThis->hMonitors.push_back(hMon); + pThis->hdcMonitors.push_back(hdc); + pThis->rcMonitors.push_back(*lprcMonitor); + pThis->iMonitors.push_back(pThis->hdcMonitors.size()); + return TRUE; + } + + WinMonitorStats() { EnumDisplayMonitors(0, 0, MonitorEnum, (LPARAM)this); } +}; +#endif QJsonArray fillArray(const QVector& items); ScreenPlay::SearchType::SearchType getSearchTypeFromInstalledType(const ScreenPlay::InstalledType::InstalledType type); std::optional getInstalledTypeFromString(const QString& type); diff --git a/ScreenPlayWallpaper/CMakeLists.txt b/ScreenPlayWallpaper/CMakeLists.txt index 3d7a1dc0..7850cee2 100644 --- a/ScreenPlayWallpaper/CMakeLists.txt +++ b/ScreenPlayWallpaper/CMakeLists.txt @@ -83,6 +83,5 @@ if(WIN32) # Disable console window on Windows # https://stackoverflow.com/questions/8249028/how-do-i-keep-my-qt-c-program-from-opening-a-console-in-windows set_property(TARGET ${PROJECT_NAME} PROPERTY WIN32_EXECUTABLE true) - target_link_libraries(${PROJECT_NAME} PRIVATE shcore.lib) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/index.html ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/index.html COPYONLY) endif() diff --git a/ScreenPlayWallpaper/src/winwindow.cpp b/ScreenPlayWallpaper/src/winwindow.cpp index a2ec08b5..6fbdd6ca 100644 --- a/ScreenPlayWallpaper/src/winwindow.cpp +++ b/ScreenPlayWallpaper/src/winwindow.cpp @@ -1,41 +1,8 @@ #include "winwindow.h" -#include "WinUser.h" #include "qqml.h" -#include #include #include #include -#include - -struct WinMonitorStats { - std::vector iMonitors; - std::vector hMonitors; - std::vector hdcMonitors; - std::vector rcMonitors; - std::vector scaleFactor; - std::vector> sizes; - - static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, - LPARAM pData) - { - WinMonitorStats* pThis = reinterpret_cast(pData); - auto scaleFactor = DEVICE_SCALE_FACTOR::DEVICE_SCALE_FACTOR_INVALID; - GetScaleFactorForMonitor(hMon, &scaleFactor); - - UINT x = 0; - UINT y = 0; - GetDpiForMonitor(hMon, MONITOR_DPI_TYPE::MDT_RAW_DPI, &x, &y); - pThis->sizes.push_back({ x, y }); - pThis->scaleFactor.push_back(scaleFactor); - pThis->hMonitors.push_back(hMon); - pThis->hdcMonitors.push_back(hdc); - pThis->rcMonitors.push_back(*lprcMonitor); - pThis->iMonitors.push_back(pThis->hdcMonitors.size()); - return TRUE; - } - - WinMonitorStats() { EnumDisplayMonitors(0, 0, MonitorEnum, (LPARAM)this); } -}; /*! \brief Searches for the worker window for our window to parent to. @@ -225,11 +192,6 @@ WinWindow::WinWindow( configureWindowGeometry(); - if (hasWindowScaling()) { - qInfo() << "Monitor with scaling detected!"; - configureWindowGeometry(); - } - // We do not support autopause for multi monitor wallpaper if (this->activeScreensList().length() == 1) { if (checkWallpaperVisible) { @@ -294,13 +256,13 @@ void WinWindow::setupWallpaperForOneScreen(int activeScreen) const QRect screenRect = QApplication::screens().at(activeScreen)->geometry(); const int boderWidth = 2; const float scaling = getScaling(activeScreen); - const auto width = screenRect.width() * scaling + boderWidth; - const auto height = screenRect.height() * scaling + boderWidth; - const int borderOffset = -1; - const int x = screenRect.x() + m_zeroPoint.x() + borderOffset; - const int y = screenRect.y() + m_zeroPoint.y() + borderOffset; + ScreenPlayUtil::WinMonitorStats Monitors; + const int width = std::abs(Monitors.rcMonitors[activeScreen].right - Monitors.rcMonitors[activeScreen].left); + const int height = std::abs(Monitors.rcMonitors[activeScreen].top - Monitors.rcMonitors[activeScreen].bottom); + const int x = Monitors.rcMonitors[activeScreen].left + m_zeroPoint.x() + borderOffset; + const int y = Monitors.rcMonitors[activeScreen].top + m_zeroPoint.y() + borderOffset; qInfo() << QString("Setup window activeScreen: %1 scaling: %2 x: %3 y: %4 width: %5 height: %6").arg(activeScreen).arg(scaling).arg(x).arg(y).arg(width).arg(height); {