diff --git a/CMakeLists.txt b/CMakeLists.txt index bfe03dca..2b6d95ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,7 +56,7 @@ execute_process( OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE) -add_compile_definitions(COMPILE_INFO="${BUILD_DATE} + ${GIT_COMMIT_HASH}") +add_compile_definitions(COMPILE_INFO="Build Date: ${BUILD_DATE}. Git Hash: ${GIT_COMMIT_HASH}. ") add_compile_definitions(SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}") add_compile_definitions(SCREENPLAY_STEAM="${SCREENPLAY_STEAM}") @@ -76,6 +76,9 @@ add_subdirectory(CMake) if(${SCREENPLAY_STEAM}) add_subdirectory(ScreenPlayWorkshop) +else() + # Only add target SteamSDKQtEnums + add_subdirectory(ScreenPlayWorkshop/SteamSDK) endif() if(WIN32) diff --git a/ScreenPlay/CMakeLists.txt b/ScreenPlay/CMakeLists.txt index b5604ccc..a7058fbc 100644 --- a/ScreenPlay/CMakeLists.txt +++ b/ScreenPlay/CMakeLists.txt @@ -204,7 +204,7 @@ target_link_libraries( Qt6::Svg Qt6::WebEngineQuick Qt6::WebEngineCore - SteamSDK) + SteamSDKQtEnums) if(${TESTS_ENABLED}) add_executable(tst_ScreenPlay tests/tst_main.cpp) diff --git a/ScreenPlay/src/monitorlistmodel.cpp b/ScreenPlay/src/monitorlistmodel.cpp index 36b92993..cb468956 100644 --- a/ScreenPlay/src/monitorlistmodel.cpp +++ b/ScreenPlay/src/monitorlistmodel.cpp @@ -135,6 +135,41 @@ QVariant MonitorListModel::data(const QModelIndex& index, int role) const */ void MonitorListModel::loadMonitors() { + +#ifdef Q_OS_WIN + QModelIndex index; + ScreenPlayUtil::WinMonitorStats monitors; + + // This offset lets us center the monitor selection view in the center + int offsetX = 0; + int offsetY = 0; + for (int i = 0; i < monitors.iMonitors.size(); i++) { + const int x = monitors.rcMonitors[i].left; + const int y = monitors.rcMonitors[i].top; + if (x < 0) { + offsetX += (x * -1); + } + if (y < 0) { + offsetY += (y * -1); + } + } + + for (int i = 0; i < monitors.iMonitors.size(); i++) { + const int width = std::abs(monitors.rcMonitors[i].right - monitors.rcMonitors[i].left); + const int height = std::abs(monitors.rcMonitors[i].top - monitors.rcMonitors[i].bottom); + const int x = monitors.rcMonitors[i].left; + const int y = monitors.rcMonitors[i].top; + QRect availableVirtualGeometry( + x + offsetX, + y + offsetY, + width, + height); + beginInsertRows(index, m_monitorList.size(), m_monitorList.size()); + m_monitorList.append(Monitor { i, availableVirtualGeometry, QApplication::screens().at(i) }); + endInsertRows(); + } +#else + QModelIndex index; int offsetX = 0; int offsetY = 0; @@ -148,7 +183,6 @@ void MonitorListModel::loadMonitors() } } - QModelIndex index; for (int i = 0; i < QApplication::screens().count(); i++) { QScreen* screen = QApplication::screens().at(i); @@ -166,6 +200,7 @@ void MonitorListModel::loadMonitors() m_monitorList.append(Monitor { i, availableVirtualGeometry, screen }); endInsertRows(); } +#endif emit monitorReloadCompleted(); } diff --git a/ScreenPlay/src/screenplaywallpaper.cpp b/ScreenPlay/src/screenplaywallpaper.cpp index 389a1ec9..3434554b 100644 --- a/ScreenPlay/src/screenplaywallpaper.cpp +++ b/ScreenPlay/src/screenplaywallpaper.cpp @@ -174,6 +174,11 @@ void ScreenPlayWallpaper::processError(QProcess::ProcessError error) */ bool ScreenPlayWallpaper::setWallpaperValue(const QString& key, const QString& value, const bool save) { + if (!m_connection) { + qWarning() << "Cannot set value for unconnected wallpaper!"; + return false; + } + QJsonObject obj; obj.insert(key, value); 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/ScreenPlayUtil/src/util.cpp b/ScreenPlayUtil/src/util.cpp index 00119aba..339c5a10 100644 --- a/ScreenPlayUtil/src/util.cpp +++ b/ScreenPlayUtil/src/util.cpp @@ -233,7 +233,7 @@ std::optional getInstalledTypeFromStri { using ScreenPlay::InstalledType::InstalledType; - if (type.endsWith("Wallpaper")) { + if (type.endsWith("Wallpaper", Qt::CaseInsensitive)) { if (type.startsWith("video", Qt::CaseInsensitive)) { return InstalledType::VideoWallpaper; } @@ -254,7 +254,7 @@ std::optional getInstalledTypeFromStri } } - if (type.endsWith("Widget")) { + if (type.endsWith("Widget", Qt::CaseInsensitive)) { if (type.startsWith("qml", Qt::CaseInsensitive)) { return InstalledType::QMLWidget; } @@ -266,28 +266,27 @@ std::optional getInstalledTypeFromStri return std::nullopt; } - /*! \brief Maps the video codec type from a QString to an enum. Used for parsing the project.json. */ -std::optional getVideoCodecFromString(const QString &type) +std::optional getVideoCodecFromString(const QString& type) { - if(type.isEmpty()) + if (type.isEmpty()) return std::nullopt; - if(type.contains("vp8",Qt::CaseInsensitive)) + if (type.contains("vp8", Qt::CaseInsensitive)) return ScreenPlay::VideoCodec::VideoCodec::VP8; - if(type.contains("vp9",Qt::CaseInsensitive)) + if (type.contains("vp9", Qt::CaseInsensitive)) return ScreenPlay::VideoCodec::VideoCodec::VP9; - if(type.contains("av1",Qt::CaseInsensitive)) + if (type.contains("av1", Qt::CaseInsensitive)) return ScreenPlay::VideoCodec::VideoCodec::AV1; - if(type.contains("h264",Qt::CaseInsensitive)) + if (type.contains("h264", Qt::CaseInsensitive)) return ScreenPlay::VideoCodec::VideoCodec::H264; - if(type.contains("h265",Qt::CaseInsensitive)) + if (type.contains("h265", Qt::CaseInsensitive)) return ScreenPlay::VideoCodec::VideoCodec::H264; return std::nullopt; @@ -395,5 +394,4 @@ std::optional> parseStringToIntegerList(const QString string) return list; } - } 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/qml/Wallpaper.qml b/ScreenPlayWallpaper/qml/Wallpaper.qml index b030c6a2..6e870c77 100644 --- a/ScreenPlayWallpaper/qml/Wallpaper.qml +++ b/ScreenPlayWallpaper/qml/Wallpaper.qml @@ -17,11 +17,18 @@ Rectangle { if (Wallpaper.videoCodec === VideoCodec.Unknown) { Wallpaper.terminate() } + // macOS only supports h264 via the native Qt MM - if (Qt.platform === "osx" && (Wallpaper.videoCodec === VideoCodec.VP8 - || Wallpaper.videoCodec === VideoCodec.VP9)) { - loader.source = "qrc:/ScreenPlayWallpaper/qml/MultimediaWebView.qml" - } else { + if (Qt.platform.os === "osx") { + if ((Wallpaper.videoCodec === VideoCodec.VP8 + || Wallpaper.videoCodec === VideoCodec.VP9)) { + loader.source = "qrc:/ScreenPlayWallpaper/qml/MultimediaWebView.qml" + } else { + loader.source = "qrc:/ScreenPlayWallpaper/qml/MultimediaView.qml" + } + } + + if (Qt.platform.os === "windows") { loader.source = "qrc:/ScreenPlayWallpaper/qml/MultimediaView.qml" } fadeIn() diff --git a/ScreenPlayWallpaper/src/winwindow.cpp b/ScreenPlayWallpaper/src/winwindow.cpp index a2ec08b5..2ee42195 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); { diff --git a/ScreenPlayWorkshop/CMakeLists.txt b/ScreenPlayWorkshop/CMakeLists.txt index 0c9006c2..9faaee43 100644 --- a/ScreenPlayWorkshop/CMakeLists.txt +++ b/ScreenPlayWorkshop/CMakeLists.txt @@ -34,54 +34,31 @@ set(HEADER src/steamaccount.h src/steamqmlimageprovider.h) +set(STEAM_LIB_PATH "${CMAKE_CURRENT_SOURCE_DIR}/SteamSDK/redistributable_bin/") + +if(WIN32) + set(WORKSHOP_PLUGIN_DIR ${CMAKE_BINARY_DIR}/bin/Workshop) + set(STEAM_LIB "${STEAM_LIB_PATH}/win64/steam_api64.lib") + set(STEAM_BIN "${STEAM_LIB_PATH}/win64/steam_api64.dll") +elseif(APPLE) + set(WORKSHOP_PLUGIN_DIR ${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/Workshop) + set(STEAM_LIB "${STEAM_LIB_PATH}/osx/libsteam_api.dylib") + set(STEAM_BIN ${STEAM_LIB}) +elseif(UNIX) + set(WORKSHOP_PLUGIN_DIR ${CMAKE_BINARY_DIR}/bin/Workshop) + set(STEAM_LIB "${STEAM_LIB_PATH}/linux64/libsteam_api.so") + set(STEAM_BIN ${STEAM_LIB}) +endif() + qt_add_qml_module( ${PROJECT_NAME} - OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/Workshop + OUTPUT_DIRECTORY ${WORKSHOP_PLUGIN_DIR} URI "Workshop" SOURCES ${SOURCES} ${HEADER} VERSION 1.0) - -# Needed by the automatic generated target missing includes -# https://github.com/qt/qtdeclarative/blob/7a7064e14f094e843e1ee832cc927e86f887621a/src/qml/Qt6QmlMacros.cmake#L2042 -target_include_directories(${PROJECT_NAME} PUBLIC src/) - -set(STEAM_LIB_PATH "${CMAKE_CURRENT_SOURCE_DIR}/SteamSDK/redistributable_bin/") - -if(WIN32) - set(STEAM_LIB "${STEAM_LIB_PATH}/win64/steam_api64.lib") - set(STEAM_BIN "${STEAM_LIB_PATH}/win64/steam_api64.dll") -elseif(APPLE) - set(STEAM_LIB "${STEAM_LIB_PATH}/osx/libsteam_api.dylib") - set(STEAM_BIN ${STEAM_LIB}) -elseif(UNIX) - set(STEAM_LIB "${STEAM_LIB_PATH}/linux64/libsteam_api.so") - set(STEAM_BIN ${STEAM_LIB}) -endif() - -target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Quick ${STEAM_LIB} ScreenPlayUtil SteamSDK) - if(APPLE) - set(workshop_install_dir ${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/Workshop) - - add_custom_target( - build-time-make-directory - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory ${workshop_install_dir}) - - add_custom_command( - TARGET ${PROJECT_NAME} - POST_BUILD - COMMENT "Copying workshop plugin into ScreenPlay.app bundle" - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/Workshop/libworkshopplugin.dylib ${workshop_install_dir}) - - add_custom_command( - TARGET ${PROJECT_NAME} - POST_BUILD - COMMENT "Copying steam library into ScreenPlay.app bundle" - COMMAND ${CMAKE_COMMAND} -E copy ${STEAM_BIN} ${workshop_install_dir}) - if(${SCREENPLAY_STEAM}) add_custom_command( TARGET ${PROJECT_NAME} @@ -89,11 +66,24 @@ if(APPLE) COMMENT "Copying steam_appid.txt into ScreenPlay.app bundle. This is for development only!" COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/steam_appid.txt ${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/) - endif() + add_custom_command( + TARGET ${PROJECT_NAME} + POST_BUILD + COMMENT "Copying libsteam_api.dylib into ScreenPlay.app bundle." + COMMAND ${CMAKE_COMMAND} -E copy ${STEAM_LIB} + ${WORKSHOP_PLUGIN_DIR}) + endif() else() if(${SCREENPLAY_STEAM}) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/steam_appid.txt ${CMAKE_BINARY_DIR}/bin/steam_appid.txt COPYONLY) + configure_file(${STEAM_BIN} ${CMAKE_BINARY_DIR}/bin/ COPYONLY) endif() - configure_file(${STEAM_BIN} ${CMAKE_BINARY_DIR}/bin/ COPYONLY) endif() + + +# Needed by the automatic generated target missing includes +# https://github.com/qt/qtdeclarative/blob/7a7064e14f094e843e1ee832cc927e86f887621a/src/qml/Qt6QmlMacros.cmake#L2042 +target_include_directories(${PROJECT_NAME} PUBLIC src/) + +target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Quick ${STEAM_LIB} ScreenPlayUtil SteamSDK SteamSDKQtEnums) diff --git a/ScreenPlayWorkshop/SteamSDK/CMakeLists.txt b/ScreenPlayWorkshop/SteamSDK/CMakeLists.txt index f74286af..74e908c4 100644 --- a/ScreenPlayWorkshop/SteamSDK/CMakeLists.txt +++ b/ScreenPlayWorkshop/SteamSDK/CMakeLists.txt @@ -50,11 +50,17 @@ set(HEADER public/steam/steamps3params.h public/steam/steamtypes.h public/steam/steamuniverse.h - # CUSTOM - public/steam/steam_qt_enums_generated.h - # ENDCUSTOM ) -add_library(${PROJECT_NAME} STATIC ${HEADER}) -target_include_directories(${PROJECT_NAME} PUBLIC public/) -target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core) + +if(${SCREENPLAY_STEAM}) + add_library(${PROJECT_NAME} STATIC ${HEADER}) + target_include_directories(${PROJECT_NAME} PUBLIC public/) + target_link_libraries(${PROJECT_NAME}) +endif() + +# We allaways need the generated enums as a workaround to register these enums in app.cpp. +# Registering in the ScreenPlayWorkshop plugin does not work for some reason. +add_library(SteamSDKQtEnums STATIC public/steam/steam_qt_enums_generated.h) +target_include_directories(SteamSDKQtEnums PUBLIC public/) +target_link_libraries(SteamSDKQtEnums PRIVATE Qt6::Core) diff --git a/Tools/build.py b/Tools/build.py index a45a0591..e15e5a8a 100644 --- a/Tools/build.py +++ b/Tools/build.py @@ -45,7 +45,7 @@ if not args.build_type: print("Build type argument is missing (release,debug). Example: python build.py -t release -steam=True") sys.exit(1) -qt_version = "6.2.0" +qt_version = "6.2.1" steam_build = "OFF" if args.steam_build: if args.steam_build: