diff --git a/dgl/Application.hpp b/dgl/Application.hpp index cf634b3a..ee11db3c 100644 --- a/dgl/Application.hpp +++ b/dgl/Application.hpp @@ -21,11 +21,6 @@ START_NAMESPACE_DGL -// -------------------------------------------------------------------------------------------------------------------- -// Forward class names - -class Window; - // -------------------------------------------------------------------------------------------------------------------- /** diff --git a/dgl/Cairo.hpp b/dgl/Cairo.hpp index 2aa38408..a234b009 100644 --- a/dgl/Cairo.hpp +++ b/dgl/Cairo.hpp @@ -30,7 +30,7 @@ START_NAMESPACE_DGL */ struct CairoGraphicsContext : GraphicsContext { - cairo_t* cairo; // FIXME proper name.. + cairo_t* handle; }; // ----------------------------------------------------------------------- diff --git a/dgl/Window.hpp b/dgl/Window.hpp index bd6f17f3..09e719cb 100644 --- a/dgl/Window.hpp +++ b/dgl/Window.hpp @@ -56,7 +56,12 @@ public: /** Constructor for an embed Window, typically used in modules or plugins that run inside another host. */ - explicit Window(Application& app, uintptr_t parentWindowHandle, double scaling, bool resizable); + explicit Window(Application& app, + uintptr_t parentWindowHandle, + uint width, + uint height, + double scaling, + bool resizable); /** Destructor. @@ -68,11 +73,33 @@ public: */ bool isEmbed() const noexcept; + /** + Check if this window is visible / mapped. + Invisible windows do not receive events except resize. + @see setVisible(bool) + */ bool isVisible() const noexcept; + + /** + Set windows visible (or not) according to @a visible. + Only valid for standalones, embed windows are always visible. + @see isVisible(), hide(), show() + */ void setVisible(bool visible); - inline void show() { setVisible(true); } - inline void hide() { setVisible(true); } + /** + Show window. + This is the same as calling setVisible(true). + @see isVisible(), setVisible(bool) + */ + void show(); + + /** + Hide window. + This is the same as calling setVisible(false). + @see isVisible(), setVisible(bool) + */ + void hide(); /** Hide window and notify application of a window close event. @@ -85,6 +112,44 @@ public: */ void close(); + /** + Get width. + */ + uint getWidth() const noexcept; + + /** + Get height. + */ + uint getHeight() const noexcept; + + /** + Get size. + */ + Size getSize() const noexcept; + + /** + Set width. + */ + void setWidth(uint width); + + /** + Set height. + */ + void setHeight(uint height); + + /** + Set size using @a width and @a height values. + */ + void setSize(uint width, uint height); + + /** + Set size. + */ + void setSize(const Size& size); + + const char* getTitle() const noexcept; + void setTitle(const char* title); + /** Get the "native" window handle. Returned value depends on the platform: @@ -95,6 +160,11 @@ public: */ uintptr_t getNativeWindowHandle() const noexcept; +protected: + virtual void onDisplayBefore(); + virtual void onDisplayAfter(); + virtual void onReshape(uint width, uint height); + private: struct PrivateData; PrivateData* const pData; @@ -180,15 +250,6 @@ END_NAMESPACE_DGL bool getIgnoringKeyRepeat() const noexcept; void setIgnoringKeyRepeat(bool ignore) noexcept; - uint getWidth() const noexcept; - uint getHeight() const noexcept; - Size getSize() const noexcept; - void setSize(uint width, uint height); - void setSize(Size size); - - const char* getTitle() const noexcept; - void setTitle(const char* title); - void setGeometryConstraints(uint width, uint height, bool aspect); void setTransientWinId(uintptr_t winId); @@ -206,9 +267,6 @@ END_NAMESPACE_DGL protected: - virtual void onDisplayBefore(); - virtual void onDisplayAfter(); - virtual void onReshape(uint width, uint height); virtual void onClose(); #ifndef DGL_FILE_BROWSER_DISABLED diff --git a/dgl/src/ApplicationPrivateData.cpp b/dgl/src/ApplicationPrivateData.cpp index d92fe1a2..0a75af82 100644 --- a/dgl/src/ApplicationPrivateData.cpp +++ b/dgl/src/ApplicationPrivateData.cpp @@ -21,6 +21,8 @@ START_NAMESPACE_DGL +typedef std::list::reverse_iterator WindowListReverseIterator; + // -------------------------------------------------------------------------------------------------------------------- Application::PrivateData::PrivateData(const bool standalone) @@ -97,9 +99,9 @@ void Application::PrivateData::quit() isQuitting = true; #ifndef DPF_TEST_APPLICATION_CPP - for (std::list::reverse_iterator rit = windows.rbegin(), rite = windows.rend(); rit != rite; ++rit) + for (WindowListReverseIterator rit = windows.rbegin(), rite = windows.rend(); rit != rite; ++rit) { - Window* const window(*rit); + DGL_NAMESPACE::Window* const window(*rit); window->close(); } #endif diff --git a/dgl/src/ApplicationPrivateData.hpp b/dgl/src/ApplicationPrivateData.hpp index 0074755c..15b252a6 100644 --- a/dgl/src/ApplicationPrivateData.hpp +++ b/dgl/src/ApplicationPrivateData.hpp @@ -47,10 +47,10 @@ struct Application::PrivateData { uint visibleWindows; /** List of windows for this application. Only used during `close`. */ - std::list windows; + std::list windows; /** List of idle callbacks for this application. */ - std::list idleCallbacks; + std::list idleCallbacks; /** Constructor and destructor */ PrivateData(const bool standalone); diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp index 040d6f66..36bb8284 100644 --- a/dgl/src/Window.cpp +++ b/dgl/src/Window.cpp @@ -29,8 +29,13 @@ START_NAMESPACE_DGL Window::Window(Application& app) : pData(new PrivateData(app.pData, this)) {} -Window::Window(Application& app, const uintptr_t parentWindowHandle, const double scaling, const bool resizable) - : pData(new PrivateData(app.pData, this, parentWindowHandle, scaling, resizable)) {} +Window::Window(Application& app, + const uintptr_t parentWindowHandle, + const uint width, + const uint height, + const double scaling, + const bool resizable) + : pData(new PrivateData(app.pData, this, parentWindowHandle, width, height, scaling, resizable)) {} Window::~Window() { @@ -49,7 +54,20 @@ bool Window::isVisible() const noexcept void Window::setVisible(const bool visible) { - pData->setVisible(visible); + if (visible) + pData->show(); + else + pData->hide(); +} + +void Window::show() +{ + pData->show(); +} + +void Window::hide() +{ + pData->hide(); } void Window::close() @@ -57,11 +75,77 @@ void Window::close() pData->close(); } +uint Window::getWidth() const noexcept +{ + return puglGetFrame(pData->view).width; +} + +uint Window::getHeight() const noexcept +{ + return puglGetFrame(pData->view).height; +} + +Size Window::getSize() const noexcept +{ + const PuglRect rect = puglGetFrame(pData->view); + return Size(rect.width, rect.height); +} + +void Window::setWidth(const uint width) +{ + setSize(width, getHeight()); +} + +void Window::setHeight(const uint height) +{ + setSize(getWidth(), height); +} + +void Window::setSize(const uint width, const uint height) +{ + DISTRHO_SAFE_ASSERT_UINT2_RETURN(width > 1 && height > 1, width, height,); + + puglSetWindowSize(pData->view, width, height); +} + +void Window::setSize(const Size& size) +{ + setSize(size.getWidth(), size.getHeight()); +} + +const char* Window::getTitle() const noexcept +{ + return puglGetWindowTitle(pData->view); +} + +void Window::setTitle(const char* const title) +{ + puglSetWindowTitle(pData->view, title); +} + uintptr_t Window::getNativeWindowHandle() const noexcept { return puglGetNativeWindow(pData->view); } +void Window::onDisplayBefore() +{ + const GraphicsContext& context(pData->getGraphicsContext()); + PrivateData::Fallback::onDisplayBefore(context); +} + +void Window::onDisplayAfter() +{ + const GraphicsContext& context(pData->getGraphicsContext()); + PrivateData::Fallback::onDisplayAfter(context); +} + +void Window::onReshape(const uint width, const uint height) +{ + const GraphicsContext& context(pData->getGraphicsContext()); + PrivateData::Fallback::onReshape(context, width, height); +} + #if 0 #if 0 void Window::exec(bool lockWait) @@ -134,44 +218,6 @@ void Window::setGeometryConstraints(const uint width, const uint height, bool as puglUpdateGeometryConstraints(pData->fView, width, height, aspect); } -uint Window::getWidth() const noexcept -{ - return puglGetFrame(pData->fView).width; -} - -uint Window::getHeight() const noexcept -{ - return puglGetFrame(pData->fView).height; -} - -Size Window::getSize() const noexcept -{ - const PuglRect rect = puglGetFrame(pData->fView); - return Size(rect.width, rect.height); -} - -void Window::setSize(const uint width, const uint height) -{ - DISTRHO_SAFE_ASSERT_INT2_RETURN(width > 1 && height > 1, width, height,); - - puglSetWindowSize(pData->fView, width, height); -} - -void Window::setSize(const Size size) -{ - setSize(size.getWidth(), size.getHeight()); -} - -const char* Window::getTitle() const noexcept -{ - return puglGetWindowTitle(pData->fView); -} - -void Window::setTitle(const char* const title) -{ - puglSetWindowTitle(pData->fView, title); -} - void Window::setTransientWinId(const uintptr_t winId) { puglSetTransientFor(pData->fView, winId); @@ -189,17 +235,6 @@ Application& Window::getApp() const noexcept } #endif -#if 0 -const GraphicsContext& Window::getGraphicsContext() const noexcept -{ - GraphicsContext& context = pData->fContext; -#ifdef DGL_CAIRO - context.cairo = (cairo_t*)puglGetContext(pData->fView); -#endif - return context; -} -#endif - void Window::_setAutoScaling(double scaling) noexcept { DISTRHO_SAFE_ASSERT_RETURN(scaling > 0.0,); @@ -240,21 +275,6 @@ void Window::removeIdleCallback(IdleCallback* const callback) // ----------------------------------------------------------------------- -void Window::onDisplayBefore() -{ - PrivateData::Fallback::onDisplayBefore(); -} - -void Window::onDisplayAfter() -{ - PrivateData::Fallback::onDisplayAfter(); -} - -void Window::onReshape(const uint width, const uint height) -{ - PrivateData::Fallback::onReshape(width, height); -} - void Window::onClose() { } diff --git a/dgl/src/WindowPrivateData.cpp b/dgl/src/WindowPrivateData.cpp index 9e07004d..cbc2665c 100644 --- a/dgl/src/WindowPrivateData.cpp +++ b/dgl/src/WindowPrivateData.cpp @@ -21,6 +21,21 @@ START_NAMESPACE_DGL +#define DGL_DEBUG_EVENTS + +#if defined(DEBUG) && defined(DGL_DEBUG_EVENTS) +# define DGL_DBG(msg) std::fprintf(stderr, "%s", msg); +# define DGL_DBGp(...) std::fprintf(stderr, __VA_ARGS__); +# define DGL_DBGF std::fflush(stderr); +#else +# define DGL_DBG(msg) +# define DGL_DBGp(...) +# define DGL_DBGF +#endif + +#define DEFAULT_WIDTH 640 +#define DEFAULT_HEIGHT 480 + // ----------------------------------------------------------------------- Window::PrivateData::PrivateData(Application::PrivateData* const a, Window* const s) @@ -31,7 +46,7 @@ Window::PrivateData::PrivateData(Application::PrivateData* const a, Window* cons isVisible(false), isEmbed(false) { - init(false); + init(DEFAULT_WIDTH, DEFAULT_HEIGHT, false); } Window::PrivateData::PrivateData(Application::PrivateData* const a, Window* const s, Window& transientWindow) @@ -42,13 +57,15 @@ Window::PrivateData::PrivateData(Application::PrivateData* const a, Window* cons isVisible(false), isEmbed(false) { - init(false); + init(DEFAULT_WIDTH, DEFAULT_HEIGHT, false); puglSetTransientFor(view, transientWindow.getNativeWindowHandle()); } Window::PrivateData::PrivateData(Application::PrivateData* const a, Window* const s, - const uintptr_t parentWindowHandle, const double scaling, const bool resizable) + const uintptr_t parentWindowHandle, + const uint width, const uint height, + const double scaling, const bool resizable) : appData(a), self(s), view(puglNewView(appData->world)), @@ -56,11 +73,12 @@ Window::PrivateData::PrivateData(Application::PrivateData* const a, Window* cons isVisible(parentWindowHandle != 0), isEmbed(parentWindowHandle != 0) { - init(resizable); + init(width, height, resizable); if (isEmbed) { appData->oneWindowShown(); + puglSetDefaultSize(view, width, height); puglSetParentWindow(view, parentWindowHandle); puglShow(view); } @@ -85,16 +103,15 @@ Window::PrivateData::~PrivateData() // ----------------------------------------------------------------------- -void Window::PrivateData::init(const bool resizable) +void Window::PrivateData::init(const uint width, const uint height, const bool resizable) { appData->windows.push_back(self); appData->idleCallbacks.push_back(this); + memset(graphicsContext, 0, sizeof(graphicsContext)); if (view == nullptr) { - /* - DGL_DBG("Failed!\n"); - */ + DGL_DBG("Failed to create Pugl view, everything will fail!\n"); return; } @@ -116,231 +133,144 @@ void Window::PrivateData::init(const bool resizable) // puglSetFileSelectedFunc(fView, fileBrowserSelectedCallback); // #endif - // DGL_DBG("Success!\n"); -} - -// ----------------------------------------------------------------------- - -void Window::PrivateData::close() -{ -// DGL_DBG("Window close\n"); - - if (isEmbed || isClosed) - return; - - isClosed = true; - setVisible(false); - appData->oneWindowClosed(); + PuglRect rect = puglGetFrame(view); + rect.width = width; + rect.height = height; + puglSetFrame(view, rect); } // ----------------------------------------------------------------------- -void Window::PrivateData::setVisible(const bool visible) +void Window::PrivateData::show() { - if (isVisible == visible) + if (isVisible) { -// DGL_DBG("Window setVisible matches current state, ignoring request\n"); + DGL_DBG("Window show matches current visible state, ignoring request\n"); return; } if (isEmbed) { -// DGL_DBG("Window setVisible cannot be called when embedded\n"); + DGL_DBG("Window show cannot be called when embedded\n"); return; } -// DGL_DBG("Window setVisible called\n"); + DGL_DBG("Window show called\n"); - isVisible = visible; +#if 0 && defined(DISTRHO_OS_MAC) +// if (mWindow != nullptr) +// { +// if (mParentWindow != nullptr) +// [mParentWindow addChildWindow:mWindow +// ordered:NSWindowAbove]; +// } +#endif - if (visible) + if (isClosed) { -// #if 0 && defined(DISTRHO_OS_MAC) -// if (mWindow != nullptr) -// { -// if (mParentWindow != nullptr) -// [mParentWindow addChildWindow:mWindow -// ordered:NSWindowAbove]; -// } -// #endif + isClosed = false; + appData->oneWindowShown(); + + const PuglStatus status = puglRealize(view); + DISTRHO_SAFE_ASSERT_INT_RETURN(status == PUGL_SUCCESS, status, close()); - if (isClosed) - { - puglRealize(view); #ifdef DISTRHO_OS_WINDOWS - puglWin32ShowWindowCentered(view); + puglWin32ShowWindowCentered(view); #else - puglShow(view); + puglShow(view); #endif - appData->oneWindowShown(); - isClosed = false; - } - else - { + } + else + { #ifdef DISTRHO_OS_WINDOWS - puglWin32RestoreWindow(view); + puglWin32RestoreWindow(view); #else - puglShow(view); + puglShow(view); #endif - } } - else - { -// #if 0 && defined(DISTRHO_OS_MAC) -// if (mWindow != nullptr) -// { -// if (mParentWindow != nullptr) -// [mParentWindow removeChildWindow:mWindow]; -// } -// #endif - puglHide(view); + isVisible = true; +} -// if (fModal.enabled) -// exec_fini(); +void Window::PrivateData::hide() +{ + if (! isVisible) + { + DGL_DBG("Window hide matches current visible state, ignoring request\n"); + return; + } + if (isEmbed) + { + DGL_DBG("Window hide cannot be called when embedded\n"); + return; } -} -// ----------------------------------------------------------------------- + DGL_DBG("Window hide called\n"); -void Window::PrivateData::idleCallback() -{ -// #if defined(DISTRHO_OS_WINDOWS) && !defined(DGL_FILE_BROWSER_DISABLED) -// if (fSelectedFile.isNotEmpty()) +#if 0 && defined(DISTRHO_OS_MAC) +// if (mWindow != nullptr) // { -// char* const buffer = fSelectedFile.getAndReleaseBuffer(); -// fView->fileSelectedFunc(fView, buffer); -// std::free(buffer); +// if (mParentWindow != nullptr) +// [mParentWindow removeChildWindow:mWindow]; // } -// #endif -// -// if (fModal.enabled && fModal.parent != nullptr) -// fModal.parent->windowSpecificIdle(); -} - -// ----------------------------------------------------------------------- - -PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const PuglEvent* const event) -{ - Window::PrivateData* const pData = (Window::PrivateData*)puglGetHandle(view); - return PUGL_SUCCESS; -} - -// ----------------------------------------------------------------------- - -END_NAMESPACE_DGL - -#if 0 -#ifdef DGL_CAIRO -# define PUGL_CAIRO -# include "../Cairo.hpp" -#endif -#ifdef DGL_OPENGL -# define PUGL_OPENGL -# include "../OpenGL.hpp" #endif -#ifndef DPF_TEST_WINDOW_CPP -#include "WidgetPrivateData.hpp" -#include "pugl-upstream/include/pugl/pugl.h" -#include "pugl-extra/extras.h" -#endif + puglHide(view); -extern "C" { -#include "pugl-upstream/src/implementation.c" -#include "pugl-extra/extras.c" -} +// if (fModal.enabled) +// exec_fini(); -#if defined(DISTRHO_OS_HAIKU) -# define DGL_DEBUG_EVENTS -# include "pugl-upstream/src/haiku.cpp" -#elif defined(DISTRHO_OS_MAC) -# include "pugl-upstream/src/mac.m" -#elif defined(DISTRHO_OS_WINDOWS) -# include "ppugl-upstream/src/win.c" -# undef max -# undef min -#else -# define DGL_PUGL_USING_X11 -extern "C" { -# include "pugl-upstream/src/x11.c" -// # ifdef DGL_CAIRO -// # include "pugl-upstream/src/x11_cairo.c" -// # endif -# ifdef DGL_OPENGL -# include "pugl-upstream/src/x11_gl.c" -# endif -# define PUGL_DETAIL_X11_H_INCLUDED -# include "pugl-extra/x11.c" + isVisible = false; } -#endif -#include -#include -#include -#include -#include -#include - -#define FOR_EACH_WIDGET(it) \ - for (std::list::iterator it = fWidgets.begin(); it != fWidgets.end(); ++it) - -#define FOR_EACH_WIDGET_INV(rit) \ - for (std::list::reverse_iterator rit = fWidgets.rbegin(); rit != fWidgets.rend(); ++rit) - -#define DGL_DEBUG_EVENTS +// ----------------------------------------------------------------------- -#if defined(DEBUG) && defined(DGL_DEBUG_EVENTS) -# define DGL_DBG(msg) std::fprintf(stderr, "%s", msg); -# define DGL_DBGp(...) std::fprintf(stderr, __VA_ARGS__); -# define DGL_DBGF std::fflush(stderr); -#else -# define DGL_DBG(msg) -# define DGL_DBGp(...) -# define DGL_DBGF -#endif +void Window::PrivateData::close() +{ + DGL_DBG("Window close\n"); -START_NAMESPACE_DGL + if (isEmbed || isClosed) + return; -// Fallback build-specific Window functions -struct Fallback { - static void onDisplayBefore(); - static void onDisplayAfter(); - static void onReshape(uint width, uint height); -}; + isClosed = true; + hide(); + appData->oneWindowClosed(); +} // ----------------------------------------------------------------------- -void Window::PrivateData::addWidget(Widget* const widget) +const GraphicsContext& Window::PrivateData::getGraphicsContext() const noexcept { - fWidgets.push_back(widget); -} - -void Window::PrivateData::removeWidget(Widget* const widget) -{ - fWidgets.remove(widget); + GraphicsContext& context((GraphicsContext&)graphicsContext); +#ifdef DGL_CAIRO + ((CairoGraphicsContext&)context).handle = (cairo_t*)puglGetContext(view); +#endif + return context; } // ----------------------------------------------------------------------- -void Window::PrivateData::onPuglClose() +void Window::PrivateData::idleCallback() { - DGL_DBG("PUGL: onClose\n"); - -// if (fModal.enabled) -// exec_fini(); - - fSelf->onClose(); - - if (fModal.childFocus != nullptr) - fModal.childFocus->fSelf->onClose(); - - close(); +// #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(); } +// ----------------------------------------------------------------------- + void Window::PrivateData::onPuglDisplay() { - fSelf->onDisplayBefore(); + self->onDisplayBefore(); + /* if (fWidgets.size() != 0) { const PuglRect rect = puglGetFrame(fView); @@ -353,8 +283,9 @@ void Window::PrivateData::onPuglDisplay() widget->pData->display(width, height, fAutoScaling, false); } } + */ - fSelf->onDisplayAfter(); + self->onDisplayAfter(); } void Window::PrivateData::onPuglReshape(const int width, const int height) @@ -363,8 +294,9 @@ void Window::PrivateData::onPuglReshape(const int width, const int height) DGL_DBGp("PUGL: onReshape : %i %i\n", width, height); - fSelf->onReshape(width, height); + self->onReshape(width, height); + /* FOR_EACH_WIDGET(it) { Widget* const widget(*it); @@ -372,35 +304,43 @@ void Window::PrivateData::onPuglReshape(const int width, const int height) if (widget->pData->needsFullViewport) widget->setSize(width, height); } + */ } -void Window::PrivateData::onPuglMouse(const Widget::MouseEvent& ev) -{ - DGL_DBGp("PUGL: onMouse : %i %i %i %i\n", ev.button, ev.press, ev.pos.getX(), ev.pos.getY()); - -// if (fModal.childFocus != nullptr) -// return fModal.childFocus->focus(); +static int printEvent(const PuglEvent* event, const char* prefix, const bool verbose); - Widget::MouseEvent rev = ev; - double x = ev.pos.getX() / fAutoScaling; - double y = ev.pos.getY() / fAutoScaling; +PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const PuglEvent* const event) +{ + printEvent(event, "pugl event: ", true); + Window::PrivateData* const pData = (Window::PrivateData*)puglGetHandle(view); - FOR_EACH_WIDGET_INV(rit) + switch (event->type) { - Widget* const widget(*rit); + ///< No event + case PUGL_NOTHING: + break; - rev.pos = Point(x - widget->getAbsoluteX(), - y - widget->getAbsoluteY()); + ///< View moved/resized, a #PuglEventConfigure + case PUGL_CONFIGURE: + pData->onPuglReshape(event->configure.width, event->configure.height); + break; - if (widget->isVisible() && widget->onMouse(rev)) - break; + ///< View must be drawn, a #PuglEventExpose + case PUGL_EXPOSE: + pData->onPuglDisplay(); + break; + + // TODO + default: + break; } + + return PUGL_SUCCESS; } // ----------------------------------------------------------------------- -static inline int -printModifiers(const uint32_t mods) +static int printModifiers(const uint32_t mods) { return fprintf(stderr, "Modifiers:%s%s%s%s\n", (mods & PUGL_MOD_SHIFT) ? " Shift" : "", @@ -409,8 +349,7 @@ printModifiers(const uint32_t mods) (mods & PUGL_MOD_SUPER) ? " Super" : ""); } -static inline int -printEvent(const PuglEvent* event, const char* prefix, const bool verbose) +static int printEvent(const PuglEvent* event, const char* prefix, const bool verbose) { #define FFMT "%6.1f" #define PFMT FFMT " " FFMT @@ -526,9 +465,156 @@ printEvent(const PuglEvent* event, const char* prefix, const bool verbose) return 0; } +// ----------------------------------------------------------------------- + +void Window::PrivateData::Fallback::onDisplayBefore(const GraphicsContext&) +{ +#ifdef DGL_OPENGL + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); +#endif +} + +void Window::PrivateData::Fallback::onDisplayAfter(const GraphicsContext&) +{ +} + +void Window::PrivateData::Fallback::onReshape(const GraphicsContext&, const uint width, const uint height) +{ +#ifdef DGL_OPENGL + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0.0, static_cast(width), static_cast(height), 0.0, 0.0, 1.0); + glViewport(0, 0, static_cast(width), static_cast(height)); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +#else + // unused + (void)width; + (void)height; +#endif +} + +// ----------------------------------------------------------------------- + +END_NAMESPACE_DGL + +#if 0 +#ifdef DGL_CAIRO +# define PUGL_CAIRO +# include "../Cairo.hpp" +#endif +#ifdef DGL_OPENGL +# define PUGL_OPENGL +# include "../OpenGL.hpp" +#endif + +#ifndef DPF_TEST_WINDOW_CPP +#include "WidgetPrivateData.hpp" +#include "pugl-upstream/include/pugl/pugl.h" +#include "pugl-extra/extras.h" +#endif + +extern "C" { +#include "pugl-upstream/src/implementation.c" +#include "pugl-extra/extras.c" +} + +#if defined(DISTRHO_OS_HAIKU) +# define DGL_DEBUG_EVENTS +# include "pugl-upstream/src/haiku.cpp" +#elif defined(DISTRHO_OS_MAC) +# include "pugl-upstream/src/mac.m" +#elif defined(DISTRHO_OS_WINDOWS) +# include "ppugl-upstream/src/win.c" +# undef max +# undef min +#else +# define DGL_PUGL_USING_X11 +extern "C" { +# include "pugl-upstream/src/x11.c" +// # ifdef DGL_CAIRO +// # include "pugl-upstream/src/x11_cairo.c" +// # endif +# ifdef DGL_OPENGL +# include "pugl-upstream/src/x11_gl.c" +# endif +# define PUGL_DETAIL_X11_H_INCLUDED +# include "pugl-extra/x11.c" +} +#endif + +#include +#include +#include +#include +#include +#include + +START_NAMESPACE_DGL + +#define FOR_EACH_WIDGET(it) \ + for (std::list::iterator it = fWidgets.begin(); it != fWidgets.end(); ++it) + +#define FOR_EACH_WIDGET_INV(rit) \ + for (std::list::reverse_iterator rit = fWidgets.rbegin(); rit != fWidgets.rend(); ++rit) + +// ----------------------------------------------------------------------- + +void Window::PrivateData::addWidget(Widget* const widget) +{ + fWidgets.push_back(widget); +} + +void Window::PrivateData::removeWidget(Widget* const widget) +{ + fWidgets.remove(widget); +} + +// ----------------------------------------------------------------------- + +void Window::PrivateData::onPuglClose() +{ + DGL_DBG("PUGL: onClose\n"); + +// if (fModal.enabled) +// exec_fini(); + + fSelf->onClose(); + + if (fModal.childFocus != nullptr) + fModal.childFocus->fSelf->onClose(); + + close(); +} + +void Window::PrivateData::onPuglMouse(const Widget::MouseEvent& ev) +{ + DGL_DBGp("PUGL: onMouse : %i %i %i %i\n", ev.button, ev.press, ev.pos.getX(), ev.pos.getY()); + +// if (fModal.childFocus != nullptr) +// return fModal.childFocus->focus(); + + Widget::MouseEvent rev = ev; + double x = ev.pos.getX() / fAutoScaling; + double y = ev.pos.getY() / fAutoScaling; + + FOR_EACH_WIDGET_INV(rit) + { + Widget* const widget(*rit); + + rev.pos = Point(x - widget->getAbsoluteX(), + y - widget->getAbsoluteY()); + + if (widget->isVisible() && widget->onMouse(rev)) + break; + } +} + PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const PuglEvent* const event) { - printEvent(event, "", true); Window::PrivateData* const pData = (Window::PrivateData*)puglGetHandle(view); switch (event->type) @@ -607,37 +693,5 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu // ----------------------------------------------------------------------- -void Window::PrivateData::Fallback::onDisplayBefore() -{ -#ifdef DGL_OPENGL - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glLoadIdentity(); -#endif -} - -void Window::PrivateData::Fallback::onDisplayAfter() -{ -} - -void Window::PrivateData::Fallback::onReshape(const uint width, const uint height) -{ -#ifdef DGL_OPENGL - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0.0, static_cast(width), static_cast(height), 0.0, 0.0, 1.0); - glViewport(0, 0, static_cast(width), static_cast(height)); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); -#else - // unused - (void)width; - (void)height; -#endif -} - -// ----------------------------------------------------------------------- - END_NAMESPACE_DGL #endif diff --git a/dgl/src/WindowPrivateData.hpp b/dgl/src/WindowPrivateData.hpp index ae326454..f50dd632 100644 --- a/dgl/src/WindowPrivateData.hpp +++ b/dgl/src/WindowPrivateData.hpp @@ -40,6 +40,9 @@ struct Window::PrivateData : IdleCallback { /** Pugl view instance. */ PuglView* const view; + /** Reserved space for graphics context. */ + mutable uint8_t graphicsContext[sizeof(void*)]; + /** 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; @@ -57,13 +60,17 @@ struct Window::PrivateData : IdleCallback { PrivateData(AppData* appData, Window* self, Window& transientWindow); /** Constructor for an embed Window, with a few extra hints from the host side. */ - PrivateData(AppData* appData, Window* self, uintptr_t parentWindowHandle, double scaling, bool resizable); + PrivateData(AppData* appData, Window* self, uintptr_t parentWindowHandle, + uint width, uint height, double scaling, bool resizable); /** Destructor. */ ~PrivateData() override; /** Helper initialization function called at the end of all this class constructors. */ - void init(bool resizable); + void init(uint width, uint height, bool resizable); + + void show(); + void hide(); /** Hide window and notify application of a window close event. * Does nothing if window is embed (that is, not standalone). @@ -74,12 +81,24 @@ struct Window::PrivateData : IdleCallback { */ void close(); - void setVisible(bool visible); + const GraphicsContext& getGraphicsContext() const noexcept; void idleCallback() override; + // pugl events + void onPuglDisplay(); + void onPuglReshape(int width, int height); + + // Pugl event handling entry point static PuglStatus puglEventCallback(PuglView* view, const PuglEvent* event); + // Fallback build-specific Window functions + struct Fallback { + static void onDisplayBefore(const GraphicsContext& context); + static void onDisplayAfter(const GraphicsContext& context); + static void onReshape(const GraphicsContext& context, uint width, uint height); + }; + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData) }; @@ -161,8 +180,6 @@ END_NAMESPACE_DGL // ------------------------------------------------------------------- void onPuglClose(); - void onPuglDisplay(); - void onPuglReshape(const int width, const int height); void onPuglMouse(const Widget::MouseEvent& ev); // ------------------------------------------------------------------- diff --git a/dgl/src/pugl-upstream b/dgl/src/pugl-upstream index 5a3a1309..b0a018a0 160000 --- a/dgl/src/pugl-upstream +++ b/dgl/src/pugl-upstream @@ -1 +1 @@ -Subproject commit 5a3a1309ad6432d72cdb7f37e3e36383dd6ba372 +Subproject commit b0a018a006c5d7d7796074b86c1b69f8671d2d83 diff --git a/dgl/src/pugl.cpp b/dgl/src/pugl.cpp index dc39fc31..0307107d 100644 --- a/dgl/src/pugl.cpp +++ b/dgl/src/pugl.cpp @@ -35,6 +35,10 @@ # include # include # include +# ifdef HAVE_XCURSOR +# include +# include +# endif # ifdef HAVE_XRANDR # include # endif @@ -42,10 +46,6 @@ # include # include # endif -# ifdef HAVE_XCURSOR -# include -# include -# endif # ifdef DGL_CAIRO # include # include @@ -85,6 +85,74 @@ START_NAMESPACE_DGL #include "pugl-upstream/src/implementation.c" +// -------------------------------------------------------------------------------------------------------------------- +// missing in pugl, directly returns title char* pointer + +const char* puglGetWindowTitle(const PuglView* view) +{ + return view->title; +} + +// -------------------------------------------------------------------------------------------------------------------- +// set window size without changing frame x/y position + +PuglStatus puglSetWindowSize(PuglView* view, unsigned int width, unsigned int height) +{ +#if defined(DISTRHO_OS_HAIKU) || defined(DISTRHO_OS_MAC) + // TODO + const PuglRect frame = { 0.0, 0.0, (double)width, (double)height }; + return puglSetFrame(view, frame); +#elif defined(DISTRHO_OS_WINDOWS) + // matches upstream pugl, except we add SWP_NOMOVE flag + if (view->impl->hwnd) + { + RECT rect = { (long)frame.x, + (long)frame.y, + (long)frame.x + (long)frame.width, + (long)frame.y + (long)frame.height }; + + AdjustWindowRectEx(&rect, puglWinGetWindowFlags(view), FALSE, puglWinGetWindowExFlags(view)); + + if (! SetWindowPos(view->impl->hwnd, + HWND_TOP, + rect.left, + rect.top, + rect.right - rect.left, + rect.bottom - rect.top, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER)) + return PUGL_UNKNOWN_ERROR; + } +#else + // matches upstream pugl, except we use XResizeWindow instead of XMoveResizeWindow + if (view->impl->win) + { + if (! XResizeWindow(view->world->impl->display, view->impl->win, width, height)) + return PUGL_UNKNOWN_ERROR; +#if 0 + if (! fResizable) + { + XSizeHints sizeHints; + memset(&sizeHints, 0, sizeof(sizeHints)); + + sizeHints.flags = PSize|PMinSize|PMaxSize; + sizeHints.width = static_cast(width); + sizeHints.height = static_cast(height); + sizeHints.min_width = static_cast(width); + sizeHints.min_height = static_cast(height); + sizeHints.max_width = static_cast(width); + sizeHints.max_height = static_cast(height); + + XSetWMNormalHints(xDisplay, xWindow, &sizeHints); + } +#endif + } +#endif + + view->frame.width = width; + view->frame.height = height; + return PUGL_SUCCESS; +} + // -------------------------------------------------------------------------------------------------------------------- END_NAMESPACE_DGL diff --git a/dgl/src/pugl.hpp b/dgl/src/pugl.hpp index 3d5374e5..4d58b87a 100644 --- a/dgl/src/pugl.hpp +++ b/dgl/src/pugl.hpp @@ -31,6 +31,18 @@ START_NAMESPACE_DGL #define PUGL_DISABLE_DEPRECATED #include "pugl-upstream/include/pugl/pugl.h" +PUGL_BEGIN_DECLS + +// missing in pugl, directly returns title char* pointer +PUGL_API const char* +puglGetWindowTitle(const PuglView* view); + +// set window size without changing frame x/y position +PUGL_API PuglStatus +puglSetWindowSize(PuglView* view, unsigned int width, unsigned int height); + +PUGL_END_DECLS + // -------------------------------------------------------------------------------------------------------------------- END_NAMESPACE_DGL diff --git a/tests/Application.cpp b/tests/Application.cpp index 95c08e61..b9859804 100644 --- a/tests/Application.cpp +++ b/tests/Application.cpp @@ -21,34 +21,10 @@ #include "dgl/src/Application.cpp" #include "dgl/src/ApplicationPrivateData.cpp" -#include "distrho/extra/Thread.hpp" - START_NAMESPACE_DGL // -------------------------------------------------------------------------------------------------------------------- -class ApplicationQuitter : public Thread -{ - Application& app; - -public: - ApplicationQuitter(Application& a) - : Thread("ApplicationQuitter"), - app(a) - { - startThread(); - } - -private: - void run() override - { - d_sleep(2); - app.quit(); - } -}; - -// -------------------------------------------------------------------------------------------------------------------- - struct IdleCallbackCounter : IdleCallback { int counter; diff --git a/tests/Makefile b/tests/Makefile index e7a413dd..276b3360 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -45,39 +45,32 @@ endif ifeq ($(HAVE_OPENGL),true) endif +ifeq ($(HAVE_VULKAN),true) +endif + # --------------------------------------------------------------------------------------------------------------------- all: $(TARGETS) # --------------------------------------------------------------------------------------------------------------------- -../build/tests/%: ../build/tests/%.cpp.o - @echo "Linking $*" - $(SILENT)$(CXX) $< $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) -o $@ - @echo "Running test for $*" - $(SILENT)$@ +define RUN_TEST + + ${1} +endef + # valgrind --leak-check=full $@ -../build/tests/%.cairo: ../build/tests/%.cpp.cairo.o - @echo "Linking $*" - $(SILENT)$(CXX) $< $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) $(CAIRO_LIBS) -o $@ - @echo "Running test for $*" - $(SILENT)$@ +run: $(TARGETS) + $(foreach TEST,$(TARGETS),$(call RUN_TEST,$(TEST))) -../build/tests/%.opengl: ../build/tests/%.cpp.opengl.o - @echo "Linking $*" - $(SILENT)$(CXX) $< $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) $(OPENGL_LIBS) -o $@ - @echo "Running test for $*" - $(SILENT) $@ -# gdb -ex run +# --------------------------------------------------------------------------------------------------------------------- -../build/tests/%.vulkan: ../build/tests/%.cpp.vulkan.o - @echo "Linking $*" - $(SILENT)$(CXX) $< $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) $(VULKAN_LIBS) -o $@ - @echo "Running test for $*" - $(SILENT)$@ +clean: + rm -rf ../build/tests # --------------------------------------------------------------------------------------------------------------------- +# building steps ../build/tests/%.c.o: %.c -@mkdir -p ../build/tests @@ -105,9 +98,23 @@ all: $(TARGETS) $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(OPENGL_FLAGS) -DDGL_VULKAN -c -o $@ # --------------------------------------------------------------------------------------------------------------------- +# linking steps -clean: - rm -rf ../build/tests +../build/tests/%: ../build/tests/%.cpp.o + @echo "Linking $*" + $(SILENT)$(CXX) $< $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) -o $@ + +../build/tests/%.cairo: ../build/tests/%.cpp.cairo.o + @echo "Linking $*" + $(SILENT)$(CXX) $< $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) $(CAIRO_LIBS) -o $@ + +../build/tests/%.opengl: ../build/tests/%.cpp.opengl.o + @echo "Linking $*" + $(SILENT)$(CXX) $< $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) $(OPENGL_LIBS) -o $@ + +../build/tests/%.vulkan: ../build/tests/%.cpp.vulkan.o + @echo "Linking $*" + $(SILENT)$(CXX) $< $(LINK_FLAGS) $(DGL_SYSTEM_LIBS) $(VULKAN_LIBS) -o $@ # --------------------------------------------------------------------------------------------------------------------- diff --git a/tests/Window.cpp b/tests/Window.cpp index 7de187e1..2c726278 100644 --- a/tests/Window.cpp +++ b/tests/Window.cpp @@ -21,9 +21,11 @@ #include "tests.hpp" #define DPF_TEST_WINDOW_CPP +#define DPF_TEST_POINT_CPP #include "dgl/src/pugl.cpp" #include "dgl/src/Application.cpp" #include "dgl/src/ApplicationPrivateData.cpp" +#include "dgl/src/Geometry.cpp" #include "dgl/src/Window.cpp" #include "dgl/src/WindowPrivateData.cpp" @@ -35,11 +37,27 @@ int main() using DGL_NAMESPACE::Window; - // creating simple window + // creating and destroying simple window { Application app(true); Window win(app); - app.idle(); + } + + // creating and destroying simple window, with a delay + { + Application app(true); + ApplicationQuitter appQuitter(app); + Window win(app); + app.exec(); + } + + // showing and closing simple window, MUST be visible on screen + { + Application app(true); + ApplicationQuitter appQuitter(app); + Window win(app); + win.show(); + app.exec(); } // TODO diff --git a/tests/tests.hpp b/tests/tests.hpp index f3aeae85..37bdd6f1 100644 --- a/tests/tests.hpp +++ b/tests/tests.hpp @@ -14,10 +14,40 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "dgl/Base.hpp" +#include "dgl/Application.hpp" + +#include "distrho/extra/Thread.hpp" #define DISTRHO_ASSERT_EQUAL(v1, v2, msg) \ if (v1 != v2) { d_stderr2("Test condition failed: %s; file:%s line:%i", msg, __FILE__, __LINE__); return 1; } #define DISTRHO_ASSERT_NOT_EQUAL(v1, v2, msg) \ if (v1 == v2) { d_stderr2("Test condition failed: %s; file:%s line:%i", msg, __FILE__, __LINE__); return 1; } + +START_NAMESPACE_DGL + +// -------------------------------------------------------------------------------------------------------------------- + +class ApplicationQuitter : public Thread +{ + Application& app; + +public: + ApplicationQuitter(Application& a) + : Thread("ApplicationQuitter"), + app(a) + { + startThread(); + } + +private: + void run() override + { + d_sleep(2); + app.quit(); + } +}; + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DGL