-
-
Notifications
You must be signed in to change notification settings - Fork 95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to correctly handle external UI with scale factor #428
Comments
just use https://github.com/DISTRHO/DPF/blob/main/distrho/extra/ExternalWindow.hpp#L205 ? |
I tried const QSize& hint = fWidget->sizeHint();
UI::setWidth(hint.width() * getScaleFactor());
UI::setHeight(hint.height() * getScaleFactor()); The host window size is still small. |
did you log it to see if the scale factor is not 1? anyway sorting out the high-dpi needs to be a plugin-side thing, your code doesnt look right. the plugin needs to scale according to the host, not the other way around. |
then all is fine from DPF side. what you need here is to get the Qt side to apply the same. On Qt the size hints are merely hints, they do not set the size. Even the |
But the problem is: the "initial" window size is not fit with scale factors larger than 100%. (I have In my plugin, Qt UI is clipped by host. I want to change the host display size (not Qt itself). My effort in the code is to change the host display size. |
that is mostly already there. but in any case since you are using an external UI, you already have access to the display factor right on the |
Seems that APIs like The Qt window itself is created in the right scale factor. But the host window is not: still limited to its default size, and cannot be changed at runtime. What I want to change is the host display size itself, just the window below. |
this is not the right way to look at it. it is not the host that creates the window, we are. the UI size is defined on the plugin side, the host cannot dictate what the size is going to be. |
So how should I create the window with the right scale factor? Would you love to take a look at my code? Sounds like our window size is defined either by NOTE: Assume that the Qt widget window (not our DPF window) itself has fixed size. |
Ignore the After you have the Qt side scaling as needed then see about dynamically changing the size during runtime. |
Thanks! I'll try your methods mentioned above. |
Sounds like I have forgotten a critical thing: my project does not create window ( This is the init code in fWidget = std::make_unique<synthv1widget_dpf>(fDspInstance->getSynthesizer(), this);
m_widgetSize = fWidget->sizeHint();
m_widgetSize.setHeight(m_widgetSize.height() * getScaleFactor());
m_widgetSize.setWidth(m_widgetSize.width() * getScaleFactor());
fWidget->setMinimumSize(m_widgetSize);
// Explicitly set window position to avoid misplace on some platforms (especially Windows)
fWidget->move(0, 0);
// Embed plug-in UI into host window.
fParent = (WId) getParentWindowHandle();
fWinId = fWidget->winId(); // Must require WinID first, otherwise plug-in will crash!
if (fParent)
{
fWidget->windowHandle()->setParent(QWindow::fromWinId(fParent));
}
// Explicitly show UI. This is required when using external UI mode of DPF.
fWidget->show(); Does it have problem? Should I create a QWindow first, then set |
as far as I know the scale factor is a global Qt setting. I am closing the issue unless you can prove dpf is doing something wrong here, these details you need to figure them out by yourself. |
Now let's put Qt aside, and discuss the plugin window itself. The "plugin window" is the window created by plugin API (e.g. VST2's Seems that the discussions above had mistake the "window" as Qt window. I think DPF may need some improvements about creating plugin window in different scale factor. Let me describe it. In UI::UI(const uint width, const uint height, const bool automaticallyScaleAndSetAsMinimumSize)
: UIWidget(UI::PrivateData::createNextWindow(this,
#ifdef DISTRHO_UI_DEFAULT_WIDTH
width == 0 ? DISTRHO_UI_DEFAULT_WIDTH :
#endif
width,
#ifdef DISTRHO_UI_DEFAULT_HEIGHT
height == 0 ? DISTRHO_UI_DEFAULT_HEIGHT :
#endif
height,
#ifdef DISTRHO_UI_DEFAULT_WIDTH
width == 0
#else
false
#endif
)),
uiData(UI::PrivateData::s_nextPrivateData)
{
/* main code ... */
} I tried to set And, in function UI::PrivateData::createNextWindow(UI* const ui, uint width, uint height, const bool adjustForScaleFactor)
{
UI::PrivateData* const pData = s_nextPrivateData;
#if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
const double scaleFactor = d_isNotZero(pData->scaleFactor) ? pData->scaleFactor : getDesktopScaleFactor(pData->winId);
if (adjustForScaleFactor && d_isNotZero(scaleFactor) && d_isNotEqual(scaleFactor, 1.0))
{
width *= scaleFactor;
height *= scaleFactor;
}
pData->window = new PluginWindow(ui, pData->app);
ExternalWindow::PrivateData ewData;
ewData.parentWindowHandle = pData->winId;
ewData.width = width;
ewData.height = height;
ewData.scaleFactor = scaleFactor; But the plugin window creation seems to ignore the size assigned by For example, in VST2 case VST_EFFECT_OPCODE_WINDOW_GETRECT:
if (fVstUI != nullptr)
{
// =====================================================================
// If works well, fVstUI should be available, and get the right window size.
// =====================================================================
fVstRect.right = fVstUI->getWidth();
fVstRect.bottom = fVstUI->getHeight();
# ifdef DISTRHO_OS_MAC
const double scaleFactor = fVstUI->getScaleFactor();
fVstRect.right /= scaleFactor;
fVstRect.bottom /= scaleFactor;
# endif
}
else
{
// =====================================================================
// However, fVstUi is not available, so it fallback to DISTRHO_UI_DEFAULT_(WIDTH|HEIGHT).
// That's why I open this issue.
// =====================================================================
double scaleFactor = fLastScaleFactor;
#if defined(DISTRHO_UI_DEFAULT_WIDTH) && defined(DISTRHO_UI_DEFAULT_HEIGHT)
fVstRect.right = DISTRHO_UI_DEFAULT_WIDTH;
fVstRect.bottom = DISTRHO_UI_DEFAULT_HEIGHT;
if (d_isZero(scaleFactor))
scaleFactor = 1.0;
#else
UIExporter tmpUI(nullptr, 0, fPlugin.getSampleRate(),
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, d_nextBundlePath,
fPlugin.getInstancePointer(), scaleFactor);
fVstRect.right = tmpUI.getWidth();
fVstRect.bottom = tmpUI.getHeight();
scaleFactor = tmpUI.getScaleFactor();
tmpUI.quit();
#endif
#ifdef DISTRHO_OS_MAC
fVstRect.right /= scaleFactor;
fVstRect.bottom /= scaleFactor;
#endif
}
*(vst_rect**)ptr = &fVstRect;
return 1; Sounds like |
The external-ui does not make use of adjustForScaleFactor, because that is something that DPF tries to handle internally (scaling up the opengl/cairo context). This cannot be done automatically for external-uis since they are by their very nature external. The issue you are having is due to hosts asking for window size before creating the window, this is one of the targets of I think the best approach here is to code something as an example plugin that is simple and can be easily tested. |
Great idea! This will help developers who are interested in external UI.
However, by now the scale factor is not applied to initial window size. If it can apply scale factor correctly, my issue can be solved. Is it possible to modify the code in double scaleFactor = __A_FUNCTION_TO_GET_SYSTEM_SCALE_FACTOR__();
#if defined(DISTRHO_UI_DEFAULT_WIDTH) && defined(DISTRHO_UI_DEFAULT_HEIGHT)
if (d_isZero(scaleFactor))
scaleFactor = 1.0;
fVstRect.right = DISTRHO_UI_DEFAULT_WIDTH * scaleFactor;
fVstRect.bottom = DISTRHO_UI_DEFAULT_HEIGHT * scaleFactor;
if (fLastScaleFactor != scaleFactor)
fLastScaleFactor = scaleFactor;
BTW, as I described on the previous reply, by setting Here's my modification, to let initial window apply the scaled size (VST2 only) case VST_EFFECT_OPCODE_WINDOW_GETRECT:
if (fVstUI != nullptr)
{
fVstRect.right = fVstUI->getWidth();
fVstRect.bottom = fVstUI->getHeight();
# ifdef DISTRHO_OS_MAC
const double scaleFactor = fVstUI->getScaleFactor();
fVstRect.right /= scaleFactor;
fVstRect.bottom /= scaleFactor;
# endif
}
else
{
UIVst* tmpVstUI = new UIVst(fAudioMaster, fEffect, this, &fPlugin, (intptr_t)ptr, fLastScaleFactor);
if (tmpVstUI != nullptr) {
d_stderr(" Created temp VstUI. Size: (%d x %d)", tmpVstUI->getWidth(), tmpVstUI->getHeight());
fVstRect.right = tmpVstUI->getWidth();
fVstRect.bottom = tmpVstUI->getHeight();
delete tmpVstUI;
tmpVstUI = nullptr;
} else {
double scaleFactor = fLastScaleFactor;
#if defined(DISTRHO_UI_DEFAULT_WIDTH) && defined(DISTRHO_UI_DEFAULT_HEIGHT)
fVstRect.right = DISTRHO_UI_DEFAULT_WIDTH;
fVstRect.bottom = DISTRHO_UI_DEFAULT_HEIGHT;
if (d_isZero(scaleFactor))
scaleFactor = 1.0;
#else
UIExporter tmpUI(nullptr, 0, fPlugin.getSampleRate(),
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, d_nextBundlePath,
fPlugin.getInstancePointer(), scaleFactor);
fVstRect.right = tmpUI.getWidth();
fVstRect.bottom = tmpUI.getHeight();
scaleFactor = tmpUI.getScaleFactor();
tmpUI.quit();
#endif
}
#ifdef DISTRHO_OS_MAC
fVstRect.right /= scaleFactor;
fVstRect.bottom /= scaleFactor;
#endif
}
*(vst_rect**)ptr = &fVstRect;
return 1; BTW2, VST and VST3 seem to have APIs for adjusting window size on the plugin side. For example, Xhip synthesizer has VSTi edition. It makes use of an API to adjust window size dynamically. |
Hi, FalkTX!
I've migrated rncbc's synthv1 to DPF. It has a Qt-based UI. But it doesn't behave well on Windows 10, with 125% scale factor.
Just like this screenshot describes, REAPER's host window size is still at 100% scale factor, so the UI cannot be fully shown. All of VST2, VST3 and CLAP have this issue.
I've tried to set host window size on UI constructor, but in vain. Window size is still untouched:
UI::setWidth()
andUI::setHeight()
SetWindowPos()
:SetWindowPos((HWND)getParentWindowHandle(), HWND_TOP, 0, 0, 1800, 1000, SWP_NOMOVE);
QWindow::fromWinId()
to get parent window's QWindow instance, then callsetWidth()
andsetHeight()
I've also tried modifying
DISTRHO_UI_DEFAULT_WIDTH
andDISTRHO_UI_DEFAULT_HEIGHT
, but they are not flexible with different scale factors.So how can I solve this?
What's more,
setGeometryConstraints()
, andDISTRHO::UI
constructor paramautomaticallyScaleAndSetAsMinimumSize
do not work with external UI.The text was updated successfully, but these errors were encountered: