summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJohan Klokkhammer Helsing <johan.helsing@qt.io>2019-08-28 07:37:19 +0200
committerJohan Klokkhammer Helsing <johan.helsing@qt.io>2019-08-29 14:11:20 +0200
commitc4318f7b831778acf385cad99f33f000f2a9e045 (patch)
treef9411c6e86bbd9d446383bb9c5068612f441e801 /src
parentfc9c4a04d7359cb00a733c56cf85fc9737c9886d (diff)
parentf5a28afe4c2cb82540c94616e7a9e3e72e0e8327 (diff)
Merge remote-tracking branch 'origin/5.12' into 5.13
Conflicts: src/client/qwaylandinputdevice.cpp src/client/qwaylandintegration.cpp src/client/qwaylandwindow_p.h src/shared/qwaylandxkb.cpp Change-Id: Ibac7998502351e93c71c9b786536298657afe3d0
Diffstat (limited to 'src')
-rw-r--r--src/client/qwaylanddatadevice.cpp8
-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/qwaylandinputdevice.cpp13
-rw-r--r--src/client/qwaylandintegration.cpp39
-rw-r--r--src/client/qwaylandintegration_p.h2
-rw-r--r--src/client/qwaylandqtkey.cpp6
-rw-r--r--src/client/qwaylandscreen.cpp5
-rw-r--r--src/client/qwaylandwindow.cpp2
-rw-r--r--src/client/qwaylandwindow_p.h1
-rw-r--r--src/qtwaylandscanner/qtwaylandscanner.cpp11
-rw-r--r--src/shared/qwaylandsharedmemoryformathelper_p.h31
13 files changed, 117 insertions, 65 deletions
diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp
index 11984f9d3..6b2a408eb 100644
--- a/src/client/qwaylanddatadevice.cpp
+++ b/src/client/qwaylanddatadevice.cpp
@@ -154,9 +154,13 @@ void QWaylandDataDevice::data_device_drop()
void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface, wl_fixed_t x, wl_fixed_t y, wl_data_offer *id)
{
- m_enterSerial = serial;
- m_dragWindow = QWaylandWindow::fromWlSurface(surface)->window();
+ auto *dragWaylandWindow = QWaylandWindow::fromWlSurface(surface);
+ if (!dragWaylandWindow)
+ return; // Ignore foreign surfaces
+
+ m_dragWindow = dragWaylandWindow->window();
m_dragPoint = calculateDragPosition(x, y, m_dragWindow);
+ m_enterSerial = serial;
QMimeData *dragData = nullptr;
Qt::DropActions supportedActions;
diff --git a/src/client/qwaylanddataoffer.cpp b/src/client/qwaylanddataoffer.cpp
index 0c732c020..3da16ed00 100644
--- a/src/client/qwaylanddataoffer.cpp
+++ b/src/client/qwaylanddataoffer.cpp
@@ -135,7 +135,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();
}
@@ -158,23 +158,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 4a91c1c96..78524f6fc 100644
--- a/src/client/qwaylanddisplay.cpp
+++ b/src/client/qwaylanddisplay.cpp
@@ -186,9 +186,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));
}
}
@@ -198,25 +198,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()
@@ -245,10 +236,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 558d8d9b5..7cfbc19b8 100644
--- a/src/client/qwaylanddisplay_p.h
+++ b/src/client/qwaylanddisplay_p.h
@@ -201,7 +201,6 @@ public slots:
private:
void waitForScreens();
- void exitWithError();
void checkError() const;
void handleWaylandSync();
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index 9ee3c19d4..b5c18a074 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -562,6 +562,8 @@ void QWaylandInputDevice::Pointer::pointer_enter(uint32_t serial, struct wl_surf
return;
QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
+ if (!window)
+ return; // Ignore foreign surfaces
if (mFocus) {
qCWarning(lcQpaWayland) << "The compositor sent a wl_pointer.enter event before sending a"
@@ -569,6 +571,7 @@ void QWaylandInputDevice::Pointer::pointer_enter(uint32_t serial, struct wl_surf
<< "attempting to work around it by invalidating the current focus";
invalidateFocus();
}
+
mFocus = window;
connect(mFocus.data(), &QWaylandWindow::wlSurfaceDestroyed, this, &Pointer::handleFocusDestroyed);
@@ -597,6 +600,10 @@ void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surfac
if (!surface)
return;
+ auto *window = QWaylandWindow::fromWlSurface(surface);
+ if (!window)
+ return; // Ignore foreign surfaces
+
if (!QWaylandWindow::mouseGrab()) {
QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
window->handleMouseLeave(mParent);
@@ -972,9 +979,13 @@ void QWaylandInputDevice::Touch::touch_down(uint32_t serial,
if (!surface)
return;
+ auto *window = QWaylandWindow::fromWlSurface(surface);
+ if (!window)
+ return; // Ignore foreign surfaces
+
mParent->mTime = time;
mParent->mSerial = serial;
- mFocus = QWaylandWindow::fromWlSurface(surface);
+ mFocus = window;
mParent->mQDisplay->setLastInputDevice(mParent, serial, mFocus);
mParent->handleTouchPoint(id, wl_fixed_to_double(x), wl_fixed_to_double(y), Qt::TouchPointPressed);
}
diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp
index ea2b50b4a..85fcef43f 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 3aef2c4d9..a66999c7f 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/qwaylandqtkey.cpp b/src/client/qwaylandqtkey.cpp
index a60185bd6..192619738 100644
--- a/src/client/qwaylandqtkey.cpp
+++ b/src/client/qwaylandqtkey.cpp
@@ -70,7 +70,11 @@ void QWaylandQtKeyExtension::zqt_key_v1_key(struct wl_surface *surface,
}
QWaylandInputDevice *dev = inputDevices.first();
- QWaylandWindow *win = surface ? QWaylandWindow::fromWlSurface(surface) : dev->keyboardFocus();
+
+ auto *win = surface ? QWaylandWindow::fromWlSurface(surface) : nullptr;
+
+ if (!win)
+ win = dev->keyboardFocus();
if (!win || !win->window()) {
qWarning("qt_key_extension: handle_qtkey: No keyboard focus");
diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp
index 5b04ae609..d116a807b 100644
--- a/src/client/qwaylandscreen.cpp
+++ b/src/client/qwaylandscreen.cpp
@@ -217,8 +217,9 @@ QWaylandScreen * QWaylandScreen::waylandScreenFromWindow(QWindow *window)
QWaylandScreen *QWaylandScreen::fromWlOutput(::wl_output *output)
{
- auto wlOutput = static_cast<QtWayland::wl_output *>(wl_output_get_user_data(output));
- return static_cast<QWaylandScreen *>(wlOutput);
+ if (auto *o = QtWayland::wl_output::fromObject(output))
+ return static_cast<QWaylandScreen *>(o);
+ return nullptr;
}
void QWaylandScreen::output_mode(uint32_t flags, int width, int height, int refresh)
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index 7f82136fe..40289d814 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -199,7 +199,9 @@ void QWaylandWindow::initWindow()
void QWaylandWindow::initializeWlSurface()
{
+ Q_ASSERT(!isInitialized());
init(mDisplay->createSurface(static_cast<QtWayland::wl_surface *>(this)));
+ emit wlSurfaceCreated();
}
bool QWaylandWindow::shouldCreateShellSurface() const
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index 9eff738b8..9a1040288 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:
diff --git a/src/qtwaylandscanner/qtwaylandscanner.cpp b/src/qtwaylandscanner/qtwaylandscanner.cpp
index 56045e880..7f3dc5ad6 100644
--- a/src/qtwaylandscanner/qtwaylandscanner.cpp
+++ b/src/qtwaylandscanner/qtwaylandscanner.cpp
@@ -986,6 +986,7 @@ bool Scanner::process()
printf("\n");
printf(" struct ::%s *object() { return m_%s; }\n", interfaceName, interfaceName);
printf(" const struct ::%s *object() const { return m_%s; }\n", interfaceName, interfaceName);
+ printf(" static %s *fromObject(struct ::%s *object);\n", interfaceName, interfaceName);
printf("\n");
printf(" bool isInitialized() const;\n");
printf("\n");
@@ -1130,6 +1131,16 @@ bool Scanner::process()
printf(" }\n");
printf("\n");
+ printf(" %s *%s::fromObject(struct ::%s *object)\n", interfaceName, interfaceName, interfaceName);
+ printf(" {\n");
+ if (hasEvents) {
+ printf(" if (wl_proxy_get_listener((struct ::wl_proxy *)object) != (void *)&m_%s_listener)\n", interfaceName);
+ printf(" return nullptr;\n");
+ }
+ printf(" return static_cast<%s *>(%s_get_user_data(object));\n", interfaceName, interfaceName);
+ printf(" }\n");
+ printf("\n");
+
printf(" bool %s::isInitialized() const\n", interfaceName);
printf(" {\n");
printf(" return m_%s != nullptr;\n", interfaceName);
diff --git a/src/shared/qwaylandsharedmemoryformathelper_p.h b/src/shared/qwaylandsharedmemoryformathelper_p.h
index 85905c02f..72cc8401c 100644
--- a/src/shared/qwaylandsharedmemoryformathelper_p.h
+++ b/src/shared/qwaylandsharedmemoryformathelper_p.h
@@ -51,7 +51,26 @@ class QWaylandSharedMemoryFormatHelper
{
public:
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();
private:
@@ -108,16 +127,6 @@ wl_shm_format QWaylandSharedMemoryFormatHelper::fromQImageFormat(QImage::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> retFormats;