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>
This commit is contained in:
parent
ac1d9c43e6
commit
08c6462d1b
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user