Merge "Merge remote-tracking branch 'origin/5.14' into 5.15"

This commit is contained in:
Qt Forward Merge Bot 2020-04-06 01:00:35 +02:00 committed by Edward Welbourne
commit 12fc3f5751
7 changed files with 148 additions and 115 deletions

View File

@ -84,10 +84,8 @@ enum {
WM_QT_ACTIVATENOTIFIERS = WM_USER + 2
};
// WM_QT_SENDPOSTEDEVENTS message parameter
enum {
WMWP_QT_TOFOREIGNLOOP = 0,
WMWP_QT_FROMWAKEUP
SendPostedEventsTimerId = ~1u
};
class QEventDispatcherWin32Private;
@ -100,8 +98,8 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
QEventDispatcherWin32Private::QEventDispatcherWin32Private()
: threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0),
getMessageHook(0), wakeUps(0), activateNotifiersPosted(false),
winEventNotifierActivatedEvent(NULL)
getMessageHook(0), sendPostedEventsTimerId(0), wakeUps(0),
activateNotifiersPosted(false), winEventNotifierActivatedEvent(NULL)
{
}
@ -129,6 +127,18 @@ void WINAPI QT_WIN_CALLBACK qt_fast_timer_proc(uint timerId, uint /*reserved*/,
QCoreApplication::postEvent(t->dispatcher, new QTimerEvent(t->timerId));
}
static inline UINT inputQueueMask()
{
UINT result = QS_ALLEVENTS;
// QTBUG 28513, QTBUG-29097, QTBUG-29435: QS_TOUCH, QS_POINTER became part of
// QS_INPUT in Windows Kit 8. They should not be used when running on pre-Windows 8.
#if WINVER > 0x0601
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8)
result &= ~(QS_TOUCH | QS_POINTER);
#endif // WINVER > 0x0601
return result;
}
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
{
if (message == WM_NCCREATE)
@ -240,6 +250,9 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
case WM_TIMER:
Q_ASSERT(d != 0);
if (wp == d->sendPostedEventsTimerId)
q->sendPostedEvents();
else
d->sendTimerEvent(wp);
return 0;
case WM_QT_SENDPOSTEDEVENTS:
@ -247,6 +260,10 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
// We send posted events manually, if the window procedure was invoked
// by the foreign event loop (e.g. from the native modal dialog).
// Skip sending, if the message queue is not empty.
// sendPostedEventsTimer will deliver posted events later.
static const UINT mask = inputQueueMask();
if (HIWORD(GetQueueStatus(mask)) == 0)
q->sendPostedEvents();
return 0;
} // switch (message)
@ -254,33 +271,18 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
return DefWindowProc(hwnd, message, wp, lp);
}
static inline UINT inputQueueMask()
{
UINT result = QS_ALLEVENTS;
// QTBUG 28513, QTBUG-29097, QTBUG-29435: QS_TOUCH, QS_POINTER became part of
// QS_INPUT in Windows Kit 8. They should not be used when running on pre-Windows 8.
#if WINVER > 0x0601
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8)
result &= ~(QS_TOUCH | QS_POINTER);
#endif // WINVER > 0x0601
return result;
}
LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp)
{
QEventDispatcherWin32 *q = qobject_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance());
Q_ASSERT(q != 0);
QEventDispatcherWin32Private *d = q->d_func();
MSG *msg = reinterpret_cast<MSG *>(lp);
static const UINT mask = inputQueueMask();
if (HIWORD(GetQueueStatus(mask)) == 0 && wp == PM_REMOVE) {
// Allow posting WM_QT_SENDPOSTEDEVENTS message.
d->wakeUps.storeRelaxed(0);
if (!(msg->hwnd == d->internalHwnd && msg->message == WM_QT_SENDPOSTEDEVENTS)) {
PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS,
WMWP_QT_TOFOREIGNLOOP, 0);
}
if (msg->hwnd == d->internalHwnd && msg->message == WM_QT_SENDPOSTEDEVENTS
&& wp == PM_REMOVE && d->sendPostedEventsTimerId == 0) {
// Start a timer to deliver posted events when the message queue is emptied.
d->sendPostedEventsTimerId = SetTimer(d->internalHwnd, SendPostedEventsTimerId,
USER_TIMER_MINIMUM, NULL);
}
return d->getMessageHook ? CallNextHookEx(0, code, wp, lp) : 0;
}
@ -571,12 +573,15 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
}
if (haveMessage) {
if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
// Set result to 'true', if the message was sent by wakeUp().
if (msg.wParam == WMWP_QT_FROMWAKEUP)
// Set result to 'true' because the message was sent by wakeUp().
retVal = true;
continue;
}
if (msg.message == WM_TIMER) {
// Skip timer event intended for use inside foreign loop.
if (d->internalHwnd == msg.hwnd && msg.wParam == d->sendPostedEventsTimerId)
continue;
// avoid live-lock by keeping track of the timers we've already sent
bool found = false;
for (int i = 0; !found && i < processedTimers.count(); ++i) {
@ -968,8 +973,7 @@ void QEventDispatcherWin32::wakeUp()
Q_D(QEventDispatcherWin32);
if (d->internalHwnd && d->wakeUps.testAndSetAcquire(0, 1)) {
// post a WM_QT_SENDPOSTEDEVENTS to this thread if there isn't one already pending
if (!PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS,
WMWP_QT_FROMWAKEUP, 0))
if (!PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0))
qErrnoWarning("QEventDispatcherWin32::wakeUp: Failed to post a message");
}
}
@ -1015,6 +1019,10 @@ void QEventDispatcherWin32::closingDown()
if (d->getMessageHook)
UnhookWindowsHookEx(d->getMessageHook);
d->getMessageHook = 0;
if (d->sendPostedEventsTimerId != 0)
KillTimer(d->internalHwnd, d->sendPostedEventsTimerId);
d->sendPostedEventsTimerId = 0;
}
bool QEventDispatcherWin32::event(QEvent *e)
@ -1056,6 +1064,14 @@ bool QEventDispatcherWin32::event(QEvent *e)
void QEventDispatcherWin32::sendPostedEvents()
{
Q_D(QEventDispatcherWin32);
if (d->sendPostedEventsTimerId != 0)
KillTimer(d->internalHwnd, d->sendPostedEventsTimerId);
d->sendPostedEventsTimerId = 0;
// Allow posting WM_QT_SENDPOSTEDEVENTS message.
d->wakeUps.storeRelaxed(0);
QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData.loadRelaxed());
}

