Merge remote-tracking branch 'origin/5.15' into dev

Change-Id: I416564cb07c9b3e9d88c7924abc44e3947b6ab4f
This commit is contained in:
Qt Forward Merge Bot 2019-09-17 03:07:23 +02:00
commit 5d790b82f6
11 changed files with 91 additions and 63 deletions

View File

@ -141,7 +141,7 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T
} }
int pipefd[2]; int pipefd[2];
if (qt_safe_pipe(pipefd, O_NONBLOCK) == -1) { if (qt_safe_pipe(pipefd) == -1) {
qWarning("QWaylandMimeData: pipe2() failed"); qWarning("QWaylandMimeData: pipe2() failed");
return QVariant(); return QVariant();
} }
@ -163,23 +163,32 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T
int QWaylandMimeData::readData(int fd, QByteArray &data) const int QWaylandMimeData::readData(int fd, QByteArray &data) const
{ {
char buf[4096]; fd_set readset;
int retryCount = 0; FD_ZERO(&readset);
int n; FD_SET(fd, &readset);
while (true) { struct timeval timeout;
n = QT_READ(fd, buf, sizeof buf); timeout.tv_sec = 1;
if (n == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && ++retryCount < 1000) timeout.tv_usec = 0;
usleep(1000);
else int ready = select(FD_SETSIZE, &readset, nullptr, nullptr, &timeout);
break; if (ready < 0) {
} qWarning() << "QWaylandDataOffer: select() failed";
if (retryCount >= 1000) return -1;
} else if (ready == 0) {
qWarning("QWaylandDataOffer: timeout reading from pipe"); qWarning("QWaylandDataOffer: timeout reading from pipe");
if (n > 0) { return -1;
data.append(buf, n); } else {
n = readData(fd, data); char buf[4096];
int n = QT_READ(fd, buf, sizeof buf);
if (n > 0) {
data.append(buf, n);
n = readData(fd, data);
} else if (n < 0) {
qWarning("QWaylandDataOffer: read() failed");
}
return n;
} }
return n;
} }
} }

View File

@ -189,9 +189,9 @@ void QWaylandDisplay::checkError() const
int ecode = wl_display_get_error(mDisplay); int ecode = wl_display_get_error(mDisplay);
if ((ecode == EPIPE || ecode == ECONNRESET)) { if ((ecode == EPIPE || ecode == ECONNRESET)) {
// special case this to provide a nicer error // special case this to provide a nicer error
qWarning("The Wayland connection broke. Did the Wayland compositor die?"); qFatal("The Wayland connection broke. Did the Wayland compositor die?");
} else { } else {
qErrnoWarning(ecode, "The Wayland connection experienced a fatal error"); qFatal("The Wayland connection experienced a fatal error: %s", strerror(ecode));
} }
} }
@ -201,25 +201,16 @@ void QWaylandDisplay::flushRequests()
wl_display_read_events(mDisplay); wl_display_read_events(mDisplay);
} }
if (wl_display_dispatch_pending(mDisplay) < 0) { if (wl_display_dispatch_pending(mDisplay) < 0)
checkError(); checkError();
exitWithError();
}
wl_display_flush(mDisplay); wl_display_flush(mDisplay);
} }
void QWaylandDisplay::blockingReadEvents() void QWaylandDisplay::blockingReadEvents()
{ {
if (wl_display_dispatch(mDisplay) < 0) { if (wl_display_dispatch(mDisplay) < 0)
checkError(); checkError();
exitWithError();
}
}
void QWaylandDisplay::exitWithError()
{
::exit(1);
} }
wl_event_queue *QWaylandDisplay::createEventQueue() wl_event_queue *QWaylandDisplay::createEventQueue()
@ -248,10 +239,9 @@ void QWaylandDisplay::dispatchQueueWhile(wl_event_queue *queue, std::function<bo
else else
wl_display_cancel_read(mDisplay); wl_display_cancel_read(mDisplay);
if (wl_display_dispatch_queue_pending(mDisplay, queue) < 0) { if (wl_display_dispatch_queue_pending(mDisplay, queue) < 0)
checkError(); checkError();
exitWithError();
}
if (!condition()) if (!condition())
break; break;
} }

View File

@ -208,7 +208,6 @@ public slots:
private: private:
void waitForScreens(); void waitForScreens();
void exitWithError();
void checkError() const; void checkError() const;
void handleWaylandSync(); void handleWaylandSync();

View File

