From 49fc896d62107dc28806570507412c0d75f6ec91 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sat, 19 Dec 2020 23:30:47 +0100 Subject: [PATCH] Remove Win32 effEditIdle() timer Now Editor is completely decoupled from VST2. --- src/wine-host/bridges/vst2.cpp | 8 ++++--- src/wine-host/editor.cpp | 44 ++++------------------------------ src/wine-host/editor.h | 43 +++++++-------------------------- 3 files changed, 19 insertions(+), 76 deletions(-) diff --git a/src/wine-host/bridges/vst2.cpp b/src/wine-host/bridges/vst2.cpp index 60b29992..623f4fa0 100644 --- a/src/wine-host/bridges/vst2.cpp +++ b/src/wine-host/bridges/vst2.cpp @@ -42,10 +42,12 @@ std::mutex current_bridge_instance_mutex; /** * Opcodes that should always be handled on the main thread because they may * involve GUI operations. + * + * XXX: We removed effEditIdle from here and everything still seems to work + * fine. Verify that this didn't break any plugins. */ const std::set unsafe_opcodes{effOpen, effClose, effEditGetRect, - effEditOpen, effEditClose, effEditIdle, - effEditTop}; + effEditOpen, effEditClose, effEditTop}; intptr_t VST_CALL_CONV host_callback_proxy(AEffect*, int, int, intptr_t, void*, float); @@ -391,7 +393,7 @@ intptr_t Vst2Bridge::dispatch_wrapper(AEffect* plugin, const std::string window_class = "yabridge plugin " + sockets.base_dir.string(); Editor& editor_instance = - editor.emplace(config, window_class, x11_handle, plugin); + editor.emplace(config, window_class, x11_handle); return plugin->dispatcher(plugin, opcode, index, value, editor_instance.get_win32_handle(), diff --git a/src/wine-host/editor.cpp b/src/wine-host/editor.cpp index da5234fe..1315b945 100644 --- a/src/wine-host/editor.cpp +++ b/src/wine-host/editor.cpp @@ -18,9 +18,6 @@ #include -// The Win32 API requires you to hardcode identifiers for tiemrs -constexpr size_t idle_timer_id = 1337; - /** * The most significant bit in an event's response type is used to indicate * whether the event source. @@ -84,8 +81,7 @@ WindowClass::~WindowClass() { Editor::Editor(const Configuration& config, const std::string& window_class_name, - const size_t parent_window_handle, - AEffect* effect) + const size_t parent_window_handle) : x11_connection(xcb_connect(nullptr, nullptr), xcb_disconnect), client_area(get_maximum_screen_dimensions(*x11_connection)), window_class(window_class_name), @@ -110,12 +106,10 @@ Editor::Editor(const Configuration& config, // If `config.editor_double_embed` is set, then we'll also create a child // window in `win32_child_handle`. If we do this before calling // `ShowWindow()` on `win32_handle` we'll run into X11 errors. - idle_timer(win32_handle.get(), idle_timer_id, 100), + win32_child_handle(std::nullopt), parent_window(parent_window_handle), wine_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) { + topmost_window(find_topmost_window(*x11_connection, parent_window)) { xcb_generic_error_t* error; // Used for input focus grabbing to only grab focus when the window is @@ -225,10 +219,6 @@ HWND Editor::get_win32_handle() const { } } -void Editor::send_idle_event() { - plugin->dispatcher(plugin, effEditIdle, 0, 0, nullptr, 0); -} - void Editor::handle_win32_events() const { MSG msg; @@ -236,21 +226,11 @@ void Editor::handle_win32_events() const { // with child GUI components. So far limiting this to `max_win32_messages` // messages has only been needed for Waves plugins as they otherwise cause // an infinite message loop. + // TODO: If the timer is no longer needed, then we can drop this entire + // function for (int i = 0; i < max_win32_messages && PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE); i++) { - // This timer would periodically send `effEditIdle` events so the editor - // remains responsive even during blocking GUI operations such as open - // dropdowns or message boxes. This is only needed when the GUI is - // actually blocked and it will be dispatched by the messaging loop of - // the blocking GUI component. Since we're not touching the - // `effEditIdle` event sent by the host we can always filter this timer - // event out in this event loop. - if (msg.message == WM_TIMER && msg.wParam == idle_timer_id && - msg.hwnd == win32_handle.get()) { - continue; - } - TranslateMessage(&msg); DispatchMessage(&msg); } @@ -470,20 +450,6 @@ LRESULT CALLBACK window_proc(HWND handle, SetWindowLongPtr(handle, GWLP_USERDATA, reinterpret_cast(editor)); } break; - case WM_TIMER: { - auto editor = reinterpret_cast( - GetWindowLongPtr(handle, GWLP_USERDATA)); - if (!editor || wParam != idle_timer_id) { - break; - } - - // We'll send idle messages on a timer. This way the plugin will get - // keep periodically updating its editor either when the host sends - // `effEditIdle` themself, or periodically when the GUI is being - // blocked by a dropdown or a message box. - editor->send_idle_event(); - return 0; - } break; // In case the WM does not support the EWMH active window property, // we'll fall back to grabbing focus when the user clicks on the window // by listening to the generated `WM_PARENTNOTIFY` messages. Otherwise diff --git a/src/wine-host/editor.h b/src/wine-host/editor.h index c75523c1..daccf194 100644 --- a/src/wine-host/editor.h +++ b/src/wine-host/editor.h @@ -16,22 +16,21 @@ #pragma once -// Use the native version of xcb -#pragma push_macro("_WIN32") -#undef _WIN32 -#include -#pragma pop_macro("_WIN32") +#include +#include +#include #ifndef NOMINMAX #define NOMINMAX #define WINE_NOWINSOCK #endif -#include #include -#include -#include -#include +// Use the native version of xcb +#pragma push_macro("_WIN32") +#undef _WIN32 +#include +#pragma pop_macro("_WIN32") #include "../common/configuration.h" #include "utils.h" @@ -101,15 +100,12 @@ class Editor { * windows. * @param parent_window_handle The X11 window handle passed by the VST host * for the editor to embed itself into. - * @param effect The plugin this window is being created for. Used to send - * `effEditIdle` messages on a timer. * * @see win32_handle */ Editor(const Configuration& config, const std::string& window_class_name, - const size_t parent_window_handle, - AEffect* effect); + const size_t parent_window_handle); ~Editor(); @@ -131,13 +127,6 @@ class Editor { */ bool supports_ewmh_active_window() const; - /** - * Send a single `effEditIdle` event to the plugin to allow it to update its - * GUI state. This is called periodically from a timer while the GUI is - * being blocked, and also called explicitly by the host on a timer. - */ - void send_idle_event(); - /** * Pump messages from the editor loop loop until all events are process. * Must be run from the same thread the GUI was created in because of Win32 @@ -225,15 +214,6 @@ class Editor { #pragma GCC diagnostic pop - /** - * 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. */ @@ -252,11 +232,6 @@ class Editor { */ const xcb_window_t topmost_window; - /** - *Needed to handle idle updates through a timer - */ - AEffect* plugin; - /** * The atom corresponding to `_NET_ACTIVE_WINDOW`. */