Signed-off-by: falkTX <falktx@falktx.com>pull/272/head
| @@ -40,7 +40,6 @@ OBJS_common = \ | |||
| ../build/dgl/Window.cpp.o \ | |||
| ../build/dgl/WindowPrivateData.cpp.o | |||
| # ../build/dgl/StandaloneWindow.cpp.o \ | |||
| # ../build/dgl/WindowFileBrowser.cpp.o | |||
| # TODO: ImageWidgets.cpp | |||
| @@ -65,11 +64,6 @@ OBJS_opengl = $(OBJS_common) \ | |||
| ../build/dgl/NanoVG.cpp.opengl.o \ | |||
| ../build/dgl/pugl.cpp.opengl.o | |||
| # ../build/dgl/Image.cpp.opengl.o \ | |||
| # ../build/dgl/ImageWidgets.cpp.opengl.o \ | |||
| # ../build/dgl/WidgetPrivateData.cpp.opengl.o \ | |||
| # ../build/dgl/WindowPrivateData.cpp.opengl.o | |||
| # ifeq ($(MACOS),true) | |||
| # OBJS_opengl += ../build/dgl/Window.mm.opengl.o | |||
| # else | |||
| @@ -185,16 +185,6 @@ public: | |||
| const GLenum format = GL_BGRA, | |||
| const GLenum type = GL_UNSIGNED_BYTE) noexcept; | |||
| /** | |||
| TODO document this. | |||
| */ | |||
| void setup(); | |||
| /** | |||
| TODO document this. | |||
| */ | |||
| void cleanup(); | |||
| /** | |||
| Get the image format. | |||
| */ | |||
| @@ -53,33 +53,10 @@ public: | |||
| uint getHeight() const noexcept { return Window::getHeight(); } | |||
| const Size<uint> getSize() const noexcept { return Window::getSize(); } | |||
| void repaint() noexcept { Window::repaint(); } | |||
| /** | |||
| Overloaded functions to ensure size changes apply on both TopLevelWidget and Window classes. | |||
| */ | |||
| void setWidth(uint width) | |||
| { | |||
| TopLevelWidget::setWidth(width); | |||
| Window::setWidth(width); | |||
| } | |||
| void setHeight(uint height) | |||
| { | |||
| TopLevelWidget::setHeight(height); | |||
| Window::setHeight(height); | |||
| } | |||
| void setSize(uint width, uint height) | |||
| { | |||
| TopLevelWidget::setSize(width, height); | |||
| Window::setSize(width, height); | |||
| } | |||
| void setSize(const Size<uint>& size) | |||
| { | |||
| TopLevelWidget::setSize(size); | |||
| Window::setSize(size); | |||
| } | |||
| void setWidth(uint width) { Window::setWidth(width); } | |||
| void setHeight(uint height) { Window::setHeight(height); } | |||
| void setSize(uint width, uint height) { Window::setSize(width, height); } | |||
| void setSize(const Size<uint>& size) { Window::setSize(size); } | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(StandaloneWindow) | |||
| }; | |||
| @@ -52,12 +52,14 @@ public: | |||
| /** | |||
| Check if this widget contains the point defined by @a x and @a y. | |||
| */ | |||
| // TODO rename as containsRelativePos | |||
| template<typename T> | |||
| bool contains(T x, T y) const noexcept; | |||
| /** | |||
| Check if this widget contains the point @a pos. | |||
| */ | |||
| // TODO rename as containsRelativePos | |||
| template<typename T> | |||
| bool contains(const Point<T>& pos) const noexcept; | |||
| @@ -119,6 +121,11 @@ public: | |||
| */ | |||
| void repaint() noexcept override; | |||
| /** | |||
| Indicate that this subwidget will draw out of bounds, and thus needs the entire viewport available for drawing. | |||
| */ | |||
| void setNeedsFullViewportDrawing(bool needsFullViewportForDrawing = true); | |||
| protected: | |||
| /** | |||
| A function called when the subwidget's absolute position is changed. | |||
| @@ -271,7 +271,6 @@ protected: | |||
| /** | |||
| A function called when the window is resized. | |||
| If there is a top-level widget associated with this window, its size will be set right after this function. | |||
| TODO this seems wrong, top-level widget should be resized here | |||
| */ | |||
| virtual void onReshape(uint width, uint height); | |||
| @@ -551,9 +551,7 @@ ImageSlider::ImageSlider(Widget* const parentWidget, const Image& image) noexcep | |||
| fEndPos(), | |||
| fSliderArea() | |||
| { | |||
| /* TODO | |||
| setNeedsFullViewport(); | |||
| */ | |||
| setNeedsFullViewportDrawing(); | |||
| } | |||
| float ImageSlider::getValue() const noexcept | |||
| @@ -114,44 +114,81 @@ void Rectangle<T>::_draw(const bool outline) | |||
| // ----------------------------------------------------------------------- | |||
| static void setupOpenGLImage(const OpenGLImage& image, GLuint textureId) | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(image.isValid(),); | |||
| glEnable(GL_TEXTURE_2D); | |||
| glBindTexture(GL_TEXTURE_2D, textureId); | |||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); | |||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); | |||
| static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f }; | |||
| glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans); | |||
| glPixelStorei(GL_PACK_ALIGNMENT, 1); | |||
| glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | |||
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, | |||
| static_cast<GLsizei>(image.getWidth()), | |||
| static_cast<GLsizei>(image.getHeight()), | |||
| 0, | |||
| image.getFormat(), image.getType(), image.getRawData()); | |||
| glBindTexture(GL_TEXTURE_2D, 0); | |||
| glDisable(GL_TEXTURE_2D); | |||
| } | |||
| OpenGLImage::OpenGLImage() | |||
| : ImageBase(), | |||
| fFormat(0), | |||
| fType(0), | |||
| fTextureId(0), | |||
| setupCalled(false) {} | |||
| setupCalled(false) | |||
| { | |||
| glGenTextures(1, &fTextureId); | |||
| DISTRHO_SAFE_ASSERT(fTextureId != 0); | |||
| } | |||
| OpenGLImage::OpenGLImage(const char* const rawData, const uint width, const uint height, const GLenum format, const GLenum type) | |||
| : ImageBase(rawData, width, height), | |||
| fFormat(format), | |||
| fType(type), | |||
| fTextureId(0), | |||
| setupCalled(false) {} | |||
| setupCalled(false) | |||
| { | |||
| glGenTextures(1, &fTextureId); | |||
| DISTRHO_SAFE_ASSERT(fTextureId != 0); | |||
| } | |||
| OpenGLImage::OpenGLImage(const char* const rawData, const Size<uint>& size, const GLenum format, const GLenum type) | |||
| : ImageBase(rawData, size), | |||
| fFormat(format), | |||
| fType(type), | |||
| fTextureId(0), | |||
| setupCalled(false) {} | |||
| setupCalled(false) | |||
| { | |||
| glGenTextures(1, &fTextureId); | |||
| DISTRHO_SAFE_ASSERT(fTextureId != 0); | |||
| } | |||
| OpenGLImage::OpenGLImage(const OpenGLImage& image) | |||
| : ImageBase(image), | |||
| fFormat(image.fFormat), | |||
| fType(image.fType), | |||
| fTextureId(0), | |||
| setupCalled(false) {} | |||
| setupCalled(false) | |||
| { | |||
| glGenTextures(1, &fTextureId); | |||
| DISTRHO_SAFE_ASSERT(fTextureId != 0); | |||
| } | |||
| OpenGLImage::~OpenGLImage() | |||
| { | |||
| if (setupCalled) { | |||
| // FIXME test if this is still necessary with new pugl | |||
| #ifndef DISTRHO_OS_MAC | |||
| if (fTextureId != 0) | |||
| cleanup(); | |||
| #endif | |||
| DISTRHO_SAFE_ASSERT(fTextureId == 0); | |||
| } | |||
| if (fTextureId != 0) | |||
| glDeleteTextures(1, &fTextureId); | |||
| } | |||
| void OpenGLImage::loadFromMemory(const char* const rawData, | |||
| @@ -175,43 +212,6 @@ void OpenGLImage::loadFromMemory(const char* const rdata, | |||
| setupCalled = false; | |||
| } | |||
| void OpenGLImage::setup() | |||
| { | |||
| setupCalled = true; | |||
| DISTRHO_SAFE_ASSERT_RETURN(fTextureId == 0,); | |||
| DISTRHO_SAFE_ASSERT_RETURN(isValid(),); | |||
| glGenTextures(1, &fTextureId); | |||
| DISTRHO_SAFE_ASSERT_RETURN(fTextureId != 0,); | |||
| glEnable(GL_TEXTURE_2D); | |||
| glBindTexture(GL_TEXTURE_2D, fTextureId); | |||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); | |||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); | |||
| static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f }; | |||
| glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans); | |||
| glPixelStorei(GL_PACK_ALIGNMENT, 1); | |||
| glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | |||
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, | |||
| static_cast<GLsizei>(size.getWidth()), static_cast<GLsizei>(size.getHeight()), 0, | |||
| fFormat, fType, rawData); | |||
| glBindTexture(GL_TEXTURE_2D, 0); | |||
| glDisable(GL_TEXTURE_2D); | |||
| } | |||
| void OpenGLImage::cleanup() | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(fTextureId != 0,); | |||
| glDeleteTextures(1, &fTextureId); | |||
| fTextureId = 0; | |||
| } | |||
| GLenum OpenGLImage::getFormat() const noexcept | |||
| { | |||
| return fFormat; | |||
| @@ -249,18 +249,15 @@ void OpenGLImage::drawAt(const int x, const int y) | |||
| void OpenGLImage::drawAt(const Point<int>& pos) | |||
| { | |||
| if (isInvalid()) | |||
| if (fTextureId == 0 || isInvalid()) | |||
| return; | |||
| if (! setupCalled) | |||
| { | |||
| // TODO check if this is valid, give warning about needing to call setup/cleanup manually | |||
| setup(); | |||
| setupOpenGLImage(*this, fTextureId); | |||
| setupCalled = true; | |||
| } | |||
| if (fTextureId == 0) | |||
| return; | |||
| glEnable(GL_TEXTURE_2D); | |||
| glBindTexture(GL_TEXTURE_2D, fTextureId); | |||
| @@ -305,7 +302,7 @@ void SubWidget::PrivateData::display(const uint width, const uint height, const | |||
| { | |||
| bool needsDisableScissor = false; | |||
| if (absolutePos.isZero() && self->getSize() == Size<uint>(width, height)) | |||
| if (needsFullViewportForDrawing || (absolutePos.isZero() && self->getSize() == Size<uint>(width, height))) | |||
| { | |||
| // full viewport size | |||
| glViewport(0, | |||
| @@ -348,7 +345,7 @@ void SubWidget::PrivateData::display(const uint width, const uint height, const | |||
| needsDisableScissor = false; | |||
| } | |||
| // displaySubWidgets(width, height, autoScaleFactor); | |||
| selfw->pData->displaySubWidgets(width, height, autoScaleFactor); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -365,7 +362,7 @@ void TopLevelWidget::PrivateData::display() | |||
| if (window.pData->autoScaling) | |||
| glViewport(0, -(height * autoScaleFactor - height), width * autoScaleFactor, height * autoScaleFactor); | |||
| else | |||
| glViewport(0, -height, width, height); | |||
| glViewport(0, 0, width, height); | |||
| // main widget drawing | |||
| self->onDisplay(); | |||
| @@ -1,65 +0,0 @@ | |||
| /* | |||
| * DISTRHO Plugin Framework (DPF) | |||
| * Copyright (C) 2012-2020 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. | |||
| */ | |||
| #include "../StandaloneWindow.hpp" | |||
| #include "../TopLevelWidget.hpp" | |||
| START_NAMESPACE_DGL | |||
| // ----------------------------------------------------------------------- | |||
| StandaloneWindow::StandaloneWindow(Application& app) | |||
| : Window(app), | |||
| TopLevelWidget(this) {} | |||
| void StandaloneWindow::exec() | |||
| { | |||
| Window::show(); | |||
| Application::exec(); | |||
| } | |||
| void StandaloneWindow::onReshape(uint width, uint height) | |||
| { | |||
| if (fWidget != nullptr) | |||
| fWidget->setSize(width, height); | |||
| Window::onReshape(width, height); | |||
| } | |||
| #if 0 | |||
| void StandaloneWindow::_addWidget(TopLevelWidget* widget) | |||
| { | |||
| if (fWidget == nullptr) | |||
| { | |||
| fWidget = widget; | |||
| fWidget->pData->needsFullViewport = true; | |||
| } | |||
| Window::_addWidget(widget); | |||
| } | |||
| void StandaloneWindow::_removeWidget(TopLevelWidget* widget) | |||
| { | |||
| if (fWidget == widget) | |||
| { | |||
| fWidget->pData->needsFullViewport = false; | |||
| fWidget = nullptr; | |||
| } | |||
| Window::_removeWidget(widget); | |||
| } | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DGL | |||
| @@ -33,7 +33,7 @@ SubWidget::~SubWidget() | |||
| template<typename T> | |||
| bool SubWidget::contains(T x, T y) const noexcept | |||
| { | |||
| return Rectangle<double>(getAbsoluteX(), getAbsoluteY(), getWidth(), getHeight()).contains(x, y); | |||
| return Rectangle<double>(0, 0, getWidth(), getHeight()).contains(x, y); | |||
| } | |||
| template<typename T> | |||
| @@ -111,7 +111,17 @@ void SubWidget::repaint() noexcept | |||
| return; | |||
| if (TopLevelWidget* const topw = getTopLevelWidget()) | |||
| topw->repaint(getConstrainedAbsoluteArea()); | |||
| { | |||
| if (pData->needsFullViewportForDrawing) | |||
| topw->repaint(); | |||
| else | |||
| topw->repaint(getConstrainedAbsoluteArea()); | |||
| } | |||
| } | |||
| void SubWidget::setNeedsFullViewportDrawing(const bool needsFullViewportForDrawing) | |||
| { | |||
| pData->needsFullViewportForDrawing = needsFullViewportForDrawing; | |||
| } | |||
| void SubWidget::onPositionChanged(const PositionChangedEvent&) | |||
| @@ -23,6 +23,7 @@ START_NAMESPACE_DGL | |||
| SubWidget::PrivateData::PrivateData(SubWidget* const s, Widget* const pw) | |||
| : self(s), | |||
| selfw((Widget*)s), | |||
| parentWidget(pw), | |||
| absolutePos(), | |||
| needsViewportScaling(false) | |||
| @@ -25,8 +25,10 @@ START_NAMESPACE_DGL | |||
| struct SubWidget::PrivateData { | |||
| SubWidget* const self; | |||
| Widget* const selfw; | |||
| Widget* const parentWidget; | |||
| Point<int> absolutePos; | |||
| bool needsFullViewportForDrawing; // needed for widgets drawing out of bounds | |||
| bool needsViewportScaling; // needed for NanoVG | |||
| explicit PrivateData(SubWidget* const s, Widget* const pw); | |||
| @@ -205,6 +205,7 @@ void Window::PrivateData::init(const uint width, const uint height, const bool r | |||
| rect.width = width; | |||
| rect.height = height; | |||
| puglSetFrame(view, rect); | |||
| puglSetWindowSize(view, width, height); | |||
| // FIXME this is bad | |||
| puglRealize(view); | |||
| @@ -293,16 +294,6 @@ void Window::PrivateData::hide() | |||
| // ----------------------------------------------------------------------- | |||
| void Window::PrivateData::focus() | |||
| { | |||
| if (! isEmbed) | |||
| puglRaiseWindow(view); | |||
| puglGrabFocus(view); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| void Window::PrivateData::close() | |||
| { | |||
| DGL_DBG("Window close\n"); | |||
| @@ -317,6 +308,16 @@ void Window::PrivateData::close() | |||
| // ----------------------------------------------------------------------- | |||
| void Window::PrivateData::focus() | |||
| { | |||
| if (! isEmbed) | |||
| puglRaiseWindow(view); | |||
| puglGrabFocus(view); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| void Window::PrivateData::setResizable(const bool resizable) | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(! isEmbed,); | |||
| @@ -360,6 +361,10 @@ void Window::PrivateData::startModal() | |||
| // make parent give focus to us | |||
| modal.parent->modal.child = this; | |||
| // FIXME? | |||
| PuglRect rect = puglGetFrame(view); | |||
| puglSetDefaultSize(view, rect.width, rect.height); | |||
| // make sure both parent and ourselves are visible | |||
| modal.parent->show(); | |||
| show(); | |||
| @@ -446,6 +451,9 @@ void Window::PrivateData::onPuglConfigure(const int width, const int height) | |||
| if (topLevelWidget != nullptr) | |||
| topLevelWidget->setSize(width, height); | |||
| #endif | |||
| // always repaint after a resize | |||
| puglPostRedisplay(view); | |||
| } | |||
| void Window::PrivateData::onPuglExpose() | |||
| @@ -488,9 +496,7 @@ void Window::PrivateData::onPuglFocus(const bool focus, const CrossingMode mode) | |||
| if (modal.child != nullptr) | |||
| return modal.child->focus(); | |||
| #ifndef DPF_TEST_WINDOW_CPP | |||
| self->onFocus(focus, mode); | |||
| #endif | |||
| } | |||
| void Window::PrivateData::onPuglKey(const Events::KeyboardEvent& ev) | |||
| @@ -571,12 +577,16 @@ void Window::PrivateData::onPuglScroll(const Events::ScrollEvent& ev) | |||
| #endif | |||
| } | |||
| #if defined(DEBUG) && defined(DGL_DEBUG_EVENTS) | |||
| static int printEvent(const PuglEvent* event, const char* prefix, const bool verbose); | |||
| #endif | |||
| PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const PuglEvent* const event) | |||
| { | |||
| printEvent(event, "pugl event: ", true); | |||
| Window::PrivateData* const pData = (Window::PrivateData*)puglGetHandle(view); | |||
| #if defined(DEBUG) && defined(DGL_DEBUG_EVENTS) | |||
| printEvent(event, "pugl event: ", true); | |||
| #endif | |||
| switch (event->type) | |||
| { | |||
| @@ -739,6 +749,7 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu | |||
| // ----------------------------------------------------------------------- | |||
| #if defined(DEBUG) && defined(DGL_DEBUG_EVENTS) | |||
| static int printModifiers(const uint32_t mods) | |||
| { | |||
| return fprintf(stderr, "Modifiers:%s%s%s%s\n", | |||
| @@ -863,6 +874,7 @@ static int printEvent(const PuglEvent* event, const char* prefix, const bool ver | |||
| return 0; | |||
| } | |||
| #endif | |||
| #undef DGL_DBG | |||
| #undef DGL_DBGF | |||
| @@ -118,7 +118,6 @@ struct Window::PrivateData : IdleCallback { | |||
| void show(); | |||
| void hide(); | |||
| void focus(); | |||
| /** Hide window and notify application of a window close event. | |||
| * Does nothing if window is embed (that is, not standalone). | |||
| @@ -129,6 +128,8 @@ struct Window::PrivateData : IdleCallback { | |||
| */ | |||
| void close(); | |||
| void focus(); | |||
| void setResizable(bool resizable); | |||
| const GraphicsContext& getGraphicsContext() const noexcept; | |||