From 014afe1c0559b8d38b8c3df20df8ef48fa5a1192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Sun, 23 Apr 2017 15:00:29 +0200 Subject: [PATCH] [platformx/x11] Fix touch events for internal Qt windows Summary: To have touch events working we need to do memory layout changes on the xcb events. This is fine for identifying the touch events which should trigger the screen edge. But when passed on to Qt to have QtQuick windows (e.g. Alt+Tab) handle the touch events, this results in a problem: Qt itself does also the memory movement and then the movement is double and touch events break. To prevent this problem an RAII class is added which moves the memory in the ctor and moves it back in the dtor. So during KWin's processing it has the right memory layout and later on in Qt's processing it has the proper "wrong" layout which Qt can fix again. Test Plan: Touch events in Alt+Tab work Reviewers: #kwin, #plasma Subscribers: plasma-devel, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D5549 --- .../x11/standalone/xinputintegration.cpp | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/plugins/platforms/x11/standalone/xinputintegration.cpp b/plugins/platforms/x11/standalone/xinputintegration.cpp index 66ec1d84d4..32250708fa 100644 --- a/plugins/platforms/x11/standalone/xinputintegration.cpp +++ b/plugins/platforms/x11/standalone/xinputintegration.cpp @@ -43,6 +43,32 @@ static inline qreal fixed1616ToReal(FP1616 val) return (val) * 1.0 / (1 << 16); } +class GeEventMemMover +{ +public: + GeEventMemMover(xcb_generic_event_t *event) + : m_event(reinterpret_cast(event)) + { + // xcb event structs contain stuff that wasn't on the wire, the full_sequence field + // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes. + // Move this data back to have the same layout in memory as it was on the wire + // and allow casting, overwriting the full_sequence field. + memmove((char*) m_event + 32, (char*) m_event + 36, m_event->length * 4); + } + ~GeEventMemMover() + { + // move memory layout back, so that Qt can do the same without breaking + memmove((char*) m_event + 36, (char *) m_event + 32, m_event->length * 4); + } + + xcb_ge_generic_event_t *operator->() const { + return m_event; + } + +private: + xcb_ge_generic_event_t *m_event; +}; + class XInputEventFilter : public X11EventFilter { public: @@ -52,8 +78,7 @@ public: virtual ~XInputEventFilter() = default; bool event(xcb_generic_event_t *event) override { - xcb_ge_generic_event_t *ge = reinterpret_cast(event); - xi2PrepareXIGenericDeviceEvent(ge); + GeEventMemMover ge(event); switch (ge->event_type) { case XI_RawKeyPress: { auto re = reinterpret_cast(event); @@ -118,7 +143,7 @@ public: } break; case XI_TouchBegin: { - auto e = reinterpret_cast(ge); + auto e = reinterpret_cast(event); m_lastTouchPositions.insert(e->detail, QPointF(fixed1616ToReal(e->event_x), fixed1616ToReal(e->event_y))); break; } @@ -175,14 +200,6 @@ private: return m_x11Display; } - void xi2PrepareXIGenericDeviceEvent(xcb_ge_generic_event_t *event) { - // xcb event structs contain stuff that wasn't on the wire, the full_sequence field - // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes. - // Move this data back to have the same layout in memory as it was on the wire - // and allow casting, overwriting the full_sequence field. - memmove((char*) event + 32, (char*) event + 36, event->length * 4); - } - QPointer m_x11Cursor; Display *m_x11Display = nullptr; uint32_t m_trackingTouchId = 0;