Signed-off-by: falkTX <falktx@falktx.com>pull/272/head
| @@ -25,9 +25,9 @@ BUILD_CXX_FLAGS += -Wno-missing-field-initializers -Wno-extra -Wno-narrowing | |||
| OBJS_common = \ | |||
| ../build/dgl/Application.cpp.o \ | |||
| ../build/dgl/ApplicationPrivateData.cpp.o | |||
| # ../build/dgl/Color.cpp.o \ | |||
| # ../build/dgl/Geometry.cpp.o \ | |||
| ../build/dgl/ApplicationPrivateData.cpp.o \ | |||
| ../build/dgl/Color.cpp.o \ | |||
| ../build/dgl/Geometry.cpp.o | |||
| # ../build/dgl/ImageBase.cpp.o \ | |||
| # ../build/dgl/Resources.cpp.o\ | |||
| # ../build/dgl/StandaloneWindow.cpp.o \ | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
| * or without fee is hereby granted, provided that the above copyright notice and this | |||
| @@ -19,29 +19,59 @@ | |||
| #include "Geometry.hpp" | |||
| #ifdef DISTRHO_DEFINES_H_INCLUDED | |||
| START_NAMESPACE_DISTRHO | |||
| class UI; | |||
| class UIExporter; | |||
| END_NAMESPACE_DISTRHO | |||
| #endif | |||
| START_NAMESPACE_DGL | |||
| // ----------------------------------------------------------------------- | |||
| class Application; | |||
| class Widget; | |||
| class StandaloneWindow; | |||
| class Window | |||
| { | |||
| public: | |||
| explicit Window(Application& app); | |||
| explicit Window(Application& app, uintptr_t parentWindowHandle, double scaling, bool resizable); | |||
| virtual ~Window(); | |||
| void close(); | |||
| /** | |||
| Get the "native" window handle. | |||
| Returned value depends on the platform: | |||
| - HaikuOS: This is a pointer to a `BView`. | |||
| - MacOS: This is a pointer to an `NSView*`. | |||
| - Windows: This is a `HWND`. | |||
| - Everything else: This is an [X11] `Window`. | |||
| */ | |||
| uintptr_t getNativeWindowHandle() const noexcept; | |||
| private: | |||
| struct PrivateData; | |||
| PrivateData* const pData; | |||
| friend class Application; | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Window); | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DGL | |||
| /* TODO | |||
| * add focusEvent with CrossingMode arg | |||
| * add eventcrossing/enter-leave event | |||
| */ | |||
| class Window | |||
| { | |||
| public: | |||
| // class StandaloneWindow; | |||
| // class Widget; | |||
| // #ifdef DISTRHO_DEFINES_H_INCLUDED | |||
| // START_NAMESPACE_DISTRHO | |||
| // class UI; | |||
| // class UIExporter; | |||
| // END_NAMESPACE_DISTRHO | |||
| // #endif | |||
| #if 0 | |||
| #ifndef DGL_FILE_BROWSER_DISABLED | |||
| /** | |||
| File browser options. | |||
| @@ -81,14 +111,10 @@ public: | |||
| }; | |||
| #endif // DGL_FILE_BROWSER_DISABLED | |||
| explicit Window(Application& app); | |||
| explicit Window(Window& transientParentWindow); | |||
| explicit Window(Application& app, uintptr_t parentWindowHandle, double scaling, bool resizable); | |||
| virtual ~Window(); | |||
| static Window& withTransientParentWindow(Window& transientParentWindow); | |||
| void show(); | |||
| void hide(); | |||
| void close(); | |||
| void exec(bool lockWait = false); | |||
| void focus(); | |||
| @@ -129,21 +155,12 @@ public: | |||
| Application& getApp() const noexcept; | |||
| #endif | |||
| /** | |||
| Get the "native" window handle. | |||
| Returned value depends on the platform: | |||
| - HaikuOS: This is a pointer to a `BView`. | |||
| - MacOS: This is a pointer to an `NSView*`. | |||
| - Windows: This is a `HWND`. | |||
| - Everything else: This is an [X11] `Window`. | |||
| */ | |||
| uintptr_t getNativeWindowHandle() const noexcept; | |||
| const GraphicsContext& getGraphicsContext() const noexcept; | |||
| void addIdleCallback(IdleCallback* const callback); | |||
| void removeIdleCallback(IdleCallback* const callback); | |||
| protected: | |||
| virtual void onDisplayBefore(); | |||
| virtual void onDisplayAfter(); | |||
| @@ -157,17 +174,6 @@ protected: | |||
| // internal | |||
| void _setAutoScaling(double scaling) noexcept; | |||
| private: | |||
| struct PrivateData; | |||
| PrivateData* const pData; | |||
| friend class Application; | |||
| friend class Widget; | |||
| friend class StandaloneWindow; | |||
| #ifdef DISTRHO_DEFINES_H_INCLUDED | |||
| friend class DISTRHO_NAMESPACE::UI; | |||
| friend class DISTRHO_NAMESPACE::UIExporter; | |||
| #endif | |||
| virtual void _addWidget(Widget* const widget); | |||
| virtual void _removeWidget(Widget* const widget); | |||
| void _idle(); | |||
| @@ -175,20 +181,24 @@ private: | |||
| bool handlePluginKeyboard(const bool press, const uint key); | |||
| bool handlePluginSpecial(const bool press, const Key key); | |||
| // friend class Widget; | |||
| // friend class StandaloneWindow; | |||
| // #ifdef DISTRHO_DEFINES_H_INCLUDED | |||
| // friend class DISTRHO_NAMESPACE::UI; | |||
| // friend class DISTRHO_NAMESPACE::UIExporter; | |||
| // #endif | |||
| // Prevent copies | |||
| #ifdef DISTRHO_PROPER_CPP11_SUPPORT | |||
| Window& operator=(Window&) = delete; | |||
| Window& operator=(const Window&) = delete; | |||
| #else | |||
| Window& operator=(Window&); | |||
| Window& operator=(const Window&); | |||
| #endif | |||
| // #ifdef DISTRHO_PROPER_CPP11_SUPPORT | |||
| // Window& operator=(Window&) = delete; | |||
| // Window& operator=(const Window&) = delete; | |||
| // #else | |||
| // Window& operator=(Window&); | |||
| // Window& operator=(const Window&); | |||
| // #endif | |||
| DISTRHO_LEAK_DETECTOR(Window); | |||
| }; | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DGL | |||
| #endif // DGL_WINDOW_HPP_INCLUDED | |||
| @@ -87,13 +87,13 @@ void Application::PrivateData::idle(const uint timeoutInMs) | |||
| puglUpdate(world, timeoutInSeconds); | |||
| } | |||
| #ifndef DPF_TEST_APPLICATION_CPP | |||
| for (std::list<Window*>::iterator it = windows.begin(), ite = windows.end(); it != ite; ++it) | |||
| { | |||
| Window* const window(*it); | |||
| window->_idle(); | |||
| } | |||
| #endif | |||
| // #ifndef DPF_TEST_APPLICATION_CPP | |||
| // for (std::list<Window*>::iterator it = windows.begin(), ite = windows.end(); it != ite; ++it) | |||
| // { | |||
| // Window* const window(*it); | |||
| // window->_idle(); | |||
| // } | |||
| // #endif | |||
| for (std::list<IdleCallback*>::iterator it = idleCallbacks.begin(), ite = idleCallbacks.end(); it != ite; ++it) | |||
| { | |||
| @@ -68,7 +68,7 @@ struct Application::PrivateData { | |||
| /** Set flag indicating application is quitting, and closes all windows in reverse order of registration. */ | |||
| void quit(); | |||
| DISTRHO_DECLARE_NON_COPY_STRUCT(PrivateData) | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData) | |||
| }; | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
| * or without fee is hereby granted, provided that the above copyright notice and this | |||
| @@ -16,17 +16,19 @@ | |||
| #include "WindowPrivateData.hpp" | |||
| #include "pugl.hpp" | |||
| START_NAMESPACE_DGL | |||
| // ----------------------------------------------------------------------- | |||
| // Window | |||
| // Window::Window(Window& transientParentWindow) | |||
| // : pData(new PrivateData(transientParentWindow.pData->fAppData, this, transientParentWindow)) {} | |||
| Window::Window(Application& app) | |||
| : pData(new PrivateData(app.pData, this)) {} | |||
| Window::Window(Window& transientParentWindow) | |||
| : pData(new PrivateData(transientParentWindow.pData->fAppData, this, transientParentWindow)) {} | |||
| Window::Window(Application& app, const uintptr_t parentWindowHandle, const double scaling, const bool resizable) | |||
| : pData(new PrivateData(app.pData, this, parentWindowHandle, scaling, resizable)) {} | |||
| @@ -35,6 +37,17 @@ Window::~Window() | |||
| delete pData; | |||
| } | |||
| void Window::close() | |||
| { | |||
| pData->close(); | |||
| } | |||
| uintptr_t Window::getNativeWindowHandle() const noexcept | |||
| { | |||
| return puglGetNativeWindow(pData->view); | |||
| } | |||
| #if 0 | |||
| void Window::show() | |||
| { | |||
| pData->setVisible(true); | |||
| @@ -45,11 +58,6 @@ void Window::hide() | |||
| pData->setVisible(false); | |||
| } | |||
| void Window::close() | |||
| { | |||
| pData->close(); | |||
| } | |||
| #if 0 | |||
| void Window::exec(bool lockWait) | |||
| { | |||
| @@ -191,11 +199,6 @@ Application& Window::getApp() const noexcept | |||
| } | |||
| #endif | |||
| uintptr_t Window::getNativeWindowHandle() const noexcept | |||
| { | |||
| return puglGetNativeWindow(pData->fView); | |||
| } | |||
| #if 0 | |||
| const GraphicsContext& Window::getGraphicsContext() const noexcept | |||
| { | |||
| @@ -285,6 +288,7 @@ bool Window::handlePluginSpecial(const bool press, const Key key) | |||
| return false; | |||
| // return pData->handlePluginSpecial(press, key); | |||
| } | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
| * or without fee is hereby granted, provided that the above copyright notice and this | |||
| @@ -15,7 +15,116 @@ | |||
| */ | |||
| #include "WindowPrivateData.hpp" | |||
| #include "../Widget.hpp" | |||
| #include "pugl.hpp" | |||
| START_NAMESPACE_DGL | |||
| // ----------------------------------------------------------------------- | |||
| Window::PrivateData::PrivateData(Application::PrivateData* const a, Window* const s) | |||
| : appData(a), | |||
| self(s), | |||
| view(puglNewView(appData->world)) | |||
| { | |||
| init(true); | |||
| } | |||
| Window::PrivateData::PrivateData(Application::PrivateData* const a, Window* const s, Window& transientWindow) | |||
| : appData(a), | |||
| self(s), | |||
| view(puglNewView(appData->world)) | |||
| { | |||
| 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)) | |||
| { | |||
| // TODO view parent | |||
| init(resizable); | |||
| } | |||
| Window::PrivateData::~PrivateData() | |||
| { | |||
| if (self != nullptr) | |||
| appData->windows.remove(self); | |||
| if (view != nullptr) | |||
| puglFreeView(view); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| void Window::PrivateData::init(const bool resizable) | |||
| { | |||
| if (self == nullptr || view == nullptr) | |||
| { | |||
| /* | |||
| DGL_DBG("Failed!\n"); | |||
| */ | |||
| return; | |||
| } | |||
| #ifdef DGL_CAIRO | |||
| puglSetBackend(view, puglCairoBackend()); | |||
| #endif | |||
| #ifdef DGL_OPENGL | |||
| puglSetBackend(view, puglGlBackend()); | |||
| #endif | |||
| #ifdef DGL_Vulkan | |||
| puglSetBackend(view, puglVulkanBackend()); | |||
| #endif | |||
| puglSetHandle(view, this); | |||
| puglSetViewHint(view, PUGL_RESIZABLE, resizable ? PUGL_TRUE : PUGL_FALSE); | |||
| puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, PUGL_FALSE); | |||
| puglSetEventFunc(view, puglEventCallback); | |||
| // #ifndef DGL_FILE_BROWSER_DISABLED | |||
| // puglSetFileSelectedFunc(fView, fileBrowserSelectedCallback); | |||
| // #endif | |||
| appData->windows.push_back(self); | |||
| // DGL_DBG("Success!\n"); | |||
| } | |||
| void Window::PrivateData::close() | |||
| { | |||
| /* | |||
| DGL_DBG("Window close\n"); | |||
| if (fUsingEmbed) | |||
| return; | |||
| setVisible(false); | |||
| if (! fFirstInit) | |||
| { | |||
| fAppData->oneWindowHidden(); | |||
| fFirstInit = true; | |||
| } | |||
| */ | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| 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" | |||
| @@ -25,6 +134,12 @@ | |||
| # 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" | |||
| @@ -63,38 +178,151 @@ extern "C" { | |||
| #include <stdio.h> | |||
| #include <string.h> | |||
| #define FOR_EACH_WIDGET(it) \ | |||
| for (std::list<Widget*>::iterator it = fWidgets.begin(); it != fWidgets.end(); ++it) | |||
| #define FOR_EACH_WIDGET_INV(rit) \ | |||
| for (std::list<Widget*>::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 | |||
| START_NAMESPACE_DGL | |||
| // Fallback build-specific Window functions | |||
| struct Fallback { | |||
| static void onDisplayBefore(); | |||
| static void onDisplayAfter(); | |||
| static void onReshape(uint width, uint height); | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| void Window::PrivateData::init(const bool resizable) | |||
| 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() | |||
| { | |||
| if (fSelf == nullptr || fView == nullptr) | |||
| 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("Failed!\n"); | |||
| return; | |||
| DGL_DBG("Creating embedded window..."); DGL_DBGF; | |||
| puglSetParentWindow(fView, parentWindowHandle); | |||
| } | |||
| else | |||
| { | |||
| DGL_DBG("Creating window without parent..."); DGL_DBGF; | |||
| } | |||
| // #ifdef DGL_CAIRO | |||
| // puglSetBackend(fView, puglCairoBackend()); | |||
| // #endif | |||
| #ifdef DGL_OPENGL | |||
| puglSetBackend(fView, puglGlBackend()); | |||
| 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 | |||
| puglSetHandle(fView, this); | |||
| puglSetViewHint(fView, PUGL_RESIZABLE, resizable ? PUGL_TRUE : PUGL_FALSE); | |||
| puglSetViewHint(fView, PUGL_IGNORE_KEY_REPEAT, PUGL_FALSE); | |||
| puglSetEventFunc(fView, puglEventCallback); | |||
| // #ifndef DGL_FILE_BROWSER_DISABLED | |||
| // puglSetFileSelectedFunc(fView, fileBrowserSelectedCallback); | |||
| // #endif | |||
| fWidgets.clear(); | |||
| fAppData->windows.push_back(fSelf); | |||
| 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) | |||
| @@ -160,6 +388,97 @@ void Window::PrivateData::setVisible(const bool visible) | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| 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::onPuglDisplay() | |||
| { | |||
| fSelf->onDisplayBefore(); | |||
| if (fWidgets.size() != 0) | |||
| { | |||
| const PuglRect rect = puglGetFrame(fView); | |||
| const int width = rect.width; | |||
| const int height = rect.height; | |||
| FOR_EACH_WIDGET(it) | |||
| { | |||
| Widget* const widget(*it); | |||
| widget->pData->display(width, height, fAutoScaling, false); | |||
| } | |||
| } | |||
| fSelf->onDisplayAfter(); | |||
| } | |||
| void Window::PrivateData::onPuglReshape(const int width, const int height) | |||
| { | |||
| DISTRHO_SAFE_ASSERT_INT2_RETURN(width > 1 && height > 1, width, height,); | |||
| DGL_DBGp("PUGL: onReshape : %i %i\n", width, height); | |||
| fSelf->onReshape(width, height); | |||
| FOR_EACH_WIDGET(it) | |||
| { | |||
| Widget* const widget(*it); | |||
| 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(); | |||
| 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<double>(x - widget->getAbsoluteX(), | |||
| y - widget->getAbsoluteY()); | |||
| if (widget->isVisible() && widget->onMouse(rev)) | |||
| break; | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| void Window::PrivateData::windowSpecificIdle() | |||
| { | |||
| #if defined(DISTRHO_OS_WINDOWS) && !defined(DGL_FILE_BROWSER_DISABLED) | |||
| @@ -418,3 +737,4 @@ void Window::PrivateData::Fallback::onReshape(const uint width, const uint heigh | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DGL | |||
| #endif | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
| * or without fee is hereby granted, provided that the above copyright notice and this | |||
| @@ -18,44 +18,41 @@ | |||
| #define DGL_WINDOW_PRIVATE_DATA_HPP_INCLUDED | |||
| #include "../Window.hpp" | |||
| #include "ApplicationPrivateData.hpp" | |||
| #include "WidgetPrivateData.hpp" | |||
| #include "pugl-upstream/include/pugl/pugl.h" | |||
| #include "pugl-extra/extras.h" | |||
| #include "pugl.hpp" | |||
| #include <vector> | |||
| START_NAMESPACE_DGL | |||
| #define FOR_EACH_WIDGET(it) \ | |||
| for (std::list<Widget*>::iterator it = fWidgets.begin(); it != fWidgets.end(); ++it) | |||
| class Widget; | |||
| #define FOR_EACH_WIDGET_INV(rit) \ | |||
| for (std::list<Widget*>::reverse_iterator rit = fWidgets.rbegin(); rit != fWidgets.rend(); ++rit) | |||
| // ----------------------------------------------------------------------- | |||
| #define DGL_DEBUG_EVENTS | |||
| struct Window::PrivateData { | |||
| typedef Application::PrivateData AppData; | |||
| #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 | |||
| AppData* const appData; | |||
| Window* const self; | |||
| PuglView* const view; | |||
| START_NAMESPACE_DGL | |||
| PrivateData(AppData* appData, Window* self); | |||
| PrivateData(AppData* appData, Window* self, Window& transientWindow); | |||
| PrivateData(AppData* appData, Window* self, uintptr_t parentWindowHandle, double scaling, bool resizable); | |||
| ~PrivateData(); | |||
| // ----------------------------------------------------------------------- | |||
| void init(bool resizable); | |||
| void close(); | |||
| struct Window::PrivateData { | |||
| typedef Application::PrivateData AppData; | |||
| static PuglStatus puglEventCallback(PuglView* view, const PuglEvent* event); | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| AppData* const fAppData; | |||
| Window* const fSelf; | |||
| PuglView* const fView; | |||
| END_NAMESPACE_DGL | |||
| #if 0 | |||
| // this one depends on build type | |||
| // GraphicsContext fContext; | |||
| @@ -109,272 +106,36 @@ struct Window::PrivateData { | |||
| String fSelectedFile; | |||
| # endif | |||
| #endif | |||
| // Fallback build-specific Window functions | |||
| struct Fallback { | |||
| static void onDisplayBefore(); | |||
| static void onDisplayAfter(); | |||
| static void onReshape(uint width, uint height); | |||
| }; | |||
| /* | |||
| PrivateData(Application& app, Window* const self) | |||
| : fApp(app), | |||
| fSelf(self) | |||
| { | |||
| } | |||
| PrivateData(Application& app, Window* const self, Window& parent) | |||
| : fApp(app), | |||
| fSelf(self) | |||
| { | |||
| } | |||
| PrivateData(Application& app, Window* const self, const intptr_t parentId, const double scaling, const bool resizable) | |||
| : fApp(app), | |||
| fSelf(self) | |||
| { | |||
| } | |||
| */ | |||
| 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(); | |||
| } | |||
| 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()); | |||
| } | |||
| 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; | |||
| } | |||
| } | |||
| ~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"); | |||
| } | |||
| #if 0 // ndef DPF_TEST_WINDOW_CPP | |||
| // ------------------------------------------------------------------- | |||
| // stuff that uses pugl internals or build-specific things | |||
| void init(const bool resizable = false); | |||
| void setVisible(const bool visible); | |||
| void windowSpecificIdle(); | |||
| static PuglStatus puglEventCallback(PuglView* const view, const PuglEvent* const event); | |||
| // ------------------------------------------------------------------- | |||
| void close() | |||
| { | |||
| DGL_DBG("Window close\n"); | |||
| if (fUsingEmbed) | |||
| return; | |||
| setVisible(false); | |||
| if (! fFirstInit) | |||
| { | |||
| fAppData->oneWindowHidden(); | |||
| fFirstInit = true; | |||
| } | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| void addWidget(Widget* const widget) | |||
| { | |||
| fWidgets.push_back(widget); | |||
| } | |||
| void removeWidget(Widget* const widget) | |||
| { | |||
| fWidgets.remove(widget); | |||
| } | |||
| void addWidget(Widget* const widget); | |||
| void removeWidget(Widget* const widget); | |||
| // ------------------------------------------------------------------- | |||
| void onPuglClose() | |||
| { | |||
| DGL_DBG("PUGL: onClose\n"); | |||
| // if (fModal.enabled) | |||
| // exec_fini(); | |||
| fSelf->onClose(); | |||
| if (fModal.childFocus != nullptr) | |||
| fModal.childFocus->fSelf->onClose(); | |||
| close(); | |||
| } | |||
| void onPuglDisplay() | |||
| { | |||
| fSelf->onDisplayBefore(); | |||
| if (fWidgets.size() != 0) | |||
| { | |||
| const PuglRect rect = puglGetFrame(fView); | |||
| const int width = rect.width; | |||
| const int height = rect.height; | |||
| FOR_EACH_WIDGET(it) | |||
| { | |||
| Widget* const widget(*it); | |||
| widget->pData->display(width, height, fAutoScaling, false); | |||
| } | |||
| } | |||
| fSelf->onDisplayAfter(); | |||
| } | |||
| void onPuglReshape(const int width, const int height) | |||
| { | |||
| DISTRHO_SAFE_ASSERT_INT2_RETURN(width > 1 && height > 1, width, height,); | |||
| DGL_DBGp("PUGL: onReshape : %i %i\n", width, height); | |||
| fSelf->onReshape(width, height); | |||
| FOR_EACH_WIDGET(it) | |||
| { | |||
| Widget* const widget(*it); | |||
| if (widget->pData->needsFullViewport) | |||
| widget->setSize(width, height); | |||
| } | |||
| } | |||
| void 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<double>(x - widget->getAbsoluteX(), | |||
| y - widget->getAbsoluteY()); | |||
| if (widget->isVisible() && widget->onMouse(rev)) | |||
| break; | |||
| } | |||
| } | |||
| void onPuglClose(); | |||
| void onPuglDisplay(); | |||
| void onPuglReshape(const int width, const int height); | |||
| void onPuglMouse(const Widget::MouseEvent& ev); | |||
| // ------------------------------------------------------------------- | |||
| #ifdef DISTRHO_DEFINES_H_INCLUDED | |||
| friend class DISTRHO_NAMESPACE::UI; | |||
| #endif | |||
| DISTRHO_DECLARE_NON_COPY_STRUCT(PrivateData) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DGL | |||
| // #ifdef DISTRHO_DEFINES_H_INCLUDED | |||
| // friend class DISTRHO_NAMESPACE::UI; | |||
| // #endif | |||
| #if 0 | |||
| // ----------------------------------------------------------------------- | |||
| @@ -27,6 +27,7 @@ | |||
| #elif defined(DISTRHO_OS_MAC) | |||
| #elif defined(DISTRHO_OS_WINDOWS) | |||
| #else | |||
| # include <dlfcn.h> | |||
| # include <sys/select.h> | |||
| # include <sys/time.h> | |||
| # include <X11/X.h> | |||
| @@ -45,17 +46,39 @@ | |||
| # include <X11/Xcursor/Xcursor.h> | |||
| # include <X11/cursorfont.h> | |||
| # endif | |||
| # ifdef DGL_CAIRO | |||
| # include <cairo.h> | |||
| # include <cairo-xlib.h> | |||
| # endif | |||
| # ifdef DGL_OPENGL | |||
| # include <GL/glx.h> | |||
| # endif | |||
| # ifdef DGL_VULKAN | |||
| # include <vulkan/vulkan_core.h> | |||
| # include <vulkan/vulkan_xlib.h> | |||
| # endif | |||
| #endif | |||
| START_NAMESPACE_DGL | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| #define PUGL_DISABLE_DEPRECATED | |||
| #if defined(DISTRHO_OS_HAIKU) | |||
| #elif defined(DISTRHO_OS_MAC) | |||
| #elif defined(DISTRHO_OS_WINDOWS) | |||
| #else | |||
| # 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 | |||
| # ifdef DGL_VULKAN | |||
| # include "pugl-upstream/src/x11_vulkan.c" | |||
| # endif | |||
| #endif | |||
| #include "pugl-upstream/src/implementation.c" | |||
| @@ -28,6 +28,7 @@ START_NAMESPACE_DGL | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| #define PUGL_DISABLE_DEPRECATED | |||
| #include "pugl-upstream/include/pugl/pugl.h" | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| @@ -20,9 +20,19 @@ BUILD_CXX_FLAGS += -Wno-missing-field-initializers -Wno-extra | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| TESTS = Application Color Point | |||
| TARGETS = $(TESTS:%=../build/tests/%) | |||
| OBJS = $(TARGETS:%=%.cpp.o) | |||
| TESTS = Application Color Point | |||
| ifeq ($(HAVE_CAIRO),true) | |||
| WTESTS = Window.cairo | |||
| endif | |||
| ifeq ($(HAVE_OPENGL),true) | |||
| WTESTS = Window.opengl | |||
| endif | |||
| ifeq ($(HAVE_VULKAN),true) | |||
| WTESTS = Window.vulkan | |||
| endif | |||
| TARGETS = $(TESTS:%=../build/tests/%) | |||
| TARGETS += $(WTESTS:Window.%=../build/tests/Window.%) | |||
| OBJS = $(TARGETS:%=%.cpp.o) | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| @@ -45,6 +55,25 @@ all: $(TARGETS) | |||
| $(SILENT)$@ | |||
| # 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)$@ | |||
| ../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)$@ | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| ../build/tests/%.c.o: %.c | |||
| @@ -57,14 +86,26 @@ all: $(TARGETS) | |||
| @echo "Compiling $<" | |||
| $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||
| ../build/tests/%.cpp.cairo.o: %.cpp | |||
| -@mkdir -p ../build/tests | |||
| @echo "Compiling $< (Cairo)" | |||
| $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(CAIRO_FLAGS) -DDGL_CAIRO -c -o $@ | |||
| ../build/tests/%.cpp.opengl.o: %.cpp | |||
| -@mkdir -p ../build/tests | |||
| @echo "Compiling $< (OpenGL)" | |||
| $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(OPENGL_FLAGS) -DDGL_OPENGL -c -o $@ | |||
| ../build/tests/%.cpp.vulkan.o: Window.cpp | |||
| -@mkdir -p ../build/tests | |||
| @echo "Compiling $< (Vulkan)" | |||
| $(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) $(OPENGL_FLAGS) -DDGL_VULKAN -c -o $@ | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| clean: | |||
| rm -rf ../build/tests | |||
| debug: | |||
| $(MAKE) DEBUG=true | |||
| # --------------------------------------------------------------------------------------------------------------------- | |||
| -include $(OBJS:%.o=%.d) | |||
| @@ -31,14 +31,22 @@ static int runTestsPerType() | |||
| Point<T> p; | |||
| DISTRHO_ASSERT_EQUAL(p.getX(), 0, "point start X value is 0"); | |||
| DISTRHO_ASSERT_EQUAL(p.getY(), 0, "point start Y value is 0"); | |||
| DISTRHO_ASSERT_EQUAL(p.isZero(), true, "point start is zero"); | |||
| DISTRHO_ASSERT_EQUAL(p.isNotZero(), false, "point start is for sure zero"); | |||
| p.setX(5); | |||
| DISTRHO_ASSERT_EQUAL(p.getX(), 5, "point X value changed to 5"); | |||
| DISTRHO_ASSERT_EQUAL(p.getY(), 0, "point start Y value remains 0"); | |||
| DISTRHO_ASSERT_EQUAL(p.isZero(), false, "point after custom X is not zero"); | |||
| DISTRHO_ASSERT_EQUAL(p.isNotZero(), true, "point after custom X is for sure not zero"); | |||
| p.setY(7); | |||
| DISTRHO_ASSERT_EQUAL(p.getX(), 5, "point X value remains 5"); | |||
| DISTRHO_ASSERT_EQUAL(p.getY(), 7, "point Y value changed to 7"); | |||
| DISTRHO_ASSERT_EQUAL(p.isZero(), false, "point after custom X and Y is not zero"); | |||
| DISTRHO_ASSERT_EQUAL(p.isNotZero(), true, "point after custom X and Y is for sure not zero"); | |||
| // TODO everything else | |||
| } | |||
| return 0; | |||
| @@ -0,0 +1,49 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
| * or without fee is hereby granted, provided that the above copyright notice and this | |||
| * permission notice appear in all copies. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |||
| * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |||
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |||
| * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||
| * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
| */ | |||
| #if !(defined(DGL_CAIRO) || defined(DGL_OPENGL) || defined(DGL_VULKAN)) | |||
| # error test setup failed, must be for cairo, opengl or vulkan | |||
| #endif | |||
| #include "tests.hpp" | |||
| #define DPF_TEST_WINDOW_CPP | |||
| #include "dgl/src/pugl.cpp" | |||
| #include "dgl/src/Application.cpp" | |||
| #include "dgl/src/ApplicationPrivateData.cpp" | |||
| #include "dgl/src/Window.cpp" | |||
| #include "dgl/src/WindowPrivateData.cpp" | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| int main() | |||
| { | |||
| USE_NAMESPACE_DGL; | |||
| using DGL_NAMESPACE::Window; | |||
| // creating simple window | |||
| { | |||
| Application app(true); | |||
| Window win(app); | |||
| } | |||
| // TODO | |||
| return 0; | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||