diff options
author | Jan-Arve Sæther <jan-arve.saether@nokia.com> | 2009-11-13 08:56:37 (GMT) |
---|---|---|
committer | Jan-Arve Sæther <jan-arve.saether@nokia.com> | 2009-11-13 08:56:37 (GMT) |
commit | 57d05153b3ef2df1f1dd38eb9560d6019e1bcd4a (patch) | |
tree | 1f967dce191db75e62a951f7ae3be357bb27b0fd | |
parent | baf18674870cc86db12cb44a28dd5480cc04ea8a (diff) | |
parent | 8e589bc0aa6df55052e37b3107f2f03a1dc17d06 (diff) | |
download | Qt-57d05153b3ef2df1f1dd38eb9560d6019e1bcd4a.zip Qt-57d05153b3ef2df1f1dd38eb9560d6019e1bcd4a.tar.gz Qt-57d05153b3ef2df1f1dd38eb9560d6019e1bcd4a.tar.bz2 |
Merge branch '4.6' of scm.dev.nokia.troll.no:qt/oslo-staging-2 into 4.6
42 files changed, 1193 insertions, 292 deletions
@@ -191,6 +191,7 @@ plugin_commonU.def *.qtplugin *.sis *.sisx +*.lst # Generated by abldfast.bat from devtools. .abldsteps.* diff --git a/mkspecs/symbian-sbsv2/flm/qt/qmake_generate_temp_dirs.flm b/mkspecs/symbian-sbsv2/flm/qt/qmake_generate_temp_dirs.flm deleted file mode 100644 index ca6cca9..0000000 --- a/mkspecs/symbian-sbsv2/flm/qt/qmake_generate_temp_dirs.flm +++ /dev/null @@ -1,22 +0,0 @@ -# /**************************************************************************** -# ** -# ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -# ** Contact: Nokia Corporation (qt-info@nokia.com) -# ** -# ** This file is part of symbian-sbsv2 mkspec. -# ** -# ****************************************************************************/ - -include $(FLMHOME)/metaflm.mk - -SINGLETON:=$(call sanitise,TEMP_DIRS_$(EXTENSION_ROOT)) - -ifeq ($($(SINGLETON)),) -$(SINGLETON):=1 -$(call makepath,$(DIRS)) -$(eval $(call GenerateStandardCleanTarget,'',$(DIRS))) -endif - - - - diff --git a/mkspecs/symbian-sbsv2/flm/qt/qt.xml b/mkspecs/symbian-sbsv2/flm/qt/qt.xml index 5074e47..c99b5e2 100644 --- a/mkspecs/symbian-sbsv2/flm/qt/qt.xml +++ b/mkspecs/symbian-sbsv2/flm/qt/qt.xml @@ -35,11 +35,6 @@ <param name='LINK_TARGET' /> </interface> - <interface name="qt.qmake_generate_temp_dirs" extends="Symbian.UserFLM" - flm="qmake_generate_temp_dirs.flm"> - <param name='DIRS' /> - </interface> - <interface name="qt.qmake_store_build" extends="Symbian.UserFLM" flm="qmake_store_build.flm"> </interface> diff --git a/qmake/generators/symbian/symmake.cpp b/qmake/generators/symbian/symmake.cpp index 8ec4b3f..1326a49 100644 --- a/qmake/generators/symbian/symmake.cpp +++ b/qmake/generators/symbian/symmake.cpp @@ -610,19 +610,10 @@ void SymbianMakefileGenerator::initMmpVariables() incpaths << project->values("UI_HEADERS_DIR"); incpaths << project->values("UI_DIR"); - QString epocPath("epoc32"); for (int j = 0; j < incpaths.size(); ++j) { QString includepath = canonizePath(incpaths.at(j)); appendIfnotExist(sysincspaths, includepath); - // As a workaround for Symbian toolchain insistence to treat include - // statements as relative to source file rather than the file they appear in, - // we generate extra temporary include directories to make - // relative include paths used in various headers to work properly. - // Note that this is not a fix-all solution; it's just a stop-gap measure - // to make Qt itself build until toolchain can support relative includes in - // a way that Qt expects. - if (!includepath.contains(epocPath)) // No temp dirs for epoc includes - appendIfnotExist(sysincspaths, includepath + QString("/" QT_EXTRA_INCLUDE_DIR)); + appendAbldTempDirs(sysincspaths, includepath); } // Remove duplicate include path entries diff --git a/qmake/generators/symbian/symmake.h b/qmake/generators/symbian/symmake.h index 36f6e05..a3e2c17 100644 --- a/qmake/generators/symbian/symmake.h +++ b/qmake/generators/symbian/symmake.h @@ -147,6 +147,7 @@ protected: virtual void writeBldInfMkFilePart(QTextStream& t, bool addDeploymentExtension) = 0; virtual void writeMkFile(const QString& wrapperFileName, bool deploymentOnly) = 0; virtual void writeWrapperMakefile(QFile& wrapperFile, bool isPrimaryMakefile) = 0; + virtual void appendAbldTempDirs(QStringList& sysincspaths, QString includepath) = 0; public: diff --git a/qmake/generators/symbian/symmake_abld.cpp b/qmake/generators/symbian/symmake_abld.cpp index 4d1673b..1b5464f 100644 --- a/qmake/generators/symbian/symmake_abld.cpp +++ b/qmake/generators/symbian/symmake_abld.cpp @@ -450,3 +450,17 @@ void SymbianAbldMakefileGenerator::writeBldInfMkFilePart(QTextStream& t, bool ad t << "gnumakefile " << gnuMakefileName << endl; } } + +void SymbianAbldMakefileGenerator::appendAbldTempDirs(QStringList& sysincspaths, QString includepath) +{ + // As a workaround for Symbian toolchain insistence to treat include + // statements as relative to source file rather than the file they appear in, + // we generate extra temporary include directories to make + // relative include paths used in various headers to work properly. + // Note that this is not a fix-all solution; it's just a stop-gap measure + // to make Qt itself build until toolchain can support relative includes in + // a way that Qt expects. + QString epocPath("epoc32"); + if (!includepath.contains(epocPath)) // No temp dirs for epoc includes + appendIfnotExist(sysincspaths, includepath + QString("/" QT_EXTRA_INCLUDE_DIR)); +} diff --git a/qmake/generators/symbian/symmake_abld.h b/qmake/generators/symbian/symmake_abld.h index f844096..11b9cd1 100644 --- a/qmake/generators/symbian/symmake_abld.h +++ b/qmake/generators/symbian/symmake_abld.h @@ -55,6 +55,7 @@ protected: virtual void writeBldInfMkFilePart(QTextStream& t, bool addDeploymentExtension); virtual void writeMkFile(const QString& wrapperFileName, bool deploymentOnly); virtual void writeWrapperMakefile(QFile& wrapperFile, bool isPrimaryMakefile); + virtual void appendAbldTempDirs(QStringList& sysincspaths, QString includepath); void writeStoreBuildTarget(QTextStream &t); bool writeDeploymentTargets(QTextStream &t); diff --git a/qmake/generators/symbian/symmake_sbsv2.cpp b/qmake/generators/symbian/symmake_sbsv2.cpp index cad2736..5e624de 100644 --- a/qmake/generators/symbian/symmake_sbsv2.cpp +++ b/qmake/generators/symbian/symmake_sbsv2.cpp @@ -182,15 +182,22 @@ void SymbianSbsv2MakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, boo } t << endl; + QString winscw("winscw"); // For more specific builds, targets are in this form: build-platform, e.g. release-armv5 foreach(QString item, debugPlatforms) { t << "debug-" << item << ": " << BLD_INF_FILENAME << endl; - t << "\t$(SBS) -c " << item << "_udeb" << testClause << endl; + if(QString::compare(item, winscw) == 0) + t << "\t$(SBS) -c " << item << "_udeb.mwccinc" << testClause << endl; + else + t << "\t$(SBS) -c " << item << "_udeb" << testClause << endl; } foreach(QString item, releasePlatforms) { t << "release-" << item << ": " << BLD_INF_FILENAME << endl; - t << "\t$(SBS) -c " << item << "_urel" << testClause << endl; + if(QString::compare(item, winscw) == 0) + t << "\t$(SBS) -c " << item << "_urel.mwccinc" << testClause << endl; + else + t << "\t$(SBS) -c " << item << "_urel" << testClause << endl; } t << endl; @@ -379,28 +386,6 @@ void SymbianSbsv2MakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t t << "END" << endl; } - // Generate temp dirs - QString tempDirs; - for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) { - QStringList values = it.value(); - for (int i = 0; i < values.size(); ++i) { - QString value = values.at(i); - if (value.endsWith("/" QT_EXTRA_INCLUDE_DIR)) { - value = fileInfo(value).absoluteFilePath(); - tempDirs.append(value); - tempDirs.append(" "); - } - } - } - - if (tempDirs.size()) - tempDirs.chop(1); // Remove final space - - t << "START EXTENSION qt/qmake_generate_temp_dirs" << endl; - t << "OPTION DIRS " << tempDirs << endl; - t << "END" << endl; - t << endl; - t << "START EXTENSION qt/qmake_store_build" << endl; t << "END" << endl; t << endl; @@ -414,3 +399,10 @@ void SymbianSbsv2MakefileGenerator::writeBldInfMkFilePart(QTextStream& t, bool a Q_UNUSED(t); Q_UNUSED(addDeploymentExtension); } + +void SymbianSbsv2MakefileGenerator::appendAbldTempDirs(QStringList& sysincspaths, QString includepath) +{ + //Do nothing + Q_UNUSED(sysincspaths); + Q_UNUSED(includepath); +} diff --git a/qmake/generators/symbian/symmake_sbsv2.h b/qmake/generators/symbian/symmake_sbsv2.h index 1cbddb3..9472b68 100644 --- a/qmake/generators/symbian/symmake_sbsv2.h +++ b/qmake/generators/symbian/symmake_sbsv2.h @@ -55,6 +55,7 @@ protected: virtual void writeBldInfMkFilePart(QTextStream& t, bool addDeploymentExtension); virtual void writeMkFile(const QString& wrapperFileName, bool deploymentOnly); virtual void writeWrapperMakefile(QFile& wrapperFile, bool isPrimaryMakefile); + virtual void appendAbldTempDirs(QStringList& sysincspaths, QString includepath); public: diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp b/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp index a793390..a559249 100644 --- a/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp +++ b/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp @@ -29,6 +29,10 @@ using namespace Phonon::MMF; \internal */ +/*! \namespace Phonon::MMF + \internal +*/ + AbstractAudioEffect::AbstractAudioEffect(QObject *parent, const QList<EffectParameter> ¶ms) : MediaNode::MediaNode(parent) , m_params(params) diff --git a/src/3rdparty/phonon/mmf/ancestormovemonitor.cpp b/src/3rdparty/phonon/mmf/ancestormovemonitor.cpp index 0447d57..18ced94 100644 --- a/src/3rdparty/phonon/mmf/ancestormovemonitor.cpp +++ b/src/3rdparty/phonon/mmf/ancestormovemonitor.cpp @@ -26,7 +26,7 @@ QT_BEGIN_NAMESPACE using namespace Phonon::MMF; -/*! \class MMF::AncestorMoveMonitor +/*! \class Phonon::MMF::AncestorMoveMonitor \internal \brief Class which installs a global event filter, and listens for move events which may affect the absolute position of widgets registered with @@ -34,6 +34,11 @@ using namespace Phonon::MMF; See QTBUG-4956 */ + +/*! \class Phonon::MMF::VideoOutputObserver + \internal +*/ + //----------------------------------------------------------------------------- // Constructor / destructor //----------------------------------------------------------------------------- diff --git a/src/3rdparty/phonon/mmf/utils.cpp b/src/3rdparty/phonon/mmf/utils.cpp index 58d1ece..d728fcf 100644 --- a/src/3rdparty/phonon/mmf/utils.cpp +++ b/src/3rdparty/phonon/mmf/utils.cpp @@ -24,16 +24,24 @@ QT_BEGIN_NAMESPACE using namespace Phonon; using namespace Phonon::MMF; -/*! \namespace MMF::Utils +/*! \namespace Phonon::MMF::Utils \internal */ -/*! \class MMF::TTraceContext +/*! \class Phonon::MMF::TTraceContext \internal */ -/*! \class MMF::Utils - \internal +/*! \enum Phonon::MMF::PanicCode + \internal +*/ + +/*! \enum Phonon::MMF::TTraceCategory + \internal +*/ + +/*! \enum Phonon::MMF::MediaType + \internal */ _LIT(PanicCategory, "Phonon::MMF"); diff --git a/src/3rdparty/phonon/phonon/audiooutput.cpp b/src/3rdparty/phonon/phonon/audiooutput.cpp index 00b2ebd..962f828 100644 --- a/src/3rdparty/phonon/phonon/audiooutput.cpp +++ b/src/3rdparty/phonon/phonon/audiooutput.cpp @@ -257,6 +257,7 @@ void AudioOutputPrivate::setupBackendObject() // set up attributes pINTERFACE_CALL(setVolume(pow(volume, VOLTAGE_TO_LOUDNESS_EXPONENT))); +#ifndef QT_NO_PHONON_SETTINGSGROUP // if the output device is not available and the device was not explicitly set if (!callSetOutputDevice(this, device) && !outputDeviceOverridden) { // fall back in the preference list of output devices @@ -276,6 +277,7 @@ void AudioOutputPrivate::setupBackendObject() callSetOutputDevice(this, none); handleAutomaticDeviceChange(none, FallbackChange); } +#endif //QT_NO_PHONON_SETTINGSGROUP } void AudioOutputPrivate::_k_volumeChanged(qreal newVolume) @@ -305,6 +307,7 @@ void AudioOutputPrivate::_k_audioDeviceFailed() pDebug() << Q_FUNC_INFO; // outputDeviceIndex identifies a failing device // fall back in the preference list of output devices +#ifndef QT_NO_PHONON_SETTINGSGROUP const QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices); for (int i = 0; i < deviceList.count(); ++i) { const int devIndex = deviceList.at(i); @@ -317,6 +320,7 @@ void AudioOutputPrivate::_k_audioDeviceFailed() } } } +#endif //QT_NO_PHONON_SETTINGSGROUP // if we get here there is no working output device. Tell the backend. const AudioOutputDevice none; callSetOutputDevice(this, none); @@ -326,6 +330,7 @@ void AudioOutputPrivate::_k_audioDeviceFailed() void AudioOutputPrivate::_k_deviceListChanged() { pDebug() << Q_FUNC_INFO; +#ifndef QT_NO_PHONON_SETTINGSGROUP // let's see if there's a usable device higher in the preference list const QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings); DeviceChangeType changeType = HigherPreferenceChange; @@ -351,6 +356,7 @@ void AudioOutputPrivate::_k_deviceListChanged() break; // found one with higher preference that works } } +#endif //QT_NO_PHONON_SETTINGSGROUP } static struct diff --git a/src/3rdparty/phonon/phonon/backendcapabilities.cpp b/src/3rdparty/phonon/phonon/backendcapabilities.cpp index 62c9cc9..5defe09 100644 --- a/src/3rdparty/phonon/phonon/backendcapabilities.cpp +++ b/src/3rdparty/phonon/phonon/backendcapabilities.cpp @@ -75,10 +75,12 @@ bool BackendCapabilities::isMimeTypeAvailable(const QString &mimeType) QList<AudioOutputDevice> BackendCapabilities::availableAudioOutputDevices() { QList<AudioOutputDevice> ret; +#ifndef QT_NO_PHONON_SETTINGSGROUP const QList<int> deviceIndexes = GlobalConfig().audioOutputDeviceListFor(Phonon::NoCategory); for (int i = 0; i < deviceIndexes.count(); ++i) { ret.append(AudioOutputDevice::fromIndex(deviceIndexes.at(i))); } +#endif //QT_NO_PHONON_SETTINGSGROUP return ret; } diff --git a/src/3rdparty/phonon/phonon/effectwidget.cpp b/src/3rdparty/phonon/phonon/effectwidget.cpp index fb9cf6e..f8341e5 100644 --- a/src/3rdparty/phonon/phonon/effectwidget.cpp +++ b/src/3rdparty/phonon/phonon/effectwidget.cpp @@ -97,8 +97,9 @@ void EffectWidgetPrivate::autogenerateUi() Q_Q(EffectWidget); QVBoxLayout *mainLayout = new QVBoxLayout(q); mainLayout->setMargin(0); - for (int i = 0; i < effect->parameters().count(); ++i) { - const EffectParameter ¶ = effect->parameters().at(i); + const QList<Phonon::EffectParameter> parameters = effect->parameters(); + for (int i = 0; i < parameters.count(); ++i) { + const EffectParameter ¶ = parameters.at(i); QVariant value = effect->parameterValue(para); QHBoxLayout *pLayout = new QHBoxLayout; mainLayout->addLayout(pLayout); diff --git a/src/3rdparty/phonon/phonon/globalconfig.cpp b/src/3rdparty/phonon/phonon/globalconfig.cpp index 3718c6a..429a29f 100644 --- a/src/3rdparty/phonon/phonon/globalconfig.cpp +++ b/src/3rdparty/phonon/phonon/globalconfig.cpp @@ -178,13 +178,15 @@ QList<int> GlobalConfig::audioOutputDeviceListFor(Phonon::Category category, int return listSortedByConfig(backendConfig, category, defaultList); } -#endif //QT_NO_SETTINGSGROUPS +#endif //QT_NO_PHONON_SETTINGSGROUP int GlobalConfig::audioOutputDeviceFor(Phonon::Category category, int override) const { +#ifndef QT_NO_PHONON_SETTINGSGROUP QList<int> ret = audioOutputDeviceListFor(category, override); - if (ret.isEmpty()) - return -1; - return ret.first(); + if (!ret.isEmpty()) + return ret.first(); +#endif //QT_NO_PHONON_SETTINGSGROUP + return -1; } #ifndef QT_NO_PHONON_AUDIOCAPTURE diff --git a/src/3rdparty/webkit/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp b/src/3rdparty/webkit/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp index 117393a..bbb676b 100644 --- a/src/3rdparty/webkit/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp +++ b/src/3rdparty/webkit/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp @@ -971,7 +971,10 @@ void tst_QWebElement::render() QImage testImage(resource.width(), resource.height(), QImage::Format_ARGB32); QPainter painter0(&testImage); painter0.fillRect(imageRect, Qt::white); - painter0.drawImage(0, 0, resource); + //render() uses pixmaps internally, and pixmaps might have bit depths + // other than 32, giving different pixel values due to rounding. + QPixmap pix = QPixmap::fromImage(resource); + painter0.drawPixmap(0, 0, pix); painter0.end(); QImage image1(resource.width(), resource.height(), QImage::Format_ARGB32); diff --git a/src/corelib/arch/armv6/qatomic_generic_armv6.cpp b/src/corelib/arch/armv6/qatomic_generic_armv6.cpp new file mode 100644 index 0000000..3078662 --- /dev/null +++ b/src/corelib/arch/armv6/qatomic_generic_armv6.cpp @@ -0,0 +1,260 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** +** This file implements the generic atomics interface using ARMv6 assembly +** instructions. It is more efficent than the inline versions when Qt is +** built for the THUMB instruction set, as the required instructions are +** only available in ARM state. +****************************************************************************/ + +#include <QtCore/qglobal.h> + +#ifdef QT_HAVE_ARMV6 + +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + +#ifdef Q_CC_RVCT +#pragma push +#pragma arm +Q_CORE_EXPORT asm +bool QBasicAtomicInt_testAndSetOrdered(volatile int *_q_value, int expectedValue, int newValue) +{ + CODE32 + //R0 = _q_value + //R1 = expectedValue + //R2 = newValue +retry_testAndSetOrdered + LDREX r3,[r0] //r3 = *_q_value + EORS r3,r3,r1 //if (r3 == expectedValue) { + STREXEQ r3,r2,[r0] //*_q_value = newvalue, r3 = error + TEQEQ r3,#1 //if error + BEQ retry_testAndSetOrdered //then goto retry } + RSBS r0,r3,#1 //return (r3 == 0) + MOVCC r0,#0 + BX r14 +} + +Q_CORE_EXPORT asm +int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *_q_value, int newValue) +{ + CODE32 +//R0 = _q_value +//R1 = newValue +retry_fetchAndStoreOrdered + LDREX r3,[r0] //r3 = *_q_value + STREX r2,r1,[r0] //*_q_value = newValue, r2 = error + TEQ r2,#0 //if error + BNE retry_fetchAndStoreOrdered //then goto retry + MOV r0,r3 //return r3 + BX r14 +} + +Q_CORE_EXPORT asm +int QBasicAtomicInt_fetchAndAddOrdered(volatile int *_q_value, int valueToAdd) +{ + CODE32 + //R0 = _q_value + //R1 = valueToAdd + STMDB sp!,{r12,lr} +retry_fetchAndAddOrdered + LDREX r2,[r0] //r2 = *_q_value + ADD r3,r2,r1 //r3 = r2 + r1 + STREX r12,r3,[r0] //*_q_value = r3, r12 = error + TEQ r12,#0 //if error + BNE retry_fetchAndAddOrdered //then retry + MOV r0,r2 //return r2 + LDMIA sp!,{r12,pc} +} + +Q_CORE_EXPORT asm +bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *_q_value, + void *expectedValue, + void *newValue) +{ + CODE32 + //R0 = _q_value + //R1 = expectedValue + //R2 = newValue +retryPointer_testAndSetOrdered + LDREX r3,[r0] //r3 = *_q_value + EORS r3,r3,r1 //if (r3 == expectedValue) { + STREXEQ r3,r2,[r0] //*_q_value = newvalue, r3 = error + TEQEQ r3,#1 //if error + BEQ retryPointer_testAndSetOrdered //then goto retry } + RSBS r0,r3,#1 //return (r3 == 0) + MOVCC r0,#0 + BX r14 +} + +Q_CORE_EXPORT asm +void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *_q_value, void *newValue) +{ + CODE32 + //R0 = _q_value + //R1 = newValue +retryPointer_fetchAndStoreOrdered + LDREX r3,[r0] //r3 = *_q_value + STREX r2,r1,[r0] //*_q_value = newValue, r2 = error + TEQ r2,#0 //if error + BNE retryPointer_fetchAndStoreOrdered //then goto retry + MOV r0,r3 //return r3 + BX r14 +} + +Q_CORE_EXPORT asm +void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *_q_value, qptrdiff valueToAdd) +{ + CODE32 + //R0 = _q_value + //R1 = valueToAdd + STMDB sp!,{r12,lr} +retryPointer_fetchAndAddOrdered + LDREX r2,[r0] //r2 = *_q_value + ADD r3,r2,r1 //r3 = r2 + r1 + STREX r12,r3,[r0] //*_q_value = r3, r12 = error + TEQ r12,#0 //if error + BNE retryPointer_fetchAndAddOrdered //then retry + MOV r0,r2 //return r2 + LDMIA sp!,{r12,pc} +} + +#pragma pop +#elif defined (Q_CC_GCCE) +Q_CORE_EXPORT __declspec( naked ) +bool QBasicAtomicInt_testAndSetOrdered(volatile int *_q_value, int expectedValue, int newValue) +{ + //R0 = _q_value + //R1 = expectedValue + //R2 = newValue + asm("retry_testAndSetOrdered:"); + asm(" LDREX r3,[r0]"); //r3 = *_q_value + asm(" EORS r3,r3,r1"); //if (r3 == expectedValue) { + asm(" STREXEQ r3,r2,[r0]"); //*_q_value = newvalue, r3 = error + asm(" TEQEQ r3,#1"); //if error + asm(" BEQ retry_testAndSetOrdered"); //then goto retry } + asm(" RSBS r0,r3,#1"); //return (r3 == 0) + asm(" MOVCC r0,#0"); + asm(" BX r14"); +} + +Q_CORE_EXPORT __declspec( naked ) +int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *_q_value, int newValue) +{ +//R0 = _q_value +//R1 = newValue + asm("retry_fetchAndStoreOrdered:"); + asm(" LDREX r3,[r0]"); //r3 = *_q_value + asm(" STREX r2,r1,[r0]"); //*_q_value = newValue, r2 = error + asm(" TEQ r2,#0"); //if error + asm(" BNE retry_fetchAndStoreOrdered"); //then goto retry + asm(" MOV r0,r3"); //return r3 + asm(" BX r14"); +} + +Q_CORE_EXPORT __declspec( naked ) +int QBasicAtomicInt_fetchAndAddOrdered(volatile int *_q_value, int valueToAdd) +{ + //R0 = _q_value + //R1 = valueToAdd + asm(" STMDB sp!,{r12,lr}"); + asm("retry_fetchAndAddOrdered:"); + asm(" LDREX r2,[r0]"); //r2 = *_q_value + asm(" ADD r3,r2,r1 "); //r3 = r2 + r1 + asm(" STREX r12,r3,[r0]"); //*_q_value = r3, r12 = error + asm(" TEQ r12,#0"); //if error + asm(" BNE retry_fetchAndAddOrdered"); //then retry + asm(" MOV r0,r2"); //return r2 + asm(" LDMIA sp!,{r12,pc}"); +} + +Q_CORE_EXPORT __declspec( naked ) +bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *_q_value, + void *expectedValue, + void *newValue) +{ + //R0 = _q_value + //R1 = expectedValue + //R2 = newValue + asm("retryPointer_testAndSetOrdered:"); + asm(" LDREX r3,[r0]"); //r3 = *_q_value + asm(" EORS r3,r3,r1"); //if (r3 == expectedValue) { + asm(" STREXEQ r3,r2,[r0]"); //*_q_value = newvalue, r3 = error + asm(" TEQEQ r3,#1"); //if error + asm(" BEQ retryPointer_testAndSetOrdered"); //then goto retry } + asm(" RSBS r0,r3,#1"); //return (r3 == 0) + asm(" MOVCC r0,#0"); + asm(" BX r14"); +} + +Q_CORE_EXPORT __declspec( naked ) +void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *_q_value, void *newValue) +{ + //R0 = _q_value + //R1 = newValue + asm("retryPointer_fetchAndStoreOrdered:"); + asm(" LDREX r3,[r0]"); //r3 = *_q_value + asm(" STREX r2,r1,[r0]"); //*_q_value = newValue, r2 = error + asm(" TEQ r2,#0"); //if error + asm(" BNE retryPointer_fetchAndStoreOrdered"); //then goto retry + asm(" MOV r0,r3"); //return r3 + asm(" BX r14"); +} + +Q_CORE_EXPORT __declspec( naked ) +void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *_q_value, qptrdiff valueToAdd) +{ + //R0 = _q_value + //R1 = valueToAdd + asm(" STMDB sp!,{r12,lr}"); + asm("retryPointer_fetchAndAddOrdered:"); + asm(" LDREX r2,[r0]"); //r2 = *_q_value + asm(" ADD r3,r2,r1"); //r3 = r2 + r1 + asm(" STREX r12,r3,[r0]"); //*_q_value = r3, r12 = error + asm(" TEQ r12,#0"); //if error + asm(" BNE retryPointer_fetchAndAddOrdered"); //then retry + asm(" MOV r0,r2"); //return r2 + asm(" LDMIA sp!,{r12,pc}"); +} +#else +#error unknown arm compiler +#endif +QT_END_NAMESPACE +#endif diff --git a/src/corelib/arch/qatomic_armv6.h b/src/corelib/arch/qatomic_armv6.h index 6862638..1e9f0c4 100644 --- a/src/corelib/arch/qatomic_armv6.h +++ b/src/corelib/arch/qatomic_armv6.h @@ -45,7 +45,6 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE - #define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE inline bool QBasicAtomicInt::isReferenceCountingNative() @@ -101,6 +100,8 @@ template <typename T> Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() { return false; } +#ifndef Q_CC_RVCT + inline bool QBasicAtomicInt::ref() { register int newValue; @@ -155,21 +156,6 @@ inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) return result == 0; } -inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) { register int originalValue; @@ -188,21 +174,6 @@ inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) return originalValue; } -inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) -{ - return fetchAndStoreOrdered(newValue); -} - inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) { register int originalValue; @@ -224,21 +195,6 @@ inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) return originalValue; } -inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) -{ - return fetchAndAddOrdered(valueToAdd); -} - -inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) -{ - return fetchAndAddOrdered(valueToAdd); -} - -inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) -{ - return fetchAndAddOrdered(valueToAdd); -} - template <typename T> Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) { @@ -259,24 +215,6 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValu } template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} - -template <typename T> Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) { register T *originalValue; @@ -296,24 +234,6 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) } template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) -{ - return fetchAndStoreOrdered(newValue); -} - -template <typename T> Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) { register T *originalValue; @@ -335,6 +255,226 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueTo return originalValue; } +#else +// This is Q_CC_RVCT + +// RVCT inline assembly documentation: +// http://www.keil.com/support/man/docs/armcc/armcc_chdcffdb.htm +// RVCT embedded assembly documentation: +// http://www.keil.com/support/man/docs/armcc/armcc_chddbeib.htm + +// save our pragma state and switch to ARM mode +#pragma push +#pragma arm + +inline bool QBasicAtomicInt::ref() +{ + register int newValue; + register int result; + retry: + __asm { + ldrex newValue, [&_q_value] + add newValue, newValue, #1 + strex result, newValue, [&_q_value] + teq result, #0 + bne retry + } + return newValue != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + register int newValue; + register int result; + retry: + __asm { + ldrex newValue, [&_q_value] + sub newValue, newValue, #1 + strex result, newValue, [&_q_value] + teq result, #0 + bne retry + } + return newValue != 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + register int result; + retry: + __asm { + ldrex result, [&_q_value] + eors result, result, expectedValue + strexeq result, newValue, [&_q_value] + teqeq result, #1 + beq retry + } + return result == 0; +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + register int originalValue; + register int result; + retry: + __asm { + ldrex originalValue, [&_q_value] + strex result, newValue, [&_q_value] + teq result, #0 + bne retry + } + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + register int originalValue; + register int newValue; + register int result; + retry: + __asm { + ldrex originalValue, [&_q_value] + add newValue, originalValue, valueToAdd + strex result, newValue, [&_q_value] + teq result, #0 + bne retry + } + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + register T *result; + retry: + __asm { + ldrex result, [&_q_value] + eors result, result, expectedValue + strexeq result, newValue, [&_q_value] + teqeq result, #1 + beq retry + } + return result == 0; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + register T *originalValue; + register int result; + retry: + __asm { + ldrex originalValue, [&_q_value] + strex result, newValue, [&_q_value] + teq result, #0 + bne retry + } + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + register T *originalValue; + register T *newValue; + register int result; + retry: + __asm { + ldrex originalValue, [&_q_value] + add newValue, originalValue, valueToAdd * sizeof(T) + strex result, newValue, [&_q_value] + teq result, #0 + bne retry + } + return originalValue; +} + +// go back to the previous pragma state (probably Thumb mode) +#pragma pop +#endif + +// common code + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + template <typename T> Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) { diff --git a/src/corelib/arch/qatomic_symbian.h b/src/corelib/arch/qatomic_symbian.h index 3721aca..92f6ef9 100644 --- a/src/corelib/arch/qatomic_symbian.h +++ b/src/corelib/arch/qatomic_symbian.h @@ -42,12 +42,8 @@ #ifndef QATOMIC_SYMBIAN_H #define QATOMIC_SYMBIAN_H -#if defined(Q_CC_RVCT) -# define QT_NO_ARM_EABI -# include <QtCore/qatomic_arm.h> -#elif defined(Q_CC_NOKIAX86) || defined(Q_CC_GCCE) -# include <QtCore/qatomic_generic.h> -#endif +#include <qglobal.h> +#include <e32std.h> QT_BEGIN_HEADER @@ -55,7 +51,232 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) -// Empty, but needed to avoid warnings +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE + +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE + +Q_CORE_EXPORT bool QBasicAtomicPointer_isTestAndSetNative(); +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return QBasicAtomicPointer_isTestAndSetNative(); } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE + +Q_CORE_EXPORT bool QBasicAtomicPointer_isFetchAndStoreNative(); +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return QBasicAtomicPointer_isFetchAndStoreNative(); } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE + +Q_CORE_EXPORT bool QBasicAtomicPointer_isFetchAndAddNative(); +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return QBasicAtomicPointer_isFetchAndAddNative(); } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +Q_CORE_EXPORT bool QBasicAtomicInt_testAndSetOrdered(volatile int *, int, int); +Q_CORE_EXPORT int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *, int); +Q_CORE_EXPORT int QBasicAtomicInt_fetchAndAddOrdered(volatile int *, int); + +Q_CORE_EXPORT bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *, void *, void *); +Q_CORE_EXPORT void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *, void *); +Q_CORE_EXPORT void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *, qptrdiff); + +// Reference counting + +//LockedInc and LockedDec are machine coded for ARMv6 (and future proof) +inline bool QBasicAtomicInt::ref() +{ + int original = User::LockedInc((TInt&)_q_value); + return original != -1; +} + +inline bool QBasicAtomicInt::deref() +{ + int original = User::LockedDec((TInt&)_q_value); + return original != 1; +} + +// Test and set for integers + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + return QBasicAtomicInt_testAndSetOrdered(&_q_value, expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch and store for integers + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + return QBasicAtomicInt_fetchAndStoreOrdered(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch and add for integers + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + return QBasicAtomicInt_fetchAndAddOrdered(&_q_value, valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +// Test and set for pointers + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + union { T * volatile * typed; void * volatile * voidp; } pointer; + pointer.typed = &_q_value; + return QBasicAtomicPointer_testAndSetOrdered(pointer.voidp, expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch and store for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + union { T * volatile * typed; void * volatile * voidp; } pointer; + union { T *typed; void *voidp; } returnValue; + pointer.typed = &_q_value; + returnValue.voidp = QBasicAtomicPointer_fetchAndStoreOrdered(pointer.voidp, newValue); + return returnValue.typed; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch and add for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + union { T * volatile *typed; void * volatile *voidp; } pointer; + union { T *typed; void *voidp; } returnValue; + pointer.typed = &_q_value; + returnValue.voidp = QBasicAtomicPointer_fetchAndAddOrdered(pointer.voidp, valueToAdd * sizeof(T)); + return returnValue.typed; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} QT_END_NAMESPACE diff --git a/src/corelib/arch/symbian/arch.pri b/src/corelib/arch/symbian/arch.pri index deb94b1..3ef1c9e 100644 --- a/src/corelib/arch/symbian/arch.pri +++ b/src/corelib/arch/symbian/arch.pri @@ -2,4 +2,4 @@ # Symbian architecture # SOURCES += $$QT_ARCH_CPP/qatomic_symbian.cpp \ - $$QT_ARCH_CPP/../generic/qatomic_generic_unix.cpp + $$QT_ARCH_CPP/../armv6/qatomic_generic_armv6.cpp diff --git a/src/corelib/arch/symbian/qatomic_symbian.cpp b/src/corelib/arch/symbian/qatomic_symbian.cpp index 8f02155..91b49c7 100644 --- a/src/corelib/arch/symbian/qatomic_symbian.cpp +++ b/src/corelib/arch/symbian/qatomic_symbian.cpp @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE // This way we can report on heap cells and handles that are really not owned by anything which still exists. // This information can be used to detect whether memory leaks are happening, particularly if these numbers grow as the app is used more. // This code is placed here as it happens to make it the very last static to be destroyed in a Qt app. The -// reason assumed is that this file appears before any other file declaring static data in the generated +// reason assumed is that this file appears before any other file declaring static data in the generated // Symbian MMP file. This particular file was chosen as it is the earliest symbian specific file. struct QSymbianPrintExitInfo { @@ -77,37 +77,158 @@ struct QSymbianPrintExitInfo TInt initThreadHandleCount; } symbian_printExitInfo; -QT_END_NAMESPACE +Q_CORE_EXPORT bool QBasicAtomicInt::isReferenceCountingNative() +{ +#ifdef QT_HAVE_ARMV6 + return true; +#else + return false; +#endif +} +Q_CORE_EXPORT bool QBasicAtomicInt::isTestAndSetNative() +{ +#ifdef QT_HAVE_ARMV6 + return true; +#else + return false; +#endif +} -#if defined(Q_CC_RVCT) +Q_CORE_EXPORT bool QBasicAtomicInt::isFetchAndStoreNative() +{ +#ifdef QT_HAVE_ARMV6 + return true; +#else + return false; +#endif +} -#include "../arm/qatomic_arm.cpp" +Q_CORE_EXPORT bool QBasicAtomicInt::isFetchAndAddNative() +{ +#ifdef QT_HAVE_ARMV6 + return true; +#else + return false; +#endif +} -QT_BEGIN_NAMESPACE +Q_CORE_EXPORT bool QBasicAtomicPointer_isTestAndSetNative() +{ +#ifdef QT_HAVE_ARMV6 + return true; +#else + return false; +#endif +} -Q_CORE_EXPORT __asm char q_atomic_swp(volatile char *ptr, char newval) +Q_CORE_EXPORT bool QBasicAtomicPointer_isFetchAndStoreNative() { - add r2, pc, #0 - bx r2 - arm - swpb r2,r1,[r0] - mov r0, r2 - bx lr - thumb +#ifdef QT_HAVE_ARMV6 + return true; +#else + return false; +#endif } -Q_CORE_EXPORT __asm int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +Q_CORE_EXPORT bool QBasicAtomicPointer_isFetchAndAddNative() { - add r2, pc, #0 - bx r2 - arm - swp r2,r1,[r0] - mov r0, r2 - bx lr - thumb +#ifdef QT_HAVE_ARMV6 + return true; +#else + return false; +#endif } -QT_END_NAMESPACE +//For ARMv6, the generic atomics are machine coded +#ifndef QT_HAVE_ARMV6 + +class QCriticalSection +{ +public: + QCriticalSection() { fastlock.CreateLocal(); } + ~QCriticalSection() { fastlock.Close(); } + void lock() { fastlock.Wait(); } + void unlock() { fastlock.Signal(); } -#endif // Q_CC_RVCT +private: + RFastLock fastlock; +}; + +QCriticalSection qAtomicCriticalSection; + +Q_CORE_EXPORT +bool QBasicAtomicInt_testAndSetOrdered(volatile int *_q_value, int expectedValue, int newValue) +{ + bool returnValue = false; + qAtomicCriticalSection.lock(); + if (*_q_value == expectedValue) { + *_q_value = newValue; + returnValue = true; + } + qAtomicCriticalSection.unlock(); + return returnValue; +} + +Q_CORE_EXPORT +int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *_q_value, int newValue) +{ + int returnValue; + qAtomicCriticalSection.lock(); + returnValue = *_q_value; + *_q_value = newValue; + qAtomicCriticalSection.unlock(); + return returnValue; +} + +Q_CORE_EXPORT +int QBasicAtomicInt_fetchAndAddOrdered(volatile int *_q_value, int valueToAdd) +{ + int returnValue; + qAtomicCriticalSection.lock(); + returnValue = *_q_value; + *_q_value += valueToAdd; + qAtomicCriticalSection.unlock(); + return returnValue; +} + +Q_CORE_EXPORT +bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *_q_value, + void *expectedValue, + void *newValue) +{ + bool returnValue = false; + qAtomicCriticalSection.lock(); + if (*_q_value == expectedValue) { + *_q_value = newValue; + returnValue = true; + } + qAtomicCriticalSection.unlock(); + return returnValue; +} + +Q_CORE_EXPORT +void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *_q_value, void *newValue) +{ + void *returnValue; + qAtomicCriticalSection.lock(); + returnValue = *_q_value; + *_q_value = newValue; + qAtomicCriticalSection.unlock(); + return returnValue; +} + +Q_CORE_EXPORT +void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *_q_value, qptrdiff valueToAdd) +{ + void *returnValue; + qAtomicCriticalSection.lock(); + returnValue = *_q_value; + *_q_value = reinterpret_cast<char *>(returnValue) + valueToAdd; + qAtomicCriticalSection.unlock(); + return returnValue; +} + +#endif // QT_HAVE_ARMV6 + +QT_END_NAMESPACE diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index d113e02..9558256 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -437,13 +437,18 @@ namespace QT_NAMESPACE {} #elif defined(__GCCE__) # define Q_CC_GCCE # define QT_VISIBILITY_AVAILABLE +# if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) +# define QT_HAVE_ARMV6 +# endif /* ARM Realview Compiler Suite RVCT compiler also defines __EDG__ and __GNUC__ (if --gnu flag is given), so check for it before that */ #elif defined(__ARMCC__) || defined(__CC_ARM) # define Q_CC_RVCT - +# if __TARGET_ARCH_ARM >= 6 +# define QT_HAVE_ARMV6 +# endif #elif defined(__GNUC__) # define Q_CC_GNU # define Q_C_CALLBACKS diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp index 6bc6b76..3b1befd 100644 --- a/src/gui/dialogs/qfiledialog.cpp +++ b/src/gui/dialogs/qfiledialog.cpp @@ -3022,12 +3022,6 @@ bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) { case Qt::Key_Escape: q->hide(); return true; -#ifdef QT_KEYPAD_NAVIGATION - case Qt::Key_Down: - case Qt::Key_Up: - return (QApplication::navigationMode() != Qt::NavigationModeKeypadTabOrder - && QApplication::navigationMode() != Qt::NavigationModeKeypadDirectional); -#endif default: break; } @@ -3145,20 +3139,16 @@ QSize QFileDialogListView::sizeHint() const void QFileDialogListView::keyPressEvent(QKeyEvent *e) { - if (!d_ptr->itemViewKeyboardEvent(e)) { - QListView::keyPressEvent(e); - } #ifdef QT_KEYPAD_NAVIGATION - else if ((QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder - || QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) - && !hasEditFocus()) { - e->ignore(); - } else { - e->accept(); + if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) { + QListView::keyPressEvent(e); + return; } -#else +#endif // QT_KEYPAD_NAVIGATION + + if (!d_ptr->itemViewKeyboardEvent(e)) + QListView::keyPressEvent(e); e->accept(); -#endif } QFileDialogTreeView::QFileDialogTreeView(QWidget *parent) : QTreeView(parent) @@ -3184,20 +3174,16 @@ void QFileDialogTreeView::init(QFileDialogPrivate *d_pointer) void QFileDialogTreeView::keyPressEvent(QKeyEvent *e) { - if (!d_ptr->itemViewKeyboardEvent(e)) { - QTreeView::keyPressEvent(e); - } #ifdef QT_KEYPAD_NAVIGATION - else if ((QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder - || QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) - && !hasEditFocus()) { - e->ignore(); - } else { - e->accept(); + if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) { + QTreeView::keyPressEvent(e); + return; } -#else +#endif // QT_KEYPAD_NAVIGATION + + if (!d_ptr->itemViewKeyboardEvent(e)) + QTreeView::keyPressEvent(e); e->accept(); -#endif } QSize QFileDialogTreeView::sizeHint() const @@ -3213,13 +3199,16 @@ QSize QFileDialogTreeView::sizeHint() const */ void QFileDialogLineEdit::keyPressEvent(QKeyEvent *e) { +#ifdef QT_KEYPAD_NAVIGATION + if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) { + QLineEdit::keyPressEvent(e); + return; + } +#endif // QT_KEYPAD_NAVIGATION + int key = e->key(); QLineEdit::keyPressEvent(e); - if (key != Qt::Key_Escape -#ifdef QT_KEYPAD_NAVIGATION - && QApplication::navigationMode() == Qt::NavigationModeNone -#endif - ) + if (key != Qt::Key_Escape) e->accept(); if (hideOnEsc && (key == Qt::Key_Escape || key == Qt::Key_Return || key == Qt::Key_Enter)) { e->accept(); diff --git a/src/gui/image/qpixmap_s60.cpp b/src/gui/image/qpixmap_s60.cpp index f7a880c..21415d3 100644 --- a/src/gui/image/qpixmap_s60.cpp +++ b/src/gui/image/qpixmap_s60.cpp @@ -349,7 +349,8 @@ QS60PixmapData::QS60PixmapData(PixelType type) : QRasterPixmapData(type), bitmapDevice(0), bitmapGc(0), pengine(0), - bytes(0) + bytes(0), + formatLocked(false) { } @@ -425,11 +426,12 @@ void QS60PixmapData::release() } /*! - * Takes ownership of bitmap + * Takes ownership of bitmap. Used by window surface */ void QS60PixmapData::fromSymbianBitmap(CFbsBitmap* bitmap) { cfbsBitmap = bitmap; + formatLocked = true; if(!initSymbianBitmapContext()) { qWarning("Could not create CBitmapContext"); @@ -693,8 +695,10 @@ void QS60PixmapData::beginDataAccess() bytes = newBytes; TDisplayMode mode = cfbsBitmap->DisplayMode(); QImage::Format format = qt_TDisplayMode2Format(mode); - //on S60 3.1, premultiplied alpha pixels are stored in a bitmap with 16MA type - if (format == QImage::Format_ARGB32) + // On S60 3.1, premultiplied alpha pixels are stored in a bitmap with 16MA type. + // S60 window surface needs backing store pixmap for transparent window in ARGB32 format. + // In that case formatLocked is true. + if (!formatLocked && format == QImage::Format_ARGB32) format = QImage::Format_ARGB32_Premultiplied; // pixel data is actually in premultiplied format QVector<QRgb> savedColorTable; diff --git a/src/gui/image/qpixmap_s60_p.h b/src/gui/image/qpixmap_s60_p.h index b23961a..b1b5824 100644 --- a/src/gui/image/qpixmap_s60_p.h +++ b/src/gui/image/qpixmap_s60_p.h @@ -118,6 +118,8 @@ private: QPaintEngine *pengine; uchar* bytes; + bool formatLocked; + friend class QPixmap; friend class QS60WindowSurface; friend class QS60PaintEngine; diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h index 452aa75..d0b488e 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_p.h +++ b/src/gui/inputmethod/qcoefepinputcontext_p.h @@ -84,7 +84,7 @@ public: bool filterEvent(const QEvent *event); void mouseHandler( int x, QMouseEvent *event); - bool isComposing() const { return m_isEditing; } + bool isComposing() const { return !m_preeditString.isEmpty(); } void setFocusWidget(QWidget * w); void widgetDestroyed(QWidget *w); @@ -132,6 +132,7 @@ public: // From MObjectProvider public: TTypeUid::Ptr MopSupplyObject(TTypeUid id); + MObjectProvider *MopNext(); private: QSymbianControl *m_parent; @@ -139,13 +140,14 @@ private: QString m_preeditString; Qt::InputMethodHints m_lastImHints; TUint m_textCapabilities; - bool m_isEditing; bool m_inDestruction; bool m_pendingInputCapabilitiesChanged; int m_cursorVisibility; int m_inlinePosition; MFepInlineTextFormatRetriever *m_formatRetriever; MFepPointerEventHandlerDuringInlineEdit *m_pointerHandler; + int m_longPress; + int m_cursorPos; }; QT_END_NAMESPACE diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 25b2313..08d86d7 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -65,13 +65,14 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent) m_fepState(q_check_ptr(new CAknEdwinState)), // CBase derived object needs check on new m_lastImHints(Qt::ImhNone), m_textCapabilities(TCoeInputCapabilities::EAllText), - m_isEditing(false), m_inDestruction(false), m_pendingInputCapabilitiesChanged(false), m_cursorVisibility(1), m_inlinePosition(0), m_formatRetriever(0), - m_pointerHandler(0) + m_pointerHandler(0), + m_longPress(0), + m_cursorPos(0) { m_fepState->SetObjectProvider(this); m_fepState->SetFlags(EAknEditorFlagDefault); @@ -79,7 +80,7 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent) m_fepState->SetPermittedInputModes( EAknEditorAllInputModes ); m_fepState->SetDefaultCase( EAknEditorLowerCase ); m_fepState->SetPermittedCases( EAknEditorLowerCase|EAknEditorUpperCase ); - m_fepState->SetSpecialCharacterTableResourceId( 0 ); + m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_SPECIAL_CHARACTER_TABLE_DIALOG); m_fepState->SetNumericKeymap( EAknEditorStandardNumberModeKeymap ); } @@ -202,14 +203,26 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) { const QKeyEvent *keyEvent = static_cast<const QKeyEvent *>(event); - Q_ASSERT(m_lastImHints == focusWidget()->inputMethodHints()); - if (keyEvent->key() == Qt::Key_F20 && m_lastImHints & Qt::ImhHiddenText) { - // Special case in Symbian. On editors with secret text, F20 is for some reason - // considered to be a backspace. - QKeyEvent modifiedEvent(keyEvent->type(), Qt::Key_Backspace, keyEvent->modifiers(), - keyEvent->text(), keyEvent->isAutoRepeat(), keyEvent->count()); - QApplication::sendEvent(focusWidget(), &modifiedEvent); - return true; + switch (keyEvent->key()) { + case Qt::Key_F20: + Q_ASSERT(m_lastImHints == focusWidget()->inputMethodHints()); + if (m_lastImHints & Qt::ImhHiddenText) { + // Special case in Symbian. On editors with secret text, F20 is for some reason + // considered to be a backspace. + QKeyEvent modifiedEvent(keyEvent->type(), Qt::Key_Backspace, keyEvent->modifiers(), + keyEvent->text(), keyEvent->isAutoRepeat(), keyEvent->count()); + QApplication::sendEvent(focusWidget(), &modifiedEvent); + return true; + } + break; + case Qt::Key_Select: + if (!m_preeditString.isEmpty()) { + commitCurrentString(false); + return true; + } + break; + default: + break; } } @@ -243,7 +256,6 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) void QCoeFepInputContext::mouseHandler( int x, QMouseEvent *event) { - Q_ASSERT(m_isEditing); Q_ASSERT(focusWidget()); if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::LeftButton) { @@ -407,6 +419,14 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) } m_fepState->SetNumericKeymap(static_cast<TAknEditorNumericKeymap>(flags)); + if (hints & ImhEmailCharactersOnly) { + m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_EMAIL_ADDR_SPECIAL_CHARACTER_TABLE_DIALOG); + } else if (hints & ImhUrlCharactersOnly) { + m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_URL_SPECIAL_CHARACTER_TABLE_DIALOG); + } else { + m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_SPECIAL_CHARACTER_TABLE_DIALOG); + } + if (hints & ImhHiddenText) { m_textCapabilities = TCoeInputCapabilities::EAllText | TCoeInputCapabilities::ESecretText; } else { @@ -478,8 +498,8 @@ void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText, if (!w) return; - m_isEditing = true; - + m_cursorPos = w->inputMethodQuery(Qt::ImCursorPosition).toInt(); + QList<QInputMethodEvent::Attribute> attributes; m_cursorVisibility = aCursorVisibility ? 1 : 0; @@ -543,8 +563,6 @@ void QCoeFepInputContext::CancelFepInlineEdit() event.setCommitString(QLatin1String(""), 0, 0); m_preeditString.clear(); sendEvent(event); - - m_isEditing = false; } TInt QCoeFepInputContext::DocumentLengthForFep() const @@ -683,16 +701,22 @@ void QCoeFepInputContext::DoCommitFepInlineEditL() void QCoeFepInputContext::commitCurrentString(bool triggeredBySymbian) { if (m_preeditString.size() == 0) { + QWidget *w = focusWidget(); + if (triggeredBySymbian && w) { + // We must replace the last character only if the input box has already accepted one + if (w->inputMethodQuery(Qt::ImCursorPosition).toInt() != m_cursorPos) + m_longPress = 1; + } return; } QList<QInputMethodEvent::Attribute> attributes; QInputMethodEvent event(QLatin1String(""), attributes); - event.setCommitString(m_preeditString, 0, 0);//m_preeditString.size()); + event.setCommitString(m_preeditString, 0-m_longPress, m_longPress); m_preeditString.clear(); sendEvent(event); - m_isEditing = false; + m_longPress = 0; if (!triggeredBySymbian) { CCoeFep* fep = CCoeEnv::Static()->Fep(); @@ -733,6 +757,14 @@ TTypeUid::Ptr QCoeFepInputContext::MopSupplyObject(TTypeUid /*id*/) return TTypeUid::Null(); } +MObjectProvider *QCoeFepInputContext::MopNext() +{ + QWidget *w = focusWidget(); + if (w) + return w->effectiveWinId(); + return 0; +} + QT_END_NAMESPACE #endif // QT_NO_IM diff --git a/src/gui/itemviews/qtreewidget.cpp b/src/gui/itemviews/qtreewidget.cpp index 040c498..c133ae4 100644 --- a/src/gui/itemviews/qtreewidget.cpp +++ b/src/gui/itemviews/qtreewidget.cpp @@ -2851,7 +2851,14 @@ QTreeWidgetItem *QTreeWidget::itemAt(const QPoint &p) const QRect QTreeWidget::visualItemRect(const QTreeWidgetItem *item) const { Q_D(const QTreeWidget); - return visualRect(d->index(item)); + //the visual rect for an item is across all columns. So we need to determine + //what is the first and last column and get their visual index rects + QModelIndex base = d->index(item); + const int firstVisiblesection = header()->logicalIndexAt(- header()->offset()); + const int lastVisibleSection = header()->logicalIndexAt(header()->length() - header()->offset() - 1); + QModelIndex first = base.sibling(base.row(), header()->logicalIndex(firstVisiblesection)); + QModelIndex last = base.sibling(base.row(), header()->logicalIndex(lastVisibleSection)); + return visualRect(first) | visualRect(last); } /*! diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 5578a72..dd2ccf2 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -319,7 +319,12 @@ void QLongTapTimer::RunL() } QSymbianControl::QSymbianControl(QWidget *w) - : CCoeControl(), qwidget(w), m_ignoreFocusChanged(false) + : CCoeControl() + , qwidget(w) + , m_longTapDetector(0) + , m_ignoreFocusChanged(0) + , m_previousEventLongTap(0) + , m_symbianPopupIsOpen(0) { } @@ -911,6 +916,15 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) return; if (IsFocused() && IsVisible()) { + if (m_symbianPopupIsOpen) { + QWidget *fw = QApplication::focusWidget(); + if (fw) { + QFocusEvent event(QEvent::FocusIn, Qt::PopupFocusReason); + QCoreApplication::sendEvent(fw, &event); + } + m_symbianPopupIsOpen = false; + } + QApplication::setActiveWindow(qwidget->window()); #ifdef Q_WS_S60 // If widget is fullscreen, hide status pane and button container @@ -924,6 +938,16 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) buttonGroup->MakeVisible(!isFullscreen); #endif } else if (QApplication::activeWindow() == qwidget->window()) { + if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog()) { + QWidget *fw = QApplication::focusWidget(); + if (fw) { + QFocusEvent event(QEvent::FocusOut, Qt::PopupFocusReason); + QCoreApplication::sendEvent(fw, &event); + } + m_symbianPopupIsOpen = true; + return; + } + QApplication::setActiveWindow(0); } // else { We don't touch the active window unless we were explicitly activated or deactivated } diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp index ecad72f..22ac319 100644 --- a/src/gui/kernel/qsoftkeymanager.cpp +++ b/src/gui/kernel/qsoftkeymanager.cpp @@ -213,11 +213,15 @@ void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &softkeys) CEikButtonGroupContainer* nativeContainer = S60->buttonGroupContainer(); nativeContainer->DrawableWindow()->SetOrdinalPosition(0); nativeContainer->DrawableWindow()->SetPointerCapturePriority(1); //keep softkeys available in modal dialog - QT_TRAP_THROWING(nativeContainer->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS)); + nativeContainer->DrawableWindow()->SetFaded(EFalse, RWindowTreeNode::EFadeIncludeChildren); int position = -1; - int command; bool needsExitButton = true; + QT_TRAP_THROWING( + //Using -1 instead of EAknSoftkeyEmpty to avoid flickering. + nativeContainer->SetCommandL(0, -1, KNullDesC); + nativeContainer->SetCommandL(2, -1, KNullDesC); + ); for (int index = 0; index < softkeys.count(); index++) { const QAction* softKeyAction = softkeys.at(index); @@ -238,7 +242,7 @@ void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &softkeys) break; } - command = (softKeyAction->objectName().contains("_q_menuSoftKeyAction")) + int command = (softKeyAction->objectName().contains("_q_menuSoftKeyAction")) ? EAknSoftkeyOptions : s60CommandStart + index; @@ -255,7 +259,8 @@ void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &softkeys) : Qt::Widget; if (needsExitButton && sourceWindowType != Qt::Dialog && sourceWindowType != Qt::Popup) - QT_TRAP_THROWING(nativeContainer->SetCommandL(2, EAknSoftkeyExit, qt_QString2TPtrC(QSoftKeyManager::tr("Exit")))); + QT_TRAP_THROWING( + nativeContainer->SetCommandL(2, EAknSoftkeyExit, qt_QString2TPtrC(QSoftKeyManager::tr("Exit")))); nativeContainer->DrawDeferred(); // 3.1 needs an extra invitation } diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index 3405bcf..d45c34a 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -175,7 +175,7 @@ public: protected: // from MAknFadedComponent TInt CountFadedComponents() {return 1;} - CCoeControl* FadedComponent(TInt aIndex) {return this;} + CCoeControl* FadedComponent(TInt /*aIndex*/) {return this;} #else #warning No fallback implementation for QSymbianControl::FadeBehindPopup void FadeBehindPopup(bool /*fade*/){ } @@ -202,9 +202,10 @@ private: private: QWidget *qwidget; - bool m_ignoreFocusChanged; QLongTapTimer* m_longTapDetector; - bool m_previousEventLongTap; + bool m_ignoreFocusChanged : 1; + bool m_previousEventLongTap : 1; + bool m_symbianPopupIsOpen : 1; #ifdef Q_WS_S60 // Fader object used to fade everything except this menu and the CBA. diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 88cd63d..504a538 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -359,6 +359,7 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) ); QT_TRAP_THROWING(control->ConstructL(true, desktop)); + control->SetMopParent(static_cast<CEikAppUi*>(S60->appUi())); // Symbian windows are always created in an inactive state // We perform this assignment for the case where the window is being re-created @@ -1235,7 +1236,7 @@ void QWidget::releaseKeyboard() void QWidget::grabMouse() { - if (!qt_nograb()) { + if (isVisible() && !qt_nograb()) { if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this) QWidgetPrivate::mouseGrabber->releaseMouse(); Q_ASSERT(testAttribute(Qt::WA_WState_Created)); @@ -1252,7 +1253,7 @@ void QWidget::grabMouse() #ifndef QT_NO_CURSOR void QWidget::grabMouse(const QCursor &cursor) { - if (!qt_nograb()) { + if (isVisible() && !qt_nograb()) { if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this) QWidgetPrivate::mouseGrabber->releaseMouse(); Q_ASSERT(testAttribute(Qt::WA_WState_Created)); diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index c35c33a..628a109 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -370,7 +370,6 @@ symbian { SOURCES += painting/qwindowsurface_s60.cpp armccIfdefBlock = \ "$${LITERAL_HASH}if defined(ARMV6)" \ - "MACRO QT_HAVE_ARMV6" \ "SOURCEPATH painting" \ "SOURCE qblendfunctions_armv6_rvct.s" \ "SOURCE qdrawhelper_armv6_rvct.s" \ diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp index 8737f10..ba1b642 100644 --- a/src/gui/painting/qblendfunctions.cpp +++ b/src/gui/painting/qblendfunctions.cpp @@ -223,21 +223,25 @@ void qt_scale_image_16bit(uchar *destPixels, int dbpl, int h = ty2 - ty1; int w = tx2 - tx1; + quint32 basex; quint32 srcy; + const int dstx = qCeil((tx1 + 0.5 - qMin(targetRect.left(), targetRect.right())) * ix) - 1; + const int dsty = qCeil((ty1 + 0.5 - qMin(targetRect.top(), targetRect.bottom())) * iy) - 1; + if (sx < 0) { - int dstx = qFloor((tx1 + 0.5 - targetRect.right()) * ix) + 1; + int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1; basex = quint32(srcRect.right() * 65536) + dstx; } else { - int dstx = qCeil((tx1 + 0.5 - targetRect.left()) * ix) - 1; + int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1; basex = quint32(srcRect.left() * 65536) + dstx; } if (sy < 0) { - int dsty = qFloor((ty1 + 0.5 - targetRect.bottom()) * iy) + 1; + int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1; srcy = quint32(srcRect.bottom() * 65536) + dsty; } else { - int dsty = qCeil((ty1 + 0.5 - targetRect.top()) * iy) - 1; + int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1; srcy = quint32(srcRect.top() * 65536) + dsty; } @@ -738,18 +742,22 @@ template <typename T> void qt_scale_image_32bit(uchar *destPixels, int dbpl, quint32 basex; quint32 srcy; + const int dstx = qCeil((tx1 + 0.5 - qMin(targetRect.left(), targetRect.right())) * ix) - 1; + const int dsty = qCeil((ty1 + 0.5 - qMin(targetRect.top(), targetRect.bottom())) * iy) - 1; + + if (sx < 0) { - int dstx = qFloor((tx1 + 0.5 - targetRect.right()) * ix) + 1; + int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1; basex = quint32(srcRect.right() * 65536) + dstx; } else { - int dstx = qCeil((tx1 + 0.5 - targetRect.left()) * ix) - 1; + int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1; basex = quint32(srcRect.left() * 65536) + dstx; } if (sy < 0) { - int dsty = qFloor((ty1 + 0.5 - targetRect.bottom()) * iy) + 1; + int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1; srcy = quint32(srcRect.bottom() * 65536) + dsty; } else { - int dsty = qCeil((ty1 + 0.5 - targetRect.top()) * iy) - 1; + int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1; srcy = quint32(srcRect.top() * 65536) + dsty; } diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index 02ffb29..9179237 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -473,7 +473,7 @@ void QS60StylePrivate::setBackgroundTexture(QApplication *app) const Q_UNUSED(app) QPalette applicationPalette = QApplication::palette(); applicationPalette.setBrush(QPalette::Window, backgroundTexture()); - setThemePalette(app); + setThemePalette(&applicationPalette); } void QS60StylePrivate::deleteBackground() @@ -799,6 +799,9 @@ QSize QS60StylePrivate::partSize(QS60StyleEnums::SkinParts part, SkinElementFlag case QS60StyleEnums::SP_QgnGrafTabPassiveR: case QS60StyleEnums::SP_QgnGrafTabPassiveL: case QS60StyleEnums::SP_QgnGrafTabActiveL: + //Returned QSize for tabs must not be square, but narrow rectangle with width:height + //ratio of 1:2 for horizontal tab bars (and 2:1 for vertical ones). + result.setWidth(10); break; case QS60StyleEnums::SP_QgnIndiSliderEdit: result.scale(pixelMetric(QStyle::PM_SliderLength), @@ -809,7 +812,7 @@ QSize QS60StylePrivate::partSize(QS60StyleEnums::SkinParts part, SkinElementFlag case QS60StyleEnums::SP_QgnGrafBarFrameSideR: result.setWidth(pixelMetric(PM_Custom_FrameCornerWidth)); break; - + case QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed: case QS60StyleEnums::SP_QsnCpScrollHandleTopPressed: case QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed: diff --git a/src/gui/widgets/qdialogbuttonbox.cpp b/src/gui/widgets/qdialogbuttonbox.cpp index 2231b98..2ee5751 100644 --- a/src/gui/widgets/qdialogbuttonbox.cpp +++ b/src/gui/widgets/qdialogbuttonbox.cpp @@ -315,9 +315,9 @@ void QDialogButtonBoxPrivate::initLayout() buttonLayout = new QVBoxLayout(q); } - int left, top, right, bottom; + int left, top, right, bottom; setLayoutItemMargins(QStyle::SE_PushButtonLayoutItem); - getLayoutItemMargins(&left, &top, &right, &bottom); + getLayoutItemMargins(&left, &top, &right, &bottom); buttonLayout->setContentsMargins(-left, -top, -right, -bottom); if (!q->testAttribute(Qt::WA_WState_OwnSizePolicy)) { @@ -356,7 +356,7 @@ void QDialogButtonBoxPrivate::addButtonsToLayout(const QList<QAbstractButton *> void QDialogButtonBoxPrivate::layoutButtons() { Q_Q(QDialogButtonBox); - const int MacGap = 36 - 8; // 8 is the default gap between a widget and a spacer item + const int MacGap = 36 - 8; // 8 is the default gap between a widget and a spacer item for (int i = buttonLayout->count() - 1; i >= 0; --i) { QLayoutItem *item = buttonLayout->takeAt(i); @@ -581,6 +581,22 @@ QAction* QDialogButtonBoxPrivate::createSoftKey(QAbstractButton *button, QDialog } QObject::connect(action, SIGNAL(triggered()), button, SIGNAL(clicked())); action->setSoftKeyRole(softkeyRole); + + + QWidget *dialog = 0; + QWidget *p = q; + while (p && !p->isWindow()) { + p = p->parentWidget(); + if ((dialog = qobject_cast<QDialog *>(p))) + break; + } + + if (dialog) { + dialog->addAction(action); + } else { + q->addAction(action); + } + return action; } #endif @@ -1193,12 +1209,8 @@ bool QDialogButtonBox::event(QEvent *event) if (!hasDefault && firstAcceptButton) firstAcceptButton->setDefault(true); #ifdef QT_SOFTKEYS_ENABLED - if (dialog) { + if (dialog) setFixedSize(0,0); - dialog->addActions(d->softKeyActions.values()); - } else { - addActions(d->softKeyActions.values()); - } #endif }else if (event->type() == QEvent::LanguageChange) { d->retranslateStrings(); diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp index 3d908a1..ea711e8 100644 --- a/src/gui/widgets/qlabel.cpp +++ b/src/gui/widgets/qlabel.cpp @@ -1170,22 +1170,10 @@ void QLabelPrivate::updateShortcut() // But then we do want to hide the ampersands, so we can't use shortcutId. hasShortcut = false; - if (control) { - ensureTextPopulated(); - // Underline the first character that follows an ampersand - shortcutCursor = control->document()->find(QLatin1String("&")); - if (shortcutCursor.isNull()) - return; - hasShortcut = true; - shortcutId = q->grabShortcut(QKeySequence::mnemonic(text)); - shortcutCursor.deleteChar(); // remove the ampersand - shortcutCursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); - } else { - if (!text.contains(QLatin1Char('&'))) - return; - hasShortcut = true; - shortcutId = q->grabShortcut(QKeySequence::mnemonic(text)); - } + if (!text.contains(QLatin1Char('&'))) + return; + hasShortcut = true; + shortcutId = q->grabShortcut(QKeySequence::mnemonic(text)); } #endif // QT_NO_SHORTCUT @@ -1456,6 +1444,24 @@ void QLabelPrivate::ensureTextPopulated() const doc->setPlainText(text); #endif doc->setUndoRedoEnabled(false); + +#ifndef QT_NO_SHORTCUT + if (hasShortcut) { + // Underline the first character that follows an ampersand (and remove the others ampersands) + int from = 0; + bool found = false; + QTextCursor cursor; + while (!(cursor = control->document()->find((QLatin1String("&")), from)).isNull()) { + cursor.deleteChar(); // remove the ampersand + cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); + from = cursor.position(); + if (!found && cursor.selectedText() != QLatin1String("&")) { //not a second & + found = true; + shortcutCursor = cursor; + } + } + } +#endif } } textDirty = false; diff --git a/src/gui/widgets/qlabel_p.h b/src/gui/widgets/qlabel_p.h index c5a74e2..ca17a35 100644 --- a/src/gui/widgets/qlabel_p.h +++ b/src/gui/widgets/qlabel_p.h @@ -113,7 +113,7 @@ public: mutable uint hasShortcut : 1; Qt::TextFormat textformat; mutable QTextControl *control; - QTextCursor shortcutCursor; + mutable QTextCursor shortcutCursor; Qt::TextInteractionFlags textInteractionFlags; inline bool needTextControl() const { diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 2914164..300a2ea 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -414,7 +414,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) int c = m_cursor; // cursor position after insertion of commit string - if (event->replacementStart() <= 0) + if (event->replacementStart() == 0) c += event->commitString().length() + qMin(-event->replacementStart(), event->replacementLength()); m_cursor += event->replacementStart(); diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp index 027a5d6..fa6f7a1 100644 --- a/src/gui/widgets/qmainwindowlayout.cpp +++ b/src/gui/widgets/qmainwindowlayout.cpp @@ -1641,6 +1641,9 @@ void QMainWindowLayout::animationFinished(QWidget *widget) savedState.clear(); currentGapPos.clear(); pluggingWidget = 0; + //applying the state will make sure that the currentGap is updated correctly + //and all the geometries (especially the one from the central widget) is correct + layoutState.apply(false); } if (!widgetAnimator.animating()) { diff --git a/tests/auto/qlabel/tst_qlabel.cpp b/tests/auto/qlabel/tst_qlabel.cpp index 9d957a5..6b7e106 100644 --- a/tests/auto/qlabel/tst_qlabel.cpp +++ b/tests/auto/qlabel/tst_qlabel.cpp @@ -51,6 +51,7 @@ #include <qmovie.h> #include <qpicture.h> #include <qmessagebox.h> +#include <private/qlabel_p.h> //TESTED_CLASS= //TESTED_FILES= @@ -116,6 +117,9 @@ private slots: void unicodeText_data(); void unicodeText(); + void mnemonic_data(); + void mnemonic(); + private: QLabel *testWidget; QPointer<Widget> test_box; @@ -224,6 +228,7 @@ void tst_QLabel::setBuddy() QVERIFY( !test_edit->hasFocus() ); QTest::keyClick( test_box, 't', Qt::AltModifier ); QVERIFY( test_edit->hasFocus() ); + delete test_box; } void tst_QLabel::text() @@ -245,6 +250,7 @@ void tst_QLabel::setText_data() QTest::newRow( QString(prefix + "data1").toLatin1() ) << QString("This is the first line\nThis is the second line") << QString("Courier"); QTest::newRow( QString(prefix + "data2").toLatin1() ) << QString("This is the first line\nThis is the second line\nThis is the third line") << QString("Helvetica"); QTest::newRow( QString(prefix + "data3").toLatin1() ) << QString("This is <b>bold</b> richtext") << QString("Courier"); + QTest::newRow( QString(prefix + "data4").toLatin1() ) << QString("I Have a &shortcut") << QString("Helvetica"); } void tst_QLabel::setText() @@ -509,5 +515,50 @@ void tst_QLabel::unicodeText() testWidget->show(); } +void tst_QLabel::mnemonic_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<QString>("expectedDocText"); + QTest::addColumn<QString>("expectedShortcutCursor"); + + QTest::newRow("1") << QString("Normal") << QString("Normal") << QString(); + QTest::newRow("2") << QString("&Simple") << QString("Simple") << QString("S"); + QTest::newRow("3") << QString("Also &simple") << QString("Also simple") << QString("s"); + QTest::newRow("4") << QString("&&With &Double &&") << QString("&With Double &") << QString("D"); + QTest::newRow("5") << QString("Hep&&Hop") << QString("Hep&Hop") << QString(""); + QTest::newRow("6") << QString("Hep&&&Hop") << QString("Hep&Hop") << QString("H"); +} + + +void tst_QLabel::mnemonic() +{ + // this test that the mnemonics appears correctly when the label has a text control. + + QFETCH(QString, text); + QFETCH(QString, expectedDocText); + QFETCH(QString, expectedShortcutCursor); + + QWidget w; + QHBoxLayout *hbox = new QHBoxLayout; + QLabel *lab = new QLabel(text); + //lab->setText("plop &plop"); + QLineEdit *lineedit = new QLineEdit; + lab->setBuddy(lineedit); + lab->setTextInteractionFlags(Qt::TextSelectableByMouse); + + hbox->addWidget(lab); + hbox->addWidget(lineedit); + hbox->addWidget(new QLineEdit); + w.setLayout(hbox); + w.show(); + QTest::qWaitForWindowShown(&w); + + QLabelPrivate *d = static_cast<QLabelPrivate *>(QObjectPrivate::get(lab)); + QVERIFY(d->control); + QCOMPARE(d->control->document()->toPlainText(), expectedDocText); + QCOMPARE(d->shortcutCursor.selectedText(), expectedShortcutCursor); +} + + QTEST_MAIN(tst_QLabel) #include "tst_qlabel.moc" |