Commit 9e986f8c authored by Alois Wohlschlager's avatar Alois Wohlschlager 🌾 Committed by David Edmundson
Browse files

Fix crash on drag-and-drop over panel

The fake drag-and-drop events caused by the panel reuse the real event's
mimeData, and were handled asynchronously. By the time the fake event
has been dispatched from the event loop, the mimeData may already have
been freed. Send the fake events synchronously again.

A guard is added to avoid the original potential bug of infinite recursion.

BUG: 398440


(cherry picked from commit c19d8de7)
parent cf68b619
......@@ -877,16 +877,18 @@ bool PanelView::event(QEvent *e)
// first, don't mess with position if the cursor is actually outside the view:
// somebody is doing a click and drag that must not break when the cursor i outside
if (geometry().contains(QCursor::pos(screenToFollow()))) {
if (!containmentContainsPosition(me->windowPos())) {
auto me2 = new QMouseEvent(me->type(),
positionAdjustedForContainment(me->windowPos()),
positionAdjustedForContainment(me->windowPos()),
positionAdjustedForContainment(me->windowPos()) + position(),
me->button(),
me->buttons(),
me->modifiers());
QCoreApplication::postEvent(this, me2);
if (!containmentContainsPosition(me->windowPos()) && !m_fakeEventPending) {
QMouseEvent me2(me->type(),
positionAdjustedForContainment(me->windowPos()),
positionAdjustedForContainment(me->windowPos()),
positionAdjustedForContainment(me->windowPos()) + position(),
me->button(),
me->buttons(),
me->modifiers());
m_fakeEventPending = true;
QCoreApplication::sendEvent(this, &me2);
m_fakeEventPending = false;
return true;
}
} else {
......@@ -899,18 +901,20 @@ bool PanelView::event(QEvent *e)
case QEvent::Wheel: {
QWheelEvent *we = static_cast<QWheelEvent *>(e);
if (!containmentContainsPosition(we->pos())) {
auto we2 = new QWheelEvent(positionAdjustedForContainment(we->pos()),
positionAdjustedForContainment(we->pos()) + position(),
we->pixelDelta(),
we->angleDelta(),
we->angleDelta().y(),
we->orientation(),
we->buttons(),
we->modifiers(),
we->phase());
QCoreApplication::postEvent(this, we2);
if (!containmentContainsPosition(we->pos()) && !m_fakeEventPending) {
QWheelEvent we2(positionAdjustedForContainment(we->pos()),
positionAdjustedForContainment(we->pos()) + position(),
we->pixelDelta(),
we->angleDelta(),
we->angleDelta().y(),
we->orientation(),
we->buttons(),
we->modifiers(),
we->phase());
m_fakeEventPending = true;
QCoreApplication::sendEvent(this, &we2);
m_fakeEventPending = false;
return true;
}
break;
......@@ -918,14 +922,16 @@ bool PanelView::event(QEvent *e)
case QEvent::DragEnter: {
QDragEnterEvent *de = static_cast<QDragEnterEvent *>(e);
if (!containmentContainsPosition(de->pos())) {
auto de2 = new QDragEnterEvent(positionAdjustedForContainment(de->pos()).toPoint(),
de->possibleActions(),
de->mimeData(),
de->mouseButtons(),
de->keyboardModifiers());
QCoreApplication::postEvent(this, de2);
if (!containmentContainsPosition(de->pos()) && !m_fakeEventPending) {
QDragEnterEvent de2(positionAdjustedForContainment(de->pos()).toPoint(),
de->possibleActions(),
de->mimeData(),
de->mouseButtons(),
de->keyboardModifiers());
m_fakeEventPending = true;
QCoreApplication::sendEvent(this, &de2);
m_fakeEventPending = false;
return true;
}
break;
......@@ -935,28 +941,32 @@ bool PanelView::event(QEvent *e)
break;
case QEvent::DragMove: {
QDragMoveEvent *de = static_cast<QDragMoveEvent *>(e);
if (!containmentContainsPosition(de->pos())) {
auto de2 = new QDragMoveEvent(positionAdjustedForContainment(de->pos()).toPoint(),
de->possibleActions(),
de->mimeData(),
de->mouseButtons(),
de->keyboardModifiers());
QCoreApplication::postEvent(this, de2);
if (!containmentContainsPosition(de->pos()) && !m_fakeEventPending) {
QDragMoveEvent de2(positionAdjustedForContainment(de->pos()).toPoint(),
de->possibleActions(),
de->mimeData(),
de->mouseButtons(),
de->keyboardModifiers());
m_fakeEventPending = true;
QCoreApplication::sendEvent(this, &de2);
m_fakeEventPending = false;
return true;
}
break;
}
case QEvent::Drop: {
QDropEvent *de = static_cast<QDropEvent *>(e);
if (!containmentContainsPosition(de->pos())) {
auto de2 = new QDropEvent(positionAdjustedForContainment(de->pos()).toPoint(),
de->possibleActions(),
de->mimeData(),
de->mouseButtons(),
de->keyboardModifiers());
QCoreApplication::postEvent(this, de2);
if (!containmentContainsPosition(de->pos()) && !m_fakeEventPending) {
QDropEvent de2(positionAdjustedForContainment(de->pos()).toPoint(),
de->possibleActions(),
de->mimeData(),
de->mouseButtons(),
de->keyboardModifiers());
m_fakeEventPending = true;
QCoreApplication::sendEvent(this, &de2);
m_fakeEventPending = false;
return true;
}
break;
......
......@@ -230,6 +230,7 @@ private:
int m_rightPadding;
bool m_initCompleted;
bool m_containsMouse = false;
bool m_fakeEventPending = false;
Qt::Alignment m_alignment;
QPointer<PlasmaQuick::ConfigView> m_panelConfigView;
ShellCorona *m_corona;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment