summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Klokkhammer Helsing <johan.helsing@qt.io>2018-12-03 10:35:13 +0100
committerJohan Helsing <johan.helsing@qt.io>2019-01-02 11:48:01 +0000
commit00c0bad3184e32ff0b1dd799b7ef121eaa737c0d (patch)
treea6099c3701defba634708cf508bd42ea14045114
parent09b6fcf3ec501cb94d89833745264a16c2a74209 (diff)
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 <pierluigi.fiorini@liri.io>
-rw-r--r--src/client/qwaylandinputdevice.cpp39
1 files changed, 25 insertions, 14 deletions
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index ba55e6e1..90e138a3 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)