summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/CMakeLists.txt7
-rw-r--r--src/corelib/io/qiooperation_p_p.h4
-rw-r--r--src/corelib/io/qrandomaccessasyncfile_p_p.h14
-rw-r--r--src/corelib/io/qrandomaccessasyncfile_qioring.cpp438
-rw-r--r--src/corelib/tools/qlist.h23
-rw-r--r--src/plugins/platforms/wasm/qwasmevent.cpp4
-rw-r--r--src/plugins/platforms/wasm/qwasmevent.h4
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.cpp2
-rw-r--r--src/plugins/platforms/wasm/qwasmkeytranslator.cpp42
-rw-r--r--src/plugins/platforms/wasm/qwasmkeytranslator.h13
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.cpp3
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.h3
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.cpp7
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.h4
-rw-r--r--src/plugins/platforms/wayland/CMakeLists.txt1
-rw-r--r--src/plugins/platforms/wayland/qwaylanddisplay.cpp2
-rw-r--r--src/plugins/platforms/wayland/qwaylandeventdispatcher.cpp55
-rw-r--r--src/plugins/platforms/wayland/qwaylandeventdispatcher_p.h68
-rw-r--r--src/plugins/platforms/wayland/qwaylandintegration.cpp4
-rw-r--r--tests/auto/corelib/io/qrandomaccessasyncfile/tst_qrandomaccessasyncfile.cpp22
-rw-r--r--tests/auto/corelib/tools/qlist/tst_qlist.cpp33
-rw-r--r--tests/auto/wasm/CMakeLists.txt1
-rw-r--r--tests/auto/wasm/qwasmkeytranslator/tst_qwasmkeytranslator.cpp404
23 files changed, 540 insertions, 618 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index eda3152d9b7..e12d824cebb 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -583,6 +583,13 @@ if(QT_FEATURE_async_io)
SOURCES
io/qrandomaccessasyncfile_darwin.mm
)
+ elseif(LINUX AND QT_FEATURE_liburing)
+ qt_internal_extend_target(Core
+ SOURCES
+ io/qrandomaccessasyncfile_qioring.cpp
+ DEFINES
+ QT_RANDOMACCESSASYNCFILE_QIORING
+ )
elseif(QT_FEATURE_thread AND QT_FEATURE_future)
# TODO: This should become the last (fallback) condition later.
# We migth also want to rewrite it so that it does not depend on
diff --git a/src/corelib/io/qiooperation_p_p.h b/src/corelib/io/qiooperation_p_p.h
index 470e0858fd3..be780d4c785 100644
--- a/src/corelib/io/qiooperation_p_p.h
+++ b/src/corelib/io/qiooperation_p_p.h
@@ -24,6 +24,10 @@
#include <QtCore/qspan.h>
#include <QtCore/qvarlengtharray.h>
+#ifdef QT_RANDOMACCESSASYNCFILE_QIORING
+#include <QtCore/private/qioring_p.h>
+#endif
+
#include <variant>
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/io/qrandomaccessasyncfile_p_p.h b/src/corelib/io/qrandomaccessasyncfile_p_p.h
index 924c9f9ed83..11ad788c884 100644
--- a/src/corelib/io/qrandomaccessasyncfile_p_p.h
+++ b/src/corelib/io/qrandomaccessasyncfile_p_p.h
@@ -43,6 +43,11 @@
#endif // Q_OS_DARWIN
+#ifdef QT_RANDOMACCESSASYNCFILE_QIORING
+#include <QtCore/private/qioring_p.h>
+#include <QtCore/qlist.h>
+#endif
+
QT_BEGIN_NAMESPACE
class QRandomAccessAsyncFilePrivate : public QObjectPrivate
@@ -114,6 +119,15 @@ private:
void processFlush();
void processOpen();
void operationComplete();
+#elif defined(QT_RANDOMACCESSASYNCFILE_QIORING)
+ void queueCompletion(QIOOperationPrivate *priv, QIOOperation::Error error);
+ void startReadIntoSingle(QIOOperation *op, const QSpan<std::byte> &to);
+ void startWriteFromSingle(QIOOperation *op, const QSpan<const std::byte> &from);
+ QIORing::RequestHandle cancel(QIORing::RequestHandle handle);
+ QIORing *m_ioring = nullptr;
+ qintptr m_fd = -1;
+ QList<QPointer<QIOOperation>> m_operations;
+ QHash<QIOOperation *, QIORing::RequestHandle> m_opHandleMap;
#endif
#ifdef Q_OS_DARWIN
using OperationId = quint64;
diff --git a/src/corelib/io/qrandomaccessasyncfile_qioring.cpp b/src/corelib/io/qrandomaccessasyncfile_qioring.cpp
new file mode 100644
index 00000000000..c9783ea2856
--- /dev/null
+++ b/src/corelib/io/qrandomaccessasyncfile_qioring.cpp
@@ -0,0 +1,438 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:default
+
+#include "qrandomaccessasyncfile_p_p.h"
+
+#include "qiooperation_p.h"
+#include "qiooperation_p_p.h"
+
+#include <QtCore/qfile.h> // QtPrivate::toFilesystemPath
+#include <QtCore/qtypes.h>
+#include <QtCore/private/qioring_p.h>
+
+#include <QtCore/q26numeric.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_STATIC_LOGGING_CATEGORY(lcQRandomAccessIORing, "qt.core.qrandomaccessasyncfile.ioring",
+ QtCriticalMsg);
+
+QRandomAccessAsyncFilePrivate::QRandomAccessAsyncFilePrivate() = default;
+
+QRandomAccessAsyncFilePrivate::~QRandomAccessAsyncFilePrivate() = default;
+
+void QRandomAccessAsyncFilePrivate::init()
+{
+ m_ioring = QIORing::sharedInstance();
+ if (!m_ioring)
+ qCCritical(lcQRandomAccessIORing, "QRandomAccessAsyncFile: ioring failed to initialize");
+}
+
+QIORing::RequestHandle QRandomAccessAsyncFilePrivate::cancel(QIORing::RequestHandle handle)
+{
+ if (handle) {
+ QIORingRequest<QIORing::Operation::Cancel> cancelRequest;
+ cancelRequest.handle = handle;
+ return m_ioring->queueRequest(std::move(cancelRequest));
+ }
+ return nullptr;
+}
+
+void QRandomAccessAsyncFilePrivate::cancelAndWait(QIOOperation *op)
+{
+ auto *opHandle = m_opHandleMap.value(op);
+ if (auto *handle = cancel(opHandle)) {
+ m_ioring->waitForRequest(handle);
+ m_ioring->waitForRequest(opHandle);
+ }
+}
+
+void QRandomAccessAsyncFilePrivate::queueCompletion(QIOOperationPrivate *priv, QIOOperation::Error error)
+{
+ // Remove the handle now in case the user cancels or deletes the io-operation
+ // before operationComplete is called - the null-handle will protect from
+ // nasty issues that may occur when trying to cancel an operation that's no
+ // longer in the queue:
+ m_opHandleMap.remove(priv->q_func());
+ // @todo: Look into making it emit only if synchronously completed
+ QMetaObject::invokeMethod(priv->q_ptr, [priv, error](){
+ priv->operationComplete(error);
+ }, Qt::QueuedConnection);
+}
+
+QIOOperation *QRandomAccessAsyncFilePrivate::open(const QString &path, QIODeviceBase::OpenMode mode)
+{
+ auto *dataStorage = new QtPrivate::QIOOperationDataStorage();
+
+ auto *priv = new QIOOperationPrivate(dataStorage);
+ priv->type = QIOOperation::Type::Open;
+
+ auto *op = new QIOOperation(*priv, q_ptr);
+ if (m_fileState != FileState::Closed) {
+ queueCompletion(priv, QIOOperation::Error::Open);
+ return op;
+ }
+ m_operations.append(op);
+ m_fileState = FileState::OpenPending;
+
+ QIORingRequest<QIORing::Operation::Open> openOperation;
+ openOperation.path = QtPrivate::toFilesystemPath(path);
+ openOperation.flags = mode;
+ openOperation.setCallback([this, op,
+ priv](const QIORingRequest<QIORing::Operation::Open> &request) {
+ if (const auto *err = std::get_if<QFileDevice::FileError>(&request.result)) {
+ if (m_fileState != FileState::Opened) {
+ // We assume there was only one pending open() in flight.
+ m_fd = -1;
+ m_fileState = FileState::Closed;
+ }
+ if (priv->error == QIOOperation::Error::Aborted || *err == QFileDevice::AbortError)
+ queueCompletion(priv, QIOOperation::Error::Aborted);
+ else
+ queueCompletion(priv, QIOOperation::Error::Open);
+ } else if (const auto *result = std::get_if<QIORingResult<QIORing::Operation::Open>>(
+ &request.result)) {
+ if (m_fileState == FileState::OpenPending) {
+ m_fileState = FileState::Opened;
+ m_fd = result->fd;
+ queueCompletion(priv, QIOOperation::Error::None);
+ } else { // Something went wrong, we did not expect a callback:
+ // So we close the new handle:
+ QIORingRequest<QIORing::Operation::Close> closeRequest;
+ closeRequest.fd = result->fd;
+ QIORing::RequestHandle handle = m_ioring->queueRequest(std::move(closeRequest));
+ // Since the user issued multiple open() calls they get to wait for the close() to
+ // finish:
+ m_ioring->waitForRequest(handle);
+ queueCompletion(priv, QIOOperation::Error::Open);
+ }
+ }
+ m_operations.removeOne(op);
+ });
+ m_opHandleMap.insert(priv->q_func(), m_ioring->queueRequest(std::move(openOperation)));
+
+ return op;
+}
+
+void QRandomAccessAsyncFilePrivate::close()
+{
+ // all the operations should be aborted
+ const auto ops = std::exchange(m_operations, {});
+ QList<QIORing::RequestHandle> tasksToAwait;
+ // Request to cancel all of the in-flight operations:
+ for (const auto &op : ops) {
+ if (op) {
+ op->d_func()->error = QIOOperation::Error::Aborted;
+ if (auto *opHandle = m_opHandleMap.value(op)) {
+ tasksToAwait.append(cancel(opHandle));
+ tasksToAwait.append(opHandle);
+ }
+ }
+ }
+
+ QIORingRequest<QIORing::Operation::Close> closeRequest;
+ closeRequest.fd = m_fd;
+ tasksToAwait.append(m_ioring->queueRequest(std::move(closeRequest)));
+
+ // Wait for completion:
+ for (const QIORing::RequestHandle &handle : tasksToAwait)
+ m_ioring->waitForRequest(handle);
+ m_fileState = FileState::Closed;
+ m_fd = -1;
+}
+
+qint64 QRandomAccessAsyncFilePrivate::size() const
+{
+ QIORingRequest<QIORing::Operation::Stat> statRequest;
+ statRequest.fd = m_fd;
+ qint64 finalSize = 0;
+ statRequest.setCallback([&finalSize](const QIORingRequest<QIORing::Operation::Stat> &request) {
+ if (const auto *err = std::get_if<QFileDevice::FileError>(&request.result)) {
+ Q_UNUSED(err);
+ finalSize = -1;
+ } else if (const auto *res = std::get_if<QIORingResult<QIORing::Operation::Stat>>(&request.result)) {
+ finalSize = q26::saturate_cast<qint64>(res->size);
+ }
+ });
+ auto *handle = m_ioring->queueRequest(std::move(statRequest));
+ m_ioring->waitForRequest(handle);
+
+ return finalSize;
+}
+
+QIOOperation *QRandomAccessAsyncFilePrivate::flush()
+{
+ auto *dataStorage = new QtPrivate::QIOOperationDataStorage();
+
+ auto *priv = new QIOOperationPrivate(dataStorage);
+ priv->type = QIOOperation::Type::Flush;
+
+ auto *op = new QIOOperation(*priv, q_ptr);
+ m_operations.append(op);
+
+ QIORingRequest<QIORing::Operation::Flush> flushRequest;
+ flushRequest.fd = m_fd;
+ flushRequest.setCallback([this, op](const QIORingRequest<QIORing::Operation::Flush> &request) {
+ auto *priv = QIOOperationPrivate::get(op);
+ if (const auto *err = std::get_if<QFileDevice::FileError>(&request.result)) {
+ if (priv->error == QIOOperation::Error::Aborted || *err == QFileDevice::AbortError)
+ queueCompletion(priv, QIOOperation::Error::Aborted);
+ else if (*err == QFileDevice::OpenError)
+ queueCompletion(priv, QIOOperation::Error::FileNotOpen);
+ else
+ queueCompletion(priv, QIOOperation::Error::Flush);
+ } else if (std::get_if<QIORingResult<QIORing::Operation::Flush>>(&request.result)) {
+ queueCompletion(priv, QIOOperation::Error::None);
+ }
+ m_operations.removeOne(op);
+ });
+ m_opHandleMap.insert(priv->q_func(), m_ioring->queueRequest(std::move(flushRequest)));
+
+ return op;
+}
+
+void QRandomAccessAsyncFilePrivate::startReadIntoSingle(QIOOperation *op,
+ const QSpan<std::byte> &to)
+{
+ QIORingRequest<QIORing::Operation::Read> readRequest;
+ readRequest.fd = m_fd;
+ auto *priv = QIOOperationPrivate::get(op);
+ if (priv->offset < 0) { // The QIORing offset is unsigned, so error out now
+ queueCompletion(priv, QIOOperation::Error::IncorrectOffset);
+ m_operations.removeOne(op);
+ return;
+ }
+ readRequest.offset = priv->offset;
+ readRequest.destination = to;
+ readRequest.setCallback([this, op](const QIORingRequest<QIORing::Operation::Read> &request) {
+ auto *priv = QIOOperationPrivate::get(op);
+ if (const auto *err = std::get_if<QFileDevice::FileError>(&request.result)) {
+ if (priv->error == QIOOperation::Error::Aborted || *err == QFileDevice::AbortError)
+ queueCompletion(priv, QIOOperation::Error::Aborted);
+ else if (*err == QFileDevice::OpenError)
+ queueCompletion(priv, QIOOperation::Error::FileNotOpen);
+ else if (*err == QFileDevice::PositionError)
+ queueCompletion(priv, QIOOperation::Error::IncorrectOffset);
+ else
+ queueCompletion(priv, QIOOperation::Error::Read);
+ } else if (const auto *result = std::get_if<QIORingResult<QIORing::Operation::Read>>(
+ &request.result)) {
+ priv->appendBytesProcessed(result->bytesRead);
+ if (priv->dataStorage->containsReadSpans())
+ priv->dataStorage->getReadSpans().first().slice(0, result->bytesRead);
+ else
+ priv->dataStorage->getByteArray().slice(0, result->bytesRead);
+
+ queueCompletion(priv, QIOOperation::Error::None);
+ }
+ m_operations.removeOne(op);
+ });
+ m_opHandleMap.insert(priv->q_func(), m_ioring->queueRequest(std::move(readRequest)));
+}
+
+QIOReadOperation *QRandomAccessAsyncFilePrivate::read(qint64 offset, qint64 maxSize)
+{
+ QByteArray array;
+ array.resizeForOverwrite(maxSize);
+ auto *dataStorage = new QtPrivate::QIOOperationDataStorage(std::move(array));
+
+ auto *priv = new QIOOperationPrivate(dataStorage);
+ priv->offset = offset;
+ priv->type = QIOOperation::Type::Read;
+
+ auto *op = new QIOReadOperation(*priv, q_ptr);
+ m_operations.append(op);
+
+ startReadIntoSingle(op, as_writable_bytes(QSpan(dataStorage->getByteArray())));
+
+ return op;
+}
+
+QIOWriteOperation *QRandomAccessAsyncFilePrivate::write(qint64 offset, const QByteArray &data)
+{
+ return write(offset, QByteArray(data));
+}
+
+void QRandomAccessAsyncFilePrivate::startWriteFromSingle(QIOOperation *op,
+ const QSpan<const std::byte> &from)
+{
+ QIORingRequest<QIORing::Operation::Write> writeRequest;
+ writeRequest.fd = m_fd;
+ auto *priv = QIOOperationPrivate::get(op);
+ if (priv->offset < 0) { // The QIORing offset is unsigned, so error out now
+ queueCompletion(priv, QIOOperation::Error::IncorrectOffset);
+ m_operations.removeOne(op);
+ return;
+ }
+ writeRequest.offset = priv->offset;
+ writeRequest.source = from;
+ writeRequest.setCallback([this, op](const QIORingRequest<QIORing::Operation::Write> &request) {
+ auto *priv = QIOOperationPrivate::get(op);
+ if (const auto *err = std::get_if<QFileDevice::FileError>(&request.result)) {
+ if (priv->error == QIOOperation::Error::Aborted || *err == QFileDevice::AbortError)
+ queueCompletion(priv, QIOOperation::Error::Aborted);
+ else if (*err == QFileDevice::OpenError)
+ queueCompletion(priv, QIOOperation::Error::FileNotOpen);
+ else if (*err == QFileDevice::PositionError)
+ queueCompletion(priv, QIOOperation::Error::IncorrectOffset);
+ else
+ queueCompletion(priv, QIOOperation::Error::Write);
+ } else if (const auto *result = std::get_if<QIORingResult<QIORing::Operation::Write>>(
+ &request.result)) {
+ priv->appendBytesProcessed(result->bytesWritten);
+ queueCompletion(priv, QIOOperation::Error::None);
+ }
+ m_operations.removeOne(op);
+ });
+ m_opHandleMap.insert(priv->q_func(), m_ioring->queueRequest(std::move(writeRequest)));
+}
+
+QIOWriteOperation *QRandomAccessAsyncFilePrivate::write(qint64 offset, QByteArray &&data)
+{
+ auto *dataStorage = new QtPrivate::QIOOperationDataStorage(std::move(data));
+
+ auto *priv = new QIOOperationPrivate(dataStorage);
+ priv->offset = offset;
+ priv->type = QIOOperation::Type::Write;
+
+ auto *op = new QIOWriteOperation(*priv, q_ptr);
+ m_operations.append(op);
+
+ startWriteFromSingle(op, as_bytes(QSpan(dataStorage->getByteArray())));
+
+ return op;
+}
+
+QIOVectoredReadOperation *QRandomAccessAsyncFilePrivate::readInto(qint64 offset,
+ QSpan<std::byte> buffer)
+{
+ auto *dataStorage = new QtPrivate::QIOOperationDataStorage(
+ QSpan<const QSpan<std::byte>>{ buffer });
+
+ auto *priv = new QIOOperationPrivate(dataStorage);
+ priv->offset = offset;
+ priv->type = QIOOperation::Type::Read;
+
+ auto *op = new QIOVectoredReadOperation(*priv, q_ptr);
+ m_operations.append(op);
+
+ startReadIntoSingle(op, dataStorage->getReadSpans().first());
+
+ return op;
+}
+
+QIOVectoredWriteOperation *QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset,
+ QSpan<const std::byte> buffer)
+{
+ auto *dataStorage = new QtPrivate::QIOOperationDataStorage(
+ QSpan<const QSpan<const std::byte>>{ buffer });
+
+ auto *priv = new QIOOperationPrivate(dataStorage);
+ priv->offset = offset;
+ priv->type = QIOOperation::Type::Write;
+
+ auto *op = new QIOVectoredWriteOperation(*priv, q_ptr);
+ m_operations.append(op);
+
+ startWriteFromSingle(op, dataStorage->getWriteSpans().first());
+
+ return op;
+}
+
+QIOVectoredReadOperation *
+QRandomAccessAsyncFilePrivate::readInto(qint64 offset, QSpan<const QSpan<std::byte>> buffers)
+{
+ if (!QIORing::supportsOperation(QtPrivate::Operation::VectoredRead))
+ return nullptr;
+ auto *dataStorage = new QtPrivate::QIOOperationDataStorage(buffers);
+
+ auto *priv = new QIOOperationPrivate(dataStorage);
+ priv->offset = offset;
+ priv->type = QIOOperation::Type::Read;
+
+ auto *op = new QIOVectoredReadOperation(*priv, q_ptr);
+ if (priv->offset < 0) { // The QIORing offset is unsigned, so error out now
+ queueCompletion(priv, QIOOperation::Error::IncorrectOffset);
+ return op;
+ }
+ m_operations.append(op);
+
+ QIORingRequest<QIORing::Operation::VectoredRead> readRequest;
+ readRequest.fd = m_fd;
+ readRequest.offset = priv->offset;
+ readRequest.destinations = dataStorage->getReadSpans();
+ readRequest.setCallback([this,
+ op](const QIORingRequest<QIORing::Operation::VectoredRead> &request) {
+ auto *priv = QIOOperationPrivate::get(op);
+ if (const auto *err = std::get_if<QFileDevice::FileError>(&request.result)) {
+ if (priv->error == QIOOperation::Error::Aborted || *err == QFileDevice::AbortError)
+ queueCompletion(priv, QIOOperation::Error::Aborted);
+ else
+ queueCompletion(priv, QIOOperation::Error::Read);
+ } else if (const auto
+ *result = std::get_if<QIORingResult<QIORing::Operation::VectoredRead>>(
+ &request.result)) {
+ priv->appendBytesProcessed(result->bytesRead);
+ qint64 processed = result->bytesRead;
+ for (auto &span : priv->dataStorage->getReadSpans()) {
+ if (span.size() < processed) {
+ processed -= span.size();
+ } else { // span.size >= processed
+ span.slice(0, processed);
+ processed = 0;
+ }
+ }
+ queueCompletion(priv, QIOOperation::Error::None);
+ }
+ m_operations.removeOne(op);
+ });
+ m_opHandleMap.insert(priv->q_func(), m_ioring->queueRequest(std::move(readRequest)));
+
+ return op;
+}
+
+QIOVectoredWriteOperation *
+QRandomAccessAsyncFilePrivate::writeFrom(qint64 offset, QSpan<const QSpan<const std::byte>> buffers)
+{
+ if (!QIORing::supportsOperation(QtPrivate::Operation::VectoredWrite))
+ return nullptr;
+ auto *dataStorage = new QtPrivate::QIOOperationDataStorage(buffers);
+
+ auto *priv = new QIOOperationPrivate(dataStorage);
+ priv->offset = offset;
+ priv->type = QIOOperation::Type::Write;
+
+ auto *op = new QIOVectoredWriteOperation(*priv, q_ptr);
+ if (priv->offset < 0) { // The QIORing offset is unsigned, so error out now
+ queueCompletion(priv, QIOOperation::Error::IncorrectOffset);
+ return op;
+ }
+ m_operations.append(op);
+
+ QIORingRequest<QIORing::Operation::VectoredWrite> writeRequest;
+ writeRequest.fd = m_fd;
+ writeRequest.offset = priv->offset;
+ writeRequest.sources = dataStorage->getWriteSpans();
+ writeRequest.setCallback(
+ [this, op](const QIORingRequest<QIORing::Operation::VectoredWrite> &request) {
+ auto *priv = QIOOperationPrivate::get(op);
+ if (const auto *err = std::get_if<QFileDevice::FileError>(&request.result)) {
+ if (priv->error == QIOOperation::Error::Aborted || *err == QFileDevice::AbortError)
+ queueCompletion(priv, QIOOperation::Error::Aborted);
+ else
+ queueCompletion(priv, QIOOperation::Error::Write);
+ } else if (const auto *result = std::get_if<
+ QIORingResult<QIORing::Operation::VectoredWrite>>(
+ &request.result)) {
+ priv->appendBytesProcessed(result->bytesWritten);
+ queueCompletion(priv, QIOOperation::Error::None);
+ }
+ m_operations.removeOne(op);
+ });
+ m_opHandleMap.insert(priv->q_func(), m_ioring->queueRequest(std::move(writeRequest)));
+
+ return op;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index a11f7913dc7..e69b9aebabb 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -301,21 +301,27 @@ public:
explicit QList(qsizetype size)
: d(size)
{
- if (size)
+ if (size) {
+ Q_CHECK_PTR(d.data());
d->appendInitialize(size);
+ }
}
QList(qsizetype size, parameter_type t)
: d(size)
{
- if (size)
+ if (size) {
+ Q_CHECK_PTR(d.data());
d->copyAppend(size, t);
+ }
}
inline QList(std::initializer_list<T> args)
: d(qsizetype(args.size()))
{
- if (args.size())
+ if (args.size()) {
+ Q_CHECK_PTR(d.data());
d->copyAppend(args.begin(), args.end());
+ }
}
QList<T> &operator=(std::initializer_list<T> args)
@@ -332,6 +338,7 @@ public:
const auto distance = std::distance(i1, i2);
if (distance) {
d = DataPointer(qsizetype(distance));
+ Q_CHECK_PTR(d.data());
// appendIteratorRange can deal with contiguous iterators on its own,
// this is an optimization for C++17 code.
if constexpr (std::is_same_v<std::decay_t<InputIterator>, iterator> ||
@@ -352,8 +359,10 @@ public:
QList(qsizetype size, Qt::Initialization)
: d(size)
{
- if (size)
+ if (size) {
+ Q_CHECK_PTR(d.data());
d->appendUninitialized(size);
+ }
}
// compiler-generated special member functions are fine!
@@ -823,7 +832,10 @@ void QList<T>::reserve(qsizetype asize)
}
}
- DataPointer detached(qMax(asize, size()));
+ qsizetype newSize = qMax(asize, size());
+ DataPointer detached(newSize);
+ if (newSize)
+ Q_CHECK_PTR(detached.data());
detached->copyAppend(d->begin(), d->end());
if (detached.d_ptr())
detached->setFlag(Data::CapacityReserved);
@@ -839,6 +851,7 @@ inline void QList<T>::squeeze()
// must allocate memory
DataPointer detached(size());
if (size()) {
+ Q_CHECK_PTR(detached.data());
if (d.needsDetach())
detached->copyAppend(d.data(), d.data() + d.size);
else
diff --git a/src/plugins/platforms/wasm/qwasmevent.cpp b/src/plugins/platforms/wasm/qwasmevent.cpp
index e6d5a20a24d..676d9c8e155 100644
--- a/src/plugins/platforms/wasm/qwasmevent.cpp
+++ b/src/plugins/platforms/wasm/qwasmevent.cpp
@@ -112,7 +112,7 @@ bool Event::isTargetedForQtElement() const
return topElementClassName.startsWith("qt-"); // .e.g. qt-window-canvas
}
-KeyEvent::KeyEvent(EventType type, emscripten::val event, QWasmDeadKeySupport *deadKeySupport) : Event(type, event)
+KeyEvent::KeyEvent(EventType type, emscripten::val event) : Event(type, event)
{
const auto code = event["code"].as<std::string>();
const auto webKey = event["key"].as<std::string>();
@@ -137,8 +137,6 @@ KeyEvent::KeyEvent(EventType type, emscripten::val event, QWasmDeadKeySupport *d
if (key == Qt::Key_Tab)
text = "\t";
-
- deadKeySupport->applyDeadKeyTranslations(this);
}
MouseEvent::MouseEvent(EventType type, emscripten::val event) : Event(type, event)
diff --git a/src/plugins/platforms/wasm/qwasmevent.h b/src/plugins/platforms/wasm/qwasmevent.h
index 9b6f11fd5da..ef1b6129e3c 100644
--- a/src/plugins/platforms/wasm/qwasmevent.h
+++ b/src/plugins/platforms/wasm/qwasmevent.h
@@ -17,8 +17,6 @@
#include <emscripten/val.h>
QT_BEGIN_NAMESPACE
-
-class QWasmDeadKeySupport;
class QWindow;
enum class EventType {
@@ -65,7 +63,7 @@ struct Event
struct KeyEvent : public Event
{
- KeyEvent(EventType type, emscripten::val webEvent, QWasmDeadKeySupport *deadKeySupport);
+ KeyEvent(EventType type, emscripten::val webEvent);
Qt::Key key;
QFlags<Qt::KeyboardModifier> modifiers;
diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp
index b56c57974d1..7417f316169 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.cpp
+++ b/src/plugins/platforms/wasm/qwasmintegration.cpp
@@ -200,7 +200,7 @@ QWasmWindow *QWasmIntegration::createWindow(QWindow *window, WId nativeHandle) c
{
auto *wasmScreen = QWasmScreen::get(window->screen());
QWasmCompositor *compositor = wasmScreen->compositor();
- return new QWasmWindow(window, wasmScreen->deadKeySupport(), compositor,
+ return new QWasmWindow(window, compositor,
m_backingStores.value(window), nativeHandle);
}
diff --git a/src/plugins/platforms/wasm/qwasmkeytranslator.cpp b/src/plugins/platforms/wasm/qwasmkeytranslator.cpp
index 8f5240d2d0c..90a4ee807fb 100644
--- a/src/plugins/platforms/wasm/qwasmkeytranslator.cpp
+++ b/src/plugins/platforms/wasm/qwasmkeytranslator.cpp
@@ -250,46 +250,4 @@ std::optional<Qt::Key> QWasmKeyTranslator::mapWebKeyTextToQtKey(const char *toFi
: std::optional<Qt::Key>();
}
-QWasmDeadKeySupport::QWasmDeadKeySupport() = default;
-
-QWasmDeadKeySupport::~QWasmDeadKeySupport() = default;
-
-void QWasmDeadKeySupport::applyDeadKeyTranslations(KeyEvent *event)
-{
- if (event->deadKey) {
- m_activeDeadKey = event->key;
- } else if (m_activeDeadKey != Qt::Key_unknown
- && (((m_keyModifiedByDeadKeyOnPress == Qt::Key_unknown
- && event->type == EventType::KeyDown))
- || (m_keyModifiedByDeadKeyOnPress == event->key
- && event->type == EventType::KeyUp))) {
- const Qt::Key baseKey = event->key;
- const Qt::Key translatedKey = translateBaseKeyUsingDeadKey(baseKey, m_activeDeadKey);
- if (translatedKey != Qt::Key_unknown) {
- event->key = translatedKey;
-
- auto foundText = event->modifiers.testFlag(Qt::ShiftModifier)
- ? findKeyTextByKeyId(DiacriticalCharsKeyToTextUppercase, event->key)
- : findKeyTextByKeyId(DiacriticalCharsKeyToTextLowercase, event->key);
- Q_ASSERT(foundText.has_value());
- event->text = foundText->size() == 1 ? *foundText : QString();
- }
-
- if (!event->text.isEmpty()) {
- if (event->type == EventType::KeyDown) {
- // Assume the first keypress with an active dead key is treated as modified,
- // regardless of whether it has actually been modified or not. Take into account
- // only events that produce actual key text.
- if (!event->text.isEmpty())
- m_keyModifiedByDeadKeyOnPress = baseKey;
- } else {
- Q_ASSERT(event->type == EventType::KeyUp);
- Q_ASSERT(m_keyModifiedByDeadKeyOnPress == baseKey);
- m_keyModifiedByDeadKeyOnPress = Qt::Key_unknown;
- m_activeDeadKey = Qt::Key_unknown;
- }
- }
- }
-}
-
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmkeytranslator.h b/src/plugins/platforms/wasm/qwasmkeytranslator.h
index 11a89e61930..3e18bcb8802 100644
--- a/src/plugins/platforms/wasm/qwasmkeytranslator.h
+++ b/src/plugins/platforms/wasm/qwasmkeytranslator.h
@@ -17,18 +17,5 @@ namespace QWasmKeyTranslator {
std::optional<Qt::Key> mapWebKeyTextToQtKey(const char *toFind);
}
-class QWasmDeadKeySupport
-{
-public:
- explicit QWasmDeadKeySupport();
- ~QWasmDeadKeySupport();
-
- void applyDeadKeyTranslations(KeyEvent *event);
-
-private:
- Qt::Key m_activeDeadKey = Qt::Key_unknown;
- Qt::Key m_keyModifiedByDeadKeyOnPress = Qt::Key_unknown;
-};
-
QT_END_NAMESPACE
#endif // QWASMKEYTRANSLATOR_H
diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp
index a2c8306b13b..bbfc71edc54 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.cpp
+++ b/src/plugins/platforms/wasm/qwasmscreen.cpp
@@ -30,8 +30,7 @@ QWasmScreen::QWasmScreen(const emscripten::val &containerOrCanvas)
: m_container(containerOrCanvas),
m_intermediateContainer(emscripten::val::undefined()),
m_shadowContainer(emscripten::val::undefined()),
- m_compositor(new QWasmCompositor(this)),
- m_deadKeySupport(std::make_unique<QWasmDeadKeySupport>())
+ m_compositor(new QWasmCompositor(this))
{
auto document = m_container["ownerDocument"];
diff --git a/src/plugins/platforms/wasm/qwasmscreen.h b/src/plugins/platforms/wasm/qwasmscreen.h
index a19818af2ff..6ddd4c736d0 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.h
+++ b/src/plugins/platforms/wasm/qwasmscreen.h
@@ -22,7 +22,6 @@ class QPlatformOpenGLContext;
class QWasmWindow;
class QWasmBackingStore;
class QWasmCompositor;
-class QWasmDeadKeySupport;
class QOpenGLContext;
class QWasmScreen : public QObject, public QPlatformScreen, public QWasmWindowTreeNode<>
@@ -41,7 +40,6 @@ public:
QPointingDevice *tabletDevice() { return m_tabletDevice.get(); }
QWasmCompositor *compositor();
- QWasmDeadKeySupport *deadKeySupport() { return m_deadKeySupport.get(); }
QList<QWasmWindow *> allWindows() const;
@@ -83,7 +81,6 @@ private:
std::unique_ptr<QWasmCompositor> m_compositor;
std::unique_ptr<QPointingDevice> m_touchDevice;
std::unique_ptr<QPointingDevice> m_tabletDevice;
- std::unique_ptr<QWasmDeadKeySupport> m_deadKeySupport;
QRect m_geometry = QRect(0, 0, 100, 100);
int m_depth = 32;
QImage::Format m_format = QImage::Format_RGB32;
diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp
index d318c977a90..264471794bd 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.cpp
+++ b/src/plugins/platforms/wasm/qwasmwindow.cpp
@@ -40,13 +40,12 @@ QT_BEGIN_NAMESPACE
Q_GUI_EXPORT int qt_defaultDpiX();
-QWasmWindow::QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport,
+QWasmWindow::QWasmWindow(QWindow *w,
QWasmCompositor *compositor, QWasmBackingStore *backingStore,
WId nativeHandle)
: QPlatformWindow(w),
m_compositor(compositor),
m_backingStore(backingStore),
- m_deadKeySupport(deadKeySupport),
m_document(dom::document()),
m_decoratedWindow(m_document.call<emscripten::val>("createElement", emscripten::val("div"))),
m_window(m_document.call<emscripten::val>("createElement", emscripten::val("div"))),
@@ -216,9 +215,9 @@ void QWasmWindow::registerEventHandlers()
[this](emscripten::val event) { this->handleWheelEvent(event); });
m_keyDownCallback = QWasmEventHandler(m_window, "keydown",
- [this](emscripten::val event) { this->handleKeyEvent(KeyEvent(EventType::KeyDown, event, m_deadKeySupport)); });
+ [this](emscripten::val event) { this->handleKeyEvent(KeyEvent(EventType::KeyDown, event)); });
m_keyUpCallback =QWasmEventHandler(m_window, "keyup",
- [this](emscripten::val event) {this->handleKeyEvent(KeyEvent(EventType::KeyUp, event, m_deadKeySupport)); });
+ [this](emscripten::val event) {this->handleKeyEvent(KeyEvent(EventType::KeyUp, event)); });
m_inputCallback = QWasmEventHandler(m_window, "input",
[this](emscripten::val event){ handleInputEvent(event); });
diff --git a/src/plugins/platforms/wasm/qwasmwindow.h b/src/plugins/platforms/wasm/qwasmwindow.h
index 8e6e5021dcf..87f4d6644c7 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.h
+++ b/src/plugins/platforms/wasm/qwasmwindow.h
@@ -31,7 +31,6 @@ class EventCallback;
struct KeyEvent;
struct PointerEvent;
-class QWasmDeadKeySupport;
struct WheelEvent;
Q_DECLARE_LOGGING_CATEGORY(qLcQpaWasmInputContext)
@@ -41,7 +40,7 @@ class QWasmWindow final : public QPlatformWindow,
public QNativeInterface::Private::QWasmWindow
{
public:
- QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport, QWasmCompositor *compositor,
+ QWasmWindow(QWindow *w, QWasmCompositor *compositor,
QWasmBackingStore *backingStore, WId nativeHandle);
~QWasmWindow() final;
@@ -159,7 +158,6 @@ private:
QWasmCompositor *m_compositor = nullptr;
QWasmBackingStore *m_backingStore = nullptr;
- QWasmDeadKeySupport *m_deadKeySupport;
QRect m_normalGeometry {0, 0, 0 ,0};
emscripten::val m_document;
diff --git a/src/plugins/platforms/wayland/CMakeLists.txt b/src/plugins/platforms/wayland/CMakeLists.txt
index d9415f0a011..9a5db541a42 100644
--- a/src/plugins/platforms/wayland/CMakeLists.txt
+++ b/src/plugins/platforms/wayland/CMakeLists.txt
@@ -78,7 +78,6 @@ qt_internal_add_module(WaylandClient
qwaylandviewport.cpp qwaylandviewport_p.h
qwaylandwindow.cpp qwaylandwindow_p.h
qwaylandwindowmanagerintegration.cpp qwaylandwindowmanagerintegration_p.h
- qwaylandeventdispatcher.cpp qwaylandeventdispatcher_p.h
shellintegration/qwaylandclientshellapi_p.h
shellintegration/qwaylandshellintegration_p.h shellintegration/qwaylandshellintegration.cpp
shellintegration/qwaylandshellintegrationfactory.cpp shellintegration/qwaylandshellintegrationfactory_p.h
diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp
index 1fc5e5c30a0..f20b0c5a7dc 100644
--- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp
+++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp
@@ -32,7 +32,6 @@
#include "qwaylandtextinputv3_p.h"
#include "qwaylandinputcontext_p.h"
#include "qwaylandinputmethodcontext_p.h"
-#include "qwaylandeventdispatcher_p.h"
#include "qwaylandwindowmanagerintegration_p.h"
#include "qwaylandshellintegration_p.h"
@@ -525,7 +524,6 @@ void QWaylandDisplay::reconnect()
void QWaylandDisplay::flushRequests()
{
m_eventThread->readAndDispatchEvents();
- QWindowSystemInterface::flushWindowSystemEvents(QWaylandEventDispatcher::eventDispatcher->flags());
}
// We have to wait until we have an eventDispatcher before creating the eventThread,
diff --git a/src/plugins/platforms/wayland/qwaylandeventdispatcher.cpp b/src/plugins/platforms/wayland/qwaylandeventdispatcher.cpp
deleted file mode 100644
index f5f14f29824..00000000000
--- a/src/plugins/platforms/wayland/qwaylandeventdispatcher.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) 2025 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-
-#include "qwaylandeventdispatcher_p.h"
-
-QT_BEGIN_NAMESPACE
-
-namespace QtWaylandClient {
-
-QWaylandEventDispatcher *QWaylandEventDispatcher::eventDispatcher = nullptr;
-
-QAbstractEventDispatcher *QWaylandEventDispatcher::createEventDispatcher()
-{
-#if !defined(QT_NO_GLIB) && !defined(Q_OS_WIN)
- if (qEnvironmentVariableIsEmpty("QT_NO_GLIB") && QEventDispatcherGlib::versionSupported())
- return new QWaylandGlibEventDispatcher();
-#endif
- return new QWaylandUnixEventDispatcher();
-}
-
-QWaylandEventDispatcher::QWaylandEventDispatcher()
-{
- Q_ASSERT(!eventDispatcher);
- eventDispatcher = this;
-}
-
-QWaylandEventDispatcher::~QWaylandEventDispatcher()
-{
- Q_ASSERT(eventDispatcher == this);
- eventDispatcher = nullptr;
-}
-
-bool QWaylandUnixEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
-{
- m_flags = flags;
- return QUnixEventDispatcherQPA::processEvents(flags);
-}
-
-QEventLoop::ProcessEventsFlags QWaylandUnixEventDispatcher::flags() const
-{
- return m_flags;
-}
-
-#if !defined(QT_NO_GLIB) && !defined(Q_OS_WIN)
-
-QEventLoop::ProcessEventsFlags QWaylandGlibEventDispatcher::flags() const
-{
- return m_flags;
-}
-
-#endif
-
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/qwaylandeventdispatcher_p.h b/src/plugins/platforms/wayland/qwaylandeventdispatcher_p.h
deleted file mode 100644
index a0426d44a21..00000000000
--- a/src/plugins/platforms/wayland/qwaylandeventdispatcher_p.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (C) 2025 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-
-#ifndef QWAYLANDEVENTDISPATCHER_P_H
-#define QWAYLANDEVENTDISPATCHER_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtGui/private/qunixeventdispatcher_qpa_p.h>
-#if !defined(QT_NO_GLIB) && !defined(Q_OS_WIN)
-#include <QtGui/private/qeventdispatcher_glib_p.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-namespace QtWaylandClient {
-
-class QWaylandEventDispatcher
-{
-public:
- static QAbstractEventDispatcher *createEventDispatcher();
-
- static QWaylandEventDispatcher *eventDispatcher;
-
-public:
- QWaylandEventDispatcher();
- virtual ~QWaylandEventDispatcher();
-
- virtual QEventLoop::ProcessEventsFlags flags() const = 0;
-};
-
-class QWaylandUnixEventDispatcher : public QUnixEventDispatcherQPA, QWaylandEventDispatcher
-{
- Q_OBJECT
-public:
- bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
-
- QEventLoop::ProcessEventsFlags flags() const override;
-
-private:
- QEventLoop::ProcessEventsFlags m_flags;
-};
-
-#if !defined(QT_NO_GLIB) && !defined(Q_OS_WIN)
-
-class QWaylandGlibEventDispatcher : public QPAEventDispatcherGlib, QWaylandEventDispatcher
-{
- Q_OBJECT
-public:
- QEventLoop::ProcessEventsFlags flags() const override;
-};
-
-#endif
-
-}
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp
index b16a97d4c77..28a0cca9e55 100644
--- a/src/plugins/platforms/wayland/qwaylandintegration.cpp
+++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp
@@ -18,7 +18,6 @@
#include "qwaylandplatformservices_p.h"
#include "qwaylandscreen_p.h"
#include "qwaylandcursor_p.h"
-#include "qwaylandeventdispatcher_p.h"
#if defined(Q_OS_MACOS)
# include <QtGui/private/qcoretextfontdatabase_p.h>
@@ -26,6 +25,7 @@
#else
# include <QtGui/private/qgenericunixfontdatabase_p.h>
#endif
+#include <QtGui/private/qgenericunixeventdispatcher_p.h>
#include <QtGui/private/qgenericunixtheme_p.h>
#include <QtGui/private/qguiapplication_p.h>
@@ -182,7 +182,7 @@ QPlatformBackingStore *QWaylandIntegration::createPlatformBackingStore(QWindow *
QAbstractEventDispatcher *QWaylandIntegration::createEventDispatcher() const
{
- return QWaylandEventDispatcher::createEventDispatcher();
+ return createUnixEventDispatcher();
}
QPlatformNativeInterface *QWaylandIntegration::createPlatformNativeInterface()
diff --git a/tests/auto/corelib/io/qrandomaccessasyncfile/tst_qrandomaccessasyncfile.cpp b/tests/auto/corelib/io/qrandomaccessasyncfile/tst_qrandomaccessasyncfile.cpp
index 6dceb583469..bcc30f98700 100644
--- a/tests/auto/corelib/io/qrandomaccessasyncfile/tst_qrandomaccessasyncfile.cpp
+++ b/tests/auto/corelib/io/qrandomaccessasyncfile/tst_qrandomaccessasyncfile.cpp
@@ -78,8 +78,9 @@ void tst_QRandomAccessAsyncFile::initTestCase()
QVERIFY(m_file.open());
QByteArray data(FileSize, Qt::Uninitialized);
+ auto *ptr = data.data();
for (qsizetype i = 0; i < FileSize; ++i)
- data[i] = char(i % 256);
+ ptr[i] = char(i % 256);
qint64 written = m_file.write(data);
QCOMPARE_EQ(written, FileSize);
@@ -88,7 +89,13 @@ void tst_QRandomAccessAsyncFile::initTestCase()
void tst_QRandomAccessAsyncFile::cleanupTestCase()
{
m_file.close();
- QVERIFY(m_file.remove());
+ using namespace std::chrono_literals;
+ QDeadlineTimer dt(10s);
+ // Loop a little bit in case there is an access race on Windows:
+ bool success = false;
+ while (!(success = m_file.remove()) && !dt.hasExpired())
+ QThread::msleep(100);
+ QVERIFY2(success, qPrintable(m_file.errorString()));
}
void tst_QRandomAccessAsyncFile::size()
@@ -586,13 +593,16 @@ void tst_QRandomAccessAsyncFile::fileClosedInProgress()
}
file.close();
- auto isAbortedOrComplete = [](QIOOperation *op) {
- return op->error() == QIOOperation::Error::Aborted
- || op->error() == QIOOperation::Error::None;
+ auto isAbortedOrCompleteOrFailedToOpen = [](QIOOperation *op) {
+ return op->error() == QIOOperation::Error::Aborted // Aborted
+ || op->error() == QIOOperation::Error::Open // Failed, because other op is in progress
+ || op->error() == QIOOperation::Error::None; // Completed
};
for (auto op : operations) {
QTRY_VERIFY(op->isFinished());
- QVERIFY(isAbortedOrComplete(op));
+ QVERIFY2(isAbortedOrCompleteOrFailedToOpen(op),
+ qPrintable("Expected Aborted, Open or None, got %1"_L1.arg(
+ QDebug::toString(op->error()))));
}
}
diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp
index b91665f55da..a93079b33de 100644
--- a/tests/auto/corelib/tools/qlist/tst_qlist.cpp
+++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp
@@ -301,6 +301,7 @@ private slots:
void constructors_emptyReserveZero() const;
void constructors_emptyReserve() const;
void constructors_reserveAndInitialize() const;
+ void constructorsThrowOnSillySize() const;
void copyConstructorInt() const { copyConstructor<int>(); }
void copyConstructorMovable() const { copyConstructor<Movable>(); }
void copyConstructorNoexceptMovable() const { copyConstructor<NoexceptMovable>(); }
@@ -704,6 +705,38 @@ void tst_QList::constructors_reserveAndInitialize() const
QCOMPARE(meaningoflife.i, 'n');
}
+void tst_QList::constructorsThrowOnSillySize() const
+{
+#ifdef QT_NO_EXCEPTIONS
+ QSKIP("Compiled without exception support");
+#else
+ // Only testing primitives for this; it should be enough.
+ using T = int;
+ QList<T> dummy(4, 1);
+
+ // This should cause QArrayData::allocate() to overflow and thus return
+ // nullptr.
+ constexpr size_t MaxMemory = std::numeric_limits<size_t>::max() / 4 * 3;
+ static_assert(MaxMemory > size_t(std::numeric_limits<ptrdiff_t>::max()));
+ static_assert(MaxMemory / sizeof(T) < size_t(std::numeric_limits<ptrdiff_t>::max() - 1));
+ constexpr qsizetype NumElements = MaxMemory / sizeof(T);
+
+ QVERIFY_THROWS_EXCEPTION(std::bad_alloc, QList<T> l(NumElements));
+ QVERIFY_THROWS_EXCEPTION(std::bad_alloc, QList<T> l(NumElements, 0));
+ QVERIFY_THROWS_EXCEPTION(std::bad_alloc, QList<T> l(NumElements, Qt::Uninitialized));
+
+ // Since we're here, we might as well test resize() and reserve().
+ QVERIFY_THROWS_EXCEPTION(std::bad_alloc, QList<T> l; l.reserve(NumElements));
+ QVERIFY_THROWS_EXCEPTION(std::bad_alloc, QList<T> l; l.resize(NumElements));
+ QVERIFY_THROWS_EXCEPTION(std::bad_alloc, QList<T> l; l.resize(NumElements, 0));
+ QVERIFY_THROWS_EXCEPTION(std::bad_alloc, QList<T> l; l.resizeForOverwrite(NumElements));
+
+ // The reversed iterators will cause QList to pass a negative size to
+ // QArrayData::allocate(), which is also silly.
+ QVERIFY_THROWS_EXCEPTION(std::bad_alloc, QList<T> l(dummy.constEnd(), dummy.constBegin()));
+#endif
+}
+
template<typename T>
void tst_QList::copyConstructor() const
{
diff --git a/tests/auto/wasm/CMakeLists.txt b/tests/auto/wasm/CMakeLists.txt
index ffa2b9ca98c..6fac23b8d17 100644
--- a/tests/auto/wasm/CMakeLists.txt
+++ b/tests/auto/wasm/CMakeLists.txt
@@ -3,7 +3,6 @@
add_subdirectory(fetchapi)
add_subdirectory(localfileapi)
-add_subdirectory(qwasmkeytranslator)
add_subdirectory(qwasmwindowstack)
add_subdirectory(qwasmwindowtreenode)
add_subdirectory(qwasmpromise)
diff --git a/tests/auto/wasm/qwasmkeytranslator/tst_qwasmkeytranslator.cpp b/tests/auto/wasm/qwasmkeytranslator/tst_qwasmkeytranslator.cpp
deleted file mode 100644
index a5aa6dcd43b..00000000000
--- a/tests/auto/wasm/qwasmkeytranslator/tst_qwasmkeytranslator.cpp
+++ /dev/null
@@ -1,404 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-
-#include "../../../../src/plugins/platforms/wasm/qwasmkeytranslator.h"
-
-#include "../../../../src/plugins/platforms/wasm/qwasmevent.h"
-
-#include <QTest>
-
-#include <emscripten/val.h>
-
-namespace {
-emscripten::val makeDeadKeyJsEvent(QString code, Qt::KeyboardModifiers modifiers)
-{
- auto jsEvent = emscripten::val::object();
- jsEvent.set("code", emscripten::val(code.toStdString()));
- jsEvent.set("key", emscripten::val("Dead"));
- jsEvent.set("shiftKey", emscripten::val(modifiers.testFlag(Qt::ShiftModifier)));
- jsEvent.set("ctrlKey", emscripten::val(false));
- jsEvent.set("altKey", emscripten::val(false));
- jsEvent.set("metaKey", emscripten::val(false));
-
- return jsEvent;
-}
-
-emscripten::val makeKeyJsEvent(QString code, QString key, Qt::KeyboardModifiers modifiers)
-{
- auto jsEvent = emscripten::val::object();
- jsEvent.set("code", emscripten::val(code.toStdString()));
- jsEvent.set("key", emscripten::val(key.toStdString()));
- jsEvent.set("shiftKey", emscripten::val(modifiers.testFlag(Qt::ShiftModifier)));
- jsEvent.set("ctrlKey", emscripten::val(modifiers.testFlag(Qt::ControlModifier)));
- jsEvent.set("altKey", emscripten::val(modifiers.testFlag(Qt::AltModifier)));
- jsEvent.set("metaKey", emscripten::val(modifiers.testFlag(Qt::MetaModifier)));
-
- return jsEvent;
-}
-} // unnamed namespace
-
-class tst_QWasmKeyTranslator : public QObject
-{
- Q_OBJECT
-
-public:
- tst_QWasmKeyTranslator() = default;
-
-private slots:
- void init();
-
- void modifyByDeadKey_data();
- void modifyByDeadKey();
- void deadKeyModifiesOnlyOneKeyPressAndUp();
- void deadKeyIgnoresKeyUpPrecedingKeyDown();
- void onlyKeysProducingTextAreModifiedByDeadKeys();
-};
-
-void tst_QWasmKeyTranslator::init() { }
-
-void tst_QWasmKeyTranslator::modifyByDeadKey_data()
-{
- QTest::addColumn<QString>("deadKeyCode");
- QTest::addColumn<Qt::KeyboardModifiers>("deadKeyModifiers");
- QTest::addColumn<QString>("targetKeyCode");
- QTest::addColumn<QString>("targetKey");
- QTest::addColumn<Qt::Key>("targetQtKey");
- QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
- QTest::addColumn<QString>("expectedModifiedKey");
-
- QTest::newRow("à (Backquote)") << "Backquote" << Qt::KeyboardModifiers() << "KeyA"
- << "a" << Qt::Key_Agrave << Qt::KeyboardModifiers() << "à";
- QTest::newRow("À (Backquote)")
- << "Backquote" << Qt::KeyboardModifiers() << "KeyA"
- << "A" << Qt::Key_Agrave << Qt::KeyboardModifiers(Qt::ShiftModifier) << "À";
- QTest::newRow("à (IntlBackslash)") << "IntlBackslash" << Qt::KeyboardModifiers() << "KeyA"
- << "a" << Qt::Key_Agrave << Qt::KeyboardModifiers() << "à";
- QTest::newRow("À (IntlBackslash)")
- << "IntlBackslash" << Qt::KeyboardModifiers() << "KeyA"
- << "A" << Qt::Key_Agrave << Qt::KeyboardModifiers(Qt::ShiftModifier) << "À";
- QTest::newRow("á (Quote)") << "Quote" << Qt::KeyboardModifiers() << "KeyA"
- << "a" << Qt::Key_Aacute << Qt::KeyboardModifiers() << "á";
- QTest::newRow("Á (Quote)") << "Quote" << Qt::KeyboardModifiers() << "KeyA"
- << "A" << Qt::Key_Aacute << Qt::KeyboardModifiers(Qt::ShiftModifier)
- << "Á";
- QTest::newRow("á") << "KeyE" << Qt::KeyboardModifiers() << "KeyA"
- << "a" << Qt::Key_Aacute << Qt::KeyboardModifiers() << "á";
- QTest::newRow("Á") << "KeyE" << Qt::KeyboardModifiers() << "KeyA"
- << "A" << Qt::Key_Aacute << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Á";
- QTest::newRow("ä (Mac Umlaut)") << "KeyU" << Qt::KeyboardModifiers() << "KeyA"
- << "a" << Qt::Key_Adiaeresis << Qt::KeyboardModifiers() << "ä";
- QTest::newRow("Ä (Mac Umlaut)")
- << "KeyU" << Qt::KeyboardModifiers() << "KeyA"
- << "A" << Qt::Key_Adiaeresis << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ä";
- QTest::newRow("ä (Shift+Quote)")
- << "Quote" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyA"
- << "a" << Qt::Key_Adiaeresis << Qt::KeyboardModifiers() << "ä";
- QTest::newRow("Ä (Shift+Quote)")
- << "Quote" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyA"
- << "A" << Qt::Key_Adiaeresis << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ä";
- QTest::newRow("â") << "KeyI" << Qt::KeyboardModifiers() << "KeyA"
- << "a" << Qt::Key_Acircumflex << Qt::KeyboardModifiers() << "â";
- QTest::newRow("Â") << "KeyI" << Qt::KeyboardModifiers() << "KeyA"
- << "A" << Qt::Key_Acircumflex << Qt::KeyboardModifiers(Qt::ShiftModifier)
- << "Â";
- QTest::newRow("â (^ key)") << "Digit6" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyA"
- << "a" << Qt::Key_Acircumflex << Qt::KeyboardModifiers() << "â";
- QTest::newRow("Â (^ key)") << "Digit6" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyA"
- << "A" << Qt::Key_Acircumflex
- << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Â";
- QTest::newRow("ã") << "KeyN" << Qt::KeyboardModifiers() << "KeyA"
- << "a" << Qt::Key_Atilde << Qt::KeyboardModifiers() << "ã";
- QTest::newRow("Ã") << "KeyN" << Qt::KeyboardModifiers() << "KeyA"
- << "A" << Qt::Key_Atilde << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ã";
-
- QTest::newRow("è (Backquote)") << "Backquote" << Qt::KeyboardModifiers() << "KeyE"
- << "e" << Qt::Key_Egrave << Qt::KeyboardModifiers() << "è";
- QTest::newRow("È (Backquote)")
- << "Backquote" << Qt::KeyboardModifiers() << "KeyE"
- << "E" << Qt::Key_Egrave << Qt::KeyboardModifiers(Qt::ShiftModifier) << "È";
- QTest::newRow("è") << "IntlBackslash" << Qt::KeyboardModifiers() << "KeyE"
- << "e" << Qt::Key_Egrave << Qt::KeyboardModifiers() << "è";
- QTest::newRow("È") << "IntlBackslash" << Qt::KeyboardModifiers() << "KeyE"
- << "E" << Qt::Key_Egrave << Qt::KeyboardModifiers(Qt::ShiftModifier) << "È";
- QTest::newRow("é") << "KeyE" << Qt::KeyboardModifiers() << "KeyE"
- << "e" << Qt::Key_Eacute << Qt::KeyboardModifiers() << "é";
- QTest::newRow("É") << "KeyE" << Qt::KeyboardModifiers() << "KeyE"
- << "E" << Qt::Key_Eacute << Qt::KeyboardModifiers(Qt::ShiftModifier) << "É";
- QTest::newRow("é (Quote)") << "Quote" << Qt::KeyboardModifiers() << "KeyE"
- << "e" << Qt::Key_Eacute << Qt::KeyboardModifiers() << "é";
- QTest::newRow("É (Quote)") << "Quote" << Qt::KeyboardModifiers() << "KeyE"
- << "E" << Qt::Key_Eacute << Qt::KeyboardModifiers(Qt::ShiftModifier)
- << "É";
- QTest::newRow("ë (Mac Umlaut)") << "KeyU" << Qt::KeyboardModifiers() << "KeyE"
- << "e" << Qt::Key_Ediaeresis << Qt::KeyboardModifiers() << "ë";
- QTest::newRow("Ë (Mac Umlaut)")
- << "KeyU" << Qt::KeyboardModifiers() << "KeyE"
- << "E" << Qt::Key_Ediaeresis << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ë";
- QTest::newRow("ë (Shift+Quote)")
- << "Quote" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyE"
- << "e" << Qt::Key_Ediaeresis << Qt::KeyboardModifiers() << "ë";
- QTest::newRow("Ë (Shift+Quote)")
- << "Quote" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyE"
- << "E" << Qt::Key_Ediaeresis << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ë";
- QTest::newRow("ê") << "KeyI" << Qt::KeyboardModifiers() << "KeyE"
- << "e" << Qt::Key_Ecircumflex << Qt::KeyboardModifiers() << "ê";
- QTest::newRow("Ê") << "KeyI" << Qt::KeyboardModifiers() << "KeyE"
- << "E" << Qt::Key_Ecircumflex << Qt::KeyboardModifiers(Qt::ShiftModifier)
- << "Ê";
- QTest::newRow("ê (^ key)") << "Digit6" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyE"
- << "e" << Qt::Key_Ecircumflex << Qt::KeyboardModifiers() << "ê";
- QTest::newRow("Ê (^ key)") << "Digit6" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyE"
- << "E" << Qt::Key_Ecircumflex
- << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ê";
-
- QTest::newRow("ì (Backquote)") << "Backquote" << Qt::KeyboardModifiers() << "KeyI"
- << "i" << Qt::Key_Igrave << Qt::KeyboardModifiers() << "ì";
- QTest::newRow("Ì (Backquote)")
- << "Backquote" << Qt::KeyboardModifiers() << "KeyI"
- << "I" << Qt::Key_Igrave << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ì";
- QTest::newRow("ì") << "IntlBackslash" << Qt::KeyboardModifiers() << "KeyI"
- << "i" << Qt::Key_Igrave << Qt::KeyboardModifiers() << "ì";
- QTest::newRow("Ì") << "IntlBackslash" << Qt::KeyboardModifiers() << "KeyI"
- << "I" << Qt::Key_Igrave << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ì";
- QTest::newRow("í") << "KeyE" << Qt::KeyboardModifiers() << "KeyI"
- << "i" << Qt::Key_Iacute << Qt::KeyboardModifiers() << "í";
- QTest::newRow("Í") << "KeyE" << Qt::KeyboardModifiers() << "KeyI"
- << "I" << Qt::Key_Iacute << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Í";
- QTest::newRow("í (Quote)") << "Quote" << Qt::KeyboardModifiers() << "KeyI"
- << "i" << Qt::Key_Iacute << Qt::KeyboardModifiers() << "í";
- QTest::newRow("Í (Quote)") << "Quote" << Qt::KeyboardModifiers() << "KeyI"
- << "I" << Qt::Key_Iacute << Qt::KeyboardModifiers(Qt::ShiftModifier)
- << "Í";
- QTest::newRow("ï (Mac Umlaut)") << "KeyU" << Qt::KeyboardModifiers() << "KeyI"
- << "i" << Qt::Key_Idiaeresis << Qt::KeyboardModifiers() << "ï";
- QTest::newRow("Ï (Mac Umlaut)")
- << "KeyU" << Qt::KeyboardModifiers() << "KeyI"
- << "I" << Qt::Key_Idiaeresis << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ï";
- QTest::newRow("ï (Shift+Quote)")
- << "Quote" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyI"
- << "i" << Qt::Key_Idiaeresis << Qt::KeyboardModifiers() << "ï";
- QTest::newRow("Ï (Shift+Quote)")
- << "Quote" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyI"
- << "I" << Qt::Key_Idiaeresis << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ï";
- QTest::newRow("î") << "KeyI" << Qt::KeyboardModifiers() << "KeyI"
- << "i" << Qt::Key_Icircumflex << Qt::KeyboardModifiers() << "î";
- QTest::newRow("Î") << "KeyI" << Qt::KeyboardModifiers() << "KeyI"
- << "I" << Qt::Key_Icircumflex << Qt::KeyboardModifiers(Qt::ShiftModifier)
- << "Î";
- QTest::newRow("î (^ key)") << "Digit6" << Qt::KeyboardModifiers() << "KeyI"
- << "i" << Qt::Key_Icircumflex << Qt::KeyboardModifiers() << "î";
- QTest::newRow("Î (^ key)") << "Digit6" << Qt::KeyboardModifiers() << "KeyI"
- << "I" << Qt::Key_Icircumflex
- << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Î";
-
- QTest::newRow("ñ") << "KeyN" << Qt::KeyboardModifiers() << "KeyN"
- << "n" << Qt::Key_Ntilde << Qt::KeyboardModifiers() << "ñ";
- QTest::newRow("Ñ") << "KeyN" << Qt::KeyboardModifiers() << "KeyN"
- << "N" << Qt::Key_Ntilde << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ñ";
-
- QTest::newRow("ò (Backquote)") << "Backquote" << Qt::KeyboardModifiers() << "KeyO"
- << "o" << Qt::Key_Ograve << Qt::KeyboardModifiers() << "ò";
- QTest::newRow("Ò (Backquote)")
- << "Backquote" << Qt::KeyboardModifiers() << "KeyO"
- << "O" << Qt::Key_Ograve << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ò";
- QTest::newRow("ò") << "IntlBackslash" << Qt::KeyboardModifiers() << "KeyO"
- << "o" << Qt::Key_Ograve << Qt::KeyboardModifiers() << "ò";
- QTest::newRow("Ò") << "IntlBackslash" << Qt::KeyboardModifiers() << "KeyO"
- << "O" << Qt::Key_Ograve << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ò";
- QTest::newRow("ó") << "KeyE" << Qt::KeyboardModifiers() << "KeyO"
- << "o" << Qt::Key_Oacute << Qt::KeyboardModifiers() << "ó";
- QTest::newRow("Ó") << "KeyE" << Qt::KeyboardModifiers() << "KeyO"
- << "O" << Qt::Key_Oacute << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ó";
- QTest::newRow("ó (Quote)") << "Quote" << Qt::KeyboardModifiers() << "KeyO"
- << "o" << Qt::Key_Oacute << Qt::KeyboardModifiers() << "ó";
- QTest::newRow("Ó (Quote)") << "Quote" << Qt::KeyboardModifiers() << "KeyO"
- << "O" << Qt::Key_Oacute << Qt::KeyboardModifiers(Qt::ShiftModifier)
- << "Ó";
- QTest::newRow("ö (Mac Umlaut)") << "KeyU" << Qt::KeyboardModifiers() << "KeyO"
- << "o" << Qt::Key_Odiaeresis << Qt::KeyboardModifiers() << "ö";
- QTest::newRow("Ö (Mac Umlaut)")
- << "KeyU" << Qt::KeyboardModifiers() << "KeyO"
- << "O" << Qt::Key_Odiaeresis << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ö";
- QTest::newRow("ö (Shift+Quote)")
- << "Quote" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyO"
- << "o" << Qt::Key_Odiaeresis << Qt::KeyboardModifiers() << "ö";
- QTest::newRow("Ö (Shift+Quote)")
- << "Quote" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyO"
- << "O" << Qt::Key_Odiaeresis << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ö";
- QTest::newRow("ô") << "KeyI" << Qt::KeyboardModifiers() << "KeyO"
- << "o" << Qt::Key_Ocircumflex << Qt::KeyboardModifiers() << "ô";
- QTest::newRow("Ô") << "KeyI" << Qt::KeyboardModifiers() << "KeyO"
- << "O" << Qt::Key_Ocircumflex << Qt::KeyboardModifiers(Qt::ShiftModifier)
- << "Ô";
- QTest::newRow("ô (^ key)") << "Digit6" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyO"
- << "o" << Qt::Key_Ocircumflex << Qt::KeyboardModifiers() << "ô";
- QTest::newRow("Ô (^ key)") << "Digit6" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyO"
- << "O" << Qt::Key_Ocircumflex
- << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ô";
- QTest::newRow("õ") << "KeyN" << Qt::KeyboardModifiers() << "KeyO"
- << "o" << Qt::Key_Otilde << Qt::KeyboardModifiers() << "õ";
- QTest::newRow("Õ") << "KeyN" << Qt::KeyboardModifiers() << "KeyO"
- << "O" << Qt::Key_Otilde << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Õ";
-
- QTest::newRow("ù (Backquote)") << "Backquote" << Qt::KeyboardModifiers() << "KeyU"
- << "u" << Qt::Key_Ugrave << Qt::KeyboardModifiers() << "ù";
- QTest::newRow("Ù (Backquote)")
- << "Backquote" << Qt::KeyboardModifiers() << "KeyU"
- << "U" << Qt::Key_Ugrave << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ù";
- QTest::newRow("ù") << "IntlBackslash" << Qt::KeyboardModifiers() << "KeyU"
- << "u" << Qt::Key_Ugrave << Qt::KeyboardModifiers() << "ù";
- QTest::newRow("Ù") << "IntlBackslash" << Qt::KeyboardModifiers() << "KeyU"
- << "U" << Qt::Key_Ugrave << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ù";
- QTest::newRow("ú") << "KeyE" << Qt::KeyboardModifiers() << "KeyU"
- << "u" << Qt::Key_Uacute << Qt::KeyboardModifiers() << "ú";
- QTest::newRow("Ú") << "KeyE" << Qt::KeyboardModifiers() << "KeyU"
- << "U" << Qt::Key_Uacute << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ú";
- QTest::newRow("ú (Quote)") << "Quote" << Qt::KeyboardModifiers() << "KeyU"
- << "u" << Qt::Key_Uacute << Qt::KeyboardModifiers() << "ú";
- QTest::newRow("Ú (Quote)") << "Quote" << Qt::KeyboardModifiers() << "KeyU"
- << "U" << Qt::Key_Uacute << Qt::KeyboardModifiers(Qt::ShiftModifier)
- << "Ú";
- QTest::newRow("ü (Mac Umlaut)") << "KeyU" << Qt::KeyboardModifiers() << "KeyU"
- << "u" << Qt::Key_Udiaeresis << Qt::KeyboardModifiers() << "ü";
- QTest::newRow("Ü (Mac Umlaut)")
- << "KeyU" << Qt::KeyboardModifiers() << "KeyU"
- << "U" << Qt::Key_Udiaeresis << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ü";
- QTest::newRow("ü (Shift+Quote)")
- << "Quote" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyU"
- << "u" << Qt::Key_Udiaeresis << Qt::KeyboardModifiers() << "ü";
- QTest::newRow("Ü (Shift+Quote)")
- << "Quote" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyU"
- << "U" << Qt::Key_Udiaeresis << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ü";
- QTest::newRow("û") << "KeyI" << Qt::KeyboardModifiers() << "KeyU"
- << "û" << Qt::Key_Ucircumflex << Qt::KeyboardModifiers() << "û";
- QTest::newRow("Û") << "KeyI" << Qt::KeyboardModifiers() << "KeyU"
- << "U" << Qt::Key_Ucircumflex << Qt::KeyboardModifiers(Qt::ShiftModifier)
- << "Û";
- QTest::newRow("û (^ key)") << "Digit6" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyU"
- << "û" << Qt::Key_Ucircumflex << Qt::KeyboardModifiers() << "û";
- QTest::newRow("Û (^ key)") << "Digit6" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyU"
- << "U" << Qt::Key_Ucircumflex
- << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Û";
-
- QTest::newRow("ý") << "KeyE" << Qt::KeyboardModifiers() << "KeyY"
- << "y" << Qt::Key_Yacute << Qt::KeyboardModifiers() << "ý";
- QTest::newRow("Ý") << "KeyE" << Qt::KeyboardModifiers() << "KeyY"
- << "Y" << Qt::Key_Yacute << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ý";
- QTest::newRow("ý (Quote)") << "Quote" << Qt::KeyboardModifiers() << "KeyY"
- << "y" << Qt::Key_Yacute << Qt::KeyboardModifiers() << "ý";
- QTest::newRow("Ý (Quote)") << "Quote" << Qt::KeyboardModifiers() << "KeyY"
- << "Y" << Qt::Key_Yacute << Qt::KeyboardModifiers(Qt::ShiftModifier)
- << "Ý";
- QTest::newRow("ÿ (Mac Umlaut)") << "KeyU" << Qt::KeyboardModifiers() << "KeyY"
- << "y" << Qt::Key_ydiaeresis << Qt::KeyboardModifiers() << "ÿ";
- QTest::newRow("Ÿ (Mac Umlaut)")
- << "KeyU" << Qt::KeyboardModifiers() << "KeyY"
- << "Y" << Qt::Key_ydiaeresis << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ÿ";
- QTest::newRow("ÿ (Shift+Quote)")
- << "Quote" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyY"
- << "y" << Qt::Key_ydiaeresis << Qt::KeyboardModifiers() << "ÿ";
- QTest::newRow("Ÿ (Shift+Quote)")
- << "Quote" << Qt::KeyboardModifiers(Qt::ShiftModifier) << "KeyY"
- << "Y" << Qt::Key_ydiaeresis << Qt::KeyboardModifiers(Qt::ShiftModifier) << "Ÿ";
-}
-
-void tst_QWasmKeyTranslator::modifyByDeadKey()
-{
- QFETCH(QString, deadKeyCode);
- QFETCH(Qt::KeyboardModifiers, deadKeyModifiers);
- QFETCH(QString, targetKeyCode);
- QFETCH(QString, targetKey);
- QFETCH(Qt::Key, targetQtKey);
- QFETCH(Qt::KeyboardModifiers, modifiers);
- QFETCH(QString, expectedModifiedKey);
-
- QWasmDeadKeySupport deadKeySupport;
-
- KeyEvent event(EventType::KeyDown, makeDeadKeyJsEvent(deadKeyCode, deadKeyModifiers), &deadKeySupport);
- QCOMPARE(event.deadKey, true);
-
- KeyEvent eDown(EventType::KeyDown, makeKeyJsEvent(targetKeyCode, targetKey, modifiers), &deadKeySupport);
- QCOMPARE(eDown.deadKey, false);
- QCOMPARE(eDown.text, expectedModifiedKey);
- QCOMPARE(eDown.key, targetQtKey);
-
- KeyEvent eUp(EventType::KeyUp, makeKeyJsEvent(targetKeyCode, targetKey, modifiers), &deadKeySupport);
- QCOMPARE(eUp.deadKey, false);
- QCOMPARE(eUp.text, expectedModifiedKey);
- QCOMPARE(eUp.key, targetQtKey);
-}
-
-void tst_QWasmKeyTranslator::deadKeyModifiesOnlyOneKeyPressAndUp()
-{
- QWasmDeadKeySupport deadKeySupport;
- KeyEvent event(EventType::KeyDown, makeDeadKeyJsEvent("KeyU", Qt::KeyboardModifiers()), &deadKeySupport);
-
- KeyEvent eDown(EventType::KeyDown, makeKeyJsEvent("KeyU", "u", Qt::KeyboardModifiers()), &deadKeySupport);
- QCOMPARE(eDown.text, "ü");
- QCOMPARE(eDown.key, Qt::Key_Udiaeresis);
-
- KeyEvent eUp(EventType::KeyUp, makeKeyJsEvent("KeyU", "u", Qt::KeyboardModifiers()), &deadKeySupport);
- QCOMPARE(eUp.text, "ü");
- QCOMPARE(eUp.key, Qt::Key_Udiaeresis);
-
- KeyEvent eDown2(EventType::KeyDown, makeKeyJsEvent("KeyU", "u", Qt::KeyboardModifiers()), &deadKeySupport);
- QCOMPARE(eDown2.text, "u");
- QCOMPARE(eDown2.key, Qt::Key_U);
-
- KeyEvent eUp2(EventType::KeyUp, makeKeyJsEvent("KeyU", "u", Qt::KeyboardModifiers()), &deadKeySupport);
- QCOMPARE(eUp2.text, "u");
- QCOMPARE(eUp2.key, Qt::Key_U);
-}
-
-void tst_QWasmKeyTranslator::deadKeyIgnoresKeyUpPrecedingKeyDown()
-{
- QWasmDeadKeySupport deadKeySupport;
-
- KeyEvent deadKeyDownEvent(EventType::KeyDown,
- makeDeadKeyJsEvent("KeyU", Qt::KeyboardModifiers()), &deadKeySupport);
-
- KeyEvent deadKeyUpEvent(EventType::KeyUp, makeDeadKeyJsEvent("KeyU", Qt::KeyboardModifiers()), &deadKeySupport);
-
- KeyEvent otherKeyUpEvent(EventType::KeyUp,
- makeKeyJsEvent("AltLeft", "Alt", Qt::KeyboardModifiers()), &deadKeySupport);
-
- KeyEvent eDown(EventType::KeyDown, makeKeyJsEvent("KeyU", "u", Qt::KeyboardModifiers()), &deadKeySupport);
- QCOMPARE(eDown.text, "ü");
- QCOMPARE(eDown.key, Qt::Key_Udiaeresis);
-
- KeyEvent yetAnotherKeyUpEvent(
- EventType::KeyUp, makeKeyJsEvent("ControlLeft", "Control", Qt::KeyboardModifiers()), &deadKeySupport);
-
- KeyEvent eUp(EventType::KeyUp, makeKeyJsEvent("KeyU", "u", Qt::KeyboardModifiers()), &deadKeySupport);
- QCOMPARE(eUp.text, "ü");
- QCOMPARE(eUp.key, Qt::Key_Udiaeresis);
-}
-
-void tst_QWasmKeyTranslator::onlyKeysProducingTextAreModifiedByDeadKeys()
-{
- QWasmDeadKeySupport deadKeySupport;
-
- KeyEvent deadKeyDownEvent(EventType::KeyDown,
- makeDeadKeyJsEvent("KeyU", Qt::KeyboardModifiers()), &deadKeySupport);
-
- KeyEvent noTextKeyDown(EventType::KeyDown,
- makeKeyJsEvent("AltLeft", "Alt", Qt::KeyboardModifiers()), &deadKeySupport);
- QCOMPARE(noTextKeyDown.text, "");
- QCOMPARE(noTextKeyDown.key, Qt::Key_Alt);
-
- KeyEvent noTextKeyUp(EventType::KeyUp,
- makeKeyJsEvent("AltLeft", "Alt", Qt::KeyboardModifiers()), &deadKeySupport);
- QCOMPARE(noTextKeyDown.text, "");
- QCOMPARE(noTextKeyDown.key, Qt::Key_Alt);
-
- KeyEvent eDown(EventType::KeyDown, makeKeyJsEvent("KeyU", "u", Qt::KeyboardModifiers()), &deadKeySupport);
- QCOMPARE(eDown.text, "ü");
- QCOMPARE(eDown.key, Qt::Key_Udiaeresis);
-
- KeyEvent eUp(EventType::KeyUp, makeKeyJsEvent("KeyU", "u", Qt::KeyboardModifiers()), &deadKeySupport);
- QCOMPARE(eUp.text, "ü");
- QCOMPARE(eUp.key, Qt::Key_Udiaeresis);
-}
-
-QTEST_MAIN(tst_QWasmKeyTranslator)
-#include "tst_qwasmkeytranslator.moc"