Browse Source

Start adding some actual implementation to Window class

Signed-off-by: falkTX <falktx@falktx.com>
pull/272/head
falkTX 1 year ago
parent
commit
97f90a6128
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
11 changed files with 192 additions and 271 deletions
  1. +1
    -1
      .gitmodules
  2. +20
    -7
      dgl/Window.hpp
  3. +10
    -8
      dgl/src/ApplicationPrivateData.cpp
  4. +16
    -9
      dgl/src/ApplicationPrivateData.hpp
  5. +14
    -24
      dgl/src/Window.cpp
  6. +111
    -215
      dgl/src/WindowPrivateData.cpp
  7. +14
    -3
      dgl/src/WindowPrivateData.hpp
  8. +1
    -1
      dgl/src/pugl-upstream
  9. +2
    -0
      dgl/src/pugl.cpp
  10. +2
    -3
      tests/Makefile
  11. +1
    -0
      tests/Window.cpp

+ 1
- 1
.gitmodules View File

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

+ 20
- 7
dgl/Window.hpp View File

@@ -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);



+ 10
- 8
dgl/src/ApplicationPrivateData.cpp View File

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


+ 16
- 9
dgl/src/ApplicationPrivateData.hpp View File

@@ -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)


+ 14
- 24
dgl/src/Window.cpp View File

@@ -37,27 +37,32 @@ 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)
{
@@ -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;


+ 111
- 215
dgl/src/WindowPrivateData.cpp View File

@@ -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)
{


+ 14
- 3
dgl/src/WindowPrivateData.hpp View File

@@ -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);


+ 1
- 1
dgl/src/pugl-upstream

@@ -1 +1 @@
Subproject commit 2d3100e47eee6a8bf2209ee19157de6d23dd1c55
Subproject commit 5a3a1309ad6432d72cdb7f37e3e36383dd6ba372

+ 2
- 0
dgl/src/pugl.cpp View File

@@ -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"


+ 2
- 3
tests/Makefile View File

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


+ 1
- 0
tests/Window.cpp View File

@@ -39,6 +39,7 @@ int main()
{
Application app(true);
Window win(app);
app.idle();
}

// TODO


Loading…
Cancel
Save