Fix crash when accessing QStyleHints before QGuiApplication is constructed.

Make styleHints a static member variable of QGuiApplicationPrivate and
fix accessor accordingly. Extend tst_QApplication::settableStyleHints()
to run without QApplication instance as well and add a similar test
to  QGuiApplication.

Task-number: QTBUG-44499
Change-Id: I42b92ef38f7dd512d08d70accfa7dd4f09a22f01
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
This commit is contained in:
Friedemann Kleint 2015-02-23 17:01:24 +01:00
parent 7bbde34ee0
commit 33403f2c79
9 changed files with 59 additions and 16 deletions

View File

@ -163,6 +163,7 @@ QWindow *QGuiApplicationPrivate::focus_window = 0;
static QBasicMutex applicationFontMutex;
QFont *QGuiApplicationPrivate::app_font = 0;
QStyleHints *QGuiApplicationPrivate::styleHints = Q_NULLPTR;
bool QGuiApplicationPrivate::obey_desktop_settings = true;
QInputDeviceManager *QGuiApplicationPrivate::m_inputDeviceManager = 0;
@ -595,7 +596,6 @@ QGuiApplication::~QGuiApplication()
QGuiApplicationPrivate::QGuiApplicationPrivate(int &argc, char **argv, int flags)
: QCoreApplicationPrivate(argc, argv, flags),
styleHints(0),
inputMethod(0),
lastTouchType(QEvent::TouchEnd),
ownGlobalShareContext(false)
@ -1349,7 +1349,8 @@ QGuiApplicationPrivate::~QGuiApplicationPrivate()
cleanupThreadData();
delete styleHints;
delete QGuiApplicationPrivate::styleHints;
QGuiApplicationPrivate::styleHints = Q_NULLPTR;
delete inputMethod;
qt_cleanupFontDatabase();
@ -1717,7 +1718,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
}
mouse_buttons = buttons = e->buttons;
if (button & e->buttons) {
ulong doubleClickInterval = static_cast<ulong>(qApp->styleHints()->mouseDoubleClickInterval());
ulong doubleClickInterval = static_cast<ulong>(QGuiApplication::styleHints()->mouseDoubleClickInterval());
doubleClick = e->timestamp - mousePressTime < doubleClickInterval && button == mousePressButton;
type = frameStrut ? QEvent::NonClientAreaMouseButtonPress : QEvent::MouseButtonPress;
mousePressTime = e->timestamp;
@ -3294,9 +3295,9 @@ void QGuiApplication::restoreOverrideCursor()
*/
QStyleHints *QGuiApplication::styleHints()
{
if (!qGuiApp->d_func()->styleHints)
qGuiApp->d_func()->styleHints = new QStyleHints();
return qGuiApp->d_func()->styleHints;
if (!QGuiApplicationPrivate::styleHints)
QGuiApplicationPrivate::styleHints = new QStyleHints();
return QGuiApplicationPrivate::styleHints;
}
/*!

View File

@ -218,7 +218,7 @@ public:
static QFont *app_font;
QStyleHints *styleHints;
static QStyleHints *styleHints;
static bool obey_desktop_settings;
QInputMethod *inputMethod;

View File

@ -35,6 +35,7 @@
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformtheme.h>
#include <private/qguiapplication_p.h>
#include <qdebug.h>
QT_BEGIN_NAMESPACE
@ -46,6 +47,10 @@ static inline QVariant hint(QPlatformIntegration::StyleHint h)
static inline QVariant themeableHint(QPlatformTheme::ThemeHint th,
QPlatformIntegration::StyleHint ih)
{
if (!QCoreApplication::instance()) {
qWarning() << "Must construct a QGuiApplication before accessing a platform theme hint.";
return QVariant();
}
if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
const QVariant themeHint = theme->themeHint(th);
if (themeHint.isValid())

View File

@ -2892,7 +2892,7 @@ void QApplication::setStartDragTime(int ms)
int QApplication::startDragTime()
{
return qApp->styleHints()->startDragTime();
return QGuiApplication::styleHints()->startDragTime();
}
/*
@ -2930,7 +2930,7 @@ void QApplication::setStartDragDistance(int l)
int QApplication::startDragDistance()
{
return qApp->styleHints()->startDragDistance();
return QGuiApplication::styleHints()->startDragDistance();
}
/*!
@ -3973,7 +3973,7 @@ void QApplication::setCursorFlashTime(int msecs)
int QApplication::cursorFlashTime()
{
return qApp->styleHints()->cursorFlashTime();
return QGuiApplication::styleHints()->cursorFlashTime();
}
/*!
@ -3991,7 +3991,7 @@ void QApplication::setDoubleClickInterval(int ms)
int QApplication::doubleClickInterval()
{
return qApp->styleHints()->mouseDoubleClickInterval();
return QGuiApplication::styleHints()->mouseDoubleClickInterval();
}
/*!
@ -4019,7 +4019,7 @@ void QApplication::setKeyboardInputInterval(int ms)
int QApplication::keyboardInputInterval()
{
return qApp->styleHints()->keyboardInputInterval();
return QGuiApplication::styleHints()->keyboardInputInterval();
}
/*!

View File

@ -1181,7 +1181,7 @@ void QAbstractSpinBox::timerEvent(QTimerEvent *event)
killTimer(d->spinClickThresholdTimerId);
d->spinClickThresholdTimerId = -1;
d->effectiveSpinRepeatRate = d->buttonState & Keyboard
? qApp->styleHints()->keyboardAutoRepeatRate()
? QGuiApplication::styleHints()->keyboardAutoRepeatRate()
: d->spinClickTimerInterval;
d->spinClickTimerId = startTimer(d->effectiveSpinRepeatRate);
doStep = true;

View File

@ -2153,7 +2153,7 @@ QMenu *QLineEdit::createStandardContextMenu()
d->selectAllAction = action;
connect(action, SIGNAL(triggered()), SLOT(selectAll()));
if (!d->control->isReadOnly() && qApp->styleHints()->useRtlExtensions()) {
if (!d->control->isReadOnly() && QGuiApplication::styleHints()->useRtlExtensions()) {
popup->addSeparator();
QUnicodeControlCharacterMenu *ctrlCharacterMenu = new QUnicodeControlCharacterMenu(this, popup);
popup->addMenu(ctrlCharacterMenu);

View File

@ -2281,7 +2281,7 @@ QMenu *QWidgetTextControl::createStandardContextMenu(const QPointF &pos, QWidget
a->setObjectName(QStringLiteral("select-all"));
}
if ((d->interactionFlags & Qt::TextEditable) && qApp->styleHints()->useRtlExtensions()) {
if ((d->interactionFlags & Qt::TextEditable) && QGuiApplication::styleHints()->useRtlExtensions()) {
menu->addSeparator();
QUnicodeControlCharacterMenu *ctrlCharacterMenu = new QUnicodeControlCharacterMenu(this, menu);
menu->addMenu(ctrlCharacterMenu);

View File

@ -37,7 +37,9 @@
#include <QtGui/QWindow>
#include <QtGui/QScreen>
#include <QtGui/QCursor>
#include <QtGui/QFont>
#include <QtGui/QPalette>
#include <QtGui/QStyleHints>
#include <qpa/qwindowsysteminterface.h>
#include <qgenericplugin.h>
@ -74,6 +76,9 @@ private slots:
void genericPluginsAndWindowSystemEvents();
void layoutDirection();
void globalShareContext();
void settableStyleHints_data();
void settableStyleHints(); // Needs to run last as it changes style hints.
};
void tst_QGuiApplication::cleanup()
@ -961,4 +966,24 @@ void tst_QGuiApplication::globalShareContext()
#endif
}
void tst_QGuiApplication::settableStyleHints_data()
{
QTest::addColumn<bool>("appInstance");
QTest::newRow("app") << true;
QTest::newRow("no-app") << false;
}
void tst_QGuiApplication::settableStyleHints()
{
QFETCH(bool, appInstance);
int argc = 0;
QScopedPointer<QGuiApplication> app;
if (appInstance)
app.reset(new QGuiApplication(argc, 0));
const int keyboardInputInterval = 555;
QGuiApplication::styleHints()->setKeyboardInputInterval(keyboardInputInterval);
QCOMPARE(QGuiApplication::styleHints()->keyboardInputInterval(), keyboardInputInterval);
}
QTEST_APPLESS_MAIN(tst_QGuiApplication)

View File

@ -172,6 +172,7 @@ private slots:
void abortQuitOnShow();
void settableStyleHints_data();
void settableStyleHints(); // Needs to run last as it changes style hints.
};
@ -2298,10 +2299,21 @@ void tst_QApplication::abortQuitOnShow()
QCOMPARE(app.exec(), 1);
}
void tst_QApplication::settableStyleHints_data()
{
QTest::addColumn<bool>("appInstance");
QTest::newRow("app") << true;
QTest::newRow("no-app") << false;
}
void tst_QApplication::settableStyleHints()
{
QFETCH(bool, appInstance);
int argc = 0;
QApplication app(argc, 0);
QScopedPointer<QApplication> app;
if (appInstance)
app.reset(new QApplication(argc, 0));
QApplication::setCursorFlashTime(437);
QCOMPARE(QApplication::cursorFlashTime(), 437);
QApplication::setDoubleClickInterval(128);