summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorShane Kearns <shane.kearns@accenture.com>2010-06-11 11:11:05 (GMT)
committerShane Kearns <shane.kearns@accenture.com>2010-06-11 15:14:19 (GMT)
commit5471f3cc5f3b1ec9fbe15ba35ab23dfd9fcc42c9 (patch)
tree5207081b3e4dbab15ae3a2b14b622569549d384d /src/gui
parentda424a2e8a8570e24eac6272bb410a51381fcad7 (diff)
downloadQt-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.cpp25
-rw-r--r--src/gui/kernel/qt_s60_p.h26
-rw-r--r--src/gui/text/qfontdatabase_s60.cpp18
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);