summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-05-21 15:08:37 +0200
committerQt Continuous Integration System <qt-info@nokia.com>2010-05-21 15:08:37 +0200
commit5cfefb0f71e4f4587f1c31d3d785136a9655085b (patch)
tree0b457b5cbd5a32013cbdd7e7615f59ead727b09f
parent16760f8ef992f022c24eb7d34ccc49b6a1868f16 (diff)
parent832b1a48050df80515353d9887976f364913ff8e (diff)
Merge branch '4.6' of scm.dev.nokia.troll.no:qt/oslo-staging-2 into 4.6-integration
* '4.6' of scm.dev.nokia.troll.no:qt/oslo-staging-2: Fixed an assert in QMenu Call eglTerminate() when the last QEglContext is destroyed to free mem.
-rw-r--r--src/gui/egl/qegl.cpp37
-rw-r--r--src/gui/widgets/qmenu.cpp12
-rw-r--r--tests/auto/qmenu/tst_qmenu.cpp54
3 files changed, 88 insertions, 15 deletions
diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp
index ee192169d9..c16aeb19bd 100644
--- a/src/gui/egl/qegl.cpp
+++ b/src/gui/egl/qegl.cpp
@@ -42,11 +42,40 @@
#include <QtGui/qpaintdevice.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qwidget.h>
+#include <QtCore/qatomic.h>
#include <QtCore/qdebug.h>
#include "qegl_p.h"
QT_BEGIN_NAMESPACE
+
+/*
+ QEglContextTracker is used to track the EGL contexts that we
+ create internally in Qt, so that we can call eglTerminate() to
+ free additional EGL resources when the last context is destroyed.
+*/
+
+class QEglContextTracker
+{
+public:
+ static void ref() { contexts.ref(); }
+ static void deref() {
+ if (!contexts.deref()) {
+ eglTerminate(QEglContext::display());
+ displayOpen = 0;
+ }
+ }
+ static void setDisplayOpened() { displayOpen = 1; }
+ static bool displayOpened() { return displayOpen; }
+
+private:
+ static QAtomicInt contexts;
+ static QAtomicInt displayOpen;
+};
+
+QAtomicInt QEglContextTracker::contexts = 0;
+QAtomicInt QEglContextTracker::displayOpen = 0;
+
// Current GL and VG contexts. These are used to determine if
// we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent().
// If a background thread modifies the value, the worst that will
@@ -65,6 +94,7 @@ QEglContext::QEglContext()
, ownsContext(true)
, sharing(false)
{
+ QEglContextTracker::ref();
}
QEglContext::~QEglContext()
@@ -75,6 +105,7 @@ QEglContext::~QEglContext()
currentGLContext = 0;
if (currentVGContext == this)
currentVGContext = 0;
+ QEglContextTracker::deref();
}
bool QEglContext::isValid() const
@@ -361,11 +392,9 @@ QEglProperties QEglContext::configProperties(EGLConfig cfg) const
EGLDisplay QEglContext::display()
{
- static bool openedDisplay = false;
-
- if (!openedDisplay) {
+ if (!QEglContextTracker::displayOpened()) {
dpy = eglGetDisplay(nativeDisplay());
- openedDisplay = true;
+ QEglContextTracker::setDisplayOpened();
if (dpy == EGL_NO_DISPLAY) {
qWarning("QEglContext::display(): Falling back to EGL_DEFAULT_DISPLAY");
dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp
index 879ba2a1af..c05829a39b 100644
--- a/src/gui/widgets/qmenu.cpp
+++ b/src/gui/widgets/qmenu.cpp
@@ -992,19 +992,9 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e)
return false;
}
-class ExceptionGuard
-{
-public:
- inline ExceptionGuard(bool *w = 0) : watched(w) { Q_ASSERT(!(*watched)); *watched = true; }
- inline ~ExceptionGuard() { *watched = false; }
- inline operator bool() { return *watched; }
-private:
- bool *watched;
-};
-
void QMenuPrivate::activateCausedStack(const QList<QPointer<QWidget> > &causedStack, QAction *action, QAction::ActionEvent action_e, bool self)
{
- ExceptionGuard guard(&activationRecursionGuard);
+ QBoolBlocker guard(activationRecursionGuard);
#ifdef QT3_SUPPORT
const int actionId = q_func()->findIdForAction(action);
#endif
diff --git a/tests/auto/qmenu/tst_qmenu.cpp b/tests/auto/qmenu/tst_qmenu.cpp
index 9dc18e0f3f..63e7310d3e 100644
--- a/tests/auto/qmenu/tst_qmenu.cpp
+++ b/tests/auto/qmenu/tst_qmenu.cpp
@@ -51,6 +51,7 @@
#include <QListWidget>
#include <QWidgetAction>
#include <QDesktopWidget>
+#include <qdialog.h>
#include <qmenu.h>
#include <qstyle.h>
@@ -104,6 +105,7 @@ private slots:
void setFixedWidth();
void deleteActionInTriggered();
void pushButtonPopulateOnAboutToShow();
+ void QTBUG_10735_crashWithDialog();
protected slots:
void onActivated(QAction*);
void onHighlighted(QAction*);
@@ -932,5 +934,57 @@ void tst_QMenu::pushButtonPopulateOnAboutToShow()
}
+class MyMenu : public QMenu
+{
+ Q_OBJECT
+public:
+ MyMenu() : m_currentIndex(0)
+ {
+ for (int i = 0; i < 2; ++i)
+ dialogActions[i] = addAction( QString("dialog %1").arg(i), dialogs + i, SLOT(exec()));
+ }
+
+
+ void activateAction(int index)
+ {
+ m_currentIndex = index;
+ popup(QPoint());
+ QTest::qWaitForWindowShown(this);
+ setActiveAction(dialogActions[index]);
+ QTimer::singleShot(500, this, SLOT(checkVisibility()));
+ QTest::keyClick(this, Qt::Key_Enter); //activation
+ }
+
+public slots:
+ void activateLastAction()
+ {
+ activateAction(1);
+ }
+
+ void checkVisibility()
+ {
+ QTRY_VERIFY(dialogs[m_currentIndex].isVisible());
+ if (m_currentIndex == 1) {
+ QApplication::closeAllWindows(); //this is the end of the test
+ }
+ }
+
+
+private:
+ QAction *dialogActions[2];
+ QDialog dialogs[2];
+ int m_currentIndex;
+};
+
+void tst_QMenu::QTBUG_10735_crashWithDialog()
+{
+ MyMenu menu;
+
+ QTimer::singleShot(1000, &menu, SLOT(activateLastAction()));
+ menu.activateAction(0);
+
+}
+
+
QTEST_MAIN(tst_QMenu)
#include "tst_qmenu.moc"