commit 3a84bbb3ebbba9a02a36e65a0048f767f8b5cbd0
parent 96aa685d38522a6674ba1adf30efc4c213f9c272
Author: falkTX <falktx@falktx.com>
Date: Tue, 27 Feb 2024 12:47:20 +0100
Special case for repainting on AU hosts
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
10 files changed, 102 insertions(+), 26 deletions(-)
diff --git a/dgl/Window.hpp b/dgl/Window.hpp
@@ -545,6 +545,7 @@ private:
uint height,
double scaleFactor,
bool resizable,
+ bool usesScheduledRepaints,
bool usesSizeRequest,
bool doPostInit);
diff --git a/dgl/src/ApplicationPrivateData.cpp b/dgl/src/ApplicationPrivateData.cpp
@@ -23,6 +23,7 @@
START_NAMESPACE_DGL
+typedef std::list<DGL_NAMESPACE::Window*>::iterator WindowListIterator;
typedef std::list<DGL_NAMESPACE::Window*>::reverse_iterator WindowListReverseIterator;
static d_ThreadHandle getCurrentThreadHandle() noexcept
@@ -59,6 +60,7 @@ Application::PrivateData::PrivateData(const bool standalone)
isQuitting(false),
isQuittingInNextCycle(false),
isStarting(true),
+ needsRepaint(false),
visibleWindows(0),
mainThreadHandle(getCurrentThreadHandle()),
windows(),
@@ -144,6 +146,20 @@ void Application::PrivateData::triggerIdleCallbacks()
}
}
+void Application::PrivateData::repaintIfNeeeded()
+{
+ if (needsRepaint)
+ {
+ needsRepaint = false;
+
+ for (WindowListIterator it = windows.begin(), ite = windows.end(); it != ite; ++it)
+ {
+ DGL_NAMESPACE::Window* const window(*it);
+ window->repaint();
+ }
+ }
+}
+
void Application::PrivateData::quit()
{
if (! isThisTheMainThread(mainThreadHandle))
diff --git a/dgl/src/ApplicationPrivateData.hpp b/dgl/src/ApplicationPrivateData.hpp
@@ -63,6 +63,9 @@ struct Application::PrivateData {
/** Whether the applicating is starting up, that is, no windows have been made visible yet. Defaults to true. */
bool isStarting;
+ /** When true force all windows to be repainted on next idle. */
+ bool needsRepaint;
+
/** Counter of visible windows, only used in standalone mode.
If 0->1, application is starting. If 1->0, application is quitting/stopping. */
uint visibleWindows;
@@ -96,6 +99,9 @@ struct Application::PrivateData {
/** Run each idle callback without updating pugl world. */
void triggerIdleCallbacks();
+ /** Trigger a repaint of all windows if @a needsRepaint is true. */
+ void repaintIfNeeeded();
+
/** Set flag indicating application is quitting, and close all windows in reverse order of registration.
For standalone mode only. */
void quit();
diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp
@@ -106,7 +106,7 @@ Window::Window(Application& app,
const uint height,
const double scaleFactor,
const bool resizable)
- : pData(new PrivateData(app, this, parentWindowHandle, width, height, scaleFactor, resizable, false))
+ : pData(new PrivateData(app, this, parentWindowHandle, width, height, scaleFactor, resizable, false, false))
{
pData->initPost();
}
@@ -117,9 +117,11 @@ Window::Window(Application& app,
const uint height,
const double scaleFactor,
const bool resizable,
- const bool isVST3,
+ const bool usesScheduledRepaints,
+ const bool usesSizeRequest,
const bool doPostInit)
- : pData(new PrivateData(app, this, parentWindowHandle, width, height, scaleFactor, resizable, isVST3))
+ : pData(new PrivateData(app, this, parentWindowHandle, width, height, scaleFactor, resizable,
+ usesScheduledRepaints, usesSizeRequest))
{
if (doPostInit)
pData->initPost();
@@ -411,8 +413,13 @@ bool Window::openFileBrowser(const FileBrowserOptions& options)
void Window::repaint() noexcept
{
- if (pData->view != nullptr)
- puglPostRedisplay(pData->view);
+ if (pData->view == nullptr)
+ return;
+
+ if (pData->usesScheduledRepaints)
+ pData->appData->needsRepaint = true;
+
+ puglPostRedisplay(pData->view);
}
void Window::repaint(const Rectangle<uint>& rect) noexcept
@@ -420,6 +427,9 @@ void Window::repaint(const Rectangle<uint>& rect) noexcept
if (pData->view == nullptr)
return;
+ if (pData->usesScheduledRepaints)
+ pData->appData->needsRepaint = true;
+
PuglRect prect = {
static_cast<PuglCoord>(rect.getX()),
static_cast<PuglCoord>(rect.getY()),
diff --git a/dgl/src/WindowPrivateData.cpp b/dgl/src/WindowPrivateData.cpp
@@ -115,6 +115,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s)
isClosed(true),
isVisible(false),
isEmbed(false),
+ usesScheduledRepaints(false),
usesSizeRequest(false),
scaleFactor(DGL_NAMESPACE::getScaleFactor(view)),
autoScaling(false),
@@ -144,6 +145,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, PrivateData* c
isClosed(true),
isVisible(false),
isEmbed(false),
+ usesScheduledRepaints(false),
usesSizeRequest(false),
scaleFactor(ppData->scaleFactor),
autoScaling(false),
@@ -175,6 +177,7 @@ Window::PrivateData::PrivateData(Application& a, Window* const s,
isClosed(parentWindowHandle == 0),
isVisible(parentWindowHandle != 0),
isEmbed(parentWindowHandle != 0),
+ usesScheduledRepaints(false),
usesSizeRequest(false),
scaleFactor(scale != 0.0 ? scale : DGL_NAMESPACE::getScaleFactor(view)),
autoScaling(false),
@@ -198,7 +201,9 @@ Window::PrivateData::PrivateData(Application& a, Window* const s,
Window::PrivateData::PrivateData(Application& a, Window* const s,
const uintptr_t parentWindowHandle,
const uint width, const uint height,
- const double scale, const bool resizable, const bool usesSizeRequest_)
+ const double scale, const bool resizable,
+ const bool _usesScheduledRepaints,
+ const bool _usesSizeRequest)
: app(a),
appData(a.pData),
self(s),
@@ -207,7 +212,8 @@ Window::PrivateData::PrivateData(Application& a, Window* const s,
isClosed(parentWindowHandle == 0),
isVisible(parentWindowHandle != 0 && view != nullptr),
isEmbed(parentWindowHandle != 0),
- usesSizeRequest(usesSizeRequest_),
+ usesScheduledRepaints(_usesScheduledRepaints),
+ usesSizeRequest(_usesSizeRequest),
scaleFactor(scale != 0.0 ? scale : DGL_NAMESPACE::getScaleFactor(view)),
autoScaling(false),
autoScaleFactor(1.0),
diff --git a/dgl/src/WindowPrivateData.hpp b/dgl/src/WindowPrivateData.hpp
@@ -60,7 +60,10 @@ struct Window::PrivateData : IdleCallback {
/** Whether this Window is embed into another (usually not DGL-controlled) Window. */
const bool isEmbed;
- /** Whether to ignore resize requests and feed them into the host instead. used for VST3 */
+ /** Whether to schedule repaints on the next idle call, used for AU */
+ const bool usesScheduledRepaints;
+
+ /** Whether to ignore resize requests and feed them into the host instead, used for CLAP and VST3 */
const bool usesSizeRequest;
/** Scale factor to report to widgets on request, purely informational. */
@@ -131,7 +134,8 @@ struct Window::PrivateData : IdleCallback {
/** Constructor for an embed Window, with a few extra hints from the host side. */
explicit PrivateData(Application& app, Window* self, uintptr_t parentWindowHandle,
- uint width, uint height, double scaling, bool resizable, bool isVST3);
+ uint width, uint height, double scaling, bool resizable,
+ bool usesScheduledRepaints, bool usesSizeRequest);
/** Destructor. */
~PrivateData() override;
diff --git a/distrho/src/DistrhoUIAU.mm b/distrho/src/DistrhoUIAU.mm
@@ -155,12 +155,17 @@ public:
void postSetup()
{
- const NSSize size = NSMakeSize(fUI.getWidth(), fUI.getHeight());
+ const double scaleFactor = fUI.getScaleFactor();
+ const NSSize size = NSMakeSize(fUI.getWidth() / scaleFactor, fUI.getHeight() / scaleFactor);
NSView* const uiView = reinterpret_cast<NSView*>(fUI.getNativeWindowHandle());
- [fParentView setAutoresizesSubviews:fUI.isResizable()];
- [fParentView setFrameSize:size];
+ for (NSView* subview in [uiView subviews])
+ {
+ [subview setFrameSize:size];
+ break;
+ }
[uiView setFrameSize:size];
+ [fParentView setFrameSize:size];
}
private:
@@ -362,7 +367,8 @@ private:
void setSize(const uint width, const uint height)
{
- [fParentView setFrameSize:NSMakeSize(width, height)];
+ const double scaleFactor = fUI.getScaleFactor();
+ [fParentView setFrameSize:NSMakeSize(width / scaleFactor, height / scaleFactor)];
}
static void setSizeCallback(void* const ptr, const uint width, const uint height)
@@ -396,7 +402,7 @@ END_NAMESPACE_DISTRHO
- (id) initWithPreferredSize:(NSSize)size
{
- self = [super initWithFrame: NSMakeRect (0, 0, size.width, size.height)];
+ self = [super initWithFrame: NSMakeRect(0, 0, size.width, size.height)];
[self setHidden:NO];
return self;
}
@@ -467,8 +473,7 @@ END_NAMESPACE_DISTRHO
#endif
#if defined(DISTRHO_UI_DEFAULT_WIDTH) && defined(DISTRHO_UI_DEFAULT_HEIGHT)
- const double scaleFactor = [NSScreen mainScreen].backingScaleFactor;
- inPreferredSize = NSMakeSize(DISTRHO_UI_DEFAULT_WIDTH * scaleFactor, DISTRHO_UI_DEFAULT_HEIGHT * scaleFactor);
+ inPreferredSize = NSMakeSize(DISTRHO_UI_DEFAULT_WIDTH, DISTRHO_UI_DEFAULT_HEIGHT);
#endif
// create view
diff --git a/distrho/src/DistrhoUIInternal.hpp b/distrho/src/DistrhoUIInternal.hpp
@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
- * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com>
+ * Copyright (C) 2012-2024 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -232,6 +232,7 @@ public:
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, );
ui->uiIdle();
+ uiData->app.repaintIfNeeeded();
}
void showAndFocus()
@@ -247,6 +248,7 @@ public:
uiData->app.idle();
ui->uiIdle();
+ uiData->app.repaintIfNeeeded();
return ! uiData->app.isQuitting();
}
@@ -277,6 +279,7 @@ public:
uiData->app.triggerIdleCallbacks();
ui->uiIdle();
+ uiData->app.repaintIfNeeeded();
}
#if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
diff --git a/distrho/src/DistrhoUIPrivateData.hpp b/distrho/src/DistrhoUIPrivateData.hpp
@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
- * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com>
+ * Copyright (C) 2012-2024 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -43,13 +43,19 @@
# define DISTRHO_UI_IS_STANDALONE 0
#endif
+#if defined(DISTRHO_PLUGIN_TARGET_AU)
+# define DISTRHO_UI_USES_SCHEDULED_REPAINTS true
+#else
+# define DISTRHO_UI_USES_SCHEDULED_REPAINTS false
+#endif
+
#if defined(DISTRHO_PLUGIN_TARGET_VST3) || defined(DISTRHO_PLUGIN_TARGET_CLAP)
# define DISTRHO_UI_USES_SIZE_REQUEST true
#else
# define DISTRHO_UI_USES_SIZE_REQUEST false
#endif
-#ifdef DISTRHO_PLUGIN_TARGET_VST2
+#if defined(DISTRHO_PLUGIN_TARGET_AU) || defined(DISTRHO_PLUGIN_TARGET_VST2)
# undef DISTRHO_UI_USER_RESIZABLE
# define DISTRHO_UI_USER_RESIZABLE 0
#endif
@@ -103,6 +109,7 @@ struct PluginApplication
void idle() {}
void quit() {}
void triggerIdleCallbacks() {}
+ void repaintIfNeeeded() {}
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginApplication)
};
@@ -137,6 +144,11 @@ public:
pData->triggerIdleCallbacks();
}
+ void repaintIfNeeeded()
+ {
+ pData->repaintIfNeeeded();
+ }
+
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginApplication)
};
#endif
@@ -194,7 +206,10 @@ public:
const uint height,
const double scaleFactor)
: Window(app, parentWindowHandle, width, height, scaleFactor,
- DISTRHO_UI_USER_RESIZABLE, DISTRHO_UI_USES_SIZE_REQUEST, false),
+ DISTRHO_UI_USER_RESIZABLE,
+ DISTRHO_UI_USES_SCHEDULED_REPAINTS,
+ DISTRHO_UI_USES_SIZE_REQUEST,
+ false),
ui(uiPtr),
initializing(true),
receivedReshapeDuringInit(false)
diff --git a/examples/Info/InfoExampleUI.cpp b/examples/Info/InfoExampleUI.cpp
@@ -1,6 +1,6 @@
/*
* DISTRHO Plugin Framework (DPF)
- * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
+ * Copyright (C) 2012-2024 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -38,13 +38,23 @@ public:
std::memset(fParameters, 0, sizeof(float)*kParameterCount);
std::memset(fStrBuf, 0, sizeof(char)*(0xff+1));
-#ifdef DGL_NO_SHARED_RESOURCES
+ #ifdef DGL_NO_SHARED_RESOURCES
createFontFromFile("sans", "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf");
-#else
+ #else
loadSharedResources();
-#endif
-
- setGeometryConstraints(DISTRHO_UI_DEFAULT_WIDTH, DISTRHO_UI_DEFAULT_HEIGHT, true);
+ #endif
+
+ if (d_isNotEqual(fScaleFactor, 1.0))
+ {
+ const uint width = DISTRHO_UI_DEFAULT_WIDTH * fScaleFactor;
+ const uint height = DISTRHO_UI_DEFAULT_HEIGHT * fScaleFactor;
+ setGeometryConstraints(width, height, true);
+ setSize(width, height);
+ }
+ else
+ {
+ setGeometryConstraints(DISTRHO_UI_DEFAULT_WIDTH, DISTRHO_UI_DEFAULT_HEIGHT, true);
+ }
// no need to show resize handle if window is user-resizable
if (fResizable)