diff --git a/dgl/SubWidget.hpp b/dgl/SubWidget.hpp index 137bb809..9bd1614e 100644 --- a/dgl/SubWidget.hpp +++ b/dgl/SubWidget.hpp @@ -121,6 +121,12 @@ public: */ void repaint() noexcept override; + /** + Bring this widget to the "front" of the parent widget. + Makes the widget behave as if it was the last to be registered on the parent widget, thus being "in front". + */ + virtual void toFront(); + /** Indicate that this subwidget will draw out of bounds, and thus needs the entire viewport available for drawing. */ diff --git a/dgl/Widget.hpp b/dgl/Widget.hpp index 8505c216..a659046a 100644 --- a/dgl/Widget.hpp +++ b/dgl/Widget.hpp @@ -156,37 +156,43 @@ public: /** Mouse press or release event. - @a button The button number starting from 1 (1 = left, 2 = middle, 3 = right). - @a press True if the button was pressed, false if released. - @a pos The widget-relative coordinates of the pointer. + @a button The button number starting from 1 (1 = left, 2 = middle, 3 = right). + @a press True if the button was pressed, false if released. + @a pos The widget-relative coordinates of the pointer. + @a absolutePos The absolute coordinates of the pointer. @see onMouse */ struct MouseEvent : BaseEvent { uint button; bool press; Point pos; + Point absolutePos; /** Constuctor */ MouseEvent() noexcept : BaseEvent(), button(0), press(false), - pos(0.0, 0.0) {} + pos(0.0, 0.0), + absolutePos(0.0, 0.0) {} }; /** Mouse motion event. - @a pos The widget-relative coordinates of the pointer. + @a pos The widget-relative coordinates of the pointer. + @a absolutePos The absolute coordinates of the pointer. @see onMotion */ struct MotionEvent : BaseEvent { Point pos; + Point absolutePos; /** Constuctor */ MotionEvent() noexcept : BaseEvent(), - pos(0.0, 0.0) {} + pos(0.0, 0.0), + absolutePos(0.0, 0.0) {} }; /** @@ -198,13 +204,15 @@ public: Some systems and devices support finer resolution and/or higher values for fast scrolls, so programs should handle any value gracefully. - @a pos The widget-relative coordinates of the pointer. - @a delta The scroll distance. - @a direction The direction of the scroll or "smooth". + @a pos The widget-relative coordinates of the pointer. + @a absolutePos The absolute coordinates of the pointer. + @a delta The scroll distance. + @a direction The direction of the scroll or "smooth". @see onScroll */ struct ScrollEvent : BaseEvent { Point pos; + Point absolutePos; Point delta; ScrollDirection direction; @@ -212,6 +220,7 @@ public: ScrollEvent() noexcept : BaseEvent(), pos(0.0, 0.0), + absolutePos(0.0, 0.0), delta(0.0, 0.0), direction(kScrollSmooth) {} }; diff --git a/dgl/src/OpenGL.cpp b/dgl/src/OpenGL.cpp index df2cdf38..7dc82f0f 100644 --- a/dgl/src/OpenGL.cpp +++ b/dgl/src/OpenGL.cpp @@ -582,7 +582,7 @@ void SubWidget::PrivateData::display(const uint width, const uint height, const const int w = static_cast(self->getWidth()); const int h = static_cast(self->getHeight()); - if (viewportScaleFactor != 0.0) + if (viewportScaleFactor != 0.0 && viewportScaleFactor != 1.0) { glViewport(x, -static_cast(height * viewportScaleFactor - height + absolutePos.getY() + 0.5), @@ -598,10 +598,7 @@ void SubWidget::PrivateData::display(const uint width, const uint height, const else if (needsFullViewportForDrawing || (absolutePos.isZero() && self->getSize() == Size(width, height))) { // full viewport size - glViewport(0, - -static_cast(height - height + 0.5), - static_cast(width + 0.5), - static_cast(height + 0.5)); + glViewport(0, 0, static_cast(width), static_cast(height)); } else { diff --git a/dgl/src/SubWidget.cpp b/dgl/src/SubWidget.cpp index ab084648..f8e1d01a 100644 --- a/dgl/src/SubWidget.cpp +++ b/dgl/src/SubWidget.cpp @@ -15,6 +15,7 @@ */ #include "SubWidgetPrivateData.hpp" +#include "WidgetPrivateData.hpp" #include "../TopLevelWidget.hpp" START_NAMESPACE_DGL @@ -118,6 +119,14 @@ void SubWidget::repaint() noexcept } } +void SubWidget::toFront() +{ + std::list& subwidgets(pData->parentWidget->pData->subWidgets); + + subwidgets.remove(this); + subwidgets.push_back(this); +} + void SubWidget::setNeedsFullViewportDrawing(const bool needsFullViewportForDrawing) { pData->needsFullViewportForDrawing = needsFullViewportForDrawing; diff --git a/dgl/src/TopLevelWidgetPrivateData.cpp b/dgl/src/TopLevelWidgetPrivateData.cpp index ef3d54a8..618cf357 100644 --- a/dgl/src/TopLevelWidgetPrivateData.cpp +++ b/dgl/src/TopLevelWidgetPrivateData.cpp @@ -92,6 +92,8 @@ bool TopLevelWidget::PrivateData::mouseEvent(const MouseEvent& ev) rev.pos.setX(ev.pos.getX() / autoScaleFactor); rev.pos.setY(ev.pos.getY() / autoScaleFactor); + rev.absolutePos.setX(ev.absolutePos.getX() / autoScaleFactor); + rev.absolutePos.setY(ev.absolutePos.getY() / autoScaleFactor); } // give top-level widget chance to catch this event first @@ -116,6 +118,8 @@ bool TopLevelWidget::PrivateData::motionEvent(const MotionEvent& ev) rev.pos.setX(ev.pos.getX() / autoScaleFactor); rev.pos.setY(ev.pos.getY() / autoScaleFactor); + rev.absolutePos.setX(ev.absolutePos.getX() / autoScaleFactor); + rev.absolutePos.setY(ev.absolutePos.getY() / autoScaleFactor); } // give top-level widget chance to catch this event first @@ -140,6 +144,8 @@ bool TopLevelWidget::PrivateData::scrollEvent(const ScrollEvent& ev) rev.pos.setX(ev.pos.getX() / autoScaleFactor); rev.pos.setY(ev.pos.getY() / autoScaleFactor); + rev.absolutePos.setX(ev.absolutePos.getX() / autoScaleFactor); + rev.absolutePos.setY(ev.absolutePos.getY() / autoScaleFactor); rev.delta.setX(ev.delta.getX() / autoScaleFactor); rev.delta.setY(ev.delta.getY() / autoScaleFactor); } diff --git a/dgl/src/WidgetPrivateData.cpp b/dgl/src/WidgetPrivateData.cpp index 0b016490..60be6c88 100644 --- a/dgl/src/WidgetPrivateData.cpp +++ b/dgl/src/WidgetPrivateData.cpp @@ -130,8 +130,20 @@ bool Widget::PrivateData::giveMouseEventForSubWidgets(MouseEvent& ev) if (subWidgets.size() == 0) return false; - const double x = ev.pos.getX(); - const double y = ev.pos.getY(); + double x = ev.absolutePos.getX(); + double y = ev.absolutePos.getY(); + + if (SubWidget* const selfw = dynamic_cast(self)) + { + if (selfw->pData->needsViewportScaling) + { + x -= selfw->getAbsoluteX(); + y -= selfw->getAbsoluteY(); + + ev.absolutePos.setX(x); + ev.absolutePos.setY(y); + } + } FOR_EACH_SUBWIDGET_INV(rit) { @@ -157,8 +169,20 @@ bool Widget::PrivateData::giveMotionEventForSubWidgets(MotionEvent& ev) if (subWidgets.size() == 0) return false; - const double x = ev.pos.getX(); - const double y = ev.pos.getY(); + double x = ev.absolutePos.getX(); + double y = ev.absolutePos.getY(); + + if (SubWidget* const selfw = dynamic_cast(self)) + { + if (selfw->pData->needsViewportScaling) + { + x -= selfw->getAbsoluteX(); + y -= selfw->getAbsoluteY(); + + ev.absolutePos.setX(x); + ev.absolutePos.setY(y); + } + } FOR_EACH_SUBWIDGET_INV(rit) { @@ -184,8 +208,20 @@ bool Widget::PrivateData::giveScrollEventForSubWidgets(ScrollEvent& ev) if (subWidgets.size() == 0) return false; - const double x = ev.pos.getX(); - const double y = ev.pos.getY(); + double x = ev.absolutePos.getX(); + double y = ev.absolutePos.getY(); + + if (SubWidget* const selfw = dynamic_cast(self)) + { + if (selfw->pData->needsViewportScaling) + { + x -= selfw->getAbsoluteX(); + y -= selfw->getAbsoluteY(); + + ev.absolutePos.setX(x); + ev.absolutePos.setY(y); + } + } FOR_EACH_SUBWIDGET_INV(rit) { diff --git a/dgl/src/WindowPrivateData.cpp b/dgl/src/WindowPrivateData.cpp index 7c7453a4..5821e580 100644 --- a/dgl/src/WindowPrivateData.cpp +++ b/dgl/src/WindowPrivateData.cpp @@ -945,6 +945,7 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu ev.button = event->button.button; ev.press = event->type == PUGL_BUTTON_PRESS; ev.pos = Point(event->button.x, event->button.y); + ev.absolutePos = ev.pos; pData->onPuglMouse(ev); break; } @@ -957,6 +958,7 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu ev.flags = event->motion.flags; ev.time = static_cast(event->motion.time * 1000.0 + 0.5); ev.pos = Point(event->motion.x, event->motion.y); + ev.absolutePos = ev.pos; pData->onPuglMotion(ev); break; } @@ -971,6 +973,7 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu ev.pos = Point(event->scroll.x, event->scroll.y); ev.delta = Point(event->scroll.dx, event->scroll.dy); ev.direction = static_cast(event->scroll.direction); + ev.absolutePos = ev.pos; pData->onPuglScroll(ev); break; }