summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
19 files changed, 491 insertions, 207 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()