Deliver tablet events to the toplevel widget if there is no child

QWidgetWindow dispatched only tablet presses to the toplevel widget if
no child was found at the position; other events, such as hover events,
were discarded. The tabletTracking test case even documented that
shortcoming in a comment.

Fix that by falling back to the toplevel widget for any event. As
before, only press events initialize the tablet grabbing target widget.

Remove the now unneeded parent widget from the test case, and move the
test class into the only test function that uses it.

Amends ea615b421b and
8fd6cef372.

Pick-to: 6.4
Fixes: QTBUG-108747
Change-Id: I79050f1e063931e439945f64b50712dcc1ecb18c
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
Volker Hilsheimer 2022-11-30 16:17:18 +01:00 committed by Shawn Rutledge
parent f6b137bdc4
commit 7956d9e060
2 changed files with 44 additions and 51 deletions

View File

@ -1053,11 +1053,10 @@ void QWidgetWindow::handleTabletEvent(QTabletEvent *event)
if (!widget) {
widget = m_widget->childAt(event->position().toPoint());
if (event->type() == QEvent::TabletPress) {
if (!widget)
widget = m_widget;
if (!widget)
widget = m_widget;
if (event->type() == QEvent::TabletPress)
qt_tablet_target = widget;
}
}
if (widget) {

View File

@ -12500,60 +12500,54 @@ void tst_QWidget::testForOutsideWSRangeFlag()
}
}
class TabletWidget : public QWidget
{
public:
TabletWidget(QWidget *parent) : QWidget(parent) { }
int tabletEventCount = 0;
int pressEventCount = 0;
int moveEventCount = 0;
int releaseEventCount = 0;
int trackingChangeEventCount = 0;
qint64 uid = -1;
protected:
void tabletEvent(QTabletEvent *event) override {
++tabletEventCount;
uid = event->pointingDevice()->uniqueId().numericId();
switch (event->type()) {
case QEvent::TabletMove:
++moveEventCount;
break;
case QEvent::TabletPress:
++pressEventCount;
break;
case QEvent::TabletRelease:
++releaseEventCount;
break;
default:
break;
}
}
bool event(QEvent *ev) override {
if (ev->type() == QEvent::TabletTrackingChange)
++trackingChangeEventCount;
return QWidget::event(ev);
}
};
void tst_QWidget::tabletTracking()
{
QWidget parent;
parent.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
parent.resize(200,200);
// QWidgetWindow::handleTabletEvent doesn't deliver tablet events to the window's widget, only to a child.
// So it doesn't do any good to show a TabletWidget directly: it needs a parent.
TabletWidget widget(&parent);
class TabletWidget : public QWidget
{
public:
using QWidget::QWidget;
int tabletEventCount = 0;
int pressEventCount = 0;
int moveEventCount = 0;
int releaseEventCount = 0;
int trackingChangeEventCount = 0;
qint64 uid = -1;
protected:
void tabletEvent(QTabletEvent *event) override {
++tabletEventCount;
uid = event->pointingDevice()->uniqueId().numericId();
switch (event->type()) {
case QEvent::TabletMove:
++moveEventCount;
break;
case QEvent::TabletPress:
++pressEventCount;
break;
case QEvent::TabletRelease:
++releaseEventCount;
break;
default:
break;
}
}
bool event(QEvent *ev) override {
if (ev->type() == QEvent::TabletTrackingChange)
++trackingChangeEventCount;
return QWidget::event(ev);
}
} widget;
widget.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
widget.resize(200,200);
parent.showNormal();
QVERIFY(QTest::qWaitForWindowExposed(&parent));
widget.showNormal();
QVERIFY(QTest::qWaitForWindowExposed(&widget));
widget.setAttribute(Qt::WA_TabletTracking);
QTRY_COMPARE(widget.trackingChangeEventCount, 1);
QVERIFY(widget.hasTabletTracking());
QWindow *window = parent.windowHandle();
QWindow *window = widget.windowHandle();
QPointF local(10, 10);
QPointF global = window->mapToGlobal(local.toPoint());
QPointF deviceLocal = QHighDpi::toNativeLocalPosition(local, window);