DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

commit 97f90a612854a1f01acb861b49408701233b980c
parent 9edea25fab9c0e4b02ea3f2e508542f18b7d3f4c
Author: falkTX <falktx@falktx.com>
Date:   Mon,  3 May 2021 16:43:17 +0100

Start adding some actual implementation to Window class

Signed-off-by: falkTX <falktx@falktx.com>

Diffstat:
M.gitmodules | 2+-
Mdgl/Window.hpp | 27++++++++++++++++++++-------
Mdgl/src/ApplicationPrivateData.cpp | 18++++++++++--------
Mdgl/src/ApplicationPrivateData.hpp | 25++++++++++++++++---------
Mdgl/src/Window.cpp | 38++++++++++++++------------------------
Mdgl/src/WindowPrivateData.cpp | 326+++++++++++++++++++++++++++----------------------------------------------------
Mdgl/src/WindowPrivateData.hpp | 17++++++++++++++---
Mdgl/src/pugl.cpp | 2++
Mtests/Makefile | 5++---
Mtests/Window.cpp | 1+
10 files changed, 191 insertions(+), 270 deletions(-)

diff --git a/.gitmodules b/.gitmodules @@ -1,3 +1,3 @@ [submodule "dgl/src/pugl-upstream"] path = dgl/src/pugl-upstream - url = https://github.com/lv2/pugl.git + url = https://github.com/DISTRHO/pugl.git diff --git a/dgl/Window.hpp b/dgl/Window.hpp @@ -63,6 +63,26 @@ public: */ virtual ~Window(); + /** + Whether this Window is embed into another (usually not DGL-controlled) Window. + */ + bool isEmbed() const noexcept; + + bool isVisible() const noexcept; + void setVisible(bool visible); + + inline void show() { setVisible(true); } + inline void hide() { setVisible(true); } + + /** + Hide window and notify application of a window close event. + The application event-loop will stop when all windows have been closed. + For standalone windows only, has no effect if window is embed. + @see isEmbed() + + @note It is possible to hide the window while not stopping the event-loop. + A closed window is always hidden, but the reverse is not always true. + */ void close(); /** @@ -144,8 +164,6 @@ END_NAMESPACE_DGL static Window& withTransientParentWindow(Window& transientParentWindow); - void show(); - void hide(); void exec(bool lockWait = false); void focus(); @@ -156,11 +174,6 @@ END_NAMESPACE_DGL bool openFileBrowser(const FileBrowserOptions& options); #endif - bool isEmbed() const noexcept; - - bool isVisible() const noexcept; - void setVisible(bool visible); - bool isResizable() const noexcept; void setResizable(bool resizable); diff --git a/dgl/src/ApplicationPrivateData.cpp b/dgl/src/ApplicationPrivateData.cpp @@ -28,6 +28,7 @@ Application::PrivateData::PrivateData(const bool standalone) standalone ? PUGL_WORLD_THREADS : 0x0)), isStandalone(standalone), isQuitting(false), + isStarting(true), visibleWindows(0), windows(), idleCallbacks() @@ -36,14 +37,11 @@ Application::PrivateData::PrivateData(const bool standalone) puglSetWorldHandle(world, this); puglSetClassName(world, DISTRHO_MACRO_AS_STRING(DGL_NAMESPACE)); - - // puglSetLogLevel(world, PUGL_LOG_LEVEL_DEBUG); - } Application::PrivateData::~PrivateData() { - DISTRHO_SAFE_ASSERT(isQuitting); + DISTRHO_SAFE_ASSERT(isStarting || isQuitting); DISTRHO_SAFE_ASSERT(visibleWindows == 0); windows.clear(); @@ -57,21 +55,23 @@ Application::PrivateData::~PrivateData() void Application::PrivateData::oneWindowShown() noexcept { - DISTRHO_SAFE_ASSERT_RETURN(isStandalone,); - if (++visibleWindows == 1) + { isQuitting = false; + isStarting = false; + } } -void Application::PrivateData::oneWindowHidden() noexcept +void Application::PrivateData::oneWindowClosed() noexcept { - DISTRHO_SAFE_ASSERT_RETURN(isStandalone,); DISTRHO_SAFE_ASSERT_RETURN(visibleWindows != 0,); if (--visibleWindows == 0) isQuitting = true; } +// -------------------------------------------------------------------------------------------------------------------- + void Application::PrivateData::idle(const uint timeoutInMs) { if (world != nullptr) @@ -92,6 +92,8 @@ void Application::PrivateData::idle(const uint timeoutInMs) void Application::PrivateData::quit() { + DISTRHO_SAFE_ASSERT_RETURN(isStandalone,); + isQuitting = true; #ifndef DPF_TEST_APPLICATION_CPP diff --git a/dgl/src/ApplicationPrivateData.hpp b/dgl/src/ApplicationPrivateData.hpp @@ -39,31 +39,38 @@ struct Application::PrivateData { /** Whether the applicating is about to quit, or already stopped. Defaults to false. */ bool isQuitting; + /** Whether the applicating is starting up, that is, no windows have been made visible yet. Defaults to true. */ + bool isStarting; + /** Counter of visible windows, only used in standalone mode. If 0->1, application is starting. If 1->0, application is quitting/stopping. */ uint visibleWindows; - /** List of windows for this application. Used as a way to call each window `idle`. */ + /** List of windows for this application. Only used during `close`. */ std::list<Window*> windows; - /** List of idle callbacks for this application. Run after all windows `idle`. */ + /** List of idle callbacks for this application. */ std::list<IdleCallback*> idleCallbacks; /** Constructor and destructor */ PrivateData(const bool standalone); ~PrivateData(); - /** Flag one window shown or hidden status, which modifies @a visibleWindows. - For standalone mode only. - Modifies @a isQuitting under certain conditions */ + /** Flag one window as shown, which increments @a visibleWindows. + Sets @a isQuitting and @a isStarting as false if this is the first window. + For standalone mode only. */ void oneWindowShown() noexcept; - void oneWindowHidden() noexcept; - /** Run Pugl world update for @a timeoutInMs, and then the idle functions for each window and idle callback, - in order of registration. */ + /** Flag one window as closed, which decrements @a visibleWindows. + Sets @a isQuitting as true if this is the last window. + For standalone mode only. */ + void oneWindowClosed() noexcept; + + /** Run Pugl world update for @a timeoutInMs, and then each idle callback in order of registration. */ void idle(const uint timeoutInMs); - /** Set flag indicating application is quitting, and closes all windows in reverse order of registration. */ + /** Set flag indicating application is quitting, and close all windows in reverse order of registration. + For standalone mode only. */ void quit(); DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData) diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp @@ -37,28 +37,33 @@ Window::~Window() delete pData; } -void Window::close() +bool Window::isEmbed() const noexcept { - pData->close(); + return pData->isEmbed; } -uintptr_t Window::getNativeWindowHandle() const noexcept +bool Window::isVisible() const noexcept { - return puglGetNativeWindow(pData->view); + return pData->isVisible; } -#if 0 -void Window::show() +void Window::setVisible(const bool visible) { - pData->setVisible(true); + pData->setVisible(visible); } -void Window::hide() +void Window::close() +{ + pData->close(); +} + +uintptr_t Window::getNativeWindowHandle() const noexcept { - pData->setVisible(false); + return puglGetNativeWindow(pData->view); } #if 0 +#if 0 void Window::exec(bool lockWait) { pData->exec(lockWait); @@ -89,21 +94,6 @@ void Window::repaint(const Rectangle<uint>& rect) noexcept puglPostRedisplayRect(pData->fView, prect); } -bool Window::isEmbed() const noexcept -{ - return pData->fUsingEmbed; -} - -bool Window::isVisible() const noexcept -{ - return pData->fVisible; -} - -void Window::setVisible(const bool visible) -{ - pData->setVisible(visible); -} - bool Window::isResizable() const noexcept { return puglGetViewHint(pData->fView, PUGL_RESIZABLE) == PUGL_TRUE; diff --git a/dgl/src/WindowPrivateData.cpp b/dgl/src/WindowPrivateData.cpp @@ -26,32 +26,56 @@ START_NAMESPACE_DGL Window::PrivateData::PrivateData(Application::PrivateData* const a, Window* const s) : appData(a), self(s), - view(puglNewView(appData->world)) + view(puglNewView(appData->world)), + isClosed(true), + isVisible(false), + isEmbed(false) { - init(true); + init(false); } Window::PrivateData::PrivateData(Application::PrivateData* const a, Window* const s, Window& transientWindow) : appData(a), self(s), - view(puglNewView(appData->world)) + view(puglNewView(appData->world)), + isClosed(true), + isVisible(false), + isEmbed(false) { + init(false); + puglSetTransientFor(view, transientWindow.getNativeWindowHandle()); - init(true); } Window::PrivateData::PrivateData(Application::PrivateData* const a, Window* const s, const uintptr_t parentWindowHandle, const double scaling, const bool resizable) : appData(a), self(s), - view(puglNewView(appData->world)) + view(puglNewView(appData->world)), + isClosed(parentWindowHandle == 0), + isVisible(parentWindowHandle != 0), + isEmbed(parentWindowHandle != 0) { - // TODO view parent init(resizable); + + if (isEmbed) + { + appData->oneWindowShown(); + puglSetParentWindow(view, parentWindowHandle); + puglShow(view); + } } Window::PrivateData::~PrivateData() { + if (isEmbed) + { + puglHide(view); + appData->oneWindowClosed(); + isClosed = true; + isVisible = false; + } + appData->idleCallbacks.remove(this); appData->windows.remove(self); @@ -95,28 +119,102 @@ void Window::PrivateData::init(const bool resizable) // DGL_DBG("Success!\n"); } +// ----------------------------------------------------------------------- + void Window::PrivateData::close() { - /* - DGL_DBG("Window close\n"); +// DGL_DBG("Window close\n"); - if (fUsingEmbed) + if (isEmbed || isClosed) return; + isClosed = true; setVisible(false); + appData->oneWindowClosed(); +} + +// ----------------------------------------------------------------------- + +void Window::PrivateData::setVisible(const bool visible) +{ + if (isVisible == visible) + { +// DGL_DBG("Window setVisible matches current state, ignoring request\n"); + return; + } + if (isEmbed) + { +// DGL_DBG("Window setVisible cannot be called when embedded\n"); + return; + } + +// DGL_DBG("Window setVisible called\n"); + + isVisible = visible; + + if (visible) + { +// #if 0 && defined(DISTRHO_OS_MAC) +// if (mWindow != nullptr) +// { +// if (mParentWindow != nullptr) +// [mParentWindow addChildWindow:mWindow +// ordered:NSWindowAbove]; +// } +// #endif - if (! fFirstInit) + if (isClosed) + { + puglRealize(view); +#ifdef DISTRHO_OS_WINDOWS + puglWin32ShowWindowCentered(view); +#else + puglShow(view); +#endif + appData->oneWindowShown(); + isClosed = false; + } + else + { +#ifdef DISTRHO_OS_WINDOWS + puglWin32RestoreWindow(view); +#else + puglShow(view); +#endif + } + } + else { - fAppData->oneWindowHidden(); - fFirstInit = true; +// #if 0 && defined(DISTRHO_OS_MAC) +// if (mWindow != nullptr) +// { +// if (mParentWindow != nullptr) +// [mParentWindow removeChildWindow:mWindow]; +// } +// #endif + + puglHide(view); + +// if (fModal.enabled) +// exec_fini(); } - */ } // ----------------------------------------------------------------------- void Window::PrivateData::idleCallback() { +// #if defined(DISTRHO_OS_WINDOWS) && !defined(DGL_FILE_BROWSER_DISABLED) +// if (fSelectedFile.isNotEmpty()) +// { +// char* const buffer = fSelectedFile.getAndReleaseBuffer(); +// fView->fileSelectedFunc(fView, buffer); +// std::free(buffer); +// } +// #endif +// +// if (fModal.enabled && fModal.parent != nullptr) +// fModal.parent->windowSpecificIdle(); } // ----------------------------------------------------------------------- @@ -156,8 +254,6 @@ extern "C" { # define DGL_DEBUG_EVENTS # include "pugl-upstream/src/haiku.cpp" #elif defined(DISTRHO_OS_MAC) -# define PuglWindow DISTRHO_JOIN_MACRO(PuglWindow, DGL_NAMESPACE) -# define PuglOpenGLView DISTRHO_JOIN_MACRO(PuglOpenGLView, DGL_NAMESPACE) # include "pugl-upstream/src/mac.m" #elif defined(DISTRHO_OS_WINDOWS) # include "ppugl-upstream/src/win.c" @@ -214,189 +310,6 @@ struct Fallback { // ----------------------------------------------------------------------- -Window::PrivateData::PrivateData(Application::PrivateData* const appData, Window* const self) - : fAppData(appData), - fSelf(self), - fView(puglNewView(appData->world)), - fFirstInit(true), - fVisible(false), - fUsingEmbed(false), - fScaling(1.0), - fAutoScaling(1.0), - fWidgets(), - fModal() -{ - DGL_DBG("Creating window without parent..."); DGL_DBGF; - init(); -} - -#ifndef DPF_TEST_WINDOW_CPP -Window::PrivateData::PrivateData(Application::PrivateData* const appData, Window* const self, Window& transientWindow) - : fAppData(appData), - fSelf(self), - fView(puglNewView(appData->world)), - fFirstInit(true), - fVisible(false), - fUsingEmbed(false), - fScaling(1.0), - fAutoScaling(1.0), - fWidgets(), - fModal(transientWindow.pData) -{ - DGL_DBG("Creating window with parent..."); DGL_DBGF; - init(); - - puglSetTransientFor(fView, transientWindow.getNativeWindowHandle()); -} -#endif - -Window::PrivateData::PrivateData(Application::PrivateData* const appData, Window* const self, - const uintptr_t parentWindowHandle, - const double scaling, - const bool resizable) - : fAppData(appData), - fSelf(self), - fView(puglNewView(appData->world)), - fFirstInit(true), - fVisible(parentWindowHandle != 0), - fUsingEmbed(parentWindowHandle != 0), - fScaling(scaling), - fAutoScaling(1.0), - fWidgets(), - fModal() -{ - if (fUsingEmbed) - { - DGL_DBG("Creating embedded window..."); DGL_DBGF; - puglSetParentWindow(fView, parentWindowHandle); - } - else - { - DGL_DBG("Creating window without parent..."); DGL_DBGF; - } - - init(resizable); - - if (fUsingEmbed) - { - DGL_DBG("NOTE: Embed window is always visible and non-resizable\n"); -// puglShowWindow(fView); -// fAppData->oneWindowShown(); -// fFirstInit = false; - } -} - -Window::PrivateData::~PrivateData() -{ - DGL_DBG("Destroying window..."); DGL_DBGF; - -#if 0 - if (fModal.enabled) - { - exec_fini(); - close(); - } -#endif - - fWidgets.clear(); - - if (fUsingEmbed) - { -// puglHideWindow(fView); -// fAppData->oneWindowHidden(); - } - - if (fSelf != nullptr) - fAppData->windows.remove(fSelf); - -#if defined(DISTRHO_OS_MAC) && !defined(DGL_FILE_BROWSER_DISABLED) - if (fOpenFilePanel) - { - [fOpenFilePanel release]; - fOpenFilePanel = nullptr; - } - if (fFilePanelDelegate) - { - [fFilePanelDelegate release]; - fFilePanelDelegate = nullptr; - } -#endif - - if (fView != nullptr) - puglFreeView(fView); - - DGL_DBG("Success!\n"); -} - -// ----------------------------------------------------------------------- - -void Window::PrivateData::setVisible(const bool visible) -{ - if (fVisible == visible) - { - DGL_DBG("Window setVisible matches current state, ignoring request\n"); - return; - } - if (fUsingEmbed) - { - DGL_DBG("Window setVisible cannot be called when embedded\n"); - return; - } - - DGL_DBG("Window setVisible called\n"); - - fVisible = visible; - - if (visible) - { -#if 0 && defined(DISTRHO_OS_MAC) - if (mWindow != nullptr) - { - if (mParentWindow != nullptr) - [mParentWindow addChildWindow:mWindow - ordered:NSWindowAbove]; - } -#endif - - if (fFirstInit) - { - puglRealize(fView); -#ifdef DISTRHO_OS_WINDOWS - puglShowWindowCentered(fView); -#else - puglShow(fView); -#endif - fAppData->oneWindowShown(); - fFirstInit = false; - } - else - { -#ifdef DISTRHO_OS_WINDOWS - puglWin32RestoreWindow(fView); -#else - puglShow(fView); -#endif - } - } - else - { -#if 0 && defined(DISTRHO_OS_MAC) - if (mWindow != nullptr) - { - if (mParentWindow != nullptr) - [mParentWindow removeChildWindow:mWindow]; - } -#endif - - puglHide(fView); - -// if (fModal.enabled) -// exec_fini(); - } -} - -// ----------------------------------------------------------------------- - void Window::PrivateData::addWidget(Widget* const widget) { fWidgets.push_back(widget); @@ -486,23 +399,6 @@ void Window::PrivateData::onPuglMouse(const Widget::MouseEvent& ev) // ----------------------------------------------------------------------- -void Window::PrivateData::windowSpecificIdle() -{ -#if defined(DISTRHO_OS_WINDOWS) && !defined(DGL_FILE_BROWSER_DISABLED) - if (fSelectedFile.isNotEmpty()) - { - char* const buffer = fSelectedFile.getAndReleaseBuffer(); - fView->fileSelectedFunc(fView, buffer); - std::free(buffer); - } -#endif - - if (fModal.enabled && fModal.parent != nullptr) - fModal.parent->windowSpecificIdle(); -} - -// ----------------------------------------------------------------------- - static inline int printModifiers(const uint32_t mods) { diff --git a/dgl/src/WindowPrivateData.hpp b/dgl/src/WindowPrivateData.hpp @@ -18,7 +18,6 @@ #define DGL_WINDOW_PRIVATE_DATA_HPP_INCLUDED #include "../Window.hpp" -// #include "ApplicationPrivateData.hpp" #include "pugl.hpp" @@ -41,6 +40,16 @@ struct Window::PrivateData : IdleCallback { /** Pugl view instance. */ PuglView* const view; + /** Whether this Window is closed (not visible or counted in the Application it is tied to). + Defaults to true unless embed (embed windows are never closed). */ + bool isClosed; + + /** Whether this Window is currently visible/mapped. Defaults to false. */ + bool isVisible; + + /** Whether this Window is embed into another (usually not DGL-controlled) Window. */ + const bool isEmbed; + /** Constructor for a regular, standalone window. */ PrivateData(AppData* appData, Window* self); @@ -58,13 +67,15 @@ struct Window::PrivateData : IdleCallback { /** Hide window and notify application of a window close event. * Does nothing if window is embed (that is, not standalone). - * The application event-loop will stop if all windows have been closed. + * The application event-loop will stop when all windows have been closed. * - * @note It is possible to hide the window while not stopping event-loop. + * @note It is possible to hide the window while not stopping the event-loop. * A closed window is always hidden, but the reverse is not always true. */ void close(); + void setVisible(bool visible); + void idleCallback() override; static PuglStatus puglEventCallback(PuglView* view, const PuglEvent* event); diff --git a/dgl/src/pugl.cpp b/dgl/src/pugl.cpp @@ -67,6 +67,8 @@ START_NAMESPACE_DGL #if defined(DISTRHO_OS_HAIKU) #elif defined(DISTRHO_OS_MAC) +# define PuglWindow DISTRHO_JOIN_MACRO(PuglWindow, DGL_NAMESPACE) +# define PuglOpenGLView DISTRHO_JOIN_MACRO(PuglOpenGLView, DGL_NAMESPACE) #elif defined(DISTRHO_OS_WINDOWS) #else # include "pugl-upstream/src/x11.c" diff --git a/tests/Makefile b/tests/Makefile @@ -35,7 +35,7 @@ TARGETS = $(TESTS:%=../build/tests/%) TARGETS += $(WTESTS:Window.%=../build/tests/Window.%) OBJS = $(TESTS:%=../build/tests/%.cpp.o) -OBJS += $(WTESTS:Window.%=../build/tests/Window.%.cpp.o) +OBJS += $(WTESTS:Window.%=../build/tests/Window.cpp.%.o) # --------------------------------------------------------------------------------------------------------------------- @@ -68,8 +68,7 @@ all: $(TARGETS) @echo "Linking $*" $(SILENT)$(CXX) $< $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) $(OPENGL_LIBS) -o $@ @echo "Running test for $*" -# $(SILENT) - $@ + $(SILENT) $@ # gdb -ex run ../build/tests/%.vulkan: ../build/tests/%.cpp.vulkan.o diff --git a/tests/Window.cpp b/tests/Window.cpp @@ -39,6 +39,7 @@ int main() { Application app(true); Window win(app); + app.idle(); } // TODO