diff --git a/CHANGELOG.md b/CHANGELOG.md index 38cad5c9..ded007a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,10 @@ TODO: Add an updated screenshot with some fancy VST3-only plugins to the readme - Slightly increased resposniveness when resizing plugin GUIs by preventing unnecessary blitting. This also reduces flickering with plugins that don't do double buffering. +- Window closing is now deferred. This means that when closing the editor + window, the host no longer has to wait for Wine to fully close the window. + Most hosts already do something similar themselves, so this may not make any + difference in responsiveness. - VST2 editor idle events are now handled slightly differently. This should result in even more responsive GUIs and I have not come across any plugins where this change introduced issues, but please let me know if it does break diff --git a/src/wine-host/editor.cpp b/src/wine-host/editor.cpp index 073b08eb..2d64c283 100644 --- a/src/wine-host/editor.cpp +++ b/src/wine-host/editor.cpp @@ -123,7 +123,7 @@ Editor::Editor(const Configuration& config, const size_t parent_window_handle) nullptr, GetModuleHandle(nullptr), this), - DestroyWindow), + destroy_window_async), // 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. @@ -213,15 +213,17 @@ Editor::Editor(const Configuration& config, const size_t parent_window_handle) #pragma GCC diagnostic ignored "-Wignored-attributes" // As explained above, we can't do this directly in the initializer // list - win32_child_handle = std::unique_ptr, - decltype(&DestroyWindow)>( - CreateWindowEx(WS_EX_TOOLWINDOW, - reinterpret_cast(window_class.atom), - "yabridge plugin child", WS_CHILD, CW_USEDEFAULT, - CW_USEDEFAULT, client_area.width, - client_area.height, win32_handle.get(), nullptr, - GetModuleHandle(nullptr), this), - DestroyWindow); + win32_child_handle = + std::unique_ptr, + decltype(&destroy_window_async)>( + CreateWindowEx(WS_EX_TOOLWINDOW, + reinterpret_cast(window_class.atom), + "yabridge plugin child", WS_CHILD, + CW_USEDEFAULT, CW_USEDEFAULT, + client_area.width, client_area.height, + win32_handle.get(), nullptr, + GetModuleHandle(nullptr), this), + destroy_window_async); #pragma GCC diagnostic pop ShowWindow(win32_child_handle->get(), SW_SHOWNORMAL); @@ -250,14 +252,6 @@ Editor::~Editor() { xcb_reparent_window(x11_connection.get(), wine_window, root, 0, 0); xcb_flush(x11_connection.get()); - - // FIXME: I have no idea why, but for some reason the window still hangs - // some of the times without manually resetting the - // `std::unique_ptr`` to the window handle` (which calls - // `DestroyWindow()`), even though the behavior should be identical - // without this line. - win32_child_handle.reset(); - win32_handle.reset(); } HWND Editor::get_win32_handle() const { @@ -419,6 +413,10 @@ void Editor::set_input_focus(bool grab) const { xcb_flush(x11_connection.get()); } +void Editor::destroy_window_async(HWND window_handle) { + PostMessage(window_handle, WM_CLOSE, 0, 0); +} + bool Editor::is_wine_window_active() const { if (!supports_ewmh_active_window()) { return false; diff --git a/src/wine-host/editor.h b/src/wine-host/editor.h index 6d6826c1..1e61c631 100644 --- a/src/wine-host/editor.h +++ b/src/wine-host/editor.h @@ -154,6 +154,13 @@ class Editor { const bool use_xembed; private: + /** + * Post a message to this window's message queue to clean up the window. + * This way we don't have to wait for the window to actually fully close + * before returning. + */ + static void destroy_window_async(HWND window_handle); + /** * Returns `true` if the currently active window (as per * `_NET_ACTIVE_WINDOW`) contains `wine_window`. If the window manager does @@ -211,7 +218,8 @@ class Editor { * The handle for the window created through Wine that the plugin uses to * embed itself in. */ - std::unique_ptr, decltype(&DestroyWindow)> + std::unique_ptr, + decltype(&destroy_window_async)> win32_handle; /** @@ -222,8 +230,8 @@ class Editor { * of the readme for more details). The plugin should then embed itself * within this child window. */ - std::optional< - std::unique_ptr, decltype(&DestroyWindow)>> + std::optional, + decltype(&destroy_window_async)>> win32_child_handle; #pragma GCC diagnostic pop