Fix QGraphicsView's abuse of QEvent's d-pointer in Leave event handling

QGraphicsSceneEvent carries a widget pointer, and we can add a new
event
type. Assert that QGraphicsScene doesn't get Leave events from
elsewhere.

This was the only "usage" of QEvent's d-pointer in Qt, so with this gone
we can reduce the size of QEvent by 8 bytes.

Change-Id: I0513daf742de9084d0469d55b7a7f41b667e8081
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Volker Hilsheimer 2020-11-11 00:12:10 +01:00
parent f27f9e7bd3
commit 89391da882
4 changed files with 14 additions and 7 deletions

View File

@ -153,6 +153,7 @@ QT_BEGIN_NAMESPACE
\value GraphicsSceneMove Widget was moved (QGraphicsSceneMoveEvent).
\value GraphicsSceneResize Widget was resized (QGraphicsSceneResizeEvent).
\value GraphicsSceneWheel Mouse wheel rolled in a graphics scene (QGraphicsSceneWheelEvent).
\value GraphicsSceneLeave The cursor leaves a graphics scene (QGraphicsSceneWheelEvent).
\value Hide Widget was hidden (QHideEvent).
\value HideToParent A child widget has been hidden.
\value HoverEnter The mouse cursor enters a hover widget (QHoverEvent).

View File

@ -205,6 +205,7 @@ public:
GraphicsSceneDragLeave = 166,
GraphicsSceneDrop = 167,
GraphicsSceneWheel = 168,
GraphicsSceneLeave = 220,
KeyboardLayoutChange = 169, // keyboard layout changed

View File

@ -3371,9 +3371,15 @@ bool QGraphicsScene::event(QEvent *event)
break;
}
case QEvent::Leave:
// hackieshly unpacking the viewport pointer from the leave event.
d->leaveScene(reinterpret_cast<QWidget *>(event->d));
Q_ASSERT_X(false, "QGraphicsScene::event",
"QGraphicsScene must not receive QEvent::Leave, use GraphicsSceneLeave");
break;
case QEvent::GraphicsSceneLeave:
{
auto *leaveEvent = static_cast<QGraphicsSceneEvent*>(event);
d->leaveScene(leaveEvent->widget());
break;
}
case QEvent::GraphicsSceneHelp:
helpEvent(static_cast<QGraphicsSceneHelpEvent *>(event));
break;

View File

@ -2871,11 +2871,10 @@ bool QGraphicsView::viewportEvent(QEvent *event)
d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.constFirst());
}
d->useLastMouseEvent = false;
// a hack to pass a viewport pointer to the scene inside the leave event
Q_ASSERT(event->d == nullptr);
QScopedValueRollback<QEventPrivate *> rb(event->d);
event->d = reinterpret_cast<QEventPrivate *>(viewport());
QCoreApplication::sendEvent(d->scene, event);
QGraphicsSceneEvent leaveEvent(QEvent::GraphicsSceneLeave);
leaveEvent.setWidget(viewport());
QCoreApplication::sendEvent(d->scene, &leaveEvent);
event->setAccepted(leaveEvent.isAccepted());
break;
}
#if QT_CONFIG(tooltip)