summaryrefslogtreecommitdiffstats
path: root/src/client
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2018-12-22 18:53:35 +0100
committerLiang Qi <liang.qi@qt.io>2018-12-22 18:53:35 +0100
commit5a6020f6efb4f09a77745614c6d1c0369bc5e365 (patch)
treeed8dec085d4f2a7ac359e5bbbb432b8449fb82fa /src/client
parented03ec25de7e44d8e9a6aea359518851f5a8efa9 (diff)
parentf2dc41b5babf0a7b51a1735f290540d7be695042 (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.pro4
-rw-r--r--src/client/qwaylandinputdevice.cpp22
-rw-r--r--src/client/qwaylandinputdevice_p.h10
-rw-r--r--src/client/qwaylandwindow.cpp107
-rw-r--r--src/client/qwaylandwindow_p.h9
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;