mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-06 19:40:10 +02:00
VST3: Fix broken resizing in Ardour
Adds timer_proc lambda for VST3 to check for size mismatches and trigger a new resize to correct it through eventual consistency. This is done to workaround an X11 sync issue where the plugin view would end up smaller or larger than its wrapper window. In Ardour this could result in the plugin becoming uninteractable.
This commit is contained in:
committed by
Robbert van der Helm
parent
945528cd7f
commit
604375b756
@@ -806,9 +806,38 @@ void Vst3Bridge::run() {
|
|||||||
initial_size.emplace(size.getWidth(),
|
initial_size.emplace(size.getWidth(),
|
||||||
size.getHeight());
|
size.getHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HACK: Create a resize watchdog that periodically
|
||||||
|
// verifies the wrapper window size matches the expected
|
||||||
|
// size. This works around VST3 resize issues (mostly)
|
||||||
|
// in Ardour during mutual recursion where X11
|
||||||
|
// operations may not be applied and the wrapper window
|
||||||
|
// remains smaller or larger than the wine window. The
|
||||||
|
// goal here is eventual consistency
|
||||||
|
auto resize_watchdog = [&instance = instance] {
|
||||||
|
if (instance.editor) {
|
||||||
|
if (const auto expected =
|
||||||
|
instance.editor
|
||||||
|
->check_size_mismatch()) {
|
||||||
|
// Resize the plugin view to propagate the
|
||||||
|
// target size everywhere.
|
||||||
|
if (instance.plug_view_instance) {
|
||||||
|
Steinberg::ViewRect rect{
|
||||||
|
0, 0,
|
||||||
|
(expected->width),
|
||||||
|
(expected->height)};
|
||||||
|
instance.plug_frame_proxy->resizeView(
|
||||||
|
instance.plug_view_instance
|
||||||
|
->plug_view,
|
||||||
|
&rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Editor& editor_instance = instance.editor.emplace(
|
Editor& editor_instance = instance.editor.emplace(
|
||||||
main_context_, config_, generic_logger_, x11_handle,
|
main_context_, config_, generic_logger_, x11_handle,
|
||||||
std::nullopt, initial_size);
|
std::move(resize_watchdog), initial_size);
|
||||||
const tresult result =
|
const tresult result =
|
||||||
instance.plug_view_instance->plug_view->attached(
|
instance.plug_view_instance->plug_view->attached(
|
||||||
editor_instance.win32_handle(), type.c_str());
|
editor_instance.win32_handle(), type.c_str());
|
||||||
|
|||||||
@@ -427,6 +427,34 @@ void Editor::resize(uint16_t width, uint16_t height) {
|
|||||||
wrapper_window_size_.height = height;
|
wrapper_window_size_.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<Size> Editor::check_size_mismatch() {
|
||||||
|
xcb_generic_error_t* error = nullptr;
|
||||||
|
const xcb_get_geometry_cookie_t cookie =
|
||||||
|
xcb_get_geometry(x11_connection_.get(), wrapper_window_.window_);
|
||||||
|
const std::unique_ptr<xcb_get_geometry_reply_t> geom(
|
||||||
|
xcb_get_geometry_reply(x11_connection_.get(), cookie, &error));
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
free(error);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (geom && (geom->width != wrapper_window_size_.width ||
|
||||||
|
geom->height != wrapper_window_size_.height)) {
|
||||||
|
logger_.log_editor_trace([&]() {
|
||||||
|
return "DEBUG: Size mismatch detected. Actual: " +
|
||||||
|
std::to_string(geom->width) + "x" +
|
||||||
|
std::to_string(geom->height) + ", Expected: " +
|
||||||
|
std::to_string(wrapper_window_size_.width) + "x" +
|
||||||
|
std::to_string(wrapper_window_size_.height);
|
||||||
|
});
|
||||||
|
|
||||||
|
return wrapper_window_size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
void Editor::show() noexcept {
|
void Editor::show() noexcept {
|
||||||
ShowWindow(win32_window_.handle_, SW_SHOWNORMAL);
|
ShowWindow(win32_window_.handle_, SW_SHOWNORMAL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,6 +204,15 @@ class Editor {
|
|||||||
*/
|
*/
|
||||||
void resize(uint16_t width, uint16_t height);
|
void resize(uint16_t width, uint16_t height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the wrapper window's actual X11 size matches the expected size.
|
||||||
|
* Returns the expected size if there's a mismatch, or nullopt if sizes
|
||||||
|
* match. This is used as a workaround for VST3 plugins where rapid
|
||||||
|
* resizing during mutual recursion can cause the X11 window to get stuck
|
||||||
|
* at an intermediate size.
|
||||||
|
*/
|
||||||
|
std::optional<Size> check_size_mismatch();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the window, should be called after the plugin has embedded itself.
|
* Show the window, should be called after the plugin has embedded itself.
|
||||||
* There's absolutely zero reason why this can't be done in the constructor,
|
* There's absolutely zero reason why this can't be done in the constructor,
|
||||||
|
|||||||
Reference in New Issue
Block a user