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:
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