View File

@ -171,6 +171,7 @@ public:
HHOOK getMessageHook;
// for controlling when to send posted events
UINT_PTR sendPostedEventsTimerId;
QAtomicInt wakeUps;
// timers

View File

@ -235,15 +235,15 @@ bool QLibraryPrivate::load_sys()
hnd = dlopen(QFile::encodeName(attempt), dlFlags);
#ifdef Q_OS_ANDROID
if (!pHnd) {
if (!hnd) {
auto attemptFromBundle = attempt;
pHnd = dlopen(QFile::encodeName(attemptFromBundle.replace(QLatin1Char('/'), QLatin1Char('_'))), dlFlags);
hnd = dlopen(QFile::encodeName(attemptFromBundle.replace(QLatin1Char('/'), QLatin1Char('_'))), dlFlags);
}
if (pHnd) {
if (hnd) {
using JniOnLoadPtr = jint (*)(JavaVM *vm, void *reserved);
JniOnLoadPtr jniOnLoad = reinterpret_cast<JniOnLoadPtr>(dlsym(pHnd, "JNI_OnLoad"));
if (jniOnLoad && jniOnLoad(QtAndroidPrivate::javaVM(), nullptr) == JNI_ERR) {
dlclose(pHnd);
dlclose(hnd);
pHnd = nullptr;
}
}

View File

@ -277,10 +277,11 @@ static int fromOffsetString(QStringView offsetString, bool *valid) noexcept
\reentrant
\brief The QDate class provides date functions.
A QDate object represents a particular date. This can be expressed as a
calendar date, i.e. year, month, and day numbers, in the proleptic Gregorian
calendar.
A QDate object represents a particular day, regardless of calendar,
locale or other settings used when creating it or supplied by the system.
It can report the year, month and day of the month that represent the
day with respect to the proleptic Gregorian calendar or any calendar supplied
as a QCalendar object.
A QDate object is typically created by giving the year, month, and day
numbers explicitly. Note that QDate interprets year numbers less than 100 as
@ -1578,9 +1579,8 @@ qint64 QDate::daysTo(const QDate &d) const
/*!
\fn bool QDate::operator==(const QDate &d) const
Returns \c true if this date is equal to \a d; otherwise returns
false.
Returns \c true if this date and \a d represent the same day, otherwise
\c false.
*/
/*!
@ -1588,6 +1588,8 @@ qint64 QDate::daysTo(const QDate &d) const
Returns \c true if this date is different from \a d; otherwise
returns \c false.
\sa operator==()
*/
/*!

View File

@ -374,7 +374,7 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
*/
/*!
\enum QLineF::IntersectType
\enum QLineF::IntersectionType
Describes the intersection between two lines.

View File

@ -1229,6 +1229,11 @@ void DeleteLaterWidget::runTest()
QCoreApplication::processEvents();
// At this point, the event queue is empty. As we want a deferred
// deletion to occur before the timer event, we should provoke the
// event dispatcher for the next spin.
QCoreApplication::eventDispatcher()->interrupt();
QVERIFY(!stillAlive); // verify at the end to make test terminate
}
@ -1258,8 +1263,10 @@ void tst_QApplication::testDeleteLater()
QObject *stillAlive = wgt->findChild<QObject*>("deleteLater");
QVERIFY(stillAlive);
wgt->show();
QCoreApplication::exec();
QVERIFY(wgt->isHidden());
delete wgt;
}

View File

@ -348,41 +348,46 @@ void tst_QScroller::scrollerProperties()
void tst_QScroller::scrollTo()
{
{
tst_QScrollerWidget *sw = new tst_QScrollerWidget();
QScopedPointer<tst_QScrollerWidget> sw(new tst_QScrollerWidget);
sw->show();
QApplication::setActiveWindow(sw.data());
if (!QTest::qWaitForWindowExposed(sw.data()) || !QTest::qWaitForWindowActive(sw.data()))
QSKIP("Failed to show and activate window");
sw->scrollArea = QRectF(0, 0, 1000, 1000);
sw->scrollPosition = QPointF(500, 500);
QScroller *s1 = QScroller::scroller(sw);
QScroller *s1 = QScroller::scroller(sw.data());
QCOMPARE(s1->state(), QScroller::Inactive);
// a normal scroll
s1->scrollTo(QPointF(100,100), 100);
QTest::qWait(200);
QCOMPARE( sw->receivedPrepare, true );
QTRY_COMPARE(sw->receivedPrepare, true);
QCOMPARE(sw->receivedScroll, true);
QCOMPARE(sw->receivedFirst, true);
QCOMPARE(sw->receivedLast, true);
QCOMPARE(sw->receivedOvershoot, false);
QVERIFY(qFuzzyCompare( sw->currentPos.x(), 100 ));
QTRY_VERIFY(qFuzzyCompare(sw->currentPos.x(), 100));
QVERIFY(qFuzzyCompare(sw->currentPos.y(), 100));
delete sw;
}
}
void tst_QScroller::scroll()
{
#if QT_CONFIG(gestures) && QT_CONFIG(scroller)
// -- good case. normal scroll
tst_QScrollerWidget *sw = new tst_QScrollerWidget();
QScopedPointer<tst_QScrollerWidget> sw(new tst_QScrollerWidget());
sw->scrollArea = QRectF(0, 0, 1000, 1000);
QScroller::grabGesture(sw, QScroller::TouchGesture);
QScroller::grabGesture(sw.data(), QScroller::TouchGesture);
sw->setGeometry(100, 100, 400, 300);
sw->show();
QApplication::setActiveWindow(sw.data());
if (!QTest::qWaitForWindowExposed(sw.data()) || !QTest::qWaitForWindowActive(sw.data()))
QSKIP("Failed to show and activate window");
QScroller *s1 = QScroller::scroller(sw);
kineticScroll(sw, QPointF(500, 500), QPoint(0, 0), QPoint(100, 100), QPoint(200, 200));
QScroller *s1 = QScroller::scroller(sw.data());
kineticScroll(sw.data(), QPointF(500, 500), QPoint(0, 0), QPoint(100, 100), QPoint(200, 200));
// now we should be scrolling
QTRY_COMPARE(s1->state(), QScroller::Scrolling);
@ -401,26 +406,28 @@ void tst_QScroller::scroll()
sw->reset();
sw->scrollArea = QRectF(0, 0, 0, 1000);
kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(100, 0), QPoint(200, 0));
kineticScrollNoTest(sw.data(), QPointF(0, 500), QPoint(0, 0), QPoint(100, 0), QPoint(200, 0));
QTRY_COMPARE(s1->state(), QScroller::Inactive);
QCOMPARE(sw->currentPos.x(), 0.0);
QCOMPARE(sw->currentPos.y(), 500.0);
delete sw;
#endif
}
void tst_QScroller::overshoot()
{
#if QT_CONFIG(gestures) && QT_CONFIG(scroller)
tst_QScrollerWidget *sw = new tst_QScrollerWidget();
QScopedPointer<tst_QScrollerWidget> sw(new tst_QScrollerWidget);
sw->scrollArea = QRectF(0, 0, 1000, 1000);
QScroller::grabGesture(sw, QScroller::TouchGesture);
QScroller::grabGesture(sw.data(), QScroller::TouchGesture);
sw->setGeometry(100, 100, 400, 300);
sw->show();
QApplication::setActiveWindow(sw.data());
if (!QTest::qWaitForWindowExposed(sw.data()) || !QTest::qWaitForWindowActive(sw.data()))
QSKIP("Failed to show and activate window");
QScroller *s1 = QScroller::scroller(sw);
QScroller *s1 = QScroller::scroller(sw.data());
QScrollerProperties sp1 = s1->scrollerProperties();
sp1.setScrollMetric(QScrollerProperties::OvershootDragResistanceFactor, 0.5);
@ -431,7 +438,7 @@ void tst_QScroller::overshoot()
sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootWhenScrollable));
s1->setScrollerProperties(sp1);
kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
kineticScrollNoTest(sw.data(), QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
QTRY_COMPARE(s1->state(), QScroller::Inactive);
@ -446,7 +453,7 @@ void tst_QScroller::overshoot()
sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootWhenScrollable));
s1->setScrollerProperties(sp1);
kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
kineticScrollNoTest(sw.data(), QPointF(0, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
QTRY_COMPARE(s1->state(), QScroller::Inactive);
@ -461,7 +468,7 @@ void tst_QScroller::overshoot()
sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOn));
s1->setScrollerProperties(sp1);
kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
kineticScrollNoTest(sw.data(), QPointF(0, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
QTRY_COMPARE(s1->state(), QScroller::Inactive);
@ -477,7 +484,7 @@ void tst_QScroller::overshoot()
sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOff));
s1->setScrollerProperties(sp1);
kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
kineticScrollNoTest(sw.data(), QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
QTRY_COMPARE(s1->state(), QScroller::Inactive);
@ -493,25 +500,24 @@ void tst_QScroller::overshoot()
sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOn));
s1->setScrollerProperties(sp1);
kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
kineticScrollNoTest(sw.data(), QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
QTRY_COMPARE(s1->state(), QScroller::Inactive);
QVERIFY(qFuzzyCompare(sw->currentPos.x(), 0));
QVERIFY(qFuzzyCompare(sw->currentPos.y(), 500));
QCOMPARE(sw->receivedOvershoot, false);
delete sw;
#endif
}
void tst_QScroller::multipleWindows()
{
#if QT_CONFIG(gestures) && QT_CONFIG(scroller)
QScopedPointer<tst_QScrollerWidget> sw1(new tst_QScrollerWidget());
QScopedPointer<tst_QScrollerWidget> sw1(new tst_QScrollerWidget);
sw1->scrollArea = QRectF(0, 0, 1000, 1000);
QScroller::grabGesture(sw1.data(), QScroller::TouchGesture);
sw1->setGeometry(100, 100, 400, 300);
QScroller *s1 = QScroller::scroller(sw1.data());
kineticScroll(sw1.data(), QPointF(500, 500), QPoint(0, 0), QPoint(100, 100), QPoint(200, 200));
// now we should be scrolling
@ -522,6 +528,7 @@ void tst_QScroller::multipleWindows()
sw2->scrollArea = QRectF(0, 0, 1000, 1000);
QScroller::grabGesture(sw2.data(), QScroller::TouchGesture);
sw2->setGeometry(100, 100, 400, 300);
QScroller *s2 = QScroller::scroller(sw2.data());
kineticScroll(sw2.data(), QPointF(500, 500), QPoint(0, 0), QPoint(100, 100), QPoint(200, 200));
// now we should be scrolling