Android: Fix crash in QCompleter test

The call to QPlatformWindow::setVisible() will trigger flushing
of the window system events. Depending on the events, this could
lead to the window being hidden. Since platformScreen()->addWindow()
and removeWindow() was done *after* this flush, you could get the
remove for a window before it had been added, whereas the logic
in these functions were written under the assumption that there
is exactly one remove per add, and that add always precedes the
remove.

This has only been seen when running the QCompleter test so far.

This patch reorders the statements to make sure the events are flushed
after the window stack has been updated. In addition, it adds asserts
for the assumptions in the addWindow/removeWindow code to catch bugs
there earlier.

Change-Id: Ic67b03afbf7acbcb78be86bffa4c26360dc5832f
Task-number: QTBUG-43836
Reviewed-by: Christian Stromme <christian.stromme@theqtcompany.com>
This commit is contained in:
Eskil Abrahamsen Blomfeldt 2015-01-14 13:09:29 +01:00
parent e58a721c5d
commit c27e1f498f
2 changed files with 8 additions and 4 deletions

View File

@ -131,6 +131,7 @@ void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window)
if (window->parent() && window->isRaster())
return;
Q_ASSERT(!m_windowStack.contains(window));
m_windowStack.prepend(window);
if (window->isRaster()) {
m_rasterSurfaces.ref();
@ -147,7 +148,10 @@ void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window)
if (window->parent() && window->isRaster())
return;
Q_ASSERT(m_windowStack.contains(window));
m_windowStack.removeOne(window);
Q_ASSERT(!m_windowStack.contains(window));
if (window->isRaster()) {
m_rasterSurfaces.deref();

View File

@ -82,15 +82,15 @@ void QAndroidPlatformWindow::setVisible(bool visible)
setGeometry(platformScreen()->availableGeometry());
}
QRect availableGeometry = screen()->availableGeometry();
if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0)
QPlatformWindow::setVisible(visible);
if (visible)
platformScreen()->addWindow(this);
else
platformScreen()->removeWindow(this);
QRect availableGeometry = screen()->availableGeometry();
if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0)
QPlatformWindow::setVisible(visible);
// The Android Activity is activated before Qt is initialized, causing the application state to
// never be set to 'active'. We explicitly set this state when the first window becomes visible.
if (visible)