diff options
author | Johan Klokkhammer Helsing <johan.helsing@qt.io> | 2019-08-28 07:37:19 +0200 |
---|---|---|
committer | Johan Klokkhammer Helsing <johan.helsing@qt.io> | 2019-08-29 15:03:23 +0200 |
commit | cd2c3a8916a9cc7ab31f6e18e6f1510a048f4ace (patch) | |
tree | 3477c30d459905b8a68feb9abd64cc36082eeba0 | |
parent | 8751c06eceee400bc4b92f2a8f51d6381cbc7ee5 (diff) | |
parent | c4318f7b831778acf385cad99f33f000f2a9e045 (diff) | |
download | qtwayland-cd2c3a8916a9cc7ab31f6e18e6f1510a048f4ace.tar.gz |
Merge "Merge remote-tracking branch 'origin/5.12' into 5.13"
-rw-r--r-- | src/client/qwaylanddatadevice.cpp | 8 | ||||
-rw-r--r-- | src/client/qwaylanddataoffer.cpp | 41 | ||||
-rw-r--r-- | src/client/qwaylanddisplay.cpp | 22 | ||||
-rw-r--r-- | src/client/qwaylanddisplay_p.h | 1 | ||||
-rw-r--r-- | src/client/qwaylandinputdevice.cpp | 13 | ||||
-rw-r--r-- | src/client/qwaylandintegration.cpp | 39 | ||||
-rw-r--r-- | src/client/qwaylandintegration_p.h | 2 | ||||
-rw-r--r-- | src/client/qwaylandqtkey.cpp | 6 | ||||
-rw-r--r-- | src/client/qwaylandscreen.cpp | 5 | ||||
-rw-r--r-- | src/client/qwaylandwindow.cpp | 2 | ||||
-rw-r--r-- | src/client/qwaylandwindow_p.h | 1 | ||||
-rw-r--r-- | src/qtwaylandscanner/qtwaylandscanner.cpp | 11 | ||||
-rw-r--r-- | src/shared/qwaylandsharedmemoryformathelper_p.h | 31 |
13 files changed, 117 insertions, 65 deletions
diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp index 11984f9d..6b2a408e 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 0c732c02..3da16ed0 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 4a91c1c9..78524f6f 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 558d8d9b..7cfbc19b 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 9ee3c19d..b5c18a07 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 ea2b50b4..85fcef43 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/qwaylandqtkey.cpp b/src/client/qwaylandqtkey.cpp index a60185bd..19261973 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 5b04ae60..d116a807 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 7f82136f..40289d81 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 9eff738b..9a104028 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 56045e88..7f3dc5ad 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 85905c02..72cc8401 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; |