commit feeb29de55351d08335d501e6605c1940aa8ed81
parent 3098954a0024021db40f6deb3ebf8876e84fae79
Author: falkTX <falktx@falktx.com>
Date: Sat, 15 May 2021 20:56:12 +0100
Plug-in all pugl/dpf events except SpecialEvent
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
8 files changed, 344 insertions(+), 194 deletions(-)
diff --git a/dgl/Base.hpp b/dgl/Base.hpp
@@ -130,6 +130,21 @@ enum CrossingMode {
kCrossingUngrab ///< Crossing due to a grab release
};
+/**
+ Scroll direction.
+
+ Describes the direction of a scroll event along with whether the scroll is a "smooth" scroll.
+ The discrete directions are for devices like mouse wheels with constrained axes,
+ while a smooth scroll is for those with arbitrary scroll direction freedom, like some touchpads.
+*/
+enum ScrollDirection {
+ kScrollUp, ///< Scroll up
+ kScrollDown, ///< Scroll down
+ kScrollLeft, ///< Scroll left
+ kScrollRight, ///< Scroll right
+ kScrollSmooth ///< Smooth scroll in any direction
+};
+
// --------------------------------------------------------------------------------------------------------------------
// Base DGL classes
diff --git a/dgl/Events.hpp b/dgl/Events.hpp
@@ -170,19 +170,22 @@ namespace Events
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 pos The widget-relative coordinates of the pointer.
+ @a delta The scroll distance.
+ @a direction The direction of the scroll or "smooth".
@see onScroll
*/
struct ScrollEvent : BaseEvent {
Point<double> pos;
Point<double> delta;
+ ScrollDirection direction;
/** Constuctor */
ScrollEvent() noexcept
: BaseEvent(),
pos(0.0, 0.0),
- delta(0.0, 0.0) {}
+ delta(0.0, 0.0),
+ direction(kScrollSmooth) {}
};
/**
diff --git a/dgl/src/TopLevelWidgetPrivateData.cpp b/dgl/src/TopLevelWidgetPrivateData.cpp
@@ -37,7 +37,37 @@ TopLevelWidget::PrivateData::~PrivateData()
window.pData->topLevelWidget = nullptr;
}
-void TopLevelWidget::PrivateData::mouseEvent(const Events::MouseEvent& ev)
+bool TopLevelWidget::PrivateData::keyboardEvent(const Events::KeyboardEvent& ev)
+{
+ // give top-level widget chance to catch this event first
+ if (self->onKeyboard(ev))
+ return true;
+
+ // propagate event to all subwidgets recursively
+ return selfw->pData->giveKeyboardEventForSubWidgets(ev);
+}
+
+bool TopLevelWidget::PrivateData::specialEvent(const Events::SpecialEvent& ev)
+{
+ // give top-level widget chance to catch this event first
+ if (self->onSpecial(ev))
+ return true;
+
+ // propagate event to all subwidgets recursively
+ return selfw->pData->giveSpecialEventForSubWidgets(ev);
+}
+
+bool TopLevelWidget::PrivateData::characterInputEvent(const Events::CharacterInputEvent& ev)
+{
+ // give top-level widget chance to catch this event first
+ if (self->onCharacterInput(ev))
+ return true;
+
+ // propagate event to all subwidgets recursively
+ return selfw->pData->giveCharacterInputEventForSubWidgets(ev);
+}
+
+bool TopLevelWidget::PrivateData::mouseEvent(const Events::MouseEvent& ev)
{
Events::MouseEvent rev = ev;
@@ -51,10 +81,52 @@ void TopLevelWidget::PrivateData::mouseEvent(const Events::MouseEvent& ev)
// give top-level widget chance to catch this event first
if (self->onMouse(ev))
- return;
+ return true;
+
+ // propagate event to all subwidgets recursively
+ return selfw->pData->giveMouseEventForSubWidgets(rev);
+}
+
+bool TopLevelWidget::PrivateData::motionEvent(const Events::MotionEvent& ev)
+{
+ Events::MotionEvent rev = ev;
+
+ if (window.pData->autoScaling)
+ {
+ const double autoScaleFactor = window.pData->autoScaleFactor;
+
+ rev.pos.setX(ev.pos.getX() / autoScaleFactor);
+ rev.pos.setY(ev.pos.getY() / autoScaleFactor);
+ }
+
+ // give top-level widget chance to catch this event first
+ if (self->onMotion(ev))
+ return true;
+
+ // propagate event to all subwidgets recursively
+ return selfw->pData->giveMotionEventForSubWidgets(rev);
+}
+
+bool TopLevelWidget::PrivateData::scrollEvent(const Events::ScrollEvent& ev)
+{
+ Events::ScrollEvent rev = ev;
+
+ if (window.pData->autoScaling)
+ {
+ const double autoScaleFactor = window.pData->autoScaleFactor;
+
+ rev.pos.setX(ev.pos.getX() / autoScaleFactor);
+ rev.pos.setY(ev.pos.getY() / autoScaleFactor);
+ rev.delta.setX(ev.delta.getX() / autoScaleFactor);
+ rev.delta.setY(ev.delta.getY() / autoScaleFactor);
+ }
+
+ // give top-level widget chance to catch this event first
+ if (self->onScroll(ev))
+ return true;
// propagate event to all subwidgets recursively
- selfw->pData->giveMouseEventForSubWidgets(rev);
+ return selfw->pData->giveScrollEventForSubWidgets(rev);
}
void TopLevelWidget::PrivateData::fallbackOnResize()
diff --git a/dgl/src/TopLevelWidgetPrivateData.hpp b/dgl/src/TopLevelWidgetPrivateData.hpp
@@ -33,7 +33,12 @@ struct TopLevelWidget::PrivateData {
explicit PrivateData(TopLevelWidget* const s, Window& w);
~PrivateData();
void display();
- void mouseEvent(const Events::MouseEvent& ev);
+ bool keyboardEvent(const Events::KeyboardEvent& ev);
+ bool specialEvent(const Events::SpecialEvent& ev);
+ bool characterInputEvent(const Events::CharacterInputEvent& ev);
+ bool mouseEvent(const Events::MouseEvent& ev);
+ bool motionEvent(const Events::MotionEvent& ev);
+ bool scrollEvent(const Events::ScrollEvent& ev);
void fallbackOnResize();
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData)
diff --git a/dgl/src/WidgetPrivateData.cpp b/dgl/src/WidgetPrivateData.cpp
@@ -67,12 +67,68 @@ void Widget::PrivateData::displaySubWidgets(const uint width, const uint height,
}
}
-void Widget::PrivateData::giveMouseEventForSubWidgets(Events::MouseEvent& ev)
+// -----------------------------------------------------------------------
+
+bool Widget::PrivateData::giveKeyboardEventForSubWidgets(const Events::KeyboardEvent& ev)
{
if (! visible)
- return;
+ return false;
if (subWidgets.size() == 0)
- return;
+ return false;
+
+ FOR_EACH_SUBWIDGET_INV(rit)
+ {
+ SubWidget* const widget(*rit);
+
+ if (widget->isVisible() && widget->onKeyboard(ev))
+ return true;
+ }
+
+ return false;
+}
+
+bool Widget::PrivateData::giveSpecialEventForSubWidgets(const Events::SpecialEvent& ev)
+{
+ if (! visible)
+ return false;
+ if (subWidgets.size() == 0)
+ return false;
+
+ FOR_EACH_SUBWIDGET_INV(rit)
+ {
+ SubWidget* const widget(*rit);
+
+ if (widget->isVisible() && widget->onSpecial(ev))
+ return true;
+ }
+
+ return false;
+}
+
+bool Widget::PrivateData::giveCharacterInputEventForSubWidgets(const Events::CharacterInputEvent& ev)
+{
+ if (! visible)
+ return false;
+ if (subWidgets.size() == 0)
+ return false;
+
+ FOR_EACH_SUBWIDGET_INV(rit)
+ {
+ SubWidget* const widget(*rit);
+
+ if (widget->isVisible() && widget->onCharacterInput(ev))
+ return true;
+ }
+
+ return false;
+}
+
+bool Widget::PrivateData::giveMouseEventForSubWidgets(Events::MouseEvent& ev)
+{
+ if (! visible)
+ return false;
+ if (subWidgets.size() == 0)
+ return false;
const double x = ev.pos.getX();
const double y = ev.pos.getY();
@@ -88,8 +144,64 @@ void Widget::PrivateData::giveMouseEventForSubWidgets(Events::MouseEvent& ev)
y - widget->getAbsoluteY());
if (widget->onMouse(ev))
- return;
+ return true;
}
+
+ return false;
+}
+
+bool Widget::PrivateData::giveMotionEventForSubWidgets(Events::MotionEvent& ev)
+{
+ if (! visible)
+ return false;
+ if (subWidgets.size() == 0)
+ return false;
+
+ const double x = ev.pos.getX();
+ const double y = ev.pos.getY();
+
+ FOR_EACH_SUBWIDGET_INV(rit)
+ {
+ SubWidget* const widget(*rit);
+
+ if (! widget->isVisible())
+ continue;
+
+ ev.pos = Point<double>(x - widget->getAbsoluteX(),
+ y - widget->getAbsoluteY());
+
+ if (widget->onMotion(ev))
+ return true;
+ }
+
+ return false;
+}
+
+bool Widget::PrivateData::giveScrollEventForSubWidgets(Events::ScrollEvent& ev)
+{
+ if (! visible)
+ return false;
+ if (subWidgets.size() == 0)
+ return false;
+
+ const double x = ev.pos.getX();
+ const double y = ev.pos.getY();
+
+ FOR_EACH_SUBWIDGET_INV(rit)
+ {
+ SubWidget* const widget(*rit);
+
+ if (! widget->isVisible())
+ continue;
+
+ ev.pos = Point<double>(x - widget->getAbsoluteX(),
+ y - widget->getAbsoluteY());
+
+ if (widget->onScroll(ev))
+ return true;
+ }
+
+ return false;
}
// -----------------------------------------------------------------------
diff --git a/dgl/src/WidgetPrivateData.hpp b/dgl/src/WidgetPrivateData.hpp
@@ -42,7 +42,13 @@ struct Widget::PrivateData {
~PrivateData();
void displaySubWidgets(uint width, uint height, double autoScaleFactor);
- void giveMouseEventForSubWidgets(Events::MouseEvent& ev);
+
+ bool giveKeyboardEventForSubWidgets(const Events::KeyboardEvent& ev);
+ bool giveSpecialEventForSubWidgets(const Events::SpecialEvent& ev);
+ bool giveCharacterInputEventForSubWidgets(const Events::CharacterInputEvent& ev);
+ bool giveMouseEventForSubWidgets(Events::MouseEvent& ev);
+ bool giveMotionEventForSubWidgets(Events::MotionEvent& ev);
+ bool giveScrollEventForSubWidgets(Events::ScrollEvent& ev);
static TopLevelWidget* findTopLevelWidget(Widget* const w);
diff --git a/dgl/src/WindowPrivateData.cpp b/dgl/src/WindowPrivateData.cpp
@@ -384,9 +384,48 @@ void Window::PrivateData::onPuglClose()
close();
}
+void Window::PrivateData::onPuglKey(const Events::KeyboardEvent& ev)
+{
+ DGL_DBGp("onPuglKey : %i %u %u\n", ev.press, ev.key, ev.keycode);
+
+// if (fModal.childFocus != nullptr)
+// return fModal.childFocus->focus();
+
+#ifndef DPF_TEST_WINDOW_CPP
+ if (topLevelWidget != nullptr)
+ topLevelWidget->pData->keyboardEvent(ev);
+#endif
+}
+
+void Window::PrivateData::onPuglSpecial(const Events::SpecialEvent& ev)
+{
+ DGL_DBGp("onPuglSpecial : %i %u\n", ev.press, ev.key);
+
+// if (fModal.childFocus != nullptr)
+// return fModal.childFocus->focus();
+
+#ifndef DPF_TEST_WINDOW_CPP
+ if (topLevelWidget != nullptr)
+ topLevelWidget->pData->specialEvent(ev);
+#endif
+}
+
+void Window::PrivateData::onPuglText(const Events::CharacterInputEvent& ev)
+{
+ DGL_DBGp("onPuglText : %u %u %s\n", ev.keycode, ev.character, ev.string);
+
+// if (fModal.childFocus != nullptr)
+// return fModal.childFocus->focus();
+
+#ifndef DPF_TEST_WINDOW_CPP
+ if (topLevelWidget != nullptr)
+ topLevelWidget->pData->characterInputEvent(ev);
+#endif
+}
+
void Window::PrivateData::onPuglMouse(const Events::MouseEvent& ev)
{
- DGL_DBGp("PUGL: onMouse : %i %i %f %f\n", ev.button, ev.press, ev.pos.getX(), ev.pos.getY());
+ DGL_DBGp("onPuglMouse : %i %i %f %f\n", ev.button, ev.press, ev.pos.getX(), ev.pos.getY());
// if (fModal.childFocus != nullptr)
// return fModal.childFocus->focus();
@@ -397,6 +436,32 @@ void Window::PrivateData::onPuglMouse(const Events::MouseEvent& ev)
#endif
}
+void Window::PrivateData::onPuglMotion(const Events::MotionEvent& ev)
+{
+ DGL_DBGp("onPuglMotion : %f %f\n", ev.button, ev.pos.getX(), ev.pos.getY());
+
+// if (fModal.childFocus != nullptr)
+// return fModal.childFocus->focus();
+
+#ifndef DPF_TEST_WINDOW_CPP
+ if (topLevelWidget != nullptr)
+ topLevelWidget->pData->motionEvent(ev);
+#endif
+}
+
+void Window::PrivateData::onPuglScroll(const Events::ScrollEvent& ev)
+{
+ DGL_DBGp("onPuglScroll : %f %f %f %f\n", ev.pos.getX(), ev.pos.getY(), ev.delta.getX(), ev.delta.getY());
+
+// if (fModal.childFocus != nullptr)
+// return fModal.childFocus->focus();
+
+#ifndef DPF_TEST_WINDOW_CPP
+ if (topLevelWidget != nullptr)
+ topLevelWidget->pData->scrollEvent(ev);
+#endif
+}
+
static int printEvent(const PuglEvent* event, const char* prefix, const bool verbose);
PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const PuglEvent* const event)
@@ -424,6 +489,7 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu
///< View moved/resized, a #PuglEventConfigure
case PUGL_CONFIGURE:
+ // unused x, y (double)
pData->onPuglConfigure(event->configure.width, event->configure.height);
break;
@@ -441,6 +507,7 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu
///< View must be drawn, a #PuglEventExpose
case PUGL_EXPOSE:
+ // unused x, y, width, height (double)
pData->onPuglExpose();
break;
@@ -459,14 +526,38 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu
///< Key pressed, a #PuglEventKey
case PUGL_KEY_PRESS:
- break;
///< Key released, a #PuglEventKey
case PUGL_KEY_RELEASE:
+ {
+ // unused x, y, xRoot, yRoot (double)
+ // TODO special keys?
+ Events::KeyboardEvent ev;
+ ev.mod = event->key.state;
+ ev.flags = event->key.flags;
+ ev.time = static_cast<uint>(event->key.time * 1000.0 + 0.5);
+ ev.press = event->type == PUGL_KEY_PRESS;
+ ev.key = event->key.key;
+ ev.keycode = event->key.keycode;
+ if ((ev.mod & kModifierShift) != 0 && ev.key >= 'a' && ev.key <= 'z')
+ ev.key -= 'a' - 'A'; // a-z -> A-Z
+ pData->onPuglKey(ev);
break;
+ }
///< Character entered, a #PuglEventText
case PUGL_TEXT:
+ {
+ // unused x, y, xRoot, yRoot (double)
+ Events::CharacterInputEvent ev;
+ ev.mod = event->text.state;
+ ev.flags = event->text.flags;
+ ev.time = static_cast<uint>(event->text.time * 1000.0 + 0.5);
+ ev.keycode = event->text.keycode;
+ ev.character = event->text.character;
+ std::strncpy(ev.string, event->text.string, sizeof(ev.string));
+ pData->onPuglText(ev);
break;
+ }
///< Pointer entered view, a #PuglEventCrossing
case PUGL_POINTER_IN:
@@ -493,11 +584,29 @@ PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const Pu
///< Pointer moved, a #PuglEventMotion
case PUGL_MOTION:
+ {
+ Events::MotionEvent ev;
+ ev.mod = event->motion.state;
+ ev.flags = event->motion.flags;
+ ev.time = static_cast<uint>(event->motion.time * 1000.0 + 0.5);
+ ev.pos = Point<double>(event->motion.x, event->motion.y);
+ pData->onPuglMotion(ev);
break;
+ }
///< Scrolled, a #PuglEventScroll
case PUGL_SCROLL:
+ {
+ Events::ScrollEvent ev;
+ ev.mod = event->scroll.state;
+ ev.flags = event->scroll.flags;
+ ev.time = static_cast<uint>(event->scroll.time * 1000.0 + 0.5);
+ ev.pos = Point<double>(event->scroll.x, event->scroll.y);
+ ev.delta = Point<double>(event->scroll.dx, event->scroll.dy);
+ ev.direction = static_cast<ScrollDirection>(event->scroll.direction);
+ pData->onPuglScroll(ev);
break;
+ }
///< Custom client message, a #PuglEventClient
case PUGL_CLIENT:
@@ -646,6 +755,9 @@ static int printEvent(const PuglEvent* event, const char* prefix, const bool ver
return 0;
}
+#undef DGL_DBG
+#undef DGL_DBGF
+
// -----------------------------------------------------------------------
END_NAMESPACE_DGL
diff --git a/dgl/src/WindowPrivateData.hpp b/dgl/src/WindowPrivateData.hpp
@@ -109,20 +109,16 @@ struct Window::PrivateData : IdleCallback {
void onPuglConfigure(int width, int height);
void onPuglExpose();
void onPuglClose();
+ void onPuglKey(const Events::KeyboardEvent& ev);
+ void onPuglSpecial(const Events::SpecialEvent& ev);
+ void onPuglText(const Events::CharacterInputEvent& ev);
void onPuglMouse(const Events::MouseEvent& ev);
+ void onPuglMotion(const Events::MotionEvent& ev);
+ void onPuglScroll(const Events::ScrollEvent& ev);
// Pugl event handling entry point
static PuglStatus puglEventCallback(PuglView* view, const PuglEvent* event);
-#if 0
- // Fallback build-specific Window functions
- struct Fallback {
- static void onDisplayBefore(const GraphicsContext& context);
- static void onDisplayAfter(const GraphicsContext& context);
- static void onReshape(const GraphicsContext& context, uint width, uint height);
- };
-#endif
-
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData)
};
@@ -185,33 +181,6 @@ END_NAMESPACE_DGL
#endif
#endif
-#if 0 // ndef DPF_TEST_WINDOW_CPP
- // -------------------------------------------------------------------
- // stuff that uses pugl internals or build-specific things
-
- void init(const bool resizable = false);
- void setVisible(const bool visible);
- void windowSpecificIdle();
-
- // -------------------------------------------------------------------
-
- // -------------------------------------------------------------------
-
- void addWidget(Widget* const widget);
- void removeWidget(Widget* const widget);
-
- // -------------------------------------------------------------------
-
- void onPuglClose();
- void onPuglMouse(const Widget::MouseEvent& ev);
-
- // -------------------------------------------------------------------
-#endif
-
-// #ifdef DISTRHO_DEFINES_H_INCLUDED
-// friend class DISTRHO_NAMESPACE::UI;
-// #endif
-
#if 0
// -----------------------------------------------------------------------
// Window Private
@@ -287,147 +256,6 @@ struct Window::PrivateData {
// -------------------------------------------------------------------
- // -------------------------------------------------------------------
-
- int onPuglKeyboard(const bool press, const uint key)
- {
- DBGp("PUGL: onKeyboard : %i %i\n", press, key);
-
- if (fModal.childFocus != nullptr)
- {
- fModal.childFocus->focus();
- return 0;
- }
-
- Widget::KeyboardEvent ev;
- ev.press = press;
- ev.key = key;
- ev.mod = static_cast<Modifier>(puglGetModifiers(fView));
- ev.time = puglGetEventTimestamp(fView);
-
- FOR_EACH_WIDGET_INV(rit)
- {
- Widget* const widget(*rit);
-
- if (widget->isVisible() && widget->onKeyboard(ev))
- return 0;
- }
-
- return 1;
- }
-
- int onPuglSpecial(const bool press, const Key key)
- {
- DBGp("PUGL: onSpecial : %i %i\n", press, key);
-
- if (fModal.childFocus != nullptr)
- {
- fModal.childFocus->focus();
- return 0;
- }
-
- Widget::SpecialEvent ev;
- ev.press = press;
- ev.key = key;
- ev.mod = static_cast<Modifier>(puglGetModifiers(fView));
- ev.time = puglGetEventTimestamp(fView);
-
- FOR_EACH_WIDGET_INV(rit)
- {
- Widget* const widget(*rit);
-
- if (widget->isVisible() && widget->onSpecial(ev))
- return 0;
- }
-
- return 1;
- }
-
- void onPuglMotion(int x, int y)
- {
- // DBGp("PUGL: onMotion : %i %i\n", x, y);
-
- if (fModal.childFocus != nullptr)
- return;
-
- x /= fAutoScaling;
- y /= fAutoScaling;
-
- Widget::MotionEvent ev;
- ev.mod = static_cast<Modifier>(puglGetModifiers(fView));
- ev.time = puglGetEventTimestamp(fView);
-
- FOR_EACH_WIDGET_INV(rit)
- {
- Widget* const widget(*rit);
-
- ev.pos = Point<int>(x-widget->getAbsoluteX(), y-widget->getAbsoluteY());
-
- if (widget->isVisible() && widget->onMotion(ev))
- break;
- }
- }
-
- void onPuglScroll(int x, int y, float dx, float dy)
- {
- DBGp("PUGL: onScroll : %i %i %f %f\n", x, y, dx, dy);
-
- if (fModal.childFocus != nullptr)
- return;
-
- x /= fAutoScaling;
- y /= fAutoScaling;
- dx /= fAutoScaling;
- dy /= fAutoScaling;
-
- Widget::ScrollEvent ev;
- ev.delta = Point<float>(dx, dy);
- ev.mod = static_cast<Modifier>(puglGetModifiers(fView));
- ev.time = puglGetEventTimestamp(fView);
-
- FOR_EACH_WIDGET_INV(rit)
- {
- Widget* const widget(*rit);
-
- ev.pos = Point<int>(x-widget->getAbsoluteX(), y-widget->getAbsoluteY());
-
- if (widget->isVisible() && widget->onScroll(ev))
- break;
- }
- }
-
- // -------------------------------------------------------------------
-
- bool handlePluginKeyboard(const bool press, const uint key)
- {
- DBGp("PUGL: handlePluginKeyboard : %i %i\n", press, key);
-
- if (fModal.childFocus != nullptr)
- {
- fModal.childFocus->focus();
- return true;
- }
-
- Widget::KeyboardEvent ev;
- ev.press = press;
- ev.key = key;
- ev.mod = static_cast<Modifier>(fView->mods);
- ev.time = 0;
-
- if ((ev.mod & kModifierShift) != 0 && ev.key >= 'a' && ev.key <= 'z')
- ev.key -= 'a' - 'A'; // a-z -> A-Z
-
- FOR_EACH_WIDGET_INV(rit)
- {
- Widget* const widget(*rit);
-
- if (widget->isVisible() && widget->onKeyboard(ev))
- return true;
- }
-
- return false;
- }
-
bool handlePluginSpecial(const bool press, const Key key)
{
DBGp("PUGL: handlePluginSpecial : %i %i\n", press, key);
@@ -519,7 +347,4 @@ struct Window::PrivateData {
};
#endif
-// #undef DGL_DBG
-// #undef DGL_DBGF
-
#endif // DGL_WINDOW_PRIVATE_DATA_HPP_INCLUDED