4a7c76d4a5
All these TUs relied on transitive includes of qpointer.h, maybe to a large extent via qevent.h, though, given that qevent.h is more or less the only public QtBase header that includes qpointer.h, something else seems to be at play here. Said qevent.h actually needs QPointer in-name-only, so a forward declaration would suffice. Prepare for qevent.h dropping the include. The algorithm I used was: If the TU mentions 'passiveGrabbers', the name of the QEvent function that returns QPointers, and the TU doesn't have qpointer.h included explicitly, include it. That may produce False Positives, but better safe than sorry. Otherwise, in src/, add an include to all source and header files which mention QPointer. Exception: if foo.h of a foo.cpp already includes it, don't include again. Task-number: QTBUG-117670 Change-Id: I3321cccdb41ce0ba6d8a709cea92427aba398254 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
336 lines
13 KiB
C++
336 lines
13 KiB
C++
// Copyright (C) 2020 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
|
|
|
|
#include <QTest>
|
|
#include <qevent.h>
|
|
#include <qwindow.h>
|
|
#include <QtGui/private/qpointingdevice_p.h>
|
|
|
|
#include <QtCore/qpointer.h>
|
|
|
|
Q_LOGGING_CATEGORY(lcTests, "qt.gui.tests")
|
|
|
|
class MouseEventWidget : public QWindow
|
|
{
|
|
public:
|
|
MouseEventWidget(QWindow *parent = nullptr) : QWindow(parent)
|
|
{
|
|
setGeometry(100, 100, 100, 100);
|
|
}
|
|
bool grabExclusive = false;
|
|
bool grabPassive = false;
|
|
bool mousePressEventRecieved;
|
|
bool mouseReleaseEventRecieved;
|
|
int mousePressButton;
|
|
int mousePressButtons;
|
|
int mousePressModifiers;
|
|
int mouseReleaseButton;
|
|
int mouseReleaseButtons;
|
|
int mouseReleaseModifiers;
|
|
ulong timestamp;
|
|
ulong pressTimestamp;
|
|
ulong lastTimestamp;
|
|
QVector2D velocity;
|
|
protected:
|
|
void mousePressEvent(QMouseEvent *e) override
|
|
{
|
|
const auto &firstPoint = e->point(0);
|
|
qCDebug(lcTests) << e << firstPoint;
|
|
timestamp = firstPoint.timestamp();
|
|
lastTimestamp = firstPoint.lastTimestamp();
|
|
if (e->type() == QEvent::MouseButtonPress) {
|
|
auto firstPoint = e->points().first();
|
|
QCOMPARE(e->exclusiveGrabber(firstPoint), nullptr);
|
|
QVERIFY(e->passiveGrabbers(firstPoint).isEmpty());
|
|
QCOMPARE(firstPoint.timeHeld(), 0);
|
|
QCOMPARE(firstPoint.pressTimestamp(), e->timestamp());
|
|
pressTimestamp = e->timestamp();
|
|
}
|
|
QWindow::mousePressEvent(e);
|
|
mousePressButton = e->button();
|
|
mousePressButtons = e->buttons();
|
|
mousePressModifiers = e->modifiers();
|
|
mousePressEventRecieved = true;
|
|
e->accept();
|
|
// It's not normal for QWindow to be the grabber, but that's easier to test
|
|
// without needing to create child ojects.
|
|
if (grabExclusive)
|
|
e->setExclusiveGrabber(firstPoint, this);
|
|
if (grabPassive)
|
|
e->addPassiveGrabber(firstPoint, this);
|
|
}
|
|
void mouseMoveEvent(QMouseEvent *e) override
|
|
{
|
|
qCDebug(lcTests) << e << e->points().first();
|
|
timestamp = e->points().first().timestamp();
|
|
lastTimestamp = e->points().first().lastTimestamp();
|
|
velocity = e->points().first().velocity();
|
|
}
|
|
void mouseReleaseEvent(QMouseEvent *e) override
|
|
{
|
|
qCDebug(lcTests) << e << e->points().first();
|
|
QWindow::mouseReleaseEvent(e);
|
|
mouseReleaseButton = e->button();
|
|
mouseReleaseButtons = e->buttons();
|
|
mouseReleaseModifiers = e->modifiers();
|
|
timestamp = e->points().first().timestamp();
|
|
lastTimestamp = e->points().first().lastTimestamp();
|
|
velocity = e->points().first().velocity();
|
|
mouseReleaseEventRecieved = true;
|
|
e->accept();
|
|
}
|
|
};
|
|
|
|
class tst_QMouseEvent : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public slots:
|
|
void initTestCase();
|
|
void cleanupTestCase();
|
|
void init();
|
|
private slots:
|
|
void mouseEventBasic();
|
|
void checkMousePressEvent_data();
|
|
void checkMousePressEvent();
|
|
void checkMouseReleaseEvent_data();
|
|
void checkMouseReleaseEvent();
|
|
void grabbers_data();
|
|
void grabbers();
|
|
void velocity();
|
|
void clone();
|
|
|
|
private:
|
|
MouseEventWidget* testMouseWidget;
|
|
};
|
|
|
|
void tst_QMouseEvent::initTestCase()
|
|
{
|
|
testMouseWidget = new MouseEventWidget;
|
|
testMouseWidget->show();
|
|
}
|
|
|
|
void tst_QMouseEvent::cleanupTestCase()
|
|
{
|
|
delete testMouseWidget;
|
|
}
|
|
|
|
void tst_QMouseEvent::init()
|
|
{
|
|
testMouseWidget->mousePressEventRecieved = false;
|
|
testMouseWidget->mouseReleaseEventRecieved = false;
|
|
testMouseWidget->mousePressButton = 0;
|
|
testMouseWidget->mousePressButtons = 0;
|
|
testMouseWidget->mousePressModifiers = 0;
|
|
testMouseWidget->mouseReleaseButton = 0;
|
|
testMouseWidget->mouseReleaseButtons = 0;
|
|
testMouseWidget->mouseReleaseModifiers = 0;
|
|
}
|
|
|
|
void tst_QMouseEvent::mouseEventBasic()
|
|
{
|
|
QPointF local(100, 100);
|
|
QPointF scene(200, 200);
|
|
QPointF screen(300, 300);
|
|
// Press left button
|
|
QMouseEvent me(QEvent::MouseButtonPress, local, scene, screen, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
|
QVERIFY(me.isInputEvent());
|
|
QVERIFY(me.isPointerEvent());
|
|
QVERIFY(me.isSinglePointEvent());
|
|
QCOMPARE(me.isAccepted(), true);
|
|
QCOMPARE(me.button(), Qt::LeftButton);
|
|
QCOMPARE(me.buttons(), Qt::LeftButton);
|
|
QVERIFY(me.isBeginEvent());
|
|
QVERIFY(!me.isEndEvent());
|
|
QCOMPARE(me.position(), local);
|
|
QCOMPARE(me.scenePosition(), scene);
|
|
QCOMPARE(me.globalPosition(), screen);
|
|
// Press right button while left is already pressed
|
|
QMouseEvent me2(QEvent::MouseButtonPress, local, scene, screen, Qt::RightButton, Qt::LeftButton | Qt::RightButton, Qt::NoModifier);
|
|
QVERIFY(me2.isBeginEvent());
|
|
QVERIFY(!me2.isEndEvent());
|
|
// Release right button while left is still pressed
|
|
QMouseEvent me3 = QMouseEvent(QEvent::MouseButtonRelease, local, scene, screen, Qt::RightButton, Qt::LeftButton, Qt::NoModifier);
|
|
QVERIFY(!me3.isBeginEvent());
|
|
QVERIFY(me3.isEndEvent());
|
|
// Release left button in the usual way
|
|
QMouseEvent me4 = QMouseEvent(QEvent::MouseButtonRelease, local, scene, screen, Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
|
|
QVERIFY(!me4.isBeginEvent());
|
|
QVERIFY(me4.isEndEvent());
|
|
}
|
|
|
|
void tst_QMouseEvent::checkMousePressEvent_data()
|
|
{
|
|
QTest::addColumn<int>("buttonPressed");
|
|
QTest::addColumn<int>("keyPressed");
|
|
|
|
QTest::newRow("leftButton-nokey") << int(Qt::LeftButton) << int(Qt::NoButton);
|
|
QTest::newRow("leftButton-shiftkey") << int(Qt::LeftButton) << int(Qt::ShiftModifier);
|
|
QTest::newRow("leftButton-controlkey") << int(Qt::LeftButton) << int(Qt::ControlModifier);
|
|
QTest::newRow("leftButton-altkey") << int(Qt::LeftButton) << int(Qt::AltModifier);
|
|
QTest::newRow("leftButton-metakey") << int(Qt::LeftButton) << int(Qt::MetaModifier);
|
|
QTest::newRow("rightButton-nokey") << int(Qt::RightButton) << int(Qt::NoButton);
|
|
QTest::newRow("rightButton-shiftkey") << int(Qt::RightButton) << int(Qt::ShiftModifier);
|
|
QTest::newRow("rightButton-controlkey") << int(Qt::RightButton) << int(Qt::ControlModifier);
|
|
QTest::newRow("rightButton-altkey") << int(Qt::RightButton) << int(Qt::AltModifier);
|
|
QTest::newRow("rightButton-metakey") << int(Qt::RightButton) << int(Qt::MetaModifier);
|
|
QTest::newRow("middleButton-nokey") << int(Qt::MiddleButton) << int(Qt::NoButton);
|
|
QTest::newRow("middleButton-shiftkey") << int(Qt::MiddleButton) << int(Qt::ShiftModifier);
|
|
QTest::newRow("middleButton-controlkey") << int(Qt::MiddleButton) << int(Qt::ControlModifier);
|
|
QTest::newRow("middleButton-altkey") << int(Qt::MiddleButton) << int(Qt::AltModifier);
|
|
QTest::newRow("middleButton-metakey") << int(Qt::MiddleButton) << int(Qt::MetaModifier);
|
|
}
|
|
|
|
void tst_QMouseEvent::checkMousePressEvent()
|
|
{
|
|
QFETCH(int,buttonPressed);
|
|
QFETCH(int,keyPressed);
|
|
int button = buttonPressed;
|
|
int buttons = button;
|
|
int modifiers = keyPressed;
|
|
|
|
QTest::mousePress(testMouseWidget, Qt::MouseButton(buttonPressed), Qt::KeyboardModifiers(keyPressed));
|
|
qApp->processEvents();
|
|
QVERIFY(testMouseWidget->mousePressEventRecieved);
|
|
QCOMPARE(testMouseWidget->mousePressButton, button);
|
|
QCOMPARE(testMouseWidget->mousePressButtons, buttons);
|
|
QCOMPARE(testMouseWidget->mousePressModifiers, modifiers);
|
|
|
|
QTest::mouseRelease(testMouseWidget, Qt::MouseButton(buttonPressed), Qt::KeyboardModifiers(keyPressed));
|
|
qApp->processEvents();
|
|
}
|
|
|
|
void tst_QMouseEvent::checkMouseReleaseEvent_data()
|
|
{
|
|
QTest::addColumn<int>("buttonReleased");
|
|
QTest::addColumn<int>("keyPressed");
|
|
|
|
QTest::newRow("leftButton-nokey") << int(Qt::LeftButton) << int(Qt::NoButton);
|
|
QTest::newRow("leftButton-shiftkey") << int(Qt::LeftButton) << int(Qt::ShiftModifier);
|
|
QTest::newRow("leftButton-controlkey") << int(Qt::LeftButton) << int(Qt::ControlModifier);
|
|
QTest::newRow("leftButton-altkey") << int(Qt::LeftButton) << int(Qt::AltModifier);
|
|
QTest::newRow("leftButton-metakey") << int(Qt::LeftButton) << int(Qt::MetaModifier);
|
|
QTest::newRow("rightButton-nokey") << int(Qt::RightButton) << int(Qt::NoButton);
|
|
QTest::newRow("rightButton-shiftkey") << int(Qt::RightButton) << int(Qt::ShiftModifier);
|
|
QTest::newRow("rightButton-controlkey") << int(Qt::RightButton) << int(Qt::ControlModifier);
|
|
QTest::newRow("rightButton-altkey") << int(Qt::RightButton) << int(Qt::AltModifier);
|
|
QTest::newRow("rightButton-metakey") << int(Qt::RightButton) << int(Qt::MetaModifier);
|
|
QTest::newRow("middleButton-nokey") << int(Qt::MiddleButton) << int(Qt::NoButton);
|
|
QTest::newRow("middleButton-shiftkey") << int(Qt::MiddleButton) << int(Qt::ShiftModifier);
|
|
QTest::newRow("middleButton-controlkey") << int(Qt::MiddleButton) << int(Qt::ControlModifier);
|
|
QTest::newRow("middleButton-altkey") << int(Qt::MiddleButton) << int(Qt::AltModifier);
|
|
QTest::newRow("middleButton-metakey") << int(Qt::MiddleButton) << int(Qt::MetaModifier);
|
|
}
|
|
|
|
void tst_QMouseEvent::checkMouseReleaseEvent()
|
|
{
|
|
QFETCH(int,buttonReleased);
|
|
QFETCH(int,keyPressed);
|
|
int button = buttonReleased;
|
|
int buttons = 0;
|
|
int modifiers = keyPressed;
|
|
|
|
QTest::mouseClick(testMouseWidget, Qt::MouseButton(buttonReleased), Qt::KeyboardModifiers(keyPressed));
|
|
qApp->processEvents();
|
|
QVERIFY(testMouseWidget->mouseReleaseEventRecieved);
|
|
QCOMPARE(testMouseWidget->mouseReleaseButton, button);
|
|
QCOMPARE(testMouseWidget->mouseReleaseButtons, buttons);
|
|
QCOMPARE(testMouseWidget->mouseReleaseModifiers, modifiers);
|
|
}
|
|
|
|
void tst_QMouseEvent::grabbers_data()
|
|
{
|
|
QTest::addColumn<bool>("grabExclusive");
|
|
QTest::addColumn<bool>("grabPassive");
|
|
|
|
QTest::newRow("no grab") << false << false;
|
|
QTest::newRow("exclusive") << true << false;
|
|
QTest::newRow("passive") << false << true;
|
|
}
|
|
|
|
void tst_QMouseEvent::grabbers()
|
|
{
|
|
QFETCH(bool, grabExclusive);
|
|
QFETCH(bool, grabPassive);
|
|
|
|
testMouseWidget->grabExclusive = grabExclusive;
|
|
testMouseWidget->grabPassive = grabPassive;
|
|
|
|
QTest::mousePress(testMouseWidget, Qt::LeftButton, Qt::KeyboardModifiers(), {10, 10});
|
|
|
|
auto devPriv = QPointingDevicePrivate::get(QPointingDevice::primaryPointingDevice());
|
|
QCOMPARE(devPriv->activePoints.count(), 1);
|
|
|
|
// Ensure that grabbers are persistent between events, within the stored touchpoints
|
|
auto firstEPD = devPriv->pointById(0);
|
|
QCOMPARE(firstEPD->eventPoint.pressTimestamp(), testMouseWidget->pressTimestamp);
|
|
QCOMPARE(firstEPD->exclusiveGrabber, grabExclusive ? testMouseWidget : nullptr);
|
|
QCOMPARE(firstEPD->passiveGrabbers.size(), grabPassive ? 1 : 0);
|
|
if (grabPassive)
|
|
QCOMPARE(firstEPD->passiveGrabbers.first(), testMouseWidget);
|
|
|
|
// Ensure that grabbers are forgotten after release delivery
|
|
QTest::mouseRelease(testMouseWidget, Qt::LeftButton, Qt::KeyboardModifiers(), {10, 10});
|
|
QTRY_COMPARE(firstEPD->exclusiveGrabber, nullptr);
|
|
QCOMPARE(firstEPD->passiveGrabbers.size(), 0);
|
|
}
|
|
|
|
void tst_QMouseEvent::velocity()
|
|
{
|
|
testMouseWidget->grabExclusive = true;
|
|
auto devPriv = QPointingDevicePrivate::get(const_cast<QPointingDevice *>(QPointingDevice::primaryPointingDevice()));
|
|
devPriv->activePoints.clear();
|
|
|
|
qCDebug(lcTests) << "sending mouse press event";
|
|
QPoint pos(10, 10);
|
|
QTest::mousePress(testMouseWidget, Qt::LeftButton, Qt::KeyboardModifiers(), pos);
|
|
QCOMPARE(devPriv->activePoints.count(), 1);
|
|
QVERIFY(devPriv->activePoints.count() <= 2);
|
|
const auto &firstPoint = devPriv->pointById(0)->eventPoint;
|
|
QVERIFY(firstPoint.timestamp() > 0);
|
|
QCOMPARE(firstPoint.state(), QEventPoint::State::Pressed);
|
|
|
|
ulong timestamp = firstPoint.timestamp();
|
|
for (int i = 1; i < 4; ++i) {
|
|
qCDebug(lcTests) << "sending mouse move event" << i;
|
|
pos += {10, 10};
|
|
QTest::mouseMove(testMouseWidget, pos, 1);
|
|
qApp->processEvents();
|
|
qCDebug(lcTests) << firstPoint;
|
|
// currently we expect it to be updated in-place in devPriv->activePoints
|
|
QVERIFY(firstPoint.timestamp() > timestamp);
|
|
QVERIFY(testMouseWidget->timestamp > testMouseWidget->lastTimestamp);
|
|
QCOMPARE(testMouseWidget->timestamp, firstPoint.timestamp());
|
|
timestamp = firstPoint.timestamp();
|
|
QVERIFY(testMouseWidget->velocity.x() > 0);
|
|
QVERIFY(testMouseWidget->velocity.y() > 0);
|
|
}
|
|
QTest::mouseRelease(testMouseWidget, Qt::LeftButton, Qt::KeyboardModifiers(), pos, 1);
|
|
qCDebug(lcTests) << firstPoint;
|
|
QVERIFY(testMouseWidget->velocity.x() > 0);
|
|
QVERIFY(testMouseWidget->velocity.y() > 0);
|
|
}
|
|
|
|
void tst_QMouseEvent::clone()
|
|
{
|
|
const QPointF pos(10.0f, 10.0f);
|
|
|
|
QMouseEvent originalMe(QEvent::MouseButtonPress, pos, pos, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
|
QVERIFY(!originalMe.allPointsAccepted());
|
|
QVERIFY(!originalMe.points().first().isAccepted());
|
|
|
|
// create a clone of the original
|
|
std::unique_ptr<QMouseEvent> clonedMe(originalMe.clone());
|
|
QVERIFY(!clonedMe->allPointsAccepted());
|
|
QVERIFY(!clonedMe->points().first().isAccepted());
|
|
|
|
// now we alter originalMe, which should *not* change clonedMe
|
|
originalMe.setAccepted(true);
|
|
QVERIFY(!clonedMe->allPointsAccepted());
|
|
QVERIFY(!clonedMe->points().first().isAccepted());
|
|
}
|
|
|
|
QTEST_MAIN(tst_QMouseEvent)
|
|
#include "tst_qmouseevent.moc"
|