From a34716370185d98ab0de25903913d8f2c7c821fa Mon Sep 17 00:00:00 2001 From: Li Qiu Date: Wed, 27 Aug 2014 18:24:52 +0300 Subject: DataOffer not invalidated when client loses keyboard focus The data_offer object should be invalidated when client loses keyboard focus. Otherwise in following scenario, it will become zombie object: start app1 -> copy text -> start app2 -> paste text -> close app1 -> paste again in app2 -> seg fault in qtwayland. The root cause is that when app2 takes focus the first time, data_device.data_offer event was sent to it from DataDevice::setFocus. When app1 is closed, the data source reference in data offer becomes invalid. so when trying to paste again in app2, segmentation faults Change-Id: I16a584e80fddaadd269b00cdf39eb405dd95b622 Task-number: QTBUG-41005 Reviewed-by: Giulio Camuffo --- src/client/qwaylanddatadevice.cpp | 5 +++++ src/client/qwaylanddatadevice_p.h | 1 + src/client/qwaylandinputdevice.cpp | 5 +++++ src/client/qwaylandwindow.cpp | 9 +++++++++ src/client/qwaylandwindow_p.h | 1 + 5 files changed, 21 insertions(+) diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp index 8f690aae..74f879f9 100644 --- a/src/client/qwaylanddatadevice.cpp +++ b/src/client/qwaylanddatadevice.cpp @@ -77,6 +77,11 @@ QWaylandDataOffer *QWaylandDataDevice::selectionOffer() const return m_selectionOffer.data(); } +void QWaylandDataDevice::invalidateSelectionOffer() +{ + m_selectionOffer.reset(); +} + QWaylandDataSource *QWaylandDataDevice::selectionSource() const { return m_selectionSource.data(); diff --git a/src/client/qwaylanddatadevice_p.h b/src/client/qwaylanddatadevice_p.h index f5fad177..dae91290 100644 --- a/src/client/qwaylanddatadevice_p.h +++ b/src/client/qwaylanddatadevice_p.h @@ -65,6 +65,7 @@ public: ~QWaylandDataDevice(); QWaylandDataOffer *selectionOffer() const; + void invalidateSelectionOffer(); QWaylandDataSource *selectionSource() const; void setSelectionSource(QWaylandDataSource *source); diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp index 5be76d90..c0406768 100644 --- a/src/client/qwaylandinputdevice.cpp +++ b/src/client/qwaylandinputdevice.cpp @@ -717,6 +717,11 @@ void QWaylandInputDevice::Keyboard::keyboard_leave(uint32_t time, struct wl_surf Q_UNUSED(time); Q_UNUSED(surface); + if (surface) { + QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface); + window->unfocus(); + } + mFocus = NULL; // Use a callback to set the focus because we may get a leave/enter pair, and diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index 278825e8..0905cb3a 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -42,6 +42,7 @@ #include "qwaylandwindow_p.h" #include "qwaylandbuffer_p.h" +#include "qwaylanddatadevice_p.h" #include "qwaylanddisplay_p.h" #include "qwaylandinputdevice_p.h" #include "qwaylandscreen_p.h" @@ -642,6 +643,14 @@ void QWaylandWindow::requestActivateWindow() // we rely on compositor setting keyboard focus based on window stacking. } +void QWaylandWindow::unfocus() +{ + QWaylandInputDevice *inputDevice = mDisplay->currentInputDevice(); + if (inputDevice && inputDevice->dataDevice()) { + inputDevice->dataDevice()->invalidateSelectionOffer(); + } +} + bool QWaylandWindow::isExposed() const { if (mShellSurface) diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h index db0b5945..a69af9c0 100644 --- a/src/client/qwaylandwindow_p.h +++ b/src/client/qwaylandwindow_p.h @@ -142,6 +142,7 @@ public: void requestActivateWindow() Q_DECL_OVERRIDE; bool isExposed() const Q_DECL_OVERRIDE; + void unfocus(); QWaylandDecoration *decoration() const; void setDecoration(QWaylandDecoration *decoration); -- cgit v1.2.1