Signed-off-by: falkTX <falktx@falktx.com>pull/452/head
@@ -545,6 +545,7 @@ private: | |||
uint height, | |||
double scaleFactor, | |||
bool resizable, | |||
bool usesScheduledRepaints, | |||
bool usesSizeRequest, | |||
bool doPostInit); | |||
@@ -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)) | |||
@@ -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(); | |||
@@ -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()), | |||
@@ -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), | |||
@@ -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; | |||
@@ -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 | |||
@@ -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 | |||
@@ -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) | |||
@@ -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) | |||