diff options
author | Shane Kearns <shane.kearns@accenture.com> | 2010-06-11 11:11:05 (GMT) |
---|---|---|
committer | Shane Kearns <shane.kearns@accenture.com> | 2010-06-11 15:14:19 (GMT) |
commit | 5471f3cc5f3b1ec9fbe15ba35ab23dfd9fcc42c9 (patch) | |
tree | 5207081b3e4dbab15ae3a2b14b622569549d384d /src/gui | |
parent | da424a2e8a8570e24eac6272bb410a51381fcad7 (diff) | |
download | Qt-5471f3cc5f3b1ec9fbe15ba35ab23dfd9fcc42c9.zip Qt-5471f3cc5f3b1ec9fbe15ba35ab23dfd9fcc42c9.tar.gz Qt-5471f3cc5f3b1ec9fbe15ba35ab23dfd9fcc42c9.tar.bz2 |
Thread safety for QFontEngineS60
On symbian, creating fonts requires a connection to the window server.
Window server sessions are not sharable across threads.
To avoid QFont crashing when used outside the GUI thread, we construct a
private session to the window server when the shared CONE session is not
available.
(CCoeEnv::Static() uses TLS, so it returns null outside of GUI thread)
The private session and screen device are stored in QThreadStorage, so
they are automatically deleted when the QThread exits.
Task-number: QTBUG-8874
Reviewed-by: mread
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/kernel/qapplication_s60.cpp | 25 | ||||
-rw-r--r-- | src/gui/kernel/qt_s60_p.h | 26 | ||||
-rw-r--r-- | src/gui/text/qfontdatabase_s60.cpp | 18 |
3 files changed, 57 insertions, 12 deletions
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 78027b2..f39b462 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -2046,4 +2046,29 @@ void QApplication::restoreOverrideCursor() #endif // QT_NO_CURSOR +QS60ThreadLocalData::QS60ThreadLocalData() +{ + CCoeEnv *env = CCoeEnv::Static(); + if (env) { + //if this is the UI thread, share objects owned by CONE + usingCONEinstances = true; + wsSession = env->WsSession(); + screenDevice = env->ScreenDevice(); + } + else { + usingCONEinstances = false; + qt_symbian_throwIfError(wsSession.Connect(qt_s60GetRFs())); + screenDevice = new CWsScreenDevice(wsSession); + screenDevice->Construct(); + } +} + +QS60ThreadLocalData::~QS60ThreadLocalData() +{ + if (!usingCONEinstances) { + delete screenDevice; + wsSession.Close(); + } +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index 58da302..bec51b8 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -62,6 +62,7 @@ #include "QtGui/qevent.h" #include "qpointer.h" #include "qapplication.h" +#include "QtCore/qthreadstorage.h" #include <w32std.h> #include <coecntrl.h> #include <eikenv.h> @@ -85,10 +86,21 @@ const TInt KInternalStatusPaneChange = 0x50000000; //this macro exists because EColor16MAP enum value doesn't exist in Symbian OS 9.2 #define Q_SYMBIAN_ECOLOR16MAP TDisplayMode(13) +class QS60ThreadLocalData +{ +public: + QS60ThreadLocalData(); + ~QS60ThreadLocalData(); + bool usingCONEinstances; + RWsSession wsSession; + CWsScreenDevice *screenDevice; +}; + class QS60Data { public: QS60Data(); + QThreadStorage<QS60ThreadLocalData *> tls; TUid uid; int screenDepth; QPoint lastCursorPos; @@ -125,9 +137,9 @@ public: int menuBeingConstructed : 1; QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type static inline void updateScreenSize(); - static inline RWsSession& wsSession(); + inline RWsSession& wsSession(); static inline RWindowGroup& windowGroup(); - static inline CWsScreenDevice* screenDevice(); + inline CWsScreenDevice* screenDevice(); static inline CCoeAppUi* appUi(); static inline CEikMenuBar* menuBar(); #ifdef Q_WS_S60 @@ -256,7 +268,10 @@ inline void QS60Data::updateScreenSize() inline RWsSession& QS60Data::wsSession() { - return CCoeEnv::Static()->WsSession(); + if(!tls.hasLocalData()) { + tls.setLocalData(new QS60ThreadLocalData); + } + return tls.localData()->wsSession; } inline RWindowGroup& QS60Data::windowGroup() @@ -266,7 +281,10 @@ inline RWindowGroup& QS60Data::windowGroup() inline CWsScreenDevice* QS60Data::screenDevice() { - return CCoeEnv::Static()->ScreenDevice(); + if(!tls.hasLocalData()) { + tls.setLocalData(new QS60ThreadLocalData); + } + return tls.localData()->screenDevice; } inline CCoeAppUi* QS60Data::appUi() diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp index 40fe3b7..61c5271 100644 --- a/src/gui/text/qfontdatabase_s60.cpp +++ b/src/gui/text/qfontdatabase_s60.cpp @@ -218,17 +218,19 @@ QFontEngineFTS60::QFontEngineFTS60(const QFontDef &fd) */ qreal QFontEngineS60::pixelsToPoints(qreal pixels, Qt::Orientation orientation) { + CWsScreenDevice* device = S60->screenDevice(); return (orientation == Qt::Horizontal? - S60->screenDevice()->HorizontalPixelsToTwips(pixels) - :S60->screenDevice()->VerticalPixelsToTwips(pixels)) / KTwipsPerPoint; + device->HorizontalPixelsToTwips(pixels) + :device->VerticalPixelsToTwips(pixels)) / KTwipsPerPoint; } qreal QFontEngineS60::pointsToPixels(qreal points, Qt::Orientation orientation) { + CWsScreenDevice* device = S60->screenDevice(); const int twips = points * KTwipsPerPoint; return orientation == Qt::Horizontal? - S60->screenDevice()->HorizontalTwipsToPixels(twips) - :S60->screenDevice()->VerticalTwipsToPixels(twips); + device->HorizontalTwipsToPixels(twips) + :device->VerticalTwipsToPixels(twips); } QFontEngineMultiS60::QFontEngineMultiS60(QFontEngine *first, int script, const QStringList &fallbackFamilies) @@ -267,16 +269,16 @@ static void initializeDb() QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - const int numTypeFaces = QS60Data::screenDevice()->NumTypefaces(); + const int numTypeFaces = S60->screenDevice()->NumTypefaces(); const QSymbianFontDatabaseExtrasImplementation *dbExtras = static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); bool fontAdded = false; for (int i = 0; i < numTypeFaces; i++) { TTypefaceSupport typefaceSupport; - QS60Data::screenDevice()->TypefaceSupport(typefaceSupport, i); + S60->screenDevice()->TypefaceSupport(typefaceSupport, i); CFont *font; // We have to get a font instance in order to know all the details TFontSpec fontSpec(typefaceSupport.iTypeface.iName, 11); - if (QS60Data::screenDevice()->GetNearestFontInPixels(font, fontSpec) != KErrNone) + if (S60->screenDevice()->GetNearestFontInPixels(font, fontSpec) != KErrNone) continue; if (font->TypeUid() == KCFbsFontUid) { TOpenFontFaceAttrib faceAttrib; @@ -318,7 +320,7 @@ static void initializeDb() fontAdded = true; } - QS60Data::screenDevice()->ReleaseFont(font); + S60->screenDevice()->ReleaseFont(font); } Q_ASSERT(fontAdded); |