[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
This commit is contained in:
parent
207eb167e1
commit
014afe1c05
1 changed files with 28 additions and 11 deletions
|
@ -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<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*) 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<xcb_ge_generic_event_t *>(event);
|
||||
xi2PrepareXIGenericDeviceEvent(ge);
|
||||
GeEventMemMover ge(event);
|
||||
switch (ge->event_type) {
|
||||
case XI_RawKeyPress: {
|
||||
auto re = reinterpret_cast<xXIRawEvent*>(event);
|
||||
|
@ -118,7 +143,7 @@ public:
|
|||
}
|
||||
break;
|
||||
case XI_TouchBegin: {
|
||||
auto e = reinterpret_cast<xXIDeviceEvent*>(ge);
|
||||
auto e = reinterpret_cast<xXIDeviceEvent*>(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<X11Cursor> m_x11Cursor;
|
||||
Display *m_x11Display = nullptr;
|
||||
uint32_t m_trackingTouchId = 0;
|
||||
|
|
Loading…
Reference in a new issue