diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp index c0e5a0db..1e4bbfd3 100644 --- a/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp @@ -56,13 +56,13 @@ void ScreenPlayGodotWallpaper::hideFromTaskbar(HWND hwnd) bool ScreenPlayGodotWallpaper::configureWindowGeometry() { - if (!m_hook->searchWorkerWindowToParentTo()) { + if (!m_windowsIntegration->searchWorkerWindowToParentTo()) { UtilityFunctions::print("No worker window found"); return false; } // WARNING: Setting Window flags must be called *here*! - SetWindowLongPtr(m_hook->windowHandle, GWL_EXSTYLE, WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT); - SetWindowLongPtr(m_hook->windowHandle, GWL_STYLE, WS_POPUPWINDOW); + SetWindowLongPtr(m_windowsIntegration->windowHandle(), GWL_EXSTYLE, WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT); + SetWindowLongPtr(m_windowsIntegration->windowHandle(), GWL_STYLE, WS_POPUPWINDOW); return true; } @@ -72,23 +72,26 @@ bool ScreenPlayGodotWallpaper::init(int activeScreen) auto* displayServer = DisplayServer::get_singleton(); int64_t handle_int = displayServer->window_get_native_handle(godot::DisplayServer::HandleType::WINDOW_HANDLE, activeScreen); HWND hwnd = reinterpret_cast(static_cast(handle_int)); - m_hook = std::make_unique(); - m_hook->windowHandle = hwnd; + m_windowsIntegration = std::make_unique(); + m_windowsIntegration->setWindowHandle(hwnd); hideFromTaskbar(hwnd); if (!configureWindowGeometry()) { return false; } - ShowWindow(m_hook->windowHandle, SW_HIDE); + ShowWindow(m_windowsIntegration->windowHandle(), SW_HIDE); WindowsIntegration windowsIntegration; - auto updateWindowSize = [this, &displayServer](const int width, const int height) { + auto updateWindowSize = [&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); + + const std::optional monitor = windowsIntegration.setupWallpaperForOneScreen(activeScreen, updateWindowSize); + if (!monitor.has_value()) + return false; const std::string windowTitle = "ScreenPlayWallpaperGodot"; SetWindowText(hwnd, windowTitle.c_str()); - ShowWindow(m_hook->windowHandle, SW_SHOW); + ShowWindow(m_windowsIntegration->windowHandle(), SW_SHOW); return true; } @@ -194,14 +197,14 @@ bool ScreenPlayGodotWallpaper::exit() { // Somehow this gets called at editor startup // so just return if not initialized - if (m_hook) { + if (m_windowsIntegration) { - ShowWindow(m_hook->windowHandle, SW_HIDE); + ShowWindow(m_windowsIntegration->windowHandle(), SW_HIDE); // Force refresh so that we display the regular // desktop wallpaper again - ShowWindow(m_hook->windowHandleWorker, SW_SHOW); - ShowWindow(m_hook->windowHandleWorker, SW_HIDE); + ShowWindow(m_windowsIntegration->windowHandleWorker(), SW_SHOW); + ShowWindow(m_windowsIntegration->windowHandleWorker(), SW_HIDE); } return true; } diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.h b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.h index f735103f..08731d0c 100644 --- a/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.h +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.h @@ -62,7 +62,7 @@ private: godot::String m_appID = ""; godot::String m_projectPath = ""; - std::unique_ptr m_hook; + std::unique_ptr m_windowsIntegration; double m_timesinceLastRead = 0.0; bool m_pipeConnected = false; bool m_screenPlayConnected = false; diff --git a/ScreenPlayWallpaper/src/windowsintegration.cpp b/ScreenPlayWallpaper/src/windowsintegration.cpp index d8b71af2..ed51b7d6 100644 --- a/ScreenPlayWallpaper/src/windowsintegration.cpp +++ b/ScreenPlayWallpaper/src/windowsintegration.cpp @@ -1,14 +1,4 @@ #include "windowsintegration.h" -bool WindowsIntegration::searchWorkerWindowToParentTo() -{ - - HWND progman_hwnd = FindWindowW(L"Progman", L"Program Manager"); - const DWORD WM_SPAWN_WORKER = 0x052C; - SendMessageTimeoutW(progman_hwnd, WM_SPAWN_WORKER, 0xD, 0x1, SMTO_NORMAL, - 10000, nullptr); - - return EnumWindows(SearchForWorkerWindow, reinterpret_cast(&windowHandleWorker)); -} /*! \brief Returns scaling factor as reported by Windows. @@ -73,6 +63,15 @@ bool WindowsIntegration::hasWindowScaling() const return hasScaling; } +bool WindowsIntegration::searchWorkerWindowToParentTo() +{ + HWND progman_hwnd = FindWindowW(L"Progman", L"Program Manager"); + const DWORD WM_SPAWN_WORKER = 0x052C; + SendMessageTimeoutW(progman_hwnd, WM_SPAWN_WORKER, 0xD, 0x1, SMTO_NORMAL, + 10000, nullptr); + + return EnumWindows(SearchForWorkerWindow, reinterpret_cast(&m_windowHandleWorker)); +} /*! \brief Searches for the worker window for our window to parent to. */ @@ -140,7 +139,7 @@ bool WindowsIntegration::checkForFullScreenWindow(HWND windowHandle) * * 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, + * * In our scenario, we want to move and resize a window (`m_windowHandle`) 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: @@ -159,7 +158,7 @@ bool WindowsIntegration::checkForFullScreenWindow(HWND windowHandle) * scale factors. */ -std::optional WindowsIntegration::setupWallpaperForOneScreen(const int activeScreen, HWND windowHwnd, HWND parentWindowHwnd, std::function updateWindowSize) +std::optional WindowsIntegration::setupWallpaperForOneScreen(const int activeScreen, std::function updateWindowSize) { std::vector monitors = GetAllMonitors(); for (const auto& monitor : monitors) { @@ -167,7 +166,7 @@ std::optional WindowsIntegration::setupWallpaperForOneScreen(const int if (monitor.index != activeScreen) continue; - SetWindowPos(windowHwnd, HWND_TOP, + SetWindowPos(m_windowHandle, HWND_TOP, monitor.position.left, monitor.position.top, monitor.size.cx, monitor.size.cy, SWP_NOZORDER | SWP_NOACTIVATE); @@ -176,17 +175,17 @@ std::optional WindowsIntegration::setupWallpaperForOneScreen(const int updateWindowSize(monitor.size.cx, monitor.size.cy); RECT oldRect; - GetWindowRect(windowHwnd, &oldRect); + GetWindowRect(m_windowHandle, &oldRect); std::cout << "Old Window Position: (" << oldRect.left << ", " << oldRect.top << ")" << std::endl; - float windowDpiScaleFactor = static_cast(GetDpiForWindow(windowHwnd)) / 96.0f; + float windowDpiScaleFactor = static_cast(GetDpiForWindow(m_windowHandle)) / 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); + SetParent(m_windowHandle, m_windowHandleWorker); RECT parentRect; - GetWindowRect(parentWindowHwnd, &parentRect); + GetWindowRect(m_windowHandleWorker, &parentRect); std::cout << "WorkerW Window Position: (" << parentRect.left << ", " << parentRect.top << ")" << std::endl; int newX = static_cast((oldRect.left - parentRect.left) * (windowDpiScaleFactor / targetMonitorDpiScaleFactor)); @@ -197,7 +196,7 @@ std::optional WindowsIntegration::setupWallpaperForOneScreen(const int 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); + SetWindowPos(m_windowHandle, NULL, newX, newY, newWidth, newHeight, SWP_NOZORDER | SWP_NOACTIVATE); return { monitor }; } return std::nullopt; @@ -221,7 +220,7 @@ std::optional WindowsIntegration::setupWallpaperForOneScreen(const int * 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) +WindowsIntegration::SpanResult WindowsIntegration::setupWallpaperForMultipleScreens(const std::vector& activeScreens) { std::vector monitors = GetAllMonitors(); @@ -244,18 +243,18 @@ WindowsIntegration::SpanResult WindowsIntegration::setupWallpaperForMultipleScre int newHeight = bottommost - topmost; RECT oldRect; - GetWindowRect(windowHwnd, &oldRect); + GetWindowRect(m_windowHandle, &oldRect); - float windowDpiScaleFactor = static_cast(GetDpiForWindow(windowHwnd)) / 96.0f; + float windowDpiScaleFactor = static_cast(GetDpiForWindow(m_windowHandle)) / 96.0f; - SetParent(windowHwnd, parentWindowHwnd); + SetParent(m_windowHandle, m_windowHandleWorker); RECT parentRect; - GetWindowRect(parentWindowHwnd, &parentRect); + GetWindowRect(m_windowHandleWorker, &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); + SetWindowPos(m_windowHandle, NULL, newX, newY, newWidth, newHeight, SWP_NOZORDER | SWP_NOACTIVATE); SpanResult result; result.width = rightmost - leftmost; result.height = bottommost - topmost; @@ -281,7 +280,7 @@ WindowsIntegration::SpanResult WindowsIntegration::setupWallpaperForMultipleScre * @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) +WindowsIntegration::SpanResult WindowsIntegration::setupWallpaperForAllScreens() { std::vector monitors = GetAllMonitors(); @@ -304,19 +303,19 @@ WindowsIntegration::SpanResult WindowsIntegration::setupWallpaperForAllScreens(H 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); + SetWindowPos(m_windowHandle, 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); + GetWindowRect(m_windowHandle, &oldRect); + float windowDpiScaleFactor = static_cast(GetDpiForWindow(m_windowHandle)) / 96.0f; + SetParent(m_windowHandle, m_windowHandleWorker); RECT parentRect; - GetWindowRect(parentWindowHwnd, &parentRect); + GetWindowRect(m_windowHandleWorker, &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); + SetWindowPos(m_windowHandle, NULL, newX, newY, scaledWidth, scaledHeight, SWP_NOZORDER | SWP_NOACTIVATE); // Return the combined span of all monitors SpanResult result; @@ -327,6 +326,26 @@ WindowsIntegration::SpanResult WindowsIntegration::setupWallpaperForAllScreens(H return result; } +HWND WindowsIntegration::windowHandle() const +{ + return m_windowHandle; +} + +HWND WindowsIntegration::windowHandleWorker() const +{ + return m_windowHandleWorker; +} + +void WindowsIntegration::setWindowHandle(HWND windowHandle) +{ + m_windowHandle = windowHandle; +} + +void WindowsIntegration::setWindowHandleWorker(HWND windowHandleWorker) +{ + m_windowHandleWorker = windowHandleWorker; +} + BOOL GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { diff --git a/ScreenPlayWallpaper/src/windowsintegration.h b/ScreenPlayWallpaper/src/windowsintegration.h index 92301aa7..3c6525a3 100644 --- a/ScreenPlayWallpaper/src/windowsintegration.h +++ b/ScreenPlayWallpaper/src/windowsintegration.h @@ -83,11 +83,8 @@ struct sEnumInfo { HMONITOR hMonitor; }; -struct WindowsIntegration { - - HWND windowHandle {}; - HWND windowHandleWorker {}; - +class WindowsIntegration { +public: struct SpanResult { int width = 0; int height = 0; @@ -100,7 +97,15 @@ struct WindowsIntegration { 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); + std::optional setupWallpaperForOneScreen(const int activeScreen, std::function updateWindowSize); + SpanResult setupWallpaperForMultipleScreens(const std::vector& activeScreens); + SpanResult setupWallpaperForAllScreens(); + HWND windowHandle() const; + HWND windowHandleWorker() const; + void setWindowHandle(HWND windowHandle); + void setWindowHandleWorker(HWND windowHandleWorker); + +private: + HWND m_windowHandle {}; + HWND m_windowHandleWorker {}; }; diff --git a/ScreenPlayWallpaper/src/winwindow.cpp b/ScreenPlayWallpaper/src/winwindow.cpp index 9070a4e5..32867f5f 100644 --- a/ScreenPlayWallpaper/src/winwindow.cpp +++ b/ScreenPlayWallpaper/src/winwindow.cpp @@ -1,6 +1,5 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only #include "winwindow.h" -#include "ScreenPlayUtil/projectfile.h" #include "windowsintegration.h" #include #include @@ -124,8 +123,8 @@ ScreenPlay::WallpaperExitCode WinWindow::start() } m_windowsDesktopProperties = std::make_unique(); - m_windowHandle = reinterpret_cast(m_window.winId()); - if (!IsWindow(m_windowHandle)) { + m_windowsIntegration.setWindowHandle(reinterpret_cast(m_window.winId())); + if (!IsWindow(m_windowsIntegration.windowHandle())) { qCritical("Could not get a valid window handle!"); return ScreenPlay::WallpaperExitCode::Invalid_Start_Windows_HandleError; } @@ -160,12 +159,12 @@ ScreenPlay::WallpaperExitCode WinWindow::start() void WinWindow::setVisible(bool show) { if (show) { - if (!ShowWindow(m_windowHandle, SW_SHOW)) { + if (!ShowWindow(m_windowsIntegration.windowHandle(), SW_SHOW)) { qDebug() << "Cannot set window handle SW_SHOW"; } } else { - if (!ShowWindow(m_windowHandle, SW_HIDE)) { + if (!ShowWindow(m_windowsIntegration.windowHandle(), SW_HIDE)) { qDebug() << "Cannot set window handle SW_HIDE"; } } @@ -183,14 +182,13 @@ void WinWindow::destroyThis() void WinWindow::setupWallpaperForOneScreen(int activeScreen) { - WindowsIntegration windowsIntegration; 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 = m_windowsIntegration.setupWallpaperForOneScreen(activeScreen, updateWindowSize); } /*! @@ -198,8 +196,7 @@ void WinWindow::setupWallpaperForOneScreen(int activeScreen) */ void WinWindow::setupWallpaperForAllScreens() { - WindowsIntegration windowsIntegration; - WindowsIntegration::SpanResult span = windowsIntegration.setupWallpaperForAllScreens(m_windowHandle, m_windowHandleWorker); + WindowsIntegration::SpanResult span = m_windowsIntegration.setupWallpaperForAllScreens(); setWidth(span.width); setHeight(span.height); m_window.setWidth(width()); @@ -212,38 +209,30 @@ void WinWindow::setupWallpaperForAllScreens() void WinWindow::setupWallpaperForMultipleScreens(const QVector& activeScreensList) { std::vector activeScreens(activeScreensList.begin(), activeScreensList.end()); - WindowsIntegration windowsIntegration; - WindowsIntegration::SpanResult span = windowsIntegration.setupWallpaperForMultipleScreens(activeScreens, m_windowHandle, m_windowHandleWorker); + WindowsIntegration::SpanResult span = m_windowsIntegration.setupWallpaperForMultipleScreens(activeScreens); setWidth(span.width); setHeight(span.height); m_window.setWidth(width()); m_window.setHeight(height()); } -bool WinWindow::searchWorkerWindowToParentTo() -{ - - HWND progman_hwnd = FindWindowW(L"Progman", L"Program Manager"); - const DWORD WM_SPAWN_WORKER = 0x052C; - SendMessageTimeoutW(progman_hwnd, WM_SPAWN_WORKER, 0xD, 0x1, SMTO_NORMAL, - 10000, nullptr); - - return EnumWindows(SearchForWorkerWindow, reinterpret_cast(&m_windowHandleWorker)); -} - /*! \brief Sets the size and the parent to the worker handle to be displayed behind the desktop icons. */ void WinWindow::configureWindowGeometry() { - if (!searchWorkerWindowToParentTo()) { + if (!m_windowsIntegration.searchWorkerWindowToParentTo()) { qFatal("No worker window found"); } + if (!IsWindow(m_windowsIntegration.windowHandleWorker())) { + qCritical("Could not get a valid window handle wroker!"); + return; + } // WARNING: Setting Window flags must be called *here*! - SetWindowLongPtr(m_windowHandle, GWL_EXSTYLE, WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT); - SetWindowLongPtr(m_windowHandle, GWL_STYLE, WS_POPUP); + SetWindowLongPtr(m_windowsIntegration.windowHandle(), GWL_EXSTYLE, WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT); + SetWindowLongPtr(m_windowsIntegration.windowHandle(), GWL_STYLE, WS_POPUP); // Ether for one Screen or for all if ((QGuiApplication::screens().length() == activeScreensList().length()) && (activeScreensList().length() != 1)) { @@ -267,12 +256,12 @@ void WinWindow::terminate() if (type() != InstalledType::VideoWallpaper && type() != InstalledType::GifWallpaper) { UnhookWindowsHookEx(g_mouseHook); } - ShowWindow(m_windowHandle, SW_HIDE); + ShowWindow(m_windowsIntegration.windowHandle(), SW_HIDE); // Force refresh so that we display the regular // desktop wallpaper again - ShowWindow(m_windowHandleWorker, SW_HIDE); - ShowWindow(m_windowHandleWorker, SW_SHOW); + ShowWindow(m_windowsIntegration.windowHandleWorker(), SW_HIDE); + ShowWindow(m_windowsIntegration.windowHandleWorker(), SW_SHOW); QGuiApplication::quit(); } @@ -289,7 +278,7 @@ void WinWindow::clearComponentCache() void WinWindow::checkForFullScreenWindow() { - bool hasFullscreenWindow = WindowsIntegration().checkForFullScreenWindow(m_windowHandle); + bool hasFullscreenWindow = m_windowsIntegration.checkForFullScreenWindow(m_windowsIntegration.windowHandle()); setVisualsPaused(hasFullscreenWindow); } diff --git a/ScreenPlayWallpaper/src/winwindow.h b/ScreenPlayWallpaper/src/winwindow.h index 6e47a0b4..9ff712ec 100644 --- a/ScreenPlayWallpaper/src/winwindow.h +++ b/ScreenPlayWallpaper/src/winwindow.h @@ -18,6 +18,7 @@ #include "basewindow.h" #include "windowsdesktopproperties.h" +#include "windowsintegration.h" class WinWindow : public BaseWindow { Q_OBJECT @@ -53,7 +54,6 @@ private: void setupWallpaperForAllScreens(); void setupWallpaperForMultipleScreens(const QVector& activeScreensList); void setupWindowMouseHook(); - bool searchWorkerWindowToParentTo(); void configureWindowGeometry(); private slots: @@ -62,8 +62,7 @@ private slots: private: QPoint m_zeroPoint {}; QQuickView m_window; - HWND m_windowHandle {}; - HWND m_windowHandleWorker {}; + WindowsIntegration m_windowsIntegration; QTimer m_checkForFullScreenWindowTimer; QTimer m_reconfigureTimer; std::unique_ptr m_windowsDesktopProperties;