summaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
authorJohan Klokkhammer Helsing <johan.helsing@qt.io>2019-09-03 03:01:35 +0200
committerJohan Klokkhammer Helsing <johan.helsing@qt.io>2019-09-03 07:24:14 +0200
commit9f02bfedfe3b6b0b19d7c7a684a33b7544c84111 (patch)
tree89ecc4e3c982338363540384aa895f6949630e89 /src/client
parentf3668f88ccad6341280fbe2ca493562f80e76955 (diff)
parentcd2c3a8916a9cc7ab31f6e18e6f1510a048f4ace (diff)
downloadqtwayland-9f02bfedfe3b6b0b19d7c7a684a33b7544c84111.tar.gz
Merge remote-tracking branch 'origin/5.13' into 5.14
Conflicts: src/client/qwaylandinputdevice.cpp src/client/qwaylandwindow.cpp Change-Id: Ifd64debc484197829d2fe412afa98c29b382efa5
Diffstat (limited to 'src/client')
-rw-r--r--src/client/qwaylanddataoffer.cpp41
-rw-r--r--src/client/qwaylanddisplay.cpp22
-rw-r--r--src/client/qwaylanddisplay_p.h1
-rw-r--r--src/client/qwaylandintegration.cpp39
-rw-r--r--src/client/qwaylandintegration_p.h2
-rw-r--r--src/client/qwaylandwindow.cpp1
-rw-r--r--src/client/qwaylandwindow_p.h1
7 files changed, 59 insertions, 48 deletions
diff --git a/src/client/qwaylanddataoffer.cpp b/src/client/qwaylanddataoffer.cpp
index e31e1220..4c06277f 100644
--- a/src/client/qwaylanddataoffer.cpp
+++ b/src/client/qwaylanddataoffer.cpp
@@ -141,7 +141,7 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T
}
int pipefd[2];
- if (qt_safe_pipe(pipefd, O_NONBLOCK) == -1) {
+ if (qt_safe_pipe(pipefd) == -1) {
qWarning("QWaylandMimeData: pipe2() failed");
return QVariant();
}
@@ -163,23 +163,32 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T
int QWaylandMimeData::readData(int fd, QByteArray &data) const
{
- char buf[4096];
- int retryCount = 0;
- int n;
- while (true) {
- n = QT_READ(fd, buf, sizeof buf);
- if (n == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && ++retryCount < 1000)
- usleep(1000);
- else
- break;
- }
- if (retryCount >= 1000)
+ fd_set readset;
+ FD_ZERO(&readset);
+ FD_SET(fd, &readset);
+ struct timeval timeout;
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+
+ int ready = select(FD_SETSIZE, &readset, nullptr, nullptr, &timeout);
+ if (ready < 0) {
+ qWarning() << "QWaylandDataOffer: select() failed";
+ return -1;
+ } else if (ready == 0) {
qWarning("QWaylandDataOffer: timeout reading from pipe");
- if (n > 0) {
- data.append(buf, n);
- n = readData(fd, data);
+ return -1;
+ } else {
+ 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;
}
}
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
index cb4f190a..a17e8917 100644
--- a/src/client/qwaylanddisplay.cpp
+++ b/src/client/qwaylanddisplay.cpp
@@ -189,9 +189,9 @@ void QWaylandDisplay::checkError() const
int ecode = wl_display_get_error(mDisplay);
if ((ecode == EPIPE || ecode == ECONNRESET)) {
// 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 {
- 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);
}
- if (wl_display_dispatch_pending(mDisplay) < 0) {
+ if (wl_display_dispatch_pending(mDisplay) < 0)
checkError();
- exitWithError();
- }
wl_display_flush(mDisplay);
}
void QWaylandDisplay::blockingReadEvents()
{
- if (wl_display_dispatch(mDisplay) < 0) {
+ if (wl_display_dispatch(mDisplay) < 0)
checkError();
- exitWithError();
- }
-}
-
-void QWaylandDisplay::exitWithError()
-{
- ::exit(1);
}
wl_event_queue *QWaylandDisplay::createEventQueue()
@@ -248,10 +239,9 @@ void QWaylandDisplay::dispatchQueueWhile(wl_event_queue *queue, std::function<bo
else
wl_display_cancel_read(mDisplay);
- if (wl_display_dispatch_queue_pending(mDisplay, queue) < 0) {
+ if (wl_display_dispatch_queue_pending(mDisplay, queue) < 0)
checkError();
- exitWithError();
- }
+
if (!condition())
break;
}
diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h
index 1f085e67..14bb7719 100644
--- a/src/client/qwaylanddisplay_p.h
+++ b/src/client/qwaylanddisplay_p.h
@@ -208,7 +208,6 @@ public slots:
private:
void waitForScreens();
- void exitWithError();
void checkError() const;
void handleWaylandSync();
diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp
index 7f79d6b9..f6a80e18 100644
--- a/src/client/qwaylandintegration.cpp
+++ b/src/client/qwaylandintegration.cpp
@@ -310,11 +310,14 @@ QPlatformTheme *QWaylandIntegration::createPlatformTheme(const QString &name) co
return GenericWaylandTheme::createUnixTheme(name);
}
+// May be called from non-GUI threads
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();
+ Q_ASSERT(mClientBufferIntegrationInitialized);
return mClientBufferIntegration && mClientBufferIntegration->isValid() ? mClientBufferIntegration.data() : nullptr;
}
@@ -334,9 +337,12 @@ QWaylandShellIntegration *QWaylandIntegration::shellIntegration() const
return mShellIntegration.data();
}
+// May be called from non-GUI threads
void QWaylandIntegration::initializeClientBufferIntegration()
{
- mClientBufferIntegrationInitialized = true;
+ QMutexLocker lock(&mClientBufferInitLock);
+ if (mClientBufferIntegrationInitialized)
+ return;
QString targetKey = QString::fromLocal8Bit(qgetenv("QT_WAYLAND_CLIENT_BUFFER_INTEGRATION"));
@@ -352,22 +358,25 @@ void QWaylandIntegration::initializeClientBufferIntegration()
if (targetKey.isEmpty()) {
qWarning("Failed to determine what client buffer integration to use");
- return;
- }
-
- QStringList keys = QWaylandClientBufferIntegrationFactory::keys();
- qCDebug(lcQpaWayland) << "Available client buffer integrations:" << keys;
+ } else {
+ QStringList keys = QWaylandClientBufferIntegrationFactory::keys();
+ qCDebug(lcQpaWayland) << "Available client buffer integrations:" << keys;
- if (keys.contains(targetKey))
- mClientBufferIntegration.reset(QWaylandClientBufferIntegrationFactory::create(targetKey, QStringList()));
+ 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;
+ 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()
diff --git a/src/client/qwaylandintegration_p.h b/src/client/qwaylandintegration_p.h
index 3aef2c4d..a66999c7 100644
--- a/src/client/qwaylandintegration_p.h
+++ b/src/client/qwaylandintegration_p.h
@@ -54,6 +54,7 @@
#include <QtWaylandClient/qtwaylandclientglobal.h>
#include <qpa/qplatformintegration.h>
#include <QtCore/QScopedPointer>
+#include <QtCore/QMutex>
QT_BEGIN_NAMESPACE
@@ -152,6 +153,7 @@ private:
mutable QScopedPointer<QPlatformAccessibility> mAccessibility;
#endif
bool mFailed = false;
+ QMutex mClientBufferInitLock;
bool mClientBufferIntegrationInitialized = false;
bool mServerBufferIntegrationInitialized = false;
bool mShellIntegrationInitialized = false;
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index ce58003c..60317cda 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -205,6 +205,7 @@ void QWaylandWindow::initializeWlSurface()
connect(mSurface.data(), &QWaylandSurface::screensChanged,
this, &QWaylandWindow::handleScreensChanged);
mSurface->m_window = this;
+ emit wlSurfaceCreated();
}
bool QWaylandWindow::shouldCreateShellSurface() const
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index 8d8565d7..471ace4c 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -203,6 +203,7 @@ public slots:
void applyConfigure();
signals:
+ void wlSurfaceCreated();
void wlSurfaceDestroyed();
protected: