From 00bcdf8fca7494f1c8ae60f8062b9d810f31de1e Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Thu, 28 May 2020 15:27:35 +0200 Subject: [PATCH] Add a RAII wrapper around SetTimer() --- src/wine-host/editor.cpp | 9 +-------- src/wine-host/editor.h | 11 +++++++++++ src/wine-host/utils.cpp | 25 +++++++++++++++++++++++++ src/wine-host/utils.h | 23 +++++++++++++++++++++++ 4 files changed, 60 insertions(+), 8 deletions(-) diff --git a/src/wine-host/editor.cpp b/src/wine-host/editor.cpp index 1e329355..e316c3d6 100644 --- a/src/wine-host/editor.cpp +++ b/src/wine-host/editor.cpp @@ -79,19 +79,12 @@ Editor::Editor(const std::string& window_class_name, GetModuleHandle(nullptr), this), DestroyWindow), + idle_timer(win32_handle.get(), idle_timer_id, 100), parent_window(parent_window_handle), child_window(get_x11_handle(win32_handle.get())), topmost_window(find_topmost_window(*x11_connection, parent_window)), // Needed to send update messages on a timer plugin(effect) { - // The Win32 API will block the `DispatchMessage` call when opening e.g. a - // dropdown, but it will still allow timers to be run so the GUI can still - // update in the background. Because of this we send `effEditIdle` to the - // plugin on a timer. The refresh rate is purposely fairly low since the - // host will call `effEditIdle()` explicitely when the plugin is not busy. - // TODO: Add a `KillTimer()` now that we are hosting multiple plugins - SetTimer(win32_handle.get(), idle_timer_id, 100, nullptr); - // Because we're not using XEmbed Wine will interpret any local coordinates // as global coordinates. To work around this we'll tell the Wine window // it's located at its actual coordinates on screen rather than somewhere diff --git a/src/wine-host/editor.h b/src/wine-host/editor.h index 99c083e1..fb0a4198 100644 --- a/src/wine-host/editor.h +++ b/src/wine-host/editor.h @@ -32,6 +32,8 @@ #include #include +#include "utils.h" + /** * Used to store the maximum width and height of a screen. */ @@ -151,6 +153,15 @@ class Editor { win32_handle; private: + /** + * The Win32 API will block the `DispatchMessage` call when opening e.g. a + * dropdown, but it will still allow timers to be run so the GUI can still + * update in the background. Because of this we send `effEditIdle` to the + * plugin on a timer. The refresh rate is purposely fairly low since the + * host will call `effEditIdle()` explicitely when the plugin is not busy. + */ + Win32Timer idle_timer; + /** * The window handle of the editor window created by the DAW. */ diff --git a/src/wine-host/utils.cpp b/src/wine-host/utils.cpp index 0c9a5d62..1acac4d7 100644 --- a/src/wine-host/utils.cpp +++ b/src/wine-host/utils.cpp @@ -17,3 +17,28 @@ #include "utils.h" Win32Thread::Win32Thread() : handle(nullptr, nullptr) {} + +Win32Timer::Win32Timer(HWND window_handle, + size_t timer_id, + unsigned int interval_ms) + : window_handle(window_handle), timer_id(timer_id) { + SetTimer(window_handle, timer_id, interval_ms, nullptr); +} + +Win32Timer::~Win32Timer() { + if (timer_id.has_value()) { + KillTimer(window_handle, timer_id.value()); + } +} + +Win32Timer::Win32Timer(Win32Timer&& o) { + timer_id = o.timer_id; + o.timer_id = std::nullopt; +} + +Win32Timer& Win32Timer::operator=(Win32Timer&& o) { + timer_id = o.timer_id; + o.timer_id = std::nullopt; + + return *this; +} diff --git a/src/wine-host/utils.h b/src/wine-host/utils.h index 32c7e51b..e505cd1b 100644 --- a/src/wine-host/utils.h +++ b/src/wine-host/utils.h @@ -14,7 +14,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#pragma once + #include +#include #define NOMINMAX #define NOSERVICE @@ -71,3 +74,23 @@ class Win32Thread { std::unique_ptr, decltype(&CloseHandle)> handle; }; + +/** + * A simple RAII wrapper around `SetTimer`. Does not support timer procs since + * we don't use them. + */ +class Win32Timer { + public: + Win32Timer(HWND window_handle, size_t timer_id, unsigned int interval_ms); + ~Win32Timer(); + + Win32Timer(const Win32Timer&) = delete; + Win32Timer& operator=(const Win32Timer&) = delete; + + Win32Timer(Win32Timer&&); + Win32Timer& operator=(Win32Timer&&); + + private: + HWND window_handle; + std::optional timer_id; +};