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 GraphicsSceneMove Widget was moved (QGraphicsSceneMoveEvent).
\value GraphicsSceneResize Widget was resized (QGraphicsSceneResizeEvent). \value GraphicsSceneResize Widget was resized (QGraphicsSceneResizeEvent).
\value GraphicsSceneWheel Mouse wheel rolled in a graphics scene (QGraphicsSceneWheelEvent). \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 Hide Widget was hidden (QHideEvent).
\value HideToParent A child widget has been hidden. \value HideToParent A child widget has been hidden.
\value HoverEnter The mouse cursor enters a hover widget (QHoverEvent). \value HoverEnter The mouse cursor enters a hover widget (QHoverEvent).

View File

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

View File

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

View File

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