diff options
Diffstat (limited to 'source/l/qt5/patches/24.diff')
-rw-r--r-- | source/l/qt5/patches/24.diff | 585 |
1 files changed, 0 insertions, 585 deletions
diff --git a/source/l/qt5/patches/24.diff b/source/l/qt5/patches/24.diff deleted file mode 100644 index 5921881b7..000000000 --- a/source/l/qt5/patches/24.diff +++ /dev/null @@ -1,585 +0,0 @@ -diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp -index ea344c61c3a4643f7c725a6287f20d742b210d24..a7ce280a5df538917758e50ba8d2ee117378d546 100644 ---- a/src/client/qwaylanddisplay.cpp -+++ b/src/client/qwaylanddisplay.cpp -@@ -85,10 +85,203 @@ - - #include <errno.h> - -+#include <tuple> // for std::tie -+ -+static void checkWaylandError(struct wl_display *display) -+{ -+ int ecode = wl_display_get_error(display); -+ if ((ecode == EPIPE || ecode == ECONNRESET)) { -+ // special case this to provide a nicer error -+ qWarning("The Wayland connection broke. Did the Wayland compositor die?"); -+ } else { -+ qWarning("The Wayland connection experienced a fatal error: %s", strerror(ecode)); -+ } -+ _exit(1); -+} -+ - QT_BEGIN_NAMESPACE - - namespace QtWaylandClient { - -+class EventThread : public QThread -+{ -+ Q_OBJECT -+public: -+ enum OperatingMode { -+ EmitToDispatch, // Emit the signal, allow dispatching in a differnt thread. -+ SelfDispatch, // Dispatch the events inside this thread. -+ }; -+ -+ EventThread(struct wl_display * wl, struct wl_event_queue * ev_queue, -+ OperatingMode mode) -+ : m_fd(wl_display_get_fd(wl)) -+ , m_pipefd{ -1, -1 } -+ , m_wldisplay(wl) -+ , m_wlevqueue(ev_queue) -+ , m_mode(mode) -+ , m_reading(true) -+ , m_quitting(false) -+ { -+ setObjectName(QStringLiteral("WaylandEventThread")); -+ } -+ -+ void readAndDispatchEvents() -+ { -+ /* -+ * Dispatch pending events and flush the requests at least once. If the event thread -+ * is not reading, try to call _prepare_read() to allow the event thread to poll(). -+ * If that fails, re-try dispatch & flush again until _prepare_read() is successful. -+ * -+ * This allow any call to readAndDispatchEvents() to start event thread's polling, -+ * not only the one issued from event thread's waitForReading(), which means functions -+ * called from dispatch_pending() can safely spin an event loop. -+ */ -+ for (;;) { -+ if (dispatchQueuePending() < 0) { -+ checkWaylandError(m_wldisplay); -+ return; -+ } -+ -+ wl_display_flush(m_wldisplay); -+ -+ // We have to check if event thread is reading every time we dispatch -+ // something, as that may recursively call this function. -+ if (m_reading.loadAcquire()) -+ break; -+ -+ if (prepareReadQueue() == 0) { -+ QMutexLocker l(&m_mutex); -+ m_reading.storeRelease(true); -+ m_cond.wakeOne(); -+ break; -+ } -+ } -+ } -+ -+ void stop() -+ { -+ // We have to both write to the pipe and set the flag, as the thread may be -+ // either in the poll() or waiting for _prepare_read(). -+ if (m_pipefd[1] != -1 && write(m_pipefd[1], "\0", 1) == -1) -+ qWarning("Failed to write to the pipe: %s.", strerror(errno)); -+ -+ { -+ QMutexLocker l(&m_mutex); -+ m_quitting = true; -+ m_cond.wakeOne(); -+ } -+ -+ wait(); -+ } -+ -+Q_SIGNALS: -+ void needReadAndDispatch(); -+ -+protected: -+ void run() override -+ { -+ // we use this pipe to make the loop exit otherwise if we simply used a flag on the loop condition, if stop() gets -+ // called while poll() is blocking the thread will never quit since there are no wayland messages coming anymore. -+ struct Pipe -+ { -+ Pipe(int *fds) -+ : fds(fds) -+ { -+ if (qt_safe_pipe(fds) != 0) -+ qWarning("Pipe creation failed. Quitting may hang."); -+ } -+ ~Pipe() -+ { -+ if (fds[0] != -1) { -+ close(fds[0]); -+ close(fds[1]); -+ } -+ } -+ -+ int *fds; -+ } pipe(m_pipefd); -+ -+ // Make the main thread call wl_prepare_read(), dispatch the pending messages and flush the -+ // outbound ones. Wait until it's done before proceeding, unless we're told to quit. -+ while (waitForReading()) { -+ pollfd fds[2] = { { m_fd, POLLIN, 0 }, { m_pipefd[0], POLLIN, 0 } }; -+ poll(fds, 2, -1); -+ -+ if (fds[1].revents & POLLIN) { -+ // we don't really care to read the byte that was written here since we're closing down -+ wl_display_cancel_read(m_wldisplay); -+ break; -+ } -+ -+ if (fds[0].revents & POLLIN) -+ wl_display_read_events(m_wldisplay); -+ // The polll was succesfull and the event thread did the wl_display_read_events(). On the next iteration of the loop -+ // the event sent to the main thread will cause it to dispatch the messages just read, unless the loop exits in which -+ // case we don't care anymore about them. -+ else -+ wl_display_cancel_read(m_wldisplay); -+ } -+ } -+ -+private: -+ bool waitForReading() -+ { -+ Q_ASSERT(QThread::currentThread() == this); -+ -+ m_reading.storeRelease(false); -+ -+ if (m_mode == SelfDispatch) { -+ readAndDispatchEvents(); -+ } else { -+ Q_EMIT needReadAndDispatch(); -+ -+ QMutexLocker lock(&m_mutex); -+ // m_reading might be set from our emit or some other invocation of -+ // readAndDispatchEvents(). -+ while (!m_reading.loadRelaxed() && !m_quitting) -+ m_cond.wait(&m_mutex); -+ } -+ -+ return !m_quitting; -+ } -+ -+ int dispatchQueuePending() -+ { -+ if (m_wlevqueue) -+ return wl_display_dispatch_queue_pending(m_wldisplay, m_wlevqueue); -+ else -+ return wl_display_dispatch_pending(m_wldisplay); -+ } -+ -+ int prepareReadQueue() -+ { -+ if (m_wlevqueue) -+ return wl_display_prepare_read_queue(m_wldisplay, m_wlevqueue); -+ else -+ return wl_display_prepare_read(m_wldisplay); -+ } -+ -+ int m_fd; -+ int m_pipefd[2]; -+ wl_display *m_wldisplay; -+ wl_event_queue *m_wlevqueue; -+ OperatingMode m_mode; -+ -+ /* Concurrency note when operating in EmitToDispatch mode: -+ * m_reading is set to false inside event thread's waitForReading(), and is -+ * set to true inside main thread's readAndDispatchEvents(). -+ * The lock is not taken when setting m_reading to false, as the main thread -+ * is not actively waiting for it to turn false. However, the lock is taken -+ * inside readAndDispatchEvents() before setting m_reading to true, -+ * as the event thread is actively waiting for it under the wait condition. -+ */ -+ -+ QAtomicInteger<bool> m_reading; -+ bool m_quitting; -+ QMutex m_mutex; -+ QWaitCondition m_cond; -+}; -+ - Q_LOGGING_CATEGORY(lcQpaWayland, "qt.qpa.wayland"); // for general (uncategorized) Wayland platform logging - - struct wl_surface *QWaylandDisplay::createSurface(void *handle) -@@ -158,17 +351,16 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration) - if (!mXkbContext) - qCWarning(lcQpaWayland, "failed to create xkb context"); - #endif -- -- forceRoundTrip(); -- -- if (!mWaitingScreens.isEmpty()) { -- // Give wl_output.done and zxdg_output_v1.done events a chance to arrive -- forceRoundTrip(); -- } - } - - QWaylandDisplay::~QWaylandDisplay(void) - { -+ if (m_eventThread) -+ m_eventThread->stop(); -+ -+ if (m_frameEventQueueThread) -+ m_frameEventQueueThread->stop(); -+ - if (mSyncCallback) - wl_callback_destroy(mSyncCallback); - -@@ -189,6 +381,18 @@ QWaylandDisplay::~QWaylandDisplay(void) - wl_display_disconnect(mDisplay); - } - -+// Steps which is called just after constructor. This separates registry_global() out of the constructor -+// so that factory functions in integration can be overridden. -+void QWaylandDisplay::initialize() -+{ -+ forceRoundTrip(); -+ -+ if (!mWaitingScreens.isEmpty()) { -+ // Give wl_output.done and zxdg_output_v1.done events a chance to arrive -+ forceRoundTrip(); -+ } -+} -+ - void QWaylandDisplay::ensureScreen() - { - if (!mScreens.empty() || mPlaceholderScreen) -@@ -203,98 +407,37 @@ void QWaylandDisplay::ensureScreen() - - 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?"); -- } else { -- qWarning("The Wayland connection experienced a fatal error: %s", strerror(ecode)); -- } -- _exit(1); -+ checkWaylandError(mDisplay); - } - -+// Called in main thread, either from queued signal or directly. - void QWaylandDisplay::flushRequests() - { -- if (wl_display_prepare_read(mDisplay) == 0) { -- wl_display_read_events(mDisplay); -- } -- -- if (wl_display_dispatch_pending(mDisplay) < 0) -- checkError(); -- -- { -- QReadLocker locker(&m_frameQueueLock); -- for (const FrameQueue &q : mExternalQueues) { -- QMutexLocker locker(q.mutex); -- while (wl_display_prepare_read_queue(mDisplay, q.queue) != 0) -- wl_display_dispatch_queue_pending(mDisplay, q.queue); -- wl_display_read_events(mDisplay); -- wl_display_dispatch_queue_pending(mDisplay, q.queue); -- } -- } -- -- wl_display_flush(mDisplay); --} -- --void QWaylandDisplay::blockingReadEvents() --{ -- if (wl_display_dispatch(mDisplay) < 0) -- checkError(); --} -- --void QWaylandDisplay::destroyFrameQueue(const QWaylandDisplay::FrameQueue &q) --{ -- QWriteLocker locker(&m_frameQueueLock); -- auto it = std::find_if(mExternalQueues.begin(), -- mExternalQueues.end(), -- [&q] (const QWaylandDisplay::FrameQueue &other){ return other.queue == q.queue; }); -- Q_ASSERT(it != mExternalQueues.end()); -- mExternalQueues.erase(it); -- if (q.queue != nullptr) -- wl_event_queue_destroy(q.queue); -- delete q.mutex; -+ m_eventThread->readAndDispatchEvents(); - } - --QWaylandDisplay::FrameQueue QWaylandDisplay::createFrameQueue() -+// We have to wait until we have an eventDispatcher before creating the eventThread, -+// otherwise forceRoundTrip() may block inside _events_read() because eventThread is -+// polling. -+void QWaylandDisplay::initEventThread() - { -- QWriteLocker locker(&m_frameQueueLock); -- FrameQueue q{createEventQueue()}; -- mExternalQueues.append(q); -- return q; --} -+ m_eventThread.reset( -+ new EventThread(mDisplay, /* default queue */ nullptr, EventThread::EmitToDispatch)); -+ connect(m_eventThread.get(), &EventThread::needReadAndDispatch, this, -+ &QWaylandDisplay::flushRequests, Qt::QueuedConnection); -+ m_eventThread->start(); - --wl_event_queue *QWaylandDisplay::createEventQueue() --{ -- return wl_display_create_queue(mDisplay); -+ // wl_display_disconnect() free this. -+ m_frameEventQueue = wl_display_create_queue(mDisplay); -+ m_frameEventQueueThread.reset( -+ new EventThread(mDisplay, m_frameEventQueue, EventThread::SelfDispatch)); -+ m_frameEventQueueThread->start(); - } - --void QWaylandDisplay::dispatchQueueWhile(wl_event_queue *queue, std::function<bool ()> condition, int timeout) -+void QWaylandDisplay::blockingReadEvents() - { -- if (!condition()) -- return; -- -- QElapsedTimer timer; -- timer.start(); -- struct pollfd pFd = qt_make_pollfd(wl_display_get_fd(mDisplay), POLLIN); -- while (timeout == -1 || timer.elapsed() < timeout) { -- while (wl_display_prepare_read_queue(mDisplay, queue) != 0) -- wl_display_dispatch_queue_pending(mDisplay, queue); -- -- wl_display_flush(mDisplay); -- -- const int remaining = qMax(timeout - timer.elapsed(), 0ll); -- const int pollTimeout = timeout == -1 ? -1 : remaining; -- if (qt_poll_msecs(&pFd, 1, pollTimeout) > 0) -- wl_display_read_events(mDisplay); -- else -- wl_display_cancel_read(mDisplay); -- -- if (wl_display_dispatch_queue_pending(mDisplay, queue) < 0) -- checkError(); -- -- if (!condition()) -- break; -- } -+ if (wl_display_dispatch(mDisplay) < 0) -+ checkWaylandError(mDisplay); - } - - QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const -@@ -669,4 +812,6 @@ QWaylandCursorTheme *QWaylandDisplay::loadCursorTheme(const QString &name, int p - - } // namespace QtWaylandClient - -+#include "qwaylanddisplay.moc" -+ - QT_END_NAMESPACE -diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h -index 09a1736a267d2816873667e9f1ecb4f4892f0ed0..42bc661d3064d770aa9fde8bd62ecdbbc89732a2 100644 ---- a/src/client/qwaylanddisplay_p.h -+++ b/src/client/qwaylanddisplay_p.h -@@ -109,6 +109,7 @@ class QWaylandSurface; - class QWaylandShellIntegration; - class QWaylandCursor; - class QWaylandCursorTheme; -+class EventThread; - - typedef void (*RegistryListener)(void *data, - struct wl_registry *registry, -@@ -120,15 +121,11 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandDisplay : public QObject, public QtWayland - Q_OBJECT - - public: -- struct FrameQueue { -- FrameQueue(wl_event_queue *q = nullptr) : queue(q), mutex(new QMutex) {} -- wl_event_queue *queue; -- QMutex *mutex; -- }; -- - QWaylandDisplay(QWaylandIntegration *waylandIntegration); - ~QWaylandDisplay(void) override; - -+ void initialize(); -+ - #if QT_CONFIG(xkbcommon) - struct xkb_context *xkbContext() const { return mXkbContext.get(); } - #endif -@@ -210,12 +207,11 @@ public: - void handleKeyboardFocusChanged(QWaylandInputDevice *inputDevice); - void handleWindowDestroyed(QWaylandWindow *window); - -- wl_event_queue *createEventQueue(); -- FrameQueue createFrameQueue(); -- void destroyFrameQueue(const FrameQueue &q); -- void dispatchQueueWhile(wl_event_queue *queue, std::function<bool()> condition, int timeout = -1); -+ wl_event_queue *frameEventQueue() { return m_frameEventQueue; }; - - bool isKeyboardAvailable() const; -+ -+ void initEventThread(); - public slots: - void blockingReadEvents(); - void flushRequests(); -@@ -238,6 +234,9 @@ private: - }; - - struct wl_display *mDisplay = nullptr; -+ QScopedPointer<EventThread> m_eventThread; -+ wl_event_queue *m_frameEventQueue = nullptr; -+ QScopedPointer<EventThread> m_frameEventQueueThread; - QtWayland::wl_compositor mCompositor; - QScopedPointer<QWaylandShm> mShm; - QList<QWaylandScreen *> mWaitingScreens; -@@ -274,11 +273,9 @@ private: - QWaylandInputDevice *mLastInputDevice = nullptr; - QPointer<QWaylandWindow> mLastInputWindow; - QPointer<QWaylandWindow> mLastKeyboardFocus; -- QVector<QWaylandWindow *> mActiveWindows; -- QVector<FrameQueue> mExternalQueues; -+ QList<QWaylandWindow *> mActiveWindows; - struct wl_callback *mSyncCallback = nullptr; - static const wl_callback_listener syncCallbackListener; -- QReadWriteLock m_frameQueueLock; - - bool mClientSideInputContextRequested = !QPlatformInputContextFactory::requested().isNull(); - -diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp -index e5e7dd42c9b0145f4c9852f7e15dcc83106c321d..3b876047293887d17eeb28819c7386ded9e1f131 100644 ---- a/src/client/qwaylandintegration.cpp -+++ b/src/client/qwaylandintegration.cpp -@@ -192,14 +192,18 @@ QAbstractEventDispatcher *QWaylandIntegration::createEventDispatcher() const - - void QWaylandIntegration::initialize() - { -+ mDisplay->initEventThread(); -+ -+ // Call after eventDispatcher is fully connected, for QWaylandDisplay::forceRoundTrip() -+ mDisplay->initialize(); -+ -+ // But the aboutToBlock() and awake() should be connected after initializePlatform(). -+ // Otherwise the connected flushRequests() may consumes up all events before processEvents starts to wait, -+ // so that processEvents(QEventLoop::WaitForMoreEvents) may be blocked in the forceRoundTrip(). - QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher; - QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay.data(), SLOT(flushRequests())); - QObject::connect(dispatcher, SIGNAL(awake()), mDisplay.data(), SLOT(flushRequests())); - -- int fd = wl_display_get_fd(mDisplay->wl_display()); -- QSocketNotifier *sn = new QSocketNotifier(fd, QSocketNotifier::Read, mDisplay.data()); -- QObject::connect(sn, SIGNAL(activated(QSocketDescriptor)), mDisplay.data(), SLOT(flushRequests())); -- - // Qt does not support running with no screens - mDisplay->ensureScreen(); - } -diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp -index 1597f67e63ae7834ded50e25b0acf86b71abcd73..7de19a742b6d3f6a3ce0955f59a5bf2879d29c9e 100644 ---- a/src/client/qwaylandwindow.cpp -+++ b/src/client/qwaylandwindow.cpp -@@ -76,7 +76,6 @@ QWaylandWindow *QWaylandWindow::mMouseGrab = nullptr; - QWaylandWindow::QWaylandWindow(QWindow *window, QWaylandDisplay *display) - : QPlatformWindow(window) - , mDisplay(display) -- , mFrameQueue(mDisplay->createFrameQueue()) - , mResizeAfterSwap(qEnvironmentVariableIsSet("QT_WAYLAND_RESIZE_AFTER_SWAP")) - { - { -@@ -95,8 +94,6 @@ QWaylandWindow::QWaylandWindow(QWindow *window, QWaylandDisplay *display) - - QWaylandWindow::~QWaylandWindow() - { -- mDisplay->destroyFrameQueue(mFrameQueue); -- - delete mWindowDecoration; - - if (mSurface) -@@ -635,6 +632,8 @@ const wl_callback_listener QWaylandWindow::callbackListener = { - - void QWaylandWindow::handleFrameCallback() - { -+ QMutexLocker locker(&mFrameSyncMutex); -+ - mWaitingForFrameCallback = false; - mFrameCallbackElapsedTimer.invalidate(); - -@@ -656,12 +655,16 @@ void QWaylandWindow::handleFrameCallback() - mWaitingForUpdateDelivery = true; - QMetaObject::invokeMethod(this, doHandleExpose, Qt::QueuedConnection); - } -+ -+ mFrameSyncWait.notify_all(); - } - - bool QWaylandWindow::waitForFrameSync(int timeout) - { -- QMutexLocker locker(mFrameQueue.mutex); -- mDisplay->dispatchQueueWhile(mFrameQueue.queue, [&]() { return mWaitingForFrameCallback; }, timeout); -+ QMutexLocker locker(&mFrameSyncMutex); -+ -+ QDeadlineTimer deadline(timeout); -+ while (mWaitingForFrameCallback && mFrameSyncWait.wait(&mFrameSyncMutex, deadline)) { } - - if (mWaitingForFrameCallback) { - qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed"; -@@ -1157,8 +1160,11 @@ void QWaylandWindow::requestUpdate() - 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 (mWaitingForFrameCallback) -- return; -+ { -+ QMutexLocker locker(&mFrameSyncMutex); -+ if (mWaitingForFrameCallback) -+ return; -+ } - - // 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 -@@ -1171,7 +1177,12 @@ void QWaylandWindow::requestUpdate() - // so use invokeMethod to delay the delivery a bit. - QMetaObject::invokeMethod(this, [this] { - // Things might have changed in the meantime -- if (hasPendingUpdateRequest() && !mWaitingForFrameCallback) -+ { -+ QMutexLocker locker(&mFrameSyncMutex); -+ if (mWaitingForFrameCallback) -+ return; -+ } -+ if (hasPendingUpdateRequest()) - deliverUpdateRequest(); - }, Qt::QueuedConnection); - } -@@ -1191,9 +1202,10 @@ void QWaylandWindow::handleUpdate() - if (!mSurface) - return; - -- QMutexLocker locker(mFrameQueue.mutex); -+ QMutexLocker locker(&mFrameSyncMutex); -+ - struct ::wl_surface *wrappedSurface = reinterpret_cast<struct ::wl_surface *>(wl_proxy_create_wrapper(mSurface->object())); -- wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(wrappedSurface), mFrameQueue.queue); -+ wl_proxy_set_queue(reinterpret_cast<wl_proxy *>(wrappedSurface), mDisplay->frameEventQueue()); - mFrameCallback = wl_surface_frame(wrappedSurface); - wl_proxy_wrapper_destroy(wrappedSurface); - wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this); -@@ -1203,6 +1215,8 @@ void QWaylandWindow::handleUpdate() - // Start a timer for handling the case when the compositor stops sending frame callbacks. - if (mFrameCallbackTimeout > 0) { - QMetaObject::invokeMethod(this, [this] { -+ QMutexLocker locker(&mFrameSyncMutex); -+ - if (mWaitingForFrameCallback) { - if (mFrameCallbackCheckIntervalTimerId < 0) - mFrameCallbackCheckIntervalTimerId = startTimer(mFrameCallbackTimeout); -diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h -index e06879620c3d033f093b0866f018ec80a72a97c3..d45980a80e9ecc9c5003fa2144de63e6337bda8a 100644 ---- a/src/client/qwaylandwindow_p.h -+++ b/src/client/qwaylandwindow_p.h -@@ -232,7 +232,7 @@ protected: - int mFrameCallbackCheckIntervalTimerId = -1; - QElapsedTimer mFrameCallbackElapsedTimer; - struct ::wl_callback *mFrameCallback = nullptr; -- QWaylandDisplay::FrameQueue mFrameQueue; -+ QMutex mFrameSyncMutex; - QWaitCondition mFrameSyncWait; - - // True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer |