From 09b6fcf3ec501cb94d89833745264a16c2a74209 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Fri, 21 Dec 2018 14:41:03 +0100 Subject: Client xdg-shell: Fix protocol error for tooltips on popups [ChangeLog][QPA plugin] Fixed a protocol error that used to happen when closing a menu with an active tooltip. Fixes: QTBUG-71734 Change-Id: I784fef08494fabaa4debea11f51116cf9de1f86e Reviewed-by: David Edmundson Reviewed-by: Pier Luigi Fiorini --- src/client/qwaylandwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index f596438b6..470ae0091 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -386,7 +386,7 @@ QWaylandScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const void QWaylandWindow::setVisible(bool visible) { if (visible) { - if (window()->type() == Qt::Popup) + if (window()->type() & (Qt::Popup | Qt::ToolTip)) activePopups << this; initWindow(); mDisplay->flushRequests(); -- cgit v1.2.3 From 00c0bad3184e32ff0b1dd799b7ef121eaa737c0d Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Mon, 3 Dec 2018 10:35:13 +0100 Subject: Client: Fix various input related crashes for events without focus Some compositors fail to send wl_pointer.enter events before button and axis events. This led to nullptr dereference crashes. [ChangeLog][QPA plugin] Fixed a crash caused by compositors sending incorrect pointer events. Fix it by adding nullptr checks before trying to access the pointer focus in case the compositor didn't send enter, or if something deleted the surface (it's a QPointer). This means we are now silently ignoring events for misbehaving compositors (which is probably not optimal), but I don't see how we can easily distinguish between a missing enter and a deleted QWaylandSurface without adding more bookkeeping overhead. Ditto for wl_keyboard. Fixes: QTBUG-72235 Change-Id: I4bfaa3da4ebae37b059e1e450975566559edf40b Reviewed-by: Pier Luigi Fiorini --- src/client/qwaylandinputdevice.cpp | 39 ++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp index ba55e6e17..90e138a3d 100644 --- a/src/client/qwaylandinputdevice.cpp +++ b/src/client/qwaylandinputdevice.cpp @@ -499,10 +499,9 @@ public: void QWaylandInputDevice::Pointer::pointer_motion(uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { QWaylandWindow *window = mFocus; - if (!window) { - // We destroyed the pointer focus surface, but the server - // didn't get the message yet. + // We destroyed the pointer focus surface, but the server didn't get the message yet... + // or the server didn't send an enter event first. In either case, ignore the event. return; } @@ -533,6 +532,12 @@ void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time uint32_t button, uint32_t state) { QWaylandWindow *window = mFocus; + if (!window) { + // We destroyed the pointer focus surface, but the server didn't get the message yet... + // or the server didn't send an enter event first. In either case, ignore the event. + return; + } + Qt::MouseButton qt_button; // translate from kernel (input.h) 'button' to corresponding Qt:MouseButton. @@ -599,15 +604,15 @@ public: void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, int32_t value) { QWaylandWindow *window = mFocus; - QPoint pixelDelta; - QPoint angleDelta; - if (!window) { - // We destroyed the pointer focus surface, but the server - // didn't get the message yet. + // We destroyed the pointer focus surface, but the server didn't get the message yet... + // or the server didn't send an enter event first. In either case, ignore the event. return; } + QPoint pixelDelta; + QPoint angleDelta; + //normalize value and inverse axis int valueDelta = wl_fixed_to_int(value) * -12; @@ -712,6 +717,12 @@ static void sendKey(QWindow *tlw, ulong timestamp, QEvent::Type type, int key, Q void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { QWaylandWindow *window = mFocus; + if (!window) { + // We destroyed the keyboard focus surface, but the server didn't get the message yet... + // or the server didn't send an enter event first. In either case, ignore the event. + return; + } + uint32_t code = key + 8; bool isDown = state != WL_KEYBOARD_KEY_STATE_RELEASED; QEvent::Type type = isDown ? QEvent::KeyPress : QEvent::KeyRelease; @@ -719,12 +730,6 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, int qtkey = key + 8; // qt-compositor substracts 8 for some reason mParent->mSerial = serial; - if (!window) { - // We destroyed the keyboard focus surface, but the server - // didn't get the message yet. - return; - } - if (isDown) mParent->mQDisplay->setLastInputDevice(mParent, serial, window); @@ -791,6 +796,12 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, void QWaylandInputDevice::Keyboard::repeatKey() { + if (!mFocus) { + // We destroyed the keyboard focus surface, but the server didn't get the message yet... + // or the server didn't send an enter event first. + return; + } + mRepeatTimer.setInterval(25); sendKey(mFocus->window(), mRepeatTime, QEvent::KeyRelease, mRepeatKey, modifiers(), mRepeatCode, #if QT_CONFIG(xkbcommon) -- cgit v1.2.3 From 34e03bf56cb080f3fae7dd31f0eb1d72e3bb518c Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Wed, 2 Jan 2019 15:04:23 +0100 Subject: Client: Fix incorrect damage for decoration edges [ChangeLog][QPA plugin] Fixed a bug where surface damage for window decorations was outside the surface. Fixes: QTBUG-72818 Change-Id: I32d00174f1c308952a98bdb55731eb77be54f331 Reviewed-by: Pier Luigi Fiorini --- src/client/qwaylandabstractdecoration.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/client/qwaylandabstractdecoration.cpp b/src/client/qwaylandabstractdecoration.cpp index 479a85750..6a8f1d92d 100644 --- a/src/client/qwaylandabstractdecoration.cpp +++ b/src/client/qwaylandabstractdecoration.cpp @@ -100,6 +100,7 @@ void QWaylandAbstractDecoration::setWaylandWindow(QWaylandWindow *window) d->m_wayland_window = window; } +// \a size is without margins static QRegion marginsRegion(const QSize &size, const QMargins &margins) { QRegion r; @@ -123,7 +124,7 @@ const QImage &QWaylandAbstractDecoration::contentImage() d->m_decorationContentImage.fill(Qt::transparent); this->paint(&d->m_decorationContentImage); - QRegion damage = marginsRegion(window()->frameGeometry().size(), window()->frameMargins()); + QRegion damage = marginsRegion(window()->geometry().size(), window()->frameMargins()); for (QRect r : damage) waylandWindow()->damage(r); -- cgit v1.2.3 From 143a6ad82ea0ded69da482eff1750082fd5b2a6a Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Wed, 2 Jan 2019 12:33:03 +0100 Subject: Client: Don't assume windows have surfaces in QWaylandInputContext::update Fixes: QTBUG-72751 Change-Id: I6018a34d4a4cfcbdef5d6cd05d2d4ef12846efea Reviewed-by: Paul Olav Tvete --- src/client/qwaylandinputcontext.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/client/qwaylandinputcontext.cpp b/src/client/qwaylandinputcontext.cpp index 58ad90d41..e85faaf8e 100644 --- a/src/client/qwaylandinputcontext.cpp +++ b/src/client/qwaylandinputcontext.cpp @@ -417,6 +417,15 @@ void QWaylandInputContext::commit() textInput()->commit(); } +static ::wl_surface *surfaceForWindow(QWindow *window) +{ + if (!window || !window->handle()) + return nullptr; + + auto *waylandWindow = static_cast(window->handle()); + return waylandWindow->wl_surface::object(); +} + void QWaylandInputContext::update(Qt::InputMethodQueries queries) { qCDebug(qLcQpaInputMethods) << Q_FUNC_INFO << queries; @@ -424,15 +433,15 @@ void QWaylandInputContext::update(Qt::InputMethodQueries queries) if (!QGuiApplication::focusObject() || !textInput()) return; - if (mCurrentWindow && mCurrentWindow->handle() && !inputMethodAccepted()) { - struct ::wl_surface *surface = static_cast(mCurrentWindow->handle())->object(); - textInput()->disable(surface); + auto *currentSurface = surfaceForWindow(mCurrentWindow); + + if (currentSurface && !inputMethodAccepted()) { + textInput()->disable(currentSurface); mCurrentWindow.clear(); - } else if (!mCurrentWindow && inputMethodAccepted()) { + } else if (!currentSurface && inputMethodAccepted()) { QWindow *window = QGuiApplication::focusWindow(); - if (window && window->handle()) { - struct ::wl_surface *surface = static_cast(window->handle())->object(); - textInput()->enable(surface); + if (auto *focusSurface = surfaceForWindow(window)) { + textInput()->enable(focusSurface); mCurrentWindow = window; } } -- cgit v1.2.3