diff --git a/CMakeLists.txt b/CMakeLists.txt index 78fbea2c..3252405c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,7 +45,6 @@ list(APPEND CMAKE_MODULE_PATH "${THIRD_PARTY_PATH}/ecm/find-modules") list(APPEND CMAKE_MODULE_PATH "${THIRD_PARTY_PATH}/ecm/kde-modules") message(STATUS "[PROJECT] CMAKE_MODULE_PATH = ${CMAKE_MODULE_PATH}") - option(OSX_BUNDLE "Enable distribution macOS bundle" OFF) set(CMAKE_OSX_DEPLOYMENT_TARGET "13.0") @@ -74,7 +73,7 @@ set(VCPKG_BIN_PATH "${VCPKG_INSTALLED_PATH}/bin") option(SCREENPLAY_STEAM "For FOSS distribution so we do not bundle proprietary code." ON) option(SCREENPLAY_DEPLOY "Marks this version as an official deploy version. This version uses different import paths and other settings." - OFF) + OFF) option(SCREENPLAY_TESTS "Enables UI tests." ON) option(SCREENPLAY_INSTALLER "Indicates whether an installer via the Qt Installer Framework is created." OFF) option(SCREENPLAY_GODOT_SUPPORT "Compiles ScreenPlayGodotWallpaper." ON) @@ -103,14 +102,12 @@ else() set(DATE_ARG "") endif() - if(UNIX AND NOT APPLE) # Fixes QWebEngine linker errors on Ubuntu 22.04 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold") endif() - execute_process( COMMAND ${DATE_COMMAND} ${DATE_ARG} WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" @@ -138,10 +135,10 @@ add_subdirectory(ThirdParty) set(ECM_DIR "${THIRD_PARTY_PATH}/ecm") add_subdirectory(CMake) if(UNIX AND NOT APPLE) - # Needs to be append, because we include ecm as third party on linux - list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake") - list(APPEND CMAKE_MODULE_PATH "${ECM_DIR}") - list(APPEND CMAKE_MODULE_PATH "${ECM_DIR}/cmake") + # Needs to be append, because we include ecm as third party on linux + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake") + list(APPEND CMAKE_MODULE_PATH "${ECM_DIR}") + list(APPEND CMAKE_MODULE_PATH "${ECM_DIR}/cmake") else() endif() diff --git a/ScreenPlay/inc/public/ScreenPlay/app.h b/ScreenPlay/inc/public/ScreenPlay/app.h index efec6970..cefca236 100644 --- a/ScreenPlay/inc/public/ScreenPlay/app.h +++ b/ScreenPlay/inc/public/ScreenPlay/app.h @@ -101,7 +101,6 @@ public slots: void setMainWindowEngine(QQmlApplicationEngine* mainWindowEngine); void setWizards(Wizards* wizards); - private: QNetworkAccessManager m_networkAccessManager; std::unique_ptr m_mainWindowEngine; diff --git a/ScreenPlay/inc/public/ScreenPlay/screenplaymanager.h b/ScreenPlay/inc/public/ScreenPlay/screenplaymanager.h index 00fbc390..7c15c7de 100644 --- a/ScreenPlay/inc/public/ScreenPlay/screenplaymanager.h +++ b/ScreenPlay/inc/public/ScreenPlay/screenplaymanager.h @@ -40,7 +40,6 @@ public: int activeWidgetsCounter() const { return m_activeWidgetsCounter; } bool isAnotherScreenPlayInstanceRunning() { return m_isAnotherScreenPlayInstanceRunning; } - signals: void activeWallpaperCounterChanged(int activeWallpaperCounter); void activeWidgetsCounterChanged(int activeWidgetsCounter); diff --git a/ScreenPlay/main.cpp b/ScreenPlay/main.cpp index 2165dfef..7194dac4 100644 --- a/ScreenPlay/main.cpp +++ b/ScreenPlay/main.cpp @@ -1,11 +1,11 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only #include "ScreenPlay/app.h" +#include "ScreenPlayUtil/logginghandler.h" #include #include #include #include -#include "ScreenPlayUtil/logginghandler.h" #if defined(Q_OS_WIN) #include diff --git a/ScreenPlay/qml/Settings/Settings.qml b/ScreenPlay/qml/Settings/Settings.qml index 1643655b..b84dd0a8 100644 --- a/ScreenPlay/qml/Settings/Settings.qml +++ b/ScreenPlay/qml/Settings/Settings.qml @@ -483,8 +483,8 @@ Item { description: qsTr("If your ScreenPlay missbehaves this is a good way to look for answers. This shows all logs and warning during runtime.") buttonText: qsTr("Show Logs") onButtonPressed: { - const logsPath = StandardPaths.writableLocation(StandardPaths.GenericDataLocation) + "/ScreenPlay/Logs" - App.util.openFolderInExplorer(logsPath) + const logsPath = StandardPaths.writableLocation(StandardPaths.GenericDataLocation) + "/ScreenPlay/Logs"; + App.util.openFolderInExplorer(logsPath); } } diff --git a/ScreenPlay/src/sdkconnection.cpp b/ScreenPlay/src/sdkconnection.cpp index b022aab6..b2009aa9 100644 --- a/ScreenPlay/src/sdkconnection.cpp +++ b/ScreenPlay/src/sdkconnection.cpp @@ -39,7 +39,7 @@ void ScreenPlay::SDKConnection::readyRead() { // Split all messages by semicolon. This fixes double messages like pingping // when we get messages to fast - const QString read = QString(m_socket->readAll()); + const QString read = QString(m_socket->readAll()); const QStringList messages = read.split(";"); for (const QString& msg : messages) { if (msg == "ping") { diff --git a/ScreenPlay/src/util.cpp b/ScreenPlay/src/util.cpp index 2e2ef32f..669a91d6 100644 --- a/ScreenPlay/src/util.cpp +++ b/ScreenPlay/src/util.cpp @@ -255,7 +255,6 @@ bool Util::fileExists(const QString& filePath) const return file.isFile(); } - /*! \brief Takes ownership of \a obj and \a name. Tries to save into a text file with of name. diff --git a/ScreenPlayUtil/CMakeLists.txt b/ScreenPlayUtil/CMakeLists.txt index 81a38f79..4c02679b 100644 --- a/ScreenPlayUtil/CMakeLists.txt +++ b/ScreenPlayUtil/CMakeLists.txt @@ -55,11 +55,11 @@ set(HEADER inc/public/ScreenPlayUtil/HelpersCommon.h inc/public/ScreenPlayUtil/httpfileserver.h inc/public/ScreenPlayUtil/ListPropertyHelper.h + inc/public/ScreenPlayUtil/logginghandler.h inc/public/ScreenPlayUtil/projectfile.h inc/public/ScreenPlayUtil/PropertyHelpers.h inc/public/ScreenPlayUtil/PtrPropertyHelpers.h inc/public/ScreenPlayUtil/SingletonHelper.h - inc/public/ScreenPlayUtil/logginghandler.h inc/public/ScreenPlayUtil/util.h) if(APPLE) @@ -98,7 +98,10 @@ target_include_directories( ${PROJECT_NAME} PUBLIC inc/public/ PRIVATE src/) -target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Quick PUBLIC fmt::fmt-header-only ScreenPlaySysInfo) +target_link_libraries( + ${PROJECT_NAME} + PRIVATE Qt6::Core Qt6::Quick + PUBLIC fmt::fmt-header-only) if(WIN32) # Used for query windows monitor data diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/util.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/util.h index fcc04827..db263f83 100644 --- a/ScreenPlayUtil/inc/public/ScreenPlayUtil/util.h +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/util.h @@ -3,13 +3,13 @@ #pragma once #include "ScreenPlayUtil/contenttypes.h" -#include #include #include #include #include #include #include +#include #include namespace ScreenPlayUtil { diff --git a/ScreenPlayUtil/src/logginghandler.cpp b/ScreenPlayUtil/src/logginghandler.cpp index afa1a287..bac574cf 100644 --- a/ScreenPlayUtil/src/logginghandler.cpp +++ b/ScreenPlayUtil/src/logginghandler.cpp @@ -1,5 +1,4 @@ #include "ScreenPlayUtil/logginghandler.h" -#include "sysinfo.h" #include #include #include @@ -9,10 +8,15 @@ #include #include +#ifdef Q_OS_WINDOWS +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#endif /*! \class ScreenPlayUtil::LoggingHandler - \inmodule core \brief The LoggingHandler class writes logs to the console and a log file. */ @@ -48,7 +52,6 @@ void LoggingHandler::start() { Q_ASSERT(!m_logFileName.isEmpty()); - // Use hardcoded path for now because QStandardpaths gives us: 'C:/ProgramData/K3000' QDir directory; QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); directory = QDir(cacheDir + "/ScreenPlay/Logs"); @@ -78,29 +81,6 @@ void LoggingHandler::start() return; } - - SysInfo sysInfo; - QTextStream stream(&logFile()); - stream << "Start ScreenPlay logging " << QDateTime::currentDateTime().toString("dd.MM.yyyy-hh:mm:ss.zzz") << "\n"; - stream << "version: 1.0\n"; - stream << "buildAbi: " << QSysInfo::buildAbi() << "\n"; - stream << "buildCpuArchitecture: " << QSysInfo::buildCpuArchitecture() << "\n"; - stream << "currentCpuArchitecture: " << QSysInfo::currentCpuArchitecture() << "\n"; - stream << "kernelType: " << QSysInfo::kernelType() << "\n"; - stream << "kernelVersion: " << QSysInfo::kernelVersion() << "\n"; - stream << "machineHostName: " << QSysInfo::machineHostName() << "\n"; - stream << "machineUniqueId: " << QSysInfo::machineUniqueId() << "\n"; - stream << "prettyProductName: " << QSysInfo::prettyProductName() << "\n"; - stream << "productType: " << QSysInfo::productType() << "\n"; - stream << "productVersion: " << QSysInfo::productVersion() << "\n"; - stream << "GPU Name: " << sysInfo.gpu()->name() << "\n"; - stream << "GPU Vendor: " << sysInfo.gpu()->vendor() << "\n"; - stream << "GPU ramSize: " << QString::number(sysInfo.gpu()->ramSize()) << "\n"; - stream << "GPU cacheSize: " << QString::number(sysInfo.gpu()->cacheSize()) << "\n"; - stream << "GPU maxFrequency: " << QString::number(sysInfo.gpu()->maxFrequency()) << "\n"; - stream << QString("Uptime: %1 days %2 hours %3 minutes %4 seconds").arg(sysInfo.uptime()->days()).arg(sysInfo.uptime()->hours()).arg(sysInfo.uptime()->minutes()).arg(sysInfo.uptime()->seconds()) << "\n"; - - const auto now = QLocale().toString(QDateTime::currentDateTime(), QLocale::FormatType::ShortFormat); const auto message = QString { "[%1] Start logging\n" }.arg(now); logFile().write(message.toStdString().c_str()); diff --git a/ScreenPlayWallpaper/CMakeLists.txt b/ScreenPlayWallpaper/CMakeLists.txt index 038384be..bd2449a6 100644 --- a/ScreenPlayWallpaper/CMakeLists.txt +++ b/ScreenPlayWallpaper/CMakeLists.txt @@ -7,18 +7,17 @@ set(CMAKE_AUTOMOC ON) find_package( Qt6 - COMPONENTS - Core - Quick - Gui - Widgets - WebSockets - Svg - Multimedia - WebEngineCore - WebEngineQuick - WebChannel - Positioning) + COMPONENTS Core + Quick + Gui + Widgets + WebSockets + Svg + Multimedia + WebEngineCore + WebEngineQuick + WebChannel + Positioning) if(WIN32) set(SOURCES src/windowsdesktopproperties.cpp src/winwindow.cpp) @@ -55,25 +54,18 @@ set(LIB_HEADER) if(WIN32) set(LIB_SOURCES src/windowsintegration.cpp) set(LIB_HEADER src/windowsintegration.h) -elseif(APPLE) - set(LIB_SOURCES src/macintegration.cpp) - set(LIB_HEADER src/macintegration.h) -elseif(UNIX) - #set(LIB_SOURCES src/waylandintegration.cpp) - #set(LIB_HEADER src/waylandintegration.h) -endif() - -add_library(ScreenPlayWallpaperLib STATIC ${LIB_SOURCES} ${LIB_HEADER}) -target_include_directories(ScreenPlayWallpaperLib PUBLIC src) - -if(WIN32) + add_library(ScreenPlayWallpaperLib STATIC ${LIB_SOURCES} ${LIB_HEADER}) + target_include_directories(ScreenPlayWallpaperLib PUBLIC src) # Used for query windows monitor data target_link_libraries(ScreenPlayWallpaperLib PUBLIC shcore.lib) endif() - -add_executable(${PROJECT_NAME} ${SOURCES} ${HEADER} - src/windowsintegration.h src/windowsintegration.cpp) +add_executable( + ${PROJECT_NAME} + ${SOURCES} + ${HEADER} + src/windowsintegration.h + src/windowsintegration.cpp) qt_add_qml_module( ${PROJECT_NAME} @@ -92,34 +84,34 @@ qt_add_qml_module( target_link_libraries( ${PROJECT_NAME} - PRIVATE - ScreenPlaySDK - ScreenPlayWallpaperLib - ScreenPlayUtil - ScreenPlayWeatherplugin - Qt6::Quick - Qt6::Gui - Qt6::Widgets - Qt6::Core - Qt6::WebSockets - Qt6::Svg - Qt6::Multimedia - Qt6::WebEngineCore - Qt6::WebEngineQuick) + PRIVATE ScreenPlaySDK + ScreenPlayUtil + ScreenPlayWeatherplugin + Qt6::Quick + Qt6::Gui + Qt6::Widgets + Qt6::Core + Qt6::WebSockets + Qt6::Svg + Qt6::Multimedia + Qt6::WebEngineCore + Qt6::WebEngineQuick) if(WIN32) - target_link_libraries(${PROJECT_NAME} PRIVATE ScreenPlaySysInfoplugin) + target_link_libraries(${PROJECT_NAME} PRIVATE ScreenPlaySysInfoplugin ScreenPlayWallpaperLib) elseif(UNIX AND NOT APPLE) target_link_libraries(${PROJECT_NAME} PRIVATE X11) endif() if(UNIX AND NOT APPLE) - find_package(ECM CONFIG REQUIRED NO_MODULE) + find_package( + ECM + CONFIG + REQUIRED + NO_MODULE) set(LayerShellQt "${CMAKE_CURRENT_SOURCE_DIR}/../ThirdParty/layer-shell-qt/") find_package(LayerShellQt REQUIRED) - target_link_libraries( - ${PROJECT_NAME} - PRIVATE LayerShellQtInterface) + target_link_libraries(${PROJECT_NAME} PRIVATE LayerShellQtInterface) endif() if(APPLE) @@ -130,7 +122,7 @@ if(APPLE) TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/index.html - ${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/) + ${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/) set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/") endif() endif() diff --git a/ScreenPlayWallpaper/Godot/CMakeLists.txt b/ScreenPlayWallpaper/Godot/CMakeLists.txt index 996b9450..05fbbca5 100644 --- a/ScreenPlayWallpaper/Godot/CMakeLists.txt +++ b/ScreenPlayWallpaper/Godot/CMakeLists.txt @@ -2,4 +2,4 @@ if(WIN32) add_subdirectory(GDExtention) -endif() \ No newline at end of file +endif() diff --git a/ScreenPlayWallpaper/Godot/GDExtention/CMakeLists.txt b/ScreenPlayWallpaper/Godot/GDExtention/CMakeLists.txt index cd3421e3..60ea81de 100644 --- a/ScreenPlayWallpaper/Godot/GDExtention/CMakeLists.txt +++ b/ScreenPlayWallpaper/Godot/GDExtention/CMakeLists.txt @@ -20,37 +20,31 @@ set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON) # Output compile commands to compile_commands.json (for debugging CMake issues) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -# Build universal lib on macOS -# Note that CMAKE_OSX_ARCHITECTURES must be set before project(). +# Build universal lib on macOS Note that CMAKE_OSX_ARCHITECTURES must be set before project(). if(APPLE) - set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64" CACHE STRING "") + set(CMAKE_OSX_ARCHITECTURES + "x86_64;arm64" + CACHE STRING "") endif() # Main project information -project(ScreenPlayGodotWallpaper - LANGUAGES - CXX -) +project(ScreenPlayGodotWallpaper LANGUAGES CXX) # Create our library add_library(${PROJECT_NAME} SHARED) -target_compile_features(${PROJECT_NAME} - PRIVATE - cxx_std_17 -) +target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17) -# LIB_ARCH is the architecture being built. It is set to the build system's architecture. -# For macOS, we build a universal library (both arm64 and x86_64). +# LIB_ARCH is the architecture being built. It is set to the build system's architecture. For macOS, we build a universal library (both +# arm64 and x86_64). set(LIB_ARCH ${CMAKE_SYSTEM_PROCESSOR}) if(APPLE) set(LIB_ARCH "universal") endif() -# LIB_DIR is where the actual library ends up. This is used in both the build directory and the -# install directory and needs to be consistent with the paths in the gdextension file. -# e.g. linux.release.x86_64 = "lib/Linux-x86_64/libGDExtensionTemplate.so" +# LIB_DIR is where the actual library ends up. This is used in both the build directory and the install directory and needs to be consistent +# with the paths in the gdextension file. e.g. linux.release.x86_64 = "lib/Linux-x86_64/libGDExtensionTemplate.so" set(LIB_DIR "lib/${CMAKE_SYSTEM_NAME}-${LIB_ARCH}") message(STATUS "Building ${PROJECT_NAME} for ${LIB_ARCH} on ${CMAKE_SYSTEM_NAME}") @@ -60,19 +54,15 @@ set(BUILD_OUTPUT_DIR "${PROJECT_BINARY_DIR}/${PROJECT_NAME}/") set(OUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../ScreenPlayGodot/${PROJECT_NAME}/) # Compile directly into our Godot project -set_target_properties(${PROJECT_NAME} - PROPERTIES - CXX_VISIBILITY_PRESET hidden - VISIBILITY_INLINES_HIDDEN true - RUNTIME_OUTPUT_DIRECTORY "${OUT_PATH}/${LIB_DIR}" - LIBRARY_OUTPUT_DIRECTORY "${OUT_PATH}/${LIB_DIR}" -) +set_target_properties( + ${PROJECT_NAME} + PROPERTIES CXX_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN true + RUNTIME_OUTPUT_DIRECTORY "${OUT_PATH}/${LIB_DIR}" + LIBRARY_OUTPUT_DIRECTORY "${OUT_PATH}/${LIB_DIR}") if(NOT DEFINED CMAKE_DEBUG_POSTFIX) - set_target_properties(${PROJECT_NAME} - PROPERTIES - DEBUG_POSTFIX "-d" - ) + set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "-d") endif() # Warnings @@ -88,34 +78,27 @@ set(INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/") add_subdirectory(templates) -# ccache -# Turns on ccache if found +# ccache Turns on ccache if found include(ccache) -# Formatting -# Adds a custom target to format all the code at once +# Formatting Adds a custom target to format all the code at once include(ClangFormat) -# godot-cpp -# From here: https://github.com/godotengine/godot-cpp +# godot-cpp From here: https://github.com/godotengine/godot-cpp if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/extern/godot-cpp/Makefile") message( FATAL_ERROR - "[${PROJECT_NAME}] The godot-cpp submodule was not downloaded. Please update submodules: git submodule update --init --recursive." + "[${PROJECT_NAME}] The godot-cpp submodule was not downloaded. Please update submodules: git submodule update --init --recursive." ) endif() -set(GODOT_CPP_SYSTEM_HEADERS ON CACHE BOOL "" FORCE) +set(GODOT_CPP_SYSTEM_HEADERS + ON + CACHE BOOL "" FORCE) add_subdirectory(extern/godot-cpp) -set_target_properties(godot-cpp - PROPERTIES - CXX_VISIBILITY_PRESET hidden # visibility needs to be the same as the main library +set_target_properties(godot-cpp PROPERTIES CXX_VISIBILITY_PRESET hidden # visibility needs to be the same as the main library ) -target_link_libraries(${PROJECT_NAME} - PRIVATE - godot-cpp - ScreenPlayWallpaperLib -) +target_link_libraries(${PROJECT_NAME} PRIVATE godot-cpp ScreenPlayWallpaperLib) diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/CMakeLists.txt b/ScreenPlayWallpaper/Godot/GDExtention/src/CMakeLists.txt index b2480007..9c118279 100644 --- a/ScreenPlayWallpaper/Godot/GDExtention/src/CMakeLists.txt +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/CMakeLists.txt @@ -1,20 +1,16 @@ # SPDX-License-Identifier: Unlicense -target_sources(${PROJECT_NAME} - PRIVATE - ScreenPlayGodotWallpaper.h - ScreenPlayGodotWallpaper.cpp - WindowsPipe.h - WindowsPipe.cpp - RegisterExtension.cpp -) +target_sources( + ${PROJECT_NAME} + PRIVATE ScreenPlayGodotWallpaper.h + ScreenPlayGodotWallpaper.cpp + WindowsPipe.h + WindowsPipe.cpp + RegisterExtension.cpp) find_package(Catch2 CONFIG REQUIRED) -target_include_directories(${PROJECT_NAME} - PRIVATE - "src" -) +target_include_directories(${PROJECT_NAME} PRIVATE "src") # Test app. Start WindowsPipeTestServer.py! -add_executable(WindowsPipeTest WindowsPipeTest.cpp WindowsPipe.h WindowsPipe.cpp) +add_executable(WindowsPipeTest WindowsPipe.cpp WindowsPipe.h WindowsPipeTest.cpp) target_link_libraries(WindowsPipeTest PRIVATE Catch2::Catch2 Catch2::Catch2WithMain) -target_include_directories(WindowsPipeTest PRIVATE "src") \ No newline at end of file +target_include_directories(WindowsPipeTest PRIVATE "src") diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp index 530b3d48..ec60e8f2 100644 --- a/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp @@ -82,10 +82,10 @@ bool ScreenPlayGodotWallpaper::init(int activeScreen) ShowWindow(m_hook->windowHandle, SW_HIDE); WindowsIntegration windowsIntegration; - auto updateWindowSize = [this, &displayServer](const int width, const int height){ + auto updateWindowSize = [this, &displayServer](const int width, const int height) { displayServer->window_set_size(godot::Vector2((real_t)width, (real_t)height)); }; - std::optional monitor = windowsIntegration.setupWallpaperForOneScreen(activeScreen,m_hook->windowHandle,m_hook->windowHandleWorker,updateWindowSize); + std::optional monitor = windowsIntegration.setupWallpaperForOneScreen(activeScreen, m_hook->windowHandle, m_hook->windowHandleWorker, updateWindowSize); const std::string windowTitle = "ScreenPlayWallpaperGodot"; SetWindowText(hwnd, windowTitle.c_str()); diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.h b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.h index 1ba1f92c..fb834992 100644 --- a/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.h +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.h @@ -2,6 +2,10 @@ #pragma once +#ifndef NOMINMAX +#define NOMINMAX +#endif + #include "godot_cpp/classes/control.hpp" #include "godot_cpp/classes/global_constants.hpp" #include "godot_cpp/classes/timer.hpp" @@ -14,8 +18,8 @@ #include #include "ScreenPlayGodotWallpaper.h" -#include "windowsintegration.h" #include "WindowsPipe.h" +#include "windowsintegration.h" class ScreenPlayGodotWallpaper : public godot::Node { GDCLASS(ScreenPlayGodotWallpaper, Node) @@ -54,7 +58,6 @@ private: void hideFromTaskbar(HWND hwnd); private: - OVERLAPPED overlappedRead = {}; OVERLAPPED overlappedWrite = {}; diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipe.cpp b/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipe.cpp index 1668ec6a..731b4605 100644 --- a/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipe.cpp +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipe.cpp @@ -1,6 +1,7 @@ #include "WindowsPipe.h" -bool WindowsPipe::connectToPipe() { +bool WindowsPipe::connectToPipe() +{ if (m_pipeName.empty()) { std::cerr << "Pipe name not set." << std::endl; return false; @@ -25,7 +26,8 @@ bool WindowsPipe::connectToPipe() { return true; } -bool WindowsPipe::readFromPipe(std::string& outMessage) { +bool WindowsPipe::readFromPipe(std::string& outMessage) +{ char buffer[128]; DWORD bytesRead; @@ -52,8 +54,8 @@ bool WindowsPipe::readFromPipe(std::string& outMessage) { return true; } - -bool WindowsPipe::writeToPipe(const std::string& message) { +bool WindowsPipe::writeToPipe(const std::string& message) +{ DWORD bytesWritten; if (!WriteFile(m_hPipe, message.c_str(), static_cast(message.size()), &bytesWritten, &m_overlapped)) { diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipeTest.cpp b/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipeTest.cpp index f64231cf..bc388bfc 100644 --- a/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipeTest.cpp +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipeTest.cpp @@ -21,7 +21,7 @@ TEST_CASE("Test WindowsPipe with Python echo server", "[WindowsPipe]") std::string response; REQUIRE(client.readFromPipe(response)); REQUIRE(response == "pong;"); - std::cout << response <<"ok\n"; + std::cout << response << "ok\n"; } } } diff --git a/ScreenPlayWallpaper/Godot/GDExtention/templates/CMakeLists.txt b/ScreenPlayWallpaper/Godot/GDExtention/templates/CMakeLists.txt index e5cb7fcf..167530ea 100644 --- a/ScreenPlayWallpaper/Godot/GDExtention/templates/CMakeLists.txt +++ b/ScreenPlayWallpaper/Godot/GDExtention/templates/CMakeLists.txt @@ -1,18 +1,17 @@ # SPDX-License-Identifier: Unlicense -add_custom_target(templates - SOURCES - template.debug.gdextension.in - template.release.gdextension.in -) +add_custom_target(templates SOURCES template.debug.gdextension.in template.release.gdextension.in) add_dependencies(${PROJECT_NAME} templates) -# We shouldn't be relying on CMAKE_BUILD_TYPE (see https://github.com/asmaloney/GDExtensionTemplate/issues/25) -# But until we fix it here and in godot-cpp, ensure it's one we expect. +# We shouldn't be relying on CMAKE_BUILD_TYPE (see https://github.com/asmaloney/GDExtensionTemplate/issues/25) But until we fix it here and +# in godot-cpp, ensure it's one we expect. set(ALLOWED_BUILDS "Debug;Release;debug;release") -if(NOT "${CMAKE_BUILD_TYPE}" IN_LIST ALLOWED_BUILDS) +if(NOT + "${CMAKE_BUILD_TYPE}" + IN_LIST + ALLOWED_BUILDS) message(FATAL_ERROR "CMAKE_BUILD_TYPE must be set to Debug or Release") endif() @@ -28,7 +27,7 @@ endif() # Generate our project's .gdextension file from the template set(OUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../ScreenPlayGodot/${PROJECT_NAME}/) set(GD_EXTENSION_FILE ${PROJECT_NAME}.gdextension) -#configure_file(${GD_EXTENSION_FILE_INPUT} ${OUT_PATH}/${GD_EXTENSION_FILE}) +# configure_file(${GD_EXTENSION_FILE_INPUT} ${OUT_PATH}/${GD_EXTENSION_FILE}) unset(ALLOWED_BUILDS) unset(BUILD_TYPE) diff --git a/ScreenPlayWallpaper/main.cpp b/ScreenPlayWallpaper/main.cpp index 971de5f9..0e875807 100644 --- a/ScreenPlayWallpaper/main.cpp +++ b/ScreenPlayWallpaper/main.cpp @@ -9,15 +9,15 @@ #include "ScreenPlayWallpaper/CMakeVariables.h" #include "ScreenPlayUtil/exitcodes.h" -#include "ScreenPlayUtil/util.h" #include "ScreenPlayUtil/logginghandler.h" +#include "ScreenPlayUtil/util.h" #if defined(Q_OS_WIN) #include "src/winwindow.h" Q_IMPORT_QML_PLUGIN(ScreenPlaySysInfoPlugin) #elif defined(Q_OS_LINUX) -#include "src/linuxx11window.h" #include "src/linuxwaylandwindow.h" +#include "src/linuxx11window.h" #elif defined(Q_OS_OSX) #include "src/macwindow.h" #endif @@ -44,9 +44,9 @@ int main(int argc, char* argv[]) #if defined(Q_OS_WIN) window = std::make_unique(); #elif defined(Q_OS_LINUX) - if(platformName == "xcb"){ - window = std::make_unique(); - } else if(platformName == "wayland"){ + if (platformName == "xcb") { + window = std::make_unique(); + } else if (platformName == "wayland") { window = std::make_unique(); } #elif defined(Q_OS_OSX) diff --git a/ScreenPlayWallpaper/src/basewindow.cpp b/ScreenPlayWallpaper/src/basewindow.cpp index bfa031aa..2bb44d39 100644 --- a/ScreenPlayWallpaper/src/basewindow.cpp +++ b/ScreenPlayWallpaper/src/basewindow.cpp @@ -35,7 +35,6 @@ BaseWindow::BaseWindow() "VideoCodec", "Error: only enums"); - setOSVersion(QSysInfo::productVersion()); } diff --git a/ScreenPlayWallpaper/src/linuxwaylandwindow.cpp b/ScreenPlayWallpaper/src/linuxwaylandwindow.cpp index 5879cdeb..73d453e3 100644 --- a/ScreenPlayWallpaper/src/linuxwaylandwindow.cpp +++ b/ScreenPlayWallpaper/src/linuxwaylandwindow.cpp @@ -1,10 +1,10 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only #include "linuxwaylandwindow.h" -#include #include +#include -#include #include +#include ScreenPlay::WallpaperExitCode LinuxWaylandWindow::start() { @@ -22,20 +22,12 @@ ScreenPlay::WallpaperExitCode LinuxWaylandWindow::start() // Get the Wayland display if (QGuiApplication::platformName() == "wayland") { - QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface(); - + QPlatformNativeInterface* native = QGuiApplication::platformNativeInterface(); - auto *layerShell = LayerShellQt::Window::get(&m_window); - layerShell->setLayer(LayerShellQt::Window::LayerBackground); - layerShell->setAnchors(static_cast>( - LayerShellQt::Window::Anchor::AnchorTop | - LayerShellQt::Window::Anchor::AnchorBottom | - LayerShellQt::Window::Anchor::AnchorLeft | - LayerShellQt::Window::Anchor::AnchorRight - )); - - - + auto* layerShell = LayerShellQt::Window::get(&m_window); + layerShell->setLayer(LayerShellQt::Window::LayerBackground); + layerShell->setAnchors(static_cast>( + LayerShellQt::Window::Anchor::AnchorTop | LayerShellQt::Window::Anchor::AnchorBottom | LayerShellQt::Window::Anchor::AnchorLeft | LayerShellQt::Window::Anchor::AnchorRight)); } m_window.show(); diff --git a/ScreenPlayWallpaper/src/windowsintegration.cpp b/ScreenPlayWallpaper/src/windowsintegration.cpp index 549e69bf..d8b71af2 100644 --- a/ScreenPlayWallpaper/src/windowsintegration.cpp +++ b/ScreenPlayWallpaper/src/windowsintegration.cpp @@ -1,6 +1,4 @@ #include "windowsintegration.h" - - bool WindowsIntegration::searchWorkerWindowToParentTo() { @@ -29,20 +27,20 @@ float WindowsIntegration::getScaling(const int monitorIndex) const ZeroMemory(&displayDevice, sizeof(displayDevice)); displayDevice.cb = sizeof(displayDevice); - // Enumerate through monitors until we find the one we're looking for + // Enumerate through monitors until we find the one we're looking for for (int i = 0; EnumDisplayDevices(NULL, i, &displayDevice, 0); i++) { if (i == monitorIndex) { DEVMODE devMode; ZeroMemory(&devMode, sizeof(devMode)); devMode.dmSize = sizeof(devMode); - // Get settings for selected monitor + // Get settings for selected monitor if (!EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode)) { // Unable to get monitor settings return 1.0f; } - // Get DPI for selected monitor + // Get DPI for selected monitor HMONITOR hMonitor = MonitorFromPoint({ devMode.dmPosition.x, devMode.dmPosition.y }, MONITOR_DEFAULTTONEAREST); UINT dpiX = 0, dpiY = 0; if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) { @@ -91,15 +89,244 @@ BOOL SearchForWorkerWindow(HWND hwnd, LPARAM lparam) return TRUE; } -std::vector WindowsIntegration::GetAllMonitors() { +std::vector WindowsIntegration::GetAllMonitors() +{ std::vector monitors; - // Use the static MonitorEnumProc callback for EnumDisplayMonitors + // Use the static MonitorEnumProc callback for EnumDisplayMonitors EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, reinterpret_cast(&monitors)); return monitors; } +int WindowsIntegration::GetMonitorIndex(HMONITOR hMonitor) +{ + sEnumInfo info; + info.hMonitor = hMonitor; + + if (EnumDisplayMonitors(NULL, NULL, GetMonitorByHandle, (LPARAM)&info)) + return -1; + + return info.iIndex; +} +/*! + \brief This method is called via a fixed interval to detect if a window completely + covers a monitor. If then sets visualPaused for QML to pause the content. +*/ +bool WindowsIntegration::checkForFullScreenWindow(HWND windowHandle) +{ + + HWND hFoundWnd = nullptr; + EnumWindows(&FindTheDesiredWnd, reinterpret_cast(&hFoundWnd)); + + // True if one window has WS_MAXIMIZE + if (hFoundWnd != nullptr) { + DWORD dwFlags = 0; + HMONITOR monitor = MonitorFromWindow(hFoundWnd, dwFlags); + HMONITOR wallpaper = MonitorFromWindow(windowHandle, dwFlags); + int monitorIndex = GetMonitorIndex(monitor); + int wallpaperIndex = GetMonitorIndex(wallpaper); + // qDebug() << monitorIndex << wallpaperIndex; + + // If the window that has WS_MAXIMIZE is at the same monitor as this wallpaper + return monitorIndex == wallpaperIndex; + + } else { + return false; + } +} +/* + * Adjusting a Window's Position and Size for Different Monitor DPI Scale Factors: + * * Windows allows users to set different DPI (dots per inch) scale factors for each monitor. This DPI scaling can lead to + * discrepancies in the positioning and size of windows, especially if we want to place a window on a monitor with a different + * scale factor than the one it was originally on. + * * In our scenario, we want to move and resize a window (`windowHwnd`) to fit perfectly within a target monitor. However, + * both the window and the target monitor can have different DPI scale factors, so we need to account for these when calculating + * the window's new position and size. + * * Steps: + * * 1. Retrieve the DPI scale factor for the window: + * - This gives us the current scale factor of the window based on its original monitor. + * * 2. Retrieve the DPI scale factor for the target monitor: + * - This gives us the scale factor of the monitor where we want to place the window. + * * 3. Calculate the window's new position: + * - The new position should be relative to the `WorkerW` window's coordinates. + * - Adjust the position based on the ratio of the window's DPI scale factor to the target monitor's DPI scale factor. + * This ensures that the window is positioned correctly on the monitor regardless of any differences in scale factors. + * * 4. Calculate the window's new size: + * - Adjust the size of the window based on the ratio of the window's DPI scale factor to the target monitor's DPI scale factor. + * This ensures that the window fits perfectly within the monitor, taking into account any differences in scale factors. + * * By following this approach, we can accurately position and resize the window on any monitor, regardless of differences in DPI + * scale factors. + */ + +std::optional WindowsIntegration::setupWallpaperForOneScreen(const int activeScreen, HWND windowHwnd, HWND parentWindowHwnd, std::function updateWindowSize) +{ + std::vector monitors = GetAllMonitors(); + for (const auto& monitor : monitors) { + monitor.print(); + if (monitor.index != activeScreen) + continue; + + SetWindowPos(windowHwnd, HWND_TOP, + monitor.position.left, monitor.position.top, + monitor.size.cx, monitor.size.cy, + SWP_NOZORDER | SWP_NOACTIVATE); + + // Must be called here to fix window positions! + updateWindowSize(monitor.size.cx, monitor.size.cy); + + RECT oldRect; + GetWindowRect(windowHwnd, &oldRect); + std::cout << "Old Window Position: (" << oldRect.left << ", " << oldRect.top << ")" << std::endl; + + float windowDpiScaleFactor = static_cast(GetDpiForWindow(windowHwnd)) / 96.0f; + float targetMonitorDpiScaleFactor = monitor.scaleFactor; + std::cout << "Window DPI Scale Factor: " << windowDpiScaleFactor << std::endl; + std::cout << "Target Monitor DPI Scale Factor: " << targetMonitorDpiScaleFactor << std::endl; + + SetParent(windowHwnd, parentWindowHwnd); + RECT parentRect; + GetWindowRect(parentWindowHwnd, &parentRect); + std::cout << "WorkerW Window Position: (" << parentRect.left << ", " << parentRect.top << ")" << std::endl; + + int newX = static_cast((oldRect.left - parentRect.left) * (windowDpiScaleFactor / targetMonitorDpiScaleFactor)); + int newY = static_cast((oldRect.top - parentRect.top) * (windowDpiScaleFactor / targetMonitorDpiScaleFactor)); + std::cout << "Calculated New Position: (" << newX << ", " << newY << ")" << std::endl; + + int newWidth = static_cast(monitor.size.cx * (windowDpiScaleFactor / targetMonitorDpiScaleFactor)); + int newHeight = static_cast(monitor.size.cy * (windowDpiScaleFactor / targetMonitorDpiScaleFactor)); + std::cout << "Calculated New Size: (" << newWidth << "x" << newHeight << ")" << std::endl; + + SetWindowPos(windowHwnd, NULL, newX, newY, newWidth, newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + return { monitor }; + } + return std::nullopt; +} +/** + * Spans the window across multiple monitors. + * * This function takes a vector of monitor indices and adjusts the window's + * size and position to span across the specified monitors. It determines the + * window's new size by finding the bounding rectangle that covers all selected + * monitors. The window's new position is set to the top-left corner of this + * bounding rectangle. + * * Note: This function assumes that all monitors have the same DPI scaling. If + * they don't, the window may not fit perfectly across the monitors. + * * @param activeScreens A vector containing the indices of monitors across + * which the window should span. + * * Usage: + * setupWallpaperForMultipleScreens({0, 1}); // Spans the window across monitors 0 and 1. + * * Internals: + * 1. For each monitor in `activeScreens`, determine its bounding rectangle. + * 2. Compute the window's new width as `rightmost - leftmost` and its new + * height as `bottommost - topmost`. + * 3. Adjust the window's position and size to fit this bounding rectangle. + */ +WindowsIntegration::SpanResult WindowsIntegration::setupWallpaperForMultipleScreens(const std::vector& activeScreens, HWND windowHwnd, HWND parentWindowHwnd) +{ + std::vector monitors = GetAllMonitors(); + + int leftmost = INT_MAX; + int topmost = INT_MAX; + int rightmost = INT_MIN; + int bottommost = INT_MIN; + + for (const auto& monitorIndex : activeScreens) { + if (monitorIndex < monitors.size()) { + const Monitor& monitor = monitors[monitorIndex]; + leftmost = (std::min)(leftmost, static_cast(monitor.position.left)); + topmost = (std::min)(topmost, static_cast(monitor.position.top)); + rightmost = (std::max)(rightmost, static_cast(monitor.position.right)); + bottommost = (std::max)(bottommost, static_cast(monitor.position.bottom)); + } + } + + int newWidth = rightmost - leftmost; + int newHeight = bottommost - topmost; + + RECT oldRect; + GetWindowRect(windowHwnd, &oldRect); + + float windowDpiScaleFactor = static_cast(GetDpiForWindow(windowHwnd)) / 96.0f; + + SetParent(windowHwnd, parentWindowHwnd); + RECT parentRect; + GetWindowRect(parentWindowHwnd, &parentRect); + + int newX = static_cast((leftmost - parentRect.left) * windowDpiScaleFactor); + int newY = static_cast((topmost - parentRect.top) * windowDpiScaleFactor); + + SetWindowPos(windowHwnd, NULL, newX, newY, newWidth, newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + SpanResult result; + result.width = rightmost - leftmost; + result.height = bottommost - topmost; + result.success = true; + + return result; +} +/** + * Sets up the wallpaper to span across all connected screens. + * * This function retrieves information about all connected monitors, including their positions, dimensions, and scale factors. + * It then calculates the combined dimensions needed to span the window across all these monitors, taking into account + * the scale factors. The function also handles reparenting the window to the WorkerW window, ensuring it remains below + * other desktop icons. The calculated position and dimensions are adjusted to account for any potential scaling differences + * between the window and the combined monitor setup. + * * @note This function assumes that the window's DPI scale factor is based on a default of 96 DPI. Adjustments are made + * based on this assumption. + * * @note The function currently multiplies the scale factors of all monitors to get an overall scale factor. This may need + * adjustments based on specific application needs. + * * @return SpanResult A structure containing the combined width and height of the monitors, and a success flag indicating + * whether the operation was successful. + * * @retval SpanResult::width The combined width of all monitors after scaling. + * @retval SpanResult::height The combined height of all monitors after scaling. + * @retval SpanResult::success A boolean flag indicating the success of the operation. Currently, it always returns `true` + * assuming all operations are successful. This can be adjusted based on error checks as needed. + */ +WindowsIntegration::SpanResult WindowsIntegration::setupWallpaperForAllScreens(HWND windowHwnd, HWND parentWindowHwnd) +{ + std::vector monitors = GetAllMonitors(); + + int leftmost = INT_MAX; + int topmost = INT_MAX; + int rightmost = INT_MIN; + int bottommost = INT_MIN; + float overallScaleFactor = 1.0f; // assuming default is no scaling + + // Calculate the combined dimensions of all monitors + for (const auto& monitor : monitors) { + leftmost = (std::min)(leftmost, static_cast(monitor.position.left)); + topmost = (std::min)(topmost, static_cast(monitor.position.top)); + rightmost = (std::max)(rightmost, static_cast(monitor.position.right)); + bottommost = (std::max)(bottommost, static_cast(monitor.position.bottom)); + overallScaleFactor *= monitor.scaleFactor; // Adjust as per your scaling needs + } + + int scaledWidth = static_cast((rightmost - leftmost) * overallScaleFactor); + int scaledHeight = static_cast((bottommost - topmost) * overallScaleFactor); + + // Set the position and size of the window to span all monitors + SetWindowPos(windowHwnd, HWND_TOP, leftmost, topmost, scaledWidth, scaledHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + // Reparenting and scaling logic + RECT oldRect; + GetWindowRect(windowHwnd, &oldRect); + float windowDpiScaleFactor = static_cast(GetDpiForWindow(windowHwnd)) / 96.0f; + SetParent(windowHwnd, parentWindowHwnd); + RECT parentRect; + GetWindowRect(parentWindowHwnd, &parentRect); + int newX = static_cast((oldRect.left - parentRect.left) * (windowDpiScaleFactor / overallScaleFactor)); + int newY = static_cast((oldRect.top - parentRect.top) * (windowDpiScaleFactor / overallScaleFactor)); + + SetWindowPos(windowHwnd, NULL, newX, newY, scaledWidth, scaledHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + // Return the combined span of all monitors + SpanResult result; + result.width = scaledWidth; + result.height = scaledHeight; + result.success = true; // Assuming the operations are successful; adjust as needed + + return result; +} + BOOL GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { @@ -120,10 +347,11 @@ BOOL FindTheDesiredWnd(HWND hWnd, LPARAM lParam) return true; // keep enumerating } -BOOL MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { +BOOL MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) +{ std::vector* pMonitors = reinterpret_cast*>(dwData); - MONITORINFOEX info; + MONITORINFOEX info; info.cbSize = sizeof(info); GetMonitorInfo(hMonitor, &info); diff --git a/ScreenPlayWallpaper/src/windowsintegration.h b/ScreenPlayWallpaper/src/windowsintegration.h index 3c4d10c8..92301aa7 100644 --- a/ScreenPlayWallpaper/src/windowsintegration.h +++ b/ScreenPlayWallpaper/src/windowsintegration.h @@ -16,13 +16,14 @@ #include struct Monitor { - HMONITOR monitorID; // Handle to the monitor - int index; // Index of the monitor - RECT position; // Monitor's position and size - SIZE size; // Monitor's width and height - float scaleFactor; // Scale factor (DPI scaling as a factor, e.g., 1.5 for 150% scaling) + HMONITOR monitorID; // Handle to the monitor + int index; // Index of the monitor + RECT position; // Monitor's position and size + SIZE size; // Monitor's width and height + float scaleFactor; // Scale factor (DPI scaling as a factor, e.g., 1.5 for 150% scaling) - void print() const { + void print() const + { std::cout << "Monitor Info:" << std::endl; std::cout << "Monitor ID: " << monitorID << std::endl; std::cout << "Index: " << index << std::endl; @@ -41,14 +42,12 @@ BOOL WINAPI SearchForWorkerWindow(HWND hwnd, LPARAM lparam); struct WinMonitorStats { - WinMonitorStats() { EnumDisplayMonitors(NULL, NULL, MonitorEnum, (LPARAM)this); } - - static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData) + 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; @@ -66,7 +65,7 @@ struct WinMonitorStats { return TRUE; } - std::vector iMonitors; + std::vector iMonitors; std::vector hMonitors; std::vector hdcMonitors; std::vector rcMonitors; @@ -84,262 +83,24 @@ struct sEnumInfo { HMONITOR hMonitor; }; +struct WindowsIntegration { -class WindowsIntegration { -public: - - bool searchWorkerWindowToParentTo(); - float getScaling(const int monitorIndex) const; - bool hasWindowScaling() const; HWND windowHandle {}; HWND windowHandleWorker {}; - Point zeroPoint; - std::vector GetAllMonitors(); - - - int GetMonitorIndex(HMONITOR hMonitor) - { - sEnumInfo info; - info.hMonitor = hMonitor; - - if (EnumDisplayMonitors(NULL, NULL, GetMonitorByHandle, (LPARAM)&info)) - return -1; - - return info.iIndex; - } - - /*! - \brief This method is called via a fixed interval to detect if a window completely - covers a monitor. If then sets visualPaused for QML to pause the content. - */ - bool checkForFullScreenWindow(HWND windowHandle) - { - - HWND hFoundWnd = nullptr; - EnumWindows(&FindTheDesiredWnd, reinterpret_cast(&hFoundWnd)); - - // True if one window has WS_MAXIMIZE - if (hFoundWnd != nullptr) { - DWORD dwFlags = 0; - HMONITOR monitor = MonitorFromWindow(hFoundWnd, dwFlags); - HMONITOR wallpaper = MonitorFromWindow(windowHandle, dwFlags); - int monitorIndex = GetMonitorIndex(monitor); - int wallpaperIndex = GetMonitorIndex(wallpaper); - // qDebug() << monitorIndex << wallpaperIndex; - - // If the window that has WS_MAXIMIZE is at the same monitor as this wallpaper - return monitorIndex == wallpaperIndex; - - } else { - return false; - } - } - - // Define the result structure struct SpanResult { int width = 0; int height = 0; bool success = false; }; - /* - * Adjusting a Window's Position and Size for Different Monitor DPI Scale Factors: - * * Windows allows users to set different DPI (dots per inch) scale factors for each monitor. This DPI scaling can lead to - * discrepancies in the positioning and size of windows, especially if we want to place a window on a monitor with a different - * scale factor than the one it was originally on. - * * In our scenario, we want to move and resize a window (`windowHwnd`) to fit perfectly within a target monitor. However, - * both the window and the target monitor can have different DPI scale factors, so we need to account for these when calculating - * the window's new position and size. - * * Steps: - * * 1. Retrieve the DPI scale factor for the window: - * - This gives us the current scale factor of the window based on its original monitor. - * * 2. Retrieve the DPI scale factor for the target monitor: - * - This gives us the scale factor of the monitor where we want to place the window. - * * 3. Calculate the window's new position: - * - The new position should be relative to the `WorkerW` window's coordinates. - * - Adjust the position based on the ratio of the window's DPI scale factor to the target monitor's DPI scale factor. - * This ensures that the window is positioned correctly on the monitor regardless of any differences in scale factors. - * * 4. Calculate the window's new size: - * - Adjust the size of the window based on the ratio of the window's DPI scale factor to the target monitor's DPI scale factor. - * This ensures that the window fits perfectly within the monitor, taking into account any differences in scale factors. - * * By following this approach, we can accurately position and resize the window on any monitor, regardless of differences in DPI - * scale factors. - */ - - std::optional setupWallpaperForOneScreen(const int activeScreen, HWND windowHwnd, HWND parentWindowHwnd, std::functionupdateWindowSize) - { - std::vector monitors = GetAllMonitors(); - for (const auto& monitor : monitors) { - monitor.print(); - if (monitor.index != activeScreen) - continue; - - SetWindowPos(windowHwnd, HWND_TOP, - monitor.position.left, monitor.position.top, - monitor.size.cx, monitor.size.cy, - SWP_NOZORDER | SWP_NOACTIVATE); - - // Must be called here to fix window positions! - updateWindowSize(monitor.size.cx, monitor.size.cy); - - RECT oldRect; - GetWindowRect(windowHwnd, &oldRect); - std::cout << "Old Window Position: (" << oldRect.left << ", " << oldRect.top << ")" << std::endl; - - float windowDpiScaleFactor = static_cast(GetDpiForWindow(windowHwnd)) / 96.0f; - float targetMonitorDpiScaleFactor = monitor.scaleFactor; - std::cout << "Window DPI Scale Factor: " << windowDpiScaleFactor << std::endl; - std::cout << "Target Monitor DPI Scale Factor: " << targetMonitorDpiScaleFactor << std::endl; - - SetParent(windowHwnd, parentWindowHwnd); - RECT parentRect; - GetWindowRect(parentWindowHwnd, &parentRect); - std::cout << "WorkerW Window Position: (" << parentRect.left << ", " << parentRect.top << ")" << std::endl; - - int newX = static_cast((oldRect.left - parentRect.left) * (windowDpiScaleFactor / targetMonitorDpiScaleFactor)); - int newY = static_cast((oldRect.top - parentRect.top) * (windowDpiScaleFactor / targetMonitorDpiScaleFactor)); - std::cout << "Calculated New Position: (" << newX << ", " << newY << ")" << std::endl; - - int newWidth = static_cast(monitor.size.cx * (windowDpiScaleFactor / targetMonitorDpiScaleFactor)); - int newHeight = static_cast(monitor.size.cy * (windowDpiScaleFactor / targetMonitorDpiScaleFactor)); - std::cout << "Calculated New Size: (" << newWidth << "x" << newHeight << ")" << std::endl; - - SetWindowPos(windowHwnd, NULL, newX, newY, newWidth, newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - return {monitor}; - } - return std::nullopt; - } - /** - * Spans the window across multiple monitors. - * - * This function takes a vector of monitor indices and adjusts the window's - * size and position to span across the specified monitors. It determines the - * window's new size by finding the bounding rectangle that covers all selected - * monitors. The window's new position is set to the top-left corner of this - * bounding rectangle. - * - * Note: This function assumes that all monitors have the same DPI scaling. If - * they don't, the window may not fit perfectly across the monitors. - * - * @param activeScreens A vector containing the indices of monitors across - * which the window should span. - * - * Usage: - * setupWallpaperForMultipleScreens({0, 1}); // Spans the window across monitors 0 and 1. - * - * Internals: - * 1. For each monitor in `activeScreens`, determine its bounding rectangle. - * 2. Compute the window's new width as `rightmost - leftmost` and its new - * height as `bottommost - topmost`. - * 3. Adjust the window's position and size to fit this bounding rectangle. - */ - SpanResult setupWallpaperForMultipleScreens(const std::vector& activeScreens, HWND windowHwnd, HWND parentWindowHwnd) - { - std::vector monitors = GetAllMonitors(); - - int leftmost = INT_MAX; - int topmost = INT_MAX; - int rightmost = INT_MIN; - int bottommost = INT_MIN; - - for (const auto& monitorIndex : activeScreens) { - if (monitorIndex < monitors.size()) { - const Monitor& monitor = monitors[monitorIndex]; - leftmost = std::min(leftmost, static_cast(monitor.position.left)); - topmost = std::min(topmost, static_cast(monitor.position.top)); - rightmost = std::max(rightmost, static_cast(monitor.position.right)); - bottommost = std::max(bottommost, static_cast(monitor.position.bottom)); - } - } - - - int newWidth = rightmost - leftmost; - int newHeight = bottommost - topmost; - - RECT oldRect; - GetWindowRect(windowHwnd, &oldRect); - - float windowDpiScaleFactor = static_cast(GetDpiForWindow(windowHwnd)) / 96.0f; - - SetParent(windowHwnd, parentWindowHwnd); - RECT parentRect; - GetWindowRect(parentWindowHwnd, &parentRect); - - int newX = static_cast((leftmost - parentRect.left) * windowDpiScaleFactor); - int newY = static_cast((topmost - parentRect.top) * windowDpiScaleFactor); - - SetWindowPos(windowHwnd, NULL, newX, newY, newWidth, newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - SpanResult result; - result.width = rightmost - leftmost; - result.height = bottommost - topmost; - result.success = true; - - return result; - } - /** - * Sets up the wallpaper to span across all connected screens. - * * This function retrieves information about all connected monitors, including their positions, dimensions, and scale factors. - * It then calculates the combined dimensions needed to span the window across all these monitors, taking into account - * the scale factors. The function also handles reparenting the window to the WorkerW window, ensuring it remains below - * other desktop icons. The calculated position and dimensions are adjusted to account for any potential scaling differences - * between the window and the combined monitor setup. - * * @note This function assumes that the window's DPI scale factor is based on a default of 96 DPI. Adjustments are made - * based on this assumption. - * * @note The function currently multiplies the scale factors of all monitors to get an overall scale factor. This may need - * adjustments based on specific application needs. - * * @return SpanResult A structure containing the combined width and height of the monitors, and a success flag indicating - * whether the operation was successful. - * - * @retval SpanResult::width The combined width of all monitors after scaling. - * @retval SpanResult::height The combined height of all monitors after scaling. - * @retval SpanResult::success A boolean flag indicating the success of the operation. Currently, it always returns `true` - * assuming all operations are successful. This can be adjusted based on error checks as needed. - */ - SpanResult setupWallpaperForAllScreens( HWND windowHwnd, HWND parentWindowHwnd) { - std::vector monitors = GetAllMonitors(); - - int leftmost = INT_MAX; - int topmost = INT_MAX; - int rightmost = INT_MIN; - int bottommost = INT_MIN; - float overallScaleFactor = 1.0f; // assuming default is no scaling - - // Calculate the combined dimensions of all monitors - for (const auto& monitor : monitors) { - leftmost = std::min(leftmost, static_cast(monitor.position.left)); - topmost = std::min(topmost, static_cast(monitor.position.top)); - rightmost = std::max(rightmost, static_cast(monitor.position.right)); - bottommost = std::max(bottommost, static_cast(monitor.position.bottom)); - overallScaleFactor *= monitor.scaleFactor; // Adjust as per your scaling needs - } - - int scaledWidth = static_cast((rightmost - leftmost) * overallScaleFactor); - int scaledHeight = static_cast((bottommost - topmost) * overallScaleFactor); - - // Set the position and size of the window to span all monitors - SetWindowPos(windowHwnd, HWND_TOP, leftmost, topmost, scaledWidth, scaledHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - // Reparenting and scaling logic - RECT oldRect; - GetWindowRect(windowHwnd, &oldRect); - float windowDpiScaleFactor = static_cast(GetDpiForWindow(windowHwnd)) / 96.0f; - SetParent(windowHwnd, parentWindowHwnd); - RECT parentRect; - GetWindowRect(parentWindowHwnd, &parentRect); - int newX = static_cast((oldRect.left - parentRect.left) * (windowDpiScaleFactor / overallScaleFactor)); - int newY = static_cast((oldRect.top - parentRect.top) * (windowDpiScaleFactor / overallScaleFactor)); - - SetWindowPos(windowHwnd, NULL, newX, newY, scaledWidth, scaledHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - // Return the combined span of all monitors - SpanResult result; - result.width = scaledWidth; - result.height = scaledHeight; - result.success = true; // Assuming the operations are successful; adjust as needed - - return result; - } - - + bool searchWorkerWindowToParentTo(); + float getScaling(const int monitorIndex) const; + bool hasWindowScaling() const; + std::vector GetAllMonitors(); + int GetMonitorIndex(HMONITOR hMonitor); + bool checkForFullScreenWindow(HWND windowHandle); + std::optional setupWallpaperForOneScreen(const int activeScreen, HWND windowHwnd, HWND parentWindowHwnd, std::function updateWindowSize); + SpanResult setupWallpaperForMultipleScreens(const std::vector& activeScreens, HWND windowHwnd, HWND parentWindowHwnd); + SpanResult setupWallpaperForAllScreens(HWND windowHwnd, HWND parentWindowHwnd); }; diff --git a/ScreenPlayWallpaper/src/winwindow.cpp b/ScreenPlayWallpaper/src/winwindow.cpp index 447146eb..9070a4e5 100644 --- a/ScreenPlayWallpaper/src/winwindow.cpp +++ b/ScreenPlayWallpaper/src/winwindow.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only #include "winwindow.h" -#include "windowsintegration.h" #include "ScreenPlayUtil/projectfile.h" +#include "windowsintegration.h" #include #include #include @@ -16,7 +16,6 @@ \brief ScreenPlayWindow used for the Windows implementation. */ - HHOOK g_mouseHook; QPoint g_LastMousePosition { 0, 0 }; QPoint g_globalOffset { 0, 0 }; @@ -182,18 +181,16 @@ void WinWindow::destroyThis() emit qmlExit(); } - void WinWindow::setupWallpaperForOneScreen(int activeScreen) { WindowsIntegration windowsIntegration; - auto updateWindowSize = [this](const int width, const int height){ + auto updateWindowSize = [this](const int width, const int height) { setWidth(width); setHeight(height); m_window.setWidth(width); m_window.setHeight(height); }; - std::optional monitor = windowsIntegration.setupWallpaperForOneScreen(activeScreen,m_windowHandle,m_windowHandleWorker,updateWindowSize); - + std::optional monitor = windowsIntegration.setupWallpaperForOneScreen(activeScreen, m_windowHandle, m_windowHandleWorker, updateWindowSize); } /*! @@ -202,7 +199,7 @@ void WinWindow::setupWallpaperForOneScreen(int activeScreen) void WinWindow::setupWallpaperForAllScreens() { WindowsIntegration windowsIntegration; - WindowsIntegration::SpanResult span = windowsIntegration.setupWallpaperForAllScreens(m_windowHandle,m_windowHandleWorker); + WindowsIntegration::SpanResult span = windowsIntegration.setupWallpaperForAllScreens(m_windowHandle, m_windowHandleWorker); setWidth(span.width); setHeight(span.height); m_window.setWidth(width()); @@ -216,7 +213,7 @@ void WinWindow::setupWallpaperForMultipleScreens(const QVector& activeScree { std::vector activeScreens(activeScreensList.begin(), activeScreensList.end()); WindowsIntegration windowsIntegration; - WindowsIntegration::SpanResult span = windowsIntegration.setupWallpaperForMultipleScreens(activeScreens,m_windowHandle,m_windowHandleWorker); + WindowsIntegration::SpanResult span = windowsIntegration.setupWallpaperForMultipleScreens(activeScreens, m_windowHandle, m_windowHandleWorker); setWidth(span.width); setHeight(span.height); m_window.setWidth(width()); @@ -290,7 +287,8 @@ void WinWindow::clearComponentCache() m_window.engine()->clearComponentCache(); } -void WinWindow::checkForFullScreenWindow(){ +void WinWindow::checkForFullScreenWindow() +{ bool hasFullscreenWindow = WindowsIntegration().checkForFullScreenWindow(m_windowHandle); setVisualsPaused(hasFullscreenWindow); diff --git a/ScreenPlayWidget/main.cpp b/ScreenPlayWidget/main.cpp index f9d40f85..0b25b869 100644 --- a/ScreenPlayWidget/main.cpp +++ b/ScreenPlayWidget/main.cpp @@ -8,8 +8,8 @@ #include #include -#include "src/widgetwindow.h" #include "ScreenPlayUtil/logginghandler.h" +#include "src/widgetwindow.h" #if defined(Q_OS_WIN) Q_IMPORT_QML_PLUGIN(ScreenPlaySysInfoPlugin) @@ -95,7 +95,7 @@ int main(int argc, char* argv[]) #if defined(Q_OS_OSX) MacUtils::showDockIcon(false); #endif - logging = std::make_unique("ScreenPlayWidget_"+ appID); + logging = std::make_unique("ScreenPlayWidget_" + appID); const int status = app.exec(); logging.reset(); return status; diff --git a/ThirdParty/CMakeLists.txt b/ThirdParty/CMakeLists.txt index 01ad0a83..2260531f 100644 --- a/ThirdParty/CMakeLists.txt +++ b/ThirdParty/CMakeLists.txt @@ -16,19 +16,17 @@ FetchContent_Populate( # https://bugreports.qt.io/browse/QTCREATORBUG-27083 SOURCE_DIR ${THIRD_PARTY_PATH}/qml-plausible) - - add_subdirectory(qml-plausible) add_subdirectory(QArchive) if(UNIX AND NOT APPLE) -FetchContent_Populate( - qt-layer-shell - GIT_REPOSITORY https://github.com/KDE/layer-shell-qt.git - GIT_TAG 721c0ae334554eb2396a2d4d3358f896b8c77412 - # Workaround because: 1. QtCreator cannot handle QML_ELEMENT stuff when it is in bin folder - # https://bugreports.qt.io/browse/QTCREATORBUG-27083 - SOURCE_DIR ${THIRD_PARTY_PATH}/qt-layer-shell) + FetchContent_Populate( + qt-layer-shell + GIT_REPOSITORY https://github.com/KDE/layer-shell-qt.git + GIT_TAG 721c0ae334554eb2396a2d4d3358f896b8c77412 + # Workaround because: 1. QtCreator cannot handle QML_ELEMENT stuff when it is in bin folder + # https://bugreports.qt.io/browse/QTCREATORBUG-27083 + SOURCE_DIR ${THIRD_PARTY_PATH}/qt-layer-shell) add_subdirectory(qt-layer-shell) -endif() \ No newline at end of file +endif() diff --git a/Tools/CMakeLists.txt b/Tools/CMakeLists.txt index 80d9a1c5..90f7c38d 100644 --- a/Tools/CMakeLists.txt +++ b/Tools/CMakeLists.txt @@ -15,4 +15,4 @@ set(GODOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Apps/Godot") if(WIN32) # Todo: Add Linux and Mac support configure_file(${GODOT_PATH}/${GODOT_EDITOR_NAME} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ COPYONLY) -endif() \ No newline at end of file +endif()