Defer Win32 window closing

This gets rid of all potential delays when closing windows.
This commit is contained in:
Robbert van der Helm
2020-12-31 14:18:26 +01:00
parent fa0753f520
commit 5f8926f8ae
3 changed files with 31 additions and 21 deletions
+4
View File
@@ -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
+16 -18
View File
@@ -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<std::remove_pointer_t<HWND>,
decltype(&DestroyWindow)>(
CreateWindowEx(WS_EX_TOOLWINDOW,
reinterpret_cast<LPCSTR>(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<std::remove_pointer_t<HWND>,
decltype(&destroy_window_async)>(
CreateWindowEx(WS_EX_TOOLWINDOW,
reinterpret_cast<LPCSTR>(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;
+11 -3
View File
@@ -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<std::remove_pointer_t<HWND>, decltype(&DestroyWindow)>
std::unique_ptr<std::remove_pointer_t<HWND>,
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<std::remove_pointer_t<HWND>, decltype(&DestroyWindow)>>
std::optional<std::unique_ptr<std::remove_pointer_t<HWND>,
decltype(&destroy_window_async)>>
win32_child_handle;
#pragma GCC diagnostic pop