From b2db9cc0a6266bef99787579e88b8602b6e7883b Mon Sep 17 00:00:00 2001 From: Asahi Lina Date: Thu, 22 May 2025 11:38:22 +0900 Subject: [PATCH] VST3: Add HiDPI scaling hack Sometimes the plugin size might be off-by-one due to HiDPI scaling. If so, pretend it's actually the size that was requested, to avoid ending up in an infinite loop. --- src/wine-host/bridges/vst3.cpp | 20 ++++++++++++++++++-- src/wine-host/bridges/vst3.h | 8 ++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/wine-host/bridges/vst3.cpp b/src/wine-host/bridges/vst3.cpp index 777a76a1..35d59cce 100644 --- a/src/wine-host/bridges/vst3.cpp +++ b/src/wine-host/bridges/vst3.cpp @@ -899,8 +899,22 @@ void Vst3Bridge::run() { get_instance(request.owner_instance_id); std::lock_guard lock(instance.get_size_mutex); - return instance.plug_view_instance->plug_view->getSize( - &size); + auto result = + instance.plug_view_instance->plug_view->getSize( + &size); + // HACK: Sometimes, due to HiDPI scaling, plugins might + // end up with a size that is off by one pixel + // from the requested size. To avoid ending up in + // an infinite loop, just return the size that the + // host requested in this case. + if (result == Steinberg::kResultOk && + abs(size.getWidth() - + instance.last_set_size.getWidth()) <= 1 && + abs(size.getHeight() - + instance.last_set_size.getHeight()) <= 1) { + size = instance.last_set_size; + } + return result; }); return YaPlugView::GetSizeResponse{.result = result, @@ -934,6 +948,8 @@ void Vst3Bridge::run() { request.new_size.getHeight()); } + instance.last_set_size = request.new_size; + return result; }); }, diff --git a/src/wine-host/bridges/vst3.h b/src/wine-host/bridges/vst3.h index 1b1ef271..75054893 100644 --- a/src/wine-host/bridges/vst3.h +++ b/src/wine-host/bridges/vst3.h @@ -256,6 +256,14 @@ struct Vst3PluginInstance { * processing. */ std::optional process_setup; + + /** + * The last size that was set with onSize(). We use this to fudge the + * return value of getSize() if it is off by one pixel, which can happen + * due to HiDPI rounding. Otherwise, DAWs like Ardour might go into an + * infinite loop trying to adjust the size to a specific target. + */ + Steinberg::ViewRect last_set_size; }; /**