Fix crash when wl-shell setType is called with a hidden parent

Fall back to creating a toplevel instead

Change-Id: If7db27d08b79e4f9f8c82fa8f9bf73abdb2585d9
Reviewed-by: David Edmundson <davidedmundson@kde.org>
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
This commit is contained in:
Johan Klokkhammer Helsing 2017-10-18 11:05:48 +02:00 committed by Johan Helsing
parent b3621cfe7c
commit 6cf44bf690
2 changed files with 48 additions and 2 deletions

View File

@ -185,6 +185,7 @@ void QWaylandWlShellSurface::updateTransientParent(QWindow *parent)
|| testShowWithoutActivating(m_window->window()))
flags |= WL_SHELL_SURFACE_TRANSIENT_INACTIVE;
Q_ASSERT(parent_wayland_window->object());
set_transient(parent_wayland_window->object(),
transientPos.x(),
transientPos.y(),
@ -211,15 +212,16 @@ void QWaylandWlShellSurface::setPopup(QWaylandWindow *parent, QWaylandInputDevic
transientPos.setY(transientPos.y() + parent_wayland_window->decoration()->margins().top());
}
Q_ASSERT(parent_wayland_window->object());
set_popup(device->wl_seat(), serial, parent_wayland_window->object(),
transientPos.x(), transientPos.y(), 0);
}
void QWaylandWlShellSurface::setType(Qt::WindowType type, QWaylandWindow *transientParent)
{
if (type == Qt::Popup && transientParent)
if (type == Qt::Popup && transientParent && transientParent->object())
setPopup(transientParent, m_window->display()->lastInputDevice(), m_window->display()->lastInputSerial());
else if (transientParent)
else if (transientParent && transientParent->object())
updateTransientParent(transientParent->window());
else
setTopLevel();

View File

@ -143,6 +143,8 @@ private slots:
void touchDrag();
void mouseDrag();
void dontCrashOnMultipleCommits();
void hiddenTransientParent();
void hiddenPopupParent();
private:
MockCompositor *compositor;
@ -360,6 +362,48 @@ void tst_WaylandClient::dontCrashOnMultipleCommits()
QTRY_VERIFY(!compositor->surface());
}
void tst_WaylandClient::hiddenTransientParent()
{
QWindow parent;
QWindow transient;
transient.setTransientParent(&parent);
parent.show();
QTRY_VERIFY(compositor->surface());
parent.hide();
QTRY_VERIFY(!compositor->surface());
transient.show();
QTRY_VERIFY(compositor->surface());
}
void tst_WaylandClient::hiddenPopupParent()
{
TestWindow toplevel;
toplevel.show();
// wl_shell relies on a mouse event in order to send a serial and seat
// with the set_popup request.
QSharedPointer<MockSurface> surface;
QTRY_VERIFY(surface = compositor->surface());
QPoint mousePressPos(16, 16);
QCOMPARE(toplevel.mousePressEventCount, 0);
compositor->sendMousePress(surface, mousePressPos);
QTRY_COMPARE(toplevel.mousePressEventCount, 1);
QWindow popup;
popup.setTransientParent(&toplevel);
popup.setFlag(Qt::Popup, true);
toplevel.hide();
QTRY_VERIFY(!compositor->surface());
popup.show();
QTRY_VERIFY(compositor->surface());
}
int main(int argc, char **argv)
{
setenv("XDG_RUNTIME_DIR", ".", 1);