diff options
author | Liang Qi <liang.qi@qt.io> | 2018-12-22 18:53:35 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2018-12-22 18:53:35 +0100 |
commit | 5a6020f6efb4f09a77745614c6d1c0369bc5e365 (patch) | |
tree | ed8dec085d4f2a7ac359e5bbbb432b8449fb82fa /src/client | |
parent | ed03ec25de7e44d8e9a6aea359518851f5a8efa9 (diff) | |
parent | f2dc41b5babf0a7b51a1735f290540d7be695042 (diff) |
Merge remote-tracking branch 'origin/5.12' into dev
Conflicts:
README
src/hardwareintegration/client/xcomposite_share/xcomposite_share.pri
Change-Id: I7cbbf39916821f0f1749e3ccab3151f68f4aa1ac
Diffstat (limited to 'src/client')
-rw-r--r-- | src/client/client.pro | 4 | ||||
-rw-r--r-- | src/client/qwaylandinputdevice.cpp | 22 | ||||
-rw-r--r-- | src/client/qwaylandinputdevice_p.h | 10 | ||||
-rw-r--r-- | src/client/qwaylandwindow.cpp | 107 | ||||
-rw-r--r-- | src/client/qwaylandwindow_p.h | 9 |
5 files changed, 114 insertions, 38 deletions
diff --git a/src/client/client.pro b/src/client/client.pro index 42e7cae8c..38d0ac3e1 100644 --- a/src/client/client.pro +++ b/src/client/client.pro @@ -15,8 +15,8 @@ use_gold_linker: CONFIG += no_linker_version_script CONFIG -= precompile_header CONFIG += link_pkgconfig wayland-scanner -qtConfig(xkbcommon-evdev): \ - QMAKE_USE_PRIVATE += xkbcommon_evdev +qtConfig(xkbcommon): \ + QMAKE_USE_PRIVATE += xkbcommon qtHaveModule(linuxaccessibility_support_private): \ QT += linuxaccessibility_support_private diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp index e35c83ae8..49f1ab244 100644 --- a/src/client/qwaylandinputdevice.cpp +++ b/src/client/qwaylandinputdevice.cpp @@ -70,7 +70,7 @@ #include <QtGui/QGuiApplication> -#if QT_CONFIG(xkbcommon_evdev) +#if QT_CONFIG(xkbcommon) #include <xkbcommon/xkbcommon-compose.h> #endif @@ -84,7 +84,7 @@ QWaylandInputDevice::Keyboard::Keyboard(QWaylandInputDevice *p) connect(&mRepeatTimer, SIGNAL(timeout()), this, SLOT(repeatKey())); } -#if QT_CONFIG(xkbcommon_evdev) +#if QT_CONFIG(xkbcommon) bool QWaylandInputDevice::Keyboard::createDefaultKeyMap() { if (mXkbContext && mXkbMap && mXkbState) { @@ -156,7 +156,7 @@ void QWaylandInputDevice::Keyboard::releaseComposeState() QWaylandInputDevice::Keyboard::~Keyboard() { -#if QT_CONFIG(xkbcommon_evdev) +#if QT_CONFIG(xkbcommon) releaseComposeState(); releaseKeyMap(); #endif @@ -343,7 +343,7 @@ Qt::KeyboardModifiers QWaylandInputDevice::Keyboard::modifiers() const { Qt::KeyboardModifiers ret = Qt::NoModifier; -#if QT_CONFIG(xkbcommon_evdev) +#if QT_CONFIG(xkbcommon) if (!mXkbState) return ret; @@ -627,7 +627,7 @@ void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, in void QWaylandInputDevice::Keyboard::keyboard_keymap(uint32_t format, int32_t fd, uint32_t size) { -#if QT_CONFIG(xkbcommon_evdev) +#if QT_CONFIG(xkbcommon) if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { close(fd); return; @@ -730,7 +730,7 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, if (isDown) mParent->mQDisplay->setLastInputDevice(mParent, serial, window); -#if QT_CONFIG(xkbcommon_evdev) +#if QT_CONFIG(xkbcommon) if (!createDefaultKeyMap()) { return; } @@ -773,7 +773,7 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, #endif if (state == WL_KEYBOARD_KEY_STATE_PRESSED -#if QT_CONFIG(xkbcommon_evdev) +#if QT_CONFIG(xkbcommon) && xkb_keymap_key_repeats(mXkbMap, code) #endif ) { @@ -781,7 +781,7 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, mRepeatCode = code; mRepeatTime = time; mRepeatText = text; -#if QT_CONFIG(xkbcommon_evdev) +#if QT_CONFIG(xkbcommon) mRepeatSym = sym; #endif mRepeatTimer.setInterval(mRepeatDelay); @@ -795,7 +795,7 @@ void QWaylandInputDevice::Keyboard::repeatKey() { mRepeatTimer.setInterval(mRepeatRate); sendKey(mFocus->window(), mRepeatTime, QEvent::KeyRelease, mRepeatKey, modifiers(), mRepeatCode, -#if QT_CONFIG(xkbcommon_evdev) +#if QT_CONFIG(xkbcommon) mRepeatSym, mNativeModifiers, #else 0, 0, @@ -803,7 +803,7 @@ void QWaylandInputDevice::Keyboard::repeatKey() mRepeatText, true); sendKey(mFocus->window(), mRepeatTime, QEvent::KeyPress, mRepeatKey, modifiers(), mRepeatCode, -#if QT_CONFIG(xkbcommon_evdev) +#if QT_CONFIG(xkbcommon) mRepeatSym, mNativeModifiers, #else 0, 0, @@ -818,7 +818,7 @@ void QWaylandInputDevice::Keyboard::keyboard_modifiers(uint32_t serial, uint32_t group) { Q_UNUSED(serial); -#if QT_CONFIG(xkbcommon_evdev) +#if QT_CONFIG(xkbcommon) if (mXkbState) xkb_state_update_mask(mXkbState, mods_depressed, mods_latched, mods_locked, diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h index d1ff0da23..f27f329be 100644 --- a/src/client/qwaylandinputdevice_p.h +++ b/src/client/qwaylandinputdevice_p.h @@ -63,7 +63,7 @@ #include <QtWaylandClient/private/qwayland-wayland.h> -#if QT_CONFIG(xkbcommon_evdev) +#if QT_CONFIG(xkbcommon) #include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon-keysyms.h> #endif @@ -75,7 +75,7 @@ struct wl_cursor_image; #endif -#if QT_CONFIG(xkbcommon_evdev) +#if QT_CONFIG(xkbcommon) struct xkb_compose_state; struct xkb_compose_table; #endif @@ -208,7 +208,7 @@ public: QWaylandInputDevice *mParent = nullptr; QPointer<QWaylandWindow> mFocus; -#if QT_CONFIG(xkbcommon_evdev) +#if QT_CONFIG(xkbcommon) xkb_context *mXkbContext = nullptr; xkb_keymap *mXkbMap = nullptr; xkb_state *mXkbState = nullptr; @@ -223,7 +223,7 @@ public: int mRepeatRate = 25; int mRepeatDelay = 400; QString mRepeatText; -#if QT_CONFIG(xkbcommon_evdev) +#if QT_CONFIG(xkbcommon) xkb_keysym_t mRepeatSym; #endif QTimer mRepeatTimer; @@ -234,7 +234,7 @@ private slots: void repeatKey(); private: -#if QT_CONFIG(xkbcommon_evdev) +#if QT_CONFIG(xkbcommon) bool createDefaultKeyMap(); void releaseKeyMap(); void createComposeState(); diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index 029820e2c..a5eba5b26 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -356,6 +356,8 @@ void QWaylandWindow::sendExposeEvent(const QRect &rect) { if (!(mShellSurface && mShellSurface->handleExpose(rect))) QWindowSystemInterface::handleExposeEvent(window(), rect); + else + qCDebug(lcQpaWayland) << "sendExposeEvent: intercepted by shell extension, not sending"; mLastExposeGeometry = rect; } @@ -544,18 +546,11 @@ void QWaylandWindow::handleScreenRemoved(QScreen *qScreen) void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y) { Q_ASSERT(!buffer->committed()); - if (mFrameCallback) { - wl_callback_destroy(mFrameCallback); - mFrameCallback = nullptr; - } - if (buffer) { - mFrameCallback = frame(); - wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this); - mWaitingForFrameSync = true; + handleUpdate(); buffer->setBusy(); - attach(buffer->buffer(), x, y); + QtWayland::wl_surface::attach(buffer->buffer(), x, y); } else { QtWayland::wl_surface::attach(nullptr, 0, 0); } @@ -620,11 +615,9 @@ void QWaylandWindow::frameCallback(void *data, struct wl_callback *callback, uin Q_UNUSED(callback); QWaylandWindow *self = static_cast<QWaylandWindow*>(data); - self->mWaitingForFrameSync = false; - if (self->mUpdateRequested) { - self->mUpdateRequested = false; + self->mWaitingForFrameCallback = false; + if (self->mUpdateRequested) self->deliverUpdateRequest(); - } } QMutex QWaylandWindow::mFrameSyncMutex; @@ -632,10 +625,10 @@ QMutex QWaylandWindow::mFrameSyncMutex; void QWaylandWindow::waitForFrameSync() { QMutexLocker locker(&mFrameSyncMutex); - if (!mWaitingForFrameSync) + if (!mWaitingForFrameCallback) return; mDisplay->flushRequests(); - while (mWaitingForFrameSync) + while (mWaitingForFrameCallback) mDisplay->blockingReadEvents(); } @@ -1036,12 +1029,88 @@ QVariant QWaylandWindow::property(const QString &name, const QVariant &defaultVa return m_properties.value(name, defaultValue); } +void QWaylandWindow::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == mFallbackUpdateTimerId) { + killTimer(mFallbackUpdateTimerId); + mFallbackUpdateTimerId = -1; + + if (!isExposed()) { + qCDebug(lcWaylandBackingstore) << "Fallback update timer: Window not exposed," + << "not delivering update request."; + return; + } + + if (mWaitingForUpdate && mUpdateRequested && !mWaitingForFrameCallback) { + qCWarning(lcWaylandBackingstore) << "Delivering update request through fallback timer," + << "may not be in sync with display"; + deliverUpdateRequest(); + } + } +} + void QWaylandWindow::requestUpdate() { - if (!mWaitingForFrameSync) - QPlatformWindow::requestUpdate(); - else - mUpdateRequested = true; + if (mUpdateRequested) + return; + + mUpdateRequested = true; + + // If we have a frame callback all is good and will be taken care of there + if (mWaitingForFrameCallback) + return; + + // If we've already called deliverUpdateRequest(), but haven't seen any attach+commit/swap yet + if (mWaitingForUpdate) { + // Ideally, we should just have returned here, but we're not guaranteed that the client + // will actually update, so start this timer to deliver another request update after a while + // *IF* the client doesn't update. + int fallbackTimeout = 100; + mFallbackUpdateTimerId = startTimer(fallbackTimeout); + return; + } + + // Some applications (such as Qt Quick) depend on updates being delivered asynchronously, + // so use invokeMethod to delay the delivery a bit. + QMetaObject::invokeMethod(this, [this] { + // Things might have changed in the meantime + if (mUpdateRequested && !mWaitingForUpdate && !mWaitingForFrameCallback) + deliverUpdateRequest(); + }, Qt::QueuedConnection); +} + +// Should be called whenever we commit a buffer (directly through wl_surface.commit or indirectly +// with eglSwapBuffers) to know when it's time to commit the next one. +// Can be called from the render thread (without locking anything) so make sure to not make races in this method. +void QWaylandWindow::handleUpdate() +{ + // TODO: Should sync subsurfaces avoid requesting frame callbacks? + + if (mFrameCallback) { + wl_callback_destroy(mFrameCallback); + mFrameCallback = nullptr; + } + + if (mFallbackUpdateTimerId != -1) { + // Ideally, we would stop the fallback timer here, but since we're on another thread, + // it's not allowed. Instead we set mFallbackUpdateTimer to -1 here, so we'll just + // ignore it if it times out before it's cleaned up by the invokeMethod call. + int id = mFallbackUpdateTimerId; + mFallbackUpdateTimerId = -1; + QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection); + } + + mFrameCallback = frame(); + wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this); + mWaitingForFrameCallback = true; + mWaitingForUpdate = false; +} + +void QWaylandWindow::deliverUpdateRequest() +{ + mUpdateRequested = false; + mWaitingForUpdate = true; + QPlatformWindow::deliverUpdateRequest(); } void QWaylandWindow::addAttachOffset(const QPoint point) diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h index 56ebd3cc6..e5838d231 100644 --- a/src/client/qwaylandwindow_p.h +++ b/src/client/qwaylandwindow_p.h @@ -191,7 +191,10 @@ public: bool startSystemMove(const QPoint &pos) override; + void timerEvent(QTimerEvent *event) override; void requestUpdate() override; + void handleUpdate(); + void deliverUpdateRequest() override; public slots: void applyConfigure(); @@ -211,10 +214,14 @@ protected: Qt::MouseButtons mMousePressedInContentArea = Qt::NoButton; WId mWindowId; - bool mWaitingForFrameSync = false; + bool mWaitingForFrameCallback = false; struct ::wl_callback *mFrameCallback = nullptr; QWaitCondition mFrameSyncWait; + // True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer + bool mWaitingForUpdate = false; + int mFallbackUpdateTimerId = -1; + QMutex mResizeLock; bool mWaitingToApplyConfigure = false; bool mCanResize = true; |