diff --git a/dgl/Makefile b/dgl/Makefile index 2e228b68..2612c014 100644 --- a/dgl/Makefile +++ b/dgl/Makefile @@ -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 diff --git a/dgl/OpenGL.hpp b/dgl/OpenGL.hpp index 55905bec..3f44072e 100644 --- a/dgl/OpenGL.hpp +++ b/dgl/OpenGL.hpp @@ -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. */ diff --git a/dgl/StandaloneWindow.hpp b/dgl/StandaloneWindow.hpp index 5db33926..67031385 100644 --- a/dgl/StandaloneWindow.hpp +++ b/dgl/StandaloneWindow.hpp @@ -53,33 +53,10 @@ public: uint getHeight() const noexcept { return Window::getHeight(); } const Size 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& 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& size) { Window::setSize(size); } DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(StandaloneWindow) }; diff --git a/dgl/SubWidget.hpp b/dgl/SubWidget.hpp index 83118d32..ce51c0af 100644 --- a/dgl/SubWidget.hpp +++ b/dgl/SubWidget.hpp @@ -52,12 +52,14 @@ public: /** Check if this widget contains the point defined by @a x and @a y. */ + // TODO rename as containsRelativePos template bool contains(T x, T y) const noexcept; /** Check if this widget contains the point @a pos. */ + // TODO rename as containsRelativePos template bool contains(const Point& 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. diff --git a/dgl/Window.hpp b/dgl/Window.hpp index 8351b019..6c27f84a 100644 --- a/dgl/Window.hpp +++ b/dgl/Window.hpp @@ -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); diff --git a/dgl/src/ImageWidgets.cpp b/dgl/src/ImageWidgets.cpp index a22d8b6e..371c9cca 100644 --- a/dgl/src/ImageWidgets.cpp +++ b/dgl/src/ImageWidgets.cpp @@ -551,9 +551,7 @@ ImageSlider::ImageSlider(Widget* const parentWidget, const Image& image) noexcep fEndPos(), fSliderArea() { - /* TODO - setNeedsFullViewport(); - */ + setNeedsFullViewportDrawing(); } float ImageSlider::getValue() const noexcept diff --git a/dgl/src/OpenGL.cpp b/dgl/src/OpenGL.cpp index d9fecc8a..60924ac2 100644 --- a/dgl/src/OpenGL.cpp +++ b/dgl/src/OpenGL.cpp @@ -114,44 +114,81 @@ void Rectangle::_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(image.getWidth()), + static_cast(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& 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(size.getWidth()), static_cast(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& 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(width, height)) + if (needsFullViewportForDrawing || (absolutePos.isZero() && self->getSize() == Size(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(); diff --git a/dgl/src/StandaloneWindow.cpp b/dgl/src/StandaloneWindow.cpp deleted file mode 100644 index 6de8a291..00000000 --- a/dgl/src/StandaloneWindow.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2020 Filipe Coelho - * - * 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 diff --git a/dgl/src/SubWidget.cpp b/dgl/src/SubWidget.cpp index 6cd8e6d9..b22360ca 100644 --- a/dgl/src/SubWidget.cpp +++ b/dgl/src/SubWidget.cpp @@ -33,7 +33,7 @@ SubWidget::~SubWidget() template bool SubWidget::contains(T x, T y) const noexcept { - return Rectangle(getAbsoluteX(), getAbsoluteY(), getWidth(), getHeight()).contains(x, y); + return Rectangle(0, 0, getWidth(), getHeight()).contains(x, y); } template @@ -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&) diff --git a/dgl/src/SubWidgetPrivateData.cpp b/dgl/src/SubWidgetPrivateData.cpp index 039aa9b8..737b7024 100644 --- a/dgl/src/SubWidgetPrivateData.cpp +++ b/dgl/src/SubWidgetPrivateData.cpp @@ -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) diff --git a/dgl/src/SubWidgetPrivateData.hpp b/dgl/src/SubWidgetPrivateData.hpp index 8a219f52..bb8f7bad 100644 --- a/dgl/src/SubWidgetPrivateData.hpp +++ b/dgl/src/SubWidgetPrivateData.hpp @@ -25,8 +25,10 @@ START_NAMESPACE_DGL struct SubWidget::PrivateData { SubWidget* const self; + Widget* const selfw; Widget* const parentWidget; Point absolutePos; + bool needsFullViewportForDrawing; // needed for widgets drawing out of bounds bool needsViewportScaling; // needed for NanoVG explicit PrivateData(SubWidget* const s, Widget* const pw); diff --git a/dgl/src/WindowPrivateData.cpp b/dgl/src/WindowPrivateData.cpp index 90aa11b7..e55ad5ae 100644 --- a/dgl/src/WindowPrivateData.cpp +++ b/dgl/src/WindowPrivateData.cpp @@ -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 diff --git a/dgl/src/WindowPrivateData.hpp b/dgl/src/WindowPrivateData.hpp index 859992c9..e00f97b7 100644 --- a/dgl/src/WindowPrivateData.hpp +++ b/dgl/src/WindowPrivateData.hpp @@ -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;