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