@ -1045,8 +1045,15 @@ void QWaylandInputDevice::Pointer::flushScrollEvent()
void QWaylandInputDevice::Pointer::flushFrameEvent() void QWaylandInputDevice::Pointer::flushFrameEvent()
{ {
if (mFrameData.event) { if (auto *event = mFrameData.event) {
mFrameData.event->surface->handleMouse(mParent, *mFrameData.event); if (auto window = event->surface) {
window->handleMouse(mParent, *event);
} else if (mFrameData.event->type == QWaylandPointerEvent::Type::Release) {
// If the window has been destroyed, we still need to report an up event, but it can't
// be handled by the destroyed window (obviously), so send the event here instead.
QWindowSystemInterface::handleMouseEvent(nullptr, event->timestamp, event->local,
event->global, event->buttons, event->modifiers);
}
delete mFrameData.event; delete mFrameData.event;
mFrameData.event = nullptr; mFrameData.event = nullptr;
} }

View File

@ -446,7 +446,7 @@ public:
QPoint pixelDelta; QPoint pixelDelta;
QPoint angleDelta; QPoint angleDelta;
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized; Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;
QWaylandWindow *surface = nullptr; QPointer<QWaylandWindow> surface;
}; };
} }

View File

@ -310,11 +310,14 @@ QPlatformTheme *QWaylandIntegration::createPlatformTheme(const QString &name) co
return GenericWaylandTheme::createUnixTheme(name); return GenericWaylandTheme::createUnixTheme(name);
} }
// May be called from non-GUI threads
QWaylandClientBufferIntegration *QWaylandIntegration::clientBufferIntegration() const QWaylandClientBufferIntegration *QWaylandIntegration::clientBufferIntegration() const
{ {
if (!mClientBufferIntegrationInitialized) // Do an inexpensive check first to avoid locking whenever possible
if (Q_UNLIKELY(!mClientBufferIntegrationInitialized))
const_cast<QWaylandIntegration *>(this)->initializeClientBufferIntegration(); const_cast<QWaylandIntegration *>(this)->initializeClientBufferIntegration();
Q_ASSERT(mClientBufferIntegrationInitialized);
return mClientBufferIntegration && mClientBufferIntegration->isValid() ? mClientBufferIntegration.data() : nullptr; return mClientBufferIntegration && mClientBufferIntegration->isValid() ? mClientBufferIntegration.data() : nullptr;
} }
@ -334,9 +337,12 @@ QWaylandShellIntegration *QWaylandIntegration::shellIntegration() const
return mShellIntegration.data(); return mShellIntegration.data();
} }
// May be called from non-GUI threads
void QWaylandIntegration::initializeClientBufferIntegration() void QWaylandIntegration::initializeClientBufferIntegration()
{ {
mClientBufferIntegrationInitialized = true; QMutexLocker lock(&mClientBufferInitLock);
if (mClientBufferIntegrationInitialized)
return;
QString targetKey = QString::fromLocal8Bit(qgetenv("QT_WAYLAND_CLIENT_BUFFER_INTEGRATION")); QString targetKey = QString::fromLocal8Bit(qgetenv("QT_WAYLAND_CLIENT_BUFFER_INTEGRATION"));
@ -352,22 +358,25 @@ void QWaylandIntegration::initializeClientBufferIntegration()
if (targetKey.isEmpty()) { if (targetKey.isEmpty()) {
qWarning("Failed to determine what client buffer integration to use"); qWarning("Failed to determine what client buffer integration to use");
return;
}
QStringList keys = QWaylandClientBufferIntegrationFactory::keys();
qCDebug(lcQpaWayland) << "Available client buffer integrations:" << keys;
if (keys.contains(targetKey))
mClientBufferIntegration.reset(QWaylandClientBufferIntegrationFactory::create(targetKey, QStringList()));
if (mClientBufferIntegration) {
qCDebug(lcQpaWayland) << "Initializing client buffer integration" << targetKey;
mClientBufferIntegration->initialize(mDisplay.data());
} else { } else {
qCWarning(lcQpaWayland) << "Failed to load client buffer integration:" << targetKey; QStringList keys = QWaylandClientBufferIntegrationFactory::keys();
qCWarning(lcQpaWayland) << "Available client buffer integrations:" << keys; qCDebug(lcQpaWayland) << "Available client buffer integrations:" << keys;
if (keys.contains(targetKey))
mClientBufferIntegration.reset(QWaylandClientBufferIntegrationFactory::create(targetKey, QStringList()));
if (mClientBufferIntegration) {
qCDebug(lcQpaWayland) << "Initializing client buffer integration" << targetKey;
mClientBufferIntegration->initialize(mDisplay.data());
} else {
qCWarning(lcQpaWayland) << "Failed to load client buffer integration:" << targetKey;
qCWarning(lcQpaWayland) << "Available client buffer integrations:" << keys;
}
} }
// This must be set last to make sure other threads don't use the
// integration before initialization is complete.
mClientBufferIntegrationInitialized = true;
} }
void QWaylandIntegration::initializeServerBufferIntegration() void QWaylandIntegration::initializeServerBufferIntegration()

View File

