qt5-declarative, qt5-wayland rebuild
This commit is contained in:
@@ -116,6 +116,305 @@ index 39f4f88512..c963e1878e 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, int Step>
|
template<typename T, int Step>
|
||||||
|
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
|
||||||
|
index ee31cb38d9..187339169b 100644
|
||||||
|
--- a/src/qml/qml/qqmldata_p.h
|
||||||
|
+++ b/src/qml/qml/qqmldata_p.h
|
||||||
|
@@ -176,24 +176,24 @@ public:
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NotifyList {
|
||||||
|
- quint64 connectionMask;
|
||||||
|
-
|
||||||
|
- quint16 maximumTodoIndex;
|
||||||
|
- quint16 notifiesSize;
|
||||||
|
-
|
||||||
|
- QQmlNotifierEndpoint *todo;
|
||||||
|
- QQmlNotifierEndpoint**notifies;
|
||||||
|
+ QAtomicInteger<quint64> connectionMask;
|
||||||
|
+ QQmlNotifierEndpoint *todo = nullptr;
|
||||||
|
+ QQmlNotifierEndpoint**notifies = nullptr;
|
||||||
|
+ quint16 maximumTodoIndex = 0;
|
||||||
|
+ quint16 notifiesSize = 0;
|
||||||
|
void layout();
|
||||||
|
private:
|
||||||
|
void layout(QQmlNotifierEndpoint*);
|
||||||
|
};
|
||||||
|
- NotifyList *notifyList;
|
||||||
|
+ QAtomicPointer<NotifyList> notifyList;
|
||||||
|
|
||||||
|
- inline QQmlNotifierEndpoint *notify(int index);
|
||||||
|
+ inline QQmlNotifierEndpoint *notify(int index) const;
|
||||||
|
void addNotify(int index, QQmlNotifierEndpoint *);
|
||||||
|
int endpointCount(int index);
|
||||||
|
bool signalHasEndpoint(int index) const;
|
||||||
|
- void disconnectNotifiers();
|
||||||
|
+
|
||||||
|
+ enum class DeleteNotifyList { Yes, No };
|
||||||
|
+ void disconnectNotifiers(DeleteNotifyList doDelete);
|
||||||
|
|
||||||
|
// The context that created the C++ object
|
||||||
|
QQmlContextData *context = nullptr;
|
||||||
|
@@ -201,12 +201,12 @@ public:
|
||||||
|
QQmlContextData *outerContext = nullptr;
|
||||||
|
QQmlContextDataRef ownContext;
|
||||||
|
|
||||||
|
- QQmlAbstractBinding *bindings;
|
||||||
|
- QQmlBoundSignal *signalHandlers;
|
||||||
|
+ QQmlAbstractBinding *bindings = nullptr;
|
||||||
|
+ QQmlBoundSignal *signalHandlers = nullptr;
|
||||||
|
|
||||||
|
// Linked list for QQmlContext::contextObjects
|
||||||
|
- QQmlData *nextContextObject;
|
||||||
|
- QQmlData**prevContextObject;
|
||||||
|
+ QQmlData *nextContextObject = nullptr;
|
||||||
|
+ QQmlData**prevContextObject = nullptr;
|
||||||
|
|
||||||
|
inline bool hasBindingBit(int) const;
|
||||||
|
inline void setBindingBit(QObject *obj, int);
|
||||||
|
@@ -216,10 +216,10 @@ public:
|
||||||
|
inline void setPendingBindingBit(QObject *obj, int);
|
||||||
|
inline void clearPendingBindingBit(int);
|
||||||
|
|
||||||
|
- quint16 lineNumber;
|
||||||
|
- quint16 columnNumber;
|
||||||
|
+ quint16 lineNumber = 0;
|
||||||
|
+ quint16 columnNumber = 0;
|
||||||
|
|
||||||
|
- quint32 jsEngineId; // id of the engine that created the jsWrapper
|
||||||
|
+ quint32 jsEngineId = 0; // id of the engine that created the jsWrapper
|
||||||
|
|
||||||
|
struct DeferredData {
|
||||||
|
DeferredData();
|
||||||
|
@@ -240,7 +240,7 @@ public:
|
||||||
|
|
||||||
|
QQmlPropertyCache *propertyCache;
|
||||||
|
|
||||||
|
- QQmlGuardImpl *guards;
|
||||||
|
+ QQmlGuardImpl *guards = nullptr;
|
||||||
|
|
||||||
|
static QQmlData *get(const QObject *object, bool create = false) {
|
||||||
|
QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
|
||||||
|
@@ -289,7 +289,7 @@ public:
|
||||||
|
|
||||||
|
private:
|
||||||
|
// For attachedProperties
|
||||||
|
- mutable QQmlDataExtended *extendedData;
|
||||||
|
+ mutable QQmlDataExtended *extendedData = nullptr;
|
||||||
|
|
||||||
|
Q_NEVER_INLINE static QQmlData *createQQmlData(QObjectPrivate *priv);
|
||||||
|
Q_NEVER_INLINE static QQmlPropertyCache *createPropertyCache(QJSEngine *engine, QObject *object);
|
||||||
|
@@ -342,23 +342,31 @@ bool QQmlData::wasDeleted(const QObject *object)
|
||||||
|
return ddata && ddata->isQueuedForDeletion;
|
||||||
|
}
|
||||||
|
|
||||||
|
-QQmlNotifierEndpoint *QQmlData::notify(int index)
|
||||||
|
+inline bool isIndexInConnectionMask(quint64 connectionMask, int index)
|
||||||
|
+{
|
||||||
|
+ return connectionMask & (1ULL << quint64(index % 64));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+QQmlNotifierEndpoint *QQmlData::notify(int index) const
|
||||||
|
{
|
||||||
|
+ // Can only happen on "home" thread. We apply relaxed semantics when loading the atomics.
|
||||||
|
+
|
||||||
|
Q_ASSERT(index <= 0xFFFF);
|
||||||
|
|
||||||
|
- if (!notifyList || !(notifyList->connectionMask & (1ULL << quint64(index % 64)))) {
|
||||||
|
+ NotifyList *list = notifyList.loadRelaxed();
|
||||||
|
+ if (!list || !isIndexInConnectionMask(list->connectionMask.loadRelaxed(), index))
|
||||||
|
return nullptr;
|
||||||
|
- } else if (index < notifyList->notifiesSize) {
|
||||||
|
- return notifyList->notifies[index];
|
||||||
|
- } else if (index <= notifyList->maximumTodoIndex) {
|
||||||
|
- notifyList->layout();
|
||||||
|
- }
|
||||||
|
|
||||||
|
- if (index < notifyList->notifiesSize) {
|
||||||
|
- return notifyList->notifies[index];
|
||||||
|
- } else {
|
||||||
|
- return nullptr;
|
||||||
|
+ if (index < list->notifiesSize)
|
||||||
|
+ return list->notifies[index];
|
||||||
|
+
|
||||||
|
+ if (index <= list->maximumTodoIndex) {
|
||||||
|
+ list->layout();
|
||||||
|
+ if (index < list->notifiesSize)
|
||||||
|
+ return list->notifies[index];
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -367,7 +375,19 @@ QQmlNotifierEndpoint *QQmlData::notify(int index)
|
||||||
|
*/
|
||||||
|
inline bool QQmlData::signalHasEndpoint(int index) const
|
||||||
|
{
|
||||||
|
- return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
|
||||||
|
+ // This can be called from any thread.
|
||||||
|
+ // We still use relaxed semantics. If we're on a thread different from the "home" thread
|
||||||
|
+ // of the QQmlData, two interesting things might happen:
|
||||||
|
+ //
|
||||||
|
+ // 1. The list might go away while we hold it. In that case we are dealing with an object whose
|
||||||
|
+ // QObject dtor is being executed concurrently. This is UB already without the notify lists.
|
||||||
|
+ // Therefore, we don't need to consider it.
|
||||||
|
+ // 2. The connectionMask may be amended or zeroed while we are looking at it. In that case
|
||||||
|
+ // we "misreport" the endpoint. Since ordering of events across threads is inherently
|
||||||
|
+ // nondeterministic, either result is correct in that case. We can accept it.
|
||||||
|
+
|
||||||
|
+ NotifyList *list = notifyList.loadRelaxed();
|
||||||
|
+ return list && isIndexInConnectionMask(list->connectionMask.loadRelaxed(), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QQmlData::hasBindingBit(int coreIndex) const
|
||||||
|
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
|
||||||
|
index 826a1a5ab4..fce8fe987f 100644
|
||||||
|
--- a/src/qml/qml/qqmlengine.cpp
|
||||||
|
+++ b/src/qml/qml/qqmlengine.cpp
|
||||||
|
@@ -718,18 +718,15 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
|
||||||
|
// Disconnect the notifiers now - during object destruction this would be too late, since
|
||||||
|
// the disconnect call wouldn't be able to call disconnectNotify(), as it isn't possible to
|
||||||
|
// get the metaobject anymore.
|
||||||
|
- d->disconnectNotifiers();
|
||||||
|
+ d->disconnectNotifiers(QQmlData::DeleteNotifyList::No);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QQmlData::QQmlData()
|
||||||
|
: ownedByQml1(false), ownMemory(true), indestructible(true), explicitIndestructibleSet(false),
|
||||||
|
hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false),
|
||||||
|
- hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false),
|
||||||
|
- bindingBitsArraySize(InlineBindingArraySize), notifyList(nullptr),
|
||||||
|
- bindings(nullptr), signalHandlers(nullptr), nextContextObject(nullptr), prevContextObject(nullptr),
|
||||||
|
- lineNumber(0), columnNumber(0), jsEngineId(0),
|
||||||
|
- propertyCache(nullptr), guards(nullptr), extendedData(nullptr)
|
||||||
|
+ hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false), dummy(0),
|
||||||
|
+ bindingBitsArraySize(InlineBindingArraySize), propertyCache(nullptr)
|
||||||
|
{
|
||||||
|
memset(bindingBitsValue, 0, sizeof(bindingBitsValue));
|
||||||
|
init();
|
||||||
|
@@ -789,7 +786,10 @@ void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int in
|
||||||
|
// QQmlEngine to emit signals from a different thread. These signals are then automatically
|
||||||
|
// marshalled back onto the QObject's thread and handled by QML from there. This is tested
|
||||||
|
// by the qqmlecmascript::threadSignal() autotest.
|
||||||
|
- if (!ddata->notifyList)
|
||||||
|
+
|
||||||
|
+ // Relaxed semantics here. If we're on a different thread we might schedule a useless event,
|
||||||
|
+ // but that should be rare.
|
||||||
|
+ if (!ddata->notifyList.loadRelaxed())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto objectThreadData = QObjectPrivate::get(object)->threadData.loadRelaxed();
|
||||||
|
@@ -1835,49 +1835,73 @@ void QQmlData::releaseDeferredData()
|
||||||
|
|
||||||
|
void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
|
||||||
|
{
|
||||||
|
- if (!notifyList) {
|
||||||
|
- notifyList = (NotifyList *)malloc(sizeof(NotifyList));
|
||||||
|
- notifyList->connectionMask = 0;
|
||||||
|
- notifyList->maximumTodoIndex = 0;
|
||||||
|
- notifyList->notifiesSize = 0;
|
||||||
|
- notifyList->todo = nullptr;
|
||||||
|
- notifyList->notifies = nullptr;
|
||||||
|
+ // Can only happen on "home" thread. We apply relaxed semantics when loading the atomics.
|
||||||
|
+
|
||||||
|
+ NotifyList *list = notifyList.loadRelaxed();
|
||||||
|
+
|
||||||
|
+ if (!list) {
|
||||||
|
+ list = new NotifyList;
|
||||||
|
+ // We don't really care when this change takes effect on other threads. The notifyList can
|
||||||
|
+ // only become non-null once in the life time of a QQmlData. It becomes null again when the
|
||||||
|
+ // underlying QObject is deleted. At that point any interaction with the QQmlData is UB
|
||||||
|
+ // anyway. So, for all intents and purposese, the list becomes non-null once and then stays
|
||||||
|
+ // non-null "forever". We can apply relaxed semantics.
|
||||||
|
+ notifyList.storeRelaxed(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_ASSERT(!endpoint->isConnected());
|
||||||
|
|
||||||
|
index = qMin(index, 0xFFFF - 1);
|
||||||
|
- notifyList->connectionMask |= (1ULL << quint64(index % 64));
|
||||||
|
|
||||||
|
- if (index < notifyList->notifiesSize) {
|
||||||
|
+ // Likewise, we don't really care _when_ the change in the connectionMask is propagated to other
|
||||||
|
+ // threads. Cross-thread event ordering is inherently nondeterministic. Therefore, when querying
|
||||||
|
+ // the conenctionMask in the presence of concurrent modification, any result is correct.
|
||||||
|
+ list->connectionMask.storeRelaxed(
|
||||||
|
+ list->connectionMask.loadRelaxed() | (1ULL << quint64(index % 64)));
|
||||||
|
|
||||||
|
- endpoint->next = notifyList->notifies[index];
|
||||||
|
+ if (index < list->notifiesSize) {
|
||||||
|
+ endpoint->next = list->notifies[index];
|
||||||
|
if (endpoint->next) endpoint->next->prev = &endpoint->next;
|
||||||
|
- endpoint->prev = ¬ifyList->notifies[index];
|
||||||
|
- notifyList->notifies[index] = endpoint;
|
||||||
|
-
|
||||||
|
+ endpoint->prev = &list->notifies[index];
|
||||||
|
+ list->notifies[index] = endpoint;
|
||||||
|
} else {
|
||||||
|
- notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
|
||||||
|
+ list->maximumTodoIndex = qMax(int(list->maximumTodoIndex), index);
|
||||||
|
|
||||||
|
- endpoint->next = notifyList->todo;
|
||||||
|
+ endpoint->next = list->todo;
|
||||||
|
if (endpoint->next) endpoint->next->prev = &endpoint->next;
|
||||||
|
- endpoint->prev = ¬ifyList->todo;
|
||||||
|
- notifyList->todo = endpoint;
|
||||||
|
+ endpoint->prev = &list->todo;
|
||||||
|
+ list->todo = endpoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-void QQmlData::disconnectNotifiers()
|
||||||
|
+void QQmlData::disconnectNotifiers(QQmlData::DeleteNotifyList doDelete)
|
||||||
|
{
|
||||||
|
- if (notifyList) {
|
||||||
|
- while (notifyList->todo)
|
||||||
|
- notifyList->todo->disconnect();
|
||||||
|
- for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
|
||||||
|
- while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
|
||||||
|
+ // Can only happen on "home" thread. We apply relaxed semantics when loading the atomics.
|
||||||
|
+ if (NotifyList *list = notifyList.loadRelaxed()) {
|
||||||
|
+ while (QQmlNotifierEndpoint *todo = list->todo)
|
||||||
|
+ todo->disconnect();
|
||||||
|
+ for (int ii = 0; ii < list->notifiesSize; ++ii) {
|
||||||
|
+ while (QQmlNotifierEndpoint *ep = list->notifies[ii])
|
||||||
|
ep->disconnect();
|
||||||
|
}
|
||||||
|
- free(notifyList->notifies);
|
||||||
|
- free(notifyList);
|
||||||
|
- notifyList = nullptr;
|
||||||
|
+ free(list->notifies);
|
||||||
|
+
|
||||||
|
+ if (doDelete == DeleteNotifyList::Yes) {
|
||||||
|
+ // We can only get here from QQmlData::destroyed(), and that can only come from the
|
||||||
|
+ // the QObject dtor. If you're still sending signals at that point you have UB already
|
||||||
|
+ // without any threads. Therefore, it's enough to apply relaxed semantics.
|
||||||
|
+ notifyList.storeRelaxed(nullptr);
|
||||||
|
+ delete list;
|
||||||
|
+ } else {
|
||||||
|
+ // We can use relaxed semantics here. The worst thing that can happen is that some
|
||||||
|
+ // signal is falsely reported as connected. Signal connectedness across threads
|
||||||
|
+ // is not quite deterministic anyway.
|
||||||
|
+ list->connectionMask.storeRelaxed(0);
|
||||||
|
+ list->maximumTodoIndex = 0;
|
||||||
|
+ list->notifiesSize = 0;
|
||||||
|
+ list->notifies = nullptr;
|
||||||
|
+
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1961,7 +1985,7 @@ void QQmlData::destroyed(QObject *object)
|
||||||
|
guard->objectDestroyed(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
- disconnectNotifiers();
|
||||||
|
+ disconnectNotifiers(DeleteNotifyList::Yes);
|
||||||
|
|
||||||
|
if (extendedData)
|
||||||
|
delete extendedData;
|
||||||
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
|
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
|
||||||
index 10c6c41338..39bfcdc999 100644
|
index 10c6c41338..39bfcdc999 100644
|
||||||
--- a/src/qml/qml/qqmlimport.cpp
|
--- a/src/qml/qml/qqmlimport.cpp
|
||||||
|
|||||||
@@ -69,6 +69,13 @@
|
|||||||
</Package-->
|
</Package-->
|
||||||
|
|
||||||
<History>
|
<History>
|
||||||
|
<Update release="41">
|
||||||
|
<Date>2023-09-08</Date>
|
||||||
|
<Version>5.15.10</Version>
|
||||||
|
<Comment>Rebuild.</Comment>
|
||||||
|
<Name>Mustafa Cinasal</Name>
|
||||||
|
<Email>muscnsl@gmail.com</Email>
|
||||||
|
</Update>
|
||||||
<Update release="40">
|
<Update release="40">
|
||||||
<Date>2023-07-07</Date>
|
<Date>2023-07-07</Date>
|
||||||
<Version>5.15.10</Version>
|
<Version>5.15.10</Version>
|
||||||
|
|||||||
@@ -85,6 +85,19 @@ index 69cc46a0..9091efbe 100644
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtensionTemplatePrivate : public QWaylandClientExtensionPrivate
|
class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtensionTemplatePrivate : public QWaylandClientExtensionPrivate
|
||||||
|
diff --git a/src/client/qwaylandabstractdecoration.cpp b/src/client/qwaylandabstractdecoration.cpp
|
||||||
|
index b6ee43c9..be0a31df 100644
|
||||||
|
--- a/src/client/qwaylandabstractdecoration.cpp
|
||||||
|
+++ b/src/client/qwaylandabstractdecoration.cpp
|
||||||
|
@@ -122,7 +122,7 @@ const QImage &QWaylandAbstractDecoration::contentImage()
|
||||||
|
if (d->m_isDirty) {
|
||||||
|
// Update the decoration backingstore
|
||||||
|
|
||||||
|
- const int bufferScale = waylandWindow()->scale();
|
||||||
|
+ const qreal bufferScale = waylandWindow()->scale();
|
||||||
|
const QSize imageSize = waylandWindow()->surfaceSize() * bufferScale;
|
||||||
|
d->m_decorationContentImage = QImage(imageSize, QImage::Format_ARGB32_Premultiplied);
|
||||||
|
// Only scale by buffer scale, not QT_SCALE_FACTOR etc.
|
||||||
diff --git a/src/client/qwaylandclipboard.cpp b/src/client/qwaylandclipboard.cpp
|
diff --git a/src/client/qwaylandclipboard.cpp b/src/client/qwaylandclipboard.cpp
|
||||||
index 81f48e05..14561c77 100644
|
index 81f48e05..14561c77 100644
|
||||||
--- a/src/client/qwaylandclipboard.cpp
|
--- a/src/client/qwaylandclipboard.cpp
|
||||||
@@ -169,8 +182,49 @@ index ce14e124..bb52683d 100644
|
|||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
diff --git a/src/client/qwaylandcursor.cpp b/src/client/qwaylandcursor.cpp
|
||||||
|
index e4eca9d4..ba76ba2d 100644
|
||||||
|
--- a/src/client/qwaylandcursor.cpp
|
||||||
|
+++ b/src/client/qwaylandcursor.cpp
|
||||||
|
@@ -44,6 +44,7 @@
|
||||||
|
#include "qwaylandshmbackingstore_p.h"
|
||||||
|
|
||||||
|
#include <QtGui/QImageReader>
|
||||||
|
+#include <QBitmap>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include <wayland-cursor.h>
|
||||||
|
@@ -250,7 +251,27 @@ QWaylandCursor::QWaylandCursor(QWaylandDisplay *display)
|
||||||
|
QSharedPointer<QWaylandBuffer> QWaylandCursor::cursorBitmapBuffer(QWaylandDisplay *display, const QCursor *cursor)
|
||||||
|
{
|
||||||
|
Q_ASSERT(cursor->shape() == Qt::BitmapCursor);
|
||||||
|
- const QImage &img = cursor->pixmap().toImage();
|
||||||
|
+
|
||||||
|
+ const QBitmap mask = cursor->mask(Qt::ReturnByValue);
|
||||||
|
+ QImage img;
|
||||||
|
+ if (cursor->pixmap().isNull())
|
||||||
|
+ img = cursor->bitmap(Qt::ReturnByValue).toImage();
|
||||||
|
+ else
|
||||||
|
+ img = cursor->pixmap().toImage();
|
||||||
|
+
|
||||||
|
+ // convert to supported format if necessary
|
||||||
|
+ if (!display->shm()->formatSupported(img.format())) {
|
||||||
|
+ if (mask.isNull()) {
|
||||||
|
+ img.convertTo(QImage::Format_RGB32);
|
||||||
|
+ } else {
|
||||||
|
+ // preserve mask
|
||||||
|
+ img.convertTo(QImage::Format_ARGB32);
|
||||||
|
+ QPixmap pixmap = QPixmap::fromImage(img);
|
||||||
|
+ pixmap.setMask(mask);
|
||||||
|
+ img = pixmap.toImage();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
QSharedPointer<QWaylandShmBuffer> buffer(new QWaylandShmBuffer(display, img.size(), img.format()));
|
||||||
|
memcpy(buffer->image()->bits(), img.bits(), size_t(img.sizeInBytes()));
|
||||||
|
return buffer;
|
||||||
diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp
|
diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp
|
||||||
index 7e2e3308..e3e60ed5 100644
|
index 7e2e3308..e66ae880 100644
|
||||||
--- a/src/client/qwaylanddatadevice.cpp
|
--- a/src/client/qwaylanddatadevice.cpp
|
||||||
+++ b/src/client/qwaylanddatadevice.cpp
|
+++ b/src/client/qwaylanddatadevice.cpp
|
||||||
@@ -72,6 +72,8 @@ QWaylandDataDevice::QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWayl
|
@@ -72,6 +72,8 @@ QWaylandDataDevice::QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWayl
|
||||||
@@ -191,7 +245,7 @@ index 7e2e3308..e3e60ed5 100644
|
|||||||
{
|
{
|
||||||
auto *seat = m_display->currentInputDevice();
|
auto *seat = m_display->currentInputDevice();
|
||||||
auto *origin = seat->pointerFocus();
|
auto *origin = seat->pointerFocus();
|
||||||
@@ -123,7 +125,28 @@ bool QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
|
@@ -123,7 +125,31 @@ bool QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
m_dragSource.reset(new QWaylandDataSource(m_display->dndSelectionHandler(), mimeData));
|
m_dragSource.reset(new QWaylandDataSource(m_display->dndSelectionHandler(), mimeData));
|
||||||
@@ -202,6 +256,9 @@ index 7e2e3308..e3e60ed5 100644
|
|||||||
connect(m_dragSource.data(), &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::dragSourceCancelled);
|
connect(m_dragSource.data(), &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::dragSourceCancelled);
|
||||||
+ connect(m_dragSource.data(), &QWaylandDataSource::dndResponseUpdated, this, [this](bool accepted, Qt::DropAction action) {
|
+ connect(m_dragSource.data(), &QWaylandDataSource::dndResponseUpdated, this, [this](bool accepted, Qt::DropAction action) {
|
||||||
+ auto drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag());
|
+ auto drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag());
|
||||||
|
+ if (!drag->currentDrag()) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
+ // in old versions drop action is not set, so we guess
|
+ // in old versions drop action is not set, so we guess
|
||||||
+ if (wl_data_source_get_version(m_dragSource->object()) < 3) {
|
+ if (wl_data_source_get_version(m_dragSource->object()) < 3) {
|
||||||
+ drag->setResponse(accepted);
|
+ drag->setResponse(accepted);
|
||||||
@@ -220,7 +277,7 @@ index 7e2e3308..e3e60ed5 100644
|
|||||||
|
|
||||||
start_drag(m_dragSource->object(), origin->wlSurface(), icon->wlSurface(), m_display->currentInputDevice()->serial());
|
start_drag(m_dragSource->object(), origin->wlSurface(), icon->wlSurface(), m_display->currentInputDevice()->serial());
|
||||||
return true;
|
return true;
|
||||||
@@ -152,7 +175,7 @@ void QWaylandDataDevice::data_device_drop()
|
@@ -152,7 +178,7 @@ void QWaylandDataDevice::data_device_drop()
|
||||||
supportedActions = drag->supportedActions();
|
supportedActions = drag->supportedActions();
|
||||||
} else if (m_dragOffer) {
|
} else if (m_dragOffer) {
|
||||||
dragData = m_dragOffer->mimeData();
|
dragData = m_dragOffer->mimeData();
|
||||||
@@ -229,7 +286,7 @@ index 7e2e3308..e3e60ed5 100644
|
|||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -162,7 +185,11 @@ void QWaylandDataDevice::data_device_drop()
|
@@ -162,7 +188,11 @@ void QWaylandDataDevice::data_device_drop()
|
||||||
QGuiApplication::keyboardModifiers());
|
QGuiApplication::keyboardModifiers());
|
||||||
|
|
||||||
if (drag) {
|
if (drag) {
|
||||||
@@ -242,7 +299,7 @@ index 7e2e3308..e3e60ed5 100644
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +213,7 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface,
|
@@ -186,7 +216,7 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface,
|
||||||
supportedActions = drag->supportedActions();
|
supportedActions = drag->supportedActions();
|
||||||
} else if (m_dragOffer) {
|
} else if (m_dragOffer) {
|
||||||
dragData = m_dragOffer->mimeData();
|
dragData = m_dragOffer->mimeData();
|
||||||
@@ -251,7 +308,7 @@ index 7e2e3308..e3e60ed5 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
|
const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
|
||||||
@@ -197,11 +224,7 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface,
|
@@ -197,11 +227,7 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface,
|
||||||
static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
|
static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,7 +321,7 @@ index 7e2e3308..e3e60ed5 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
void QWaylandDataDevice::data_device_leave()
|
void QWaylandDataDevice::data_device_leave()
|
||||||
@@ -235,10 +258,10 @@ void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixe
|
@@ -235,10 +261,10 @@ void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixe
|
||||||
supportedActions = drag->supportedActions();
|
supportedActions = drag->supportedActions();
|
||||||
} else {
|
} else {
|
||||||
dragData = m_dragOffer->mimeData();
|
dragData = m_dragOffer->mimeData();
|
||||||
@@ -277,7 +334,7 @@ index 7e2e3308..e3e60ed5 100644
|
|||||||
QGuiApplication::mouseButtons(),
|
QGuiApplication::mouseButtons(),
|
||||||
QGuiApplication::keyboardModifiers());
|
QGuiApplication::keyboardModifiers());
|
||||||
|
|
||||||
@@ -246,11 +269,7 @@ void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixe
|
@@ -246,11 +272,7 @@ void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixe
|
||||||
static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
|
static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,7 +347,7 @@ index 7e2e3308..e3e60ed5 100644
|
|||||||
}
|
}
|
||||||
#endif // QT_CONFIG(draganddrop)
|
#endif // QT_CONFIG(draganddrop)
|
||||||
|
|
||||||
@@ -277,14 +296,10 @@ void QWaylandDataDevice::selectionSourceCancelled()
|
@@ -277,14 +299,10 @@ void QWaylandDataDevice::selectionSourceCancelled()
|
||||||
#if QT_CONFIG(draganddrop)
|
#if QT_CONFIG(draganddrop)
|
||||||
void QWaylandDataDevice::dragSourceCancelled()
|
void QWaylandDataDevice::dragSourceCancelled()
|
||||||
{
|
{
|
||||||
@@ -306,7 +363,7 @@ index 7e2e3308..e3e60ed5 100644
|
|||||||
QPoint QWaylandDataDevice::calculateDragPosition(int x, int y, QWindow *wnd) const
|
QPoint QWaylandDataDevice::calculateDragPosition(int x, int y, QWindow *wnd) const
|
||||||
{
|
{
|
||||||
QPoint pnt(wl_fixed_to_int(x), wl_fixed_to_int(y));
|
QPoint pnt(wl_fixed_to_int(x), wl_fixed_to_int(y));
|
||||||
@@ -297,6 +312,33 @@ QPoint QWaylandDataDevice::calculateDragPosition(int x, int y, QWindow *wnd) con
|
@@ -297,6 +315,33 @@ QPoint QWaylandDataDevice::calculateDragPosition(int x, int y, QWindow *wnd) con
|
||||||
}
|
}
|
||||||
return pnt;
|
return pnt;
|
||||||
}
|
}
|
||||||
@@ -587,7 +644,7 @@ index 25afff79..14d1542d 100644
|
|||||||
|
|
||||||
}
|
}
|
||||||
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
|
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
|
||||||
index 78e387bc..27f55965 100644
|
index 78e387bc..ff9a0500 100644
|
||||||
--- a/src/client/qwaylanddisplay.cpp
|
--- a/src/client/qwaylanddisplay.cpp
|
||||||
+++ b/src/client/qwaylanddisplay.cpp
|
+++ b/src/client/qwaylanddisplay.cpp
|
||||||
@@ -87,10 +87,203 @@
|
@@ -87,10 +87,203 @@
|
||||||
@@ -818,15 +875,18 @@ index 78e387bc..27f55965 100644
|
|||||||
if (mSyncCallback)
|
if (mSyncCallback)
|
||||||
wl_callback_destroy(mSyncCallback);
|
wl_callback_destroy(mSyncCallback);
|
||||||
|
|
||||||
@@ -189,6 +381,21 @@ QWaylandDisplay::~QWaylandDisplay(void)
|
@@ -187,10 +379,26 @@ QWaylandDisplay::~QWaylandDisplay(void)
|
||||||
|
#if QT_CONFIG(cursor)
|
||||||
|
qDeleteAll(mCursorThemes);
|
||||||
#endif
|
#endif
|
||||||
if (mDisplay)
|
|
||||||
wl_display_disconnect(mDisplay);
|
|
||||||
+
|
+
|
||||||
+ if (m_frameEventQueue)
|
+ if (m_frameEventQueue)
|
||||||
+ wl_event_queue_destroy(m_frameEventQueue);
|
+ wl_event_queue_destroy(m_frameEventQueue);
|
||||||
+}
|
|
||||||
+
|
+
|
||||||
|
if (mDisplay)
|
||||||
|
wl_display_disconnect(mDisplay);
|
||||||
|
}
|
||||||
|
|
||||||
+// Steps which is called just after constructor. This separates registry_global() out of the constructor
|
+// Steps which is called just after constructor. This separates registry_global() out of the constructor
|
||||||
+// so that factory functions in integration can be overridden.
|
+// so that factory functions in integration can be overridden.
|
||||||
+void QWaylandDisplay::initialize()
|
+void QWaylandDisplay::initialize()
|
||||||
@@ -837,10 +897,12 @@ index 78e387bc..27f55965 100644
|
|||||||
+ // Give wl_output.done and zxdg_output_v1.done events a chance to arrive
|
+ // Give wl_output.done and zxdg_output_v1.done events a chance to arrive
|
||||||
+ forceRoundTrip();
|
+ forceRoundTrip();
|
||||||
+ }
|
+ }
|
||||||
}
|
+}
|
||||||
|
+
|
||||||
void QWaylandDisplay::ensureScreen()
|
void QWaylandDisplay::ensureScreen()
|
||||||
@@ -205,98 +412,37 @@ void QWaylandDisplay::ensureScreen()
|
{
|
||||||
|
if (!mScreens.empty() || mPlaceholderScreen)
|
||||||
|
@@ -205,98 +413,37 @@ void QWaylandDisplay::ensureScreen()
|
||||||
|
|
||||||
void QWaylandDisplay::checkError() const
|
void QWaylandDisplay::checkError() const
|
||||||
{
|
{
|
||||||
@@ -959,7 +1021,7 @@ index 78e387bc..27f55965 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const
|
QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const
|
||||||
@@ -347,7 +493,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
|
@@ -347,7 +494,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
|
||||||
if (interface == QStringLiteral("wl_output")) {
|
if (interface == QStringLiteral("wl_output")) {
|
||||||
mWaitingScreens << new QWaylandScreen(this, version, id);
|
mWaitingScreens << new QWaylandScreen(this, version, id);
|
||||||
} else if (interface == QStringLiteral("wl_compositor")) {
|
} else if (interface == QStringLiteral("wl_compositor")) {
|
||||||
@@ -968,7 +1030,7 @@ index 78e387bc..27f55965 100644
|
|||||||
mCompositor.init(registry, id, mCompositorVersion);
|
mCompositor.init(registry, id, mCompositorVersion);
|
||||||
} else if (interface == QStringLiteral("wl_shm")) {
|
} else if (interface == QStringLiteral("wl_shm")) {
|
||||||
mShm.reset(new QWaylandShm(this, version, id));
|
mShm.reset(new QWaylandShm(this, version, id));
|
||||||
@@ -356,7 +502,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
|
@@ -356,7 +503,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
|
||||||
mInputDevices.append(inputDevice);
|
mInputDevices.append(inputDevice);
|
||||||
#if QT_CONFIG(wayland_datadevice)
|
#if QT_CONFIG(wayland_datadevice)
|
||||||
} else if (interface == QStringLiteral("wl_data_device_manager")) {
|
} else if (interface == QStringLiteral("wl_data_device_manager")) {
|
||||||
@@ -977,7 +1039,7 @@ index 78e387bc..27f55965 100644
|
|||||||
#endif
|
#endif
|
||||||
} else if (interface == QStringLiteral("qt_surface_extension")) {
|
} else if (interface == QStringLiteral("qt_surface_extension")) {
|
||||||
mWindowExtension.reset(new QtWayland::qt_surface_extension(registry, id, 1));
|
mWindowExtension.reset(new QtWayland::qt_surface_extension(registry, id, 1));
|
||||||
@@ -373,6 +519,8 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
|
@@ -373,6 +520,8 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
|
||||||
#if QT_CONFIG(wayland_client_primary_selection)
|
#if QT_CONFIG(wayland_client_primary_selection)
|
||||||
} else if (interface == QStringLiteral("zwp_primary_selection_device_manager_v1")) {
|
} else if (interface == QStringLiteral("zwp_primary_selection_device_manager_v1")) {
|
||||||
mPrimarySelectionManager.reset(new QWaylandPrimarySelectionDeviceManagerV1(this, id, 1));
|
mPrimarySelectionManager.reset(new QWaylandPrimarySelectionDeviceManagerV1(this, id, 1));
|
||||||
@@ -986,7 +1048,7 @@ index 78e387bc..27f55965 100644
|
|||||||
#endif
|
#endif
|
||||||
} else if (interface == QStringLiteral("zwp_text_input_manager_v2") && !mClientSideInputContextRequested) {
|
} else if (interface == QStringLiteral("zwp_text_input_manager_v2") && !mClientSideInputContextRequested) {
|
||||||
mTextInputManager.reset(new QtWayland::zwp_text_input_manager_v2(registry, id, 1));
|
mTextInputManager.reset(new QtWayland::zwp_text_input_manager_v2(registry, id, 1));
|
||||||
@@ -431,6 +579,13 @@ void QWaylandDisplay::registry_global_remove(uint32_t id)
|
@@ -431,6 +580,13 @@ void QWaylandDisplay::registry_global_remove(uint32_t id)
|
||||||
inputDevice->setTextInput(nullptr);
|
inputDevice->setTextInput(nullptr);
|
||||||
mWaylandIntegration->reconfigureInputContext();
|
mWaylandIntegration->reconfigureInputContext();
|
||||||
}
|
}
|
||||||
@@ -1000,7 +1062,7 @@ index 78e387bc..27f55965 100644
|
|||||||
mGlobals.removeAt(i);
|
mGlobals.removeAt(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -456,9 +611,10 @@ void QWaylandDisplay::addRegistryListener(RegistryListener listener, void *data)
|
@@ -456,9 +612,10 @@ void QWaylandDisplay::addRegistryListener(RegistryListener listener, void *data)
|
||||||
|
|
||||||
void QWaylandDisplay::removeListener(RegistryListener listener, void *data)
|
void QWaylandDisplay::removeListener(RegistryListener listener, void *data)
|
||||||
{
|
{
|
||||||
@@ -1012,7 +1074,7 @@ index 78e387bc..27f55965 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t QWaylandDisplay::currentTimeMillisec()
|
uint32_t QWaylandDisplay::currentTimeMillisec()
|
||||||
@@ -471,50 +627,9 @@ uint32_t QWaylandDisplay::currentTimeMillisec()
|
@@ -471,50 +628,9 @@ uint32_t QWaylandDisplay::currentTimeMillisec()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1064,7 +1126,7 @@ index 78e387bc..27f55965 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool QWaylandDisplay::supportsWindowDecoration() const
|
bool QWaylandDisplay::supportsWindowDecoration() const
|
||||||
@@ -578,14 +693,10 @@ void QWaylandDisplay::handleKeyboardFocusChanged(QWaylandInputDevice *inputDevic
|
@@ -578,14 +694,10 @@ void QWaylandDisplay::handleKeyboardFocusChanged(QWaylandInputDevice *inputDevic
|
||||||
if (mLastKeyboardFocus == keyboardFocus)
|
if (mLastKeyboardFocus == keyboardFocus)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1083,7 +1145,7 @@ index 78e387bc..27f55965 100644
|
|||||||
|
|
||||||
mLastKeyboardFocus = keyboardFocus;
|
mLastKeyboardFocus = keyboardFocus;
|
||||||
}
|
}
|
||||||
@@ -604,6 +715,19 @@ void QWaylandDisplay::handleWaylandSync()
|
@@ -604,6 +716,19 @@ void QWaylandDisplay::handleWaylandSync()
|
||||||
QWindow *activeWindow = mActiveWindows.empty() ? nullptr : mActiveWindows.last()->window();
|
QWindow *activeWindow = mActiveWindows.empty() ? nullptr : mActiveWindows.last()->window();
|
||||||
if (activeWindow != QGuiApplication::focusWindow())
|
if (activeWindow != QGuiApplication::focusWindow())
|
||||||
QWindowSystemInterface::handleWindowActivated(activeWindow);
|
QWindowSystemInterface::handleWindowActivated(activeWindow);
|
||||||
@@ -1103,7 +1165,7 @@ index 78e387bc..27f55965 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
const wl_callback_listener QWaylandDisplay::syncCallbackListener = {
|
const wl_callback_listener QWaylandDisplay::syncCallbackListener = {
|
||||||
@@ -630,6 +754,13 @@ QWaylandInputDevice *QWaylandDisplay::defaultInputDevice() const
|
@@ -630,6 +755,13 @@ QWaylandInputDevice *QWaylandDisplay::defaultInputDevice() const
|
||||||
return mInputDevices.isEmpty() ? 0 : mInputDevices.first();
|
return mInputDevices.isEmpty() ? 0 : mInputDevices.first();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1117,7 +1179,7 @@ index 78e387bc..27f55965 100644
|
|||||||
#if QT_CONFIG(cursor)
|
#if QT_CONFIG(cursor)
|
||||||
|
|
||||||
QWaylandCursor *QWaylandDisplay::waylandCursor()
|
QWaylandCursor *QWaylandDisplay::waylandCursor()
|
||||||
@@ -656,4 +787,6 @@ QWaylandCursorTheme *QWaylandDisplay::loadCursorTheme(const QString &name, int p
|
@@ -656,4 +788,6 @@ QWaylandCursorTheme *QWaylandDisplay::loadCursorTheme(const QString &name, int p
|
||||||
|
|
||||||
} // namespace QtWaylandClient
|
} // namespace QtWaylandClient
|
||||||
|
|
||||||
@@ -1295,6 +1357,28 @@ index 474fe2ab..46f629ac 100644
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QWaylandDisplay *m_display = nullptr;
|
QWaylandDisplay *m_display = nullptr;
|
||||||
|
diff --git a/src/client/qwaylandinputcontext.cpp b/src/client/qwaylandinputcontext.cpp
|
||||||
|
index 84a34674..920a4222 100644
|
||||||
|
--- a/src/client/qwaylandinputcontext.cpp
|
||||||
|
+++ b/src/client/qwaylandinputcontext.cpp
|
||||||
|
@@ -93,9 +93,14 @@ void QWaylandTextInput::reset()
|
||||||
|
void QWaylandTextInput::commit()
|
||||||
|
{
|
||||||
|
if (QObject *o = QGuiApplication::focusObject()) {
|
||||||
|
- QInputMethodEvent event;
|
||||||
|
- event.setCommitString(m_preeditCommit);
|
||||||
|
- QCoreApplication::sendEvent(o, &event);
|
||||||
|
+ if (!m_preeditCommit.isEmpty()) {
|
||||||
|
+
|
||||||
|
+ QInputMethodEvent event;
|
||||||
|
+ event.setCommitString(m_preeditCommit);
|
||||||
|
+ m_preeditCommit = QString();
|
||||||
|
+
|
||||||
|
+ QCoreApplication::sendEvent(o, &event);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
reset();
|
||||||
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
|
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
|
||||||
index e931d1f5..9a0fe49d 100644
|
index e931d1f5..9a0fe49d 100644
|
||||||
--- a/src/client/qwaylandinputdevice.cpp
|
--- a/src/client/qwaylandinputdevice.cpp
|
||||||
@@ -1544,7 +1628,7 @@ index df1c94f2..050cfdc0 100644
|
|||||||
|
|
||||||
#if QT_CONFIG(cursor)
|
#if QT_CONFIG(cursor)
|
||||||
diff --git a/src/client/qwaylandshmbackingstore.cpp b/src/client/qwaylandshmbackingstore.cpp
|
diff --git a/src/client/qwaylandshmbackingstore.cpp b/src/client/qwaylandshmbackingstore.cpp
|
||||||
index dc7ff670..41cffdf7 100644
|
index dc7ff670..90e37e95 100644
|
||||||
--- a/src/client/qwaylandshmbackingstore.cpp
|
--- a/src/client/qwaylandshmbackingstore.cpp
|
||||||
+++ b/src/client/qwaylandshmbackingstore.cpp
|
+++ b/src/client/qwaylandshmbackingstore.cpp
|
||||||
@@ -52,6 +52,7 @@
|
@@ -52,6 +52,7 @@
|
||||||
@@ -1565,7 +1649,14 @@ index dc7ff670..41cffdf7 100644
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@@ -74,8 +78,10 @@ QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
|
@@ -68,14 +72,16 @@ QT_BEGIN_NAMESPACE
|
||||||
|
namespace QtWaylandClient {
|
||||||
|
|
||||||
|
QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
|
||||||
|
- const QSize &size, QImage::Format format, int scale)
|
||||||
|
+ const QSize &size, QImage::Format format, qreal scale)
|
||||||
|
{
|
||||||
|
int stride = size.width() * 4;
|
||||||
int alloc = stride * size.height();
|
int alloc = stride * size.height();
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
|
||||||
@@ -1578,8 +1669,39 @@ index dc7ff670..41cffdf7 100644
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
QScopedPointer<QFile> filePointer;
|
QScopedPointer<QFile> filePointer;
|
||||||
|
@@ -108,7 +114,7 @@ QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display,
|
||||||
|
QWaylandShm* shm = display->shm();
|
||||||
|
wl_shm_format wl_format = shm->formatFrom(format);
|
||||||
|
mImage = QImage(data, size.width(), size.height(), stride, format);
|
||||||
|
- mImage.setDevicePixelRatio(qreal(scale));
|
||||||
|
+ mImage.setDevicePixelRatio(scale);
|
||||||
|
|
||||||
|
mShmPool = wl_shm_create_pool(shm->object(), fd, alloc);
|
||||||
|
init(wl_shm_pool_create_buffer(mShmPool,0, size.width(), size.height(),
|
||||||
|
@@ -271,7 +277,7 @@ QWaylandShmBuffer *QWaylandShmBackingStore::getBuffer(const QSize &size)
|
||||||
|
void QWaylandShmBackingStore::resize(const QSize &size)
|
||||||
|
{
|
||||||
|
QMargins margins = windowDecorationMargins();
|
||||||
|
- int scale = waylandWindow()->scale();
|
||||||
|
+ qreal scale = waylandWindow()->scale();
|
||||||
|
QSize sizeWithMargins = (size + QSize(margins.left()+margins.right(),margins.top()+margins.bottom())) * scale;
|
||||||
|
|
||||||
|
// We look for a free buffer to draw into. If the buffer is not the last buffer we used,
|
||||||
|
diff --git a/src/client/qwaylandshmbackingstore_p.h b/src/client/qwaylandshmbackingstore_p.h
|
||||||
|
index e01632da..f3fae438 100644
|
||||||
|
--- a/src/client/qwaylandshmbackingstore_p.h
|
||||||
|
+++ b/src/client/qwaylandshmbackingstore_p.h
|
||||||
|
@@ -71,7 +71,7 @@ class QWaylandWindow;
|
||||||
|
class Q_WAYLAND_CLIENT_EXPORT QWaylandShmBuffer : public QWaylandBuffer {
|
||||||
|
public:
|
||||||
|
QWaylandShmBuffer(QWaylandDisplay *display,
|
||||||
|
- const QSize &size, QImage::Format format, int scale = 1);
|
||||||
|
+ const QSize &size, QImage::Format format, qreal scale = 1);
|
||||||
|
~QWaylandShmBuffer() override;
|
||||||
|
QSize size() const override { return mImage.size(); }
|
||||||
|
int scale() const override { return int(mImage.devicePixelRatio()); }
|
||||||
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
|
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
|
||||||
index df2dcdaa..3b700002 100644
|
index df2dcdaa..07d8f8f1 100644
|
||||||
--- a/src/client/qwaylandwindow.cpp
|
--- a/src/client/qwaylandwindow.cpp
|
||||||
+++ b/src/client/qwaylandwindow.cpp
|
+++ b/src/client/qwaylandwindow.cpp
|
||||||
@@ -76,7 +76,6 @@ QWaylandWindow *QWaylandWindow::mMouseGrab = nullptr;
|
@@ -76,7 +76,6 @@ QWaylandWindow *QWaylandWindow::mMouseGrab = nullptr;
|
||||||
@@ -1600,6 +1722,15 @@ index df2dcdaa..3b700002 100644
|
|||||||
delete mWindowDecoration;
|
delete mWindowDecoration;
|
||||||
|
|
||||||
if (mSurface)
|
if (mSurface)
|
||||||
|
@@ -189,7 +185,7 @@ void QWaylandWindow::initWindow()
|
||||||
|
// typically be integer 1 (normal-dpi) or 2 (high-dpi). Call set_buffer_scale()
|
||||||
|
// to inform the compositor that high-resolution buffers will be provided.
|
||||||
|
if (mDisplay->compositorVersion() >= 3)
|
||||||
|
- mSurface->set_buffer_scale(scale());
|
||||||
|
+ mSurface->set_buffer_scale(mScale);
|
||||||
|
|
||||||
|
if (QScreen *s = window()->screen())
|
||||||
|
setOrientationMask(s->orientationUpdateMask());
|
||||||
@@ -243,6 +239,7 @@ bool QWaylandWindow::shouldCreateSubSurface() const
|
@@ -243,6 +239,7 @@ bool QWaylandWindow::shouldCreateSubSurface() const
|
||||||
|
|
||||||
void QWaylandWindow::reset()
|
void QWaylandWindow::reset()
|
||||||
@@ -1731,29 +1862,39 @@ index df2dcdaa..3b700002 100644
|
|||||||
handleUpdate();
|
handleUpdate();
|
||||||
buffer->setBusy();
|
buffer->setBusy();
|
||||||
|
|
||||||
@@ -583,7 +572,11 @@ void QWaylandWindow::damage(const QRect &rect)
|
@@ -583,7 +572,16 @@ void QWaylandWindow::damage(const QRect &rect)
|
||||||
if (mSurface == nullptr)
|
if (mSurface == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
- mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
|
- mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
|
||||||
+ const int s = scale();
|
+ const qreal s = scale();
|
||||||
+ if (mDisplay->compositorVersion() >= 4)
|
+ if (mDisplay->compositorVersion() >= 4) {
|
||||||
+ mSurface->damage_buffer(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height());
|
+ const QRect bufferRect =
|
||||||
+ else
|
+ QRectF(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height())
|
||||||
|
+ .toAlignedRect();
|
||||||
|
+ mSurface->damage_buffer(bufferRect.x(), bufferRect.y(), bufferRect.width(),
|
||||||
|
+ bufferRect.height());
|
||||||
|
+ } else {
|
||||||
+ mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
|
+ mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
|
||||||
|
+ }
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWaylandWindow::safeCommit(QWaylandBuffer *buffer, const QRegion &damage)
|
void QWaylandWindow::safeCommit(QWaylandBuffer *buffer, const QRegion &damage)
|
||||||
@@ -619,8 +612,14 @@ void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage)
|
@@ -619,8 +617,19 @@ void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
attachOffset(buffer);
|
attachOffset(buffer);
|
||||||
- for (const QRect &rect: damage)
|
- for (const QRect &rect: damage)
|
||||||
- mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
|
- mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
|
||||||
+ if (mDisplay->compositorVersion() >= 4) {
|
+ if (mDisplay->compositorVersion() >= 4) {
|
||||||
+ const int s = scale();
|
+ const qreal s = scale();
|
||||||
+ for (const QRect &rect: damage)
|
+ for (const QRect &rect : damage) {
|
||||||
+ mSurface->damage_buffer(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height());
|
+ const QRect bufferRect =
|
||||||
|
+ QRectF(s * rect.x(), s * rect.y(), s * rect.width(), s * rect.height())
|
||||||
|
+ .toAlignedRect();
|
||||||
|
+ mSurface->damage_buffer(bufferRect.x(), bufferRect.y(), bufferRect.width(),
|
||||||
|
+ bufferRect.height());
|
||||||
|
+ }
|
||||||
+ } else {
|
+ } else {
|
||||||
+ for (const QRect &rect: damage)
|
+ for (const QRect &rect: damage)
|
||||||
+ mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
|
+ mSurface->damage(rect.x(), rect.y(), rect.width(), rect.height());
|
||||||
@@ -1761,7 +1902,7 @@ index df2dcdaa..3b700002 100644
|
|||||||
Q_ASSERT(!buffer->committed());
|
Q_ASSERT(!buffer->committed());
|
||||||
buffer->setCommitted();
|
buffer->setCommitted();
|
||||||
mSurface->commit();
|
mSurface->commit();
|
||||||
@@ -635,42 +634,53 @@ void QWaylandWindow::commit()
|
@@ -635,42 +644,53 @@ void QWaylandWindow::commit()
|
||||||
|
|
||||||
const wl_callback_listener QWaylandWindow::callbackListener = {
|
const wl_callback_listener QWaylandWindow::callbackListener = {
|
||||||
[](void *data, wl_callback *callback, uint32_t time) {
|
[](void *data, wl_callback *callback, uint32_t time) {
|
||||||
@@ -1832,7 +1973,7 @@ index df2dcdaa..3b700002 100644
|
|||||||
|
|
||||||
if (mWaitingForFrameCallback) {
|
if (mWaitingForFrameCallback) {
|
||||||
qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
|
qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
|
||||||
@@ -874,7 +884,11 @@ bool QWaylandWindow::createDecoration()
|
@@ -874,7 +894,11 @@ bool QWaylandWindow::createDecoration()
|
||||||
// size and are not redrawn, leaving the new buffer empty. As a simple
|
// size and are not redrawn, leaving the new buffer empty. As a simple
|
||||||
// work-around, we trigger a full extra update whenever the client-side
|
// work-around, we trigger a full extra update whenever the client-side
|
||||||
// window decorations are toggled while the window is showing.
|
// window decorations are toggled while the window is showing.
|
||||||
@@ -1845,7 +1986,7 @@ index df2dcdaa..3b700002 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
return mWindowDecoration;
|
return mWindowDecoration;
|
||||||
@@ -1028,8 +1042,17 @@ void QWaylandWindow::handleScreensChanged()
|
@@ -1028,8 +1052,17 @@ void QWaylandWindow::handleScreensChanged()
|
||||||
if (newScreen == mLastReportedScreen)
|
if (newScreen == mLastReportedScreen)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1863,7 +2004,25 @@ index df2dcdaa..3b700002 100644
|
|||||||
|
|
||||||
int scale = newScreen->isPlaceholder() ? 1 : static_cast<QWaylandScreen *>(newScreen)->scale();
|
int scale = newScreen->isPlaceholder() ? 1 : static_cast<QWaylandScreen *>(newScreen)->scale();
|
||||||
if (scale != mScale) {
|
if (scale != mScale) {
|
||||||
@@ -1101,10 +1124,18 @@ bool QWaylandWindow::setMouseGrabEnabled(bool grab)
|
@@ -1080,14 +1113,14 @@ bool QWaylandWindow::isActive() const
|
||||||
|
return mDisplay->isWindowActivated(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
-int QWaylandWindow::scale() const
|
||||||
|
+qreal QWaylandWindow::scale() const
|
||||||
|
{
|
||||||
|
- return mScale;
|
||||||
|
+ return devicePixelRatio();
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal QWaylandWindow::devicePixelRatio() const
|
||||||
|
{
|
||||||
|
- return mScale;
|
||||||
|
+ return qreal(mScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QWaylandWindow::setMouseGrabEnabled(bool grab)
|
||||||
|
@@ -1101,10 +1134,18 @@ bool QWaylandWindow::setMouseGrabEnabled(bool grab)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1883,7 +2042,7 @@ index df2dcdaa..3b700002 100644
|
|||||||
mLastReportedWindowStates = states;
|
mLastReportedWindowStates = states;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1146,19 +1177,24 @@ void QWaylandWindow::timerEvent(QTimerEvent *event)
|
@@ -1146,19 +1187,24 @@ void QWaylandWindow::timerEvent(QTimerEvent *event)
|
||||||
if (event->timerId() != mFrameCallbackCheckIntervalTimerId)
|
if (event->timerId() != mFrameCallbackCheckIntervalTimerId)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1919,7 +2078,7 @@ index df2dcdaa..3b700002 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
void QWaylandWindow::requestUpdate()
|
void QWaylandWindow::requestUpdate()
|
||||||
@@ -1167,8 +1203,11 @@ void QWaylandWindow::requestUpdate()
|
@@ -1167,8 +1213,11 @@ void QWaylandWindow::requestUpdate()
|
||||||
Q_ASSERT(hasPendingUpdateRequest()); // should be set by QPA
|
Q_ASSERT(hasPendingUpdateRequest()); // should be set by QPA
|
||||||
|
|
||||||
// If we have a frame callback all is good and will be taken care of there
|
// If we have a frame callback all is good and will be taken care of there
|
||||||
@@ -1933,7 +2092,7 @@ index df2dcdaa..3b700002 100644
|
|||||||
|
|
||||||
// If we've already called deliverUpdateRequest(), but haven't seen any attach+commit/swap yet
|
// If we've already called deliverUpdateRequest(), but haven't seen any attach+commit/swap yet
|
||||||
// This is a somewhat redundant behavior and might indicate a bug in the calling code, so log
|
// This is a somewhat redundant behavior and might indicate a bug in the calling code, so log
|
||||||
@@ -1181,7 +1220,12 @@ void QWaylandWindow::requestUpdate()
|
@@ -1181,7 +1230,12 @@ void QWaylandWindow::requestUpdate()
|
||||||
// so use invokeMethod to delay the delivery a bit.
|
// so use invokeMethod to delay the delivery a bit.
|
||||||
QMetaObject::invokeMethod(this, [this] {
|
QMetaObject::invokeMethod(this, [this] {
|
||||||
// Things might have changed in the meantime
|
// Things might have changed in the meantime
|
||||||
@@ -1947,7 +2106,7 @@ index df2dcdaa..3b700002 100644
|
|||||||
deliverUpdateRequest();
|
deliverUpdateRequest();
|
||||||
}, Qt::QueuedConnection);
|
}, Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
@@ -1192,19 +1236,18 @@ void QWaylandWindow::requestUpdate()
|
@@ -1192,19 +1246,18 @@ void QWaylandWindow::requestUpdate()
|
||||||
void QWaylandWindow::handleUpdate()
|
void QWaylandWindow::handleUpdate()
|
||||||
{
|
{
|
||||||
qCDebug(lcWaylandBackingstore) << "handleUpdate" << QThread::currentThread();
|
qCDebug(lcWaylandBackingstore) << "handleUpdate" << QThread::currentThread();
|
||||||
@@ -1972,7 +2131,7 @@ index df2dcdaa..3b700002 100644
|
|||||||
mFrameCallback = wl_surface_frame(wrappedSurface);
|
mFrameCallback = wl_surface_frame(wrappedSurface);
|
||||||
wl_proxy_wrapper_destroy(wrappedSurface);
|
wl_proxy_wrapper_destroy(wrappedSurface);
|
||||||
wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this);
|
wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this);
|
||||||
@@ -1214,6 +1257,8 @@ void QWaylandWindow::handleUpdate()
|
@@ -1214,6 +1267,8 @@ void QWaylandWindow::handleUpdate()
|
||||||
// Start a timer for handling the case when the compositor stops sending frame callbacks.
|
// Start a timer for handling the case when the compositor stops sending frame callbacks.
|
||||||
if (mFrameCallbackTimeout > 0) {
|
if (mFrameCallbackTimeout > 0) {
|
||||||
QMetaObject::invokeMethod(this, [this] {
|
QMetaObject::invokeMethod(this, [this] {
|
||||||
@@ -1981,7 +2140,7 @@ index df2dcdaa..3b700002 100644
|
|||||||
if (mWaitingForFrameCallback) {
|
if (mWaitingForFrameCallback) {
|
||||||
if (mFrameCallbackCheckIntervalTimerId < 0)
|
if (mFrameCallbackCheckIntervalTimerId < 0)
|
||||||
mFrameCallbackCheckIntervalTimerId = startTimer(mFrameCallbackTimeout);
|
mFrameCallbackCheckIntervalTimerId = startTimer(mFrameCallbackTimeout);
|
||||||
@@ -1274,6 +1319,20 @@ void QWaylandWindow::setOpaqueArea(const QRegion &opaqueArea)
|
@@ -1274,6 +1329,20 @@ void QWaylandWindow::setOpaqueArea(const QRegion &opaqueArea)
|
||||||
wl_region_destroy(region);
|
wl_region_destroy(region);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2003,7 +2162,7 @@ index df2dcdaa..3b700002 100644
|
|||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
|
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
|
||||||
index 01337cff..2f219d8c 100644
|
index 01337cff..741f9e5c 100644
|
||||||
--- a/src/client/qwaylandwindow_p.h
|
--- a/src/client/qwaylandwindow_p.h
|
||||||
+++ b/src/client/qwaylandwindow_p.h
|
+++ b/src/client/qwaylandwindow_p.h
|
||||||
@@ -98,6 +98,9 @@ public:
|
@@ -98,6 +98,9 @@ public:
|
||||||
@@ -2016,7 +2175,7 @@ index 01337cff..2f219d8c 100644
|
|||||||
virtual WindowType windowType() const = 0;
|
virtual WindowType windowType() const = 0;
|
||||||
virtual void ensureSize();
|
virtual void ensureSize();
|
||||||
WId winId() const override;
|
WId winId() const override;
|
||||||
@@ -148,6 +151,7 @@ public:
|
@@ -148,13 +151,14 @@ public:
|
||||||
void setWindowState(Qt::WindowStates states) override;
|
void setWindowState(Qt::WindowStates states) override;
|
||||||
void setWindowFlags(Qt::WindowFlags flags) override;
|
void setWindowFlags(Qt::WindowFlags flags) override;
|
||||||
void handleWindowStatesChanged(Qt::WindowStates states);
|
void handleWindowStatesChanged(Qt::WindowStates states);
|
||||||
@@ -2024,6 +2183,14 @@ index 01337cff..2f219d8c 100644
|
|||||||
|
|
||||||
void raise() override;
|
void raise() override;
|
||||||
void lower() override;
|
void lower() override;
|
||||||
|
|
||||||
|
void setMask(const QRegion ®ion) override;
|
||||||
|
|
||||||
|
- int scale() const;
|
||||||
|
+ qreal scale() const;
|
||||||
|
qreal devicePixelRatio() const override;
|
||||||
|
|
||||||
|
void requestActivateWindow() override;
|
||||||
@@ -206,6 +210,10 @@ public:
|
@@ -206,6 +210,10 @@ public:
|
||||||
void handleUpdate();
|
void handleUpdate();
|
||||||
void deliverUpdateRequest() override;
|
void deliverUpdateRequest() override;
|
||||||
@@ -2227,6 +2394,19 @@ index 6c8f04ec..94c56325 100644
|
|||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
|
||||||
|
index c1f45fa6..bbc63444 100644
|
||||||
|
--- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
|
||||||
|
+++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp
|
||||||
|
@@ -195,7 +195,7 @@ public:
|
||||||
|
QOpenGLTextureCache *cache = QOpenGLTextureCache::cacheForContext(m_context->context());
|
||||||
|
|
||||||
|
QSize surfaceSize = window->surfaceSize();
|
||||||
|
- int scale = window->scale() ;
|
||||||
|
+ qreal scale = window->scale() ;
|
||||||
|
glViewport(0, 0, surfaceSize.width() * scale, surfaceSize.height() * scale);
|
||||||
|
|
||||||
|
//Draw Decoration
|
||||||
diff --git a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h
|
diff --git a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h
|
||||||
index 56a710c3..c6a8b6c6 100644
|
index 56a710c3..c6a8b6c6 100644
|
||||||
--- a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h
|
--- a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabuf.h
|
||||||
|
|||||||
@@ -85,6 +85,13 @@
|
|||||||
</Package>
|
</Package>
|
||||||
|
|
||||||
<History>
|
<History>
|
||||||
|
<Update release="35">
|
||||||
|
<Date>2023-09-08</Date>
|
||||||
|
<Version>5.15.10</Version>
|
||||||
|
<Comment>Rebuild.</Comment>
|
||||||
|
<Name>Mustafa Cinasal</Name>
|
||||||
|
<Email>muscnsl@gmail.com</Email>
|
||||||
|
</Update>
|
||||||
<Update release="34">
|
<Update release="34">
|
||||||
<Date>2023-06-17</Date>
|
<Date>2023-06-17</Date>
|
||||||
<Version>5.15.10</Version>
|
<Version>5.15.10</Version>
|
||||||
|
|||||||
Reference in New Issue
Block a user