diff options
author | m0dB maarten de boer <mdb.github@resorama.com> | 2023-05-06 03:46:11 +0200 |
---|---|---|
committer | m0dB <79429057+m0dB@users.noreply.github.com> | 2023-05-27 01:28:25 +0200 |
commit | 18378e439b1deadcda118d6489cdf0e538023df0 (patch) | |
tree | 58f41e124c9ec7c767613efb902d09b067e3b798 | |
parent | b3f0ed88f8dba5cb97f3dd13c6a3d2d138e082ea (diff) |
use custom mechanism to deliver drag&drop events coming from the QOpenGLWindow
-rw-r--r-- | src/widget/openglwindow.cpp | 36 | ||||
-rw-r--r-- | src/widget/openglwindow.h | 1 | ||||
-rw-r--r-- | src/widget/trackdroptarget.h | 4 | ||||
-rw-r--r-- | src/widget/wglwidgetqopengl.cpp | 9 | ||||
-rw-r--r-- | src/widget/wglwidgetqopengl.h | 5 | ||||
-rw-r--r-- | src/widget/wspinnybase.cpp | 8 | ||||
-rw-r--r-- | src/widget/wspinnybase.h | 3 | ||||
-rw-r--r-- | src/widget/wwaveformviewer.cpp | 15 | ||||
-rw-r--r-- | src/widget/wwaveformviewer.h | 2 |
9 files changed, 63 insertions, 20 deletions
diff --git a/src/widget/openglwindow.cpp b/src/widget/openglwindow.cpp index fca428bb3e..cbf8818ef3 100644 --- a/src/widget/openglwindow.cpp +++ b/src/widget/openglwindow.cpp @@ -5,6 +5,7 @@ #include "widget/tooltipqopengl.h" #include "widget/wglwidget.h" +#include "widget/trackdroptarget.h" OpenGLWindow::OpenGLWindow(WGLWidget* widget) : m_pWidget(widget) { @@ -53,17 +54,11 @@ bool OpenGLWindow::event(QEvent* ev) { // gets called recursive, potentially resulting in infinite recursion // and a stack overflow. The boolean m_handlingEvent protects against // this recursion. - - if (m_handlingEvent) { - return false; - } - m_handlingEvent = true; + const auto t = ev->type(); bool result = QOpenGLWindow::event(ev); if (m_pWidget) { - const auto t = ev->type(); - // Tooltip don't work by forwarding the events. This mimics the // tooltip behavior. if (t == QEvent::MouseMove) { @@ -74,22 +69,33 @@ bool OpenGLWindow::event(QEvent* ev) { ToolTipQOpenGL::singleton().stop(m_pWidget); } - if (t != QEvent::Resize && t != QEvent::Move && t != QEvent::Expose) { - // Send all events to the widget that owns the window container widget that contains - // this QOpenGLWindow. - // Except for: + if (t == QEvent::DragEnter || t == QEvent::DragMove || t == QEvent::DragLeave || t == QEvent::Drop) + { + // Drag & Drop events are not delivered correctly when using QApplication::sendEvent + // and even result in a recursive call to this method, so we use our own mechanism. + if (m_pWidget->trackDropTarget()) { + return m_pWidget->trackDropTarget()->handleDragAndDropEventFromWindow(ev); + } + + ev->ignore(); + return false; + } + + if (t == QEvent::Resize || t == QEvent::Move || t == QEvent::Expose) { // - Resize and Move // Any change to the geometry comes from m_pWidget and its child m_pContainerWidget. // If we send the resulting events back to the m_pWidget we will quickly overflow // the event queue with repeated resize and move events. // - Expose // This event is only for windows - - QApplication::sendEvent(m_pWidget, ev); + return result; } - } - m_handlingEvent = false; + // Send all remaining events to the widget that owns the window container widget that contains + // this QOpenGLWindow. With this mouse events, keyboard events, etc all arrive as intended, + // including the events for the WWaveformViewer that contains the waveform widget. + QApplication::sendEvent(m_pWidget, ev); + } return result; } diff --git a/src/widget/openglwindow.h b/src/widget/openglwindow.h index 01a98d78eb..3d725ba462 100644 --- a/src/widget/openglwindow.h +++ b/src/widget/openglwindow.h @@ -11,7 +11,6 @@ class OpenGLWindow : public QOpenGLWindow { WGLWidget* m_pWidget; bool m_dirty{}; - bool m_handlingEvent{}; public: OpenGLWindow(WGLWidget* widget); diff --git a/src/widget/trackdroptarget.h b/src/widget/trackdroptarget.h index 6933a4d70f..9171d177ef 100644 --- a/src/widget/trackdroptarget.h +++ b/src/widget/trackdroptarget.h @@ -2,6 +2,8 @@ #include <QString> +class QEvent; + /// Mixin to mark a widget as a drop target for tracks. /// /// This class is *not* derived from QObject (inheriting from 2 QObject classes @@ -20,6 +22,8 @@ class TrackDropTarget { emit trackDropped(filename, group); // clazy:exclude=incorrect-emit } + virtual bool handleDragAndDropEventFromWindow(QEvent* event) { return false; } + signals: virtual void trackDropped(const QString& filename, const QString& group) = 0; virtual void cloneDeck(const QString& sourceGroup, const QString& targetGroup) = 0; diff --git a/src/widget/wglwidgetqopengl.cpp b/src/widget/wglwidgetqopengl.cpp index 9064955bdf..eaaae5cbfe 100644 --- a/src/widget/wglwidgetqopengl.cpp +++ b/src/widget/wglwidgetqopengl.cpp @@ -25,6 +25,15 @@ QPaintDevice* WGLWidget::paintDevice() { return m_pOpenGLWindow; } +void WGLWidget::setTrackDropTarget(TrackDropTarget* target) +{ + m_pTrackDropTarget = target; +} + +TrackDropTarget* WGLWidget::trackDropTarget() const { + return m_pTrackDropTarget; +} + void WGLWidget::showEvent(QShowEvent* event) { if (!m_pOpenGLWindow) { m_pOpenGLWindow = new OpenGLWindow(this); diff --git a/src/widget/wglwidgetqopengl.h b/src/widget/wglwidgetqopengl.h index b775d4ea94..68b94b7921 100644 --- a/src/widget/wglwidgetqopengl.h +++ b/src/widget/wglwidgetqopengl.h @@ -12,11 +12,13 @@ class QPaintDevice; class OpenGLWindow; +class TrackDropTarget; class WGLWidget : public QWidget { private: OpenGLWindow* m_pOpenGLWindow{}; QWidget* m_pContainerWidget{}; + TrackDropTarget* m_pTrackDropTarget{}; public: WGLWidget(QWidget* parent); @@ -38,6 +40,9 @@ class WGLWidget : public QWidget { virtual void resizeGL(int w, int h); virtual void initializeGL(); + void setTrackDropTarget(TrackDropTarget* target); + TrackDropTarget* trackDropTarget() const; + protected: void showEvent(QShowEvent* event) override; void resizeEvent(QResizeEvent* event) override; diff --git a/src/widget/wspinnybase.cpp b/src/widget/wspinnybase.cpp index 9e2deaaf0b..95cecd78a1 100644 --- a/src/widget/wspinnybase.cpp +++ b/src/widget/wspinnybase.cpp @@ -95,6 +95,10 @@ WSpinnyBase::WSpinnyBase( this, &WSpinnyBase::slotCoverInfoSelected); connect(m_pCoverMenu, &WCoverArtMenu::reloadCoverArt, this, &WSpinnyBase::slotReloadCoverArt); + +#ifdef MIXXX_USE_QOPENGL + setTrackDropTarget(this); +#endif } WSpinnyBase::~WSpinnyBase() { @@ -649,6 +653,10 @@ bool WSpinnyBase::event(QEvent* pEvent) { return WGLWidget::event(pEvent); } +bool WSpinnyBase::handleDragAndDropEventFromWindow(QEvent* ev) { + return event(ev); +} + void WSpinnyBase::dragEnterEvent(QDragEnterEvent* event) { DragAndDropHelper::handleTrackDragEnterEvent(event, m_group, m_pConfig); } diff --git a/src/widget/wspinnybase.h b/src/widget/wspinnybase.h index a66840dcce..c42d1a900d 100644 --- a/src/widget/wspinnybase.h +++ b/src/widget/wspinnybase.h @@ -79,6 +79,9 @@ class WSpinnyBase : public WGLWidget, void hideEvent(QHideEvent* event) override; bool event(QEvent* pEvent) override; + // TrackDropTarget: + bool handleDragAndDropEventFromWindow(QEvent* ev) override; + double calculateAngle(double playpos); int calculateFullRotations(double playpos); double calculatePositionFromAngle(double angle); diff --git a/src/widget/wwaveformviewer.cpp b/src/widget/wwaveformviewer.cpp index a709e3c414..93c5f9d6e9 100644 --- a/src/widget/wwaveformviewer.cpp +++ b/src/widget/wwaveformviewer.cpp @@ -201,6 +201,10 @@ void WWaveformViewer::dropEvent(QDropEvent* event) { DragAndDropHelper::handleTrackDropEvent(event, *this, m_group, m_pConfig); } +bool WWaveformViewer::handleDragAndDropEventFromWindow(QEvent* ev) { + return event(ev); +} + void WWaveformViewer::leaveEvent(QEvent*) { if (m_pHoveredMark) { unhighlightMark(m_pHoveredMark); @@ -268,12 +272,15 @@ void WWaveformViewer::setWaveformWidget(WaveformWidgetAbstract* waveformWidget) connect(pWidget, &QWidget::destroyed, this, &WWaveformViewer::slotWidgetDead); m_waveformWidget->getWidget()->setMouseTracking(true); #ifdef MIXXX_USE_QOPENGL - // The OpenGLWindow used to display the waveform widget interferes with the - // normal Qt tooltip mechanism and uses it's own mechanism. We set the tooltip - // of the waveform widget to the tooltip of its parent WWaveformViewer so the - // OpenGLWindow will display it. if (m_waveformWidget->getGLWidget()) { + // The OpenGLWindow used to display the waveform widget interferes with the + // normal Qt tooltip mechanism and uses it's own mechanism. We set the tooltip + // of the waveform widget to the tooltip of its parent WWaveformViewer so the + // OpenGLWindow will display it. m_waveformWidget->getGLWidget()->setToolTip(toolTip()); + + // Tell the WGLWidget that this is its drag&drop target + m_waveformWidget->getGLWidget()->setTrackDropTarget(this); } #endif // Make connection to show "Passthrough" label on the waveform, except for diff --git a/src/widget/wwaveformviewer.h b/src/widget/wwaveformviewer.h index 4afbe391d7..b486bf7308 100644 --- a/src/widget/wwaveformviewer.h +++ b/src/widget/wwaveformviewer.h @@ -32,6 +32,8 @@ class WWaveformViewer : public WWidget, public TrackDropTarget { } void setup(const QDomNode& node, const SkinContext& context); + bool handleDragAndDropEventFromWindow(QEvent* ev) override; + void dragEnterEvent(QDragEnterEvent *event) override; void dropEvent(QDropEvent *event) override; |