diff options
author | Marc Mutz <marc.mutz@qt.io> | 2022-01-04 10:35:04 +0100 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2022-04-14 19:07:16 +0200 |
commit | da0f72ebb817bb9c92c7a183b281d8a4bf31a135 (patch) | |
tree | 072e6051b2464dba616634b94e1657d695a81715 /tests/auto/gui | |
parent | ec59ae6189c2a0405cc50f548c95c7007603934f (diff) |
QEvent: start to de-inline copy ctor and clone() of all subclasses
There's no advantage to them being inline: Absent de-virtualisation,
clone() is only supposed to be called through the vtable, and the copy
ctor is only supposed to be used in the implementation of clone().
And when the compiler de-virtualises, we don't want the code
duplication associated with inlining.
Enforce this by introducing new macros to hide the boilerplate.
This fixes missing out-of-line dtors in:
- QSinglePointEvent
- QApplicationStateChangeEvent
- QFutureCallOutEvent
Wrong covariant return in:
- QFutureCallOutEvent
And missing clone() reimplementations in:
- QCloseEvent
- QIconDragEvent
- QShowEvent
- QHideEvent
- QDragEnterEvent
- QDragLeaveEvent
While these don't carry extra data or members, a dynamic_cast of the
result of clone() as well as using the expected covariant return value
would fail:
QShowEvent *e = ~~~;
QShowEvent *e2 = e->clone(); // ERROR: converting QEvent* to QShowEvent*
Check that reimplementing clone() is binary compatible (covariant
returns may change the numerical pointer value returned, cf.
https://community.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B).
The copy-assignment operator stays inline for the time being, as the
goal is to = delete it in the future.
This patch covers, roughly, QtCore and QtGui.
[ChangeLog][QtGui][QEvent subclasses] Fixed missing clone()
reimplementations on QCloseEvent, QIconDragEvent, QShowEvent,
QHideEvent, QDragEnterEvent, and QDragLeaveEvent.
Task-number: QTBUG-45582
Task-number: QTBUG-97601
Change-Id: Ib8a0519dbe85a7a8da61050d48be338004dfa69a
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'tests/auto/gui')
-rw-r--r-- | tests/auto/gui/kernel/qevent/CMakeLists.txt | 3 | ||||
-rw-r--r-- | tests/auto/gui/kernel/qevent/tst_qevent.cpp | 82 |
2 files changed, 83 insertions, 2 deletions
diff --git a/tests/auto/gui/kernel/qevent/CMakeLists.txt b/tests/auto/gui/kernel/qevent/CMakeLists.txt index 2bb22eb469..7b37b0c51a 100644 --- a/tests/auto/gui/kernel/qevent/CMakeLists.txt +++ b/tests/auto/gui/kernel/qevent/CMakeLists.txt @@ -7,4 +7,7 @@ qt_internal_add_test(tst_qevent SOURCES tst_qevent.cpp + PUBLIC_LIBRARIES + Qt::Gui + Qt::CorePrivate ) diff --git a/tests/auto/gui/kernel/qevent/tst_qevent.cpp b/tests/auto/gui/kernel/qevent/tst_qevent.cpp index 6542ed5ad3..cc8ac6ea6c 100644 --- a/tests/auto/gui/kernel/qevent/tst_qevent.cpp +++ b/tests/auto/gui/kernel/qevent/tst_qevent.cpp @@ -29,8 +29,73 @@ #include <QTest> -#include <QtCore/qcoreapplication.h> -#include <QtCore/qcoreevent.h> +#include <QtGui/qguiapplication.h> +#include <QtGui/qevent.h> +#include <QtCore/private/qfutureinterface_p.h> + +#define FOR_EACH_CORE_EVENT(X) \ + /* qcoreevent.h */ \ + X(QEvent, (QEvent::None)) \ + X(QTimerEvent, (42)) \ + X(QChildEvent, (QEvent::ChildAdded, nullptr)) \ + X(QDynamicPropertyChangeEvent, ("size")) \ + X(QDeferredDeleteEvent, ()) \ + /* qfutureinterface_p.h */ \ + X(QFutureCallOutEvent, ()) \ + /* end */ + +#define FOR_EACH_GUI_EVENT(X) \ + /* qevent.h */ \ + X(QInputEvent, (QEvent::None, nullptr)) \ + X(QPointerEvent, (QEvent::None, nullptr)) \ + /* doesn't work with nullptr: */ \ + X(QSinglePointEvent, (QEvent::None, QPointingDevice::primaryPointingDevice(), {}, {}, {}, {}, {}, {})) \ + X(QEnterEvent, ({}, {}, {})) \ + X(QMouseEvent, (QEvent::None, {}, {}, {}, {}, {}, {}, {}, QPointingDevice::primaryPointingDevice())) \ + X(QHoverEvent, (QEvent::None, {}, {}, QPointF{})) \ + X(QWheelEvent, ({}, {}, {}, {}, {}, {}, {}, {})) \ + X(QTabletEvent, (QEvent::None, QPointingDevice::primaryPointingDevice(), {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {})) \ + X(QNativeGestureEvent, ({}, QPointingDevice::primaryPointingDevice(), 0, {}, {}, {}, {}, {})) \ + X(QKeyEvent, (QEvent::None, 0, {})) \ + X(QFocusEvent, (QEvent::None)) \ + X(QPaintEvent, (QRect{0, 0, 100, 100})) \ + X(QMoveEvent, ({}, {})) \ + X(QExposeEvent, ({})) \ + X(QPlatformSurfaceEvent, ({})) \ + X(QResizeEvent, ({}, {})) \ + X(QCloseEvent, ()) \ + X(QIconDragEvent, ()) \ + X(QShowEvent, ()) \ + X(QHideEvent, ()) \ + QT_WARNING_PUSH \ + QT_WARNING_DISABLE_DEPRECATED \ + X(QContextMenuEvent, (QContextMenuEvent::Reason::Keyboard, {})) \ + QT_WARNING_POP \ + X(QInputMethodEvent, ()) \ + X(QInputMethodQueryEvent, ({})) \ + X(QDropEvent, ({}, {}, {}, {}, {})) \ + X(QDragMoveEvent, ({}, {}, {}, {}, {})) \ + X(QDragEnterEvent, ({}, {}, {}, {}, {})) \ + X(QDragLeaveEvent, ()) \ + X(QHelpEvent, ({}, {}, {})) \ + X(QStatusTipEvent, ({})) \ + X(QWhatsThisClickedEvent, ({})) \ + X(QActionEvent, (0, nullptr)) \ + X(QFileOpenEvent, (QString{})) \ + X(QToolBarChangeEvent, (false)) \ + X(QShortcutEvent, ({}, 0)) \ + X(QWindowStateChangeEvent, ({})) \ + X(QTouchEvent, (QEvent::None)) \ + X(QScrollPrepareEvent, ({})) \ + X(QScrollEvent, ({}, {}, {})) \ + X(QScreenOrientationChangeEvent, (nullptr, {})) \ + X(QApplicationStateChangeEvent, ({})) \ + /* end */ + +#define FOR_EACH_EVENT(X) \ + FOR_EACH_CORE_EVENT(X) \ + FOR_EACH_GUI_EVENT(X) \ + /* end */ class tst_QEvent : public QObject { @@ -40,6 +105,7 @@ public: ~tst_QEvent(); private slots: + void clone() const; void registerEventType_data(); void registerEventType(); void exhaustEventTypeRegistration(); // keep behind registerEventType() test @@ -55,6 +121,18 @@ tst_QEvent::tst_QEvent() tst_QEvent::~tst_QEvent() { } +void tst_QEvent::clone() const +{ +#define ACTION(Type, Init) do { \ + const std::unique_ptr<const Type> e(new Type Init); \ + auto c = e->clone(); \ + static_assert(std::is_same_v<decltype(c), Type *>); \ + delete c; \ + } while (0); + + FOR_EACH_EVENT(ACTION) +} + void tst_QEvent::registerEventType_data() { QTest::addColumn<int>("hint"); |