From 5d1051a00c0d84c7eefe44b82f2a0a3c8dd6f458 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Mon, 23 Mar 2020 22:19:49 +0100 Subject: [PATCH] Fix plugins not updating with dropdowns --- README.md | 5 +++-- src/wine-host/editor.cpp | 32 +++++++++++++++----------------- src/wine-host/plugin-bridge.h | 2 +- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 928a86f8..010d4f5a 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,9 @@ Yet Another way to use Windows VST2 plugins in Linux VST hosts. There are a few things that should be done before releasing this, including: - Implement missing features: - - GUIs. It mostly works right now, but there are a few small problems - remaining regarding window placement and child windows (i.e. droopdowns). + - GUIs. The only problem remaining is that child windows (such as dropdowns) + don't appear anchored to the reparented editor and will still appear in the + top left corner of the screen. - Add missing details if any to the architecture section. - Document what this has been tested on and what does or does not work. - Document wine32 support. diff --git a/src/wine-host/editor.cpp b/src/wine-host/editor.cpp index e1ef85f3..6d6a027b 100644 --- a/src/wine-host/editor.cpp +++ b/src/wine-host/editor.cpp @@ -78,10 +78,6 @@ bool Editor::embed_into(const size_t parent_window_handle) { return false; } - // TODO: Right now the child's child windows are not anchored to the window - // and do not receive keyboard focus. THis affects things like - // dropdowns. - // This follows the embedding procedure specified in the XEmbed sped: // https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html // under 'Embedding life cycle @@ -89,18 +85,7 @@ bool Editor::embed_into(const size_t parent_window_handle) { // a library const size_t child_window_handle = get_x11_handle().value(); - xcb_reparent_window(x11_connection.get(), child_window_handle, - parent_window_handle, 0, 0); - // Honestly, I'm not sure if all of this XEmbed stuff is even doing anything - - // This tells the WM that the parent window embedding and mapping/uumapping - // a child window. Requires the PROPERTY_NOTIFY event. - std::array xembed_info_values{xembed_protocol_version, 1}; - xcb_change_property(x11_connection.get(), XCB_PROP_MODE_REPLACE, - child_window_handle, xcb_xembed_info, xcb_xembed_info, - 32, 2, xembed_info_values.data()); - const int parent_events = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_STRUCTURE_NOTIFY; @@ -113,6 +98,16 @@ bool Editor::embed_into(const size_t parent_window_handle) { xcb_change_window_attributes(x11_connection.get(), child_window_handle, XCB_CW_EVENT_MASK, &child_events); + xcb_reparent_window(x11_connection.get(), child_window_handle, + parent_window_handle, 0, 0); + + // This tells the WM that the parent window embedding and mapping/uumapping + // a child window. Requires the PROPERTY_NOTIFY event. + std::array xembed_info_values{xembed_protocol_version, 1}; + xcb_change_property(x11_connection.get(), XCB_PROP_MODE_REPLACE, + child_window_handle, xcb_xembed_info, xcb_xembed_info, + 32, 2, xembed_info_values.data()); + // Tell the window from Wine it's embedded into the window provided by the // host send_xembed_event(child_window_handle, xembed_embedded_notify_msg, 0, @@ -125,7 +120,7 @@ bool Editor::embed_into(const size_t parent_window_handle) { xcb_map_window(x11_connection.get(), child_window_handle); xcb_flush(x11_connection.get()); - ShowWindow(win32_handle->get(), SW_SHOW); + ShowWindow(win32_handle->get(), SW_SHOWNORMAL); return true; } @@ -135,7 +130,10 @@ void Editor::handle_events() { // the window if (win32_handle.has_value()) { MSG msg; - while (PeekMessage(&msg, win32_handle->get(), 0, 0, PM_REMOVE)) { + // The second argument has to be null since we not only want to handle + // events for this window but also for all child windows (i.e. + // dropdowns). I spent way longer debugging this than I want to admit. + while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } diff --git a/src/wine-host/plugin-bridge.h b/src/wine-host/plugin-bridge.h index ac6fc697..3400cbfb 100644 --- a/src/wine-host/plugin-bridge.h +++ b/src/wine-host/plugin-bridge.h @@ -124,7 +124,7 @@ class PluginBridge { */ std::thread parameters_handler; /** - * The t thread that handles calls to `processReplacing` (and `process`). + * The thread that handles calls to `processReplacing` (and `process`). */ std::thread process_replacing_handler;