@ -54,6 +54,7 @@
#include <QtWaylandClient/qtwaylandclientglobal.h> #include <QtWaylandClient/qtwaylandclientglobal.h>
#include <qpa/qplatformintegration.h> #include <qpa/qplatformintegration.h>
#include <QtCore/QScopedPointer> #include <QtCore/QScopedPointer>
#include <QtCore/QMutex>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -152,6 +153,7 @@ private:
mutable QScopedPointer<QPlatformAccessibility> mAccessibility; mutable QScopedPointer<QPlatformAccessibility> mAccessibility;
#endif #endif
bool mFailed = false; bool mFailed = false;
QMutex mClientBufferInitLock;
bool mClientBufferIntegrationInitialized = false; bool mClientBufferIntegrationInitialized = false;
bool mServerBufferIntegrationInitialized = false; bool mServerBufferIntegrationInitialized = false;
bool mShellIntegrationInitialized = false; bool mShellIntegrationInitialized = false;

View File

@ -205,6 +205,7 @@ void QWaylandWindow::initializeWlSurface()
connect(mSurface.data(), &QWaylandSurface::screensChanged, connect(mSurface.data(), &QWaylandSurface::screensChanged,
this, &QWaylandWindow::handleScreensChanged); this, &QWaylandWindow::handleScreensChanged);
mSurface->m_window = this; mSurface->m_window = this;
emit wlSurfaceCreated();
} }
bool QWaylandWindow::shouldCreateShellSurface() const bool QWaylandWindow::shouldCreateShellSurface() const

View File

@ -203,6 +203,7 @@ public slots:
void applyConfigure(); void applyConfigure();
signals: signals:
void wlSurfaceCreated();
void wlSurfaceDestroyed(); void wlSurfaceDestroyed();
protected: protected:

View File

@ -51,7 +51,26 @@ class QWaylandSharedMemoryFormatHelper
{ {
public: public:
static inline wl_shm_format fromQImageFormat(QImage::Format format); static inline wl_shm_format fromQImageFormat(QImage::Format format);
static inline QImage::Format fromWaylandShmFormat(wl_shm_format format); static inline QImage::Format fromWaylandShmFormat(wl_shm_format format)
{
switch (format) {
case WL_SHM_FORMAT_XRGB8888: return QImage::Format_RGB32;
case WL_SHM_FORMAT_ARGB8888: return QImage::Format_ARGB32_Premultiplied;
case WL_SHM_FORMAT_RGB565: return QImage::Format_RGB16;
case WL_SHM_FORMAT_XRGB1555: return QImage::Format_RGB555;
case WL_SHM_FORMAT_RGB888: return QImage::Format_RGB888;
case WL_SHM_FORMAT_XRGB4444: return QImage::Format_RGB444;
case WL_SHM_FORMAT_ARGB4444: return QImage::Format_ARGB4444_Premultiplied;
case WL_SHM_FORMAT_XBGR8888: return QImage::Format_RGBX8888;
case WL_SHM_FORMAT_ABGR8888: return QImage::Format_RGBA8888_Premultiplied;
case WL_SHM_FORMAT_XBGR2101010: return QImage::Format_BGR30;
case WL_SHM_FORMAT_ABGR2101010: return QImage::Format_A2BGR30_Premultiplied;
case WL_SHM_FORMAT_XRGB2101010: return QImage::Format_RGB30;
case WL_SHM_FORMAT_ARGB2101010: return QImage::Format_A2RGB30_Premultiplied;
case WL_SHM_FORMAT_C8: return QImage::Format_Alpha8;
default: return QImage::Format_Invalid;
}
}
static inline QVector<wl_shm_format> supportedWaylandFormats(); static inline QVector<wl_shm_format> supportedWaylandFormats();
private: private:
@ -108,16 +127,6 @@ wl_shm_format QWaylandSharedMemoryFormatHelper::fromQImageFormat(QImage::Format
return array.data[format]; return array.data[format];
} }
QImage::Format QWaylandSharedMemoryFormatHelper::fromWaylandShmFormat(wl_shm_format format)
{
Array array = getData();
for (size_t i = 0; i < array.size; i++) {
if (array.data[i] == format)
return QImage::Format(i);
}
return QImage::Format_Invalid;
}
QVector<wl_shm_format> QWaylandSharedMemoryFormatHelper::supportedWaylandFormats() QVector<wl_shm_format> QWaylandSharedMemoryFormatHelper::supportedWaylandFormats()
{ {
QVector<wl_shm_format> retFormats; QVector<wl_shm_format> retFormats;

View File

@ -85,6 +85,7 @@ public:
int main(int argc, char **argv) \ int main(int argc, char **argv) \
{ \ { \
setenv("XDG_RUNTIME_DIR", ".", 1); \ setenv("XDG_RUNTIME_DIR", ".", 1); \
setenv("XDG_CURRENT_DESKTOP", "qtwaylandtests", 1); \
setenv("QT_QPA_PLATFORM", "wayland", 1); \ setenv("QT_QPA_PLATFORM", "wayland", 1); \
test tc; \ test tc; \
QGuiApplication app(argc, argv); \ QGuiApplication app(argc, argv); \