diff --git a/idd/LGIddHelper/CNotifyWindow.cpp b/idd/LGIddHelper/CNotifyWindow.cpp index f6b69be2..f1497335 100644 --- a/idd/LGIddHelper/CNotifyWindow.cpp +++ b/idd/LGIddHelper/CNotifyWindow.cpp @@ -106,8 +106,15 @@ LRESULT CNotifyWindow::handleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) return 0; case WM_NO_GPU: - handleGPUNotification((bool)wParam); + { + m_gpuNotificationQueued.store(false, std::memory_order_release); + const int status = m_pendingGPUStatus.exchange( + -1, std::memory_order_acq_rel); + if (status >= 0) + handleGPUNotification(status != 0); + queueGPUNotification(); return 0; + } case WM_RESOLUTION_REJECTED: { @@ -174,6 +181,7 @@ LRESULT CNotifyWindow::onClose() LRESULT CNotifyWindow::onDestroy() { + m_iconRegistered.store(false, std::memory_order_release); if (m_clipboard) m_clipboard->Shutdown(); KillTimer(m_hwnd, ID_DISPLAY_CHECK_TIMER); @@ -235,27 +243,40 @@ void CNotifyWindow::registerIcon() return; } - m_iconRegistered = true; + m_iconRegistered.store(true, std::memory_order_release); if (!Shell_NotifyIcon(NIM_SETVERSION, &m_iconData)) DEBUG_ERROR_HR(GetLastError(), "Shell_NotifyIcon(NIM_SETVERSION)"); - if (m_gpuQueue) - { - handleGPUNotification(*m_gpuQueue); - m_gpuQueue.reset(); - } + queueGPUNotification(); } void CNotifyWindow::setGPU(bool hasGPU) { - if (m_iconRegistered) - PostMessage(m_hwnd, WM_NO_GPU, hasGPU, 0); - else - m_gpuQueue.emplace(hasGPU); + m_pendingGPUStatus.store(hasGPU ? 1 : 0, std::memory_order_release); + queueGPUNotification(); +} + +void CNotifyWindow::queueGPUNotification() +{ + if (!m_iconRegistered.load(std::memory_order_acquire) || + m_pendingGPUStatus.load(std::memory_order_acquire) < 0 || + m_gpuNotificationQueued.exchange(true, std::memory_order_acq_rel)) + return; + + if (!PostMessage(m_hwnd, WM_NO_GPU, 0, 0)) + { + m_gpuNotificationQueued.store(false, std::memory_order_release); + DEBUG_ERROR_HR(GetLastError(), "Failed to queue GPU status notification"); + } } void CNotifyWindow::handleGPUNotification(bool hasGPU) { + const bool notifyNoGPU = !hasGPU && + (!m_gpuStatusKnown || m_hasGPU); + m_gpuStatusKnown = true; + m_hasGPU = hasGPU; + StringCbCopy(m_iconData.szTip, sizeof m_iconData.szTip, hasGPU ? L"Looking Glass (IDD) with GPU acceleration" : L"Looking Glass (IDD) with software rendering"); @@ -271,7 +292,7 @@ void CNotifyWindow::handleGPUNotification(bool hasGPU) return; } - if (hasGPU) + if (hasGPU || !notifyNoGPU) return; CRegistrySettings settings; diff --git a/idd/LGIddHelper/CNotifyWindow.h b/idd/LGIddHelper/CNotifyWindow.h index 41425a28..a8919c48 100644 --- a/idd/LGIddHelper/CNotifyWindow.h +++ b/idd/LGIddHelper/CNotifyWindow.h @@ -24,7 +24,6 @@ #include #include #include -#include class CConfigWindow; class CClipboardChannel; @@ -36,8 +35,11 @@ class CNotifyWindow : public CWindow static ATOM s_atom; NOTIFYICONDATA m_iconData; - bool m_iconRegistered; - std::optional m_gpuQueue; + std::atomic_bool m_iconRegistered; + std::atomic_int m_pendingGPUStatus { -1 }; + std::atomic_bool m_gpuNotificationQueued { false }; + bool m_gpuStatusKnown = false; + bool m_hasGPU = false; HMENU m_menu; std::atomic_bool closeRequested; bool m_recoveryActive; @@ -49,6 +51,7 @@ class CNotifyWindow : public CWindow LRESULT onNotifyIcon(UINT uEvent, WORD wIconId, int x, int y); void registerIcon(); + void queueGPUNotification(); void handleGPUNotification(bool hasGPU); void handleResolutionRejected(uint32_t width, uint32_t height, uint32_t requiredSizeMiB);