diff --git a/dgl/Window.hpp b/dgl/Window.hpp index 675ae64f..6898f6a9 100644 --- a/dgl/Window.hpp +++ b/dgl/Window.hpp @@ -393,6 +393,16 @@ public: */ double getScaleFactor() const noexcept; + /** + Enable automatic internal scaling based on a custom width and height. + This will internally scale up drawing and scale down user events coordinates and sizes, + but the result is likely blurry. + + This can be used as an early step for high-dpi support, + that scales up the window contents in a blurry but usable way. + */ + void enableInternalScalingWithSize(uint baseWidth, uint baseHeight, bool keepAspectRatio = false); + /** Grab the keyboard input focus. */ diff --git a/dgl/src/Cairo.cpp b/dgl/src/Cairo.cpp index ca760a78..ab2296de 100644 --- a/dgl/src/Cairo.cpp +++ b/dgl/src/Cairo.cpp @@ -736,11 +736,7 @@ template class ImageBaseSwitch; // ----------------------------------------------------------------------- -void SubWidget::PrivateData::display(const uint width, const uint height - #if DGL_ALLOW_DEPRECATED_METHODS - , const double autoScaleFactor - #endif - ) +void SubWidget::PrivateData::display(const uint width, const uint height, const double autoScaleFactor) { cairo_t* const handle = static_cast(self->getGraphicsContext()).handle; @@ -758,13 +754,10 @@ void SubWidget::PrivateData::display(const uint width, const uint height { // full viewport size cairo_translate(handle, 0, 0); - #if DGL_ALLOW_DEPRECATED_METHODS cairo_scale(handle, autoScaleFactor, autoScaleFactor); - #endif } else { - #if DGL_ALLOW_DEPRECATED_METHODS // set viewport pos cairo_translate(handle, absolutePos.getX() * autoScaleFactor, absolutePos.getY() * autoScaleFactor); @@ -774,21 +767,12 @@ void SubWidget::PrivateData::display(const uint width, const uint height 0, std::round(self->getWidth() * autoScaleFactor), std::round(self->getHeight() * autoScaleFactor)); - #else - // set viewport pos - cairo_translate(handle, absolutePos.getX(), absolutePos.getY()); - - // then cut the outer bounds - cairo_rectangle(handle, 0, 0, self->getWidth(), self->getHeight()); - #endif cairo_clip(handle); needsResetClip = true; - #if DGL_ALLOW_DEPRECATED_METHODS // set viewport scaling cairo_scale(handle, autoScaleFactor, autoScaleFactor); - #endif } // display widget @@ -799,11 +783,7 @@ void SubWidget::PrivateData::display(const uint width, const uint height cairo_set_matrix(handle, &matrix); - #if DGL_ALLOW_DEPRECATED_METHODS selfw->pData->displaySubWidgets(width, height, autoScaleFactor); - #else - selfw->pData->displaySubWidgets(width, height); - #endif } // ----------------------------------------------------------------------- @@ -819,9 +799,7 @@ void TopLevelWidget::PrivateData::display() const uint width = size.getWidth(); const uint height = size.getHeight(); - #if DGL_ALLOW_DEPRECATED_METHODS const double autoScaleFactor = window.pData->autoScaleFactor; - #endif cairo_matrix_t matrix; cairo_get_matrix(handle, &matrix); @@ -829,12 +807,10 @@ void TopLevelWidget::PrivateData::display() // full viewport size cairo_translate(handle, 0, 0); - #if DGL_ALLOW_DEPRECATED_METHODS if (window.pData->autoScaling) cairo_scale(handle, autoScaleFactor, autoScaleFactor); else cairo_scale(handle, 1.0, 1.0); - #endif // main widget drawing self->onDisplay(); @@ -842,11 +818,7 @@ void TopLevelWidget::PrivateData::display() cairo_set_matrix(handle, &matrix); // now draw subwidgets if there are any - selfw->pData->displaySubWidgets(width, height - #if DGL_ALLOW_DEPRECATED_METHODS - , autoScaleFactor - #endif - ); + selfw->pData->displaySubWidgets(width, height, autoScaleFactor); } // ----------------------------------------------------------------------- diff --git a/dgl/src/ImageBaseWidgets.cpp b/dgl/src/ImageBaseWidgets.cpp index 8cdbc9d7..0d7d0f42 100644 --- a/dgl/src/ImageBaseWidgets.cpp +++ b/dgl/src/ImageBaseWidgets.cpp @@ -31,9 +31,8 @@ ImageBaseAboutWindow::ImageBaseAboutWindow(Window& transientParentWin if (image.isValid()) { - const double scaleFactor = getScaleFactor(); - setSize(image.getSize() * scaleFactor); - setGeometryConstraints(image.getWidth() * scaleFactor, image.getHeight() * scaleFactor, true); + enableInternalScalingWithSize(image.getWidth(), image.getHeight(), true); + setSize(image.getSize()); } done(); @@ -49,9 +48,8 @@ ImageBaseAboutWindow::ImageBaseAboutWindow(TopLevelWidget* const topL if (image.isValid()) { - const double scaleFactor = getScaleFactor(); - setSize(image.getSize() * scaleFactor); - setGeometryConstraints(image.getWidth(), image.getHeight(), true); + enableInternalScalingWithSize(image.getWidth(), image.getHeight(), true); + setSize(image.getSize()); } done(); @@ -73,9 +71,8 @@ void ImageBaseAboutWindow::setImage(const ImageType& image) img = image; - const double scaleFactor = getScaleFactor(); - setSize(image.getSize() * scaleFactor); - setGeometryConstraints(image.getWidth() * scaleFactor, image.getHeight() * scaleFactor, true); + enableInternalScalingWithSize(image.getWidth(), image.getHeight(), true); + setSize(image.getSize()); done(); } diff --git a/dgl/src/OpenGL.cpp b/dgl/src/OpenGL.cpp index f9bb0454..da15805f 100644 --- a/dgl/src/OpenGL.cpp +++ b/dgl/src/OpenGL.cpp @@ -157,11 +157,7 @@ OpenGLImage::OpenGLImage(const char* const rdata, const Size& s, const GLe // -------------------------------------------------------------------------------------------------------------------- -void SubWidget::PrivateData::display(const uint width, const uint height - #if DGL_ALLOW_DEPRECATED_METHODS - , const double autoScaleFactor - #endif - ) +void SubWidget::PrivateData::display(const uint width, const uint height, const double autoScaleFactor) { if (skipDrawing) return; @@ -195,7 +191,6 @@ void SubWidget::PrivateData::display(const uint width, const uint height } else { - #if DGL_ALLOW_DEPRECATED_METHODS // set viewport pos glViewport(d_roundToIntPositive(absolutePos.getX() * autoScaleFactor), -d_roundToIntPositive(absolutePos.getY() * autoScaleFactor), @@ -207,16 +202,6 @@ void SubWidget::PrivateData::display(const uint width, const uint height d_roundToIntPositive(height - (static_cast(self->getHeight()) + absolutePos.getY()) * autoScaleFactor), d_roundToIntPositive(self->getWidth() * autoScaleFactor), d_roundToIntPositive(self->getHeight() * autoScaleFactor)); - #else - // set viewport pos - glViewport(absolutePos.getX(), -absolutePos.getY(), static_cast(width), static_cast(height)); - - // then cut the outer bounds - glScissor(absolutePos.getX(), - static_cast(height) - self->getHeight() + absolutePos.getY(), - static_cast(self->getWidth()), - static_cast(self->getHeight())); - #endif glEnable(GL_SCISSOR_TEST); needsDisableScissor = true; @@ -228,11 +213,7 @@ void SubWidget::PrivateData::display(const uint width, const uint height if (needsDisableScissor) glDisable(GL_SCISSOR_TEST); - #if DGL_ALLOW_DEPRECATED_METHODS selfw->pData->displaySubWidgets(width, height, autoScaleFactor); - #else - selfw->pData->displaySubWidgets(width, height); - #endif } // -------------------------------------------------------------------------------------------------------------------- @@ -253,11 +234,7 @@ void TopLevelWidget::PrivateData::display() self->onDisplay(); // now draw subwidgets if there are any - selfw->pData->displaySubWidgets(width, height - #if DGL_ALLOW_DEPRECATED_METHODS - , window.pData->autoScaleFactor - #endif - ); + selfw->pData->displaySubWidgets(width, height, window.pData->autoScaleFactor); } // -------------------------------------------------------------------------------------------------------------------- diff --git a/dgl/src/OpenGL2.cpp b/dgl/src/OpenGL2.cpp index bdfd900a..dda69354 100644 --- a/dgl/src/OpenGL2.cpp +++ b/dgl/src/OpenGL2.cpp @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2025 Filipe Coelho + * Copyright (C) 2012-2026 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 @@ -538,7 +538,12 @@ void Window::PrivateData::startContext() glViewport(0, 0, static_cast(size.width), static_cast(size.height)); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(0.0, static_cast(size.width), static_cast(size.height), 0.0, 0.0, 1.0); + glOrtho(0.0, + static_cast(size.width) / autoScaleFactor, + static_cast(size.height) / autoScaleFactor, + 0.0, + 0.0, + 1.0); glViewport(0, 0, static_cast(size.width), static_cast(size.height)); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); diff --git a/dgl/src/Stub.cpp b/dgl/src/Stub.cpp index f4bd6cb3..128be9ff 100644 --- a/dgl/src/Stub.cpp +++ b/dgl/src/Stub.cpp @@ -172,15 +172,9 @@ void Rectangle::drawOutline() // -------------------------------------------------------------------------------------------------------------------- -#if DGL_ALLOW_DEPRECATED_METHODS void SubWidget::PrivateData::display(uint, uint, double) { } -#else -void SubWidget::PrivateData::display(uint, uint) -{ -} -#endif // -------------------------------------------------------------------------------------------------------------------- diff --git a/dgl/src/SubWidgetPrivateData.hpp b/dgl/src/SubWidgetPrivateData.hpp index 60626049..beea81cd 100644 --- a/dgl/src/SubWidgetPrivateData.hpp +++ b/dgl/src/SubWidgetPrivateData.hpp @@ -38,11 +38,7 @@ struct SubWidget::PrivateData { ~PrivateData(); // NOTE display function is different depending on build type, must call displaySubWidgets at the end - #if DGL_ALLOW_DEPRECATED_METHODS void display(uint width, uint height, double autoScaleFactor); - #else - void display(uint width, uint height); - #endif DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData) }; diff --git a/dgl/src/TopLevelWidgetPrivateData.cpp b/dgl/src/TopLevelWidgetPrivateData.cpp index d3aab894..90efdddf 100644 --- a/dgl/src/TopLevelWidgetPrivateData.cpp +++ b/dgl/src/TopLevelWidgetPrivateData.cpp @@ -17,7 +17,6 @@ #include "TopLevelWidgetPrivateData.hpp" #include "WidgetPrivateData.hpp" #include "WindowPrivateData.hpp" -#include "pugl.hpp" START_NAMESPACE_DGL @@ -75,7 +74,6 @@ bool TopLevelWidget::PrivateData::mouseEvent(const MouseEvent& ev) MouseEvent rev = ev; - #if DGL_ALLOW_DEPRECATED_METHODS if (window.pData->autoScaling) { const double autoScaleFactor = window.pData->autoScaleFactor; @@ -85,7 +83,6 @@ bool TopLevelWidget::PrivateData::mouseEvent(const MouseEvent& ev) rev.absolutePos.setX(ev.absolutePos.getX() / autoScaleFactor); rev.absolutePos.setY(ev.absolutePos.getY() / autoScaleFactor); } - #endif // propagate event to all subwidgets recursively return selfw->pData->giveMouseEventForSubWidgets(rev); @@ -99,7 +96,6 @@ bool TopLevelWidget::PrivateData::motionEvent(const MotionEvent& ev) MotionEvent rev = ev; - #if DGL_ALLOW_DEPRECATED_METHODS if (window.pData->autoScaling) { const double autoScaleFactor = window.pData->autoScaleFactor; @@ -109,7 +105,6 @@ bool TopLevelWidget::PrivateData::motionEvent(const MotionEvent& ev) rev.absolutePos.setX(ev.absolutePos.getX() / autoScaleFactor); rev.absolutePos.setY(ev.absolutePos.getY() / autoScaleFactor); } - #endif // propagate event to all subwidgets recursively return selfw->pData->giveMotionEventForSubWidgets(rev); @@ -123,7 +118,6 @@ bool TopLevelWidget::PrivateData::scrollEvent(const ScrollEvent& ev) ScrollEvent rev = ev; - #if DGL_ALLOW_DEPRECATED_METHODS if (window.pData->autoScaling) { const double autoScaleFactor = window.pData->autoScaleFactor; @@ -135,7 +129,6 @@ bool TopLevelWidget::PrivateData::scrollEvent(const ScrollEvent& ev) rev.delta.setX(ev.delta.getX() / autoScaleFactor); rev.delta.setY(ev.delta.getY() / autoScaleFactor); } - #endif // propagate event to all subwidgets recursively return selfw->pData->giveScrollEventForSubWidgets(rev); diff --git a/dgl/src/Vulkan.cpp b/dgl/src/Vulkan.cpp index 446a6d4c..ad7f6a52 100644 --- a/dgl/src/Vulkan.cpp +++ b/dgl/src/Vulkan.cpp @@ -235,19 +235,11 @@ VulkanImage& VulkanImage::operator=(const VulkanImage& image) noexcept // ----------------------------------------------------------------------- -void SubWidget::PrivateData::display(const uint width, const uint height - #if DGL_ALLOW_DEPRECATED_METHODS - , const double autoScaleFactor - #endif - ) +void SubWidget::PrivateData::display(const uint width, const uint height, const double autoScaleFactor) { // TODO - #if DGL_ALLOW_DEPRECATED_METHODS selfw->pData->displaySubWidgets(width, height, autoScaleFactor); - #else - selfw->pData->displaySubWidgets(width, height); - #endif } // ----------------------------------------------------------------------- @@ -267,11 +259,7 @@ void TopLevelWidget::PrivateData::display() self->onDisplay(); // now draw subwidgets if there are any - selfw->pData->displaySubWidgets(width, height - #if DGL_ALLOW_DEPRECATED_METHODS - , window.pData->autoScaleFactor - #endif - ); + selfw->pData->displaySubWidgets(width, height, window.pData->autoScaleFactor); } // ----------------------------------------------------------------------- diff --git a/dgl/src/WidgetPrivateData.cpp b/dgl/src/WidgetPrivateData.cpp index 27821e09..52990ee1 100644 --- a/dgl/src/WidgetPrivateData.cpp +++ b/dgl/src/WidgetPrivateData.cpp @@ -56,12 +56,7 @@ Widget::PrivateData::~PrivateData() std::free(name); } -void Widget::PrivateData::displaySubWidgets(const uint width, - const uint height - #if DGL_ALLOW_DEPRECATED_METHODS - , const double autoScaleFactor - #endif - ) +void Widget::PrivateData::displaySubWidgets(const uint width, const uint height, const double autoScaleFactor) { if (subWidgets.size() == 0) return; @@ -71,11 +66,7 @@ void Widget::PrivateData::displaySubWidgets(const uint width, SubWidget* const subwidget(*it); if (subwidget->isVisible()) - subwidget->pData->display(width, height - #if DGL_ALLOW_DEPRECATED_METHODS - , autoScaleFactor - #endif - ); + subwidget->pData->display(width, height, autoScaleFactor); } } diff --git a/dgl/src/WidgetPrivateData.hpp b/dgl/src/WidgetPrivateData.hpp index 94161245..19ecc940 100644 --- a/dgl/src/WidgetPrivateData.hpp +++ b/dgl/src/WidgetPrivateData.hpp @@ -42,12 +42,7 @@ struct Widget::PrivateData { explicit PrivateData(Widget* const s, Widget* const pw); ~PrivateData(); - void displaySubWidgets(uint width, - uint height - #if DGL_ALLOW_DEPRECATED_METHODS - , double autoScaleFactor - #endif - ); + void displaySubWidgets(uint width, uint height, double autoScaleFactor); bool giveKeyboardEventForSubWidgets(const KeyboardEvent& ev); bool giveCharacterInputEventForSubWidgets(const CharacterInputEvent& ev); diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp index f5ce0bb9..54b37204 100644 --- a/dgl/src/Window.cpp +++ b/dgl/src/Window.cpp @@ -270,20 +270,20 @@ void Window::setSize(uint width, uint height) { DISTRHO_SAFE_ASSERT_UINT2_RETURN(width > 1 && height > 1, width, height,); + const double scaleFactor = pData->scaleFactor; + if (pData->isEmbed) { uint minWidth = pData->minWidth; uint minHeight = pData->minHeight; - #if DGL_ALLOW_DEPRECATED_METHODS - const double scaleFactor = pData->scaleFactor; - if (pData->autoScaling && d_isNotEqual(scaleFactor, 1.0)) { minWidth = d_roundToUnsignedInt(minWidth * scaleFactor); minHeight = d_roundToUnsignedInt(minHeight * scaleFactor); + width = d_roundToUnsignedInt(width * scaleFactor); + height = d_roundToUnsignedInt(height * scaleFactor); } - #endif // handle geometry constraints here if (width < minWidth) @@ -310,6 +310,14 @@ void Window::setSize(uint width, uint height) } } } + else + { + if (pData->autoScaling && d_isNotEqual(scaleFactor, 1.0)) + { + width = d_roundToUnsignedInt(width * scaleFactor); + height = d_roundToUnsignedInt(height * scaleFactor); + } + } if (pData->usesSizeRequest) { @@ -415,6 +423,35 @@ double Window::getScaleFactor() const noexcept return pData->scaleFactor; } +void Window::enableInternalScalingWithSize(uint baseWidth, uint baseHeight, const bool keepAspectRatio) +{ + DISTRHO_SAFE_ASSERT_RETURN(baseWidth > 0,); + DISTRHO_SAFE_ASSERT_RETURN(baseHeight > 0,); + + const Size size(getSize()); + const double scaleHorizontal = size.getWidth() / static_cast(baseWidth); + const double scaleVertical = size.getHeight() / static_cast(baseHeight); + + pData->minWidth = baseWidth; + pData->minHeight = baseHeight; + pData->autoScaling = true; + pData->autoScaleFactor = scaleHorizontal < scaleVertical ? scaleHorizontal : scaleVertical; + pData->keepAspectRatio = keepAspectRatio; + + if (pData->view == nullptr) + return; + + const double scaleFactor = pData->scaleFactor; + + if (d_isNotEqual(scaleFactor, 1.0)) + { + baseWidth = d_roundToUnsignedInt(baseWidth * scaleFactor); + baseHeight = d_roundToUnsignedInt(baseHeight * scaleFactor); + } + + puglSetGeometryConstraints(pData->view, baseWidth, baseHeight, keepAspectRatio); +} + void Window::focus() { pData->focus(); @@ -465,7 +502,6 @@ void Window::repaint(const Rectangle& rect) noexcept uint width = rect.getWidth(); uint height = rect.getHeight(); - #if DGL_ALLOW_DEPRECATED_METHODS if (pData->autoScaling) { const double autoScaleFactor = pData->autoScaleFactor; @@ -475,7 +511,6 @@ void Window::repaint(const Rectangle& rect) noexcept width = d_roundToUnsignedInt(width * autoScaleFactor); height = d_roundToUnsignedInt(height * autoScaleFactor); } - #endif puglObscureRegion(pData->view, x, y, width, height); } diff --git a/dgl/src/WindowPrivateData.cpp b/dgl/src/WindowPrivateData.cpp index 3f555512..8467b69e 100644 --- a/dgl/src/WindowPrivateData.cpp +++ b/dgl/src/WindowPrivateData.cpp @@ -116,10 +116,8 @@ Window::PrivateData::PrivateData(Application& a, Window* const s) usesScheduledRepaints(false), usesSizeRequest(false), scaleFactor(DGL_NAMESPACE::getScaleFactor(view)), - #if DGL_ALLOW_DEPRECATED_METHODS autoScaling(false), autoScaleFactor(1.0), - #endif minWidth(0), minHeight(0), keepAspectRatio(false), @@ -151,10 +149,8 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, PrivateData* c usesScheduledRepaints(false), usesSizeRequest(false), scaleFactor(ppData->scaleFactor), - #if DGL_ALLOW_DEPRECATED_METHODS autoScaling(false), autoScaleFactor(1.0), - #endif minWidth(0), minHeight(0), keepAspectRatio(false), @@ -188,10 +184,8 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, usesScheduledRepaints(false), usesSizeRequest(false), scaleFactor(scale != 0.0 ? scale : DGL_NAMESPACE::getScaleFactor(view)), - #if DGL_ALLOW_DEPRECATED_METHODS autoScaling(false), autoScaleFactor(1.0), - #endif minWidth(0), minHeight(0), keepAspectRatio(false), @@ -228,10 +222,8 @@ Window::PrivateData::PrivateData(Application& a, Window* const s, usesScheduledRepaints(_usesScheduledRepaints), usesSizeRequest(_usesSizeRequest), scaleFactor(scale != 0.0 ? scale : DGL_NAMESPACE::getScaleFactor(view)), - #if DGL_ALLOW_DEPRECATED_METHODS autoScaling(false), autoScaleFactor(1.0), - #endif minWidth(0), minHeight(0), keepAspectRatio(false), @@ -660,7 +652,6 @@ void Window::PrivateData::onPuglConfigure(const uint width, const uint height) createContextIfNeeded(); - #if DGL_ALLOW_DEPRECATED_METHODS if (autoScaling) { const double scaleHorizontal = width / static_cast(minWidth); @@ -671,12 +662,9 @@ void Window::PrivateData::onPuglConfigure(const uint width, const uint height) { autoScaleFactor = 1.0; } + const uint uwidth = d_roundToUnsignedInt(width / autoScaleFactor); const uint uheight = d_roundToUnsignedInt(height / autoScaleFactor); - #else - const uint uwidth = width; - const uint uheight = height; - #endif #ifdef DGL_USE_WEB_VIEW if (webViewHandle != nullptr) diff --git a/dgl/src/WindowPrivateData.hpp b/dgl/src/WindowPrivateData.hpp index 2717a7af..df4ecf6b 100644 --- a/dgl/src/WindowPrivateData.hpp +++ b/dgl/src/WindowPrivateData.hpp @@ -73,11 +73,9 @@ struct Window::PrivateData : IdleCallback { /** Scale factor to report to widgets on request, purely informational. */ double scaleFactor; - #if DGL_ALLOW_DEPRECATED_METHODS /** Automatic scaling to apply on widgets, implemented internally. */ bool autoScaling; double autoScaleFactor; - #endif /** Pugl geometry constraints access. */ uint minWidth, minHeight;