diff options
Diffstat (limited to 'config.profiles/harmattan/patches')
15 files changed, 2232 insertions, 0 deletions
diff --git a/config.profiles/harmattan/patches/default_widget_size.diff b/config.profiles/harmattan/patches/default_widget_size.diff new file mode 100644 index 0000000..1f72881 --- /dev/null +++ b/config.profiles/harmattan/patches/default_widget_size.diff @@ -0,0 +1,13 @@ +Index: qt-maemo-qtp/src/gui/kernel/qwidget.cpp +=================================================================== +--- qt-maemo-qtp.orig/src/gui/kernel/qwidget.cpp ++++ qt-maemo-qtp/src/gui/kernel/qwidget.cpp +@@ -1326,7 +1326,7 @@ + data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,360,640); + } + #else +- data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480); ++ data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,854,480); + #endif + + focus_next = focus_prev = q; diff --git a/config.profiles/harmattan/patches/glshadercache.diff b/config.profiles/harmattan/patches/glshadercache.diff new file mode 100644 index 0000000..2c6ad9a --- /dev/null +++ b/config.profiles/harmattan/patches/glshadercache.diff @@ -0,0 +1,1003 @@ +Index: qt-maemo-qtp/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +=================================================================== +--- qt-maemo-qtp.orig/src/opengl/gl2paintengineex/qglengineshadermanager.cpp ++++ qt-maemo-qtp/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +@@ -42,12 +42,12 @@ + #include "qglengineshadermanager_p.h" + #include "qglengineshadersource_p.h" + #include "qpaintengineex_opengl2_p.h" ++#include "qglshadercache_p.h" + + #if defined(QT_DEBUG) + #include <QMetaEnum> + #endif + +- + QT_BEGIN_NAMESPACE + + static void qt_shared_shaders_free(void *data) +@@ -165,62 +165,89 @@ + + QGLShader* fragShader; + QGLShader* vertexShader; +- QByteArray source; ++ QByteArray vertexSource; ++ QByteArray fragSource; + + // Compile up the simple shader: +- source.clear(); +- source.append(qShaderSnippets[MainVertexShader]); +- source.append(qShaderSnippets[PositionOnlyVertexShader]); +- vertexShader = new QGLShader(QGLShader::Vertex, context, this); +- if (!vertexShader->compileSourceCode(source)) +- qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile"); +- +- source.clear(); +- source.append(qShaderSnippets[MainFragmentShader]); +- source.append(qShaderSnippets[ShockingPinkSrcFragmentShader]); +- fragShader = new QGLShader(QGLShader::Fragment, context, this); +- if (!fragShader->compileSourceCode(source)) +- qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile"); ++ vertexSource.append(qShaderSnippets[MainVertexShader]); ++ vertexSource.append(qShaderSnippets[PositionOnlyVertexShader]); ++ ++ fragSource.append(qShaderSnippets[MainFragmentShader]); ++ fragSource.append(qShaderSnippets[ShockingPinkSrcFragmentShader]); + + simpleShaderProg = new QGLShaderProgram(context, this); +- simpleShaderProg->addShader(vertexShader); +- simpleShaderProg->addShader(fragShader); +- simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); +- simpleShaderProg->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR); +- simpleShaderProg->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR); +- simpleShaderProg->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR); ++ ++ CachedShader simpleShaderCache(fragSource, vertexSource); ++ ++ bool inCache = simpleShaderCache.load(simpleShaderProg, context); ++ ++ if (!inCache) { ++ vertexShader = new QGLShader(QGLShader::Vertex, context, this); ++ if (!vertexShader->compileSourceCode(vertexSource)) ++ qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile"); ++ ++ fragShader = new QGLShader(QGLShader::Fragment, context, this); ++ if (!fragShader->compileSourceCode(fragSource)) ++ qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile"); ++ ++ simpleShaderProg->addShader(vertexShader); ++ simpleShaderProg->addShader(fragShader); ++ ++ simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); ++ simpleShaderProg->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR); ++ simpleShaderProg->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR); ++ simpleShaderProg->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR); ++ } ++ + simpleShaderProg->link(); +- if (!simpleShaderProg->isLinked()) { ++ ++ if (simpleShaderProg->isLinked()) { ++ if (!inCache) ++ simpleShaderCache.store(simpleShaderProg, context); ++ } else { + qCritical() << "Errors linking simple shader:" + << simpleShaderProg->log(); + } + + // Compile the blit shader: +- source.clear(); +- source.append(qShaderSnippets[MainWithTexCoordsVertexShader]); +- source.append(qShaderSnippets[UntransformedPositionVertexShader]); +- vertexShader = new QGLShader(QGLShader::Vertex, context, this); +- if (!vertexShader->compileSourceCode(source)) +- qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile"); +- +- source.clear(); +- source.append(qShaderSnippets[MainFragmentShader]); +- source.append(qShaderSnippets[ImageSrcFragmentShader]); +- fragShader = new QGLShader(QGLShader::Fragment, context, this); +- if (!fragShader->compileSourceCode(source)) +- qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile"); ++ vertexSource.clear(); ++ vertexSource.append(qShaderSnippets[MainWithTexCoordsVertexShader]); ++ vertexSource.append(qShaderSnippets[UntransformedPositionVertexShader]); ++ ++ fragSource.clear(); ++ fragSource.append(qShaderSnippets[MainFragmentShader]); ++ fragSource.append(qShaderSnippets[ImageSrcFragmentShader]); + + blitShaderProg = new QGLShaderProgram(context, this); +- blitShaderProg->addShader(vertexShader); +- blitShaderProg->addShader(fragShader); +- blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); +- blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); ++ ++ CachedShader blitShaderCache(fragSource, vertexSource); ++ ++ inCache = blitShaderCache.load(blitShaderProg, context); ++ ++ if (!inCache) { ++ vertexShader = new QGLShader(QGLShader::Vertex, context, this); ++ if (!vertexShader->compileSourceCode(vertexSource)) ++ qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile"); ++ ++ fragShader = new QGLShader(QGLShader::Fragment, context, this); ++ if (!fragShader->compileSourceCode(fragSource)) ++ qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile"); ++ ++ blitShaderProg->addShader(vertexShader); ++ blitShaderProg->addShader(fragShader); ++ ++ blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); ++ blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); ++ } ++ + blitShaderProg->link(); +- if (!blitShaderProg->isLinked()) { ++ if (blitShaderProg->isLinked()) { ++ if (!inCache) ++ blitShaderCache.store(blitShaderProg, context); ++ } else { + qCritical() << "Errors linking blit shader:" +- << simpleShaderProg->log(); ++ << blitShaderProg->log(); + } +- + } + + QGLEngineSharedShaders::~QGLEngineSharedShaders() +@@ -262,99 +289,108 @@ + } + } + +- QGLShader *vertexShader = 0; +- QGLShader *fragShader = 0; +- QGLEngineShaderProg *newProg = 0; +- bool success = false; ++ QScopedPointer<QGLEngineShaderProg> newProg; + + do { +- QByteArray source; ++ QByteArray fragSource; + // Insert the custom stage before the srcPixel shader to work around an ATI driver bug + // where you cannot forward declare a function that takes a sampler as argument. + if (prog.srcPixelFragShader == CustomImageSrcFragmentShader) +- source.append(prog.customStageSource); +- source.append(qShaderSnippets[prog.mainFragShader]); +- source.append(qShaderSnippets[prog.srcPixelFragShader]); ++ fragSource.append(prog.customStageSource); ++ fragSource.append(qShaderSnippets[prog.mainFragShader]); ++ fragSource.append(qShaderSnippets[prog.srcPixelFragShader]); + if (prog.compositionFragShader) +- source.append(qShaderSnippets[prog.compositionFragShader]); ++ fragSource.append(qShaderSnippets[prog.compositionFragShader]); + if (prog.maskFragShader) +- source.append(qShaderSnippets[prog.maskFragShader]); +- fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this); +- QByteArray description; ++ fragSource.append(qShaderSnippets[prog.maskFragShader]); ++ ++ QByteArray vertexSource; ++ vertexSource.append(qShaderSnippets[prog.mainVertexShader]); ++ vertexSource.append(qShaderSnippets[prog.positionVertexShader]); ++ ++ QScopedPointer<QGLShaderProgram> shaderProgram(new QGLShaderProgram(ctxGuard.context(), this)); ++ ++ CachedShader shaderCache(fragSource, vertexSource); ++ bool inCache = shaderCache.load(shaderProgram.data(), ctxGuard.context()); ++ ++ if (!inCache) { ++ ++ QScopedPointer<QGLShader> fragShader(new QGLShader(QGLShader::Fragment, ctxGuard.context(), this)); ++ QByteArray description; + #if defined(QT_DEBUG) +- // Name the shader for easier debugging +- description.append("Fragment shader: main="); +- description.append(snippetNameStr(prog.mainFragShader)); +- description.append(", srcPixel="); +- description.append(snippetNameStr(prog.srcPixelFragShader)); +- if (prog.compositionFragShader) { +- description.append(", composition="); +- description.append(snippetNameStr(prog.compositionFragShader)); +- } +- if (prog.maskFragShader) { +- description.append(", mask="); +- description.append(snippetNameStr(prog.maskFragShader)); +- } +- fragShader->setObjectName(QString::fromLatin1(description)); ++ // Name the shader for easier debugging ++ description.append("Fragment shader: main="); ++ description.append(snippetNameStr(prog.mainFragShader)); ++ description.append(", srcPixel="); ++ description.append(snippetNameStr(prog.srcPixelFragShader)); ++ if (prog.compositionFragShader) { ++ description.append(", composition="); ++ description.append(snippetNameStr(prog.compositionFragShader)); ++ } ++ if (prog.maskFragShader) { ++ description.append(", mask="); ++ description.append(snippetNameStr(prog.maskFragShader)); ++ } ++ fragShader->setObjectName(QString::fromLatin1(description)); + #endif +- if (!fragShader->compileSourceCode(source)) { +- qWarning() << "Warning:" << description << "failed to compile!"; +- break; +- } ++ if (!fragShader->compileSourceCode(fragSource)) { ++ qWarning() << "Warning:" << description << "failed to compile!"; ++ break; ++ } + +- source.clear(); +- source.append(qShaderSnippets[prog.mainVertexShader]); +- source.append(qShaderSnippets[prog.positionVertexShader]); +- vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this); ++ QScopedPointer<QGLShader> vertexShader(new QGLShader(QGLShader::Vertex, ctxGuard.context(), this)); + #if defined(QT_DEBUG) +- // Name the shader for easier debugging +- description.clear(); +- description.append("Vertex shader: main="); +- description.append(snippetNameStr(prog.mainVertexShader)); +- description.append(", position="); +- description.append(snippetNameStr(prog.positionVertexShader)); +- vertexShader->setObjectName(QString::fromLatin1(description)); ++ // Name the shader for easier debugging ++ description.clear(); ++ description.append("Vertex shader: main="); ++ description.append(snippetNameStr(prog.mainVertexShader)); ++ description.append(", position="); ++ description.append(snippetNameStr(prog.positionVertexShader)); ++ vertexShader->setObjectName(QString::fromLatin1(description)); + #endif +- if (!vertexShader->compileSourceCode(source)) { +- qWarning() << "Warning:" << description << "failed to compile!"; +- break; +- } ++ if (!vertexShader->compileSourceCode(vertexSource)) { ++ qWarning() << "Warning:" << description << "failed to compile!"; ++ break; ++ } + +- newProg = new QGLEngineShaderProg(prog); ++ shaderProgram->addShader(vertexShader.take()); ++ shaderProgram->addShader(fragShader.take()); + +- // If the shader program's not found in the cache, create it now. +- newProg->program = new QGLShaderProgram(ctxGuard.context(), this); +- newProg->program->addShader(vertexShader); +- newProg->program->addShader(fragShader); +- +- // We have to bind the vertex attribute names before the program is linked: +- newProg->program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); +- if (newProg->useTextureCoords) +- newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); +- if (newProg->useOpacityAttribute) +- newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR); +- if (newProg->usePmvMatrixAttribute) { +- newProg->program->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR); +- newProg->program->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR); +- newProg->program->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR); ++ // We have to bind the vertex attribute names before the program is linked: ++ shaderProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); ++ if (prog.useTextureCoords) ++ shaderProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); ++ if (prog.useOpacityAttribute) ++ shaderProgram->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR); ++ if (prog.usePmvMatrixAttribute) { ++ shaderProgram->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR); ++ shaderProgram->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR); ++ shaderProgram->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR); ++ } + } + ++ newProg.reset(new QGLEngineShaderProg(prog)); ++ newProg->program = shaderProgram.take(); ++ + newProg->program->link(); +- if (!newProg->program->isLinked()) { ++ if (newProg->program->isLinked()) { ++ if (!inCache) ++ shaderCache.store(newProg->program, ctxGuard.context()); ++ } else { + QLatin1String none("none"); + QLatin1String br("\n"); + QString error; +- error = QLatin1String("Shader program failed to link,") ++ error = QLatin1String("Shader program failed to link,"); + #if defined(QT_DEBUG) +- + br +- + QLatin1String(" Shaders Used:") + br +- + QLatin1String(" ") + vertexShader->objectName() + QLatin1String(": ") + br +- + QLatin1String(vertexShader->sourceCode()) + br +- + QLatin1String(" ") + fragShader->objectName() + QLatin1String(": ") + br +- + QLatin1String(fragShader->sourceCode()) + br ++ error += QLatin1String("\n Shaders Used:\n"); ++ for (int i = 0; i < newProg->program->shaders().count(); ++i) { ++ QGLShader *shader = newProg->program->shaders().at(i); ++ error += QLatin1String(" ") + shader->objectName() + QLatin1String(": \n") ++ + QLatin1String(shader->sourceCode()) + br; ++ } + #endif +- + QLatin1String(" Error Log:\n") +- + QLatin1String(" ") + newProg->program->log(); ++ error += QLatin1String(" Error Log:\n") ++ + QLatin1String(" ") + newProg->program->log(); + qWarning() << error; + break; + } +@@ -376,26 +412,10 @@ + } + } + +- cachedPrograms.insert(0, newProg); +- +- success = true; ++ cachedPrograms.insert(0, newProg.data()); + } while (false); + +- // Clean up everything if we weren't successful +- if (!success) { +- if (newProg) { +- delete newProg; // Also deletes the QGLShaderProgram which in turn deletes the QGLShaders +- newProg = 0; +- } +- else { +- if (vertexShader) +- delete vertexShader; +- if (fragShader) +- delete fragShader; +- } +- } +- +- return newProg; ++ return newProg.take(); + } + + void QGLEngineSharedShaders::cleanupCustomStage(QGLCustomShaderStage* stage) +Index: qt-maemo-qtp/src/opengl/gl2paintengineex/qglshadercache_meego_p.h +=================================================================== +--- /dev/null ++++ qt-maemo-qtp/src/opengl/gl2paintengineex/qglshadercache_meego_p.h +@@ -0,0 +1,457 @@ ++/**************************************************************************** ++** ++** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ++** All rights reserved. ++** Contact: Nokia Corporation (qt-info@nokia.com) ++** ++** This file is part of the QtOpenGL module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** No Commercial Usage ++** This file contains pre-release code and may not be distributed. ++** You may use this file in accordance with the terms and conditions ++** contained in the Technology Preview License Agreement accompanying ++** this package. ++** ++** GNU Lesser General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU Lesser ++** General Public License version 2.1 as published by the Free Software ++** Foundation and appearing in the file LICENSE.LGPL included in the ++** packaging of this file. Please review the following information to ++** ensure the GNU Lesser General Public License version 2.1 requirements ++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** If you have questions regarding the use of this file, please contact ++** Nokia at qt-info@nokia.com. ++** ++** ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++// ++// W A R N I N G ++// ------------- ++// ++// This file is not part of the Qt API. It exists purely as an ++// implementation detail. This header file may change from version to ++// version without notice, or even be removed. ++// ++// We mean it. ++// ++ ++#ifndef QGLSHADERCACHE_MEEGO_P_H ++#define QGLSHADERCACHE_MEEGO_P_H ++ ++#include <QtCore/qglobal.h> ++ ++#if defined(QT_MEEGO_EXPERIMENTAL_SHADERCACHE) && defined(QT_OPENGL_ES_2) ++ ++#include <QtCore/qcryptographichash.h> ++#include <QtCore/qsharedmemory.h> ++#include <QtCore/qsystemsemaphore.h> ++ ++#ifndef QT_BOOTSTRAPPED ++# include <GLES2/gl2ext.h> ++#endif ++#if defined(QT_DEBUG) || defined(QT_MEEGO_EXPERIMENTAL_SHADERCACHE_TRACE) ++# include <syslog.h> ++#endif ++ ++QT_BEGIN_HEADER ++ ++/* ++ This cache stores internal Qt shader programs in shared memory. ++ ++ This header file is ugly on purpose and can only be included once. It is only to be used ++ for the internal shader cache, not as a generic cache for anyone's shaders. ++ ++ The cache stores either ShaderCacheMaxEntries shader programs or ShaderCacheDataSize kilobytes ++ of shader programs, whatever limit is reached first. ++ ++ The layout of the cache is as outlined in the CachedShaders struct. After some ++ integers, an array of headers is reserved, then comes the space for the actual binaries. ++ ++ Shader Programs are identified by the md5sum of their frag and vertex shader source code. ++ ++ Shader Programs are never removed. The cache never shrinks or re-shuffles. This is done ++ on purpose to ensure minimum amount of locking, no alignment problems and very few write ++ operations. ++ ++ Note: Locking the shader cache could be expensive, because the entire system might hang. ++ That's why the cache is immutable to minimize the time we need to keep it locked. ++ ++ Why is it Meego specific? ++ ++ First, the size is chosen so that it fits to generic meego usage. Second, on Meego, there's ++ always at least one Qt application active (the launcher), so the cache will never be destroyed. ++ Only when the last Qt app exits, the cache dies, which should only be when someone kills the ++ X11 server. And last but not least it was only tested with Meego's SGX driver. ++ ++ There's a small tool in src/opengl/util/meego that dumps the contents of the cache. ++ */ ++ ++// anonymous namespace, prevent exporting of the private symbols ++namespace ++{ ++ ++struct CachedShaderHeader ++{ ++ /* the index in the data[] member of CachedShaders */ ++ int index; ++ /* the size of the binary shader */ ++ GLsizei size; ++ /* the format of the binary shader */ ++ GLenum format; ++ /* the md5sum of the frag+vertex shaders */ ++ char md5Sum[16]; ++}; ++ ++enum ++{ ++ /* The maximum amount of shader programs the cache can hold */ ++ ShaderCacheMaxEntries = 20 ++}; ++ ++typedef CachedShaderHeader CachedShaderHeaders[ShaderCacheMaxEntries]; ++ ++enum ++{ ++ // ShaderCacheDataSize is 20k minus the other data members of CachedShaders ++ ShaderCacheDataSize = 1024 * ShaderCacheMaxEntries - sizeof(CachedShaderHeaders) - 2 * sizeof(int) ++}; ++ ++struct CachedShaders ++{ ++ /* How much space is still available in the cache */ ++ inline int availableSize() const { return ShaderCacheDataSize - dataSize; } ++ ++ /* The current amount of cached shaders */ ++ int shaderCount; ++ ++ /* The current amount (in bytes) of cached data */ ++ int dataSize; ++ ++ /* The headers describing the shaders */ ++ CachedShaderHeaders headers; ++ ++ /* The actual binary data of the shader programs */ ++ char data[ShaderCacheDataSize]; ++}; ++ ++//#define QT_DEBUG_SHADER_CACHE ++#ifdef QT_DEBUG_SHADER_CACHE ++static QDebug shaderCacheDebug() ++{ ++ return QDebug(QtDebugMsg); ++} ++#else ++static inline QNoDebug shaderCacheDebug() { return QNoDebug(); } ++#endif ++ ++class ShaderCacheSharedMemory ++{ ++public: ++ ShaderCacheSharedMemory() ++ : shm(QLatin1String("qt_gles2_shadercache_" QT_VERSION_STR)) ++ { ++ // we need a system semaphore here, since cache creation and initialization must be atomic ++ QSystemSemaphore attachSemaphore(QLatin1String("qt_gles2_shadercache_mutex_" QT_VERSION_STR), 1); ++ ++ if (!attachSemaphore.acquire()) { ++ shaderCacheDebug() << "Unable to require shader cache semaphore:" << attachSemaphore.errorString(); ++ return; ++ } ++ ++ if (shm.attach()) { ++ // success! ++ shaderCacheDebug() << "Attached to shader cache"; ++ } else { ++ ++ // no cache exists - create and initialize it ++ if (shm.create(sizeof(CachedShaders))) { ++ shaderCacheDebug() << "Created new shader cache"; ++ initializeCache(); ++ } else { ++ shaderCacheDebug() << "Unable to create shader cache:" << shm.errorString(); ++ } ++ } ++ ++ attachSemaphore.release(); ++ } ++ ++ inline bool isAttached() const { return shm.isAttached(); } ++ ++ inline bool lock() { return shm.lock(); } ++ inline bool unlock() { return shm.unlock(); } ++ inline void *data() { return shm.data(); } ++ inline QString errorString() { return shm.errorString(); } ++ ++ ~ShaderCacheSharedMemory() ++ { ++ if (!shm.detach()) ++ shaderCacheDebug() << "Unable to detach shader cache" << shm.errorString(); ++ } ++ ++private: ++ void initializeCache() ++ { ++ // no need to lock the shared memory since we're already protected by the ++ // attach system semaphore. ++ ++ void *data = shm.data(); ++ Q_ASSERT(data); ++ ++ memset(data, 0, sizeof(CachedShaders)); ++ } ++ ++ QSharedMemory shm; ++}; ++ ++class ShaderCacheLocker ++{ ++public: ++ inline ShaderCacheLocker(ShaderCacheSharedMemory *cache) ++ : shm(cache->lock() ? cache : (ShaderCacheSharedMemory *)0) ++ { ++ if (!shm) ++ shaderCacheDebug() << "Unable to lock shader cache" << cache->errorString(); ++ } ++ ++ inline bool isLocked() const { return shm; } ++ ++ inline ~ShaderCacheLocker() ++ { ++ if (!shm) ++ return; ++ if (!shm->unlock()) ++ shaderCacheDebug() << "Unable to unlock shader cache" << shm->errorString(); ++ } ++ ++private: ++ ShaderCacheSharedMemory *shm; ++}; ++ ++#ifdef QT_BOOTSTRAPPED ++} // end namespace ++#else ++ ++static void traceCacheOverflow(const char *message) ++{ ++#if defined(QT_DEBUG) || defined (QT_MEEGO_EXPERIMENTAL_SHADERCACHE_TRACE) ++ openlog(qPrintable(QCoreApplication::applicationName()), LOG_PID | LOG_ODELAY, LOG_USER); ++ syslog(LOG_DEBUG, message); ++ closelog(); ++#endif ++ shaderCacheDebug() << message; ++} ++ ++Q_GLOBAL_STATIC(ShaderCacheSharedMemory, shaderCacheSharedMemory) ++ ++/* ++ Finds the index of the shader program identified by md5Sum in the cache. ++ Note: Does NOT lock the cache for reading, the cache must already be locked! ++ ++ Returns -1 when no shader was found. ++ */ ++static int qt_cache_index_unlocked(const QByteArray &md5Sum, CachedShaders *cache) ++{ ++ for (int i = 0; i < cache->shaderCount; ++i) { ++ if (qstrncmp(md5Sum.constData(), cache->headers[i].md5Sum, 16) == 0) { ++ return i; ++ } ++ } ++ return -1; ++} ++ ++/* Returns the index of the shader identified by md5Sum */ ++static int qt_cache_index(const QByteArray &md5Sum) ++{ ++ ShaderCacheSharedMemory *shm = shaderCacheSharedMemory(); ++ if (!shm || !shm->isAttached()) ++ return false; ++ ++ Q_ASSERT(md5Sum.length() == 16); ++ ++ ShaderCacheLocker locker(shm); ++ if (!locker.isLocked()) ++ return false; ++ ++ void *data = shm->data(); ++ Q_ASSERT(data); ++ ++ CachedShaders *cache = reinterpret_cast<CachedShaders *>(data); ++ ++ return qt_cache_index_unlocked(md5Sum, cache); ++} ++ ++/* Loads the cached shader at index \a shaderIndex into \a program ++ * Note: Since the cache is immutable, this operation doesn't lock the shared memory. ++ */ ++static bool qt_cached_shader(QGLShaderProgram *program, const QGLContext *ctx, int shaderIndex) ++{ ++ Q_ASSERT(shaderIndex >= 0 && shaderIndex <= ShaderCacheMaxEntries); ++ Q_ASSERT(program); ++ ++ ShaderCacheSharedMemory *shm = shaderCacheSharedMemory(); ++ if (!shm || !shm->isAttached()) ++ return false; ++ ++ void *data = shm->data(); ++ Q_ASSERT(data); ++ ++ CachedShaders *cache = reinterpret_cast<CachedShaders *>(data); ++ ++ shaderCacheDebug() << "fetching cached shader at index" << shaderIndex ++ << "dataIndex" << cache->headers[shaderIndex].index ++ << "size" << cache->headers[shaderIndex].size ++ << "format" << cache->headers[shaderIndex].format; ++ ++ // call program->programId first, since that resolves the glProgramBinaryOES symbol ++ GLuint programId = program->programId(); ++ glProgramBinaryOES(programId, cache->headers[shaderIndex].format, ++ cache->data + cache->headers[shaderIndex].index, ++ cache->headers[shaderIndex].size); ++ ++ return true; ++} ++ ++/* Stores the shader program in the cache. Returns false if there's an error with the cache, or ++ if the cache is too small to hold the shader. */ ++static bool qt_cache_shader(const QGLShaderProgram *shader, const QGLContext *ctx, const QByteArray &md5Sum) ++{ ++ ShaderCacheSharedMemory *shm = shaderCacheSharedMemory(); ++ if (!shm || !shm->isAttached()) ++ return false; ++ ++ void *data = shm->data(); ++ Q_ASSERT(data); ++ ++ CachedShaders *cache = reinterpret_cast<CachedShaders *>(data); ++ ++ ShaderCacheLocker locker(shm); ++ if (!locker.isLocked()) ++ return false; ++ ++ int cacheIdx = cache->shaderCount; ++ if (cacheIdx >= ShaderCacheMaxEntries) { ++ traceCacheOverflow("Qt OpenGL shader cache index overflow!"); ++ return false; ++ } ++ ++ // now that we have the lock on the shared memory, make sure no one ++ // inserted the shader already while we were unlocked ++ if (qt_cache_index_unlocked(md5Sum, cache) != -1) ++ return true; // already cached ++ ++ shaderCacheDebug() << "Caching shader at index" << cacheIdx; ++ ++ GLint binaryLength = 0; ++ glGetProgramiv(shader->programId(), GL_PROGRAM_BINARY_LENGTH_OES, &binaryLength); ++ ++ if (!binaryLength) { ++ shaderCacheDebug() << "Unable to determine binary shader size!"; ++ return false; ++ } ++ ++ if (binaryLength > cache->availableSize()) { ++ traceCacheOverflow("Qt OpenGL shader cache data overflow!"); ++ return false; ++ } ++ ++ GLsizei size = 0; ++ GLenum format = 0; ++ glGetProgramBinaryOES(shader->programId(), binaryLength, &size, &format, ++ cache->data + cache->dataSize); ++ ++ if (!size) { ++ shaderCacheDebug() << "Unable to get binary shader!"; ++ return false; ++ } ++ ++ cache->headers[cacheIdx].index = cache->dataSize; ++ cache->dataSize += binaryLength; ++ ++cache->shaderCount; ++ cache->headers[cacheIdx].size = binaryLength; ++ cache->headers[cacheIdx].format = format; ++ ++ memcpy(cache->headers[cacheIdx].md5Sum, md5Sum.constData(), 16); ++ ++ shaderCacheDebug() << "cached shader size" << size ++ << "format" << format ++ << "binarySize" << binaryLength ++ << "cache index" << cacheIdx ++ << "data index" << cache->headers[cacheIdx].index; ++ ++ return true; ++} ++ ++} // namespace ++ ++QT_BEGIN_NAMESPACE ++ ++QT_MODULE(OpenGL) ++ ++class CachedShader ++{ ++public: ++ CachedShader(const QByteArray &fragSource, const QByteArray &vertexSource) ++ : cacheIdx(-1) ++ { ++ QCryptographicHash md5Hash(QCryptographicHash::Md5); ++ ++ md5Hash.addData(fragSource); ++ md5Hash.addData(vertexSource); ++ ++ md5Sum = md5Hash.result(); ++ } ++ ++ bool isCached() ++ { ++ return cacheIndex() != -1; ++ } ++ ++ int cacheIndex() ++ { ++ if (cacheIdx != -1) ++ return cacheIdx; ++ cacheIdx = qt_cache_index(md5Sum); ++ return cacheIdx; ++ } ++ ++ bool load(QGLShaderProgram *program, const QGLContext *ctx) ++ { ++ if (cacheIndex() == -1) ++ return false; ++ return qt_cached_shader(program, ctx, cacheIdx); ++ } ++ ++ bool store(QGLShaderProgram *program, const QGLContext *ctx) ++ { ++ return qt_cache_shader(program, ctx, md5Sum); ++ } ++ ++private: ++ QByteArray md5Sum; ++ int cacheIdx; ++}; ++ ++ ++QT_END_NAMESPACE ++ ++#endif ++ ++QT_END_HEADER ++ ++#endif ++#endif +Index: qt-maemo-qtp/src/opengl/gl2paintengineex/qglshadercache_p.h +=================================================================== +--- /dev/null ++++ qt-maemo-qtp/src/opengl/gl2paintengineex/qglshadercache_p.h +@@ -0,0 +1,98 @@ ++/**************************************************************************** ++** ++** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ++** All rights reserved. ++** Contact: Nokia Corporation (qt-info@nokia.com) ++** ++** This file is part of the QtOpenGL module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** No Commercial Usage ++** This file contains pre-release code and may not be distributed. ++** You may use this file in accordance with the terms and conditions ++** contained in the Technology Preview License Agreement accompanying ++** this package. ++** ++** GNU Lesser General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU Lesser ++** General Public License version 2.1 as published by the Free Software ++** Foundation and appearing in the file LICENSE.LGPL included in the ++** packaging of this file. Please review the following information to ++** ensure the GNU Lesser General Public License version 2.1 requirements ++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** If you have questions regarding the use of this file, please contact ++** Nokia at qt-info@nokia.com. ++** ++** ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++// ++// W A R N I N G ++// ------------- ++// ++// This file is not part of the Qt API. It exists purely as an ++// implementation detail. This header file may change from version to ++// version without notice, or even be removed. ++// ++// We mean it. ++// ++ ++#ifndef QGLSHADERCACHE_P_H ++#define QGLSHADERCACHE_P_H ++ ++#include <QtCore/qglobal.h> ++ ++#if defined(QT_MEEGO_EXPERIMENTAL_SHADERCACHE) && defined(QT_OPENGL_ES_2) ++# include "qglshadercache_meego_p.h" ++#else ++ ++QT_BEGIN_HEADER ++ ++QT_BEGIN_NAMESPACE ++ ++QT_MODULE(OpenGL) ++ ++class QGLShaderProgram; ++class QGLContext; ++ ++class CachedShader ++{ ++public: ++ inline CachedShader(const QByteArray &, const QByteArray &) ++ {} ++ ++ inline bool isCached() ++ { ++ return false; ++ } ++ ++ inline bool load(QGLShaderProgram *, const QGLContext *) ++ { ++ return false; ++ } ++ ++ inline bool store(QGLShaderProgram *, const QGLContext *) ++ { ++ return false; ++ } ++}; ++ ++QT_END_NAMESPACE ++ ++QT_END_HEADER ++ ++#endif ++#endif +Index: qt-maemo-qtp/src/opengl/opengl.pro +=================================================================== +--- qt-maemo-qtp.orig/src/opengl/opengl.pro ++++ qt-maemo-qtp/src/opengl/opengl.pro +@@ -58,7 +58,9 @@ + gl2paintengineex/qglcustomshaderstage_p.h \ + gl2paintengineex/qtriangulatingstroker_p.h \ + gl2paintengineex/qtriangulator_p.h \ +- gl2paintengineex/qtextureglyphcache_gl_p.h ++ gl2paintengineex/qtextureglyphcache_gl_p.h \ ++ gl2paintengineex/qglshadercache_p.h \ ++ gl2paintengineex/qglshadercache_meego_p.h + + SOURCES += qglshaderprogram.cpp \ + qglpixmapfilter.cpp \ +Index: qt-maemo-qtp/src/opengl/util/meego/main.cpp +=================================================================== +--- /dev/null ++++ qt-maemo-qtp/src/opengl/util/meego/main.cpp +@@ -0,0 +1,48 @@ ++#include <QtCore/qdebug.h> ++ ++#define QT_DEBUG_SHADER_CACHE ++#define QT_MEEGO_EXPERIMENTAL_SHADERCACHE ++#define QT_OPENGL_ES_2 ++#define QT_BOOTSTRAPPED ++ ++typedef int GLsizei; ++typedef unsigned int GLenum; ++ ++#include "../../gl2paintengineex/qglshadercache_meego_p.h" ++ ++#include <stdlib.h> ++#include <stdio.h> ++ ++int main() ++{ ++ ShaderCacheSharedMemory shm; ++ ++ if (!shm.isAttached()) { ++ fprintf(stderr, "Unable to attach to shared memory\n"); ++ return EXIT_FAILURE; ++ } ++ ++ ShaderCacheLocker locker(&shm); ++ if (!locker.isLocked()) { ++ fprintf(stderr, "Unable to lock shared memory\n"); ++ return EXIT_FAILURE; ++ } ++ ++ void *data = shm.data(); ++ Q_ASSERT(data); ++ ++ CachedShaders *cache = reinterpret_cast<CachedShaders *>(data); ++ ++ for (int i = 0; i < cache->shaderCount; ++i) { ++ printf("Shader %d: %d bytes\n", i, cache->headers[i].size); ++ } ++ ++ printf("\nSummary:\n\n" ++ " Amount of cached shaders: %d\n" ++ " Bytes used: %d\n" ++ " Bytes available: %d\n", ++ cache->shaderCount, cache->dataSize, cache->availableSize()); ++ ++ return EXIT_SUCCESS; ++} ++ +Index: qt-maemo-qtp/src/opengl/util/meego/shader-cache-introspector.pro +=================================================================== +--- /dev/null ++++ qt-maemo-qtp/src/opengl/util/meego/shader-cache-introspector.pro +@@ -0,0 +1,7 @@ ++TEMPLATE = app ++ ++SOURCES += main.cpp ++ ++TARGET = shader-cache-introspector ++ ++QT = core diff --git a/config.profiles/harmattan/patches/icu.diff b/config.profiles/harmattan/patches/icu.diff new file mode 100644 index 0000000..16a17fd --- /dev/null +++ b/config.profiles/harmattan/patches/icu.diff @@ -0,0 +1,732 @@ +diff --git a/configure b/configure +index 3a748e2..77232dc 100755 +--- a/configure ++++ b/configure +@@ -779,6 +779,7 @@ CFG_PULSEAUDIO=auto + CFG_COREWLAN=auto + CFG_ICD=auto + CFG_NOPROCESS=no ++CFG_ICU=no + + # initalize variables used for installation + QT_INSTALL_PREFIX= +@@ -940,7 +941,7 @@ while [ "$#" -gt 0 ]; do + VAL=no + ;; + #Qt style yes options +- -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-xinput2|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-carbon|-universal|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-audio-backend|-svg|-declarative|-javascript-jit|-script|-scripttools|-rpath|-force-pkg-config|-s60|-usedeffiles) ++ -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-xinput2|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-carbon|-universal|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-audio-backend|-svg|-declarative|-javascript-jit|-script|-scripttools|-rpath|-force-pkg-config|-s60|-usedeffiles|-icu) + VAR=`echo $1 | sed "s,^-\(.*\),\1,"` + VAL=yes + ;; +@@ -2242,6 +2243,13 @@ while [ "$#" -gt 0 ]; do + QT_CFLAGS_FPU=$VAL + fi + ;; ++ icu) ++ if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then ++ CFG_ICU="$VAL" ++ else ++ UNKNOWN_OPT=yes ++ fi ++ ;; + *) + UNKNOWN_OPT=yes + ;; +@@ -7040,6 +7048,10 @@ if [ "$CFG_ICD" = "yes" ]; then + QT_CONFIG="$QT_CONFIG icd" + fi + ++if [ "$CFG_ICU" = "yes" ]; then ++ QT_CONFIG="$QT_CONFIG icu" ++fi ++ + # + # Some Qt modules are too advanced in C++ for some old compilers + # Detect here the platforms where they are known to work. +diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp +index 7cdc256..11a85d5 100644 +--- a/src/corelib/tools/qchar.cpp ++++ b/src/corelib/tools/qchar.cpp +@@ -57,6 +57,12 @@ + + QT_BEGIN_NAMESPACE + ++#ifdef QT_USE_ICU ++// from qlocale_icu.cpp ++extern uint qt_u_toUpper(uint c); ++extern uint qt_u_toLower(uint c); ++#endif ++ + #ifndef QT_NO_CODEC_FOR_C_STRINGS + # ifdef QT_NO_TEXTCODEC + # define QT_NO_CODEC_FOR_C_STRINGS +@@ -1076,6 +1082,12 @@ QChar::UnicodeVersion QChar::unicodeVersion(ushort ucs2) + */ + QChar QChar::toLower() const + { ++#ifdef QT_USE_ICU ++ uint res = qt_u_toLower(ucs); ++ if (res) ++ return QChar(res); ++ // else fall through ++#endif + const QUnicodeTables::Properties *p = qGetProp(ucs); + if (!p->lowerCaseSpecial) + return ucs + p->lowerCaseDiff; +@@ -1090,6 +1102,12 @@ QChar QChar::toLower() const + */ + uint QChar::toLower(uint ucs4) + { ++#ifdef QT_USE_ICU ++ uint res = qt_u_toLower(ucs4); ++ if (res) ++ return res; ++ // else fall through ++#endif + if (ucs4 > UNICODE_LAST_CODEPOINT) + return ucs4; + const QUnicodeTables::Properties *p = qGetProp(ucs4); +@@ -1106,6 +1124,12 @@ uint QChar::toLower(uint ucs4) + */ + ushort QChar::toLower(ushort ucs2) + { ++#ifdef QT_USE_ICU ++ uint res = qt_u_toLower(ucs2); ++ if (res) ++ return res & 0xffff; ++ // else fall through ++#endif + const QUnicodeTables::Properties *p = qGetProp(ucs2); + if (!p->lowerCaseSpecial) + return ucs2 + p->lowerCaseDiff; +@@ -1118,6 +1142,12 @@ ushort QChar::toLower(ushort ucs2) + */ + QChar QChar::toUpper() const + { ++#ifdef QT_USE_ICU ++ uint res = qt_u_toUpper(ucs); ++ if (res) ++ return QChar(res); ++ // else fall through ++#endif + const QUnicodeTables::Properties *p = qGetProp(ucs); + if (!p->upperCaseSpecial) + return ucs + p->upperCaseDiff; +@@ -1132,6 +1162,12 @@ QChar QChar::toUpper() const + */ + uint QChar::toUpper(uint ucs4) + { ++#ifdef QT_USE_ICU ++ uint res = qt_u_toUpper(ucs4); ++ if (res) ++ return res; ++ // else fall through ++#endif + if (ucs4 > UNICODE_LAST_CODEPOINT) + return ucs4; + const QUnicodeTables::Properties *p = qGetProp(ucs4); +@@ -1148,6 +1184,12 @@ uint QChar::toUpper(uint ucs4) + */ + ushort QChar::toUpper(ushort ucs2) + { ++#ifdef QT_USE_ICU ++ uint res = qt_u_toUpper(ucs2); ++ if (res) ++ return res & 0xffff; ++ // else fall through ++#endif + const QUnicodeTables::Properties *p = qGetProp(ucs2); + if (!p->upperCaseSpecial) + return ucs2 + p->upperCaseDiff; +diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp +index 6515edb..5470048 100644 +--- a/src/corelib/tools/qlocale.cpp ++++ b/src/corelib/tools/qlocale.cpp +@@ -134,6 +134,10 @@ void qt_symbianUpdateSystemPrivate(); + void qt_symbianInitSystemLocale(); + #endif + ++#ifdef QT_USE_ICU ++extern bool qt_initIcu(const QString &localeName); ++#endif ++ + /****************************************************************************** + ** Helpers for accessing Qt locale database + */ +@@ -2346,6 +2350,10 @@ void QLocale::setDefault(const QLocale &locale) + { + default_lp = locale.d(); + default_number_options = locale.numberOptions(); ++ ++#ifdef QT_USE_ICU ++ qt_initIcu(locale.name()); ++#endif + } + + /*! +diff --git a/src/corelib/tools/qlocale_icu.cpp b/src/corelib/tools/qlocale_icu.cpp +new file mode 100644 +index 0000000..7fe3801 +--- /dev/null ++++ b/src/corelib/tools/qlocale_icu.cpp +@@ -0,0 +1,247 @@ ++/**************************************************************************** ++** ++** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ++** All rights reserved. ++** Contact: Nokia Corporation (qt-info@nokia.com) ++** ++** This file is part of the QtCore module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** No Commercial Usage ++** This file contains pre-release code and may not be distributed. ++** You may use this file in accordance with the terms and conditions ++** contained in the Technology Preview License Agreement accompanying ++** this package. ++** ++** GNU Lesser General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU Lesser ++** General Public License version 2.1 as published by the Free Software ++** Foundation and appearing in the file LICENSE.LGPL included in the ++** packaging of this file. Please review the following information to ++** ensure the GNU Lesser General Public License version 2.1 requirements ++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ++** ++** In addition, as a special exception, Nokia gives you certain additional ++** rights. These rights are described in the Nokia Qt LGPL Exception ++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ++** ++** If you have questions regarding the use of this file, please contact ++** Nokia at qt-info@nokia.com. ++** ++** ++** ++** ++** ++** ++** ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#include "qglobal.h" ++#include "qlibrary.h" ++#include "qdebug.h" ++ ++#include "unicode/uversion.h" ++#include "unicode/ucol.h" ++ ++QT_BEGIN_NAMESPACE ++ ++typedef UCollator *(*Ptr_ucol_open)(const char *loc, UErrorCode *status); ++typedef void (*Ptr_ucol_close)(UCollator *coll); ++typedef UCollationResult (*Ptr_ucol_strcoll)(const UCollator *coll, const UChar *source, int32_t sourceLength, const UChar *target, int32_t targetLength); ++typedef int32_t (*Ptr_u_strToCase)(UChar *dest, int32_t destCapacity, const UChar *src, int32_t srcLength, const char *locale, UErrorCode *pErrorCode); ++ ++static Ptr_ucol_open ptr_ucol_open = 0; ++static Ptr_ucol_strcoll ptr_ucol_strcoll = 0; ++static Ptr_ucol_close ptr_ucol_close = 0; ++static Ptr_u_strToCase ptr_u_strToUpper = 0; ++static Ptr_u_strToCase ptr_u_strToLower = 0; ++ ++enum LibLoadStatus ++{ ++ ErrorLoading = -1, ++ NotLoaded = 0, ++ Loaded = 1 ++}; ++ ++static LibLoadStatus status = NotLoaded; ++ ++static UCollator *icuCollator = 0; ++ ++#define STRINGIFY2(x) #x ++#define STRINGIFY(x) STRINGIFY2(x) ++ ++bool qt_initIcu(const QString &localeString) ++{ ++ if (status == ErrorLoading) ++ return false; ++ ++ if (status == NotLoaded) { ++ ++ // resolve libicui18n ++ QLibrary lib(QLatin1String("icui18n"), QLatin1String(U_ICU_VERSION_SHORT)); ++ if (!lib.load()) { ++ qWarning() << "Unable to load library icui18n" << lib.errorString(); ++ status = ErrorLoading; ++ return false; ++ } ++ ++ ptr_ucol_open = (Ptr_ucol_open)lib.resolve("ucol_open"); ++ ptr_ucol_close = (Ptr_ucol_close)lib.resolve("ucol_close"); ++ ptr_ucol_strcoll = (Ptr_ucol_strcoll)lib.resolve("ucol_strcoll"); ++ ++ if (!ptr_ucol_open || !ptr_ucol_close || !ptr_ucol_strcoll) { ++ // try again with decorated symbol names ++ ptr_ucol_open = (Ptr_ucol_open)lib.resolve("ucol_open" STRINGIFY(U_ICU_VERSION_SUFFIX)); ++ ptr_ucol_close = (Ptr_ucol_close)lib.resolve("ucol_close" STRINGIFY(U_ICU_VERSION_SUFFIX)); ++ ptr_ucol_strcoll = (Ptr_ucol_strcoll)lib.resolve("ucol_strcoll" STRINGIFY(U_ICU_VERSION_SUFFIX)); ++ } ++ ++ if (!ptr_ucol_open || !ptr_ucol_close || !ptr_ucol_strcoll) { ++ ptr_ucol_open = 0; ++ ptr_ucol_close = 0; ++ ptr_ucol_strcoll = 0; ++ ++ qWarning("Unable to find symbols in icui18n"); ++ status = ErrorLoading; ++ return false; ++ } ++ ++ // resolve libicuuc ++ QLibrary ucLib(QLatin1String("icuuc"), QLatin1String(U_ICU_VERSION_SHORT)); ++ if (!ucLib.load()) { ++ qWarning() << "Unable to load library icuuc" << ucLib.errorString(); ++ status = ErrorLoading; ++ return false; ++ } ++ ++ ptr_u_strToUpper = (Ptr_u_strToCase)ucLib.resolve("u_strToUpper"); ++ ptr_u_strToLower = (Ptr_u_strToCase)ucLib.resolve("u_strToLower"); ++ ++ if (!ptr_u_strToUpper || !ptr_u_strToLower) { ++ ptr_u_strToUpper = (Ptr_u_strToCase)ucLib.resolve("u_strToUpper" STRINGIFY(U_ICU_VERSION_SUFFIX)); ++ ptr_u_strToLower = (Ptr_u_strToCase)ucLib.resolve("u_strToLower" STRINGIFY(U_ICU_VERSION_SUFFIX)); ++ } ++ ++ if (!ptr_u_strToUpper || !ptr_u_strToLower) { ++ ptr_u_strToUpper = 0; ++ ptr_u_strToLower = 0; ++ ++ qWarning("Unable to find symbols in icuuc"); ++ status = ErrorLoading; ++ return false; ++ } ++ ++ // success :) ++ status = Loaded; ++ } ++ ++ if (icuCollator) { ++ ptr_ucol_close(icuCollator); ++ icuCollator = 0; ++ } ++ ++ UErrorCode icuStatus = U_ZERO_ERROR; ++ icuCollator = ptr_ucol_open(localeString.toLatin1().constData(), &icuStatus); ++ ++ if (!icuCollator) { ++ qWarning("Unable to open locale %s in ICU, error code %d", qPrintable(localeString), icuStatus); ++ return false; ++ } ++ ++ return true; ++} ++ ++bool qt_ucol_strcoll(const QChar *source, int sourceLength, const QChar *target, int targetLength, int *result) ++{ ++ Q_ASSERT(result); ++ Q_ASSERT(source); ++ Q_ASSERT(target); ++ ++ if (!icuCollator) ++ return false; ++ ++ *result = ptr_ucol_strcoll(icuCollator, reinterpret_cast<const UChar *>(source), int32_t(sourceLength), ++ reinterpret_cast<const UChar *>(target), int32_t(targetLength)); ++ ++ return true; ++} ++ ++// caseFunc can either be u_strToUpper or u_strToLower ++static bool qt_u_strToCase(const QString &str, QString *out, const QLocale &locale, Ptr_u_strToCase caseFunc) ++{ ++ Q_ASSERT(out); ++ ++ if (!icuCollator) ++ return false; ++ ++ QString result(str.size(), Qt::Uninitialized); ++ ++ UErrorCode status = U_ZERO_ERROR; ++ ++ int32_t size = caseFunc(reinterpret_cast<UChar *>(result.data()), result.size(), ++ reinterpret_cast<const UChar *>(str.constData()), str.size(), ++ locale.name().toLatin1().constData(), &status); ++ ++ if (U_FAILURE(status)) ++ return false; ++ ++ if (size < result.size()) { ++ result.resize(size); ++ } else if (size > result.size()) { ++ qDebug() << "RESULT SIZE MISMATCH"; ++ // the resulting string is larger than our source string ++ result.resize(size); ++ ++ status = U_ZERO_ERROR; ++ size = caseFunc(reinterpret_cast<UChar *>(result.data()), result.size(), ++ reinterpret_cast<const UChar *>(str.constData()), str.size(), ++ locale.name().toLatin1().constData(), &status); ++ ++ if (U_FAILURE(status)) ++ return false; ++ ++ // if the sizes don't match now, we give up. ++ if (size != result.size()) ++ return false; ++ } ++ ++ *out = result; ++ return true; ++} ++ ++bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale) ++{ ++ return qt_u_strToCase(str, out, locale, ptr_u_strToUpper); ++} ++ ++bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale) ++{ ++ return qt_u_strToCase(str, out, locale, ptr_u_strToLower); ++} ++ ++uint qt_u_toUpper(uint c) ++{ ++ if (c > 0xffff) ++ return 0; ++ ++ QString out; ++ if (qt_u_strToUpper(QChar(c), &out, QLocale()) && !out.isEmpty()) ++ return out.at(0).unicode(); ++ return 0; ++} ++ ++uint qt_u_toLower(uint c) ++{ ++ if (c > 0xffff) ++ return 0; ++ ++ QString out; ++ if (qt_u_strToLower(QChar(c), &out, QLocale()) && !out.isEmpty()) ++ return out.at(0).unicode(); ++ return 0; ++} ++ ++QT_END_NAMESPACE +diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp +index d641d74..0f5cee1 100644 +--- a/src/corelib/tools/qstring.cpp ++++ b/src/corelib/tools/qstring.cpp +@@ -112,6 +112,13 @@ int qFindString(const QChar *haystack, int haystackLen, int from, + int qFindStringBoyerMoore(const QChar *haystack, int haystackLen, int from, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs); + ++#ifdef QT_USE_ICU ++// qlocale_icu.cpp ++extern bool qt_ucol_strcoll(const QChar *source, int sourceLength, const QChar *target, int targetLength, int *result); ++extern bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale); ++extern bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale); ++#endif ++ + + // Unicode case-insensitive comparison + static int ucstricmp(const ushort *a, const ushort *ae, const ushort *b, const ushort *be) +@@ -4808,6 +4815,14 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1, + TPtrC p2 = TPtrC16(reinterpret_cast<const TUint16 *>(data2), length2); + return p1.CompareC(p2); + #elif defined(Q_OS_UNIX) ++# if defined(QT_USE_ICU) ++ int res; ++ if (qt_ucol_strcoll(data1, length1, data2, length2, &res)) { ++ if (res == 0) ++ res = ucstrcmp(data1, length1, data2, length2); ++ return res; ++ } // else fall through ++# endif + // declared in <string.h> + int delta = strcoll(toLocal8Bit_helper(data1, length1), toLocal8Bit_helper(data2, length2)); + if (delta == 0) +@@ -4943,6 +4958,15 @@ QString QString::toLower() const + if (!d->size) + return *this; + ++#ifdef QT_USE_ICU ++ { ++ QString result; ++ if (qt_u_strToLower(*this, &result, QLocale())) ++ return result; ++ // else fall through and use Qt's toUpper ++ } ++#endif ++ + const ushort *e = d->data + d->size; + + // this avoids one out of bounds check in the loop +@@ -5034,6 +5058,15 @@ QString QString::toUpper() const + if (!d->size) + return *this; + ++#ifdef QT_USE_ICU ++ { ++ QString result; ++ if (qt_u_strToUpper(*this, &result, QLocale())) ++ return result; ++ // else fall through and use Qt's toUpper ++ } ++#endif ++ + const ushort *e = d->data + d->size; + + // this avoids one out of bounds check in the loop +diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri +index d81ab04..46c39f3 100644 +--- a/src/corelib/tools/tools.pri ++++ b/src/corelib/tools/tools.pri +@@ -92,6 +92,11 @@ else:SOURCES += tools/qelapsedtimer_generic.cpp + contains(QT_CONFIG, zlib):include($$PWD/../../3rdparty/zlib.pri) + else:include($$PWD/../../3rdparty/zlib_dependency.pri) + ++contains(QT_CONFIG,icu) { ++ SOURCES += tools/qlocale_icu.cpp ++ DEFINES += QT_USE_ICU ++} ++ + DEFINES += HB_EXPORT=Q_CORE_EXPORT + INCLUDEPATH += ../3rdparty/harfbuzz/src + HEADERS += ../3rdparty/harfbuzz/src/harfbuzz.h +diff --git a/tests/auto/qchar/qchar.pro b/tests/auto/qchar/qchar.pro +index 3813e4e..d991365 100644 +--- a/tests/auto/qchar/qchar.pro ++++ b/tests/auto/qchar/qchar.pro +@@ -13,3 +13,5 @@ symbian: { + } else { + DEFINES += SRCDIR=\\\"$$PWD/\\\" + } ++ ++contains(QT_CONFIG,icu):DEFINES += QT_USE_ICU +diff --git a/tests/auto/qchar/tst_qchar.cpp b/tests/auto/qchar/tst_qchar.cpp +index 45dd7eb..514a836 100644 +--- a/tests/auto/qchar/tst_qchar.cpp ++++ b/tests/auto/qchar/tst_qchar.cpp +@@ -103,7 +103,8 @@ tst_QChar::~tst_QChar() + { } + + void tst_QChar::initTestCase() +-{ } ++{ ++} + + void tst_QChar::cleanupTestCase() + { } +@@ -114,6 +115,7 @@ void tst_QChar::init() + int argc = 0; + app = new QCoreApplication(argc, NULL); + #endif ++ QLocale::setDefault(QLocale::C); + } + + void tst_QChar::cleanup() +@@ -143,9 +145,36 @@ void tst_QChar::toUpper() + QVERIFY(QChar::toUpper((uint)0x1c8) == 0x1c7); + QVERIFY(QChar::toUpper((uint)0x1c9) == 0x1c7); + +- QVERIFY(QChar::toUpper((uint)0x10400) == 0x10400); +- QVERIFY(QChar::toUpper((uint)0x10428) == 0x10400); ++ QCOMPARE(QChar::toUpper((uint)0x10400), 0x10400u); ++ QCOMPARE(QChar::toUpper((uint)0x10428), 0x10400u); ++ ++#ifdef QT_USE_ICU ++ QCOMPARE(QChar('i').toUpper(), QChar('I')); ++ QCOMPARE(QChar::toUpper(ushort('i')), ushort('I')); ++ QCOMPARE(QChar::toUpper(uint('i')), uint('I')); ++ ++ QLocale::setDefault(QLocale(QLocale::Turkish, QLocale::Turkey)); ++ ++ // in Turkish locale, upper-caseing a 'i' will result in a capital I plus dot (0x0130) ++ QCOMPARE(QChar('i').toUpper(), QChar(0x0130u)); ++ QCOMPARE(QChar::toUpper(ushort('i')), ushort(0x0130u)); ++ QCOMPARE(QChar::toUpper(uint('i')), 0x0130u); ++ ++ // upper-casing a lower-case i without dot (0x0131) will result in 'I' ++ QCOMPARE(QChar(0x0131u).toUpper(), QChar('I')); ++ QCOMPARE(QChar::toUpper(ushort(0x0131u)), ushort('I')); ++ QCOMPARE(QChar::toUpper(uint(0x0131u)), uint('I')); ++ ++ // upper-casing an upper-case 0x0130 should do nothing ++ QCOMPARE(QChar(0x0130u).toUpper(), QChar(0x0130u)); ++ QCOMPARE(QChar::toUpper(ushort(0x0130u)), ushort(0x0130u)); ++ QCOMPARE(QChar::toUpper(uint(0x0130u)), uint(0x0130u)); + ++ // upper-casing an upper-case I should do nothing ++ QCOMPARE(QChar('I').toUpper(), QChar('I')); ++ QCOMPARE(QChar::toUpper(ushort('I')), ushort('I')); ++ QCOMPARE(QChar::toUpper(uint('I')), uint('I')); ++#endif + } + + void tst_QChar::toLower() +@@ -170,6 +199,34 @@ void tst_QChar::toLower() + + QVERIFY(QChar::toLower((uint)0x10400) == 0x10428); + QVERIFY(QChar::toLower((uint)0x10428) == 0x10428); ++ ++#ifdef QT_USE_ICU ++ QCOMPARE(QChar('I').toLower(), QChar('i')); ++ QCOMPARE(QChar::toLower(ushort('I')), ushort('i')); ++ QCOMPARE(QChar::toLower(uint('I')), uint('i')); ++ ++ QLocale::setDefault(QLocale(QLocale::Turkish, QLocale::Turkey)); ++ ++ // in turkish locale, lower-casing an 'I' will result with a lower-case i without dot (0x0131) ++ QCOMPARE(QChar('I').toLower(), QChar(0x0131u)); ++ QCOMPARE(QChar::toLower(ushort('I')), ushort(0x0131u)); ++ QCOMPARE(QChar::toLower(uint('I')), uint(0x0131u)); ++ ++ // lower-casing a captial I with dot (0x0130) will result in 'i' ++ QCOMPARE(QChar(0x0130u).toLower(), QChar('i')); ++ QCOMPARE(QChar::toLower(ushort(0x0130u)), ushort('i')); ++ QCOMPARE(QChar::toLower(uint(0x0130u)), uint('i')); ++ ++ // lower-casing a lower-case i should do nothing ++ QCOMPARE(QChar('i').toLower(), QChar('i')); ++ QCOMPARE(QChar::toLower(ushort('i')), ushort('i')); ++ QCOMPARE(QChar::toLower(uint('i')), uint('i')); ++ ++ // lower-casing a lower-case i without dot (0x0131) should do nothing ++ QCOMPARE(QChar(0x0131u).toLower(), QChar(0x0131u)); ++ QCOMPARE(QChar::toLower(ushort(0x0131u)), ushort(0x0131u)); ++ QCOMPARE(QChar::toLower(uint(0x0131u)), uint(0x0131u)); ++#endif + } + + void tst_QChar::toTitle() +diff --git a/tests/auto/qstring/qstring.pro b/tests/auto/qstring/qstring.pro +index ed758c6..92dd755 100644 +--- a/tests/auto/qstring/qstring.pro ++++ b/tests/auto/qstring/qstring.pro +@@ -6,3 +6,5 @@ symbian:LIBS += -llibm + QT = core + + DEFINES += QT_NO_CAST_TO_ASCII ++ ++contains(QT_CONFIG,icu):DEFINES += QT_USE_ICU +diff --git a/tests/auto/qstring/tst_qstring.cpp b/tests/auto/qstring/tst_qstring.cpp +index ecae3d8..6baf9fc 100644 +--- a/tests/auto/qstring/tst_qstring.cpp ++++ b/tests/auto/qstring/tst_qstring.cpp +@@ -210,6 +210,8 @@ private slots: + void task262677remove(); + void QTBUG10404_compareRef(); + void QTBUG9281_arg_locale(); ++ ++ void toUpperLower_icu(); + }; + + typedef QList<int> IntList; +@@ -1544,6 +1546,11 @@ void tst_QString::toUpper() + QCOMPARE( lower.toUpper(), upper); + + ++#ifdef QT_USE_ICU ++ // test doesn't work with ICU support, since QChar is unaware of any locale ++ QEXPECT_FAIL("", "test doesn't work with ICU support, since QChar is unaware of any locale", Continue); ++ QVERIFY(false); ++#else + for (int i = 0; i < 65536; ++i) { + QString str(1, QChar(i)); + QString upper = str.toUpper(); +@@ -1551,6 +1558,7 @@ void tst_QString::toUpper() + if (upper.length() == 1) + QVERIFY(upper == QString(1, QChar(i).toUpper())); + } ++#endif + } + + void tst_QString::toLower() +@@ -1582,6 +1590,11 @@ void tst_QString::toLower() + upper += QChar(QChar::lowSurrogate(0x10400)); + QCOMPARE( upper.toLower(), lower); + ++#ifdef QT_USE_ICU ++ // test doesn't work with ICU support, since QChar is unaware of any locale ++ QEXPECT_FAIL("", "test doesn't work with ICU support, since QChar is unaware of any locale", Continue); ++ QVERIFY(false); ++#else + for (int i = 0; i < 65536; ++i) { + QString str(1, QChar(i)); + QString lower = str.toLower(); +@@ -1589,6 +1602,7 @@ void tst_QString::toLower() + if (lower.length() == 1) + QVERIFY(str.toLower() == QString(1, QChar(i).toLower())); + } ++#endif + } + + void tst_QString::trimmed() +@@ -4200,6 +4214,8 @@ void tst_QString::localeAwareCompare() + + #elif defined (Q_WS_MAC) + QSKIP("Setting the locale is not supported on OS X (you can set the C locale, but that won't affect CFStringCompare which is used to compare strings)", SkipAll); ++#elif defined(QT_USE_ICU) ++ QLocale::setDefault(QLocale(locale)); + #else + if (!locale.isEmpty()) { + const char *newLocale = setlocale(LC_ALL, locale.toLatin1()); +@@ -4211,6 +4227,11 @@ void tst_QString::localeAwareCompare() + } + #endif + ++#ifdef QT_USE_ICU ++ // ### for c1, ICU disagrees with libc on how to compare ++ QEXPECT_FAIL("c1", "ICU disagrees with test", Abort); ++#endif ++ + int testres = QString::localeAwareCompare(s1, s2); + if (result < 0) { + QVERIFY(testres < 0); +@@ -4912,6 +4933,40 @@ void tst_QString::QTBUG9281_arg_locale() + QLocale::setDefault(QLocale::C); + } + ++void tst_QString::toUpperLower_icu() ++{ ++#ifndef QT_USE_ICU ++ QSKIP("Qt was built without ICU support", QTest::SkipAll); ++#endif ++ ++ QString s = QString::fromLatin1("i"); ++ ++ QCOMPARE(s.toUpper(), QString::fromLatin1("I")); ++ QCOMPARE(s.toLower(), QString::fromLatin1("i")); ++ ++ QLocale::setDefault(QLocale(QLocale::Turkish, QLocale::Turkey)); ++ ++ // turkish locale has a capital I with a dot (U+0130, utf8 c4b0) ++ ++ QCOMPARE(s.toUpper(), QString::fromUtf8("\xc4\xb0")); ++ QCOMPARE(QString::fromUtf8("\xc4\xb0").toLower(), s); ++ ++ // nothing should happen here ++ QCOMPARE(s.toLower(), s); ++ QCOMPARE(QString::fromLatin1("I").toUpper(), QString::fromLatin1("I")); ++ ++ // U+0131, utf8 c4b1 is the lower-case i without a dot ++ QString sup = QString::fromUtf8("\xc4\xb1"); ++ ++ QCOMPARE(sup.toUpper(), QString::fromLatin1("I")); ++ QCOMPARE(QString::fromLatin1("I").toLower(), sup); ++ ++ // nothing should happen here ++ QCOMPARE(sup.toLower(), sup); ++ QCOMPARE(QString::fromLatin1("i").toLower(), QString::fromLatin1("i")); ++ ++ // the cleanup function will restore the default locale ++} + + + QTEST_APPLESS_MAIN(tst_QString) diff --git a/config.profiles/harmattan/patches/no_read_pro_from_quilt_dir.diff b/config.profiles/harmattan/patches/no_read_pro_from_quilt_dir.diff new file mode 100644 index 0000000..f5ddb67 --- /dev/null +++ b/config.profiles/harmattan/patches/no_read_pro_from_quilt_dir.diff @@ -0,0 +1,13 @@ +Index: qt-maemo-qtp/configure +=================================================================== +--- qt-maemo-qtp.orig/configure ++++ qt-maemo-qtp/configure +@@ -8465,7 +8465,7 @@ + # .projects.3 -> the rest + rm -f .projects .projects.1 .projects.2 .projects.3 + +-QMAKE_PROJECTS=`find "$relpath/." -name '*.pro' -print | sed 's-/\./-/-'` ++QMAKE_PROJECTS=`find "$relpath/." -name '*.pro' -a ! -path '*/.pc/*' -print | sed 's-/\./-/-'` + if [ -z "$AWK" ]; then + for p in `echo $QMAKE_PROJECTS`; do + echo "$p" >> .projects diff --git a/config.profiles/harmattan/patches/pinch_gesture_sent_twice.diff b/config.profiles/harmattan/patches/pinch_gesture_sent_twice.diff new file mode 100644 index 0000000..61dfbf9 --- /dev/null +++ b/config.profiles/harmattan/patches/pinch_gesture_sent_twice.diff @@ -0,0 +1,56 @@ +Index: qt-maemo-qtp/src/gui/kernel/qstandardgestures.cpp +=================================================================== +--- qt-maemo-qtp.orig/src/gui/kernel/qstandardgestures.cpp ++++ qt-maemo-qtp/src/gui/kernel/qstandardgestures.cpp +@@ -66,6 +66,9 @@ + #else + static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); + #endif ++ } else if (target) { ++ return 0; // this assumes the target is a QGraphicsObject, so we return ++ // NULL to indicate that the recognizer doesn't support graphicsobject + } + return new QPanGesture; + } +@@ -157,7 +160,11 @@ + { + if (target && target->isWidgetType()) { + static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); ++ } else if (target) { ++ return 0; // this assumes the target is a QGraphicsObject, so we return ++ // NULL to indicate that the recognizer doesn't support graphicsobject + } ++ + return new QPinchGesture; + } + +@@ -286,6 +293,9 @@ + { + if (target && target->isWidgetType()) { + static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); ++ } else if (target) { ++ return 0; // this assumes the target is a QGraphicsObject, so we return ++ // NULL to indicate that the recognizer doesn't support graphicsobject + } + return new QSwipeGesture; + } +@@ -424,6 +434,9 @@ + { + if (target && target->isWidgetType()) { + static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); ++ } else if (target) { ++ return 0; // this assumes the target is a QGraphicsObject, so we return ++ // NULL to indicate that the recognizer doesn't support graphicsobject + } + return new QTapGesture; + } +@@ -495,6 +508,9 @@ + { + if (target && target->isWidgetType()) { + static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents); ++ } else if (target) { ++ return 0; // this assumes the target is a QGraphicsObject, so we return ++ // NULL to indicate that the recognizer doesn't support graphicsobject + } + return new QTapAndHoldGesture; + } diff --git a/config.profiles/harmattan/patches/qgltexturecache.diff b/config.profiles/harmattan/patches/qgltexturecache.diff new file mode 100644 index 0000000..0fa8ad2 --- /dev/null +++ b/config.profiles/harmattan/patches/qgltexturecache.diff @@ -0,0 +1,23 @@ +Index: qt-maemo-qtp/src/opengl/qgl.cpp +=================================================================== +--- qt-maemo-qtp.orig/src/opengl/qgl.cpp ++++ qt-maemo-qtp/src/opengl/qgl.cpp +@@ -1831,18 +1831,6 @@ + void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost) + { + QWriteLocker locker(&m_lock); +- if (m_cache.totalCost() + cost > m_cache.maxCost()) { +- // the cache is full - make an attempt to remove something +- const QList<QGLTextureCacheKey> keys = m_cache.keys(); +- int i = 0; +- while (i < m_cache.count() +- && (m_cache.totalCost() + cost > m_cache.maxCost())) { +- QGLTexture *tex = m_cache.object(keys.at(i)); +- if (tex->context == ctx) +- m_cache.remove(keys.at(i)); +- ++i; +- } +- } + const QGLTextureCacheKey cacheKey = {key, QGLContextPrivate::contextGroup(ctx)}; + m_cache.insert(cacheKey, texture, cost); + } diff --git a/config.profiles/harmattan/patches/qwidget_x11.diff b/config.profiles/harmattan/patches/qwidget_x11.diff new file mode 100644 index 0000000..8bcb011 --- /dev/null +++ b/config.profiles/harmattan/patches/qwidget_x11.diff @@ -0,0 +1,39 @@ +commit 4ecc45086102807901a3bd2b9e02a169ca212716 +Author: Harald Fernengel <harald.fernengel@nokia.com> +Date: Thu Dec 9 10:51:01 2010 +0100 + + Fix a rare race condition when showing windows + + When setting a window to translucent shortly before showing it with the + OpenGL graphics system, the hijacking would call XDestroyWindow without + resetting the internal state. This might lead to the window waiting for + a map notify message forever. + + The patch now properly resets the internal state when destroying the old + window, so it'll get mapped correctly when show() is called. + + Reviewed-by: Denis Dzyubenko + +Index: qt-maemo-qtp/src/gui/kernel/qwidget_x11.cpp +=================================================================== +--- qt-maemo-qtp.orig/src/gui/kernel/qwidget_x11.cpp ++++ qt-maemo-qtp/src/gui/kernel/qwidget_x11.cpp +@@ -961,8 +961,17 @@ + inputContext->setFocusWidget(q); + } + +- if (destroyw) ++ if (destroyw) { + qt_XDestroyWindow(q, dpy, destroyw); ++ if (QTLWExtra *topData = maybeTopData()) { ++#ifndef QT_NO_XSYNC ++ if (topData->syncUpdateCounter) ++ XSyncDestroyCounter(dpy, topData->syncUpdateCounter); ++#endif ++ // we destroyed our old window - reset the top-level state ++ createTLSysExtra(); ++ } ++ } + + // newly created windows are positioned at the window system's + // (0,0) position. If the parent uses wrect mapping to expand the diff --git a/config.profiles/harmattan/patches/qwidget_x11_mapping.diff b/config.profiles/harmattan/patches/qwidget_x11_mapping.diff new file mode 100644 index 0000000..4866cfb --- /dev/null +++ b/config.profiles/harmattan/patches/qwidget_x11_mapping.diff @@ -0,0 +1,17 @@ +Index: qt-maemo-qtp/src/gui/kernel/qwidget_x11.cpp +=================================================================== +--- qt-maemo-qtp.orig/src/gui/kernel/qwidget_x11.cpp ++++ qt-maemo-qtp/src/gui/kernel/qwidget_x11.cpp +@@ -1353,6 +1353,12 @@ + //cannot trust that !isWindow() implies parentWidget() before create + return (q->isWindow() || !q->parentWidget()) ? p : q->parentWidget()->d_func()->mapToGlobal(p); + } ++ ++ // we're not embedded - use the client rect to compute the global position ++ if (!q->window()->d_func()->topData()->embedded) ++ return mapFromWS(QPoint(pos.x() - q->data->crect.left(), pos.y() - q->data->crect.top())); ++ ++ // otherwise, go through the (slow-ish) X11 round-trip + int x, y; + Window child; + QPoint p = mapToWS(pos); diff --git a/config.profiles/harmattan/patches/runtime-window-geometry-revert.diff b/config.profiles/harmattan/patches/runtime-window-geometry-revert.diff new file mode 100644 index 0000000..af55a60 --- /dev/null +++ b/config.profiles/harmattan/patches/runtime-window-geometry-revert.diff @@ -0,0 +1,12 @@ +Index: qt-maemo-qtp/src/gui/painting/qgraphicssystem_runtime.cpp +=================================================================== +--- qt-maemo-qtp.orig/src/gui/painting/qgraphicssystem_runtime.cpp ++++ qt-maemo-qtp/src/gui/painting/qgraphicssystem_runtime.cpp +@@ -285,7 +285,6 @@ + + void QRuntimeWindowSurface::setGeometry(const QRect &rect) + { +- QWindowSurface::setGeometry(rect); + m_windowSurface->setGeometry(rect); + } + diff --git a/config.profiles/harmattan/patches/series b/config.profiles/harmattan/patches/series new file mode 100644 index 0000000..f2ee5f9 --- /dev/null +++ b/config.profiles/harmattan/patches/series @@ -0,0 +1,14 @@ +tst_qscrollbar.diff +signon_authenticator4.diff +pinch_gesture_sent_twice.diff +no_read_pro_from_quilt_dir.diff +tst_qvariant.diff +icu.diff +qgltexturecache.diff +qwidget_x11.diff +qwidget_x11_mapping.diff +glshadercache.diff +temppath.diff +tst_qprogressbar.diff +default_widget_size.diff +runtime-window-geometry-revert.diff diff --git a/config.profiles/harmattan/patches/signon_authenticator4.diff b/config.profiles/harmattan/patches/signon_authenticator4.diff new file mode 100644 index 0000000..63e8d51 --- /dev/null +++ b/config.profiles/harmattan/patches/signon_authenticator4.diff @@ -0,0 +1,230 @@ +Index: qt-maemo-qtp/src/3rdparty/signon/signon.pri +=================================================================== +--- /dev/null ++++ qt-maemo-qtp/src/3rdparty/signon/signon.pri +@@ -0,0 +1,2 @@ ++# signon dependency ++CONFIG += qdbus +Index: qt-maemo-qtp/src/network/access/access.pri +=================================================================== +--- qt-maemo-qtp.orig/src/network/access/access.pri ++++ qt-maemo-qtp/src/network/access/access.pri +@@ -61,3 +61,4 @@ + access/qnetworkdiskcache.cpp + + include($$PWD/../../3rdparty/zlib_dependency.pri) ++include($$PWD/../../3rdparty/signon/signon.pri) +Index: qt-maemo-qtp/src/network/kernel/qauthenticator.cpp +=================================================================== +--- qt-maemo-qtp.orig/src/network/kernel/qauthenticator.cpp ++++ qt-maemo-qtp/src/network/kernel/qauthenticator.cpp +@@ -129,6 +129,9 @@ + \sa QSslSocket + */ + ++#ifndef QT_NO_SIGNON ++#include <QtDBus/QtDBus> ++#endif //QT_NO_SIGNON + + /*! + Constructs an empty authentication object +@@ -421,17 +424,40 @@ + { + QByteArray response; + const char *methodString = 0; ++#ifndef QT_NO_SIGNON ++ bool valid = false; ++ qint32 id = 0; ++#endif //QT_NO_SIGNON ++ + switch(method) { + case QAuthenticatorPrivate::None: + methodString = ""; + phase = Done; + break; + case QAuthenticatorPrivate::Plain: ++#ifndef QT_NO_SIGNON ++ id = this->options.value(QLatin1String("identity")).toInt(&valid); ++ if (valid) { ++ //get response from sso ++ QVariantMap signon = signonResponse(id, QLatin1String("password"),QVariantMap()); ++ response = '\0' + signon.value(QLatin1String("UserName")).toString().toUtf8() ++ + '\0' + signon.value(QLatin1String("Secret")).toString().toUtf8(); ++ } else ++#endif //QT_NO_SIGNON + response = '\0' + user.toUtf8() + '\0' + password.toUtf8(); + phase = Done; + break; + case QAuthenticatorPrivate::Basic: + methodString = "Basic "; ++#ifndef QT_NO_SIGNON ++ id = this->options.value(QLatin1String("identity")).toInt(&valid); ++ if (valid) { ++ //get response from sso ++ QVariantMap signon = signonResponse(id, QLatin1String("password"),QVariantMap()); ++ response = signon.value(QLatin1String("UserName")).toString().toLatin1() ++ + ':' + signon.value(QLatin1String("Secret")).toString().toLatin1(); ++ } else ++#endif //QT_NO_SIGNON + response = user.toLatin1() + ':' + password.toLatin1(); + response = response.toBase64(); + phase = Done; +@@ -613,6 +639,90 @@ + return hash.result().toHex(); + } + ++#ifndef QT_NO_SIGNON ++ ++static QVariantMap signonResponse(const quint32 id, const QString &method, QVariantMap args) ++{ ++ //check dbus connection ++ QDBusConnection connection = QDBusConnection::sessionBus(); ++ if (!QDBusConnection::sessionBus().isConnected()) { ++ qCritical() << "DBus connection failed"; ++ return QVariantMap(); ++ } ++ ++ QDBusMessage msg = ++ QDBusMessage::createMethodCall(QLatin1String("com.nokia.SingleSignOn"), ++ QLatin1String("/com/nokia/SingleSignOn") , ++ QLatin1String("com.nokia.SingleSignOn.AuthService"), ++ QLatin1String("getAuthSessionObjectPath")); ++ msg << id << method; ++ QDBusReply<QString> pathReply = connection.call(msg); ++ ++ QString sessionPath; ++ if (pathReply.isValid()) { ++ sessionPath = pathReply.value(); ++ } else { ++ qDebug() << pathReply.error(); ++ return QVariantMap(); ++ } ++ ++ //authenticate using auth session ++ msg = QDBusMessage::createMethodCall(QLatin1String("com.nokia.SingleSignOn"), ++ sessionPath, QString(), ++ QLatin1String("process")); ++ msg << args << method; ++ QDBusReply<QVariantMap> reply = connection.call(msg); ++ ++ if (reply.isValid()) { ++ QVariantMap map = reply.value(); ++ return map; ++ } else { ++ qDebug() << reply.error(); ++ return QVariantMap(); ++ } ++ return QVariantMap(); ++} ++ ++static QByteArray signonDigestMd5( ++ const quint32 id, ++ const QByteArray &alg, ++ QString &user, ++ const QByteArray &realm, ++ const QByteArray &nonce, /* nonce from server */ ++ QByteArray &nonceCount, /* 8 hex digits */ ++ QByteArray &cNonce, /* client nonce */ ++ const QByteArray &qop, /* qop-value: "", "auth", "auth-int" */ ++ const QByteArray &method, /* method from the request */ ++ const QByteArray &digestUri, /* requested URL */ ++ const QByteArray &hEntity /* H(entity body) if qop="auth-int" */ ++ ) ++{ ++ QByteArray digest = QByteArray(); ++ nonceCount = "00000001"; ++ ++ QVariantMap args; ++ args.insert(QLatin1String("Algorithm"), alg); ++ args.insert(QLatin1String("Realm"), QLatin1String(realm)); ++ args.insert(QLatin1String("nonce"), nonce); ++ args.insert(QLatin1String("nonceCount"), nonceCount); ++ args.insert(QLatin1String("cNonce"), cNonce); ++ args.insert(QLatin1String("qop"), qop); ++ args.insert(QLatin1String("method"), method); ++ args.insert(QLatin1String("digestUri"), digestUri); ++ args.insert(QLatin1String("Entity"), hEntity); ++ ++ QVariantMap response = signonResponse(id, QLatin1String("digest"), args); ++ ++ if (response.isEmpty()) ++ return digest; ++ digest = response.value(QLatin1String("Digest")).toByteArray(); ++ user = response.value(QLatin1String("UserName")).toString(); ++ cNonce = response.value(QLatin1String("cNonce")).toByteArray(); ++ ++ return digest; ++} ++#endif //QT_NO_SIGNON ++ + QByteArray QAuthenticatorPrivate::digestMd5Response(const QByteArray &challenge, const QByteArray &method, const QByteArray &path) + { + QHash<QByteArray,QByteArray> options = parseDigestAuthenticationChallenge(challenge); +@@ -625,9 +735,23 @@ + QByteArray nonce = options.value("nonce"); + QByteArray opaque = options.value("opaque"); + QByteArray qop = options.value("qop"); ++ QByteArray response; + + // qDebug() << "calculating digest: method=" << method << "path=" << path; +- QByteArray response = digestMd5ResponseHelper(options.value("algorithm"), user.toLatin1(), ++ ++#ifndef QT_NO_SIGNON ++ bool valid = false; ++ qint32 id = this->options.value(QLatin1String("identity")).toInt(&valid); ++ if (valid) { ++ //get response from sso ++ response = signonDigestMd5(id, options.value("algorithm"), user, ++ realm.toLatin1(), ++ nonce, nonceCountString, ++ cnonce, qop, method, ++ path, QByteArray()); ++ } else ++#endif //QT_NO_SIGNON ++ response = digestMd5ResponseHelper(options.value("algorithm"), user.toLatin1(), + realm.toLatin1(), password.toLatin1(), + nonce, nonceCountString, + cnonce, qop, method, +Index: qt-maemo-qtp/src/network/kernel/qauthenticator_p.h +=================================================================== +--- qt-maemo-qtp.orig/src/network/kernel/qauthenticator_p.h ++++ qt-maemo-qtp/src/network/kernel/qauthenticator_p.h +@@ -109,6 +109,23 @@ + + }; + ++#ifndef QT_NO_SIGNON ++ static QVariantMap signonResponse(const quint32 id, const QString &method, QVariantMap args); ++ static QByteArray signonDigestMd5( ++ const quint32 id, ++ const QByteArray &alg, ++ QString &user, ++ const QByteArray &realm, ++ const QByteArray &nonce, /* nonce from server */ ++ QByteArray &nonceCount, /* 8 hex digits */ ++ QByteArray &cNonce, /* client nonce */ ++ const QByteArray &qop, /* qop-value: "", "auth", "auth-int" */ ++ const QByteArray &method, /* method from the request */ ++ const QByteArray &digestUri, /* requested URL */ ++ const QByteArray &hEntity /* H(entity body) if qop="auth-int" */ ++ ); ++#endif //QT_NO_SIGNON ++ + + QT_END_NAMESPACE + +Index: qt-maemo-qtp/src/src.pro +=================================================================== +--- qt-maemo-qtp.orig/src/src.pro ++++ qt-maemo-qtp/src/src.pro +@@ -4,8 +4,9 @@ + unset(SRC_SUBDIRS) + win32:SRC_SUBDIRS += src_winmain + symbian:SRC_SUBDIRS += src_s60main +-SRC_SUBDIRS += src_corelib src_xml src_network src_sql src_testlib ++SRC_SUBDIRS += src_corelib src_xml + !symbian:contains(QT_CONFIG, dbus):SRC_SUBDIRS += src_dbus ++SRC_SUBDIRS += src_network src_sql src_testlib + !contains(QT_CONFIG, no-gui): SRC_SUBDIRS += src_gui + !wince*:!symbian:!vxworks:contains(QT_CONFIG, qt3support): SRC_SUBDIRS += src_qt3support + diff --git a/config.profiles/harmattan/patches/temppath.diff b/config.profiles/harmattan/patches/temppath.diff new file mode 100644 index 0000000..065c2d0 --- /dev/null +++ b/config.profiles/harmattan/patches/temppath.diff @@ -0,0 +1,28 @@ +Index: qt-maemo-qtp/mkspecs/linux-g++-maemo/qplatformdefs.h +=================================================================== +--- qt-maemo-qtp.orig/mkspecs/linux-g++-maemo/qplatformdefs.h ++++ qt-maemo-qtp/mkspecs/linux-g++-maemo/qplatformdefs.h +@@ -43,3 +43,8 @@ + + #define QT_GUI_DOUBLE_CLICK_RADIUS 20 + #define QT_GUI_DRAG_DISTANCE 16 ++ ++// TMPDIR sometimes points to /tmp and sometimes to /var/tmp ++// To guarantee native platform key generation for QSharedMemory and friends, ++// we must hard code the temp path to /var/tmp here. ++#define QT_UNIX_TEMP_PATH_OVERRIDE "/var/tmp" +Index: qt-maemo-qtp/src/corelib/io/qfsfileengine_unix.cpp +=================================================================== +--- qt-maemo-qtp.orig/src/corelib/io/qfsfileengine_unix.cpp ++++ qt-maemo-qtp/src/corelib/io/qfsfileengine_unix.cpp +@@ -643,7 +643,9 @@ + + QString QFSFileEngine::tempPath() + { +-#if defined(Q_OS_SYMBIAN) ++#if defined(QT_UNIX_TEMP_PATH_OVERRIDE) ++ QString temp = QLatin1String(QT_UNIX_TEMP_PATH_OVERRIDE); ++#elif defined(Q_OS_SYMBIAN) + TFileName symbianPath = PathInfo::PhoneMemoryRootPath(); + QString temp = QDir::fromNativeSeparators(qt_TDesC2QString(symbianPath)); + temp += QLatin1String( "temp/"); diff --git a/config.profiles/harmattan/patches/tst_qprogressbar.diff b/config.profiles/harmattan/patches/tst_qprogressbar.diff new file mode 100644 index 0000000..d252fe3 --- /dev/null +++ b/config.profiles/harmattan/patches/tst_qprogressbar.diff @@ -0,0 +1,19 @@ +Index: qt-maemo-qtp/tests/auto/qprogressbar/tst_qprogressbar.cpp +=================================================================== +--- qt-maemo-qtp.orig/tests/auto/qprogressbar/tst_qprogressbar.cpp ++++ qt-maemo-qtp/tests/auto/qprogressbar/tst_qprogressbar.cpp +@@ -179,10 +179,14 @@ + bar.repainted = false; + bar.setFormat("%v of %m (%p%)"); + qApp->processEvents(); ++ ++#if 0 // Removed + #ifndef Q_WS_MAC + // The Mac scroll bar is animated, which means we get paint events all the time. + QVERIFY(!bar.repainted); + #endif ++#endif ++ + QCOMPARE(bar.text(), QString("1 of 10 (10%)")); + bar.setRange(5, 5); + bar.setValue(5); diff --git a/config.profiles/harmattan/patches/tst_qscrollbar.diff b/config.profiles/harmattan/patches/tst_qscrollbar.diff new file mode 100644 index 0000000..3c777a9 --- /dev/null +++ b/config.profiles/harmattan/patches/tst_qscrollbar.diff @@ -0,0 +1,12 @@ +Index: qt-maemo-qtp/tests/auto/qscrollbar/tst_qscrollbar.cpp +=================================================================== +--- qt-maemo-qtp.orig/tests/auto/qscrollbar/tst_qscrollbar.cpp ++++ qt-maemo-qtp/tests/auto/qscrollbar/tst_qscrollbar.cpp +@@ -104,6 +104,7 @@ + + void tst_QScrollBar::task_209492() + { ++ QSKIP("Unstable test on Harmattan", SkipSingle); + class MyScrollArea : public QScrollArea + { + public: diff --git a/config.profiles/harmattan/patches/tst_qvariant.diff b/config.profiles/harmattan/patches/tst_qvariant.diff new file mode 100644 index 0000000..bcded52 --- /dev/null +++ b/config.profiles/harmattan/patches/tst_qvariant.diff @@ -0,0 +1,21 @@ +Index: qt-maemo-qtp/tests/auto/qvariant/tst_qvariant.cpp +=================================================================== +--- qt-maemo-qtp.orig/tests/auto/qvariant/tst_qvariant.cpp ++++ qt-maemo-qtp/tests/auto/qvariant/tst_qvariant.cpp +@@ -3122,6 +3122,7 @@ + + void tst_QVariant::numericalConvert() + { ++ int low_int = 3; + QVariant vfloat(float(5.3)); + QVariant vdouble(double(5.3)); + QVariant vreal(qreal(5.3)); +@@ -3137,7 +3138,7 @@ + + for(int i = 0; i < vect.size(); i++) { + double num = 5.3; +- if (i >= 3 && i <= 7) ++ if (i >= low_int && i <= 7) + num = 5; + QVariant *v = vect.at(i); + QCOMPARE(v->toFloat() , float(num)); |