diff options
Diffstat (limited to 'src')
758 files changed, 49066 insertions, 4558 deletions
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp b/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp index 4d8418b..817fb0d 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp +++ b/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp @@ -37,7 +37,7 @@ static HB_Bool isLetter(HB_UChar16 ucs) FLAG(HB_Letter_Titlecase) | FLAG(HB_Letter_Modifier) | FLAG(HB_Letter_Other); - return FLAG(HB_GetUnicodeCharCategory(ucs)) & test; + return (FLAG(HB_GetUnicodeCharCategory(ucs)) & test) != 0; } static HB_Bool isMark(HB_UChar16 ucs) @@ -660,18 +660,18 @@ static const unsigned char indicPosition[0xe00-0x900] = { None, None, None, None, None, None, None, None, - None, None, None, None, - None, None, None, None, - None, None, None, None, + None, Below, Below, Below, + Below, Below, Below, Below, + Below, Below, None, Below, - None, None, None, None, - Below, None, None, None, - Below, None, None, None, + Below, Below, Below, Below, + Below, Below, Below, Below, + Below, None, Below, Below, Below, Below, Below, Post, Below, None, Below, Below, - None, None, None, None, - None, None, None, None, + None, Below, Below, Below, + Below, Below, None, None, None, None, Post, Above, Post, Below, Below, Below, @@ -1741,6 +1741,11 @@ static int indic_nextSyllableBoundary(HB_Script script, const HB_UChar16 *s, int if (state == Halant && uc[pos] == 0x200d /* ZWJ */) break; // the control character should be the last char in the item + if (state == Consonant && script == HB_Script_Bengali && uc[pos-1] == 0x09B0 && uc[pos] == 0x200d /* ZWJ */) + break; + if (state == Consonant && script == HB_Script_Kannada && uc[pos-1] == 0x0CB0 && uc[pos] == 0x200d /* ZWJ */) + break; + // Bengali and Kannada has a special exception for rendering yaphala with ra (to avoid reph) see http://www.unicode.org/faq/indic.html#15 ++pos; goto finish; case Consonant: diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c b/src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c index 7cd82bb..4b68e64 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c +++ b/src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c @@ -424,12 +424,8 @@ static HB_Bool myanmar_shape_syllable(HB_Bool openType, HB_ShaperItem *item, HB_ #ifndef NO_OPENTYPE if (openType) { - unsigned short logClusters[32]; hb_uint32 where[32]; - for (i = 0; i < len; ++i) - logClusters[i] = i; - for (i = 0; i < len; ++i) { where[i] = ~(PreSubstProperty | BelowSubstProperty diff --git a/src/3rdparty/harfbuzz/tests/shaping/main.cpp b/src/3rdparty/harfbuzz/tests/shaping/main.cpp index 28f8e07..73760a8 100644 --- a/src/3rdparty/harfbuzz/tests/shaping/main.cpp +++ b/src/3rdparty/harfbuzz/tests/shaping/main.cpp @@ -642,6 +642,10 @@ void tst_QScriptEngine::bengali() { { 0x9f1, 0x9cd, 0x9ad, 0x0 }, { 0x191, 0x17d, 0x168, 0x0 } }, + // Ra ZWJ Halant Ya + { { 0x09b0, 0x200d, 0x09cd, 0x09af, 0x0 }, + { 0x016b, 0x01cf, 0x0 } }, + { {0}, {0} } }; @@ -749,6 +753,13 @@ void tst_QScriptEngine::bengali() { { 0x09b0, 0x09cd, 0x09ac, 0x09cd, 0x09ac, 0x0 }, { 0x013b, 0x00e1, 0x0 } }, + // Init feature for vowel sign E should only be + // applied when it's initial character (QTBUG-13620) + { { 0x09a8, 0x09c7, 0x0 }, + { 0x0232, 0x0086, 0x0 } }, + { { 0x09a8, 0x09a8, 0x09c7, 0x0 }, + { 0x0086, 0x009b, 0x0086, 0x0 } }, + { {0}, {0} } }; @@ -847,6 +858,19 @@ void tst_QScriptEngine::oriya() { 0x177, 0x0 } }, { { 0xb28, 0xb4d, 0xb24, 0xb4d, 0xb30, 0xb4d, 0xb2f, 0x0 }, { 0x176, 0x124, 0x0 } }, + + // QTBUG-13542 + { { 0x0b2c, 0x0b4d, 0x0b21, 0x0 }, + { 0x0089, 0x00fc, 0x0 } }, + { { 0x0b36, 0x0b4d, 0x0b2b, 0x0 }, + { 0x0092, 0x0105, 0x0 } }, + { { 0x0b36, 0x0b4d, 0x0b1f, 0x0 }, + { 0x0092, 0x00fa, 0x0 } }, + { { 0x0b39, 0x0b4d, 0x0b1f, 0x0 }, + { 0x0095, 0x00fa, 0x0 } }, + { { 0x0b15, 0x0b4d, 0x0b16, 0x0 }, + { 0x0073, 0x00f1, 0x0 } }, + { {0}, {0} } }; @@ -1005,6 +1029,11 @@ void tst_QScriptEngine::kannada() { 0x0036, 0x00c1, 0x0 } }, { { 0x0cb0, 0x0ccd, 0x200d, 0x0c95, 0x0 }, { 0x0050, 0x00a7, 0x0 } }, + + // Kaphala + { { 0x0cb0, 0x200d, 0x0ccd, 0x0c95, 0x0 }, + { 0x0050, 0x00a7, 0x0 } }, + { {0}, {0} } }; diff --git a/src/3rdparty/md5/md5.cpp b/src/3rdparty/md5/md5.cpp index f32903c..ac296b5 100644 --- a/src/3rdparty/md5/md5.cpp +++ b/src/3rdparty/md5/md5.cpp @@ -24,6 +24,7 @@ #ifndef _WIN32_WCE #include <sys/types.h> /* for stupid systems */ #else +#include <windef.h> #include <types.h> #endif diff --git a/src/3rdparty/phonon/gstreamer/devicemanager.cpp b/src/3rdparty/phonon/gstreamer/devicemanager.cpp index c3826eb..518aa85 100644 --- a/src/3rdparty/phonon/gstreamer/devicemanager.cpp +++ b/src/3rdparty/phonon/gstreamer/devicemanager.cpp @@ -22,7 +22,9 @@ #include "videowidget.h" #include "glrenderer.h" #include "widgetrenderer.h" +#ifdef Q_WS_X11 #include "x11renderer.h" +#endif #include "artssink.h" #include "pulsesupport.h" @@ -264,7 +266,7 @@ AbstractRenderer *DeviceManager::createVideoRenderer(VideoWidget *parent) if (m_videoSinkWidget == "software") { return new WidgetRenderer(parent); } -#ifndef Q_WS_QWS +#ifdef Q_WS_X11 else if (m_videoSinkWidget == "xwindow") { return new X11Renderer(parent); } else { diff --git a/src/3rdparty/phonon/gstreamer/videowidget.cpp b/src/3rdparty/phonon/gstreamer/videowidget.cpp index e1f0ec9..a4c6f79 100644 --- a/src/3rdparty/phonon/gstreamer/videowidget.cpp +++ b/src/3rdparty/phonon/gstreamer/videowidget.cpp @@ -31,7 +31,9 @@ #include "glrenderer.h" #include "widgetrenderer.h" +#ifdef Q_WS_X11 #include "x11renderer.h" +#endif #ifndef QT_NO_PHONON_VIDEO QT_BEGIN_NAMESPACE @@ -116,10 +118,12 @@ void VideoWidget::setupVideoBin() GstPad *videopad = gst_element_get_pad (queue, "sink"); gst_element_add_pad (m_videoBin, gst_ghost_pad_new ("sink", videopad)); gst_object_unref (videopad); +#ifndef Q_WS_QPA QWidget *parentWidget = qobject_cast<QWidget*>(parent()); if (parentWidget) parentWidget->winId(); // Due to some existing issues with alien in 4.4, // we must currently force the creation of a parent widget. +#endif m_isValid = true; //initialization ok, accept input } } diff --git a/src/3rdparty/phonon/gstreamer/x11renderer.h b/src/3rdparty/phonon/gstreamer/x11renderer.h index f7140da..8e2ea19 100644 --- a/src/3rdparty/phonon/gstreamer/x11renderer.h +++ b/src/3rdparty/phonon/gstreamer/x11renderer.h @@ -27,8 +27,6 @@ QT_BEGIN_NAMESPACE -#ifndef Q_WS_QWS - class QString; namespace Phonon @@ -61,8 +59,6 @@ private: } } //namespace Phonon::Gstreamer -#endif // Q_WS_QWS - QT_END_NAMESPACE #endif // Phonon_GSTREAMER_X11RENDERER_H diff --git a/src/3rdparty/phonon/phonon/mediacontroller.cpp b/src/3rdparty/phonon/phonon/mediacontroller.cpp index 59fd5c7..9f651d6 100644 --- a/src/3rdparty/phonon/phonon/mediacontroller.cpp +++ b/src/3rdparty/phonon/phonon/mediacontroller.cpp @@ -216,14 +216,14 @@ void MediaController::setCurrentAudioChannel(const Phonon::AudioChannelDescripti { IFACE; iface->interfaceCall(AddonInterface::AudioChannelInterface, - AddonInterface::setCurrentAudioChannel, QList<QVariant>() << qVariantFromValue(stream)); + AddonInterface::setCurrentAudioChannel, QList<QVariant>() << QVariant::fromValue(stream)); } void MediaController::setCurrentSubtitle(const Phonon::SubtitleDescription &stream) { IFACE; iface->interfaceCall(AddonInterface::SubtitleInterface, - AddonInterface::setCurrentSubtitle, QList<QVariant>() << qVariantFromValue(stream)); + AddonInterface::setCurrentSubtitle, QList<QVariant>() << QVariant::fromValue(stream)); } #undef IFACE diff --git a/src/3rdparty/phonon/phonon/objectdescriptionmodel.h b/src/3rdparty/phonon/phonon/objectdescriptionmodel.h index 8fd622f..d994600 100644 --- a/src/3rdparty/phonon/phonon/objectdescriptionmodel.h +++ b/src/3rdparty/phonon/phonon/objectdescriptionmodel.h @@ -141,10 +141,11 @@ namespace Phonon /* Required to ensure template class vtables are exported on both symbian and existing builds. */ -#if defined(Q_OS_SYMBIAN) && defined(Q_CC_RVCT) +#if (defined(Q_OS_SYMBIAN) && defined(Q_CC_RVCT)) || defined(Q_CC_CLANG) // RVCT compiler (2.2.686) requires the export declaration to be on the class to export vtables // MWC compiler works both ways // GCCE compiler is unknown (it can't compile QtCore yet) +// Clang also requires the export declaration to be on the class to export vtables #define PHONON_TEMPLATE_CLASS_EXPORT PHONON_EXPORT #define PHONON_TEMPLATE_CLASS_MEMBER_EXPORT #else diff --git a/src/3rdparty/phonon/phonon/qsettingsgroup_p.h b/src/3rdparty/phonon/phonon/qsettingsgroup_p.h index f28ecaa..f25b15e 100644 --- a/src/3rdparty/phonon/phonon/qsettingsgroup_p.h +++ b/src/3rdparty/phonon/phonon/qsettingsgroup_p.h @@ -54,7 +54,7 @@ class QSettingsGroup template<typename T> inline T value(const QString &key, const T &def) const { - return qvariant_cast<T>(value(key, qVariantFromValue(def))); + return qvariant_cast<T>(value(key, QVariant::fromValue(def))); } inline QVariant value(const QString &key, const QVariant &def) const @@ -66,7 +66,7 @@ class QSettingsGroup inline void setValue(const QString &key, const T &value) { Q_ASSERT(m_mutableSettings); - m_mutableSettings->setValue(m_group + key, qVariantFromValue(value)); + m_mutableSettings->setValue(m_group + key, QVariant::fromValue(value)); } inline void removeEntry(const QString &key) diff --git a/src/3rdparty/phonon/qt7/videowidget.mm b/src/3rdparty/phonon/qt7/videowidget.mm index 736dcdf..c281e16 100644 --- a/src/3rdparty/phonon/qt7/videowidget.mm +++ b/src/3rdparty/phonon/qt7/videowidget.mm @@ -278,7 +278,7 @@ public: glMatrixMode(GL_PROJECTION); glLoadIdentity(); glViewport(0, 0, GLsizei(w), GLsizei(h)); - gluOrtho2D(0, GLsizei(w), 0, GLsizei(h)); + glOrtho(0, GLsizei(w), 0, GLsizei(h), -1, 1); updateGL(); } diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro index 981dba2..3ccc57f 100644 --- a/src/3rdparty/webkit/WebCore/WebCore.pro +++ b/src/3rdparty/webkit/WebCore/WebCore.pro @@ -56,6 +56,7 @@ TEMPLATE = lib TARGET = QtWebKit contains(QT_CONFIG, embedded):CONFIG += embedded +contains(QT_CONFIG, qpa):CONFIG += embedded CONFIG(standalone_package) { isEmpty(WC_GENERATED_SOURCES_DIR):WC_GENERATED_SOURCES_DIR = $$PWD/generated @@ -2180,11 +2181,11 @@ contains(DEFINES, ENABLE_NETSCAPE_PLUGIN_API=1) { mac { SOURCES += \ - plugins/mac/PluginPackageMac.cpp \ - plugins/mac/PluginViewMac.mm + plugins/mac/PluginPackageMac.cpp OBJECTIVE_SOURCES += \ platform/text/mac/StringImplMac.mm \ - platform/mac/WebCoreNSStringExtras.mm + platform/mac/WebCoreNSStringExtras.mm \ + plugins/mac/PluginViewMac.mm INCLUDEPATH += platform/mac # Note: XP_MACOSX is defined in npapi.h } else { diff --git a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.h b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.h index 40f7e40..0df23a2 100644 --- a/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.h +++ b/src/3rdparty/webkit/WebCore/bindings/js/JSDOMBinding.h @@ -225,7 +225,7 @@ namespace WebCore { { if (!node) return JSC::jsNull(); - if (JSNode* wrapper = getCachedDOMNodeWrapper(exec, node->document(), node)) + if (JSC::JSCell* wrapper = getCachedDOMNodeWrapper(exec, node->document(), node)) return wrapper; return createDOMNodeWrapper<WrapperClass>(exec, globalObject, node); } diff --git a/src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp b/src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp index 2212f58..7f5d37d 100644 --- a/src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp +++ b/src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp @@ -567,7 +567,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type if (qstring.mid(lastSlash + 1).contains(QLatin1Char('i'))) realRe.setCaseSensitivity(Qt::CaseInsensitive); - ret = qVariantFromValue(realRe); + ret = QVariant::fromValue(realRe); dist = 0; } else { qConvDebug() << "couldn't parse a JS regexp"; @@ -578,7 +578,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type QRegExp re(qstring); if (re.isValid()) { - ret = qVariantFromValue(re); + ret = QVariant::fromValue(re); dist = 10; } } @@ -590,7 +590,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type if (qtinst) { if (qtinst->getObject()) { qConvDebug() << "found instance, with object:" << (void*) qtinst->getObject(); - ret = qVariantFromValue(qtinst->getObject()); + ret = QVariant::fromValue(qtinst->getObject()); qConvDebug() << ret; dist = 0; } else { @@ -601,7 +601,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type } } else if (type == Null) { QObject* nullobj = 0; - ret = qVariantFromValue(nullobj); + ret = QVariant::fromValue(nullobj); dist = 0; } else { qConvDebug() << "previous type was not an object:" << type; @@ -614,7 +614,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type if (qtinst) { if (qtinst->getObject()) { qConvDebug() << "found instance, with object:" << (void*) qtinst->getObject(); - ret = qVariantFromValue((void *)qtinst->getObject()); + ret = QVariant::fromValue((void *)qtinst->getObject()); qConvDebug() << ret; dist = 0; } else { @@ -624,7 +624,7 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type qConvDebug() << "wasn't a qtinstance"; } } else if (type == Null) { - ret = qVariantFromValue((void*)0); + ret = QVariant::fromValue((void*)0); dist = 0; } else if (type == Number) { // I don't think that converting a double to a pointer is a wise diff --git a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp index 88c7a1c..9de5c08 100644 --- a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp +++ b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp @@ -101,7 +101,7 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) // Make sure we get updates for each frame m_videoWidget->installEventFilter(this); - foreach (QWidget* widget, qFindChildren<QWidget*>(m_videoWidget)) + foreach (QWidget* widget, m_videoWidget->findChildren<QWidget*>()) widget->installEventFilter(this); connect(m_mediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)), diff --git a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp index 5db94a8..5004b67 100644 --- a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp +++ b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp @@ -185,7 +185,7 @@ void MediaPlayerPrivate::load(const String& url) // Don't set the header if there are no cookies. // This prevents a warning from being emitted. if (!cookies.isEmpty()) - request.setHeader(QNetworkRequest::CookieHeader, qVariantFromValue(cookies)); + request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies)); // Set the refferer, but not when requesting insecure content from a secure page QUrl documentUrl = QUrl(QString(document->documentURI())); diff --git a/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp b/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp index e584f97..dcae35f 100644 --- a/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp +++ b/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp @@ -306,7 +306,7 @@ public: } Q_INVOKABLE QObjectList myInvokableWithQObjectListArg(const QObjectList &lst) { m_qtFunctionInvoked = 14; - m_actuals << qVariantFromValue(lst); + m_actuals << QVariant::fromValue(lst); return lst; } Q_INVOKABLE QVariant myInvokableWithVariantArg(const QVariant &v) { @@ -321,38 +321,38 @@ public: } Q_INVOKABLE QList<int> myInvokableWithListOfIntArg(const QList<int> &lst) { m_qtFunctionInvoked = 17; - m_actuals << qVariantFromValue(lst); + m_actuals << QVariant::fromValue(lst); return lst; } Q_INVOKABLE QObject* myInvokableWithQObjectStarArg(QObject* obj) { m_qtFunctionInvoked = 18; - m_actuals << qVariantFromValue(obj); + m_actuals << QVariant::fromValue(obj); return obj; } Q_INVOKABLE QBrush myInvokableWithQBrushArg(const QBrush &brush) { m_qtFunctionInvoked = 19; - m_actuals << qVariantFromValue(brush); + m_actuals << QVariant::fromValue(brush); return brush; } Q_INVOKABLE void myInvokableWithBrushStyleArg(Qt::BrushStyle style) { m_qtFunctionInvoked = 43; - m_actuals << qVariantFromValue(style); + m_actuals << QVariant::fromValue(style); } Q_INVOKABLE void myInvokableWithVoidStarArg(void* arg) { m_qtFunctionInvoked = 44; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } Q_INVOKABLE void myInvokableWithAmbiguousArg(int arg) { m_qtFunctionInvoked = 45; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } Q_INVOKABLE void myInvokableWithAmbiguousArg(uint arg) { m_qtFunctionInvoked = 46; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } Q_INVOKABLE void myInvokableWithDefaultArgs(int arg1, const QString &arg2 = "") { m_qtFunctionInvoked = 47; - m_actuals << qVariantFromValue(arg1) << qVariantFromValue(arg2); + m_actuals << QVariant::fromValue(arg1) << qVariantFromValue(arg2); } Q_INVOKABLE QObject& myInvokableReturningRef() { m_qtFunctionInvoked = 48; @@ -364,11 +364,11 @@ public: } Q_INVOKABLE void myInvokableWithPointArg(const QPoint &arg) { const_cast<MyQObject*>(this)->m_qtFunctionInvoked = 50; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } Q_INVOKABLE void myInvokableWithPointArg(const QPointF &arg) { const_cast<MyQObject*>(this)->m_qtFunctionInvoked = 51; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } Q_INVOKABLE void myInvokableWithBoolArg(bool arg) { m_qtFunctionInvoked = 52; @@ -416,7 +416,7 @@ public Q_SLOTS: } void myOverloadedSlot(QObject* arg) { m_qtFunctionInvoked = 41; - m_actuals << qVariantFromValue(arg); + m_actuals << QVariant::fromValue(arg); } void myOverloadedSlot(bool arg) { m_qtFunctionInvoked = 25; @@ -818,7 +818,7 @@ void tst_QWebFrame::getSetStaticProperty() QCOMPARE(evalJS("myObject.variantProperty === 'bar'"), sTrue); m_myObject->setVariantProperty(42); QCOMPARE(evalJS("myObject.variantProperty === 42"), sTrue); - m_myObject->setVariantProperty(qVariantFromValue(QBrush())); + m_myObject->setVariantProperty(QVariant::fromValue(QBrush())); //XFAIL // QCOMPARE(evalJS("typeof myObject.variantProperty"), sVariant); @@ -1240,7 +1240,7 @@ void tst_QWebFrame::callQtInvokable() /* XFAIL - variant support m_myObject->resetQtFunctionInvoked(); { - m_myObject->setVariantProperty(qVariantFromValue(QBrush())); + m_myObject->setVariantProperty(QVariant::fromValue(QBrush())); QVariant ret = evalJS("myObject.myInvokableWithVariantArg(myObject.variantProperty)"); QVERIFY(ret.isVariant()); QCOMPARE(m_myObject->qtFunctionInvoked(), 15); diff --git a/src/activeqt/container/qaxbase.cpp b/src/activeqt/container/qaxbase.cpp index 7692749..806e2b1 100644 --- a/src/activeqt/container/qaxbase.cpp +++ b/src/activeqt/container/qaxbase.cpp @@ -3540,7 +3540,7 @@ int QAxBase::internalProperty(QMetaObject::Call call, int index, void **v) proptype = 0; } else if (t == QVariant::UserType) { qvar = QVariant(qRegisterMetaType<void*>(prop.typeName()), (void**)v[0]); -// qVariantSetValue(qvar, *(void**)v[0], prop.typeName()); +// qvar.setValue(*(void**)v[0], prop.typeName()); } else { proptype = d->metaObject()->propertyType(propname); qvar = QVariant(t, v[0]); @@ -3628,9 +3628,9 @@ int QAxBase::internalInvoke(QMetaObject::Call call, int index, void **v) if (!qvar.isValid()) { if (type == "IDispatch*") - qVariantSetValue(qvar, *(IDispatch**)v[p+1]); + qvar.setValue(*(IDispatch**)v[p+1]); else if (type == "IUnknown*") - qVariantSetValue(qvar, *(IUnknown**)v[p+1]); + qvar.setValue(*(IUnknown**)v[p+1]); else if (type == "QVariant") qvar = *(QVariant*)v[p + 1]; else if (mo->indexOfEnumerator(type) != -1) @@ -4395,15 +4395,15 @@ QVariant QAxBase::asVariant() const QByteArray cn(className()); if (cn == "QAxObject" || cn == "QAxWidget" || cn == "QAxBase") { if (d->dispatch()) - qVariantSetValue(qvar, d->dispatch()); + qvar.setValue(d->dispatch()); else if (d->ptr) - qVariantSetValue(qvar, d->ptr); + qvar.setValue(d->ptr); } else { cn = cn.mid(cn.lastIndexOf(':') + 1); QObject *object = qObject(); if (QMetaType::type(cn)) qvar = QVariant(qRegisterMetaType<QObject*>(cn + '*'), &object); -// qVariantSetValue(qvar, qObject(), cn + '*'); +// qvar.setValue(qObject(), cn + '*'); } return qvar; diff --git a/src/activeqt/container/qaxwidget.cpp b/src/activeqt/container/qaxwidget.cpp index c2108ba..15d586b 100644 --- a/src/activeqt/container/qaxwidget.cpp +++ b/src/activeqt/container/qaxwidget.cpp @@ -1163,7 +1163,7 @@ HRESULT WINAPI QAxClientSite::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPW AX_DEBUG(QAxClientSite::InsertMenus); QMenuBar *mb = menuBar; if (!mb) - mb = qFindChild<QMenuBar*>(widget->window()); + mb = widget->window()->findChild<QMenuBar*>(); if (!mb) return E_NOTIMPL; menuBar = mb; @@ -1309,7 +1309,7 @@ HRESULT WINAPI QAxClientSite::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND m_menuOwner = hwndActiveObject; QMenuBar *mb = menuBar; if (!mb) - mb = qFindChild<QMenuBar*>(widget->window()); + mb = widget->window()->findChild<QMenuBar*>(); if (!mb) return E_NOTIMPL; menuBar = mb; diff --git a/src/activeqt/control/qaxserver.cpp b/src/activeqt/control/qaxserver.cpp index 7728e50..2512f05 100644 --- a/src/activeqt/control/qaxserver.cpp +++ b/src/activeqt/control/qaxserver.cpp @@ -285,7 +285,7 @@ HRESULT UpdateRegistry(BOOL bRegister) |OLEMISC_RECOMPOSEONRESIZE; if (!control) olemisc |= OLEMISC_INVISIBLEATRUNTIME; - else if (qFindChild<QMenuBar*>(object) && !qax_disable_inplaceframe) + else if (object->findChild<QMenuBar*>() && !qax_disable_inplaceframe) olemisc |= OLEMISC_WANTSTOMENUMERGE; settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/."), className + QLatin1String(" Class")); diff --git a/src/activeqt/control/qaxserverbase.cpp b/src/activeqt/control/qaxserverbase.cpp index d8e7ea3..d833228 100644 --- a/src/activeqt/control/qaxserverbase.cpp +++ b/src/activeqt/control/qaxserverbase.cpp @@ -1313,7 +1313,7 @@ bool QAxServerBase::internalCreate() // install an event filter for stock events if (isWidget) { qt.object->installEventFilter(this); - const QList<QWidget*> children = qFindChildren<QWidget*>(qt.object); + const QList<QWidget*> children = qt.object->findChildren<QWidget*>(); QList<QWidget*>::ConstIterator it = children.constBegin(); while (it != children.constEnd()) { (*it)->installEventFilter(this); @@ -2047,10 +2047,10 @@ int QAxServerBase::qt_metacall(QMetaObject::Call call, int index, void **argv) if (vt == QVariant::UserType) { if (ptype.endsWith('*')) { variant = QVariant(QMetaType::type(ptype), (void**)argv[p+1]); - // qVariantSetValue(variant, *(void**)(argv[p + 1]), ptype); + // variant.setValue(*(void**)(argv[p + 1]), ptype); } else { variant = QVariant(QMetaType::type(ptype), argv[p+1]); - // qVariantSetValue(variant, argv[p + 1], ptype); + // variant.setValue(argv[p + 1], ptype); } } else { variant = QVariant(vt, argv[p + 1]); @@ -2537,7 +2537,7 @@ HRESULT WINAPI QAxServerBase::Invoke(DISPID dispidMember, REFIID riid, if (!type.isEmpty() && pvarResult) { if (!varp[0].isValid() && type != "QVariant") varp[0] = QVariant(QMetaType::type(type), argv_pointer); -// qVariantSetValue(varp[0], argv_pointer[0], type); +// varp[0].setValue(argv_pointer[0], type); ok = QVariantToVARIANT(varp[0], *pvarResult, type); } } @@ -3325,7 +3325,7 @@ HRESULT WINAPI QAxServerBase::OnAmbientPropertyChange(DISPID dispID) break; { QVariant qvar = VARIANTToQVariant(var, "QFont", QVariant::Font); - QFont qfont = qVariantValue<QFont>(qvar); + QFont qfont = qvariant_cast<QFont>(qvar); qt.widget->setFont(qfont); } break; @@ -3818,7 +3818,7 @@ HRESULT QAxServerBase::internalActivate() // Gone active by now, take care of UIACTIVATE canTakeFocus = qt.widget->focusPolicy() != Qt::NoFocus && !inDesignMode; if (!canTakeFocus && !inDesignMode) { - QList<QWidget*> widgets = qFindChildren<QWidget*>(qt.widget); + QList<QWidget*> widgets = qt.widget->findChildren<QWidget*>(); for (int w = 0; w < widgets.count(); ++w) { QWidget *widget = widgets[w]; canTakeFocus = widget->focusPolicy() != Qt::NoFocus; @@ -3844,13 +3844,13 @@ HRESULT QAxServerBase::internalActivate() if (m_spInPlaceFrame) { hr = m_spInPlaceFrame->SetActiveObject(this, QStringToBSTR(class_name)); if (!FAILED(hr)) { - menuBar = (qt.widget && !qax_disable_inplaceframe) ? qFindChild<QMenuBar*>(qt.widget) : 0; + menuBar = (qt.widget && !qax_disable_inplaceframe) ? qt.widget->findChild<QMenuBar*>() : 0; if (menuBar && !menuBar->isVisible()) { createMenu(menuBar); menuBar->hide(); menuBar->installEventFilter(this); } - statusBar = qt.widget ? qFindChild<QStatusBar*>(qt.widget) : 0; + statusBar = qt.widget ? qt.widget->findChild<QStatusBar*>() : 0; if (statusBar && !statusBar->isVisible()) { const int index = statusBar->metaObject()->indexOfSignal("messageChanged(QString)"); QMetaObject::connect(statusBar, index, this, -1); diff --git a/src/activeqt/shared/qaxtypes.cpp b/src/activeqt/shared/qaxtypes.cpp index 88f408e..4a38544 100644 --- a/src/activeqt/shared/qaxtypes.cpp +++ b/src/activeqt/shared/qaxtypes.cpp @@ -954,20 +954,20 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint break; case VT_I4: if (type == QVariant::Color || (!type && typeName == "QColor")) - var = qVariantFromValue(OLEColorToQColor(arg.lVal)); + var = QVariant::fromValue(OLEColorToQColor(arg.lVal)); #ifndef QT_NO_CURSOR else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*"))) - var = qVariantFromValue(QCursor(static_cast<Qt::CursorShape>(arg.lVal))); + var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(arg.lVal))); #endif else var = (int)arg.lVal; break; case VT_I4|VT_BYREF: if (type == QVariant::Color || (!type && typeName == "QColor")) - var = qVariantFromValue(OLEColorToQColor((int)*arg.plVal)); + var = QVariant::fromValue(OLEColorToQColor((int)*arg.plVal)); #ifndef QT_NO_CURSOR else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*"))) - var = qVariantFromValue(QCursor(static_cast<Qt::CursorShape>(*arg.plVal))); + var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(*arg.plVal))); #endif else var = (int)*arg.plVal; @@ -992,20 +992,20 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint break; case VT_UI4: if (type == QVariant::Color || (!type && typeName == "QColor")) - var = qVariantFromValue(OLEColorToQColor(arg.ulVal)); + var = QVariant::fromValue(OLEColorToQColor(arg.ulVal)); #ifndef QT_NO_CURSOR else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*"))) - var = qVariantFromValue(QCursor(static_cast<Qt::CursorShape>(arg.ulVal))); + var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(arg.ulVal))); #endif else var = (int)arg.ulVal; break; case VT_UI4|VT_BYREF: if (type == QVariant::Color || (!type && typeName == "QColor")) - var = qVariantFromValue(OLEColorToQColor((uint)*arg.pulVal)); + var = QVariant::fromValue(OLEColorToQColor((uint)*arg.pulVal)); #ifndef QT_NO_CURSOR else if (type == QVariant::Cursor || (!type && (typeName == "QCursor" || typeName == "QCursor*"))) - var = qVariantFromValue(QCursor(static_cast<Qt::CursorShape>(*arg.pulVal))); + var = QVariant::fromValue(QCursor(static_cast<Qt::CursorShape>(*arg.pulVal))); #endif else var = (int)*arg.pulVal; @@ -1084,20 +1084,20 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint if (disp) disp->QueryInterface(IID_IFont, (void**)&ifont); if (ifont) { - var = qVariantFromValue(IFontToQFont(ifont)); + var = QVariant::fromValue(IFontToQFont(ifont)); ifont->Release(); } else { - var = qVariantFromValue(QFont()); + var = QVariant::fromValue(QFont()); } } else if (type == QVariant::Pixmap || (!type && (typeName == "QPixmap" || typeName == "QPixmap*"))) { IPicture *ipic = 0; if (disp) disp->QueryInterface(IID_IPicture, (void**)&ipic); if (ipic) { - var = qVariantFromValue(IPictureToQPixmap(ipic)); + var = QVariant::fromValue(IPictureToQPixmap(ipic)); ipic->Release(); } else { - var = qVariantFromValue(QPixmap()); + var = QVariant::fromValue(QPixmap()); } } else { #ifdef QAX_SERVER @@ -1118,7 +1118,7 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint #ifndef QAX_SERVER if (typeName == "QVariant") { QAxObject *object = new QAxObject(disp); - var = qVariantFromValue<QAxObject*>(object); + var = QVariant::fromValue<QAxObject*>(object); } else if (typeName != "IDispatch*" && QMetaType::type(typeName)) { QByteArray typeNameStr = QByteArray(typeName); int pIndex = typeName.lastIndexOf('*'); @@ -1145,7 +1145,7 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint unkn = *arg.ppunkVal; else unkn = arg.punkVal; - qVariantSetValue(var, unkn); + var.setValue(unkn); } break; case VT_ARRAY|VT_VARIANT: diff --git a/src/corelib/arch/arch.pri b/src/corelib/arch/arch.pri index 57bc80a..971069f 100644 --- a/src/corelib/arch/arch.pri +++ b/src/corelib/arch/arch.pri @@ -21,7 +21,9 @@ vxworks:HEADERS += arch/qatomic_vxworks.h arch/qatomic_generic.h \ arch/qatomic_powerpc.h \ arch/qatomic_arm.h \ + arch/qatomic_armv5.h \ arch/qatomic_armv6.h \ + arch/qatomic_armv7.h \ arch/qatomic_i386.h \ arch/qatomic_mips.h \ arch/qatomic_s390.h \ diff --git a/src/corelib/arch/armv6/arch.pri b/src/corelib/arch/armv6/arch.pri deleted file mode 100644 index fd0cce1..0000000 --- a/src/corelib/arch/armv6/arch.pri +++ /dev/null @@ -1,3 +0,0 @@ -# -# ARMv6 -# diff --git a/src/corelib/arch/qatomic_arch.h b/src/corelib/arch/qatomic_arch.h index 00b288b..5106d29 100644 --- a/src/corelib/arch/qatomic_arch.h +++ b/src/corelib/arch/qatomic_arch.h @@ -88,6 +88,8 @@ QT_BEGIN_HEADER # include "QtCore/qatomic_sh.h" #elif defined(QT_ARCH_SH4A) # include "QtCore/qatomic_sh4a.h" +#elif defined(QT_ARCH_NACL) +# include "QtCore/qatomic_generic.h" #else # error "Qt has not been ported to this architecture" #endif diff --git a/src/corelib/arch/qatomic_arm.h b/src/corelib/arch/qatomic_arm.h index bca3375..1c1c8a5 100644 --- a/src/corelib/arch/qatomic_arm.h +++ b/src/corelib/arch/qatomic_arm.h @@ -44,387 +44,32 @@ QT_BEGIN_HEADER -QT_BEGIN_NAMESPACE - -#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE - -inline bool QBasicAtomicInt::isReferenceCountingNative() -{ return false; } -inline bool QBasicAtomicInt::isReferenceCountingWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE - -inline bool QBasicAtomicInt::isTestAndSetNative() -{ return false; } -inline bool QBasicAtomicInt::isTestAndSetWaitFree() -{ return false; } - -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE - -inline bool QBasicAtomicInt::isFetchAndStoreNative() -{ return true; } -inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() -{ return true; } - -#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE - -inline bool QBasicAtomicInt::isFetchAndAddNative() -{ return false; } -inline bool QBasicAtomicInt::isFetchAndAddWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() -{ return false; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() -{ return false; } - -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() -{ return true; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() -{ return true; } - -#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() -{ return false; } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() -{ return false; } - -#ifndef QT_NO_ARM_EABI - -// kernel places a restartable cmpxchg implementation at a fixed address -extern "C" typedef int (qt_atomic_eabi_cmpxchg_int_t)(int oldval, int newval, volatile int *ptr); -extern "C" typedef int (qt_atomic_eabi_cmpxchg_ptr_t)(const void *oldval, const void *newval, volatile void *ptr); -#define qt_atomic_eabi_cmpxchg_int (*reinterpret_cast<qt_atomic_eabi_cmpxchg_int_t *>(0xffff0fc0)) -#define qt_atomic_eabi_cmpxchg_ptr (*reinterpret_cast<qt_atomic_eabi_cmpxchg_ptr_t *>(0xffff0fc0)) - -#else - -extern Q_CORE_EXPORT char q_atomic_lock; -Q_CORE_EXPORT void qt_atomic_yield(int *); - -#ifdef Q_CC_RVCT - -Q_CORE_EXPORT __asm char q_atomic_swp(volatile char *ptr, char newval); - -#else - -inline char q_atomic_swp(volatile char *ptr, char newval) -{ - register char ret; - asm volatile("swpb %0,%2,[%3]" - : "=&r"(ret), "=m" (*ptr) - : "r"(newval), "r"(ptr) - : "cc", "memory"); - return ret; -} - -#endif // Q_CC_RVCT - -#endif // QT_NO_ARM_EABI - -// Reference counting - -inline bool QBasicAtomicInt::ref() -{ -#ifndef QT_NO_ARM_EABI - register int originalValue; - register int newValue; - do { - originalValue = _q_value; - newValue = originalValue + 1; - } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0); - return newValue != 0; -#else - int count = 0; - while (q_atomic_swp(&q_atomic_lock, ~0) != 0) - qt_atomic_yield(&count); - int originalValue = _q_value++; - q_atomic_swp(&q_atomic_lock, 0); - return originalValue != -1; -#endif -} - -inline bool QBasicAtomicInt::deref() -{ -#ifndef QT_NO_ARM_EABI - register int originalValue; - register int newValue; - do { - originalValue = _q_value; - newValue = originalValue - 1; - } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0); - return newValue != 0; -#else - int count = 0; - while (q_atomic_swp(&q_atomic_lock, ~0) != 0) - qt_atomic_yield(&count); - int originalValue = _q_value--; - q_atomic_swp(&q_atomic_lock, 0); - return originalValue != 1; -#endif -} - -// Test and set for integers - -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) -{ -#ifndef QT_NO_ARM_EABI - register int originalValue; - do { - originalValue = _q_value; - if (originalValue != expectedValue) - return false; - } while (qt_atomic_eabi_cmpxchg_int(expectedValue, newValue, &_q_value) != 0); - return true; -#else - bool returnValue = false; - int count = 0; - while (q_atomic_swp(&q_atomic_lock, ~0) != 0) - qt_atomic_yield(&count); - if (_q_value == expectedValue) { - _q_value = newValue; - returnValue = true; - } - q_atomic_swp(&q_atomic_lock, 0); - return returnValue; -#endif -} - -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 - -#ifndef Q_CC_RVCT - -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) -{ - int originalValue; - asm volatile("swp %0,%2,[%3]" - : "=&r"(originalValue), "=m" (_q_value) - : "r"(newValue), "r"(&_q_value) - : "cc", "memory"); - return originalValue; -} - -#endif - -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) -{ -#ifndef QT_NO_ARM_EABI - register int originalValue; - register int newValue; - do { - originalValue = _q_value; - newValue = originalValue + valueToAdd; - } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0); - return originalValue; -#else - int count = 0; - while (q_atomic_swp(&q_atomic_lock, ~0) != 0) - qt_atomic_yield(&count); - int originalValue = _q_value; - _q_value += valueToAdd; - q_atomic_swp(&q_atomic_lock, 0); - return originalValue; -#endif -} - -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) -{ -#ifndef QT_NO_ARM_EABI - register T *originalValue; - do { - originalValue = _q_value; - if (originalValue != expectedValue) - return false; - } while (qt_atomic_eabi_cmpxchg_ptr(expectedValue, newValue, &_q_value) != 0); - return true; +#if defined(__ARM_ARCH_7__) \ + || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) \ + || defined(__ARM_ARCH_7M__) +# define QT_ARCH_ARMV7 +QT_BEGIN_INCLUDE_HEADER +# include "QtCore/qatomic_armv7.h" +QT_END_INCLUDE_HEADER +#elif defined(__ARM_ARCH_6__) \ + || defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6T2__) \ + || defined(__ARM_ARCH_6Z__) \ + || defined(__ARM_ARCH_6K__) \ + || defined(__ARM_ARCH_6ZK__) \ + || defined(__ARM_ARCH_6M__) \ + || (__TARGET_ARCH_ARM-0 >= 6) +# define QT_ARCH_ARMV6 +QT_BEGIN_INCLUDE_HEADER +# include "QtCore/qatomic_armv6.h" +QT_END_INCLUDE_HEADER #else - bool returnValue = false; - int count = 0; - while (q_atomic_swp(&q_atomic_lock, ~0) != 0) - qt_atomic_yield(&count); - if (_q_value == expectedValue) { - _q_value = newValue; - returnValue = true; - } - q_atomic_swp(&q_atomic_lock, 0); - return returnValue; +# define QT_ARCH_ARMV5 +QT_BEGIN_INCLUDE_HEADER +# include "QtCore/qatomic_armv5.h" +QT_END_INCLUDE_HEADER #endif -} - -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 - -#ifdef Q_CC_RVCT - -template <typename T> -__asm T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) -{ - add r2, pc, #0 - bx r2 - arm - swp r2,r1,[r0] - mov r0, r2 - bx lr - thumb -} - -#else - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) -{ - T *originalValue; - asm volatile("swp %0,%2,[%3]" - : "=&r"(originalValue), "=m" (_q_value) - : "r"(newValue), "r"(&_q_value) - : "cc", "memory"); - return originalValue; -} - -#endif // Q_CC_RVCT - -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) -{ -#ifndef QT_NO_ARM_EABI - register T *originalValue; - register T *newValue; - do { - originalValue = _q_value; - newValue = originalValue + valueToAdd; - } while (qt_atomic_eabi_cmpxchg_ptr(originalValue, newValue, &_q_value) != 0); - return originalValue; -#else - int count = 0; - while (q_atomic_swp(&q_atomic_lock, ~0) != 0) - qt_atomic_yield(&count); - T *originalValue = (_q_value); - _q_value += valueToAdd; - q_atomic_swp(&q_atomic_lock, 0); - return originalValue; -#endif -} - -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 QT_END_HEADER diff --git a/src/corelib/arch/qatomic_armv5.h b/src/corelib/arch/qatomic_armv5.h new file mode 100644 index 0000000..f0f2f9a --- /dev/null +++ b/src/corelib/arch/qatomic_armv5.h @@ -0,0 +1,431 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QATOMIC_ARMV5_H +#define QATOMIC_ARMV5_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return false; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return false; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return false; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +#ifndef QT_NO_ARM_EABI + +// kernel places a restartable cmpxchg implementation at a fixed address +extern "C" typedef int (qt_atomic_eabi_cmpxchg_int_t)(int oldval, int newval, volatile int *ptr); +extern "C" typedef int (qt_atomic_eabi_cmpxchg_ptr_t)(const void *oldval, void *newval, volatile void *ptr); +#define qt_atomic_eabi_cmpxchg_int (*reinterpret_cast<qt_atomic_eabi_cmpxchg_int_t *>(0xffff0fc0)) +#define qt_atomic_eabi_cmpxchg_ptr (*reinterpret_cast<qt_atomic_eabi_cmpxchg_ptr_t *>(0xffff0fc0)) + +#else + +extern Q_CORE_EXPORT char q_atomic_lock; +Q_CORE_EXPORT void qt_atomic_yield(int *); + +#ifdef Q_CC_RVCT + +Q_CORE_EXPORT __asm char q_atomic_swp(volatile char *ptr, char newval); + +#else + +inline char q_atomic_swp(volatile char *ptr, char newval) +{ + register char ret; + asm volatile("swpb %0,%2,[%3]" + : "=&r"(ret), "=m" (*ptr) + : "r"(newval), "r"(ptr) + : "cc", "memory"); + return ret; +} + +#endif // Q_CC_RVCT + +#endif // QT_NO_ARM_EABI + +// Reference counting + +inline bool QBasicAtomicInt::ref() +{ +#ifndef QT_NO_ARM_EABI + register int originalValue; + register int newValue; + do { + originalValue = _q_value; + newValue = originalValue + 1; + } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0); + return newValue != 0; +#else + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + int originalValue = _q_value++; + q_atomic_swp(&q_atomic_lock, 0); + return originalValue != -1; +#endif +} + +inline bool QBasicAtomicInt::deref() +{ +#ifndef QT_NO_ARM_EABI + register int originalValue; + register int newValue; + do { + originalValue = _q_value; + newValue = originalValue - 1; + } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0); + return newValue != 0; +#else + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + int originalValue = _q_value--; + q_atomic_swp(&q_atomic_lock, 0); + return originalValue != 1; +#endif +} + +// Test and set for integers + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ +#ifndef QT_NO_ARM_EABI + register int originalValue; + do { + originalValue = _q_value; + if (originalValue != expectedValue) + return false; + } while (qt_atomic_eabi_cmpxchg_int(expectedValue, newValue, &_q_value) != 0); + return true; +#else + bool returnValue = false; + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + if (_q_value == expectedValue) { + _q_value = newValue; + returnValue = true; + } + q_atomic_swp(&q_atomic_lock, 0); + return returnValue; +#endif +} + +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 + +#ifndef Q_CC_RVCT + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + int originalValue; + asm volatile("swp %0,%2,[%3]" + : "=&r"(originalValue), "=m" (_q_value) + : "r"(newValue), "r"(&_q_value) + : "cc", "memory"); + return originalValue; +} + +#endif + +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) +{ +#ifndef QT_NO_ARM_EABI + register int originalValue; + register int newValue; + do { + originalValue = _q_value; + newValue = originalValue + valueToAdd; + } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0); + return originalValue; +#else + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + int originalValue = _q_value; + _q_value += valueToAdd; + q_atomic_swp(&q_atomic_lock, 0); + return originalValue; +#endif +} + +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) +{ +#ifndef QT_NO_ARM_EABI + register T *originalValue; + do { + originalValue = _q_value; + if (originalValue != expectedValue) + return false; + } while (qt_atomic_eabi_cmpxchg_ptr(expectedValue, newValue, &_q_value) != 0); + return true; +#else + bool returnValue = false; + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + if (_q_value == expectedValue) { + _q_value = newValue; + returnValue = true; + } + q_atomic_swp(&q_atomic_lock, 0); + return returnValue; +#endif +} + +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 + +#ifdef Q_CC_RVCT + +template <typename T> +__asm T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + add r2, pc, #0 + bx r2 + arm + swp r2,r1,[r0] + mov r0, r2 + bx lr + thumb +} + +#else + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + T *originalValue; + asm volatile("swp %0,%2,[%3]" + : "=&r"(originalValue), "=m" (_q_value) + : "r"(newValue), "r"(&_q_value) + : "cc", "memory"); + return originalValue; +} + +#endif // Q_CC_RVCT + +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) +{ +#ifndef QT_NO_ARM_EABI + register T *originalValue; + register T *newValue; + do { + originalValue = _q_value; + newValue = originalValue + valueToAdd; + } while (qt_atomic_eabi_cmpxchg_ptr(originalValue, newValue, &_q_value) != 0); + return originalValue; +#else + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + T *originalValue = (_q_value); + _q_value += valueToAdd; + q_atomic_swp(&q_atomic_lock, 0); + return originalValue; +#endif +} + +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 + +QT_END_HEADER + +#endif // QATOMIC_ARMV5_H diff --git a/src/corelib/arch/qatomic_armv6.h b/src/corelib/arch/qatomic_armv6.h index 38b7069..1aa3b88 100644 --- a/src/corelib/arch/qatomic_armv6.h +++ b/src/corelib/arch/qatomic_armv6.h @@ -45,6 +45,7 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE + #define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE inline bool QBasicAtomicInt::isReferenceCountingNative() @@ -102,6 +103,13 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() #ifndef Q_CC_RVCT +#ifndef Q_DATA_MEMORY_BARRIER +# define Q_DATA_MEMORY_BARRIER asm volatile("":::"memory") +#endif +#ifndef Q_COMPILER_MEMORY_BARRIER +# define Q_COMPILER_MEMORY_BARRIER asm volatile("":::"memory") +#endif + inline bool QBasicAtomicInt::ref() { register int newValue; @@ -138,7 +146,7 @@ inline bool QBasicAtomicInt::deref() return newValue != 0; } -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) { register int result; asm volatile("0:\n" @@ -152,11 +160,11 @@ inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) : [expectedValue] "r" (expectedValue), [newValue] "r" (newValue), [_q_value] "r" (&_q_value) - : "cc", "memory"); + : "cc"); return result == 0; } -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) { register int originalValue; register int result; @@ -170,11 +178,11 @@ inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) "+m" (_q_value) : [newValue] "r" (newValue), [_q_value] "r" (&_q_value) - : "cc", "memory"); + : "cc"); return originalValue; } -inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) { register int originalValue; register int newValue; @@ -191,12 +199,12 @@ inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) "+m" (_q_value) : [valueToAdd] "r" (valueToAdd), [_q_value] "r" (&_q_value) - : "cc", "memory"); + : "cc"); return originalValue; } template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) { register T *result; asm volatile("0:\n" @@ -210,12 +218,12 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValu : [expectedValue] "r" (expectedValue), [newValue] "r" (newValue), [_q_value] "r" (&_q_value) - : "cc", "memory"); + : "cc"); return result == 0; } template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) { register T *originalValue; register int result; @@ -229,12 +237,12 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) "+m" (_q_value) : [newValue] "r" (newValue), [_q_value] "r" (&_q_value) - : "cc", "memory"); + : "cc"); return originalValue; } template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) { register T *originalValue; register T *newValue; @@ -251,7 +259,7 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueTo "+m" (_q_value) : [valueToAdd] "r" (valueToAdd * sizeof(T)), [_q_value] "r" (&_q_value) - : "cc", "memory"); + : "cc"); return originalValue; } @@ -263,9 +271,18 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueTo // 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 +#if __TARGET_ARCH_THUMB-0 < 4 +// save our pragma state and switch to ARM mode (unless using Thumb2) +# pragma push +# pragma arm +#endif + +#ifndef Q_DATA_MEMORY_BARRIER +# define Q_DATA_MEMORY_BARRIER __schedule_barrier() +#endif +#ifndef Q_COMPILER_MEMORY_BARRIER +# define Q_COMPILER_MEMORY_BARRIER __schedule_barrier() +#endif inline bool QBasicAtomicInt::ref() { @@ -297,7 +314,7 @@ inline bool QBasicAtomicInt::deref() return newValue != 0; } -inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) { register int result; retry: @@ -311,7 +328,7 @@ inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) return result == 0; } -inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) { register int originalValue; register int result; @@ -325,7 +342,7 @@ inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) return originalValue; } -inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) { register int originalValue; register int newValue; @@ -342,7 +359,7 @@ inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) } template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) { register T *result; retry: @@ -357,7 +374,7 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValu } template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) { register T *originalValue; register int result; @@ -372,7 +389,7 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) } template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) { register T *originalValue; register T *newValue; @@ -388,111 +405,153 @@ Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueTo return originalValue; } -// go back to the previous pragma state (probably Thumb mode) -#pragma pop +#if __TARGET_ARCH_THUMB-0 < 4 +# pragma pop #endif -// common code +#endif -inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) -{ - return testAndSetOrdered(expectedValue, newValue); -} +// common code inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) { - return testAndSetOrdered(expectedValue, newValue); + bool returnValue = testAndSetRelaxed(expectedValue, newValue); + Q_DATA_MEMORY_BARRIER; + return returnValue; } inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) { - return testAndSetOrdered(expectedValue, newValue); + Q_DATA_MEMORY_BARRIER; + return testAndSetRelaxed(expectedValue, newValue); } -inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) { - return fetchAndStoreOrdered(newValue); + Q_DATA_MEMORY_BARRIER; + bool returnValue = testAndSetRelaxed(expectedValue, newValue); + Q_COMPILER_MEMORY_BARRIER; + return returnValue; } inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) { - return fetchAndStoreOrdered(newValue); + int returnValue = fetchAndStoreRelaxed(newValue); + Q_DATA_MEMORY_BARRIER; + return returnValue; } inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) { - return fetchAndStoreOrdered(newValue); + Q_DATA_MEMORY_BARRIER; + return fetchAndStoreRelaxed(newValue); } -inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) { - return fetchAndAddOrdered(valueToAdd); + Q_DATA_MEMORY_BARRIER; + int returnValue = fetchAndStoreRelaxed(newValue); + Q_COMPILER_MEMORY_BARRIER; + return returnValue; } + inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) { - return fetchAndAddOrdered(valueToAdd); + int returnValue = fetchAndAddRelaxed(valueToAdd); + Q_DATA_MEMORY_BARRIER; + return returnValue; } inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) { - return fetchAndAddOrdered(valueToAdd); + Q_DATA_MEMORY_BARRIER; + return fetchAndAddRelaxed(valueToAdd); } -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) { - return testAndSetOrdered(expectedValue, newValue); + Q_DATA_MEMORY_BARRIER; + int returnValue = fetchAndAddRelaxed(valueToAdd); + Q_COMPILER_MEMORY_BARRIER; + return returnValue; } template <typename T> Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) { - return testAndSetOrdered(expectedValue, newValue); + bool returnValue = testAndSetRelaxed(expectedValue, newValue); + Q_DATA_MEMORY_BARRIER; + return returnValue; } template <typename T> Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) { - return testAndSetOrdered(expectedValue, newValue); + Q_DATA_MEMORY_BARRIER; + return testAndSetRelaxed(expectedValue, newValue); } template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) { - return fetchAndStoreOrdered(newValue); + Q_DATA_MEMORY_BARRIER; + bool returnValue = testAndSetAcquire(expectedValue, newValue); + Q_COMPILER_MEMORY_BARRIER; + return returnValue; } template <typename T> Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) { - return fetchAndStoreOrdered(newValue); + T *returnValue = fetchAndStoreRelaxed(newValue); + Q_DATA_MEMORY_BARRIER; + return returnValue; } template <typename T> Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) { - return fetchAndStoreOrdered(newValue); + Q_DATA_MEMORY_BARRIER; + return fetchAndStoreRelaxed(newValue); } template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) { - return fetchAndAddOrdered(valueToAdd); + Q_DATA_MEMORY_BARRIER; + T *returnValue = fetchAndStoreRelaxed(newValue); + Q_COMPILER_MEMORY_BARRIER; + return returnValue; } template <typename T> Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) { - return fetchAndAddOrdered(valueToAdd); + T *returnValue = fetchAndAddRelaxed(valueToAdd); + Q_DATA_MEMORY_BARRIER; + return returnValue; } template <typename T> Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) { - return fetchAndAddOrdered(valueToAdd); + Q_DATA_MEMORY_BARRIER; + return fetchAndAddRelaxed(valueToAdd); } +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + Q_DATA_MEMORY_BARRIER; + T *returnValue = fetchAndAddRelaxed(valueToAdd); + Q_COMPILER_MEMORY_BARRIER; + return returnValue; +} + +#undef Q_DATA_MEMORY_BARRIER +#undef Q_COMPILER_MEMORY_BARRIER + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/arch/qatomic_armv7.h b/src/corelib/arch/qatomic_armv7.h new file mode 100644 index 0000000..a95c4ea --- /dev/null +++ b/src/corelib/arch/qatomic_armv7.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QATOMIC_ARMV7_H +#define QATOMIC_ARMV7_H + +QT_BEGIN_HEADER + +// use the DMB instruction when compiling for ARMv7, ... +#ifndef Q_CC_RCVT +# define Q_DATA_MEMORY_BARRIER asm volatile("dmb\n":::"memory") +#else +# define Q_DATA_MEMORY_BARRIER do{__asm { dmb } __schedule_barrier();}while(0) +#endif + +// ... but the implementation is otherwise identical to that for ARMv6 +QT_BEGIN_INCLUDE_HEADER +#include "QtCore/qatomic_armv6.h" +QT_END_INCLUDE_HEADER + +QT_END_HEADER + +#endif // QATOMIC_ARMV7_H diff --git a/src/corelib/arch/symbian/arch.pri b/src/corelib/arch/symbian/arch.pri index 70daee3..2e2a9b6 100644 --- a/src/corelib/arch/symbian/arch.pri +++ b/src/corelib/arch/symbian/arch.pri @@ -2,7 +2,7 @@ # Symbian architecture # SOURCES += $$QT_ARCH_CPP/qatomic_symbian.cpp \ - $$QT_ARCH_CPP/../armv6/qatomic_generic_armv6.cpp \ + $$QT_ARCH_CPP/qatomic_generic_armv6.cpp \ $$QT_ARCH_CPP/heap_hybrid.cpp \ $$QT_ARCH_CPP/debugfunction.cpp \ $$QT_ARCH_CPP/qt_heapsetup_symbian.cpp diff --git a/src/corelib/arch/armv6/qatomic_generic_armv6.cpp b/src/corelib/arch/symbian/qatomic_generic_armv6.cpp index 444d3d3..444d3d3 100644 --- a/src/corelib/arch/armv6/qatomic_generic_armv6.cpp +++ b/src/corelib/arch/symbian/qatomic_generic_armv6.cpp diff --git a/src/corelib/concurrent/qfuture.h b/src/corelib/concurrent/qfuture.h index 02ae40a..2856f5e 100644 --- a/src/corelib/concurrent/qfuture.h +++ b/src/corelib/concurrent/qfuture.h @@ -210,7 +210,7 @@ public: bool operator==(const QFuture &other) const { return (d == other.d); } bool operator!=(const QFuture &other) const { return (d != other.d); } -#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(Q_CC_XLC) +#if !defined(Q_CC_XLC) template <typename T> QFuture(const QFuture<T> &other) : d(other.d) diff --git a/src/corelib/concurrent/qfuturewatcher.cpp b/src/corelib/concurrent/qfuturewatcher.cpp index d4573c6..21b0789 100644 --- a/src/corelib/concurrent/qfuturewatcher.cpp +++ b/src/corelib/concurrent/qfuturewatcher.cpp @@ -359,6 +359,15 @@ void QFutureWatcherBase::connectNotify(const char * signal) Q_D(QFutureWatcherBase); if (qstrcmp(signal, SIGNAL(resultReadyAt(int))) == 0) d->resultAtConnected.ref(); +#ifndef QT_NO_DEBUG + if (qstrcmp(signal, SIGNAL(finished())) == 0) { + if (futureInterface().isRunning()) { + //connections should be established before calling stFuture to avoid race. + // (The future could finish before the connection is made.) + qWarning("QFutureWatcher::connect: connecting after calling setFuture() is likely to produce race"); + } + } +#endif } void QFutureWatcherBase::disconnectNotify(const char * signal) diff --git a/src/corelib/concurrent/qtconcurrentcompilertest.h b/src/corelib/concurrent/qtconcurrentcompilertest.h index 982a50c..4fbb3d7 100644 --- a/src/corelib/concurrent/qtconcurrentcompilertest.h +++ b/src/corelib/concurrent/qtconcurrentcompilertest.h @@ -51,12 +51,6 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) -#ifdef Q_CC_MSVC -# if _MSC_VER < 1300 -# define QT_CONURRENT_NONSTANDARD_COMPILER -# endif -#endif - #if defined (Q_CC_MSVC) && (_MSC_VER < 1300) # define QT_TYPENAME #else diff --git a/src/corelib/concurrent/qtconcurrentiteratekernel.h b/src/corelib/concurrent/qtconcurrentiteratekernel.h index 23aaae8..29d276b 100644 --- a/src/corelib/concurrent/qtconcurrentiteratekernel.h +++ b/src/corelib/concurrent/qtconcurrentiteratekernel.h @@ -184,12 +184,9 @@ public: #if defined (QT_NO_STL) : begin(_begin), end(_end), current(_begin), currentIndex(0), forIteration(false), progressReportingEnabled(true) -#elif !defined(QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION) +#else : begin(_begin), end(_end), current(_begin), currentIndex(0), forIteration(selectIteration(typename std::iterator_traits<Iterator>::iterator_category())), progressReportingEnabled(true) -#else - : begin(_begin), end(_end), currentIndex(0), - forIteration(selectIteration(std::iterator_category(_begin))), progressReportingEnabled(true) #endif { #if defined (QT_NO_STL) diff --git a/src/corelib/concurrent/qthreadpool.cpp b/src/corelib/concurrent/qthreadpool.cpp index 9e4189e..265de33 100644 --- a/src/corelib/concurrent/qthreadpool.cpp +++ b/src/corelib/concurrent/qthreadpool.cpp @@ -41,6 +41,7 @@ #include "qthreadpool.h" #include "qthreadpool_p.h" +#include "qelapsedtimer.h" #ifndef QT_NO_THREAD @@ -249,6 +250,7 @@ bool QThreadPoolPrivate::tooManyThreadsActive() const void QThreadPoolPrivate::startThread(QRunnable *runnable) { QScopedPointer <QThreadPoolThread> thread(new QThreadPoolThread(this)); + thread->setObjectName(QLatin1String("Thread (pooled)")); allThreads.insert(thread.data()); ++activeThreads; @@ -288,11 +290,21 @@ void QThreadPoolPrivate::reset() isExiting = false; } -void QThreadPoolPrivate::waitForDone() +bool QThreadPoolPrivate::waitForDone(int msecs) { QMutexLocker locker(&mutex); - while (!(queue.isEmpty() && activeThreads == 0)) - noActiveThreads.wait(locker.mutex()); + if (msecs < 0) { + while (!(queue.isEmpty() && activeThreads == 0)) + noActiveThreads.wait(locker.mutex()); + } else { + QElapsedTimer timer; + timer.start(); + int t; + while (!(queue.isEmpty() && activeThreads == 0) && + ((t = msecs - timer.elapsed()) > 0)) + noActiveThreads.wait(locker.mutex(), t); + } + return queue.isEmpty() && activeThreads == 0; } /*! \internal @@ -617,6 +629,23 @@ void QThreadPool::waitForDone() d->reset(); } +/*! + \overload waitForDone() + \since 4.8 + + Waits up to \a msecs milliseconds for all threads to exit and removes all + threads from the thread pool. Returns true if all threads were removed; + otherwise it returns false. +*/ +bool QThreadPool::waitForDone(int msecs) +{ + Q_D(QThreadPool); + bool rc = d->waitForDone(msecs); + if (rc) + d->reset(); + return rc; +} + QT_END_NAMESPACE #endif diff --git a/src/corelib/concurrent/qthreadpool.h b/src/corelib/concurrent/qthreadpool.h index cc1e059..0bd1884 100644 --- a/src/corelib/concurrent/qthreadpool.h +++ b/src/corelib/concurrent/qthreadpool.h @@ -85,6 +85,7 @@ public: void releaseThread(); void waitForDone(); + bool waitForDone(int msecs); }; QT_END_NAMESPACE diff --git a/src/corelib/concurrent/qthreadpool_p.h b/src/corelib/concurrent/qthreadpool_p.h index 8a2cf98..3d2d6be 100644 --- a/src/corelib/concurrent/qthreadpool_p.h +++ b/src/corelib/concurrent/qthreadpool_p.h @@ -82,7 +82,7 @@ public: void startThread(QRunnable *runnable = 0); void reset(); - void waitForDone(); + bool waitForDone(int msecs = -1); bool startFrontRunnable(); void stealRunnable(QRunnable *); diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index b7d6034..349b3d4 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -19,7 +19,14 @@ include(codecs/codecs.pri) include(statemachine/statemachine.pri) include(xml/xml.pri) -mac|darwin:LIBS_PRIVATE += -framework ApplicationServices +!qpa:mac|darwin:LIBS_PRIVATE += -framework ApplicationServices +qpa:mac|darwin { + contains(QT_CONFIG, coreservices) { + LIBS_PRIVATE += -framework CoreServices + } else { + LIBS_PRIVATE += -framework CoreFoundation + } +} mac:lib_bundle:DEFINES += QT_NO_DEBUG_PLUGIN_CHECK win32:DEFINES-=QT_NO_CAST_TO_ASCII diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index 4800716..47b82ef 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -13,13 +13,17 @@ SOURCES += \ global/qmalloc.cpp \ global/qnumeric.cpp +nacl { + SOURCES += global/qnaclunimplemented.cpp +} + # qlibraryinfo.cpp includes qconfig.cpp INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global # Only used on platforms with CONFIG += precompile_header PRECOMPILED_HEADER = global/qt_pch.h -linux*:!static:!linux-armcc:!linux-gcce { +linux*:!static:!symbian-armcc:!symbian-gcce { QMAKE_LFLAGS += -Wl,-e,qt_core_boilerplate prog=$$quote(if (/program interpreter: (.*)]/) { print $1; }) DEFINES += ELF_INTERPRETER=\\\"$$system(readelf -l /bin/ls | perl -n -e \'$$prog\')\\\" diff --git a/src/corelib/global/qconfig-minimal-system-dependencies.h b/src/corelib/global/qconfig-minimal-system-dependencies.h new file mode 100644 index 0000000..63319b9 --- /dev/null +++ b/src/corelib/global/qconfig-minimal-system-dependencies.h @@ -0,0 +1,371 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#define QT_FONTS_ARE_RESOURCES + +/* Data structures */ +#ifndef QT_NO_QUUID_STRING +# define QT_NO_QUUID_STRING +#endif +#ifndef QT_NO_STL +# define QT_NO_STL +#endif +#ifndef QT_NO_TEXTDATE +# define QT_NO_TEXTDATE +#endif +#ifndef QT_NO_DATESTRING +# define QT_NO_DATESTRING +#endif + +/* Dialogs */ +#ifndef QT_NO_FILEDIALOG +# define QT_NO_FILEDIALOG +#endif +#ifndef QT_NO_PRINTDIALOG +# define QT_NO_PRINTDIALOG +#endif +#ifndef QT_NO_PRINTPREVIEWDIALOG +# define QT_NO_PRINTPREVIEWDIALOG +#endif + + +/* File I/O */ +#ifndef QT_NO_DOM +# define QT_NO_DOM +#endif +#ifndef QT_NO_FILESYSTEMWATCHER +# define QT_NO_FILESYSTEMWATCHER +#endif +#ifndef QT_NO_FSFILEENGINE +# define QT_NO_FSFILEENGINE +#endif +#ifndef QT_NO_FILESYSTEMMODEL +# define QT_NO_FILESYSTEMMODEL +#endif +#ifndef QT_NO_FILESYSTEMMODEL +# define QT_NO_FILESYSTEMMODEL +#endif +#ifndef QT_NO_PROCESS +# define QT_NO_PROCESS +#endif +#ifndef QT_NO_TEMPORARYFILE +# define QT_NO_TEMPORARYFILE +#endif +#ifndef QT_NO_SETTINGS +# define QT_NO_SETTINGS +#endif +#ifndef QT_NO_LIBRARY +# define QT_NO_LIBRARY +#endif + +/* Fonts */ +#ifndef QT_NO_QWS_QPF2 +# define QT_NO_QWS_QPF2 +#endif + +/* Images */ +#ifndef QT_NO_IMAGEFORMATPLUGIN +# define QT_NO_IMAGEFORMATPLUGIN +#endif +#ifndef QT_NO_IMAGE_HEURISTIC_MASK +# define QT_NO_IMAGE_HEURISTIC_MASK +#endif +#ifndef QT_NO_IMAGE_TEXT +# define QT_NO_IMAGE_TEXT +#endif +#ifndef QT_NO_MOVIE +# define QT_NO_MOVIE +#endif + +/* Internationalization */ +#ifndef QT_NO_BIG_CODECS +# define QT_NO_BIG_CODECS +#endif +#ifndef QT_NO_QWS_INPUTMETHODS +# define QT_NO_QWS_INPUTMETHODS +#endif +#ifndef QT_NO_TEXTCODEC +# define QT_NO_TEXTCODEC +#endif +#ifndef QT_NO_CODECS +# define QT_NO_CODECS +#endif +#ifndef QT_NO_TEXTCODECPLUGIN +# define QT_NO_TEXTCODECPLUGIN +#endif +#ifndef QT_NO_TRANSLATION +# define QT_NO_TRANSLATION +#endif +#ifndef QT_NO_TRANSLATION_UTF8 +# define QT_NO_TRANSLATION_UTF8 +#endif + +/* ItemViews */ + +#ifndef QT_NO_DIRMODEL +# define QT_NO_DIRMODEL +#endif + +/* Kernel */ +#ifndef QT_NO_CLIPBOARD +# define QT_NO_CLIPBOARD +#endif +#ifndef QT_NO_CSSPARSER +# define QT_NO_CSSPARSER +#endif +#ifndef QT_NO_CURSOR +# define QT_NO_CURSOR +#endif +#ifndef QT_NO_DRAGANDDROP +# define QT_NO_DRAGANDDROP +#endif +#ifndef QT_NO_EFFECTS +# define QT_NO_EFFECTS +#endif +#ifndef QT_NO_SESSIONMANAGER +# define QT_NO_SESSIONMANAGER +#endif +#ifndef QT_NO_SHAREDMEMORY +# define QT_NO_SHAREDMEMORY +#endif +#ifndef QT_NO_SOUND +# define QT_NO_SOUND +#endif +#ifndef QT_NO_SYSTEMLOCALE +# define QT_NO_SYSTEMSEMAPHORE +#endif +#ifndef QT_NO_SYSTEMSEMAPHORE +# define QT_NO_SYSTEMSEMAPHORE +#endif +#ifndef QT_NO_TABLETEVENT +# define QT_NO_TABLETEVENT +#endif +#ifndef QT_NO_CRASHHANDLER +# define QT_NO_CRASHHANDLER +#endif +#ifndef QT_NO_CONCURRENT +# define QT_NO_CONCURRENT +#endif +#ifndef QT_NO_XMLSTREAM +# define QT_NO_XMLSTREAM +#endif +#ifndef QT_NO_XMLSTREAMREADER +# define QT_NO_XMLSTREAMREADER +#endif +#ifndef QT_NO_XMLSTREAMWRITER +# define QT_NO_XMLSTREAMWRITER +#endif + +/* Networking */ +#ifndef QT_NO_COP +# define QT_NO_COP +#endif +#ifndef QT_NO_HOSTINFO +# define QT_NO_HOSTINFO +#endif +#ifndef QT_NO_HTTP +# define QT_NO_HTTP +#endif +#ifndef QT_NO_NETWORKPROXY +# define QT_NO_NETWORKPROXY +#endif +#ifndef QT_NO_SOCKS5 +# define QT_NO_SOCKS5 +#endif +#ifndef QT_NO_UDPSOCKET +# define QT_NO_UDPSOCKET +#endif +#ifndef QT_NO_URLINFO +# define QT_NO_URLINFO +#endif +#ifndef QT_NO_FTP +# define QT_NO_FTP +#endif + +/* Painting */ +#ifndef QT_NO_COLORNAMES +# define QT_NO_COLORNAMES +#endif +#ifndef QT_NO_DIRECTPAINTER +# define QT_NO_DIRECTPAINTER +#endif +#ifndef QT_NO_PAINTONSCREEN +# define QT_NO_PAINTONSCREEN +#endif +#ifndef QT_NO_PAINT_DEBUG +# define QT_NO_PAINT_DEBUG +#endif +#ifndef QT_NO_PICTURE +# define QT_NO_PICTURE +#endif +#ifndef QT_NO_PRINTER +# define QT_NO_PRINTER +#endif +#ifndef QT_NO_CUPS +# define QT_NO_CUPS +#endif + +/* Qt for Embedded Linux */ +#ifndef QT_NO_QWSEMBEDWIDGET +# define QT_NO_QWSEMBEDWIDGET +#endif +#ifndef QT_NO_QWS_ALPHA_CURSOR +# define QT_NO_QWS_ALPHA_CURSOR +#endif +#ifndef QT_NO_QWS_CURSOR +# define QT_NO_QWS_CURSOR +#endif +#ifndef QT_NO_QWS_DECORATION_DEFAULT +# define QT_NO_QWS_DECORATION_DEFAULT +#endif +#ifndef QT_NO_QWS_DECORATION_STYLED +# define QT_NO_QWS_DECORATION_STYLED +#endif +#ifndef QT_NO_QWS_DECORATION_WINDOWS +# define QT_NO_QWS_DECORATION_WINDOWS +#endif +#ifndef QT_NO_QWS_MANAGER +# define QT_NO_QWS_MANAGER +#endif +#ifndef QT_NO_QWS_KEYBOARD +# define QT_NO_QWS_KEYBOARD +#endif +#ifndef QT_NO_QWS_MOUSE +# define QT_NO_QWS_MOUSE +#endif +#ifndef QT_NO_QWS_MOUSE_AUTO +# define QT_NO_QWS_MOUSE_AUTO +#endif +#ifndef QT_NO_QWS_MOUSE_MANUAL +# define QT_NO_QWS_MOUSE_MANUAL +#endif +#ifndef QT_NO_QWS_MULTIPROCESS +# define QT_NO_QWS_MULTIPROCESS +#endif +#ifndef QT_NO_QWS_SOUNDSERVER +# define QT_NO_QWS_SOUNDSERVER +#endif +#ifndef QT_NO_SXE +# define QT_NO_SXE +#endif +#ifndef QT_NO_QWS_PROPERTIES +# define QT_NO_QWS_PROPERTIES +#endif +#ifndef QT_NO_QWS_PROXYSCREEN +# define QT_NO_QWS_PROXYSCREEN +#endif +#ifndef QT_NO_QWS_DYNAMICSCREENTRANSFORMATION +# define QT_NO_QWS_DYNAMICSCREENTRANSFORMATION +#endif +#ifndef QT_NO_QWS_LINUXFB +# define QT_NO_QWS_LINUXFB +#endif +#ifndef QT_NO_QWS_MOUSE_PC +# define QT_NO_QWS_MOUSE_PC +#endif +#ifndef QT_NO_QWS_MOUSE_LINUXTP +# define QT_NO_QWS_MOUSE_LINUXTP +#endif +#ifndef QT_NO_QWS_QPF +# define QT_NO_QWS_QPF +#endif + +/* SVG */ +#ifndef QT_NO_SVG +# define QT_NO_SVG +#endif +#ifndef QT_NO_GRAPHICSSVGITEM +# define QT_NO_GRAPHICSSVGITEM +#endif +#ifndef QT_NO_SVGGENERATOR +# define QT_NO_SVGGENERATOR +#endif +#ifndef QT_NO_SVGRENDERER +# define QT_NO_SVGRENDERER +#endif +#ifndef QT_NO_SVGWIDGET +# define QT_NO_SVGWIDGET +#endif + +/* Styles */ +#ifndef QT_NO_STYLE_MOTIF +# define QT_NO_STYLE_MOTIF +#endif +#ifndef QT_NO_STYLE_CDE +# define QT_NO_STYLE_CDE +#endif +#ifndef QT_NO_STYLE_STYLESHEET +# define QT_NO_STYLE_STYLESHEET +#endif +#ifndef QT_NO_STYLE_WINDOWSCE +# define QT_NO_STYLE_WINDOWSCE +#endif +#ifndef QT_NO_STYLE_WINDOWSMOBILE +# define QT_NO_STYLE_WINDOWSMOBILE +#endif +#ifndef QT_NO_STYLE_WINDOWSVISTA +# define QT_NO_STYLE_WINDOWSVISTA +#endif +#ifndef QT_NO_STYLE_WINDOWSXP +# define QT_NO_STYLE_WINDOWSXP +#endif + +/* Utilities */ +#ifndef QT_NO_ACCESSIBILITY +# define QT_NO_ACCESSIBILITY +#endif +#ifndef QT_NO_COMPLETER +# define QT_NO_COMPLETER +#endif +#ifndef QT_NO_DESKTOPSERVICES +# define QT_NO_DESKTOPSERVICES +#endif +#ifndef QT_NO_SCRIPT +# define QT_NO_SCRIPT +#endif +#ifndef QT_NO_SYSTEMTRAYICON +# define QT_NO_SYSTEMTRAYICON +#endif + +/* Windows */ +#ifndef QT_NO_WIN_ACTIVEQT +# define QT_NO_WIN_ACTIVEQT +#endif diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h index d53504a..e0e946b 100644 --- a/src/corelib/global/qendian.h +++ b/src/corelib/global/qendian.h @@ -89,7 +89,7 @@ template <typename T> inline void qToUnaligned(const T src, uchar *dest) * and return the value in host-endian encoding. * There is no requirement that \a src must be aligned. */ -#if defined Q_CC_MSVC && _MSC_VER < 1300 || defined Q_CC_SUN +#if defined Q_CC_SUN inline quint64 qFromLittleEndian_helper(const uchar *src, quint64 *dest) { return 0 @@ -177,7 +177,7 @@ template <> inline qint16 qFromLittleEndian<qint16>(const uchar *src) * and return the value in host-endian encoding. * There is no requirement that \a src must be aligned. */ -#if defined Q_CC_MSVC && _MSC_VER < 1300 || defined Q_CC_SUN +#if defined Q_CC_SUN inline quint64 qFromBigEndian_helper(const uchar *src, quint64 *dest) { return 0 diff --git a/src/corelib/global/qfeatures.h b/src/corelib/global/qfeatures.h index b606843..9710079 100644 --- a/src/corelib/global/qfeatures.h +++ b/src/corelib/global/qfeatures.h @@ -523,11 +523,6 @@ #define QT_NO_FTP #endif -// Hyper Text Transfer Protocol -#if !defined(QT_NO_HTTP) && (defined(QT_NO_HOSTINFO)) -#define QT_NO_HTTP -#endif - // QInputContext #if !defined(QT_NO_IM) && (defined(QT_NO_LIBRARY)) #define QT_NO_IM @@ -583,6 +578,11 @@ #define QT_NO_GRAPHICSVIEW #endif +// Hyper Text Transfer Protocol +#if !defined(QT_NO_HTTP) && (defined(QT_NO_HOSTINFO) || defined(QT_NO_NETWORKPROXY)) +#define QT_NO_HTTP +#endif + // QMdiArea #if !defined(QT_NO_MDIAREA) && (defined(QT_NO_SCROLLAREA)) #define QT_NO_MDIAREA diff --git a/src/corelib/global/qfeatures.txt b/src/corelib/global/qfeatures.txt index 4d938a9..f07fbd5 100644 --- a/src/corelib/global/qfeatures.txt +++ b/src/corelib/global/qfeatures.txt @@ -1050,7 +1050,7 @@ SeeAlso: ??? Feature: HTTP Description: Supports HTTP file access. Section: Networking -Requires: HOSTINFO +Requires: HOSTINFO NETWORKPROXY Name: Hyper Text Transfer Protocol SeeAlso: ??? diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 3291fe7..9b597f6 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -74,7 +74,7 @@ # include <envLib.h> #endif -#if defined(Q_CC_MWERKS) && defined(Q_OS_MACX) +#if defined(Q_OS_MACX) && !defined(QT_NO_CORESERVICES) #include <CoreServices/CoreServices.h> #endif @@ -1232,7 +1232,7 @@ bool qSharedBuild() Defined on Mac OS X. - \sa Q_WS_WIN, Q_WS_X11, Q_WS_QWS, Q_WS_S60 + \sa Q_WS_WIN, Q_WS_X11, Q_WS_QWS, Q_WS_QPA, Q_WS_S60 */ /*! @@ -1241,7 +1241,7 @@ bool qSharedBuild() Defined on Windows. - \sa Q_WS_MAC, Q_WS_X11, Q_WS_QWS, Q_WS_S60 + \sa Q_WS_MAC, Q_WS_X11, Q_WS_QWS, Q_WS_QPA, Q_WS_S60 */ /*! @@ -1250,7 +1250,7 @@ bool qSharedBuild() Defined on X11. - \sa Q_WS_MAC, Q_WS_WIN, Q_WS_QWS, Q_WS_S60 + \sa Q_WS_MAC, Q_WS_WIN, Q_WS_QWS, Q_WS_QPA, Q_WS_S60 */ /*! @@ -1259,7 +1259,16 @@ bool qSharedBuild() Defined on Qt for Embedded Linux. - \sa Q_WS_MAC, Q_WS_WIN, Q_WS_X11, Q_WS_S60 + \sa Q_WS_MAC, Q_WS_WIN, Q_WS_X11, Q_WS_QPA, Q_WS_S60 +*/ + +/*! + \macro Q_WS_QPA + \relates <QtGlobal> + + Defined on Qt for Embedded Linux, Lite version. + + \sa Q_WS_MAC, Q_WS_WIN, Q_WS_X11, Q_WS_QWS, Q_WS_S60 */ /*! @@ -1634,7 +1643,7 @@ static const unsigned int qt_one = 1; const int QSysInfo::ByteOrder = ((*((unsigned char *) &qt_one) == 0) ? BigEndian : LittleEndian); #endif -#if !defined(QWS) && defined(Q_OS_MAC) +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) QT_BEGIN_INCLUDE_NAMESPACE #include "private/qcore_mac_p.h" @@ -1688,15 +1697,18 @@ Q_CORE_EXPORT void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding e Q_CORE_EXPORT QString qt_mac_from_pascal_string(const Str255 pstr) { return QCFString(CFStringCreateWithPascalString(0, pstr, CFStringGetSystemEncoding())); } +#endif //!defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) - +#if !defined(QWS) && defined(Q_OS_MAC) static QSysInfo::MacVersion macVersion() { +#ifndef QT_NO_CORESERVICES SInt32 gestalt_version; if (Gestalt(gestaltSystemVersion, &gestalt_version) == noErr) { return QSysInfo::MacVersion(((gestalt_version & 0x00F0) >> 4) + 2); } +#endif return QSysInfo::MV_Unknown; } const QSysInfo::MacVersion QSysInfo::MacintoshVersion = macVersion(); @@ -2007,7 +2019,7 @@ QSysInfo::S60Version QSysInfo::s60Version() */ void qt_check_pointer(const char *n, int l) { - qWarning("In file %s, line %d: Out of memory", n, l); + qFatal("In file %s, line %d: Out of memory", n, l); } /* \internal @@ -2238,7 +2250,8 @@ void qt_message_output(QtMsgType msgType, const char *buf) _LIT(format, "[Qt Message] %S"); const int maxBlockSize = 256 - ((const TDesC &)format).Length(); const TPtrC8 ptr(reinterpret_cast<const TUint8*>(buf)); - HBufC* hbuffer = q_check_ptr(HBufC::New(qMin(maxBlockSize, ptr.Length()))); + HBufC* hbuffer = HBufC::New(qMin(maxBlockSize, ptr.Length())); + Q_CHECK_PTR(hbuffer); for (int i = 0; i < ptr.Length(); i += hbuffer->Length()) { hbuffer->Des().Copy(ptr.Mid(i, qMin(maxBlockSize, ptr.Length()-i))); RDebug::Print(format, hbuffer); diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 35607d5..b75a3d8 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -44,11 +44,11 @@ #include <stddef.h> -#define QT_VERSION_STR "4.7.1" +#define QT_VERSION_STR "4.8.0" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x040701 +#define QT_VERSION 0x040800 /* can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)) */ @@ -64,6 +64,10 @@ #ifdef __cplusplus +#ifndef QT_NO_STL +#include <algorithm> +#endif + #ifndef QT_NAMESPACE /* user namespace */ # define QT_PREPEND_NAMESPACE(name) ::name @@ -216,6 +220,8 @@ namespace QT_NAMESPACE {} # define Q_OS_ULTRIX #elif defined(sinix) # define Q_OS_RELIANT +#elif defined(__native_client__) +# define Q_OS_NACL #elif defined(__linux__) || defined(__linux) # define Q_OS_LINUX #elif defined(__FreeBSD__) || defined(__DragonFly__) @@ -284,7 +290,7 @@ namespace QT_NAMESPACE {} # endif #endif -#if defined(Q_OS_MAC64) && !defined(QT_MAC_USE_COCOA) && !defined(QT_BUILD_QMAKE) +#if defined(Q_WS_MAC64) && !defined(QT_MAC_USE_COCOA) && !defined(QT_BUILD_QMAKE) && !defined(QT_BOOTSTRAPPED) #error "You are building a 64-bit application, but using a 32-bit version of Qt. Check your build configuration." #endif @@ -356,6 +362,7 @@ namespace QT_NAMESPACE {} GCCE - GCCE (Symbian GCCE builds) RVCT - ARM Realview Compiler Suite NOKIAX86 - Nokia x86 (Symbian WINSCW builds) + CLANG - C++ front-end for the LLVM compiler Should be sorted most to least authoritative. @@ -383,31 +390,12 @@ namespace QT_NAMESPACE {} #elif defined(_MSC_VER) # define Q_CC_MSVC -/* proper support of bool for _MSC_VER >= 1100 */ +# define Q_CC_MSVC_NET # define Q_CANNOT_DELETE_CONSTANT # define Q_OUTOFLINE_TEMPLATE inline # define Q_NO_TEMPLATE_FRIENDS -# define QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION -# define Q_ALIGNOF(type) __alignof(type) -# define Q_DECL_ALIGN(n) __declspec(align(n)) - -/* Visual C++.Net issues for _MSC_VER >= 1300 */ -# if _MSC_VER >= 1300 -# define Q_CC_MSVC_NET -# if _MSC_VER < 1310 || (defined(Q_OS_WIN64) && defined(_M_IA64)) -# define Q_TYPENAME -# else -# undef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION -# endif -# else -# define Q_NO_USING_KEYWORD -# define QT_NO_MEMBER_TEMPLATES -# endif -# if _MSC_VER < 1310 -# define QT_NO_QOBJECT_CHECK -# define Q_TYPENAME -# define QT_NO_TEMPLATE_TEMPLATE_PARAMETERS -# endif +# define Q_ALIGNOF(type) __alignof(type) +# define Q_DECL_ALIGN(n) __declspec(align(n)) /* Intel C++ disguising as Visual C++: the `using' keyword avoids warnings */ # if defined(__INTEL_COMPILER) # define Q_CC_INTEL @@ -419,6 +407,19 @@ namespace QT_NAMESPACE {} # undef QT_HAVE_3DNOW # endif +#if defined(Q_CC_MSVC) && _MSC_VER >= 1600 +# define Q_COMPILER_RVALUE_REFS +# define Q_COMPILER_INITIALIZER_LISTS +# define Q_COMPILER_AUTO_TYPE +# define Q_COMPILER_LAMBDA +//# define Q_COMPILER_VARIADIC_TEMPLATES +//# define Q_COMPILER_CLASS_ENUM +//# define Q_COMPILER_DEFAULT_DELETE_MEMBERS +//# define Q_COMPILER_UNICODE_STRINGS +//# define Q_COMPILER_EXTERN_TEMPLATES +# endif + + #elif defined(__BORLANDC__) || defined(__TURBOC__) # define Q_CC_BOR # define Q_INLINE_TEMPLATE @@ -458,6 +459,10 @@ namespace QT_NAMESPACE {} # define Q_CC_INTEL # define Q_NO_TEMPLATE_FRIENDS # endif +# if defined(__clang__) +/* Clang also masquerades as GCC 4.2.1 */ +# define Q_CC_CLANG +# endif # ifdef __APPLE__ # define Q_NO_DEPRECATED_CONSTRUCTORS # endif @@ -493,6 +498,26 @@ namespace QT_NAMESPACE {} # define QT_NO_ARM_EABI # endif # endif +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403 + /* C++0x features supported in GCC 4.3: */ +# define Q_COMPILER_RVALUE_REFS +# endif +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 + /* C++0x features supported in GCC 4.4: */ +# define Q_COMPILER_VARIADIC_TEMPLATES +# define Q_COMPILER_AUTO_TYPE +# define Q_COMPILER_EXTERN_TEMPLATES +# define Q_COMPILER_DEFAULT_DELETE_MEMBERS +# define Q_COMPILER_CLASS_ENUM +# define Q_COMPILER_INITIALIZER_LISTS +# endif +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 + /* C++0x features supported in GCC 4.5: */ +# define Q_COMPILER_LAMBDA +# define Q_COMPILER_UNICODE_STRINGS +# endif +# endif /* IBM compiler versions are a bit messy. There are actually two products: the C product, and the C++ product. The C++ compiler is always packaged @@ -803,7 +828,7 @@ namespace QT_NAMESPACE {} # define Q_WS_PM # error "Qt does not work with OS/2 Presentation Manager or Workplace Shell" #elif defined(Q_OS_UNIX) -# if defined(Q_OS_MAC) && !defined(__USE_WS_X11__) && !defined(Q_WS_QWS) +# if defined(Q_OS_MAC) && !defined(__USE_WS_X11__) && !defined(Q_WS_QWS) && !defined(Q_WS_QPA) # define Q_WS_MAC # define Q_WS_MACX # if defined(Q_OS_MAC64) @@ -815,7 +840,7 @@ namespace QT_NAMESPACE {} # if !defined(QT_NO_S60) # define Q_WS_S60 # endif -# elif !defined(Q_WS_QWS) +# elif !defined(Q_WS_QWS) && !defined(Q_WS_QPA) # define Q_WS_X11 # endif #endif @@ -924,10 +949,10 @@ redefine to built-in booleans to make autotests work properly */ #endif /* - Proper for-scoping in VC++6 and MIPSpro CC + Proper for-scoping in MIPSpro CC */ #ifndef QT_NO_KEYWORDS -# if (defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) && !defined(Q_CC_INTEL)) || defined(Q_CC_MIPS) || (defined(Q_CC_HPACC) && defined(__ia64)) +# if defined(Q_CC_MIPS) || (defined(Q_CC_HPACC) && defined(__ia64)) # define for if(0){}else for # endif #endif @@ -951,7 +976,7 @@ redefine to built-in booleans to make autotests work properly */ # define Q_DECL_DEPRECATED Q_DECL_DEPRECATED #elif (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && (__GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 >= 2))) || defined(Q_CC_RVCT) # define Q_DECL_DEPRECATED __attribute__ ((__deprecated__)) -#elif defined(Q_CC_MSVC) && (_MSC_VER >= 1300) +#elif defined(Q_CC_MSVC) # define Q_DECL_DEPRECATED __declspec(deprecated) # if defined (Q_CC_INTEL) # define Q_DECL_VARIABLE_DEPRECATED @@ -1050,12 +1075,12 @@ redefine to built-in booleans to make autotests work properly */ #if defined(__i386__) || defined(_WIN32) || defined(_WIN32_WCE) # if defined(Q_CC_GNU) -#if ((100*(__GNUC__ - 0) + 10*(__GNUC_MINOR__ - 0) + __GNUC_PATCHLEVEL__) >= 332) +#if !defined(Q_CC_INTEL) && ((100*(__GNUC__ - 0) + 10*(__GNUC_MINOR__ - 0) + __GNUC_PATCHLEVEL__) >= 332) # define QT_FASTCALL __attribute__((regparm(3))) #else # define QT_FASTCALL #endif -# elif defined(Q_CC_MSVC) && (_MSC_VER > 1300 || defined(Q_CC_INTEL)) +# elif defined(Q_CC_MSVC) # define QT_FASTCALL __fastcall # else # define QT_FASTCALL @@ -1077,7 +1102,7 @@ redefine to built-in booleans to make autotests work properly */ typedef int QNoImplicitBoolCast; -#if defined(QT_ARCH_ARM) || defined(QT_ARCH_ARMV6) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_MIPS) && (defined(Q_WS_QWS) || defined(Q_OS_WINCE))) || defined(QT_ARCH_SH) || defined(QT_ARCH_SH4A) +#if defined(QT_ARCH_ARM) || defined(QT_ARCH_ARMV6) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_MIPS) && (defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_WINCE))) || defined(QT_ARCH_SH) || defined(QT_ARCH_SH4A) #define QT_NO_FPU #endif @@ -1362,15 +1387,22 @@ class QDataStream; # else # define Q_GUI_EXPORT_INLINE inline # endif +# if defined(QT_BUILD_COMPAT_LIB) +# define Q_COMPAT_EXPORT_INLINE Q_COMPAT_EXPORT inline +# else +# define Q_COMPAT_EXPORT_INLINE inline +# endif #elif defined(Q_CC_RVCT) // we force RVCT not to export inlines by passing --visibility_inlines_hidden // so we need to just inline it, rather than exporting and inlining // note: this affects the contents of the DEF files (ie. these functions do not appear) # define Q_CORE_EXPORT_INLINE inline # define Q_GUI_EXPORT_INLINE inline +# define Q_COMPAT_EXPORT_INLINE inline #else # define Q_CORE_EXPORT_INLINE Q_CORE_EXPORT inline # define Q_GUI_EXPORT_INLINE Q_GUI_EXPORT inline +# define Q_COMPAT_EXPORT_INLINE Q_COMPAT_EXPORT inline #endif /* @@ -1702,7 +1734,7 @@ Q_CORE_EXPORT void qBadAlloc(); #ifdef QT_NO_EXCEPTIONS # if defined(QT_NO_DEBUG) -# define Q_CHECK_PTR(p) qt_noop(); +# define Q_CHECK_PTR(p) qt_noop() # else # define Q_CHECK_PTR(p) do {if(!(p))qt_check_pointer(__FILE__,__LINE__);} while (0) # endif @@ -1716,12 +1748,7 @@ inline T *q_check_ptr(T *p) { Q_CHECK_PTR(p); return p; } #if (defined(Q_CC_GNU) && !defined(Q_OS_SOLARIS)) || defined(Q_CC_HPACC) || defined(Q_CC_DIAB) # define Q_FUNC_INFO __PRETTY_FUNCTION__ #elif defined(_MSC_VER) - /* MSVC 2002 doesn't have __FUNCSIG__ nor can it handle QT_STRINGIFY. */ -# if _MSC_VER <= 1300 -# define Q_FUNC_INFO __FILE__ "(line number unavailable)" -# else -# define Q_FUNC_INFO __FUNCSIG__ -# endif +# define Q_FUNC_INFO __FUNCSIG__ #else # if defined(Q_OS_SOLARIS) || defined(Q_CC_XLC) || defined(Q_OS_SYMBIAN) # define Q_FUNC_INFO __FILE__ "(line number unavailable)" @@ -1971,8 +1998,6 @@ static inline bool qIsNull(float f) qIsDetached - data sharing functionality */ -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION - /* The catch-all template. */ @@ -2005,28 +2030,6 @@ public: }; }; -#else - -template <typename T> char QTypeInfoHelper(T*(*)()); -void* QTypeInfoHelper(...); - -template <typename T> inline bool qIsDetached(T &) { return true; } - -template <typename T> -class QTypeInfo -{ -public: - enum { - isPointer = (1 == sizeof(QTypeInfoHelper((T(*)())0))), - isComplex = !isPointer, - isStatic = !isPointer, - isLarge = (sizeof(T)>sizeof(void*)), - isDummy = false - }; -}; - -#endif /* QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION */ - /* Specialize a specific type with: @@ -2043,8 +2046,7 @@ enum { /* TYPEINFO flags */ Q_DUMMY_TYPE = 0x4 }; -#define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \ -template <> \ +#define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) \ class QTypeInfo<TYPE > \ { \ public: \ @@ -2058,12 +2060,22 @@ public: \ static inline const char *name() { return #TYPE; } \ } +#define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \ +template<> \ +Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) + + template <typename T> inline void qSwap(T &value1, T &value2) { +#ifdef QT_NO_STL const T t = value1; value1 = value2; value2 = t; +#else + using std::swap; + swap(value1, value2); +#endif } /* @@ -2075,12 +2087,23 @@ inline void qSwap(T &value1, T &value2) types must declare a 'bool isDetached(void) const;' member for this to work. */ +#ifdef QT_NO_STL +#define Q_DECLARE_SHARED_STL(TYPE) +#else +#define Q_DECLARE_SHARED_STL(TYPE) \ +QT_END_NAMESPACE \ +namespace std { \ + template<> inline void swap<QT_PREPEND_NAMESPACE(TYPE)>(QT_PREPEND_NAMESPACE(TYPE) &value1, QT_PREPEND_NAMESPACE(TYPE) &value2) \ + { swap(value1.data_ptr(), value2.data_ptr()); } \ +} \ +QT_BEGIN_NAMESPACE +#endif + #define Q_DECLARE_SHARED(TYPE) \ template <> inline bool qIsDetached<TYPE>(TYPE &t) { return t.isDetached(); } \ template <> inline void qSwap<TYPE>(TYPE &value1, TYPE &value2) \ -{ \ - qSwap(value1.data_ptr(), value2.data_ptr()); \ -} +{ qSwap(value1.data_ptr(), value2.data_ptr()); } \ +Q_DECLARE_SHARED_STL(TYPE) /* QTypeInfo primitive specializations @@ -2140,10 +2163,6 @@ Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n); # pragma warning(disable: 4231) /* nonstandard extension used : 'extern' before template explicit instantiation */ # pragma warning(disable: 4710) /* function not inlined */ # pragma warning(disable: 4530) /* C++ exception handler used, but unwind semantics are not enabled. Specify -GX */ -# if _MSC_VER < 1300 -# pragma warning(disable: 4284) /* return type for 'type1::operator ->' is 'type2 *' */ - /* (ie; not a UDT or reference to a UDT. Will produce errors if applied using infix notation) */ -# endif # elif defined(Q_CC_BOR) # pragma option -w-inl # pragma option -w-aus @@ -2217,13 +2236,9 @@ public: #define Q_DECLARE_FLAGS(Flags, Enum)\ typedef QFlags<Enum> Flags; -#if defined Q_CC_MSVC && _MSC_VER < 1300 -# define Q_DECLARE_INCOMPATIBLE_FLAGS(Flags) -#else -# define Q_DECLARE_INCOMPATIBLE_FLAGS(Flags) \ +#define Q_DECLARE_INCOMPATIBLE_FLAGS(Flags) \ inline QIncompatibleFlag operator|(Flags::enum_type f1, int f2) \ { return QIncompatibleFlag(int(f1) | f2); } -#endif #define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) \ inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) \ @@ -2280,9 +2295,9 @@ template <typename T> inline const QForeachContainer<T> *qForeachContainer(const QForeachContainerBase *base, const T *) { return static_cast<const QForeachContainer<T> *>(base); } -#if (defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) && !defined(Q_CC_INTEL)) || defined(Q_CC_MIPS) +#if defined(Q_CC_MIPS) /* - Proper for-scoping in VC++6 and MIPSpro CC + Proper for-scoping in MIPSpro CC */ # define Q_FOREACH(variable,container) \ if(0){}else \ @@ -2638,12 +2653,6 @@ QT_LICENSED_MODULE(DBus) # define QT_NO_QFUTURE #endif -// MSVC 6.0 and MSVC .NET 2002, can`t handle the map(), etc templates, -// but the QFuture class compiles. -#if (defined(Q_CC_MSVC) && _MSC_VER <= 1300) -# define QT_NO_CONCURRENT -#endif - // gcc 3 version has problems with some of the // map/filter overloads. #if defined(Q_CC_GNU) && (__GNUC__ < 4) @@ -2662,6 +2671,16 @@ QT_LICENSED_MODULE(DBus) # define QT_NO_PROCESS #endif +#ifdef Q_OS_NACL +#include <QtCore/qnaclunimplemented.h> +#endif + +#if defined (__ELF__) +# if defined (Q_OS_LINUX) || defined (Q_OS_SOLARIS) || defined (Q_OS_FREEBSD) || defined (Q_OS_OPENBSD) || defined (Q_OS_IRIX) +# define Q_OF_ELF +# endif +#endif + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 957abbf..d493390 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -517,6 +517,9 @@ void qt_core_boilerplate() #ifdef QT_BUILD_KEY_COMPAT2 "| " QT_BUILD_KEY_COMPAT2 " " #endif +#ifdef QT_BUILD_KEY_COMPAT3 + "| " QT_BUILD_KEY_COMPAT3 " " +#endif "|\n" "Build date: %s\n" "Installation prefix: %s\n" diff --git a/src/corelib/global/qnaclunimplemented.cpp b/src/corelib/global/qnaclunimplemented.cpp new file mode 100644 index 0000000..1a89b8df --- /dev/null +++ b/src/corelib/global/qnaclunimplemented.cpp @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** 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 "qnaclunimplemented.h" +#include <pthread.h> +#include <qglobal.h> + +/* + The purpose of this file is to stub out certain functions + that are not provided by the Native Client SDK. This is + done as an alterative to sprinkling the Qt sources with + NACL ifdefs. + + There are two main classes of functions: + + - Functions that are called but can have no effect: + For these we simply give an empty implementation + + - Functions that are referenced in the source code, but + is not/must not be called at run-time: + These we either leave undefined or implement with a + qFatal. + + This is a work in progress. +*/ + +extern "C" { + +void pthread_cleanup_push(void (*)(void *), void *) +{ + +} + +void pthread_cleanup_pop(int) +{ + +} + +int pthread_setcancelstate(int, int *) +{ + return 0; +} + +int pthread_setcanceltype(int, int *) +{ + return 0; +} + +void pthread_testcancel(void) +{ + +} + + +int pthread_cancel(pthread_t) +{ + return 0; +} + +int pthread_attr_setinheritsched(pthread_attr_t *,int) +{ + return 0; +} + + +int pthread_attr_getinheritsched(const pthread_attr_t *, int *) +{ + return 0; +} + +// event dispatcher, select +//struct fd_set; +//struct timeval; + +int fcntl(int, int, ...) +{ + return 0; +} + +int sigaction(int, const struct sigaction *, struct sigaction *) +{ + return 0; +} + +int open(const char *, int, ...) +{ + return 0; +} + +int open64(const char *, int, ...) +{ + return 0; +} + +int access(const char *, int) +{ + return 0; +} + +typedef long off64_t; +off64_t ftello64(void *) +{ + qFatal("ftello64 called"); + return 0; +} + +off64_t lseek64(int, off_t, int) +{ + qFatal("lseek64 called"); + return 0; +} + +} // Extern C + +int select(int, fd_set *, fd_set *, fd_set *, struct timeval *) +{ + return 0; +} diff --git a/src/corelib/global/qnaclunimplemented.h b/src/corelib/global/qnaclunimplemented.h new file mode 100644 index 0000000..2d3d426 --- /dev/null +++ b/src/corelib/global/qnaclunimplemented.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QNACLUNIMPLEMENTED_H +#define QNACLUNIMPLEMENTED_H + +#ifdef Q_OS_NACL + +// pthread +#include <pthread.h> +#define PTHREAD_CANCEL_DISABLE 1 +#define PTHREAD_CANCEL_ENABLE 2 +#define PTHREAD_INHERIT_SCHED 3 + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +extern "C" { + +void pthread_cleanup_push(void (*handler)(void *), void *arg); +void pthread_cleanup_pop(int execute); + +int pthread_setcancelstate(int state, int *oldstate); +int pthread_setcanceltype(int type, int *oldtype); +void pthread_testcancel(void); +int pthread_cancel(pthread_t thread); + +int pthread_attr_setinheritsched(pthread_attr_t *attr, + int inheritsched); +int pthread_attr_getinheritsched(const pthread_attr_t *attr, + int *inheritsched); + +// event dispatcher, select +//struct fd_set; +//struct timeval; +int fcntl(int fildes, int cmd, ...); +int sigaction(int sig, const struct sigaction * act, struct sigaction * oact); + +typedef long off64_t; +off64_t ftello64(void *stream); +off64_t lseek64(int fildes, off_t offset, int whence); +int open64(const char *path, int oflag, ...); + +} + +int select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * errorfds, struct timeval * timeout); + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif //Q_OS_NACL + +#endif //QNACLUNIMPLEMENTED_H diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 3952836..3ed6291 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -534,6 +534,7 @@ public: AA_DontUseNativeMenuBar = 6, AA_MacDontSwapCtrlAndMeta = 7, AA_S60DontConstructApplicationPanes = 8, + AA_X11InitThreads = 9, // Add new attributes before this line AA_AttributeCount @@ -1658,7 +1659,7 @@ public: typedef void *HANDLE; #elif defined(Q_WS_X11) typedef unsigned long HANDLE; -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_QPA) typedef void * HANDLE; #elif defined(Q_OS_SYMBIAN) typedef unsigned long int HANDLE; // equivalent to TUint32 diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 6b1aa17..f097f2a 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -156,6 +156,11 @@ whole lifetime. This attribute must be set before QApplication is constructed. + \value AA_X11InitThreads Calls XInitThreads() as part of the QApplication + construction in order to make Xlib calls thread-safe. This + attribute must be set before QApplication is constructed. + + \omitvalue AA_AttributeCount */ diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 3d964c6..cfb40bc 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -69,7 +69,7 @@ win32 { SOURCES += io/qfsfileengine_iterator_unix.cpp symbian:SOURCES += io/qprocess_symbian.cpp else:SOURCES += io/qprocess_unix.cpp - macx-*: { + !nacl:macx-*: { HEADERS += io/qfilesystemwatcher_fsevents_p.h SOURCES += io/qsettings_mac.cpp io/qfilesystemwatcher_fsevents.cpp } @@ -84,9 +84,11 @@ win32 { io/qfilesystemwatcher_dnotify_p.h } - freebsd-*|macx-*|darwin-*|openbsd-*:{ - SOURCES += io/qfilesystemwatcher_kqueue.cpp - HEADERS += io/qfilesystemwatcher_kqueue_p.h + !nacl { + freebsd-*|macx-*|darwin-*|openbsd-*:{ + SOURCES += io/qfilesystemwatcher_kqueue.cpp + HEADERS += io/qfilesystemwatcher_kqueue_p.h + } } symbian { diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp index d6b6f11..37a093c 100644 --- a/src/corelib/io/qabstractfileengine.cpp +++ b/src/corelib/io/qabstractfileengine.cpp @@ -41,12 +41,16 @@ #include "qabstractfileengine.h" #include "private/qabstractfileengine_p.h" +#ifdef QT_BUILD_CORE_LIB +#include "private/qresource_p.h" +#endif #include "qdatetime.h" #include "qreadwritelock.h" #include "qvariant.h" // built-in handlers #include "qfsfileengine.h" #include "qdiriterator.h" +#include "qstringbuilder.h" QT_BEGIN_NAMESPACE @@ -94,6 +98,8 @@ QT_BEGIN_NAMESPACE \sa QAbstractFileEngine, QAbstractFileEngine::create() */ +static bool qt_file_engine_handlers_in_use = false; + /* All application-wide handlers are stored in this list. The mutex must be acquired to ensure thread safety. @@ -123,6 +129,7 @@ Q_GLOBAL_STATIC(QAbstractFileEngineHandlerList, fileEngineHandlers) QAbstractFileEngineHandler::QAbstractFileEngineHandler() { QWriteLocker locker(fileEngineHandlerMutex()); + qt_file_engine_handlers_in_use = true; fileEngineHandlers()->prepend(this); } @@ -134,8 +141,12 @@ QAbstractFileEngineHandler::~QAbstractFileEngineHandler() { QWriteLocker locker(fileEngineHandlerMutex()); // Remove this handler from the handler list only if the list is valid. - if (!qt_abstractfileenginehandlerlist_shutDown) - fileEngineHandlers()->removeAll(this); + if (!qt_abstractfileenginehandlerlist_shutDown) { + QAbstractFileEngineHandlerList *handlers = fileEngineHandlers(); + handlers->removeOne(this); + if (handlers->isEmpty()) + qt_file_engine_handlers_in_use = false; + } } /*! @@ -166,33 +177,48 @@ QAbstractFileEngineHandler::~QAbstractFileEngineHandler() */ QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName) { - { + if (qt_file_engine_handlers_in_use) { QReadLocker locker(fileEngineHandlerMutex()); // check for registered handlers that can load the file - for (int i = 0; i < fileEngineHandlers()->size(); i++) { - if (QAbstractFileEngine *ret = fileEngineHandlers()->at(i)->create(fileName)) + QAbstractFileEngineHandlerList *handlers = fileEngineHandlers(); + for (int i = 0; i < handlers->size(); i++) { + if (QAbstractFileEngine *ret = handlers->at(i)->create(fileName)) return ret; } } #ifdef QT_BUILD_CORE_LIB - if (!fileName.startsWith(QLatin1Char('/'))) { - int prefixSeparator = fileName.indexOf(QLatin1Char(':')); - if (prefixSeparator > 1) { - QString prefix = fileName.left(prefixSeparator); - QString fileNameWithoutPrefix = fileName.mid(prefixSeparator + 1).prepend(QLatin1Char('/')); - const QStringList &paths = QDir::searchPaths(prefix); + for (int prefixSeparator = 0; prefixSeparator < fileName.size(); ++prefixSeparator) { + QChar const ch = fileName[prefixSeparator]; + if (ch == QLatin1Char('/')) + break; + + if (ch == QLatin1Char(':')) { + if (prefixSeparator == 0) + return new QResourceFileEngine(fileName); + + if (prefixSeparator == 1) + break; + + const QStringList &paths = QDir::searchPaths(fileName.left(prefixSeparator)); for (int i = 0; i < paths.count(); i++) { - QString path = paths.at(i); - path.append(fileNameWithoutPrefix); - QAbstractFileEngine *engine = create(path); + QAbstractFileEngine *engine = create(paths.at(i) % QLatin1Char('/') % fileName.mid(prefixSeparator + 1)); if (engine && (engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::ExistsFlag)) { return engine; } delete engine; } + + break; } + + // There's no need to fully validate the prefix here. Consulting the + // unicode tables could be expensive and validation is already + // performed in QDir::setSearchPaths. + // + // if (!ch.isLetterOrNumber()) + // break; } #endif diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h index 222ba8f..774c4bc 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -85,10 +85,11 @@ public: Qt_4_4 = 10, Qt_4_5 = 11, Qt_4_6 = 12, - Qt_4_7 = Qt_4_6 -#if QT_VERSION >= 0x040800 -#error Add the datastream version for this Qt version + Qt_4_7 = Qt_4_6, Qt_4_8 = Qt_4_7 +#if QT_VERSION >= 0x040900 +#error Add the datastream version for this Qt version + Qt_4_9 = Qt_4_8 #endif }; diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index 093312f..a9d5ad4 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -137,10 +137,8 @@ public: inline QNoDebug &nospace() { return *this; } inline QNoDebug &maybeSpace() { return *this; } -#ifndef QT_NO_MEMBER_TEMPLATES template<typename T> inline QNoDebug &operator<<(const T &) { return *this; } -#endif }; Q_CORE_EXPORT_INLINE QDebug qCritical() { return QDebug(QtCriticalMsg); } @@ -285,11 +283,6 @@ Q_CORE_EXPORT_INLINE QDebug qDebug() { return QDebug(QtDebugMsg); } inline QNoDebug qDebug() { return QNoDebug(); } #define qDebug QT_NO_QDEBUG_MACRO -#ifdef QT_NO_MEMBER_TEMPLATES -template<typename T> -inline QNoDebug operator<<(QNoDebug debug, const T &) { return debug; } -#endif - #endif #if !defined(QT_NO_WARNING_OUTPUT) diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index efcc8f9..426f61e 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -778,6 +778,7 @@ QString QDir::relativeFilePath(const QString &fileName) const return result; } +#ifndef QT_NO_DEPRECATED /*! \obsolete @@ -787,6 +788,7 @@ QString QDir::convertSeparators(const QString &pathName) { return toNativeSeparators(pathName); } +#endif /*! \since 4.2 @@ -1854,7 +1856,8 @@ QString QDir::homePath() /*! Returns the absolute path of the system's temporary directory. - On Unix/Linux systems this is usually \c{/tmp}; on Windows this is + On Unix/Linux systems this is the path in the \c TMPDIR environment + variable or \c{/tmp} if \c TMPDIR is not defined. On Windows this is usually the path in the \c TEMP or \c TMP environment variable. Whether a directory separator is added to the end or not, depends on the operating system. diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h index 7e5fbac..9eab24f 100644 --- a/src/corelib/io/qdir.h +++ b/src/corelib/io/qdir.h @@ -128,6 +128,10 @@ public: QDir &operator=(const QDir &); QDir &operator=(const QString &path); +#ifdef Q_COMPILER_RVALUE_REFS + inline QDir &operator=(QDir &&other) + { qSwap(d_ptr, other.d_ptr); return *this; } +#endif void setPath(const QString &path); QString path() const; diff --git a/src/corelib/io/qfileinfo.h b/src/corelib/io/qfileinfo.h index f0128b1..aec7543 100644 --- a/src/corelib/io/qfileinfo.h +++ b/src/corelib/io/qfileinfo.h @@ -67,6 +67,10 @@ public: ~QFileInfo(); QFileInfo &operator=(const QFileInfo &fileinfo); +#ifdef Q_COMPILER_RVALUE_REFS + inline QFileInfo&operator=(QFileInfo &&other) + { qSwap(d_ptr, other.d_ptr); return *this; } +#endif bool operator==(const QFileInfo &fileinfo); // 5.0 - remove me bool operator==(const QFileInfo &fileinfo) const; inline bool operator!=(const QFileInfo &fileinfo) { return !(operator==(fileinfo)); } // 5.0 - remove me diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.cpp b/src/corelib/io/qfilesystemwatcher_fsevents.cpp index d3276bd..0f96792 100644 --- a/src/corelib/io/qfilesystemwatcher_fsevents.cpp +++ b/src/corelib/io/qfilesystemwatcher_fsevents.cpp @@ -45,6 +45,8 @@ #include "qfilesystemwatcher.h" #include "qfilesystemwatcher_fsevents_p.h" +#ifndef QT_NO_FILESYSTEMWATCHER + #include <qdebug.h> #include <qfile.h> #include <qdatetime.h> @@ -487,3 +489,4 @@ void QFSEventsFileSystemWatcherEngine::run() } QT_END_NAMESPACE +#endif //QT_NO_FILESYSTEMWATCHER diff --git a/src/corelib/io/qfilesystemwatcher_fsevents_p.h b/src/corelib/io/qfilesystemwatcher_fsevents_p.h index b0462b6..c888c61 100644 --- a/src/corelib/io/qfilesystemwatcher_fsevents_p.h +++ b/src/corelib/io/qfilesystemwatcher_fsevents_p.h @@ -56,6 +56,8 @@ #include "qfilesystemwatcher_p.h" +#ifndef QT_NO_FILESYSTEMWATCHER + #include <QtCore/qmutex.h> #include <QtCore/qwaitcondition.h> #include <QtCore/qthread.h> @@ -123,6 +125,8 @@ private: #endif }; +#endif //QT_NO_FILESYSTEMWATCHER + #endif QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp index 4740a89..dc18ae7 100644 --- a/src/corelib/io/qfilesystemwatcher_inotify.cpp +++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp @@ -353,24 +353,24 @@ void QInotifyFileSystemWatcherEngine::readFromInotify() ioctl(inotifyFd, FIONREAD, (char *) &buffSize); QVarLengthArray<char, 4096> buffer(buffSize); buffSize = read(inotifyFd, buffer.data(), buffSize); - const char *at = buffer.data(); - const char * const end = at + buffSize; + char *at = buffer.data(); + char * const end = at + buffSize; - QMap<int, inotify_event> eventForId; + QMap<int, inotify_event *> eventForId; while (at < end) { - const inotify_event *event = reinterpret_cast<const inotify_event *>(at); + inotify_event *event = reinterpret_cast<inotify_event *>(at); if (eventForId.contains(event->wd)) - eventForId[event->wd].mask |= event->mask; + eventForId[event->wd]->mask |= event->mask; else - eventForId.insert(event->wd, *event); + eventForId.insert(event->wd, event); at += sizeof(inotify_event) + event->len; } - QMap<int, inotify_event>::const_iterator it = eventForId.constBegin(); + QMap<int, inotify_event *>::const_iterator it = eventForId.constBegin(); while (it != eventForId.constEnd()) { - inotify_event event = *it; + const inotify_event &event = **it; ++it; // qDebug() << "inotify event, wd" << event.wd << "mask" << hex << event.mask; diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp index 378ad20..7960792 100644 --- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp +++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp @@ -45,6 +45,8 @@ #include "qfilesystemwatcher_kqueue_p.h" #include "private/qcore_unix_p.h" +#ifndef QT_NO_FILESYSTEMWATCHER + #include <qdebug.h> #include <qfile.h> #include <qsocketnotifier.h> @@ -343,4 +345,6 @@ process_next_event: } } +#endif //QT_NO_FILESYSTEMWATCHER + QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemwatcher_kqueue_p.h b/src/corelib/io/qfilesystemwatcher_kqueue_p.h index eda646b..edc20ae 100644 --- a/src/corelib/io/qfilesystemwatcher_kqueue_p.h +++ b/src/corelib/io/qfilesystemwatcher_kqueue_p.h @@ -60,6 +60,7 @@ #include <QtCore/qthread.h> #include <QtCore/qvector.h> +#ifndef QT_NO_FILESYSTEMWATCHER struct kevent; QT_BEGIN_NAMESPACE @@ -92,4 +93,5 @@ private: QT_END_NAMESPACE +#endif //QT_NO_FILESYSTEMWATCHER #endif // FILEWATCHER_KQUEUE_P_H diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index 249ce0f..71df3c2 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -86,7 +86,8 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths, while (it.hasNext()) { QString path = it.next(); QString normalPath = path; - if ((normalPath.endsWith(QLatin1Char('/')) || normalPath.endsWith(QLatin1Char('\\'))) + if ((normalPath.endsWith(QLatin1Char('/')) && !normalPath.endsWith(QLatin1String(":/"))) + || (normalPath.endsWith(QLatin1Char('\\')) && !normalPath.endsWith(QLatin1String(":\\"))) #ifdef Q_OS_WINCE && normalPath.size() > 1) #else diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index a1ffb81..62b9981 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -152,7 +152,7 @@ QString QFSFileEnginePrivate::canonicalized(const QString &path) // ... but Linux with uClibc does not have it #if !defined(__UCLIBC__) char *ret = 0; -#if defined(Q_OS_MAC) +#if defined(Q_OS_MAC) && !defined(QT_NO_CORESERVICES) // Mac OS X 10.5.x doesn't support the realpath(X,0) extension we use here. if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) { ret = realpath(path.toLocal8Bit().constData(), (char*)0); @@ -189,9 +189,15 @@ QString QFSFileEnginePrivate::canonicalized(const QString &path) known.insert(path); do { #ifdef Q_OS_WIN - // UNC, skip past the first two elements - if (separatorPos == 0 && tmpPath.startsWith(QLatin1String("//"))) - separatorPos = tmpPath.indexOf(slash, 2); + if (separatorPos == 0) { + if (tmpPath.size() >= 2 && tmpPath.at(0) == slash && tmpPath.at(1) == slash) { + // UNC, skip past the first two elements + separatorPos = tmpPath.indexOf(slash, 2); + } else if (tmpPath.size() >= 3 && tmpPath.at(1) == QLatin1Char(':') && tmpPath.at(2) == slash) { + // volume root, skip since it can not be a symlink + separatorPos = 2; + } + } if (separatorPos != -1) #endif separatorPos = tmpPath.indexOf(slash, separatorPos + 1); @@ -208,6 +214,8 @@ QString QFSFileEnginePrivate::canonicalized(const QString &path) fi.setFile(prefix); if (fi.isSymLink()) { QString target = fi.symLinkTarget(); + if(QFileInfo(target).isRelative()) + target = fi.absolutePath() + slash + target; if (separatorPos != -1) { if (fi.isDir() && !target.endsWith(slash)) target.append(slash); diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 69e9219..03e7283 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -739,7 +739,7 @@ static bool _q_isSymbianHidden(const QString &path, bool isDir) } #endif -#if !defined(QWS) && defined(Q_OS_MAC) +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) static bool _q_isMacHidden(const QString &path) { OSErr err = noErr; @@ -824,7 +824,7 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const if (exists && (type & PermsMask)) ret |= d->getPermissions(type); if (type & TypesMask) { -#if !defined(QWS) && defined(Q_OS_MAC) +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) bool foundAlias = false; { FSRef fref; @@ -878,8 +878,11 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const } else { QString baseName = fileName(BaseName); if ((baseName.size() > 0 && baseName.at(0) == QLatin1Char('.')) -# if !defined(QWS) && defined(Q_OS_MAC) +# if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) || _q_isMacHidden(d->filePath) +# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + || d->st.st_flags & UF_HIDDEN +# endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 # endif ) { ret |= HiddenFlag; @@ -1089,7 +1092,8 @@ QString QFSFileEngine::fileName(FileName file) const int size = PATH_CHUNK_SIZE; while (1) { - s = q_check_ptr((char *) ::realloc(s, size)); + s = (char *) ::realloc(s, size); + Q_CHECK_PTR(s); len = ::readlink(d->nativeFilePath.constData(), s, size); if (len < 0) { ::free(s); @@ -1133,7 +1137,7 @@ QString QFSFileEngine::fileName(FileName file) const return ret; } } -#if !defined(QWS) && defined(Q_OS_MAC) +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) { FSRef fref; if (FSPathMakeRef((const UInt8 *)QFile::encodeName(QDir::cleanPath(d->filePath)).data(), &fref, 0) == noErr) { diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index d5c53bb..71b10b4 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -69,6 +69,14 @@ #define SECURITY_WIN32 #include <security.h> +#ifndef SPI_GETPLATFORMTYPE +#define SPI_GETPLATFORMTYPE 257 +#endif + +#ifndef PATH_MAX +#define PATH_MAX FILENAME_MAX +#endif + #ifndef _INTPTR_T_DEFINED #ifdef _WIN64 typedef __int64 intptr_t; @@ -155,6 +163,8 @@ static TRUSTEE_W worldTrusteeW; typedef BOOL (WINAPI *PtrGetUserProfileDirectoryW)(HANDLE, LPWSTR, LPDWORD); static PtrGetUserProfileDirectoryW ptrGetUserProfileDirectoryW = 0; +typedef BOOL (WINAPI *PtrGetVolumePathNamesForVolumeNameW)(LPCWSTR,LPWSTR,DWORD,PDWORD); +static PtrGetVolumePathNamesForVolumeNameW ptrGetVolumePathNamesForVolumeNameW = 0; QT_END_INCLUDE_NAMESPACE @@ -213,6 +223,9 @@ void QFSFileEnginePrivate::resolveLibs() HINSTANCE userenvHnd = QSystemLibrary::load(L"userenv"); if (userenvHnd) ptrGetUserProfileDirectoryW = (PtrGetUserProfileDirectoryW)GetProcAddress(userenvHnd, "GetUserProfileDirectoryW"); + HINSTANCE kernel32 = LoadLibrary(L"kernel32"); + if(kernel32) + ptrGetVolumePathNamesForVolumeNameW = (PtrGetVolumePathNamesForVolumeNameW)GetProcAddress(kernel32, "GetVolumePathNamesForVolumeNameW"); #endif } } @@ -1286,7 +1299,12 @@ static QString readSymLink(const QString &link) REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER*)qMalloc(bufsize); DWORD retsize = 0; if (::DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, 0, 0, rdb, bufsize, &retsize, 0)) { - if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { + if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { + int length = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t); + int offset = rdb->MountPointReparseBuffer.SubstituteNameOffset / sizeof(wchar_t); + const wchar_t* PathBuffer = &rdb->MountPointReparseBuffer.PathBuffer[offset]; + result = QString::fromWCharArray(PathBuffer, length); + } else if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { int length = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t); int offset = rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t); const wchar_t* PathBuffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[offset]; @@ -1298,6 +1316,20 @@ static QString readSymLink(const QString &link) } qFree(rdb); CloseHandle(handle); + +#if !defined(QT_NO_LIBRARY) + QFSFileEnginePrivate::resolveLibs(); + if (ptrGetVolumePathNamesForVolumeNameW) { + QRegExp matchVolName(QLatin1String("^Volume\\{([a-z]|[0-9]|-)+\\}\\\\"), Qt::CaseInsensitive); + if(matchVolName.indexIn(result) == 0) { + DWORD len; + wchar_t buffer[MAX_PATH]; + QString volumeName = result.mid(0, matchVolName.matchedLength()).prepend(QLatin1String("\\\\?\\")); + if(ptrGetVolumePathNamesForVolumeNameW((wchar_t*)volumeName.utf16(), buffer, MAX_PATH, &len) != 0) + result.replace(0,matchVolName.matchedLength(), QString::fromWCharArray(buffer)); + } + } +#endif } #else Q_UNUSED(link); @@ -1549,7 +1581,7 @@ bool QFSFileEnginePrivate::isSymlink() const if (hFind != INVALID_HANDLE_VALUE) { ::FindClose(hFind); if ((findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) - && findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK) { + && (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK || findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT)) { is_link = true; } } @@ -1649,10 +1681,12 @@ QString QFSFileEngine::fileName(FileName file) const if (!isRelativePath()) { #if !defined(Q_OS_WINCE) - if ((d->filePath.size() > 2 && d->filePath.at(1) == QLatin1Char(':') - && d->filePath.at(2) != QLatin1Char('/')) || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt - d->filePath.startsWith(QLatin1Char('/')) // It's a absolute path to the current drive, so \a.txt -> Z:\a.txt - ) { + if (d->filePath.startsWith(QLatin1Char('/')) || // It's a absolute path to the current drive, so \a.txt -> Z:\a.txt + d->filePath.size() == 2 || // It's a drive letter that needs to get a working dir appended + (d->filePath.size() > 2 && d->filePath.at(2) != QLatin1Char('/')) || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt + d->filePath.contains(QLatin1String("/../")) || d->filePath.contains(QLatin1String("/./")) || + d->filePath.endsWith(QLatin1String("/..")) || d->filePath.endsWith(QLatin1String("/."))) + { ret = QDir::fromNativeSeparators(nativeAbsoluteFilePath(d->filePath)); } else { ret = d->filePath; diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 26e587d..8544fba 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -1633,6 +1633,12 @@ QString QIODevice::errorString() const This function is called by QIODevice. Reimplement this function when creating a subclass of QIODevice. + When reimplementing this function it is important that this function + reads all the required data before returning. This is required in order + for QDataStream to be able to operate on the class. QDataStream assumes + all the requested information was read and therefore does not retry reading + if there was a problem. + \sa read() readLine() writeData() */ @@ -1645,6 +1651,12 @@ QString QIODevice::errorString() const This function is called by QIODevice. Reimplement this function when creating a subclass of QIODevice. + When reimplementing this function it is important that this function + writes all the data available before returning. This is required in order + for QDataStream to be able to operate on the class. QDataStream assumes + all the information was written and therefore does not retry writing if + there was a problem. + \sa read() write() */ diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index ce9c57e..98b1dcc 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -580,7 +580,7 @@ QResource::addSearchPath(const QString &path) \obsolete Use QDir::searchPaths() instead. - + Returns the current search path list. This list is consulted when creating a relative resource. @@ -928,7 +928,7 @@ public: } }; -#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) +#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) && ! defined (Q_OS_NACL) #define QT_USE_MMAP #endif @@ -1185,21 +1185,6 @@ QResource::unregisterResource(const uchar *rccData, const QString &resourceRoot) return false; } -//file type handler -class QResourceFileEngineHandler : public QAbstractFileEngineHandler -{ -public: - QResourceFileEngineHandler() { } - ~QResourceFileEngineHandler() { } - QAbstractFileEngine *create(const QString &path) const; -}; -QAbstractFileEngine *QResourceFileEngineHandler::create(const QString &path) const -{ - if (path.size() > 0 && path.startsWith(QLatin1Char(':'))) - return new QResourceFileEngine(path); - return 0; -} - //resource engine class QResourceFileEnginePrivate : public QAbstractFileEnginePrivate { @@ -1506,12 +1491,6 @@ bool QResourceFileEnginePrivate::unmap(uchar *ptr) return true; } -//Initialization and cleanup -Q_GLOBAL_STATIC(QResourceFileEngineHandler, resource_file_handler) - -static int qt_force_resource_init() { resource_file_handler(); return 1; } -Q_CORE_EXPORT void qInitResourceIO() { resource_file_handler(); } -static int qt_forced_resource_init = qt_force_resource_init(); -Q_CONSTRUCTOR_FUNCTION(qt_force_resource_init) +Q_CORE_EXPORT void qInitResourceIO() { } // ### Qt 5: remove QT_END_NAMESPACE diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index e6c5fb9..7235459 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -258,9 +258,7 @@ bool QConfFile::isWritable() const } else { // Create the directories to the file. QDir dir(fileInfo.absolutePath()); - if (dir.exists() && dir.isReadable()) { - return true; - } else { + if (!dir.exists()) { if (!dir.mkpath(dir.absolutePath())) return false; } @@ -1132,7 +1130,7 @@ static void initDefaultPaths(QMutexLocker *locker) if (env == 0) { userPath = homePath; userPath += QLatin1Char('/'); -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) userPath += QLatin1String("Settings"); #else userPath += QLatin1String(".config"); diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h index ec345be..5ff4d96 100644 --- a/src/corelib/io/qsettings_p.h +++ b/src/corelib/io/qsettings_p.h @@ -70,7 +70,7 @@ QT_BEGIN_NAMESPACE -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) #define QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER #endif diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 6a3037d..6ec5562 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -965,14 +965,14 @@ static void QT_FASTCALL _fragment(const char **ptr, QUrlParseData *parseData) } struct NameprepCaseFoldingEntry { - int uc; + uint uc; ushort mapping[4]; }; -inline bool operator<(int one, const NameprepCaseFoldingEntry &other) +inline bool operator<(uint one, const NameprepCaseFoldingEntry &other) { return one < other.uc; } -inline bool operator<(const NameprepCaseFoldingEntry &one, int other) +inline bool operator<(const NameprepCaseFoldingEntry &one, uint other) { return one.uc < other; } static const NameprepCaseFoldingEntry NameprepCaseFolding[] = { @@ -1861,45 +1861,44 @@ static const NameprepCaseFoldingEntry NameprepCaseFolding[] = { { 0xFF38, { 0xFF58, 0x0000, 0x0000, 0x0000 } }, { 0xFF39, { 0xFF59, 0x0000, 0x0000, 0x0000 } }, { 0xFF3A, { 0xFF5A, 0x0000, 0x0000, 0x0000 } }, - // ##### -/* { 0x10400, { 0x10428, 0x0000, 0x0000, 0x0000 } }, - { 0x10401, { 0x10429, 0x0000, 0x0000, 0x0000 } }, - { 0x10402, { 0x1042A, 0x0000, 0x0000, 0x0000 } }, - { 0x10403, { 0x1042B, 0x0000, 0x0000, 0x0000 } }, - { 0x10404, { 0x1042C, 0x0000, 0x0000, 0x0000 } }, - { 0x10405, { 0x1042D, 0x0000, 0x0000, 0x0000 } }, - { 0x10406, { 0x1042E, 0x0000, 0x0000, 0x0000 } }, - { 0x10407, { 0x1042F, 0x0000, 0x0000, 0x0000 } }, - { 0x10408, { 0x10430, 0x0000, 0x0000, 0x0000 } }, - { 0x10409, { 0x10431, 0x0000, 0x0000, 0x0000 } }, - { 0x1040A, { 0x10432, 0x0000, 0x0000, 0x0000 } }, - { 0x1040B, { 0x10433, 0x0000, 0x0000, 0x0000 } }, - { 0x1040C, { 0x10434, 0x0000, 0x0000, 0x0000 } }, - { 0x1040D, { 0x10435, 0x0000, 0x0000, 0x0000 } }, - { 0x1040E, { 0x10436, 0x0000, 0x0000, 0x0000 } }, - { 0x1040F, { 0x10437, 0x0000, 0x0000, 0x0000 } }, - { 0x10410, { 0x10438, 0x0000, 0x0000, 0x0000 } }, - { 0x10411, { 0x10439, 0x0000, 0x0000, 0x0000 } }, - { 0x10412, { 0x1043A, 0x0000, 0x0000, 0x0000 } }, - { 0x10413, { 0x1043B, 0x0000, 0x0000, 0x0000 } }, - { 0x10414, { 0x1043C, 0x0000, 0x0000, 0x0000 } }, - { 0x10415, { 0x1043D, 0x0000, 0x0000, 0x0000 } }, - { 0x10416, { 0x1043E, 0x0000, 0x0000, 0x0000 } }, - { 0x10417, { 0x1043F, 0x0000, 0x0000, 0x0000 } }, - { 0x10418, { 0x10440, 0x0000, 0x0000, 0x0000 } }, - { 0x10419, { 0x10441, 0x0000, 0x0000, 0x0000 } }, - { 0x1041A, { 0x10442, 0x0000, 0x0000, 0x0000 } }, - { 0x1041B, { 0x10443, 0x0000, 0x0000, 0x0000 } }, - { 0x1041C, { 0x10444, 0x0000, 0x0000, 0x0000 } }, - { 0x1041D, { 0x10445, 0x0000, 0x0000, 0x0000 } }, - { 0x1041E, { 0x10446, 0x0000, 0x0000, 0x0000 } }, - { 0x1041F, { 0x10447, 0x0000, 0x0000, 0x0000 } }, - { 0x10420, { 0x10448, 0x0000, 0x0000, 0x0000 } }, - { 0x10421, { 0x10449, 0x0000, 0x0000, 0x0000 } }, - { 0x10422, { 0x1044A, 0x0000, 0x0000, 0x0000 } }, - { 0x10423, { 0x1044B, 0x0000, 0x0000, 0x0000 } }, - { 0x10424, { 0x1044C, 0x0000, 0x0000, 0x0000 } }, - { 0x10425, { 0x1044D, 0x0000, 0x0000, 0x0000 } },*/ + { 0x10400, { 0xd801, 0xdc28, 0x0000, 0x0000 } }, + { 0x10401, { 0xd801, 0xdc29, 0x0000, 0x0000 } }, + { 0x10402, { 0xd801, 0xdc2A, 0x0000, 0x0000 } }, + { 0x10403, { 0xd801, 0xdc2B, 0x0000, 0x0000 } }, + { 0x10404, { 0xd801, 0xdc2C, 0x0000, 0x0000 } }, + { 0x10405, { 0xd801, 0xdc2D, 0x0000, 0x0000 } }, + { 0x10406, { 0xd801, 0xdc2E, 0x0000, 0x0000 } }, + { 0x10407, { 0xd801, 0xdc2F, 0x0000, 0x0000 } }, + { 0x10408, { 0xd801, 0xdc30, 0x0000, 0x0000 } }, + { 0x10409, { 0xd801, 0xdc31, 0x0000, 0x0000 } }, + { 0x1040A, { 0xd801, 0xdc32, 0x0000, 0x0000 } }, + { 0x1040B, { 0xd801, 0xdc33, 0x0000, 0x0000 } }, + { 0x1040C, { 0xd801, 0xdc34, 0x0000, 0x0000 } }, + { 0x1040D, { 0xd801, 0xdc35, 0x0000, 0x0000 } }, + { 0x1040E, { 0xd801, 0xdc36, 0x0000, 0x0000 } }, + { 0x1040F, { 0xd801, 0xdc37, 0x0000, 0x0000 } }, + { 0x10410, { 0xd801, 0xdc38, 0x0000, 0x0000 } }, + { 0x10411, { 0xd801, 0xdc39, 0x0000, 0x0000 } }, + { 0x10412, { 0xd801, 0xdc3A, 0x0000, 0x0000 } }, + { 0x10413, { 0xd801, 0xdc3B, 0x0000, 0x0000 } }, + { 0x10414, { 0xd801, 0xdc3C, 0x0000, 0x0000 } }, + { 0x10415, { 0xd801, 0xdc3D, 0x0000, 0x0000 } }, + { 0x10416, { 0xd801, 0xdc3E, 0x0000, 0x0000 } }, + { 0x10417, { 0xd801, 0xdc3F, 0x0000, 0x0000 } }, + { 0x10418, { 0xd801, 0xdc40, 0x0000, 0x0000 } }, + { 0x10419, { 0xd801, 0xdc41, 0x0000, 0x0000 } }, + { 0x1041A, { 0xd801, 0xdc42, 0x0000, 0x0000 } }, + { 0x1041B, { 0xd801, 0xdc43, 0x0000, 0x0000 } }, + { 0x1041C, { 0xd801, 0xdc44, 0x0000, 0x0000 } }, + { 0x1041D, { 0xd801, 0xdc45, 0x0000, 0x0000 } }, + { 0x1041E, { 0xd801, 0xdc46, 0x0000, 0x0000 } }, + { 0x1041F, { 0xd801, 0xdc47, 0x0000, 0x0000 } }, + { 0x10420, { 0xd801, 0xdc48, 0x0000, 0x0000 } }, + { 0x10421, { 0xd801, 0xdc49, 0x0000, 0x0000 } }, + { 0x10422, { 0xd801, 0xdc4A, 0x0000, 0x0000 } }, + { 0x10423, { 0xd801, 0xdc4B, 0x0000, 0x0000 } }, + { 0x10424, { 0xd801, 0xdc4C, 0x0000, 0x0000 } }, + { 0x10425, { 0xd801, 0xdc4D, 0x0000, 0x0000 } }, { 0x1D400, { 0x0061, 0x0000, 0x0000, 0x0000 } }, { 0x1D401, { 0x0062, 0x0000, 0x0000, 0x0000 } }, { 0x1D402, { 0x0063, 0x0000, 0x0000, 0x0000 } }, @@ -2354,17 +2353,23 @@ static void mapToLowerCase(QString *str, int from) { int N = sizeof(NameprepCaseFolding) / sizeof(NameprepCaseFolding[0]); - QChar *d = 0; + ushort *d = 0; for (int i = from; i < str->size(); ++i) { - int uc = str->at(i).unicode(); + uint uc = str->at(i).unicode(); if (uc < 0x80) { if (uc <= 'Z' && uc >= 'A') { - uc |= 0x20; if (!d) - d = str->data(); - d[i] = QChar(uc); + d = reinterpret_cast<ushort *>(str->data()); + d[i] = (uc | 0x20); } } else { + if (QChar(uc).isHighSurrogate() && i < str->size() - 1) { + ushort low = str->at(i + 1).unicode(); + if (QChar(low).isLowSurrogate()) { + uc = QChar::surrogateToUcs4(uc, low); + ++i; + } + } const NameprepCaseFoldingEntry *entry = qBinaryFind(NameprepCaseFolding, NameprepCaseFolding + N, uc); @@ -2373,23 +2378,26 @@ static void mapToLowerCase(QString *str, int from) while (l < 4 && entry->mapping[l]) ++l; if (l > 1) { - str->replace(i, 1, (const QChar *)&entry->mapping[0], l); + if (uc <= 0xffff) + str->replace(i, 1, reinterpret_cast<const QChar *>(&entry->mapping[0]), l); + else + str->replace(i-1, 2, reinterpret_cast<const QChar *>(&entry->mapping[0]), l); d = 0; } else { if (!d) - d = str->data(); - d[i] = QChar(entry->mapping[0]); + d = reinterpret_cast<ushort *>(str->data()); + d[i] = entry->mapping[0]; } } } } } -static bool isMappedToNothing(const QChar &ch) +static bool isMappedToNothing(uint uc) { - if (ch.unicode() < 0xad) + if (uc < 0xad) return false; - switch (ch.unicode()) { + switch (uc) { case 0x00AD: case 0x034F: case 0x1806: case 0x180B: case 0x180C: case 0x180D: case 0x200B: case 0x200C: case 0x200D: case 0x2060: case 0xFE00: case 0xFE01: case 0xFE02: case 0xFE03: case 0xFE04: case 0xFE05: case 0xFE06: case 0xFE07: @@ -2408,66 +2416,72 @@ static void stripProhibitedOutput(QString *str, int from) const ushort *in = out; const ushort *end = (ushort *)str->data() + str->size(); while (in < end) { - ushort uc = *in; - if (uc < 0x80 || - !(uc <= 0x009F - || uc == 0x00A0 - || uc == 0x0340 - || uc == 0x0341 - || uc == 0x06DD - || uc == 0x070F - || uc == 0x1680 - || uc == 0x180E - || (uc >= 0x2000 && uc <= 0x200B) - || uc == 0x200C - || uc == 0x200D - || uc == 0x200E - || uc == 0x200F - || (uc >= 0x2028 && uc <= 0x202F) - || uc == 0x205F - || (uc >= 0x2060 && uc <= 0x2063) - || uc == 0x206A - || (uc >= 0x206A && uc <= 0x206F) - || (uc >= 0x2FF0 && uc <= 0x2FFB) - || uc == 0x3000 - || (uc >= 0xD800 && uc <= 0xDFFF) - || (uc >= 0xE000 && uc <= 0xF8FF) - || (uc >= 0xFDD0 && uc <= 0xFDEF) - || uc == 0xFEFF - || (uc >= 0xFFF9 && uc <= 0xFFFC) - || (uc >= 0xFFFA && (uc <= 0xFFFE || uc == 0xFFFF)) - /* ### Add NAMEPREP support for surrogates - || uc == 0xE0001 - || (uc >= 0x2FFFE && uc <= 0x2FFFF) - || (uc >= 0x1D173 && uc <= 0x1D17A) - || (uc >= 0x1FFFE && uc <= 0x1FFFF) - || (uc >= 0x3FFFE && uc <= 0x3FFFF) - || (uc >= 0x4FFFE && uc <= 0x4FFFF) - || (uc >= 0x5FFFE && uc <= 0x5FFFF) - || (uc >= 0x6FFFE && uc <= 0x6FFFF) - || (uc >= 0x7FFFE && uc <= 0x7FFFF) - || (uc >= 0x8FFFE && uc <= 0x8FFFF) - || (uc >= 0x9FFFE && uc <= 0x9FFFF) - || (uc >= 0xAFFFE && uc <= 0xAFFFF) - || (uc >= 0xBFFFE && uc <= 0xBFFFF) - || (uc >= 0xCFFFE && uc <= 0xCFFFF) - || (uc >= 0xDFFFE && uc <= 0xDFFFF) - || (uc >= 0xE0020 && uc <= 0xE007F) - || (uc >= 0xEFFFE && uc <= 0xEFFFF) - || (uc >= 0xF0000 && uc <= 0xFFFFD) - || (uc >= 0xFFFFE && uc <= 0xFFFFF) - || (uc >= 0x100000 && uc <= 0x10FFFD) - || (uc >= 0x10FFFE && uc <= 0x10FFFF)*/)) - *out++ = *in; + uint uc = *in; + if (QChar(uc).isHighSurrogate() && in < end - 1) { + ushort low = *(in + 1); + if (QChar(low).isLowSurrogate()) { + ++in; + uc = QChar::surrogateToUcs4(uc, low); + } + } + if (uc <= 0xFFFF) { + if (uc < 0x80 || + !(uc <= 0x009F + || uc == 0x00A0 + || uc == 0x0340 + || uc == 0x0341 + || uc == 0x06DD + || uc == 0x070F + || uc == 0x1680 + || uc == 0x180E + || (uc >= 0x2000 && uc <= 0x200F) + || (uc >= 0x2028 && uc <= 0x202F) + || uc == 0x205F + || (uc >= 0x2060 && uc <= 0x2063) + || (uc >= 0x206A && uc <= 0x206F) + || (uc >= 0x2FF0 && uc <= 0x2FFB) + || uc == 0x3000 + || (uc >= 0xD800 && uc <= 0xDFFF) + || (uc >= 0xE000 && uc <= 0xF8FF) + || (uc >= 0xFDD0 && uc <= 0xFDEF) + || uc == 0xFEFF + || (uc >= 0xFFF9 && uc <= 0xFFFF))) { + *out++ = *in; + } + } else { + if (!((uc >= 0x1D173 && uc <= 0x1D17A) + || (uc >= 0x1FFFE && uc <= 0x1FFFF) + || (uc >= 0x2FFFE && uc <= 0x2FFFF) + || (uc >= 0x3FFFE && uc <= 0x3FFFF) + || (uc >= 0x4FFFE && uc <= 0x4FFFF) + || (uc >= 0x5FFFE && uc <= 0x5FFFF) + || (uc >= 0x6FFFE && uc <= 0x6FFFF) + || (uc >= 0x7FFFE && uc <= 0x7FFFF) + || (uc >= 0x8FFFE && uc <= 0x8FFFF) + || (uc >= 0x9FFFE && uc <= 0x9FFFF) + || (uc >= 0xAFFFE && uc <= 0xAFFFF) + || (uc >= 0xBFFFE && uc <= 0xBFFFF) + || (uc >= 0xCFFFE && uc <= 0xCFFFF) + || (uc >= 0xDFFFE && uc <= 0xDFFFF) + || uc == 0xE0001 + || (uc >= 0xE0020 && uc <= 0xE007F) + || (uc >= 0xEFFFE && uc <= 0xEFFFF) + || (uc >= 0xF0000 && uc <= 0xFFFFD) + || (uc >= 0xFFFFE && uc <= 0xFFFFF) + || (uc >= 0x100000 && uc <= 0x10FFFD) + || (uc >= 0x10FFFE && uc <= 0x10FFFF))) { + *out++ = QChar::highSurrogate(uc); + *out++ = QChar::lowSurrogate(uc); + } + } ++in; } if (in != out) str->truncate(out - str->utf16()); } -static bool isBidirectionalRorAL(const QChar &c) +static bool isBidirectionalRorAL(uint uc) { - ushort uc = c.unicode(); if (uc < 0x5b0) return false; return uc == 0x05BE @@ -2506,9 +2520,8 @@ static bool isBidirectionalRorAL(const QChar &c) || (uc >= 0xFE76 && uc <= 0xFEFC); } -static bool isBidirectionalL(const QChar &ch) +static bool isBidirectionalL(uint uc) { - ushort uc = ch.unicode(); if (uc < 0xaa) return (uc >= 0x0041 && uc <= 0x005A) || (uc >= 0x0061 && uc <= 0x007A); @@ -2873,8 +2886,7 @@ static bool isBidirectionalL(const QChar &ch) return true; } - /* ### Add NAMEPREP support for surrogates - || (uc >= 0x10300 && uc <= 0x1031E) + if ((uc >= 0x10300 && uc <= 0x1031E) || (uc >= 0x10320 && uc <= 0x10323) || (uc >= 0x10330 && uc <= 0x1034A) || (uc >= 0x10400 && uc <= 0x10425) @@ -2910,7 +2922,9 @@ static bool isBidirectionalL(const QChar &ch) || (uc >= 0x20000 && uc <= 0x2A6D6) || (uc >= 0x2F800 && uc <= 0x2FA1D) || (uc >= 0xF0000 && uc <= 0xFFFFD) - || (uc >= 0x100000 && uc <= 0x10FFFD)*/ + || (uc >= 0x100000 && uc <= 0x10FFFD)) { + return true; + } return false; } @@ -2943,13 +2957,37 @@ void qt_nameprep(QString *source, int from) return; // everything was mapped easily (lowercased, actually) int firstNonAscii = out - src; + // Characters unassigned in Unicode 3.2 are not allowed in "stored string" scheme + // but allowed in "query" scheme + // (Table A.1) + const bool isUnassignedAllowed = false; // ### // Characters commonly mapped to nothing are simply removed // (Table B.1) const QChar *in = out; - while (in < e) { - if (!isMappedToNothing(*in)) - *out++ = *in; - ++in; + for ( ; in < e; ++in) { + uint uc = in->unicode(); + if (QChar(uc).isHighSurrogate() && in < e - 1) { + ushort low = in[1].unicode(); + if (QChar(low).isLowSurrogate()) { + ++in; + uc = QChar::surrogateToUcs4(uc, low); + } + } + if (!isUnassignedAllowed) { + QChar::UnicodeVersion version = QChar::unicodeVersion(uc); + if (version == QChar::Unicode_Unassigned || version > QChar::Unicode_3_2) { + source->resize(from); // not allowed, clear the label + return; + } + } + if (!isMappedToNothing(uc)) { + if (uc <= 0xFFFF) { + *out++ = *in; + } else { + *out++ = QChar::highSurrogate(uc); + *out++ = QChar::lowSurrogate(uc); + } + } } if (out != in) source->truncate(out - src); @@ -2960,7 +2998,8 @@ void qt_nameprep(QString *source, int from) // Normalize to Unicode 3.2 form KC extern void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::UnicodeVersion version, int from); - qt_string_normalize(source, QString::NormalizationForm_KC, QChar::Unicode_3_2, firstNonAscii); + qt_string_normalize(source, QString::NormalizationForm_KC, QChar::Unicode_3_2, + firstNonAscii > from ? firstNonAscii - 1 : from); // Strip prohibited output stripProhibitedOutput(source, firstNonAscii); @@ -2971,14 +3010,22 @@ void qt_nameprep(QString *source, int from) src = source->data(); e = src + source->size(); for (in = src + from; in < e && (!containsLCat || !containsRandALCat); ++in) { - if (isBidirectionalL(*in)) + uint uc = in->unicode(); + if (QChar(uc).isHighSurrogate() && in < e - 1) { + ushort low = in[1].unicode(); + if (QChar(low).isLowSurrogate()) { + ++in; + uc = QChar::surrogateToUcs4(uc, low); + } + } + if (isBidirectionalL(uc)) containsLCat = true; - else if (isBidirectionalRorAL(*in)) + else if (isBidirectionalRorAL(uc)) containsRandALCat = true; } if (containsRandALCat) { - if (containsLCat || (!isBidirectionalRorAL(src[from]) - || !isBidirectionalRorAL(e[-1]))) + if (containsLCat || (!isBidirectionalRorAL(src[from].unicode()) + || !isBidirectionalRorAL(e[-1].unicode()))) source->resize(from); // not allowed, clear the label } } @@ -6001,6 +6048,14 @@ QUrl &QUrl::operator =(const QString &url) return *this; } +/*! + \fn void QUrl::swap(QUrl &other) + \since 4.8 + + Swaps URL \a other with this URL. This operation is very + fast and never fails. +*/ + /*! \internal Forces a detach. @@ -6023,19 +6078,22 @@ bool QUrl::isDetached() const /*! - Returns a QUrl representation of \a localFile, interpreted as a - local file. + Returns a QUrl representation of \a localFile, interpreted as a local + file. This function accepts paths separated by slashes as well as the + native separator for this platform. + + This function also accepts paths with a doubled leading slash (or + backslash) to indicate a remote file, as in + "//servername/path/to/file.txt". Note that only certain platforms can + actually open this file using QFile::open(). - \sa toLocalFile() + \sa toLocalFile(), isLocalFile(), QDir::toNativeSeparators */ QUrl QUrl::fromLocalFile(const QString &localFile) { QUrl url; url.setScheme(QLatin1String("file")); - QString deslashified = localFile; - deslashified.replace(QLatin1Char('\\'), QLatin1Char('/')); - - + QString deslashified = QDir::fromNativeSeparators(localFile); // magic for drives on windows if (deslashified.length() > 1 && deslashified.at(1) == QLatin1Char(':') && deslashified.at(0) != QLatin1Char('/')) { @@ -6054,35 +6112,61 @@ QUrl QUrl::fromLocalFile(const QString &localFile) } /*! - Returns the path of this URL formatted as a local file path. + Returns the path of this URL formatted as a local file path. The path + returned will use forward slashes, even if it was originally created + from one with backslashes. + + If this URL contains a non-empty hostname, it will be encoded in the + returned value in the form found on SMB networks (for example, + "//servername/path/to/file.txt"). - \sa fromLocalFile() + \sa fromLocalFile(), isLocalFile() */ QString QUrl::toLocalFile() const { - if (!d) return QString(); - if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); + // the call to isLocalFile() also ensures that we're parsed + if (!isLocalFile()) + return QString(); QString tmp; QString ourPath = path(); - if (d->scheme.isEmpty() || QString::compare(d->scheme, QLatin1String("file"), Qt::CaseInsensitive) == 0) { - // magic for shared drive on windows - if (!d->host.isEmpty()) { - tmp = QLatin1String("//") + d->host + (ourPath.length() > 0 && ourPath.at(0) != QLatin1Char('/') - ? QLatin1Char('/') + ourPath : ourPath); - } else { - tmp = ourPath; - // magic for drives on windows - if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':')) - tmp.remove(0, 1); - } + // magic for shared drive on windows + if (!d->host.isEmpty()) { + tmp = QLatin1String("//") + d->host + (ourPath.length() > 0 && ourPath.at(0) != QLatin1Char('/') + ? QLatin1Char('/') + ourPath : ourPath); + } else { + tmp = ourPath; + // magic for drives on windows + if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':')) + tmp.remove(0, 1); } return tmp; } /*! + \since 4.7 + Returns true if this URL is pointing to a local file path. A URL is a + local file path if the scheme is "file". + + Note that this function considers URLs with hostnames to be local file + paths, even if the eventual file path cannot be opened with + QFile::open(). + + \sa fromLocalFile(), toLocalFile() +*/ +bool QUrl::isLocalFile() const +{ + if (!d) return false; + if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); + + if (d->scheme.compare(QLatin1String("file"), Qt::CaseInsensitive) != 0) + return false; // not file + return true; +} + +/*! Returns true if this URL is a parent of \a childUrl. \a childUrl is a child of this URL if the two URLs share the same scheme and authority, and this URL's path is a parent of the path of \a childUrl. diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h index 6f8331a..63fe98d 100644 --- a/src/corelib/io/qurl.h +++ b/src/corelib/io/qurl.h @@ -94,8 +94,14 @@ public: #ifndef QT_NO_URL_CAST_FROM_STRING QUrl &operator =(const QString &url); #endif +#ifdef Q_COMPILER_RVALUE_REFS + inline QUrl &operator=(QUrl &&other) + { qSwap(d, other.d); return *this; } +#endif ~QUrl(); + inline void swap(QUrl &other) { qSwap(d, other.d); } + void setUrl(const QString &url); void setUrl(const QString &url, ParsingMode mode); // ### Qt 5: merge the two setUrl() functions, with mode = TolerantMode @@ -183,6 +189,7 @@ public: static QUrl fromLocalFile(const QString &localfile); QString toLocalFile() const; + bool isLocalFile() const; QString toString(FormattingOptions options = None) const; diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 1851e04..1e27c31 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -78,12 +78,12 @@ wince*: { kernel/qfunctions_wince.h } -mac:!embedded { +mac:!embedded:!qpa{ SOURCES += \ kernel/qcoreapplication_mac.cpp } -mac { +mac:!nacl { SOURCES += \ kernel/qcore_mac.cpp } diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 589d304..7e1ed9d 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -532,7 +532,7 @@ bool QAbstractItemModelPrivate::variantLessThan(const QVariant &v1, const QVaria case 1: //floating point return v1.toReal() < v2.toReal(); default: - return v1.toString() < v2.toString(); + return v1.toString().localeAwareCompare(v2.toString()) < 0; } } diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index 9591f08..22b6a36 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -68,7 +68,15 @@ # undef qDebug #endif +#if defined(QT_BUILD_QMAKE) || defined(QT_BOOTSTRAPPED) #include <ApplicationServices/ApplicationServices.h> +#else +#include <CoreFoundation/CoreFoundation.h> +#endif + +#ifndef QT_NO_CORESERVICES +#include <CoreServices/CoreServices.h> +#endif #undef DEBUG #ifdef OLD_DEBUG diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp index 66296b0..df1c1ef 100644 --- a/src/corelib/kernel/qcore_symbian_p.cpp +++ b/src/corelib/kernel/qcore_symbian_p.cpp @@ -61,7 +61,8 @@ Q_CORE_EXPORT HBufC* qt_QString2HBufC(const QString& aString) #else TPtrC16 ptr(qt_QString2TPtrC(aString)); #endif - buffer = q_check_ptr(HBufC::New(ptr.Length())); + buffer = HBufC::New(ptr.Length()); + Q_CHECK_PTR(buffer); buffer->Des().Copy(ptr); return buffer; } @@ -81,8 +82,9 @@ QHBufC::QHBufC() } QHBufC::QHBufC(const QHBufC &src) - : m_hBufC(q_check_ptr(src.m_hBufC->Alloc())) + : m_hBufC(src.m_hBufC->Alloc()) { + Q_CHECK_PTR(m_hBufC); } /*! diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp index e0d92c0..685576b 100644 --- a/src/corelib/kernel/qcore_unix.cpp +++ b/src/corelib/kernel/qcore_unix.cpp @@ -42,7 +42,8 @@ #include "qcore_unix_p.h" #include "qelapsedtimer.h" -#ifndef Q_OS_VXWORKS +#ifdef Q_OS_NACL +#elif !defined (Q_OS_VXWORKS) # if !defined(Q_OS_HPUX) || defined(__ia64) # include <sys/select.h> # endif diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index d3f399b..e967884 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -122,6 +122,11 @@ static SystemDriveFunc PtrGetSystemDrive=0; extern QString qAppFileName(); #endif +int QCoreApplicationPrivate::app_compile_version = 0x040000; //we don't know exactly, but it's at least 4.0.0 +#if defined(QT3_SUPPORT) +bool QCoreApplicationPrivate::useQt3Support = true; +#endif + #if !defined(Q_OS_WIN) #ifdef Q_OS_MAC QString QCoreApplicationPrivate::macMenuBarName() @@ -263,10 +268,14 @@ struct QCoreApplicationData { Q_GLOBAL_STATIC(QCoreApplicationData, coreappdata) -QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv) +QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint flags) : QObjectPrivate(), argc(aargc), argv(aargv), application_type(0), eventFilter(0), in_exec(false), aboutToQuitEmitted(false) { + app_compile_version = flags & 0xffffff; +#if defined(QT3_SUPPORT) + useQt3Support = !(flags & 0x01000000); +#endif static const char *const empty = ""; if (argc == 0 || argv == 0) { argc = 0; @@ -511,7 +520,7 @@ void QCoreApplication::flush() one valid character string. */ QCoreApplication::QCoreApplication(int &argc, char **argv) - : QObject(*new QCoreApplicationPrivate(argc, argv)) + : QObject(*new QCoreApplicationPrivate(argc, argv, 0x040000)) { init(); QCoreApplicationPrivate::eventDispatcher->startingUp(); @@ -527,6 +536,25 @@ QCoreApplication::QCoreApplication(int &argc, char **argv) #endif } +QCoreApplication::QCoreApplication(int &argc, char **argv, int _internal) +: QObject(*new QCoreApplicationPrivate(argc, argv, _internal)) +{ + init(); + QCoreApplicationPrivate::eventDispatcher->startingUp(); +#if defined(Q_OS_SYMBIAN) +#ifndef QT_NO_LIBRARY + // Refresh factoryloader, as text codecs are requested during lib path + // resolving process and won't be therefore properly loaded. + // Unknown if this is symbian specific issue. + QFactoryLoader::refreshAll(); +#endif +#ifndef QT_NO_SYSTEMLOCALE + d_func()->symbianInit(); +#endif +#endif //Q_OS_SYMBIAN +} + + // ### move to QCoreApplicationPrivate constructor? void QCoreApplication::init() { @@ -805,11 +833,6 @@ bool QCoreApplication::notify(QObject *receiver, QEvent *event) d->checkReceiverThread(receiver); #endif -#ifdef QT3_SUPPORT - if (event->type() == QEvent::ChildRemoved && !receiver->d_func()->pendingChildInsertedEvents.isEmpty()) - receiver->d_func()->removePendingChildInsertedEvents(static_cast<QChildEvent *>(event)->child()); -#endif // QT3_SUPPORT - return receiver->isWidgetType() ? false : d->notify_helper(receiver, event); } @@ -1019,6 +1042,7 @@ int QCoreApplication::exec() return returnCode; } + /*! Tells the application to exit with a return code. @@ -1475,7 +1499,7 @@ void QCoreApplication::removePostedEvents(QObject *receiver, int eventType) --pe.receiver->d_func()->postedEvents; #ifdef QT3_SUPPORT if (pe.event->type() == QEvent::ChildInsertedRequest) - pe.receiver->d_func()->removePendingChildInsertedEvents(0); + pe.receiver->d_func()->pendingChildInsertedEvents.clear(); #endif pe.event->posted = false; events.append(pe.event); diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h index d87103e..f1c7c26 100644 --- a/src/corelib/kernel/qcoreapplication.h +++ b/src/corelib/kernel/qcoreapplication.h @@ -78,7 +78,23 @@ class Q_CORE_EXPORT QCoreApplication : public QObject Q_DECLARE_PRIVATE(QCoreApplication) public: - QCoreApplication(int &argc, char **argv); + enum { ApplicationFlags = QT_VERSION +#if !defined(QT3_SUPPORT) + | 0x01000000 +#endif + }; + +#if defined(QT_BUILD_CORE_LIB) || defined(qdoc) + QCoreApplication(int &argc, char **argv); // ### Qt5 remove +#endif +#if !defined(qdoc) + QCoreApplication(int &argc, char **argv, int +#if !defined(QT_BUILD_CORE_LIB) + = ApplicationFlags +#endif + ); +#endif + ~QCoreApplication(); #ifdef QT_DEPRECATED diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index e066137..2355c37 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -75,7 +75,7 @@ class Q_CORE_EXPORT QCoreApplicationPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QCoreApplication) public: - QCoreApplicationPrivate(int &aargc, char **aargv); + QCoreApplicationPrivate(int &aargc, char **aargv, uint flags); ~QCoreApplicationPrivate(); bool sendThroughApplicationEventFilters(QObject *, QEvent *); @@ -129,6 +129,10 @@ public: static uint attribs; static inline bool testAttribute(uint flag) { return attribs & (1 << flag); } + static int app_compile_version; +#if defined(QT3_SUPPORT) + static bool useQt3Support; +#endif }; QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index 9d3513a..4c91aaf 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -328,6 +328,7 @@ private: friend class QETWidget; friend class QGraphicsView; friend class QGraphicsViewPrivate; + friend class QGraphicsScene; friend class QGraphicsScenePrivate; #ifndef QT_NO_GESTURES friend class QGestureManager; diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp index 8390275..e5136f9 100644 --- a/src/corelib/kernel/qeventdispatcher_glib.cpp +++ b/src/corelib/kernel/qeventdispatcher_glib.cpp @@ -180,6 +180,8 @@ static gboolean timerSourceCheck(GSource *source) static gboolean timerSourceDispatch(GSource *source, GSourceFunc, gpointer) { GTimerSource *timerSource = reinterpret_cast<GTimerSource *>(source); + if (timerSource->processEventsFlags & QEventLoop::X11ExcludeTimers) + return true; timerSource->runWithIdlePriority = true; (void) timerSource->timerList.activateTimers(); return true; // ??? don't remove, right again? diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index d8cc344..87d6a49 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -1023,7 +1023,8 @@ bool QEventDispatcherSymbian::hasPendingEvents() void QEventDispatcherSymbian::registerSocketNotifier ( QSocketNotifier * notifier ) { - QSocketActiveObject *socketAO = q_check_ptr(new QSocketActiveObject(this, notifier)); + QSocketActiveObject *socketAO = new QSocketActiveObject(this, notifier); + Q_CHECK_PTR(socketAO); m_notifiers.insert(notifier, socketAO); selectThread().requestSocketEvents(notifier, &socketAO->iStatus); } diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index f50994c..b2b9806 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -112,7 +112,9 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() bool pipefail = false; // initialize the common parts of the event loop -#if defined(Q_OS_INTEGRITY) +#if defined(Q_OS_NACL) + // do nothing. +#elif defined(Q_OS_INTEGRITY) // INTEGRITY doesn't like a "select" on pipes, so use socketpair instead if (socketpair(AF_INET, SOCK_STREAM, PF_INET, thread_pipe) == -1) { perror("QEventDispatcherUNIXPrivate(): Unable to create socket pair"); @@ -157,7 +159,9 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate() { -#if defined(Q_OS_VXWORKS) +#if defined(Q_OS_NACL) + // do nothing. +#elif defined(Q_OS_VXWORKS) close(thread_pipe[0]); char name[20]; @@ -312,7 +316,7 @@ int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags, QTimerInfoList::QTimerInfoList() { -#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) +#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) && !defined(Q_OS_NACL) if (!QElapsedTimer::isMonotonic()) { // not using monotonic timers, initialize the timeChanged() machinery previousTime = qt_gettime(); @@ -364,6 +368,10 @@ timeval qAbs(const timeval &t) */ bool QTimerInfoList::timeChanged(timeval *delta) { +#ifdef Q_OS_NACL + Q_UNUSED(delta) + return false; // Calling "times" crashes. +#endif struct tms unused; clock_t currentTicks = times(&unused); diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index 060a163..e1b6b1d 100644 --- a/src/corelib/kernel/qeventdispatcher_unix_p.h +++ b/src/corelib/kernel/qeventdispatcher_unix_p.h @@ -64,7 +64,7 @@ # include <sys/times.h> #else # include <sys/time.h> -# if !defined(Q_OS_HPUX) || defined(__ia64) +# if (!defined(Q_OS_HPUX) || defined(__ia64)) && !defined(Q_OS_NACL) # include <sys/select.h> # endif #endif diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index a719e72..aa7e32f 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -78,6 +78,8 @@ extern uint qGlobalPostedEventsCount(); #ifndef QT_NO_GESTURES #ifndef WM_GESTURE # define WM_GESTURE 0x0119 +#endif +#ifndef WM_GESTURENOTIFY # define WM_GESTURENOTIFY 0x011A #endif #endif // QT_NO_GESTURES diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 9854e68..ceb2a9c 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -266,7 +266,25 @@ QObject *QMetaObject::cast(QObject *obj) const const QMetaObject *m = obj->metaObject(); do { if (m == this) - return const_cast<QObject*>(obj); + return obj; + } while ((m = m->d.superdata)); + } + return 0; +} + +/*! + \internal + + Returns \a obj if object \a obj inherits from this + meta-object; otherwise returns 0. +*/ +const QObject *QMetaObject::cast(const QObject *obj) const +{ + if (obj) { + const QMetaObject *m = obj->metaObject(); + do { + if (m == this) + return obj; } while ((m = m->d.superdata)); } return 0; @@ -1558,6 +1576,12 @@ bool QMetaMethod::invoke(QObject *object, : Qt::QueuedConnection; } +#ifdef QT_NO_THREAD + if (connectionType == Qt::BlockingQueuedConnection) { + connectionType = Qt::DirectConnection; + } +#endif + // invoke! void *param[] = { returnValue.data(), @@ -1576,7 +1600,7 @@ bool QMetaMethod::invoke(QObject *object, int methodIndex = ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset(); if (connectionType == Qt::DirectConnection) { return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, methodIndex, param) < 0; - } else { + } else if (connectionType == Qt::QueuedConnection) { if (returnValue.data()) { qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in " "queued connections"); @@ -1609,40 +1633,21 @@ bool QMetaMethod::invoke(QObject *object, } } - if (connectionType == Qt::QueuedConnection) { - QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, - 0, - -1, - nargs, - types, - args)); - } else { - if (currentThread == objectThread) { - qWarning("QMetaMethod::invoke: Dead lock detected in " - "BlockingQueuedConnection: Receiver is %s(%p)", - mobj->className(), object); - } + QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, + 0, -1, nargs, types, args)); + } else { // blocking queued connection +#ifndef QT_NO_THREAD + if (currentThread == objectThread) { + qWarning("QMetaMethod::invoke: Dead lock detected in " + "BlockingQueuedConnection: Receiver is %s(%p)", + mobj->className(), object); + } - // blocking queued connection -#ifdef QT_NO_THREAD - QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, - 0, - -1, - nargs, - types, - args)); -#else - QSemaphore semaphore; - QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, - 0, - -1, - nargs, - types, - args, - &semaphore)); - semaphore.acquire(); + QSemaphore semaphore; + QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex, + 0, -1, 0, 0, param, &semaphore)); + semaphore.acquire(); #endif // QT_NO_THREAD - } } return true; } diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index b700351..8124487 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -138,6 +138,8 @@ private: const QMetaObject *mobj; uint handle; friend struct QMetaObject; + friend struct QMetaObjectPrivate; + friend class QObject; }; Q_DECLARE_TYPEINFO(QMetaMethod, Q_MOVABLE_TYPE); diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 4a03874..40b8715 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -131,6 +131,8 @@ struct QMetaObjectPrivate #ifndef QT_NO_QOBJECT //defined in qobject.cpp enum DisconnectType { DisconnectAll, DisconnectOne }; + static void memberIndexes(const QObject *obj, const QMetaMethod &member, + int *signalIndex, int *methodIndex); static bool connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type = 0, int *types = 0); diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index fef02cf..bb77d2c 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -311,6 +311,7 @@ static const struct { const char * typeName; int typeNameLength; int type; } typ QT_ADD_STATIC_METATYPE("long long", QMetaType::LongLong), QT_ADD_STATIC_METATYPE("unsigned long long", QMetaType::ULongLong), QT_ADD_STATIC_METATYPE("qint8", QMetaType::Char), + QT_ADD_STATIC_METATYPE("signed char", QMetaType::Char), QT_ADD_STATIC_METATYPE("quint8", QMetaType::UChar), QT_ADD_STATIC_METATYPE("qint16", QMetaType::Short), QT_ADD_STATIC_METATYPE("quint16", QMetaType::UShort), diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index e16ffe8..eebb3db 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -353,6 +353,7 @@ Q_DECLARE_BUILTIN_METATYPE(QChar, QChar) Q_DECLARE_BUILTIN_METATYPE(long, Long) Q_DECLARE_BUILTIN_METATYPE(short, Short) Q_DECLARE_BUILTIN_METATYPE(char, Char) +Q_DECLARE_BUILTIN_METATYPE(signed char, Char) Q_DECLARE_BUILTIN_METATYPE(ulong, ULong) Q_DECLARE_BUILTIN_METATYPE(ushort, UShort) Q_DECLARE_BUILTIN_METATYPE(uchar, UChar) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 579c225..573bb50 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -150,9 +150,11 @@ QObjectPrivate::QObjectPrivate(int version) postedEvents = 0; extraData = 0; connectedSignals[0] = connectedSignals[1] = 0; - inEventHandler = false; inThreadChangeEvent = false; +#ifdef QT_JAMBI_BUILD + inEventHandler = false; deleteWatch = 0; +#endif metaObject = 0; hasGuards = false; } @@ -160,8 +162,10 @@ QObjectPrivate::QObjectPrivate(int version) QObjectPrivate::~QObjectPrivate() { delete static_cast<QAbstractDynamicMetaObject*>(metaObject); +#ifdef QT_JAMBI_BUILD if (deleteWatch) *deleteWatch = 1; +#endif #ifndef QT_NO_USERDATA if (extraData) qDeleteAll(extraData->userData); @@ -170,6 +174,7 @@ QObjectPrivate::~QObjectPrivate() } +#ifdef QT_JAMBI_BUILD int *QObjectPrivate::setDeleteWatch(QObjectPrivate *d, int *w) { int *old = d->deleteWatch; d->deleteWatch = w; @@ -184,18 +189,15 @@ void QObjectPrivate::resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int dele if (oldWatch) *oldWatch = deleteWatch; } - - - - +#endif #ifdef QT3_SUPPORT void QObjectPrivate::sendPendingChildInsertedEvents() { Q_Q(QObject); for (int i = 0; i < pendingChildInsertedEvents.size(); ++i) { - QObject *c = pendingChildInsertedEvents.at(i); - if (!c) + QObject *c = pendingChildInsertedEvents.at(i).data(); + if (!c || c->parent() != q) continue; QChildEvent childEvent(QEvent::ChildInserted, c); QCoreApplication::sendEvent(q, &childEvent); @@ -203,26 +205,6 @@ void QObjectPrivate::sendPendingChildInsertedEvents() pendingChildInsertedEvents.clear(); } -void QObjectPrivate::removePendingChildInsertedEvents(QObject *child) -{ - if (!child) { - pendingChildInsertedEvents.clear(); - return; - } - - // the QObject destructor calls QObject::removeChild, which calls - // QCoreApplication::sendEvent() directly. this can happen while the event - // loop is in the middle of posting events, and when we get here, we may - // not have any more posted events for this object. - - // if this is a child remove event and the child insert hasn't - // been dispatched yet, kill that insert - for (int i = 0; i < pendingChildInsertedEvents.size(); ++i) { - QObject *&c = pendingChildInsertedEvents[i]; - if (c == child) - c = 0; - } -} #endif @@ -477,11 +459,6 @@ void QMetaObject::changeGuard(QObject **ptr, QObject *o) */ void QObjectPrivate::clearGuards(QObject *object) { - QObjectPrivate *priv = QObjectPrivate::get(object); - - if (!priv->hasGuards) - return; - GuardHash *hash = 0; QMutex *mutex = 0; QT_TRY { @@ -516,12 +493,14 @@ QMetaCallEvent::QMetaCallEvent(int id, const QObject *sender, int signalId, */ QMetaCallEvent::~QMetaCallEvent() { - for (int i = 0; i < nargs_; ++i) { - if (types_[i] && args_[i]) - QMetaType::destroy(types_[i], args_[i]); + if (types_) { + for (int i = 0; i < nargs_; ++i) { + if (types_[i] && args_[i]) + QMetaType::destroy(types_[i], args_[i]); + } + qFree(types_); + qFree(args_); } - if (types_) qFree(types_); - if (args_) qFree(args_); #ifndef QT_NO_THREAD if (semaphore_) semaphore_->release(); @@ -731,13 +710,15 @@ QObject::QObject(QObject *parent) d_ptr->q_ptr = this; d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current(); d->threadData->ref(); - QT_TRY { - if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) - parent = 0; - setParent(parent); - } QT_CATCH(...) { - d->threadData->deref(); - QT_RETHROW; + if (parent) { + QT_TRY { + if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) + parent = 0; + setParent(parent); + } QT_CATCH(...) { + d->threadData->deref(); + QT_RETHROW; + } } qt_addObject(this); } @@ -756,9 +737,11 @@ QObject::QObject(QObject *parent, const char *name) qt_addObject(d_ptr->q_ptr = this); d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current(); d->threadData->ref(); - if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) - parent = 0; - setParent(parent); + if (parent) { + if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) + parent = 0; + setParent(parent); + } setObjectName(QString::fromAscii(name)); } #endif @@ -772,21 +755,23 @@ QObject::QObject(QObjectPrivate &dd, QObject *parent) d_ptr->q_ptr = this; d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current(); d->threadData->ref(); - QT_TRY { - if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) - parent = 0; - if (d->isWidget) { - if (parent) { - d->parent = parent; - d->parent->d_func()->children.append(this); + if (parent) { + QT_TRY { + if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData)) + parent = 0; + if (d->isWidget) { + if (parent) { + d->parent = parent; + d->parent->d_func()->children.append(this); + } + // no events sent here, this is done at the end of the QWidget constructor + } else { + setParent(parent); } - // no events sent here, this is done at the end of the QWidget constructor - } else { - setParent(parent); + } QT_CATCH(...) { + d->threadData->deref(); + QT_RETHROW; } - } QT_CATCH(...) { - d->threadData->deref(); - QT_RETHROW; } qt_addObject(this); } @@ -821,7 +806,7 @@ QObject::~QObject() d->wasDeleted = true; d->blockSig = 0; // unblock signals so we always emit destroyed() - if (!d->isWidget) { + if (d->hasGuards && !d->isWidget) { // set all QPointers for this object to zero - note that // ~QWidget() does this for us, so we don't have to do it twice QObjectPrivate::clearGuards(this); @@ -839,22 +824,16 @@ QObject::~QObject() delete d->sharedRefcount; } - QT_TRY { - emit destroyed(this); - } QT_CATCH(...) { - // all the signal/slots connections are still in place - if we don't - // quit now, we will crash pretty soon. - qWarning("Detected an unexpected exception in ~QObject while emitting destroyed()."); -#if defined(Q_BUILD_INTERNAL) && !defined(QT_NO_EXCEPTIONS) - struct AutotestException : public std::exception - { - const char *what() const throw() { return "autotest swallow"; } - } autotestException; - // throw autotestException; -#else - QT_RETHROW; -#endif + if (d->isSignalConnected(0)) { + QT_TRY { + emit destroyed(this); + } QT_CATCH(...) { + // all the signal/slots connections are still in place - if we don't + // quit now, we will crash pretty soon. + qWarning("Detected an unexpected exception in ~QObject while emitting destroyed()."); + QT_RETHROW; + } } if (d->declarativeData) @@ -892,7 +871,7 @@ QObject::~QObject() if (c->next) c->next->prev = c->prev; } if (needToUnlock) - m->unlock(); + m->unlockInline(); connectionList.first = c->nextConnectionList; delete c; @@ -916,7 +895,7 @@ QObject::~QObject() bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); //the node has maybe been removed while the mutex was unlocked in relock? if (!node || node->sender != sender) { - m->unlock(); + m->unlockInline(); continue; } node->receiver = 0; @@ -926,7 +905,7 @@ QObject::~QObject() node = node->next; if (needToUnlock) - m->unlock(); + m->unlockInline(); } } @@ -936,12 +915,6 @@ QObject::~QObject() d->threadData->eventDispatcher->unregisterTimers(this); } -#ifdef QT3_SUPPORT - d->pendingChildInsertedEvents.clear(); -#endif - - d->eventFilters.clear(); - if (!d->children.isEmpty()) d->deleteChildren(); @@ -1202,7 +1175,9 @@ bool QObject::event(QEvent *e) case QEvent::MetaCall: { +#ifdef QT_JAMBI_BUILD d_func()->inEventHandler = false; +#endif QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e); QObjectPrivate::Sender currentSender; currentSender.sender = const_cast<QObject*>(mce->sender()); @@ -1520,11 +1495,14 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData currentSender->ref = 0; currentSender = 0; +#ifdef QT_JAMBI_BUILD // the current event thread also shouldn't restore the delete watch inEventHandler = false; + if (deleteWatch) *deleteWatch = 1; deleteWatch = 0; +#endif // set new thread data targetData->ref(); @@ -1774,11 +1752,7 @@ QObjectList QObject::queryList(const char *inheritsClass, \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 11 - \warning This function is not available with MSVC 6. Use - qFindChild() instead if you need to support that version of the - compiler. - - \sa findChildren(), qFindChild() + \sa findChildren() */ /*! @@ -1798,11 +1772,7 @@ QObjectList QObject::queryList(const char *inheritsClass, \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 13 - \warning This function is not available with MSVC 6. Use - qFindChildren() instead if you need to support that version of the - compiler. - - \sa findChild(), qFindChildren() + \sa findChild() */ /*! @@ -1813,20 +1783,19 @@ QObjectList QObject::queryList(const char *inheritsClass, and that have names matching the regular expression \a regExp, or an empty list if there are no such objects. The search is performed recursively. - - \warning This function is not available with MSVC 6. Use - qFindChildren() instead if you need to support that version of the - compiler. */ /*! \fn T qFindChild(const QObject *obj, const QString &name) \relates QObject + \obsolete This function is equivalent to - \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QObject::findChild() */ @@ -1834,11 +1803,14 @@ QObjectList QObject::queryList(const char *inheritsClass, /*! \fn QList<T> qFindChildren(const QObject *obj, const QString &name) \relates QObject + \obsolete This function is equivalent to - \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QObject::findChildren() */ @@ -1849,9 +1821,13 @@ QObjectList QObject::queryList(const char *inheritsClass, \overload qFindChildren() This function is equivalent to - \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a regExp). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a regExp). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. + + \sa QObject::findChildren() */ /*! @@ -1861,9 +1837,11 @@ QObjectList QObject::queryList(const char *inheritsClass, \overload qFindChildren() This function is equivalent to - \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QObject::findChild() */ @@ -1875,9 +1853,11 @@ QObjectList QObject::queryList(const char *inheritsClass, \overload qFindChildren() This function is equivalent to - \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QObject::findChildren() */ @@ -1997,12 +1977,14 @@ void QObjectPrivate::setParent_helper(QObject *o) QChildEvent e(QEvent::ChildAdded, q); QCoreApplication::sendEvent(parent, &e); #ifdef QT3_SUPPORT - if (parent->d_func()->pendingChildInsertedEvents.isEmpty()) { - QCoreApplication::postEvent(parent, - new QEvent(QEvent::ChildInsertedRequest), - Qt::HighEventPriority); + if (QCoreApplicationPrivate::useQt3Support) { + if (parent->d_func()->pendingChildInsertedEvents.isEmpty()) { + QCoreApplication::postEvent(parent, + new QEvent(QEvent::ChildInsertedRequest), + Qt::HighEventPriority); + } + parent->d_func()->pendingChildInsertedEvents.append(q); } - parent->d_func()->pendingChildInsertedEvents.append(q); #endif } } @@ -2311,7 +2293,7 @@ static void err_info_about_objects(const char * func, a thread different from this object's thread. Do not use this function in this type of scenario. - \sa QSignalMapper + \sa senderSignalIndex(), QSignalMapper */ QObject *QObject::sender() const @@ -2322,13 +2304,53 @@ QObject *QObject::sender() const if (!d->currentSender) return 0; - // Return 0 if d->currentSender isn't in d->senders - bool found = false; - for (QObjectPrivate::Connection *c = d->senders; c && !found; c = c->next) - found = (c->sender == d->currentSender->sender); - if (!found) - return 0; - return d->currentSender->sender; + for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) { + if (c->sender == d->currentSender->sender) + return d->currentSender->sender; + } + + return 0; +} + +/*! + \since 4.8 + + Returns the meta-method index of the signal that called the currently + executing slot, which is a member of the class returned by sender(). + If called outside of a slot activated by a signal, -1 is returned. + + For signals with default parameters, this function will always return + the index with all parameters, regardless of which was used with + connect(). For example, the signal \c {destroyed(QObject *obj = 0)} + will have two different indexes (with and without the parameter), but + this function will always return the index with a parameter. This does + not apply when overloading signals with different parameters. + + \warning This function violates the object-oriented principle of + modularity. However, getting access to the signal index might be useful + when many signals are connected to a single slot. + + \warning The return value of this function is not valid when the slot + is called via a Qt::DirectConnection from a thread different from this + object's thread. Do not use this function in this type of scenario. + + \sa sender(), QMetaObject::indexOfSignal(), QMetaObject::method() +*/ + +int QObject::senderSignalIndex() const +{ + Q_D(const QObject); + + QMutexLocker locker(signalSlotLock(this)); + if (!d->currentSender) + return -1; + + for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) { + if (c->sender == d->currentSender->sender) + return d->currentSender->signal; + } + + return -1; } /*! @@ -2390,6 +2412,71 @@ int QObject::receivers(const char *signal) const } /*! + \internal + + This helper function calculates signal and method index for the given + member in the specified class. + + \li If member.mobj is 0 then both signalIndex and methodIndex are set to -1. + + \li If specified member is not a member of obj instance class (or one of + its parent classes) then both signalIndex and methodIndex are set to -1. + + This function is used by QObject::connect and QObject::disconnect which + are working with QMetaMethod. + + \param[out] signalIndex is set to the signal index of member. If the member + specified is not signal this variable is set to -1. + + \param[out] methodIndex is set to the method index of the member. If the + member is not a method of the object specified by obj param this variable + is set to -1. +*/ +void QMetaObjectPrivate::memberIndexes(const QObject *obj, + const QMetaMethod &member, + int *signalIndex, int *methodIndex) +{ + *signalIndex = -1; + *methodIndex = -1; + if (!obj || !member.mobj) + return; + const QMetaObject *m = obj->metaObject(); + // Check that member is member of obj class + while (m != 0 && m != member.mobj) + m = m->d.superdata; + if (!m) + return; + *signalIndex = *methodIndex = (member.handle - get(member.mobj)->methodData)/5; + + int signalOffset; + int methodOffset; + computeOffsets(m, &signalOffset, &methodOffset); + + *methodIndex += methodOffset; + if (member.methodType() == QMetaMethod::Signal) { + *signalIndex = originalClone(m, *signalIndex); + *signalIndex += signalOffset; + } else { + *signalIndex = -1; + } +} + +static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaMethod &signal, + const QMetaObject *receiver, const QMetaMethod &method) +{ + if (signal.attributes() & QMetaMethod::Compatibility) { + if (!(method.attributes() & QMetaMethod::Compatibility)) + qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)", + sender->className(), signal.signature()); + } else if ((method.attributes() & QMetaMethod::Compatibility) && + method.methodType() == QMetaMethod::Signal) { + qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)", + sender->className(), signal.signature(), + receiver->className(), method.signature()); + } +} + +/*! \threadsafe Creates a connection of the given \a type from the \a signal in @@ -2566,7 +2653,7 @@ bool QObject::connect(const QObject *sender, const char *signal, } int *types = 0; - if ((type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection) + if ((type == Qt::QueuedConnection) && !(types = queuedConnectionTypes(smeta->method(signal_absolute_index).parameterTypes()))) return false; @@ -2574,15 +2661,8 @@ bool QObject::connect(const QObject *sender, const char *signal, { QMetaMethod smethod = smeta->method(signal_absolute_index); QMetaMethod rmethod = rmeta->method(method_index); - if (warnCompat) { - if(smethod.attributes() & QMetaMethod::Compatibility) { - if (!(rmethod.attributes() & QMetaMethod::Compatibility)) - qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)", smeta->className(), signal); - } else if(rmethod.attributes() & QMetaMethod::Compatibility && membcode != QSIGNAL_CODE) { - qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)", - smeta->className(), signal, rmeta->className(), method); - } - } + if (warnCompat) + check_and_warn_compat(smeta, smethod, rmeta, rmethod); } #endif if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index, type, types)) @@ -2591,6 +2671,111 @@ bool QObject::connect(const QObject *sender, const char *signal, return true; } +/*! + \since 4.8 + + Creates a connection of the given \a type from the \a signal in + the \a sender object to the \a method in the \a receiver object. + Returns true if the connection succeeds; otherwise returns false. + + This function works in the same way as + connect(const QObject *sender, const char *signal, + const QObject *receiver, const char *method, + Qt::ConnectionType type) + but it uses QMetaMethod to specify signal and method. + + \see connect(const QObject *sender, const char *signal, + const QObject *receiver, const char *method, + Qt::ConnectionType type) + */ +bool QObject::connect(const QObject *sender, const QMetaMethod &signal, + const QObject *receiver, const QMetaMethod &method, + Qt::ConnectionType type) +{ +#ifndef QT_NO_DEBUG + bool warnCompat = true; +#endif + if (type == Qt::AutoCompatConnection) { + type = Qt::AutoConnection; +#ifndef QT_NO_DEBUG + warnCompat = false; +#endif + } + + if (sender == 0 + || receiver == 0 + || signal.methodType() != QMetaMethod::Signal + || method.methodType() == QMetaMethod::Constructor) { + qWarning("QObject::connect: Cannot connect %s::%s to %s::%s", + sender ? sender->metaObject()->className() : "(null)", + signal.signature(), + receiver ? receiver->metaObject()->className() : "(null)", + method.signature() ); + return false; + } + + // Reconstructing SIGNAL() macro result for signal.signature() string + QByteArray signalSignature; + signalSignature.reserve(qstrlen(signal.signature())+1); + signalSignature.append((char)(QSIGNAL_CODE + '0')); + signalSignature.append(signal.signature()); + + { + QByteArray methodSignature; + methodSignature.reserve(qstrlen(method.signature())+1); + methodSignature.append((char)(method.methodType() == QMetaMethod::Slot ? QSLOT_CODE + : method.methodType() == QMetaMethod::Signal ? QSIGNAL_CODE : 0 + '0')); + methodSignature.append(method.signature()); + const void *cbdata[] = { sender, signalSignature.constData(), receiver, methodSignature.constData(), &type }; + if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata)) + return true; + } + + + int signal_index; + int method_index; + { + int dummy; + QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy); + QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index); + } + + const QMetaObject *smeta = sender->metaObject(); + const QMetaObject *rmeta = receiver->metaObject(); + if (signal_index == -1) { + qWarning("QObject::connect: Can't find signal %s on instance of class %s", + signal.signature(), smeta->className()); + return false; + } + if (method_index == -1) { + qWarning("QObject::connect: Can't find method %s on instance of class %s", + method.signature(), rmeta->className()); + return false; + } + + if (!QMetaObject::checkConnectArgs(signal.signature(), method.signature())) { + qWarning("QObject::connect: Incompatible sender/receiver arguments" + "\n %s::%s --> %s::%s", + smeta->className(), signal.signature(), + rmeta->className(), method.signature()); + return false; + } + + int *types = 0; + if ((type == Qt::QueuedConnection) + && !(types = queuedConnectionTypes(signal.parameterTypes()))) + return false; + +#ifndef QT_NO_DEBUG + if (warnCompat) + check_and_warn_compat(smeta, signal, rmeta, method); +#endif + if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index, type, types)) + return false; + + const_cast<QObject*>(sender)->connectNotify(signalSignature.constData()); + return true; +} /*! \fn bool QObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type) const @@ -2770,6 +2955,107 @@ bool QObject::disconnect(const QObject *sender, const char *signal, return res; } +/*! + \since 4.8 + + Disconnects \a signal in object \a sender from \a method in object + \a receiver. Returns true if the connection is successfully broken; + otherwise returns false. + + This function provides the same posibilities like + disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method) + but uses QMetaMethod to represent the signal and the method to be disconnected. + + Additionally this function returnsfalse and no signals and slots disconnected + if: + \list 1 + + \i \a signal is not a member of sender class or one of its parent classes. + + \i \a method is not a member of receiver class or one of its parent classes. + + \i \a signal instance represents not a signal. + + \endlist + + QMetaMethod() may be used as wildcard in the meaning "any signal" or "any slot in receiving object". + In the same way 0 can be used for \a receiver in the meaning "any receiving object". In this case + method shoud also be QMetaMethod(). \a sender parameter should be never 0. + + \see disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method) + */ +bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal, + const QObject *receiver, const QMetaMethod &method) +{ + if (sender == 0 || (receiver == 0 && method.mobj != 0)) { + qWarning("Object::disconnect: Unexpected null parameter"); + return false; + } + if (signal.mobj) { + if(signal.methodType() != QMetaMethod::Signal) { + qWarning("Object::%s: Attempt to %s non-signal %s::%s", + "disconnect","unbind", + sender->metaObject()->className(), signal.signature()); + return false; + } + } + if (method.mobj) { + if(method.methodType() == QMetaMethod::Constructor) { + qWarning("QObject::disconect: cannot use constructor as argument %s::%s", + receiver->metaObject()->className(), method.signature()); + return false; + } + } + + // Reconstructing SIGNAL() macro result for signal.signature() string + QByteArray signalSignature; + if (signal.mobj) { + signalSignature.reserve(qstrlen(signal.signature())+1); + signalSignature.append((char)(QSIGNAL_CODE + '0')); + signalSignature.append(signal.signature()); + } + + { + QByteArray methodSignature; + if (method.mobj) { + methodSignature.reserve(qstrlen(method.signature())+1); + methodSignature.append((char)(method.methodType() == QMetaMethod::Slot ? QSLOT_CODE + : method.methodType() == QMetaMethod::Signal ? QSIGNAL_CODE : 0 + '0')); + methodSignature.append(method.signature()); + } + const void *cbdata[] = { sender, signal.mobj ? signalSignature.constData() : 0, + receiver, method.mobj ? methodSignature.constData() : 0 }; + if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata)) + return true; + } + + int signal_index; + int method_index; + { + int dummy; + QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy); + QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index); + } + // If we are here sender is not null. If signal is not null while signal_index + // is -1 then this signal is not a member of sender. + if (signal.mobj && signal_index == -1) { + qWarning("QObject::disconect: signal %s not found on class %s", + signal.signature(), sender->metaObject()->className()); + return false; + } + // If this condition is true then method is not a member of receeiver. + if (receiver && method.mobj && method_index == -1) { + qWarning("QObject::disconect: method %s not found on class %s", + method.signature(), receiver->metaObject()->className()); + return false; + } + + if (!QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index)) + return false; + + const_cast<QObject*>(sender)->disconnectNotify(method.mobj ? signalSignature.constData() : 0); + return true; +} /*! \threadsafe @@ -2987,7 +3273,7 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, } if (needToUnlock) - receiverMutex->unlock(); + receiverMutex->unlockInline(); c->receiver = 0; @@ -3074,7 +3360,7 @@ void QMetaObject::connectSlotsByName(QObject *o) return; const QMetaObject *mo = o->metaObject(); Q_ASSERT(mo); - const QObjectList list = qFindChildren<QObject *>(o, QString()); + const QObjectList list = o->findChildren<QObject *>(QString()); for (int i = 0; i < mo->methodCount(); ++i) { const char *slot = mo->method(i).signature(); Q_ASSERT(slot); @@ -3121,8 +3407,7 @@ void QMetaObject::connectSlotsByName(QObject *o) } } -static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, - void **argv, QSemaphore *semaphore = 0) +static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv) { if (!c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) { QMetaMethod m = sender->metaObject()->method(signal); @@ -3152,30 +3437,9 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect signal, nargs, types, - args, - semaphore)); + args)); } -static void blocking_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv) -{ - if (QThread::currentThread() == c->receiver->thread()) { - qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: " - "Sender is %s(%p), receiver is %s(%p)", - sender->metaObject()->className(), sender, - c->receiver->metaObject()->className(), c->receiver); - } - -#ifdef QT_NO_THREAD - queued_activate(sender, signal, c, argv); -#else - QSemaphore semaphore; - queued_activate(sender, signal, c, argv, &semaphore); - QMutex *mutex = signalSlotLock(sender); - mutex->unlock(); - semaphore.acquire(); - mutex->lock(); -#endif -} /*!\internal \obsolete. @@ -3239,23 +3503,38 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign continue; QObject * const receiver = c->receiver; + const int method = c->method; + const bool receiverInSameThread = currentThreadData == receiver->d_func()->threadData; // determine if this connection should be sent immediately or // put into the event queue if ((c->connectionType == Qt::AutoConnection - && (currentThreadData != sender->d_func()->threadData + && (!receiverInSameThread || receiver->d_func()->threadData != sender->d_func()->threadData)) || (c->connectionType == Qt::QueuedConnection)) { queued_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv); continue; +#ifndef QT_NO_THREAD } else if (c->connectionType == Qt::BlockingQueuedConnection) { - blocking_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv); + locker.unlock(); + if (receiverInSameThread) { + qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: " + "Sender is %s(%p), receiver is %s(%p)", + sender->metaObject()->className(), sender, + receiver->metaObject()->className(), receiver); + } + QSemaphore semaphore; + QCoreApplication::postEvent(receiver, new QMetaCallEvent(method, + sender, signal_absolute_index, + 0, 0, + argv ? argv : empty_argv, + &semaphore)); + semaphore.acquire(); + locker.relock(); continue; +#endif } - - const int method = c->method; QObjectPrivate::Sender currentSender; - const bool receiverInSameThread = currentThreadData == receiver->d_func()->threadData; QObjectPrivate::Sender *previousSender = 0; if (receiverInSameThread) { currentSender.sender = sender; diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index d98d1f0..63fdf76 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -77,19 +77,9 @@ class QObjectUserData; typedef QList<QObject*> QObjectList; -#if defined Q_CC_MSVC && _MSC_VER < 1300 -template<typename T> inline T qFindChild(const QObject *o, const QString &name = QString(), T = 0); -template<typename T> inline QList<T> qFindChildren(const QObject *o, const QString &name = QString(), T = 0); -# ifndef QT_NO_REGEXP -template<typename T> inline QList<T> qFindChildren(const QObject *o, const QRegExp &re, T = 0); -# endif -#else -template<typename T> inline T qFindChild(const QObject *, const QString & = QString()); -template<typename T> inline QList<T> qFindChildren(const QObject *, const QString & = QString()); -# ifndef QT_NO_REGEXP -template<typename T> inline QList<T> qFindChildren(const QObject *, const QRegExp &); -# endif -#endif +Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QRegExp *re, + const QMetaObject &mo, QList<void *> *list); +Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo); class #if defined(__INTEL_COMPILER) && defined(Q_OS_WIN) @@ -109,7 +99,7 @@ public: uint ownObjectName : 1; uint sendChildEvents : 1; uint receiveChildEvents : 1; - uint inEventHandler : 1; + uint inEventHandler : 1; //only used if QT_JAMBI_BUILD uint inThreadChangeEvent : 1; uint hasGuards : 1; //true iff there is one or more QPointer attached to this object uint unused : 22; @@ -164,20 +154,36 @@ public: int startTimer(int interval); void killTimer(int id); -#ifndef QT_NO_MEMBER_TEMPLATES template<typename T> inline T findChild(const QString &aName = QString()) const - { return qFindChild<T>(this, aName); } + { return static_cast<T>(qt_qFindChild_helper(this, aName, reinterpret_cast<T>(0)->staticMetaObject)); } template<typename T> inline QList<T> findChildren(const QString &aName = QString()) const - { return qFindChildren<T>(this, aName); } + { + QList<T> list; + union { + QList<T> *typedList; + QList<void *> *voidList; + } u; + u.typedList = &list; + qt_qFindChildren_helper(this, aName, 0, reinterpret_cast<T>(0)->staticMetaObject, u.voidList); + return list; + } #ifndef QT_NO_REGEXP template<typename T> inline QList<T> findChildren(const QRegExp &re) const - { return qFindChildren<T>(this, re); } -#endif + { + QList<T> list; + union { + QList<T> *typedList; + QList<void *> *voidList; + } u; + u.typedList = &list; + qt_qFindChildren_helper(this, QString(), &re, reinterpret_cast<T>(0)->staticMetaObject, u.voidList); + return list; + } #endif #ifdef QT3_SUPPORT @@ -207,6 +213,21 @@ public: #endif #endif ); + + static bool connect(const QObject *sender, const QMetaMethod &signal, + const QObject *receiver, const QMetaMethod &method, + Qt::ConnectionType type = +#ifdef qdoc + Qt::AutoConnection +#else +#ifdef QT3_SUPPORT + Qt::AutoCompatConnection +#else + Qt::AutoConnection +#endif +#endif + ); + inline bool connect(const QObject *sender, const char *signal, const char *member, Qt::ConnectionType type = #ifdef qdoc @@ -222,6 +243,8 @@ public: static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member); + static bool disconnect(const QObject *sender, const QMetaMethod &signal, + const QObject *receiver, const QMetaMethod &member); inline bool disconnect(const char *signal = 0, const QObject *receiver = 0, const char *member = 0) { return disconnect(this, signal, receiver, member); } @@ -257,6 +280,7 @@ public Q_SLOTS: protected: QObject *sender() const; + int senderSignalIndex() const; int receivers(const char* signal) const; virtual void timerEvent(QTimerEvent *); @@ -321,46 +345,31 @@ public: }; #endif -Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QRegExp *re, - const QMetaObject &mo, QList<void *> *list); -Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo); - +#ifdef QT_DEPRECATED template<typename T> -inline T qFindChild(const QObject *o, const QString &name) -{ return static_cast<T>(qt_qFindChild_helper(o, name, reinterpret_cast<T>(0)->staticMetaObject)); } +inline QT_DEPRECATED T qFindChild(const QObject *o, const QString &name = QString()) +{ return o->findChild<T>(name); } template<typename T> -inline QList<T> qFindChildren(const QObject *o, const QString &name) +inline QT_DEPRECATED QList<T> qFindChildren(const QObject *o, const QString &name = QString()) { - QList<T> list; - union { - QList<T> *typedList; - QList<void *> *voidList; - } u; - u.typedList = &list; - qt_qFindChildren_helper(o, name, 0, reinterpret_cast<T>(0)->staticMetaObject, u.voidList); - return list; + return o->findChildren<T>(name); } #ifndef QT_NO_REGEXP template<typename T> -inline QList<T> qFindChildren(const QObject *o, const QRegExp &re) +inline QT_DEPRECATED QList<T> qFindChildren(const QObject *o, const QRegExp &re) { - QList<T> list; - union { - QList<T> *typedList; - QList<void *> *voidList; - } u; - u.typedList = &list; - qt_qFindChildren_helper(o, QString(), &re, reinterpret_cast<T>(0)->staticMetaObject, u.voidList); - return list; + return o->findChildren<T>(re); } #endif +#endif //QT_DEPRECATED + template <class T> inline T qobject_cast(QObject *object) { -#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(QT_NO_QOBJECT_CHECK) +#if !defined(QT_NO_QOBJECT_CHECK) reinterpret_cast<T>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(object)); #endif return static_cast<T>(reinterpret_cast<T>(0)->staticMetaObject.cast(object)); @@ -369,14 +378,10 @@ inline T qobject_cast(QObject *object) template <class T> inline T qobject_cast(const QObject *object) { - // this will cause a compilation error if T is not const - register T ptr = static_cast<T>(object); - Q_UNUSED(ptr); - -#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(QT_NO_QOBJECT_CHECK) +#if !defined(QT_NO_QOBJECT_CHECK) reinterpret_cast<T>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(const_cast<QObject *>(object))); #endif - return static_cast<T>(const_cast<QObject *>(reinterpret_cast<T>(0)->staticMetaObject.cast(const_cast<QObject *>(object)))); + return static_cast<T>(reinterpret_cast<T>(0)->staticMetaObject.cast(object)); } diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 814769c..effd3e6 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -55,6 +55,7 @@ #include "QtCore/qobject.h" #include "QtCore/qpointer.h" +#include "QtCore/qsharedpointer.h" #include "QtCore/qcoreevent.h" #include "QtCore/qlist.h" #include "QtCore/qvector.h" @@ -154,7 +155,6 @@ public: #ifdef QT3_SUPPORT void sendPendingChildInsertedEvents(); - void removePendingChildInsertedEvents(QObject *child); #endif static inline Sender *setCurrentSender(QObject *receiver, @@ -162,8 +162,10 @@ public: static inline void resetCurrentSender(QObject *receiver, Sender *currentSender, Sender *previousSender); +#ifdef QT_JAMBI_BUILD static int *setDeleteWatch(QObjectPrivate *d, int *newWatch); static void resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch); +#endif static void clearGuards(QObject *); static QObjectPrivate *get(QObject *o) { @@ -185,7 +187,7 @@ public: mutable quint32 connectedSignals[2]; #ifdef QT3_SUPPORT - QList<QObject *> pendingChildInsertedEvents; + QVector< QWeakPointer<QObject> > pendingChildInsertedEvents; #else // preserve binary compatibility with code compiled without Qt 3 support // keeping the binary layout stable helps the Qt Creator debugger @@ -201,7 +203,9 @@ public: // these objects are all used to indicate that a QObject was deleted // plus QPointer, which keeps a separate list QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount; +#ifdef QT_JAMBI_BUILD int *deleteWatch; +#endif }; diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 555a1f5..db46ba5 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -117,7 +117,7 @@ class QString; # define QT_TR_FUNCTIONS #endif -#if defined(QT_NO_MEMBER_TEMPLATES) || defined(QT_NO_QOBJECT_CHECK) +#if defined(QT_NO_QOBJECT_CHECK) /* tmake ignore Q_OBJECT */ #define Q_OBJECT_CHECK #else @@ -144,7 +144,7 @@ inline int qYouForgotTheQ_OBJECT_Macro(T, T) { return 0; } template <typename T1, typename T2> inline void qYouForgotTheQ_OBJECT_Macro(T1, T2) {} -#endif // QT_NO_MEMBER_TEMPLATES +#endif // QT_NO_QOBJECT_CHECK #ifdef Q_NO_DATA_RELOCATION #define Q_OBJECT_GETSTATICMETAOBJECT static const QMetaObject &getStaticMetaObject(); @@ -298,6 +298,7 @@ struct Q_CORE_EXPORT QMetaObject const QMetaObject *superClass() const; QObject *cast(QObject *obj) const; + const QObject *cast(const QObject *obj) const; #ifndef QT_NO_TRANSLATION // ### Qt 4: Merge overloads diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp index fe93ebc..6d7c7a4 100644 --- a/src/corelib/kernel/qsharedmemory.cpp +++ b/src/corelib/kernel/qsharedmemory.cpp @@ -73,14 +73,13 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key, QString part1 = key; part1.replace(QRegExp(QLatin1String("[^A-Za-z]")), QString()); result.append(part1); -#ifdef Q_OS_SYMBIAN - return result.left(KMaxKernelName); -#endif QByteArray hex = QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Sha1).toHex(); result.append(QLatin1String(hex)); #ifdef Q_OS_WIN return result; +#elif defined(Q_OS_SYMBIAN) + return result.left(KMaxKernelName); #else return QDir::tempPath() + QLatin1Char('/') + result; #endif @@ -142,9 +141,12 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key, remain. Do not mix using QtSharedMemory and QSharedMemory. Port everything to QSharedMemory. - \warning QSharedMemory changes the key in a Qt-specific way. - It is therefore currently not possible to use the shared memory of - non-Qt applications with QSharedMemory. + \warning QSharedMemory changes the key in a Qt-specific way, unless otherwise + specified. Interoperation with non-Qt applications is achieved by first creating + a default shared memory with QSharedMemory() and then setting a native key with + setNativeKey(). When using native keys, shared memory is not protected against + multiple accesses on it (e.g. unable to lock()) and a user-defined mechanism + should be used to achieve a such protection. */ /*! @@ -153,8 +155,8 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key, Constructs a shared memory object with the given \a parent. The shared memory object's key is not set by the constructor, so the shared memory object does not have an underlying shared memory - segment attached. The key must be set with setKey() before create() - or attach() can be used. + segment attached. The key must be set with setKey() or setNativeKey() + before create() or attach() can be used. \sa setKey() */ @@ -191,24 +193,62 @@ QSharedMemory::~QSharedMemory() } /*! - Sets a new \a key for this shared memory object. If \a key and the - current key are the same, the function returns without doing - anything. If the shared memory object is attached to an underlying - shared memory segment, it will \l {detach()} {detach} from it before - setting the new key. This function does not do an attach(). + Sets the platform independent \a key for this shared memory object. If \a key + is the same as the current key, the function returns without doing anything. - \sa key() isAttached() - */ + You can call key() to retrieve the platform independent key. Internally, + QSharedMemory converts this key into a platform specific key. If you instead + call nativeKey(), you will get the platform specific, converted key. + + If the shared memory object is attached to an underlying shared memory + segment, it will \l {detach()} {detach} from it before setting the new key. + This function does not do an attach(). + + \sa key() nativeKey() isAttached() +*/ void QSharedMemory::setKey(const QString &key) { Q_D(QSharedMemory); - if (key == d->key) + if (key == d->key && d->makePlatformSafeKey(key) == d->nativeKey) return; if (isAttached()) detach(); d->cleanHandle(); d->key = key; + d->nativeKey = d->makePlatformSafeKey(key); +} + +/*! + \since 4.8 + + Sets the native, platform specific, \a key for this shared memory object. If + \a key is the same as the current native key, the function returns without + doing anything. If all you want is to assign a key to a segment, you should + call setKey() instead. + + You can call nativeKey() to retrieve the native key. If a native key has been + assigned, calling key() will return a null string. + + If the shared memory object is attached to an underlying shared memory + segment, it will \l {detach()} {detach} from it before setting the new key. + This function does not do an attach(). + + The application will not be portable if you set a native key. + + \sa nativeKey() key() isAttached() +*/ +void QSharedMemory::setNativeKey(const QString &key) +{ + Q_D(QSharedMemory); + if (key == d->nativeKey && d->key.isNull()) + return; + + if (isAttached()) + detach(); + d->cleanHandle(); + d->key = QString(); + d->nativeKey = key; } bool QSharedMemoryPrivate::initKey() @@ -251,13 +291,15 @@ bool QSharedMemoryPrivate::initKey() } /*! - Returns the key assigned to this shared memory. The key is the - identifier used by the operating system to identify the shared - memory segment. When QSharedMemory is used for interprocess - communication, the key is how each process attaches to the shared - memory segment through which the IPC occurs. + Returns the key assigned with setKey() to this shared memory, or a null key + if no key has been assigned, or if the segment is using a nativeKey(). The + key is the identifier used by Qt applications to identify the shared memory + segment. - \sa setKey() + You can find the native, platform specific, key used by the operating system + by calling nativeKey(). + + \sa setKey() setNativeKey() */ QString QSharedMemory::key() const { @@ -266,13 +308,30 @@ QString QSharedMemory::key() const } /*! - Creates a shared memory segment of \a size bytes with the key passed - to the constructor or set with setKey(), attaches to the new shared - memory segment with the given access \a mode, and returns \tt true. - If a shared memory segment identified by the key already exists, the - attach operation is not performed, and \tt false is returned. When - the return value is \tt false, call error() to determine which error - occurred. + \since 4.8 + + Returns the native, platform specific, key for this shared memory object. The + native key is the identifier used by the operating system to identify the + shared memory segment. + + You can use the native key to access shared memory segments that have not + been created by Qt, or to grant shared memory access to non-Qt applications. + + \sa setKey() setNativeKey() +*/ +QString QSharedMemory::nativeKey() const +{ + Q_D(const QSharedMemory); + return d->nativeKey; +} + +/*! + Creates a shared memory segment of \a size bytes with the key passed to the + constructor, set with setKey() or set with setNativeKey(), then attaches to + the new shared memory segment with the given access \a mode and returns + \tt true. If a shared memory segment identified by the key already exists, + the attach operation is not performed and \tt false is returned. When the + return value is \tt false, call error() to determine which error occurred. \sa error() */ @@ -294,7 +353,7 @@ bool QSharedMemory::create(int size, AccessMode mode) QString function = QLatin1String("QSharedMemory::create"); #ifndef QT_NO_SYSTEMSEMAPHORE QSharedMemoryLocker lock(this); - if (!d->tryLocker(&lock, function)) + if (!d->key.isNull() && !d->tryLocker(&lock, function)) return false; #endif @@ -338,7 +397,7 @@ int QSharedMemory::size() const /*! Attempts to attach the process to the shared memory segment identified by the key that was passed to the constructor or to a - call to setKey(). The access \a mode is \l {QSharedMemory::} + call to setKey() or setNativeKey(). The access \a mode is \l {QSharedMemory::} {ReadWrite} by default. It can also be \l {QSharedMemory::} {ReadOnly}. Returns true if the attach operation is successful. If false is returned, call error() to determine which error occurred. @@ -355,7 +414,7 @@ bool QSharedMemory::attach(AccessMode mode) return false; #ifndef QT_NO_SYSTEMSEMAPHORE QSharedMemoryLocker lock(this); - if (!d->tryLocker(&lock, QLatin1String("QSharedMemory::attach"))) + if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::attach"))) return false; #endif @@ -395,7 +454,7 @@ bool QSharedMemory::detach() #ifndef QT_NO_SYSTEMSEMAPHORE QSharedMemoryLocker lock(this); - if (!d->tryLocker(&lock, QLatin1String("QSharedMemory::detach"))) + if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::detach"))) return false; #endif @@ -451,9 +510,9 @@ const void *QSharedMemory::data() const by this process and returns true. If another process has locked the segment, this function blocks until the lock is released. Then it acquires the lock and returns true. If this function returns false, - it means either that you have ignored a false return from create() - or attach(), or that QSystemSemaphore::acquire() failed due to an - unknown system error. + it means that you have ignored a false return from create() or attach(), + that you have set the key with setNativeKey() or that + QSystemSemaphore::acquire() failed due to an unknown system error. \sa unlock(), data(), QSystemSemaphore::acquire() */ diff --git a/src/corelib/kernel/qsharedmemory.h b/src/corelib/kernel/qsharedmemory.h index fba939c..5673f43 100644 --- a/src/corelib/kernel/qsharedmemory.h +++ b/src/corelib/kernel/qsharedmemory.h @@ -85,6 +85,8 @@ public: void setKey(const QString &key); QString key() const; + void setNativeKey(const QString &key); + QString nativeKey() const; bool create(int size, AccessMode mode = ReadWrite); int size() const; diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h index a52f8b3..632a6e9 100644 --- a/src/corelib/kernel/qsharedmemory_p.h +++ b/src/corelib/kernel/qsharedmemory_p.h @@ -122,6 +122,7 @@ public: void *memory; int size; QString key; + QString nativeKey; QSharedMemory::SharedMemoryError error; QString errorString; #ifndef QT_NO_SYSTEMSEMAPHORE diff --git a/src/corelib/kernel/qsharedmemory_symbian.cpp b/src/corelib/kernel/qsharedmemory_symbian.cpp index 9b84eb56..091c2b5 100644 --- a/src/corelib/kernel/qsharedmemory_symbian.cpp +++ b/src/corelib/kernel/qsharedmemory_symbian.cpp @@ -107,16 +107,14 @@ bool QSharedMemoryPrivate::cleanHandle() bool QSharedMemoryPrivate::create(int size) { - // Get a windows acceptable key - QString safeKey = makePlatformSafeKey(key); QString function = QLatin1String("QSharedMemory::create"); - if (safeKey.isEmpty()) { + if (nativeKey.isEmpty()) { error = QSharedMemory::KeyError; errorString = QSharedMemory::tr("%1: key error").arg(function); return false; } - TPtrC ptr(qt_QString2TPtrC(safeKey)); + TPtrC ptr(qt_QString2TPtrC(nativeKey)); TInt err = chunk.CreateGlobal(ptr, size, size); @@ -136,14 +134,13 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode /* mode */) // Grab a pointer to the memory block if (!chunk.Handle()) { QString function = QLatin1String("QSharedMemory::handle"); - QString safeKey = makePlatformSafeKey(key); - if (safeKey.isEmpty()) { + if (nativeKey.isEmpty()) { error = QSharedMemory::KeyError; errorString = QSharedMemory::tr("%1: unable to make key").arg(function); return false; } - TPtrC ptr(qt_QString2TPtrC(safeKey)); + TPtrC ptr(qt_QString2TPtrC(nativeKey)); TInt err = KErrNoMemory; diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp index a5f79c2..064979b 100644 --- a/src/corelib/kernel/qsharedmemory_unix.cpp +++ b/src/corelib/kernel/qsharedmemory_unix.cpp @@ -116,21 +116,20 @@ key_t QSharedMemoryPrivate::handle() return unix_key; // don't allow making handles on empty keys - if (key.isEmpty()) { + if (nativeKey.isEmpty()) { errorString = QSharedMemory::tr("%1: key is empty").arg(QLatin1String("QSharedMemory::handle:")); error = QSharedMemory::KeyError; return 0; } // ftok requires that an actual file exists somewhere - QString fileName = makePlatformSafeKey(key); - if (!QFile::exists(fileName)) { + if (!QFile::exists(nativeKey)) { errorString = QSharedMemory::tr("%1: UNIX key file doesn't exist").arg(QLatin1String("QSharedMemory::handle:")); error = QSharedMemory::NotFound; return 0; } - unix_key = ftok(QFile::encodeName(fileName).constData(), 'Q'); + unix_key = ftok(QFile::encodeName(nativeKey).constData(), 'Q'); if (-1 == unix_key) { errorString = QSharedMemory::tr("%1: ftok failed").arg(QLatin1String("QSharedMemory::handle:")); error = QSharedMemory::KeyError; @@ -181,7 +180,7 @@ bool QSharedMemoryPrivate::create(int size) { // build file if needed bool createdFile = false; - int built = createUnixKeyFile(makePlatformSafeKey(key)); + int built = createUnixKeyFile(nativeKey); if (built == -1) { errorString = QSharedMemory::tr("%1: unable to make key").arg(QLatin1String("QSharedMemory::handle:")); error = QSharedMemory::KeyError; @@ -194,7 +193,7 @@ bool QSharedMemoryPrivate::create(int size) // get handle if (!handle()) { if (createdFile) - QFile::remove(makePlatformSafeKey(key)); + QFile::remove(nativeKey); return false; } @@ -210,7 +209,7 @@ bool QSharedMemoryPrivate::create(int size) setErrorString(function); } if (createdFile && error != QSharedMemory::AlreadyExists) - QFile::remove(makePlatformSafeKey(key)); + QFile::remove(nativeKey); return false; } @@ -295,7 +294,7 @@ bool QSharedMemoryPrivate::detach() } // remove file - if (!QFile::remove(makePlatformSafeKey(key))) + if (!QFile::remove(nativeKey)) return false; } return true; diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp index 0f5fdc7..0cdb123 100644 --- a/src/corelib/kernel/qsharedmemory_win.cpp +++ b/src/corelib/kernel/qsharedmemory_win.cpp @@ -99,18 +99,17 @@ HANDLE QSharedMemoryPrivate::handle() { if (!hand) { QString function = QLatin1String("QSharedMemory::handle"); - QString safeKey = makePlatformSafeKey(key); - if (safeKey.isEmpty()) { + if (nativeKey.isEmpty()) { error = QSharedMemory::KeyError; errorString = QSharedMemory::tr("%1: unable to make key").arg(function); return false; } #ifndef Q_OS_WINCE - hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, (wchar_t*)safeKey.utf16()); + hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, (wchar_t*)nativeKey.utf16()); #else // This works for opening a mapping too, but always opens it with read/write access in // attach as it seems. - hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 0, (wchar_t*)safeKey.utf16()); + hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 0, (wchar_t*)nativeKey.utf16()); #endif if (!hand) { setErrorString(function); @@ -133,17 +132,15 @@ bool QSharedMemoryPrivate::cleanHandle() bool QSharedMemoryPrivate::create(int size) { - // Get a windows acceptable key - QString safeKey = makePlatformSafeKey(key); QString function = QLatin1String("QSharedMemory::create"); - if (safeKey.isEmpty()) { + if (nativeKey.isEmpty()) { error = QSharedMemory::KeyError; errorString = QSharedMemory::tr("%1: key error").arg(function); return false; } // Create the file mapping. - hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size, (wchar_t*)safeKey.utf16()); + hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size, (wchar_t*)nativeKey.utf16()); setErrorString(function); // hand is valid when it already exists unlike unix so explicitly check diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index f5d7c0d..aa070f1 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -947,11 +947,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result, case QMetaType::UChar: case QMetaType::UShort: case QMetaType::ULong: -#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - *f = (double)(qlonglong)qMetaTypeUNumber(d); -#else *f = double(qMetaTypeUNumber(d)); -#endif break; default: *f = 0.0; @@ -986,11 +982,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result, case QMetaType::UChar: case QMetaType::UShort: case QMetaType::ULong: -#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - *f = (float)(qlonglong)qMetaTypeUNumber(d); -#else *f = float(qMetaTypeUNumber(d)); -#endif break; default: *f = 0.0f; @@ -1084,7 +1076,7 @@ static void streamDebug(QDebug dbg, const QVariant &v) dbg.nospace() << v.toFloat(); break; case QMetaType::QObjectStar: - dbg.nospace() << qVariantValue<QObject *>(v); + dbg.nospace() << qvariant_cast<QObject *>(v); break; case QVariant::Double: dbg.nospace() << v.toDouble(); @@ -1245,7 +1237,7 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler; conversion functions to data types defined in QtGui, such as QColor, QImage, and QPixmap. In other words, there is no \c toColor() function. Instead, you can use the QVariant::value() or - the qVariantValue() template function. For example: + the qvariant_cast() template function. For example: \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 2 @@ -1360,12 +1352,12 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler; Note that you have to pass the address of the variable you want stored. - Usually, you never have to use this constructor, use qVariantFromValue() + Usually, you never have to use this constructor, use QVariant::fromValue() instead to construct variants from the pointer types represented by \c QMetaType::VoidStar, \c QMetaType::QObjectStar and \c QMetaType::QWidgetStar. - \sa qVariantFromValue(), Type + \sa QVariant::fromValue(), Type */ /*! @@ -1816,6 +1808,14 @@ QVariant& QVariant::operator=(const QVariant &variant) } /*! + \fn void QVariant::swap(QVariant &other) + \since 4.8 + + Swaps variant \a other with this variant. This operation is very + fast and never fails. +*/ + +/*! \fn void QVariant::detach() \internal @@ -3074,10 +3074,6 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 4 - \warning This function is not available with MSVC 6. Use - qVariantSetValue() instead if you need to support that version of - the compiler. - \sa value(), fromValue(), canConvert() */ @@ -3095,10 +3091,6 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 5 - \warning This function is not available with MSVC 6. Use - qVariantValue() or qvariant_cast() instead if you need to support - that version of the compiler. - \sa setValue(), fromValue(), canConvert() */ @@ -3111,10 +3103,6 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 6 - \warning This function is not available with MSVC 6. Use - qVariantCanConvert() instead if you need to support that version - of the compiler. - \sa convert() */ @@ -3130,23 +3118,22 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \note If you are working with custom types, you should use the Q_DECLARE_METATYPE() macro to register your custom type. - \warning This function is not available with MSVC 6. Use - qVariantFromValue() instead if you need to support that version - of the compiler. - \sa setValue(), value() */ /*! \fn QVariant qVariantFromValue(const T &value) \relates QVariant + \obsolete Returns a variant containing a copy of the given \a value with template type \c{T}. - This function is equivalent to QVariant::fromValue(\a value). It - is provided as a work-around for MSVC 6, which doesn't support - member template functions. + This function is equivalent to QVariant::fromValue(\a value). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. For example, a QObject pointer can be stored in a variant with the following code: @@ -3158,13 +3145,16 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) /*! \fn void qVariantSetValue(QVariant &variant, const T &value) \relates QVariant + \obsolete Sets the contents of the given \a variant to a copy of the \a value with the specified template type \c{T}. - This function is equivalent to QVariant::setValue(\a value). It - is provided as a work-around for MSVC 6, which doesn't support - member template functions. + This function is equivalent to QVariant::setValue(\a value). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QVariant::setValue() */ @@ -3175,33 +3165,39 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) Returns the given \a value converted to the template type \c{T}. - This function is equivalent to qVariantValue(). + This function is equivalent to QVariant::value(). - \sa qVariantValue(), QVariant::value() + \sa QVariant::value() */ /*! \fn T qVariantValue(const QVariant &value) \relates QVariant + \obsolete Returns the given \a value converted to the template type \c{T}. This function is equivalent to - \l{QVariant::value()}{QVariant::value}<T>(\a value). It is - provided as a work-around for MSVC 6, which doesn't support - member template functions. + \l{QVariant::value()}{QVariant::value}<T>(\a value). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QVariant::value(), qvariant_cast() */ /*! \fn bool qVariantCanConvert(const QVariant &value) \relates QVariant + \obsolete Returns true if the given \a value can be converted to the template type specified; otherwise returns false. - This function is equivalent to QVariant::canConvert(\a value). It - is provided as a work-around for MSVC 6, which doesn't support - member template functions. + This function is equivalent to QVariant::canConvert(\a value). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QVariant::canConvert() */ diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index cb2825c..611db8b 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -83,19 +83,11 @@ class QUrl; class QVariant; class QVariantComparisonHelper; -#ifndef QT_NO_MEMBER_TEMPLATES template <typename T> inline QVariant qVariantFromValue(const T &); -template <typename T> -inline void qVariantSetValue(QVariant &, const T &); - template<typename T> -inline T qVariantValue(const QVariant &); - -template<typename T> -inline bool qVariantCanConvert(const QVariant &); -#endif +inline T qvariant_cast(const QVariant &); class Q_CORE_EXPORT QVariant { @@ -227,6 +219,12 @@ class Q_CORE_EXPORT QVariant QVariant(Qt::GlobalColor color); QVariant& operator=(const QVariant &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QVariant &operator=(QVariant &&other) + { qSwap(d, other.d); return *this; } +#endif + + inline void swap(QVariant &other) { qSwap(d, other.d); } Type type() const; int userType() const; @@ -327,13 +325,12 @@ class Q_CORE_EXPORT QVariant const void *constData() const; inline const void *data() const { return constData(); } -#ifndef QT_NO_MEMBER_TEMPLATES template<typename T> inline void setValue(const T &value); template<typename T> inline T value() const - { return qVariantValue<T>(*this); } + { return qvariant_cast<T>(*this); } template<typename T> static inline QVariant fromValue(const T &value) @@ -341,8 +338,7 @@ class Q_CORE_EXPORT QVariant template<typename T> bool canConvert() const - { return qVariantCanConvert<T>(*this); } -#endif + { return canConvert(Type(qMetaTypeId<T>())); } public: #ifndef qdoc @@ -527,11 +523,9 @@ inline QSize &QVariant::asSize() { return *reinterpret_cast<QSize *>(castOrDetach(Size)); } #endif //QT3_SUPPORT -#ifndef QT_NO_MEMBER_TEMPLATES template<typename T> inline void QVariant::setValue(const T &avalue) { qVariantSetValue(*this, avalue); } -#endif #ifndef QT_NO_DATASTREAM Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant& p); @@ -594,16 +588,16 @@ template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v) return v; } +#ifdef QT_DEPRECATED template<typename T> -inline T qVariantValue(const QVariant &variant) +inline QT_DEPRECATED T qVariantValue(const QVariant &variant) { return qvariant_cast<T>(variant); } template<typename T> -inline bool qVariantCanConvert(const QVariant &variant) -{ - return variant.canConvert(static_cast<QVariant::Type>( - qMetaTypeId<T>(static_cast<T *>(0)))); -} +inline QT_DEPRECATED bool qVariantCanConvert(const QVariant &variant) +{ return variant.template canConvert<T>(); } +#endif + #endif Q_DECLARE_SHARED(QVariant) Q_DECLARE_TYPEINFO(QVariant, Q_MOVABLE_TYPE); diff --git a/src/corelib/plugin/plugin.pri b/src/corelib/plugin/plugin.pri index ba86353..50b005d 100644 --- a/src/corelib/plugin/plugin.pri +++ b/src/corelib/plugin/plugin.pri @@ -8,13 +8,15 @@ HEADERS += \ plugin/qplugin.h \ plugin/quuid.h \ plugin/qfactoryloader_p.h \ - plugin/qsystemlibrary_p.h + plugin/qsystemlibrary_p.h \ + plugin/qelfparser_p.h SOURCES += \ plugin/qpluginloader.cpp \ plugin/qfactoryloader.cpp \ plugin/quuid.cpp \ - plugin/qlibrary.cpp + plugin/qlibrary.cpp \ + plugin/qelfparser_p.cpp win32 { SOURCES += \ diff --git a/src/corelib/plugin/qelfparser_p.cpp b/src/corelib/plugin/qelfparser_p.cpp new file mode 100644 index 0000000..c60b3d5 --- /dev/null +++ b/src/corelib/plugin/qelfparser_p.cpp @@ -0,0 +1,238 @@ +/**************************************************************************** +** +** 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 "qelfparser_p.h" + +#if defined (Q_OF_ELF) && defined(Q_CC_GNU) + +#include "qlibrary_p.h" +#include <qdebug.h> + +QT_BEGIN_NAMESPACE + +// #define QELFPARSER_DEBUG 1 + +const char *QElfParser::parseSectionHeader(const char *data, ElfSectionHeader *sh) +{ + sh->name = read<qelfword_t>(data); + data += sizeof(qelfword_t); // sh_name + sh->type = read<qelfword_t>(data); + data += sizeof(qelfword_t) // sh_type + + sizeof(qelfaddr_t) // sh_flags + + sizeof(qelfaddr_t); // sh_addr + sh->offset = read<qelfoff_t>(data); + data += sizeof(qelfoff_t); // sh_offset + sh->size = read<qelfword_t>(data); + data += sizeof(qelfword_t); // sh_size + return data; +} + +int QElfParser::parse(const char *dataStart, ulong fdlen, const QString &library, QLibraryPrivate *lib, long *pos, ulong *sectionlen) +{ +#if defined(QELFPARSER_DEBUG) + qDebug() << "QElfParser::parse " << library; +#endif + + if (fdlen < 64){ + if (lib) + lib->errorString = QLibrary::tr("'%1' is not an ELF object (%2)").arg(library).arg(QLatin1String("file too small")); + return NotElf; + } + const char *data = dataStart; + if (qstrncmp(data, "\177ELF", 4) != 0) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is not an ELF object").arg(library); + return NotElf; + } + // 32 or 64 bit + if (data[4] != 1 && data[4] != 2) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("odd cpu architecture")); + return Corrupt; + } + m_bits = (data[4] << 5); + + /* If you remove this check, to read ELF objects of a different arch, please make sure you modify the typedefs + to match the _plugin_ architecture. + */ + if ((sizeof(void*) == 4 && m_bits != 32) || (sizeof(void*) == 8 && m_bits != 64)) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("wrong cpu architecture")); + return Corrupt; + } + // endian + if (data[5] == 0) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("odd endianess")); + return Corrupt; + } + m_endian = (data[5] == 1 ? ElfLittleEndian : ElfBigEndian); + + data += 16 // e_ident + + sizeof(qelfhalf_t) // e_type + + sizeof(qelfhalf_t) // e_machine + + sizeof(qelfword_t) // e_version + + sizeof(qelfaddr_t) // e_entry + + sizeof(qelfoff_t); // e_phoff + + qelfoff_t e_shoff = read<qelfoff_t> (data); + data += sizeof(qelfoff_t) // e_shoff + + sizeof(qelfword_t); // e_flags + + qelfhalf_t e_shsize = read<qelfhalf_t> (data); + + if (e_shsize > fdlen) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("unexpected e_shsize")); + return Corrupt; + } + + data += sizeof(qelfhalf_t) // e_ehsize + + sizeof(qelfhalf_t) // e_phentsize + + sizeof(qelfhalf_t); // e_phnum + + qelfhalf_t e_shentsize = read<qelfhalf_t> (data); + + if (e_shentsize % 4){ + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("unexpected e_shentsize")); + return Corrupt; + } + data += sizeof(qelfhalf_t); // e_shentsize + qelfhalf_t e_shnum = read<qelfhalf_t> (data); + data += sizeof(qelfhalf_t); // e_shnum + qelfhalf_t e_shtrndx = read<qelfhalf_t> (data); + data += sizeof(qelfhalf_t); // e_shtrndx + + if ((quint32)(e_shnum * e_shentsize) > fdlen) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("announced %2 sections, each %3 bytes, exceed file size")) + .arg(e_shnum).arg(e_shentsize); + return Corrupt; + } + +#if defined(QELFPARSER_DEBUG) + qDebug() << e_shnum << "sections starting at " << ("0x" + QByteArray::number(e_shoff, 16)).data() << "each" << e_shentsize << "bytes"; +#endif + + ElfSectionHeader strtab; + qulonglong soff = e_shoff + e_shentsize * (e_shtrndx); + + if ((soff + e_shentsize) > fdlen || soff % 4 || soff == 0) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("shstrtab section header seems to be at %1")) + .arg(QString::number(soff, 16)); + return Corrupt; + } + + parseSectionHeader(dataStart + soff, &strtab); + m_stringTableFileOffset = strtab.offset; + + if ((quint32)(m_stringTableFileOffset + e_shentsize) >= fdlen || m_stringTableFileOffset == 0) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("string table seems to be at %1")) + .arg(QString::number(soff, 16)); + return Corrupt; + } + +#if defined(QELFPARSER_DEBUG) + qDebug(".shstrtab at 0x%s", QByteArray::number(m_stringTableFileOffset, 16).data()); +#endif + + const char *s = dataStart + e_shoff; + for (int i = 0; i < e_shnum; ++i) { + ElfSectionHeader sh; + parseSectionHeader(s, &sh); + if (sh.name == 0) { + s += e_shentsize; + continue; + } + const char *shnam = dataStart + m_stringTableFileOffset + sh.name; + + if (m_stringTableFileOffset + sh.name > fdlen) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("section name %2 of %3 behind end of file")) + .arg(i).arg(e_shnum); + return Corrupt; + } + +#if defined(QELFPARSER_DEBUG) + qDebug() << "++++" << i << shnam; +#endif + + if (qstrcmp(shnam, ".qtplugin") == 0 || qstrcmp(shnam, ".rodata") == 0) { + if (!(sh.type & 0x1)) { + if (shnam[1] == 'r') { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("empty .rodata. not a library.")); + return Corrupt; + } +#if defined(QELFPARSER_DEBUG) + qDebug()<<"section is not program data. skipped."; +#endif + s += e_shentsize; + continue; + } + + if (sh.offset == 0 || (sh.offset + sh.size) > fdlen) { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("missing section data. This is not a library.")); + return Corrupt; + } + *pos = sh.offset; + *sectionlen = sh.size - 1; + if (shnam[1] == 'q') + return Ok; + } + s += e_shentsize; + } + return NoQtSection; +} + +QT_END_NAMESPACE + +#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU) diff --git a/src/corelib/plugin/qelfparser_p.h b/src/corelib/plugin/qelfparser_p.h new file mode 100644 index 0000000..8087da5 --- /dev/null +++ b/src/corelib/plugin/qelfparser_p.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QELFPARSER_P_H +#define QELFPARSER_P_H + +// +// 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. +// + +#include <qendian.h> +#include <qglobal.h> + +#if defined (Q_OF_ELF) && defined(Q_CC_GNU) + +QT_BEGIN_NAMESPACE + +class QString; +class QLibraryPrivate; + +typedef quint16 qelfhalf_t; +typedef quint32 qelfword_t; +typedef quintptr qelfoff_t; +typedef quintptr qelfaddr_t; + +class QElfParser +{ +public: + enum {Ok = 0, NotElf = 1, NoQtSection = 2, Corrupt = 3}; + enum {ElfLittleEndian = 0, ElfBigEndian = 1}; + + struct ElfSectionHeader + { + qelfword_t name; + qelfword_t type; + qelfoff_t offset; + qelfword_t size; + }; + + int m_endian; + int m_bits; + int m_stringTableFileOffset; + + template <typename T> + T read(const char *s) + { + if (m_endian == ElfBigEndian) + return qFromBigEndian<T>(reinterpret_cast<const uchar *>(s)); + else + return qFromLittleEndian<T>(reinterpret_cast<const uchar *>(s)); + } + + const char *parseSectionHeader(const char* s, ElfSectionHeader *sh); + int parse(const char *m_s, ulong fdlen, const QString &library, QLibraryPrivate *lib, long *pos, ulong *sectionlen); +}; + +QT_END_NAMESPACE + +#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU) + +#endif // QELFPARSER_P_H diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 1874a9e..fc8721c 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -1,3 +1,4 @@ + /**************************************************************************** ** ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). @@ -38,7 +39,6 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - #include "qplatformdefs.h" #include "qlibrary.h" @@ -61,11 +61,10 @@ #include <qdebug.h> #include <qvector.h> #include <qdir.h> +#include "qelfparser_p.h" QT_BEGIN_NAMESPACE -//#define QT_DEBUG_COMPONENT - #ifdef QT_NO_DEBUG # define QLIBRARY_AS_DEBUG false #else @@ -365,11 +364,35 @@ static bool qt_unix_query(const QString &library, uint *version, bool *debug, QB fdlen = data.size(); } - // verify that the pattern is present in the plugin + /* + ELF binaries on GNU, have .qplugin sections. + */ + long pos = 0; const char pattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA"; const ulong plen = qstrlen(pattern); - long pos = qt_find_pattern(filedata, fdlen, pattern, plen); - +#if defined (Q_OF_ELF) && defined(Q_CC_GNU) + int r = QElfParser().parse(filedata, fdlen, library, lib, &pos, &fdlen); + if (r == QElfParser::NoQtSection) { + if (pos > 0) { + // find inside .rodata + long rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen); + if (rel < 0) { + pos = -1; + } else { + pos += rel; + } + } else { + pos = qt_find_pattern(filedata, fdlen, pattern, plen); + } + } else if (r != QElfParser::Ok) { + if (lib && qt_debug_component()) { + qWarning("QElfParser: %s",qPrintable(lib->errorString)); + } + return false; + } +#else + pos = qt_find_pattern(filedata, fdlen, pattern, plen); +#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU) bool ret = false; if (pos >= 0) ret = qt_parse_pattern(filedata + pos, version, debug, key); @@ -392,6 +415,7 @@ struct LibraryData { QSettings *settings; LibraryMap libraryMap; + QSet<QLibraryPrivate*> loadedLibs; }; Q_GLOBAL_STATIC(LibraryData, libraryData) @@ -443,7 +467,18 @@ bool QLibraryPrivate::load() return true; if (fileName.isEmpty()) return false; - return load_sys(); + + bool ret = load_sys(); + if (ret) { + //when loading a library we add a reference to it so that the QLibraryPrivate won't get deleted + //this allows to unload the library at a later time + if (LibraryData *lib = libraryData()) { + lib->loadedLibs += this; + libraryRefCount.ref(); + } + } + + return ret; } bool QLibraryPrivate::unload() @@ -451,10 +486,16 @@ bool QLibraryPrivate::unload() if (!pHnd) return false; if (!libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to - if (instance) - delete instance(); + delete inst.data(); if (unload_sys()) { - instance = 0; + if (qt_debug_component()) + qWarning() << "QLibraryPrivate::unload succeeded on" << fileName; + //when the library is unloaded, we release the reference on it so that 'this' + //can get deleted + if (LibraryData *lib = libraryData()) { + if (lib->loadedLibs.remove(this)) + libraryRefCount.deref(); + } pHnd = 0; } } @@ -496,7 +537,7 @@ bool QLibraryPrivate::loadPlugin() \table \header \i Platform \i Valid suffixes - \row \i Windows \i \c .dll + \row \i Windows \i \c .dll, \c .DLL \row \i Unix/Linux \i \c .so \row \i AIX \i \c .a \row \i HP-UX \i \c .sl, \c .so (HP-UXi) @@ -509,7 +550,7 @@ bool QLibraryPrivate::loadPlugin() bool QLibrary::isLibrary(const QString &fileName) { #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) - return fileName.endsWith(QLatin1String(".dll")); + return fileName.endsWith(QLatin1String(".dll"), Qt::CaseInsensitive); #elif defined(Q_OS_SYMBIAN) // Plugin stubs are also considered libraries in Symbian. return (fileName.endsWith(QLatin1String(".dll")) || @@ -571,6 +612,46 @@ bool QLibrary::isLibrary(const QString &fileName) } +#if defined (Q_OS_WIN) && defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(Q_CC_INTEL) +#define QT_USE_MS_STD_EXCEPTION 1 +const char* qt_try_versioninfo(void *pfn, bool *exceptionThrown) +{ + *exceptionThrown = false; + const char *szData = 0; + typedef const char * (*VerificationFunction)(); + VerificationFunction func = reinterpret_cast<VerificationFunction>(pfn); + __try { + if(func) + szData = func(); + } __except(EXCEPTION_EXECUTE_HANDLER) { + *exceptionThrown = true; + } + return szData; +} +#endif + +#ifdef Q_CC_BOR +typedef const char * __stdcall (*QtPluginQueryVerificationDataFunction)(); +#else +typedef const char * (*QtPluginQueryVerificationDataFunction)(); +#endif + +bool qt_get_verificationdata(QtPluginQueryVerificationDataFunction pfn, uint *qt_version, bool *debug, QByteArray *key, bool *exceptionThrown) +{ + *exceptionThrown = false; + const char *szData = 0; + if (!pfn) + return false; +#ifdef QT_USE_MS_STD_EXCEPTION + szData = qt_try_versioninfo((void *)pfn, exceptionThrown); + if (*exceptionThrown) + return false; +#else + szData = pfn(); +#endif + return qt_parse_pattern(szData, qt_version, debug, key); +} + bool QLibraryPrivate::isPlugin(QSettings *settings) { errorString.clear(); @@ -646,70 +727,82 @@ bool QLibraryPrivate::isPlugin(QSettings *settings) } else #endif { - bool temporary_load = false; + bool retryLoadLibrary = false; // Only used on Windows with MS compiler.(false in other cases) + do { + bool temporary_load = false; #ifdef Q_OS_WIN - HMODULE hTempModule = 0; + HMODULE hTempModule = 0; #endif - if (!pHnd) { + if (!pHnd) { #ifdef Q_OS_WIN - //avoid 'Bad Image' message box - UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - hTempModule = ::LoadLibraryEx((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, DONT_RESOLVE_DLL_REFERENCES); - SetErrorMode(oldmode); + DWORD dwFlags = (retryLoadLibrary) ? 0: DONT_RESOLVE_DLL_REFERENCES; + //avoid 'Bad Image' message box + UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); + hTempModule = ::LoadLibraryEx((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, dwFlags); + SetErrorMode(oldmode); #else # if defined(Q_OS_SYMBIAN) - //Guard against accidentally trying to load non-plugin libraries by making sure the stub exists - if (fileinfo.exists()) + //Guard against accidentally trying to load non-plugin libraries by making sure the stub exists + if (fileinfo.exists()) # endif - temporary_load = load_sys(); + temporary_load = load_sys(); #endif - } -# ifdef Q_CC_BOR - typedef const char * __stdcall (*QtPluginQueryVerificationDataFunction)(); -# else - typedef const char * (*QtPluginQueryVerificationDataFunction)(); -# endif + } #ifdef Q_OS_WIN - QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = hTempModule - ? (QtPluginQueryVerificationDataFunction) + QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = hTempModule ? (QtPluginQueryVerificationDataFunction) #ifdef Q_OS_WINCE - ::GetProcAddress(hTempModule, L"qt_plugin_query_verification_data") + ::GetProcAddress(hTempModule, L"qt_plugin_query_verification_data") #else - ::GetProcAddress(hTempModule, "qt_plugin_query_verification_data") + ::GetProcAddress(hTempModule, "qt_plugin_query_verification_data") #endif : (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); #else - QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = NULL; + QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = NULL; # if defined(Q_OS_SYMBIAN) - if (temporary_load) { - qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); - // If resolving with function name failed (i.e. not STDDLL), try resolving using known ordinal - if (!qtPluginQueryVerificationDataFunction) - qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("1"); - } + if (temporary_load) { + qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); + // If resolving with function name failed (i.e. not STDDLL), try resolving using known ordinal + if (!qtPluginQueryVerificationDataFunction) + qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("1"); + } # else - qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); + qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); # endif #endif - - if (!qtPluginQueryVerificationDataFunction - || !qt_parse_pattern(qtPluginQueryVerificationDataFunction(), &qt_version, &debug, &key)) { - qt_version = 0; - key = "unknown"; - if (temporary_load) - unload_sys(); - } else { - success = true; - } -#ifdef Q_OS_WIN - if (hTempModule) { - BOOL ok = ::FreeLibrary(hTempModule); - if (ok) { - hTempModule = 0; + bool exceptionThrown = false; + bool ret = qt_get_verificationdata(qtPluginQueryVerificationDataFunction, + &qt_version, &debug, &key, &exceptionThrown); + if (!exceptionThrown) { + if (!ret) { + qt_version = 0; + key = "unknown"; + if (temporary_load) + unload_sys(); + } else { + success = true; + } + retryLoadLibrary = false; + } +#ifdef QT_USE_MS_STD_EXCEPTION + else { + // An exception was thrown when calling qt_plugin_query_verification_data(). + // This usually happens when plugin is compiled with the /clr compiler flag, + // & will only work if the dependencies are loaded & DLLMain() is called. + // LoadLibrary() will do this, try once with this & if it fails dont load. + retryLoadLibrary = !retryLoadLibrary; } +#endif +#ifdef Q_OS_WIN + if (hTempModule) { + BOOL ok = ::FreeLibrary(hTempModule); + if (ok) { + hTempModule = 0; + } - } + } #endif + } while(retryLoadLibrary); // Will be 'false' in all cases other than when an + // exception is thrown(will happen only when using a MS compiler) } // Qt 4.5 compatibility: stl doesn't affect binary compatibility @@ -759,6 +852,9 @@ bool QLibraryPrivate::isPlugin(QSettings *settings) #ifdef QT_BUILD_KEY_COMPAT2 && key != QT_BUILD_KEY_COMPAT2 #endif +#ifdef QT_BUILD_KEY_COMPAT3 + && key != QT_BUILD_KEY_COMPAT3 +#endif ) { if (qt_debug_component()) { qWarning("In %s:\n" @@ -1039,7 +1135,7 @@ void QLibrary::setFileNameAndVersion(const QString &fileName, const QString &ver */ void *QLibrary::resolve(const char *symbol) { - if (!load()) + if (!isLoaded() && !load()) return 0; return d->resolve(symbol); } @@ -1182,15 +1278,11 @@ QLibrary::LoadHints QLibrary::loadHints() const /* Internal, for debugging */ bool qt_debug_component() { -#if defined(QT_DEBUG_COMPONENT) - return true; //compatibility? -#else static int debug_env = -1; if (debug_env == -1) debug_env = QT_PREPEND_NAMESPACE(qgetenv)("QT_DEBUG_PLUGINS").toInt(); return debug_env != 0; -#endif } QT_END_NAMESPACE diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h index 02dc523..b73fce5 100644 --- a/src/corelib/plugin/qlibrary_p.h +++ b/src/corelib/plugin/qlibrary_p.h @@ -60,6 +60,7 @@ #include "QtCore/qpointer.h" #include "QtCore/qstringlist.h" #include "QtCore/qplugin.h" +#include "QtCore/qsharedpointer.h" #ifndef QT_NO_LIBRARY @@ -90,6 +91,7 @@ public: static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString()); + QWeakPointer<QObject> inst; QtPluginInstanceFunction instance; uint qt_version; QString lastModified; diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp index e8f0eae..9ad1c01 100644 --- a/src/corelib/plugin/qlibrary_unix.cpp +++ b/src/corelib/plugin/qlibrary_unix.cpp @@ -223,11 +223,15 @@ bool QLibraryPrivate::load_sys() #ifdef Q_OS_MAC if (!pHnd) { - if (CFBundleRef bundle = CFBundleGetBundleWithIdentifier(QCFString(fileName))) { + QByteArray utf8Bundle = fileName.toUtf8(); + QCFType<CFURLRef> bundleUrl = CFURLCreateFromFileSystemRepresentation(NULL, reinterpret_cast<const UInt8*>(utf8Bundle.data()), utf8Bundle.length(), true); + QCFType<CFBundleRef> bundle = CFBundleCreate(NULL, bundleUrl); + if(bundle) { QCFType<CFURLRef> url = CFBundleCopyExecutableURL(bundle); - QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); - pHnd = dlopen(QFile::encodeName(str), dlFlags); - attempt = str; + char executableFile[FILENAME_MAX]; + CFURLGetFileSystemRepresentation(url, true, reinterpret_cast<UInt8*>(executableFile), FILENAME_MAX); + attempt = QString::fromUtf8(executableFile); + pHnd = dlopen(QFile::encodeName(attempt), dlFlags); } } #endif diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h index 7f541f1..bd49b15 100644 --- a/src/corelib/plugin/qplugin.h +++ b/src/corelib/plugin/qplugin.h @@ -101,13 +101,17 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio // NOTE: if you change pattern, you MUST change the pattern in // qlibrary.cpp as well. changing the pattern will break all // backwards compatibility as well (no old plugins will be loaded). +// QT5: should probably remove the entire pattern thing and do the section +// trick for all platforms. for now, keep it and fallback to scan for it. # ifdef QPLUGIN_DEBUG_STR # undef QPLUGIN_DEBUG_STR # endif # ifdef QT_NO_DEBUG # define QPLUGIN_DEBUG_STR "false" +# define QPLUGIN_SECTION_DEBUG_STR "" # else # define QPLUGIN_DEBUG_STR "true" +# define QPLUGIN_SECTION_DEBUG_STR ".debug" # endif # define Q_PLUGIN_VERIFICATION_DATA \ static const char qt_plugin_verification_data[] = \ @@ -116,6 +120,13 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio "debug="QPLUGIN_DEBUG_STR"\n" \ "buildkey="QT_BUILD_KEY; +# if defined (Q_OF_ELF) && defined (Q_CC_GNU) +# define Q_PLUGIN_VERIFICATION_SECTION \ + __attribute__ ((section (".qtplugin"))) __attribute__((used)) +# else +# define Q_PLUGIN_VERIFICATION_SECTION +# endif + # if defined (Q_OS_WIN32) && defined(Q_CC_BOR) # define Q_STANDARD_CALL __stdcall # else @@ -123,7 +134,7 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio # endif # define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \ - Q_PLUGIN_VERIFICATION_DATA \ + Q_PLUGIN_VERIFICATION_SECTION Q_PLUGIN_VERIFICATION_DATA \ Q_EXTERN_C Q_DECL_EXPORT \ const char * Q_STANDARD_CALL qt_plugin_query_verification_data() \ { return qt_plugin_verification_data; } \ diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp index b1d1ecc..9f322df 100644 --- a/src/corelib/plugin/qpluginloader.cpp +++ b/src/corelib/plugin/qpluginloader.cpp @@ -198,11 +198,11 @@ QPluginLoader::~QPluginLoader() */ QObject *QPluginLoader::instance() { - if (!load()) + if (!isLoaded() && !load()) return 0; - if (d->instance) - return d->instance(); - return 0; + if (!d->inst && d->instance) + d->inst = d->instance(); + return d->inst.data(); } /*! diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 6324cc9..98f7931 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -793,7 +793,7 @@ void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &tr } // We require that at least one animation is valid. // ### generalize - QList<QVariantAnimation*> variantAnims = qFindChildren<QVariantAnimation*>(anim); + QList<QVariantAnimation*> variantAnims = anim->findChildren<QVariantAnimation*>(); if (QVariantAnimation *va = qobject_cast<QVariantAnimation*>(anim)) variantAnims.append(va); @@ -1178,7 +1178,7 @@ void QStateMachinePrivate::removeStartState() void QStateMachinePrivate::clearHistory() { Q_Q(QStateMachine); - QList<QHistoryState*> historyStates = qFindChildren<QHistoryState*>(q); + QList<QHistoryState*> historyStates = q->findChildren<QHistoryState*>(); for (int i = 0; i < historyStates.size(); ++i) { QHistoryState *h = historyStates.at(i); QHistoryStatePrivate::get(h)->configuration.clear(); @@ -1389,7 +1389,7 @@ void QStateMachinePrivate::cancelAllDelayedEvents() delayedEvents.clear(); } -namespace { +namespace _QStateMachine_Internal{ class GoToStateTransition : public QAbstractTransition { @@ -1403,7 +1403,9 @@ protected: }; } // namespace - +// mingw compiler tries to export QObject::findChild<GoToStateTransition>(), +// which doesn't work if its in an anonymous namespace. +using namespace _QStateMachine_Internal; /*! \internal @@ -1440,7 +1442,7 @@ void QStateMachinePrivate::goToState(QAbstractState *targetState) Q_ASSERT(sourceState != 0); // Reuse previous GoToStateTransition in case of several calls to // goToState() in a row. - GoToStateTransition *trans = qFindChild<GoToStateTransition*>(sourceState); + GoToStateTransition *trans = sourceState->findChild<GoToStateTransition*>(); if (!trans) { trans = new GoToStateTransition(targetState); sourceState->addTransition(trans); @@ -1562,7 +1564,7 @@ void QStateMachinePrivate::unregisterAllTransitions() { Q_Q(QStateMachine); { - QList<QSignalTransition*> transitions = qFindChildren<QSignalTransition*>(rootState()); + QList<QSignalTransition*> transitions = rootState()->findChildren<QSignalTransition*>(); for (int i = 0; i < transitions.size(); ++i) { QSignalTransition *t = transitions.at(i); if (t->machine() == q) @@ -1570,7 +1572,7 @@ void QStateMachinePrivate::unregisterAllTransitions() } } { - QList<QEventTransition*> transitions = qFindChildren<QEventTransition*>(rootState()); + QList<QEventTransition*> transitions = rootState()->findChildren<QEventTransition*>(); for (int i = 0; i < transitions.size(); ++i) { QEventTransition *t = transitions.at(i); if (t->machine() == q) diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index 43df13a..b85a22d 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -130,7 +130,7 @@ QMutex::QMutex(RecursionMode mode) \warning Destroying a locked mutex may result in undefined behavior. */ QMutex::~QMutex() -{ delete d; } +{ delete static_cast<QMutexPrivate *>(d); } /*! Locks the mutex. If another thread has locked the mutex then this @@ -146,6 +146,7 @@ QMutex::~QMutex() */ void QMutex::lock() { + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); Qt::HANDLE self; if (d->recursive) { @@ -158,11 +159,6 @@ void QMutex::lock() bool isLocked = d->contenders.fetchAndAddAcquire(1) == 0; if (!isLocked) { -#ifndef QT_NO_DEBUG - if (d->owner == self) - qWarning() << "QMutex::lock: Deadlock detected in thread" << d->owner; -#endif - // didn't get the lock, wait for it isLocked = d->wait(); Q_ASSERT_X(isLocked, "QMutex::lock", @@ -178,54 +174,11 @@ void QMutex::lock() return; } -#ifndef QT_NO_DEBUG - self = QThread::currentThreadId(); -#endif bool isLocked = d->contenders == 0 && d->contenders.testAndSetAcquire(0, 1); if (!isLocked) { - int spinCount = 0; - int lastSpinCount = d->lastSpinCount; - - enum { AdditionalSpins = 20, SpinCountPenalizationDivisor = 4 }; - const int maximumSpinCount = lastSpinCount + AdditionalSpins; - - do { - if (spinCount++ > maximumSpinCount) { - // puts("spinning useless, sleeping"); - isLocked = d->contenders.fetchAndAddAcquire(1) == 0; - if (!isLocked) { -#ifndef QT_NO_DEBUG - if (d->owner == self) - qWarning() << "QMutex::lock: Deadlock detected in thread" << d->owner; -#endif - - // didn't get the lock, wait for it - isLocked = d->wait(); - Q_ASSERT_X(isLocked, "QMutex::lock", - "Internal error, infinite wait has timed out."); - - // don't need to wait for the lock anymore - d->contenders.deref(); - } - // decrease the lastSpinCount since we didn't actually get the lock by spinning - spinCount = -d->lastSpinCount / SpinCountPenalizationDivisor; - break; - } - - isLocked = d->contenders == 0 && d->contenders.testAndSetAcquire(0, 1); - } while (!isLocked); - - // adjust the last spin lock count - lastSpinCount = d->lastSpinCount; - d->lastSpinCount = spinCount >= 0 - ? qMax(lastSpinCount, spinCount) - : lastSpinCount + spinCount; + lockInternal(); } - -#ifndef QT_NO_DEBUG - d->owner = self; -#endif } /*! @@ -247,6 +200,7 @@ void QMutex::lock() */ bool QMutex::tryLock() { + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); Qt::HANDLE self; if (d->recursive) { @@ -270,18 +224,12 @@ bool QMutex::tryLock() return isLocked; } -#ifndef QT_NO_DEBUG - self = QThread::currentThreadId(); -#endif bool isLocked = d->contenders == 0 && d->contenders.testAndSetAcquire(0, 1); if (!isLocked) { // some other thread has the mutex locked, or we tried to // recursively lock an non-recursive mutex return isLocked; } -#ifndef QT_NO_DEBUG - d->owner = self; -#endif return isLocked; } @@ -310,6 +258,7 @@ bool QMutex::tryLock() */ bool QMutex::tryLock(int timeout) { + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); Qt::HANDLE self; if (d->recursive) { @@ -337,9 +286,6 @@ bool QMutex::tryLock(int timeout) return true; } -#ifndef QT_NO_DEBUG - self = QThread::currentThreadId(); -#endif bool isLocked = d->contenders.fetchAndAddAcquire(1) == 0; if (!isLocked) { // didn't get the lock, wait for it @@ -350,9 +296,6 @@ bool QMutex::tryLock(int timeout) if (!isLocked) return false; } -#ifndef QT_NO_DEBUG - d->owner = self; -#endif return true; } @@ -366,8 +309,7 @@ bool QMutex::tryLock(int timeout) */ void QMutex::unlock() { - Q_ASSERT_X(d->owner == QThread::currentThreadId(), "QMutex::unlock()", - "A mutex must be unlocked in the same thread that locked it."); + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); if (d->recursive) { if (!--d->count) { @@ -376,9 +318,6 @@ void QMutex::unlock() d->wakeUp(); } } else { -#ifndef QT_NO_DEBUG - d->owner = 0; -#endif if (!d->contenders.testAndSetRelease(1, 0)) d->wakeUp(); } @@ -506,6 +445,72 @@ void QMutex::unlock() Use the constructor that takes a RecursionMode parameter instead. */ +/*! + \internal helper for lockInline() + */ +void QMutex::lockInternal() +{ + QMutexPrivate *d = static_cast<QMutexPrivate *>(this->d); + int spinCount = 0; + int lastSpinCount = d->lastSpinCount; + + enum { AdditionalSpins = 20, SpinCountPenalizationDivisor = 4 }; + const int maximumSpinCount = lastSpinCount + AdditionalSpins; + + do { + if (spinCount++ > maximumSpinCount) { + // puts("spinning useless, sleeping"); + bool isLocked = d->contenders.fetchAndAddAcquire(1) == 0; + if (!isLocked) { + + // didn't get the lock, wait for it + isLocked = d->wait(); + Q_ASSERT_X(isLocked, "QMutex::lock", + "Internal error, infinite wait has timed out."); + + // don't need to wait for the lock anymore + d->contenders.deref(); + } + // decrease the lastSpinCount since we didn't actually get the lock by spinning + spinCount = -d->lastSpinCount / SpinCountPenalizationDivisor; + break; + } + } while (d->contenders != 0 || !d->contenders.testAndSetAcquire(0, 1)); + + // adjust the last spin lock count + lastSpinCount = d->lastSpinCount; + d->lastSpinCount = spinCount >= 0 + ? qMax(lastSpinCount, spinCount) + : lastSpinCount + spinCount; +} + +/*! + \internal +*/ +void QMutex::unlockInternal() +{ + static_cast<QMutexPrivate *>(d)->wakeUp(); +} + +/*! + \fn QMutex::lockInline() + \internal + inline version of QMutex::lock() +*/ + +/*! + \fn QMutex::unlockInline() + \internal + inline version of QMutex::unlock() +*/ + +/*! + \fn QMutex::tryLockInline() + \internal + inline version of QMutex::tryLock() +*/ + + QT_END_NAMESPACE #endif // QT_NO_THREAD diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h index 509f300..710b794 100644 --- a/src/corelib/thread/qmutex.h +++ b/src/corelib/thread/qmutex.h @@ -43,6 +43,7 @@ #define QMUTEX_H #include <QtCore/qglobal.h> +#include <QtCore/qatomic.h> #include <new> QT_BEGIN_HEADER @@ -53,7 +54,8 @@ QT_MODULE(Core) #ifndef QT_NO_THREAD -class QMutexPrivate; +class QAtomicInt; +class QMutexData; class Q_CORE_EXPORT QMutex { @@ -66,10 +68,13 @@ public: explicit QMutex(RecursionMode mode = NonRecursive); ~QMutex(); - void lock(); - bool tryLock(); + void lock(); //### Qt5: make inline; + inline void lockInline(); + bool tryLock(); //### Qt5: make inline; bool tryLock(int timeout); - void unlock(); + inline bool tryLockInline(); + void unlock(); //### Qt5: make inline; + inline void unlockInline(); #if defined(QT3_SUPPORT) inline QT3_SUPPORT bool locked() @@ -86,9 +91,11 @@ public: #endif private: + void lockInternal(); + void unlockInternal(); Q_DISABLE_COPY(QMutex) - QMutexPrivate *d; + QMutexData *d; }; class Q_CORE_EXPORT QMutexLocker @@ -99,7 +106,7 @@ public: Q_ASSERT_X((reinterpret_cast<quintptr>(m) & quintptr(1u)) == quintptr(0), "QMutexLocker", "QMutex pointer is misaligned"); if (m) { - m->lock(); + m->lockInline(); val = reinterpret_cast<quintptr>(m) | quintptr(1u); } else { val = 0; @@ -111,7 +118,7 @@ public: { if ((val & quintptr(1u)) == quintptr(1u)) { val &= ~quintptr(1u); - mutex()->unlock(); + mutex()->unlockInline(); } } @@ -119,7 +126,7 @@ public: { if (val) { if ((val & quintptr(1u)) == quintptr(0u)) { - mutex()->lock(); + mutex()->lockInline(); val |= quintptr(1u); } } @@ -145,6 +152,46 @@ private: quintptr val; }; +class QMutexData +{ + public: + QAtomicInt contenders; + const uint recursive : 1; + uint reserved : 31; + protected: + QMutexData(QMutex::RecursionMode mode); + ~QMutexData(); +}; + +inline void QMutex::unlockInline() +{ + if (d->recursive) { + unlock(); + } else if (!d->contenders.testAndSetRelease(1, 0)) { + unlockInternal(); + } +} + +inline bool QMutex::tryLockInline() +{ + if (d->recursive) { + return tryLock(); + } else { + return d->contenders.testAndSetAcquire(0, 1); + } +} + +inline void QMutex::lockInline() +{ + if (d->recursive) { + lock(); + } else if(!tryLockInline()) { + lockInternal(); + } +} + + + #else // QT_NO_THREAD @@ -157,9 +204,11 @@ public: inline ~QMutex() {} static inline void lock() {} - static inline bool tryLock() { return true; } - static inline bool tryLock(int timeout) { Q_UNUSED(timeout); return true; } - static void unlock() {} + static inline void lockInline() {} + static inline bool tryLock(int timeout = 0) { Q_UNUSED(timeout); return true; } + static inline bool tryLockInline() { return true; } + static inline void unlock() {} + static inline void unlockInline() {} #if defined(QT3_SUPPORT) static inline QT3_SUPPORT bool locked() { return false; } diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h index dce162a..6126423 100644 --- a/src/corelib/thread/qmutex_p.h +++ b/src/corelib/thread/qmutex_p.h @@ -56,10 +56,11 @@ #include <QtCore/qglobal.h> #include <QtCore/qnamespace.h> +#include <QtCore/qmutex.h> QT_BEGIN_NAMESPACE -class QMutexPrivate { +class QMutexPrivate : public QMutexData { public: QMutexPrivate(QMutex::RecursionMode mode); ~QMutexPrivate(); @@ -68,8 +69,6 @@ public: bool wait(int timeout = -1); void wakeUp(); - const bool recursive; - QAtomicInt contenders; volatile int lastSpinCount; Qt::HANDLE owner; uint count; @@ -83,6 +82,12 @@ public: #endif }; +inline QMutexData::QMutexData(QMutex::RecursionMode mode) + : recursive(mode == QMutex::Recursive) +{} + +inline QMutexData::~QMutexData() {} + QT_END_NAMESPACE #endif // QMUTEX_P_H diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp index a58368c..7e7ef22 100644 --- a/src/corelib/thread/qmutex_unix.cpp +++ b/src/corelib/thread/qmutex_unix.cpp @@ -63,7 +63,7 @@ static void report_error(int code, const char *where, const char *what) QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode) - : recursive(mode == QMutex::Recursive), contenders(0), lastSpinCount(0), owner(0), count(0), wakeup(false) + : QMutexData(mode), lastSpinCount(0), owner(0), count(0), wakeup(false) { report_error(pthread_mutex_init(&mutex, NULL), "QMutex", "mutex init"); report_error(pthread_cond_init(&cond, NULL), "QMutex", "cv init"); diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp index 9d58953..a810000 100644 --- a/src/corelib/thread/qmutex_win.cpp +++ b/src/corelib/thread/qmutex_win.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode) - : recursive(mode == QMutex::Recursive), contenders(0), lastSpinCount(0), owner(0), count(0) + : QMutexData(mode), lastSpinCount(0), owner(0), count(0) { event = CreateEvent(0, FALSE, FALSE, 0); if (!event) diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h index 702125c..375ded1 100644 --- a/src/corelib/thread/qorderedmutexlocker_p.h +++ b/src/corelib/thread/qorderedmutexlocker_p.h @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE -class QMutex; +#include <QtCore/qmutex.h> /* Locks 2 mutexes in a defined order, avoiding a recursive lock if @@ -79,8 +79,8 @@ public: void relock() { if (!locked) { - if (mtx1) mtx1->lock(); - if (mtx2) mtx2->lock(); + if (mtx1) mtx1->lockInline(); + if (mtx2) mtx2->lockInline(); locked = true; } } @@ -88,8 +88,8 @@ public: void unlock() { if (locked) { - if (mtx1) mtx1->unlock(); - if (mtx2) mtx2->unlock(); + if (mtx1) mtx1->unlockInline(); + if (mtx2) mtx2->unlockInline(); locked = false; } } @@ -100,10 +100,10 @@ public: if (mtx1 == mtx2) return false; if (mtx1 < mtx2) { - mtx2->lock(); + mtx2->lockInline(); return true; } - if (!mtx2->tryLock()) { + if (!mtx2->tryLockInline()) { mtx1->unlock(); mtx2->lock(); mtx1->lock(); diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index a44a0e8..daf1a93 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -83,7 +83,9 @@ # define old_qDebug qDebug # undef qDebug # endif +#ifndef QT_NO_CORESERVICES # include <CoreServices/CoreServices.h> +#endif //QT_NO_CORESERVICES # ifdef old_qDebug # undef qDebug @@ -388,7 +390,7 @@ int QThread::idealThreadCount() { int cores = -1; -#if defined(Q_OS_MAC) +#if defined(Q_OS_MAC) && !defined(Q_WS_QPA) // Mac OS X cores = MPProcessorsScheduled(); #elif defined(Q_OS_HPUX) @@ -506,6 +508,7 @@ void QThread::usleep(unsigned long usecs) // Does some magic and calculate the Unix scheduler priorities // sched_policy is IN/OUT: it must be set to a valid policy before calling this function // sched_priority is OUT only +#if defined(Q_OS_DARWIN) || !defined(Q_OS_OPENBSD) && defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING-0 >= 0) static bool calculateUnixPriority(int priority, int *sched_policy, int *sched_priority) { #ifdef SCHED_IDLE @@ -533,6 +536,7 @@ static bool calculateUnixPriority(int priority, int *sched_policy, int *sched_pr *sched_priority = prio; return true; } +#endif void QThread::start(Priority priority) { diff --git a/src/corelib/thread/qthreadstorage.h b/src/corelib/thread/qthreadstorage.h index 3a786ba..6264674 100644 --- a/src/corelib/thread/qthreadstorage.h +++ b/src/corelib/thread/qthreadstorage.h @@ -91,8 +91,6 @@ inline void qThreadStorage_setLocalData(QThreadStorageData &d, T **t) { (void) d.set(*t); } -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION - // value-based specialization template <typename T> inline @@ -116,8 +114,6 @@ inline void qThreadStorage_setLocalData(QThreadStorageData &d, T *t) { (void) d.set(new T(*t)); } -#endif // QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION - // MOC_SKIP_END #endif diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp index 04018ba..a1ad787 100644 --- a/src/corelib/tools/qbitarray.cpp +++ b/src/corelib/tools/qbitarray.cpp @@ -418,6 +418,13 @@ void QBitArray::fill(bool value, int begin, int end) this bit array. */ +/*! \fn void QBitArray::swap(QBitArray &other) + \since 4.8 + + Swaps bit array \a other with this bit array. This operation is very + fast and never fails. +*/ + /*! \fn bool QBitArray::operator==(const QBitArray &other) const Returns true if \a other is equal to this bit array; otherwise diff --git a/src/corelib/tools/qbitarray.h b/src/corelib/tools/qbitarray.h index 60cdc9c..ddda5e7 100644 --- a/src/corelib/tools/qbitarray.h +++ b/src/corelib/tools/qbitarray.h @@ -63,6 +63,12 @@ public: explicit QBitArray(int size, bool val = false); QBitArray(const QBitArray &other) : d(other.d) {} inline QBitArray &operator=(const QBitArray &other) { d = other.d; return *this; } +#ifdef Q_COMPILER_RVALUE_REFS + inline QBitArray &operator=(QBitArray &&other) + { qSwap(d, other.d); return *this; } +#endif + + inline void swap(QBitArray &other) { qSwap(d, other.d); } inline int size() const { return (d.size() << 3) - *d.constData(); } inline int count() const { return (d.size() << 3) - *d.constData(); } diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index fac0f45..dc2e8e9 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -541,12 +541,14 @@ QByteArray qUncompress(const uchar* data, int nbytes) forever { ulong alloc = len; - d.reset(q_check_ptr(static_cast<QByteArray::Data *>(qRealloc(d.take(), sizeof(QByteArray::Data) + alloc)))); - if (!d) { + QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + alloc)); + if (!p) { // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS qWarning("qUncompress: could not allocate enough memory to uncompress data"); return QByteArray(); } + d.take(); // realloc was successful + d.reset(p); int res = ::uncompress((uchar*)d->array, &len, (uchar*)data+4, nbytes-4); @@ -554,12 +556,14 @@ QByteArray qUncompress(const uchar* data, int nbytes) switch (res) { case Z_OK: if (len != alloc) { - d.reset(q_check_ptr(static_cast<QByteArray::Data *>(qRealloc(d.take(), sizeof(QByteArray::Data) + len)))); - if (!d) { + QByteArray::Data *p = static_cast<QByteArray::Data *>(qRealloc(d.data(), sizeof(QByteArray::Data) + len)); + if (!p) { // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS qWarning("qUncompress: could not allocate enough memory to uncompress data"); return QByteArray(); } + d.take(); // realloc was successful + d.reset(p); } d->ref = 1; d->alloc = d->size = len; @@ -900,6 +904,13 @@ QByteArray &QByteArray::operator=(const char *str) return *this; } +/*! \fn void QByteArray::swap(QByteArray &other) + \since 4.8 + + Swaps byte array \a other with this byte array. This operation is very + fast and never fails. +*/ + /*! \fn int QByteArray::size() const Returns the number of bytes in this byte array. diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index a3fe3f5..b625f4c 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -144,6 +144,12 @@ public: QByteArray &operator=(const QByteArray &); QByteArray &operator=(const char *str); +#ifdef Q_COMPILER_RVALUE_REFS + inline QByteArray &operator=(QByteArray &&other) + { qSwap(d, other.d); return *this; } +#endif + + inline void swap(QByteArray &other) { qSwap(d, other.d); } inline int size() const; bool isEmpty() const; diff --git a/src/corelib/tools/qcache.h b/src/corelib/tools/qcache.h index 44477d7..debab7d 100644 --- a/src/corelib/tools/qcache.h +++ b/src/corelib/tools/qcache.h @@ -61,7 +61,7 @@ class QCache }; Node *f, *l; QHash<Key, Node> hash; - void *unused; + void *unused; // ### Qt5: remove int mx, total; inline void unlink(Node &n) { diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp index 3ba5186..7880bd3 100644 --- a/src/corelib/tools/qcontiguouscache.cpp +++ b/src/corelib/tools/qcontiguouscache.cpp @@ -194,6 +194,13 @@ MyRecord record(int row) const Assigns \a other to this cache and returns a reference to this cache. */ +/*! \fn void QContiguousCache::swap(QContiguousCache<T> &other) + \since 4.8 + + Swaps cache \a other with this cache. This operation is very + fast and never fails. +*/ + /*! \fn bool QContiguousCache::operator==(const QContiguousCache<T> &other) const Returns true if \a other is equal to this cache; otherwise returns false. diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h index f767962..3d0a159 100644 --- a/src/corelib/tools/qcontiguouscache.h +++ b/src/corelib/tools/qcontiguouscache.h @@ -110,6 +110,11 @@ public: inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } QContiguousCache<T> &operator=(const QContiguousCache<T> &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QContiguousCache<T> &operator=(QContiguousCache<T> &&other) + { qSwap(d, other.d); return *this; } +#endif + inline void swap(QContiguousCache<T> &other) { qSwap(d, other.d); } bool operator==(const QContiguousCache<T> &other) const; inline bool operator!=(const QContiguousCache<T> &other) const { return !(*this == other); } diff --git a/src/corelib/tools/qelapsedtimer.cpp b/src/corelib/tools/qelapsedtimer.cpp index ee7c9b9..28d3450 100644 --- a/src/corelib/tools/qelapsedtimer.cpp +++ b/src/corelib/tools/qelapsedtimer.cpp @@ -136,10 +136,11 @@ QT_BEGIN_NAMESPACE implementations, to guarantee that the same reference clock is being used. - \value SystemTime The human-readable system time. This clock is not monotonic. - \value MonotonicClock The system's monotonic clock, usually found in Unix systems. This clock is monotonic and does not overflow. - \value TickCounter The system's tick counter, used on Windows and Symbian systems. This clock may overflow. - \value MachAbsoluteTime The Mach kernel's absolute time (Mac OS X). This clock is monotonic and does not overflow. + \value SystemTime The human-readable system time. This clock is not monotonic. + \value MonotonicClock The system's monotonic clock, usually found in Unix systems. This clock is monotonic and does not overflow. + \value TickCounter The system's tick counter, used on Windows and Symbian systems. This clock may overflow. + \value MachAbsoluteTime The Mach kernel's absolute time (Mac OS X). This clock is monotonic and does not overflow. + \value PerformanceCounter The high-resolution performance counter provided by Windows. This clock is monotonic and does not overflow. \section2 SystemTime @@ -163,7 +164,9 @@ QT_BEGIN_NAMESPACE The tick counter clock type is based on the system's or the processor's tick counter, multiplied by the duration of a tick. This clock type is - used on Windows and Symbian platforms. + used on Windows and Symbian platforms. If the high-precision performance + counter is available on Windows, the \tt{PerformanceCounter} clock type + is used instead. The TickCounter clock type is the only clock type that may overflow. Windows Vista and Windows Server 2008 support the extended 64-bit tick @@ -191,6 +194,16 @@ QT_BEGIN_NAMESPACE This clock is monotonic and does not overflow. + \section2 PerformanceCounter + + This clock uses the Windows functions \tt{QueryPerformanceCounter} and + \tt{QueryPerformanceFrequency} to access the system's high-precision + performance counter. Since this counter may not be available on all + systems, QElapsedTimer will fall back to the \tt{TickCounter} clock + automatically, if this clock cannot be used. + + This clock is monotonic and does not overflow. + \sa clockType(), isMonotonic() */ diff --git a/src/corelib/tools/qelapsedtimer.h b/src/corelib/tools/qelapsedtimer.h index 0d6f0be..b996f6a 100644 --- a/src/corelib/tools/qelapsedtimer.h +++ b/src/corelib/tools/qelapsedtimer.h @@ -57,7 +57,8 @@ public: SystemTime, MonotonicClock, TickCounter, - MachAbsoluteTime + MachAbsoluteTime, + PerformanceCounter }; static ClockType clockType(); static bool isMonotonic(); diff --git a/src/corelib/tools/qelapsedtimer_win.cpp b/src/corelib/tools/qelapsedtimer_win.cpp index 135196a..c77acaa 100644 --- a/src/corelib/tools/qelapsedtimer_win.cpp +++ b/src/corelib/tools/qelapsedtimer_win.cpp @@ -42,6 +42,9 @@ #include "qelapsedtimer.h" #include <windows.h> +// Result of QueryPerformanceFrequency, 0 indicates that the high resolution timer is unavailable +static quint64 counterFrequency = 0; + typedef ULONGLONG (WINAPI *PtrGetTickCount64)(void); static PtrGetTickCount64 ptrGetTickCount64 = 0; @@ -65,12 +68,44 @@ static void resolveLibs() ptrGetTickCount64 = (PtrGetTickCount64)GetProcAddress(kernel32, "GetTickCount64"); #endif + // Retrieve the number of high-resolution performance counter ticks per second + LARGE_INTEGER frequency; + if (!QueryPerformanceFrequency(&frequency)) { + counterFrequency = 0; + } else { + counterFrequency = frequency.QuadPart; + } + done = true; } +static inline qint64 ticksToMilliseconds(qint64 ticks) +{ + if (counterFrequency > 0) { + // QueryPerformanceCounter uses an arbitrary frequency + return ticks * 1000 / counterFrequency; + } else { + // GetTickCount(64) return milliseconds + return ticks; + } +} + static quint64 getTickCount() { resolveLibs(); + + // This avoids a division by zero and disables the high performance counter if it's not available + if (counterFrequency > 0) { + LARGE_INTEGER counter; + + if (QueryPerformanceCounter(&counter)) { + return counter.QuadPart; + } else { + qWarning("QueryPerformanceCounter failed, although QueryPerformanceFrequency succeeded."); + return 0; + } + } + if (ptrGetTickCount64) return ptrGetTickCount64(); @@ -85,7 +120,12 @@ static quint64 getTickCount() QElapsedTimer::ClockType QElapsedTimer::clockType() { - return TickCounter; + resolveLibs(); + + if (counterFrequency > 0) + return PerformanceCounter; + else + return TickCounter; } bool QElapsedTimer::isMonotonic() @@ -104,22 +144,24 @@ qint64 QElapsedTimer::restart() qint64 oldt1 = t1; t1 = getTickCount(); t2 = 0; - return t1 - oldt1; + return ticksToMilliseconds(t1 - oldt1); } qint64 QElapsedTimer::elapsed() const { - return getTickCount() - t1; + qint64 elapsed = getTickCount() - t1; + return ticksToMilliseconds(elapsed); } qint64 QElapsedTimer::msecsSinceReference() const { - return t1; + return ticksToMilliseconds(t1); } qint64 QElapsedTimer::msecsTo(const QElapsedTimer &other) const { - return other.t1 - t1; + qint64 difference = other.t1 - t1; + return ticksToMilliseconds(difference); } qint64 QElapsedTimer::secsTo(const QElapsedTimer &other) const diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 2971c06..3dc9c92 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -730,6 +730,20 @@ void QHashData::checkSanity() Assigns \a other to this hash and returns a reference to this hash. */ +/*! \fn void QHash::swap(QHash<Key, T> &other) + \since 4.8 + + Swaps hash \a other with this hash. This operation is very + fast and never fails. +*/ + +/*! \fn void QMultiHash::swap(QMultiHash<Key, T> &other) + \since 4.8 + + Swaps hash \a other with this hash. This operation is very + fast and never fails. +*/ + /*! \fn bool QHash::operator==(const QHash<Key, T> &other) const Returns true if \a other is equal to this hash; otherwise returns diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index c7e4bc1..21fca2d 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -225,7 +225,7 @@ struct QHashNode inline bool same_key(uint h0, const Key &key0) { return h0 == h && key0 == key; } }; -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION + #define Q_HASH_DECLARE_INT_NODES(key_type) \ template <class T> \ struct QHashDummyNode<key_type, T> { \ @@ -253,7 +253,6 @@ Q_HASH_DECLARE_INT_NODES(ushort); Q_HASH_DECLARE_INT_NODES(int); Q_HASH_DECLARE_INT_NODES(uint); #undef Q_HASH_DECLARE_INT_NODES -#endif // QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION template <class Key, class T> class QHash @@ -284,6 +283,11 @@ public: inline ~QHash() { if (!d->ref.deref()) freeData(d); } QHash<Key, T> &operator=(const QHash<Key, T> &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QHash<Key, T> &operator=(QHash<Key, T> &&other) + { qSwap(d, other.d); return *this; } +#endif + inline void swap(QHash<Key, T> &other) { qSwap(d, other.d); } bool operator==(const QHash<Key, T> &other) const; inline bool operator!=(const QHash<Key, T> &other) const { return !(*this == other); } @@ -513,8 +517,6 @@ Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode2(QHashData::Node *node) { #ifdef Q_CC_BOR concrete(node)->~QHashNode<Key, T>(); -#elif defined(QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION) - concrete(node)->~QHashNode(); #else concrete(node)->~Node(); #endif @@ -924,6 +926,7 @@ class QMultiHash : public QHash<Key, T> public: QMultiHash() {} QMultiHash(const QHash<Key, T> &other) : QHash<Key, T>(other) {} + inline void swap(QMultiHash<Key, T> &other) { QHash<Key, T>::swap(other); } // prevent QMultiHash<->QHash swaps inline typename QHash<Key, T>::iterator replace(const Key &key, const T &value) { return QHash<Key, T>::insert(key, value); } diff --git a/src/corelib/tools/qlinkedlist.cpp b/src/corelib/tools/qlinkedlist.cpp index 7213c6e..7b452fc 100644 --- a/src/corelib/tools/qlinkedlist.cpp +++ b/src/corelib/tools/qlinkedlist.cpp @@ -147,6 +147,13 @@ QLinkedListData QLinkedListData::shared_null = { list. */ +/*! \fn void QLinkedList::swap(QLinkedList<T> &other) + \since 4.8 + + Swaps list \a other with this list. This operation is very + fast and never fails. +*/ + /*! \fn bool QLinkedList::operator==(const QLinkedList<T> &other) const Returns true if \a other is equal to this list; otherwise returns diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index 9b3efa3..849bfd3 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -85,6 +85,11 @@ public: inline QLinkedList(const QLinkedList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach(); } ~QLinkedList(); QLinkedList<T> &operator=(const QLinkedList<T> &); +#ifdef Q_COMPILER_RVALUE_REFS + inline QLinkedList<T> &operator=(QLinkedList<T> &&other) + { qSwap(d, other.d); return *this; } +#endif + inline void swap(QLinkedList<T> &other) { qSwap(d, other.d); } bool operator==(const QLinkedList<T> &l) const; inline bool operator!=(const QLinkedList<T> &l) const { return !(*this == l); } diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index 9ba3768..5706171 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -602,6 +602,13 @@ void **QListData::erase(void **xi) list. */ +/*! \fn void QList::swap(QList<T> &other) + \since 4.8 + + Swaps list \a other with this list. This operation is very + fast and never fails. +*/ + /*! \fn bool QList::operator==(const QList<T> &other) const Returns true if \a other is equal to this list; otherwise returns diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index d843cbe..b1fcabf 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -50,6 +50,10 @@ #include <iterator> #include <list> #endif +#ifdef Q_COMPILER_INITIALIZER_LISTS +#include <iterator> +#include <initializer_list> +#endif #include <new> #include <limits.h> @@ -118,6 +122,15 @@ public: inline QList(const QList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach_helper(); } ~QList(); QList<T> &operator=(const QList<T> &l); +#ifdef Q_COMPILER_RVALUE_REFS + inline QList &operator=(QList &&other) + { qSwap(d, other.d); return *this; } +#endif + inline void swap(QList<T> &other) { qSwap(d, other.d); } +#ifdef Q_COMPILER_INITIALIZER_LISTS + inline QList(std::initializer_list<T> args) : d(&QListData::shared_null) + { d->ref.ref(); qCopy(args.begin(), args.end(), std::back_inserter(*this)); } +#endif bool operator==(const QList<T> &l) const; inline bool operator!=(const QList<T> &l) const { return !(*this == l); } @@ -713,7 +726,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper() template <typename T> Q_OUTOFLINE_TEMPLATE QList<T>::~QList() { - if (d && !d->ref.deref()) + if (!d->ref.deref()) free(d); } @@ -741,8 +754,7 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::free(QListData::Data *data) { node_destruct(reinterpret_cast<Node *>(data->array + data->begin), reinterpret_cast<Node *>(data->array + data->end)); - if (data->ref == 0) - qFree(data); + qFree(data); } diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp index 3143ee4..5a5fffd 100644 --- a/src/corelib/tools/qmap.cpp +++ b/src/corelib/tools/qmap.cpp @@ -404,6 +404,20 @@ void QMapData::dump() Assigns \a other to this map and returns a reference to this map. */ +/*! \fn void QMap::swap(QMap<Key, T> &other) + \since 4.8 + + Swaps map \a other with this map. This operation is very + fast and never fails. +*/ + +/*! \fn void QMultiMap::swap(QMultiMap<Key, T> &other) + \since 4.8 + + Swaps map \a other with this map. This operation is very + fast and never fails. +*/ + /*! \fn bool QMap::operator==(const QMap<Key, T> &other) const Returns true if \a other is equal to this map; otherwise returns diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index 1c2aad3..2897529 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -107,7 +107,6 @@ template <class Key> inline bool qMapLessThanKey(const Key &key1, const Key &key return key1 < key2; } -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION template <class Ptr> inline bool qMapLessThanKey(Ptr *key1, Ptr *key2) { Q_ASSERT(sizeof(quintptr) == sizeof(Ptr *)); @@ -119,7 +118,6 @@ template <class Ptr> inline bool qMapLessThanKey(const Ptr *key1, const Ptr *key Q_ASSERT(sizeof(quintptr) == sizeof(const Ptr *)); return quintptr(key1) < quintptr(key2); } -#endif // QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION template <class Key, class T> struct QMapNode { @@ -187,6 +185,11 @@ public: inline ~QMap() { if (!d) return; if (!d->ref.deref()) freeData(d); } QMap<Key, T> &operator=(const QMap<Key, T> &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QMap<Key, T> &operator=(QMap<Key, T> &&other) + { qSwap(d, other.d); return *this; } +#endif + inline void swap(QMap<Key, T> &other) { qSwap(d, other.d); } #ifndef QT_NO_STL explicit QMap(const typename std::map<Key, T> &other); std::map<Key, T> toStdMap() const; @@ -640,13 +643,13 @@ Q_OUTOFLINE_TEMPLATE void QMap<Key, T>::freeData(QMapData *x) while (next != x) { cur = next; next = cur->forward[0]; -#if defined(_MSC_VER) && (_MSC_VER >= 1300) +#if defined(_MSC_VER) #pragma warning(disable:4189) #endif Node *concreteNode = concrete(reinterpret_cast<QMapData::Node *>(cur)); concreteNode->key.~Key(); concreteNode->value.~T(); -#if defined(_MSC_VER) && (_MSC_VER >= 1300) +#if defined(_MSC_VER) #pragma warning(default:4189) #endif } @@ -971,6 +974,7 @@ class QMultiMap : public QMap<Key, T> public: QMultiMap() {} QMultiMap(const QMap<Key, T> &other) : QMap<Key, T>(other) {} + inline void swap(QMultiMap<Key, T> &other) { QMap<Key, T>::swap(other); } inline typename QMap<Key, T>::iterator replace(const Key &key, const T &value) { return QMap<Key, T>::insert(key, value); } diff --git a/src/corelib/tools/qqueue.cpp b/src/corelib/tools/qqueue.cpp index 849bb0b..3602695 100644 --- a/src/corelib/tools/qqueue.cpp +++ b/src/corelib/tools/qqueue.cpp @@ -91,6 +91,14 @@ */ /*! + \fn void QQueue::swap(QQueue<T> &other) + \since 4.8 + + Swaps queue \a other with this queue. This operation is very + fast and never fails. +*/ + +/*! \fn void QQueue::enqueue(const T& t) Adds value \a t to the tail of the queue. diff --git a/src/corelib/tools/qqueue.h b/src/corelib/tools/qqueue.h index c29134b..4ef1a61 100644 --- a/src/corelib/tools/qqueue.h +++ b/src/corelib/tools/qqueue.h @@ -56,6 +56,7 @@ class QQueue : public QList<T> public: inline QQueue() {} inline ~QQueue() {} + inline void swap(QQueue<T> &other) { QList<T>::swap(other); } // prevent QList<->QQueue swaps inline void enqueue(const T &t) { QList<T>::append(t); } inline T dequeue() { return QList<T>::takeFirst(); } inline T &head() { return QList<T>::first(); } diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index a8bf38f..5d2a0e3 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -3858,6 +3858,14 @@ QRegExp &QRegExp::operator=(const QRegExp &rx) } /*! + \fn void QRegExp::swap(QRegExp &other) + \since 4.8 + + Swaps regular expression \a other with this regular + expression. This operation is very fast and never fails. +*/ + +/*! Returns true if this regular expression is equal to \a rx; otherwise returns false. @@ -4168,6 +4176,8 @@ int QRegExp::matchedLength() const } #ifndef QT_NO_REGEXP_CAPTURE + +#ifndef QT_NO_DEPRECATED /*! \obsolete Returns the number of captures contained in the regular expression. @@ -4178,6 +4188,7 @@ int QRegExp::numCaptures() const { return captureCount(); } +#endif /*! \since 4.6 diff --git a/src/corelib/tools/qregexp.h b/src/corelib/tools/qregexp.h index e19c130..4a74f90 100644 --- a/src/corelib/tools/qregexp.h +++ b/src/corelib/tools/qregexp.h @@ -76,6 +76,11 @@ public: QRegExp(const QRegExp &rx); ~QRegExp(); QRegExp &operator=(const QRegExp &rx); +#ifdef Q_COMPILER_RVALUE_REFS + inline QRegExp &operator=(QRegExp &&other) + { qSwap(priv,other.priv); return *this; } +#endif + inline void swap(QRegExp &other) { qSwap(priv, other.priv); } bool operator==(const QRegExp &rx) const; inline bool operator!=(const QRegExp &rx) const { return !operator==(rx); } diff --git a/src/corelib/tools/qscopedpointer.h b/src/corelib/tools/qscopedpointer.h index bc76a3b..b3a6db6 100644 --- a/src/corelib/tools/qscopedpointer.h +++ b/src/corelib/tools/qscopedpointer.h @@ -54,7 +54,7 @@ struct QScopedPointerDeleter static inline void cleanup(T *pointer) { // Enforce a complete type. - // If you get a compile error here, read the secion on forward declared + // If you get a compile error here, read the section on forward declared // classes in the QScopedPointer documentation. typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; (void) sizeof(IsIncompleteType); @@ -69,7 +69,7 @@ struct QScopedPointerArrayDeleter static inline void cleanup(T *pointer) { // Enforce a complete type. - // If you get a compile error here, read the secion on forward declared + // If you get a compile error here, read the section on forward declared // classes in the QScopedPointer documentation. typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; (void) sizeof(IsIncompleteType); @@ -186,11 +186,30 @@ template <class T, class Cleanup> Q_INLINE_TEMPLATE void qSwap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) { p1.swap(p2); } +#ifndef QT_NO_STL +QT_END_NAMESPACE +namespace std { + template <class T, class Cleanup> + Q_INLINE_TEMPLATE void swap(QT_PREPEND_NAMESPACE(QScopedPointer)<T, Cleanup> &p1, QT_PREPEND_NAMESPACE(QScopedPointer)<T, Cleanup> &p2) + { p1.swap(p2); } +} +QT_BEGIN_NAMESPACE +#endif + + + +namespace QtPrivate { + template <typename X, typename Y> struct QScopedArrayEnsureSameType; + template <typename X> struct QScopedArrayEnsureSameType<X,X> { typedef X* Type; }; + template <typename X> struct QScopedArrayEnsureSameType<const X, X> { typedef X* Type; }; +} + template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> > class QScopedArrayPointer : public QScopedPointer<T, Cleanup> { public: - explicit inline QScopedArrayPointer(T *p = 0) + template <typename D> + explicit inline QScopedArrayPointer(D *p = 0, typename QtPrivate::QScopedArrayEnsureSameType<T,D>::Type = 0) : QScopedPointer<T, Cleanup>(p) { } @@ -206,6 +225,17 @@ public: } private: + explicit inline QScopedArrayPointer(void *) { + // Enforce the same type. + + // If you get a compile error here, make sure you declare + // QScopedArrayPointer with the same template type as you pass to the + // constructor. See also the QScopedPointer documentation. + + // Storing a scalar array as a pointer to a different type is not + // allowed and results in undefined behavior. + } + Q_DISABLE_COPY(QScopedArrayPointer) }; diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index fe50d4d..472078f 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -61,6 +61,11 @@ public: inline QSet<T> &operator=(const QSet<T> &other) { q_hash = other.q_hash; return *this; } +#ifdef Q_COMPILER_RVALUE_REFS + inline QSet<T> &operator=(QSet<T> &&other) + { qSwap(q_hash, other.q_hash); return *this; } +#endif + inline void swap(QSet<T> &other) { q_hash.swap(other.q_hash); } inline bool operator==(const QSet<T> &other) const { return q_hash == other.q_hash; } diff --git a/src/corelib/tools/qset.qdoc b/src/corelib/tools/qset.qdoc index 0bc2d2d..57368f0 100644 --- a/src/corelib/tools/qset.qdoc +++ b/src/corelib/tools/qset.qdoc @@ -123,6 +123,13 @@ */ /*! + \fn void QSet::swap(QSet<T> &other) + + Swaps set \a other with this set. This operation is very fast and + never fails. +*/ + +/*! \fn bool QSet::operator==(const QSet<T> &other) const Returns true if the \a other set is equal to this set; otherwise diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h index 6483c90..45456fe 100644 --- a/src/corelib/tools/qshareddata.h +++ b/src/corelib/tools/qshareddata.h @@ -113,6 +113,10 @@ public: } return *this; } +#ifdef Q_COMPILER_RVALUE_REFS + inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) + { qSwap(d, other.d); return *this; } +#endif inline bool operator!() const { return !d; } @@ -163,14 +167,12 @@ public: explicit QExplicitlySharedDataPointer(T *data); inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); } -#ifndef QT_NO_MEMBER_TEMPLATES template<class X> inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o) : d(static_cast<T *>(o.data())) { if(d) d->ref.ref(); } -#endif inline QExplicitlySharedDataPointer<T> & operator=(const QExplicitlySharedDataPointer<T> &o) { if (o.d != d) { @@ -194,6 +196,10 @@ public: } return *this; } +#ifdef Q_COMPILER_RVALUE_REFS + inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) + { qSwap(d, other.d); return *this; } +#endif inline bool operator!() const { return !d; } @@ -257,6 +263,20 @@ template <class T> Q_INLINE_TEMPLATE void qSwap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2) { p1.swap(p2); } +#ifndef QT_NO_STL +QT_END_NAMESPACE +namespace std { + template <class T> + Q_INLINE_TEMPLATE void swap(QT_PREPEND_NAMESPACE(QSharedDataPointer)<T> &p1, QT_PREPEND_NAMESPACE(QSharedDataPointer)<T> &p2) + { p1.swap(p2); } + + template <class T> + Q_INLINE_TEMPLATE void swap(QT_PREPEND_NAMESPACE(QExplicitlySharedDataPointer)<T> &p1, QT_PREPEND_NAMESPACE(QExplicitlySharedDataPointer)<T> &p2) + { p1.swap(p2); } +} +QT_BEGIN_NAMESPACE +#endif + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index 0310baa..3cc9c45 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -1275,8 +1275,6 @@ QT_END_NAMESPACE -#if !defined(QT_NO_MEMBER_TEMPLATES) - //# define QT_SHARED_POINTER_BACKTRACE_SUPPORT # ifdef QT_SHARED_POINTER_BACKTRACE_SUPPORT # if defined(__GLIBC__) && (__GLIBC__ >= 2) && !defined(__UCLIBC__) && !defined(QT_LINUXBASE) @@ -1501,5 +1499,3 @@ void QtSharedPointer::internalSafetyCheckCleanCheck() } QT_END_NAMESPACE - -#endif diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h index c51ade6..e0f4dca 100644 --- a/src/corelib/tools/qsharedpointer.h +++ b/src/corelib/tools/qsharedpointer.h @@ -47,10 +47,7 @@ #include <QtCore/qshareddata.h> #ifndef Q_QDOC -# if !defined(QT_NO_MEMBER_TEMPLATES) -// QSharedPointer requires member template support # include <QtCore/qsharedpointer_impl.h> -# endif #else QT_BEGIN_HEADER diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 2895bba..ef8c454 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -109,7 +109,6 @@ namespace QtSharedPointer { template <class T> inline void normalDeleter(T *t) { delete t; } // this uses partial template specialization - // the only compilers that didn't support this were MSVC 6.0 and 2002 template <class T> struct RemovePointer; template <class T> struct RemovePointer<T *> { typedef T Type; }; template <class T> struct RemovePointer<QSharedPointer<T> > { typedef T Type; }; @@ -323,7 +322,6 @@ namespace QtSharedPointer { protected: typedef ExternalRefCountData Data; - inline void ref() const { d->weakref.ref(); d->strongref.ref(); } inline void deref() { deref(d, this->value); } static inline void deref(Data *d, T *value) @@ -395,7 +393,13 @@ namespace QtSharedPointer { template <class X> inline void internalCopy(const ExternalRefCount<X> &other) { - internalSet(other.d, other.data()); + Data *o = other.d; + T *actual = other.value; + if (o) + other.ref(); + qSwap(d, o); + qSwap(this->value, actual); + deref(o, actual); } inline void internalSwap(ExternalRefCount &other) @@ -411,6 +415,7 @@ namespace QtSharedPointer { template <class X> friend class QT_PREPEND_NAMESPACE(QWeakPointer); template <class X, class Y> friend QSharedPointer<X> copyAndSetPointer(X * ptr, const QSharedPointer<Y> &src); #endif + inline void ref() const { d->weakref.ref(); d->strongref.ref(); } inline void internalSet(Data *o, T *actual) { @@ -468,6 +473,13 @@ public: BaseClass::internalCopy(other); return *this; } +#ifdef Q_COMPILER_RVALUE_REFS + inline QSharedPointer<T> &operator=(QSharedPointer<T> &&other) + { + QSharedPointer<T>::internalSwap(other); + return *this; + } +#endif template <class X> inline QSharedPointer(const QSharedPointer<X> &other) : BaseClass(other) @@ -772,6 +784,16 @@ inline void qSwap(QSharedPointer<T> &p1, QSharedPointer<T> &p2) p1.swap(p2); } +#ifndef QT_NO_STL +QT_END_NAMESPACE +namespace std { + template <class T> + inline void swap(QT_PREPEND_NAMESPACE(QSharedPointer)<T> &p1, QT_PREPEND_NAMESPACE(QSharedPointer)<T> &p2) + { p1.swap(p2); } +} +QT_BEGIN_NAMESPACE +#endif + namespace QtSharedPointer { // helper functions: template <class X, class T> @@ -852,9 +874,13 @@ qobject_cast(const QWeakPointer<T> &src) { return qSharedPointerObjectCast<typename QtSharedPointer::RemovePointer<X>::Type, T>(src); } - #endif + +template<typename T> Q_DECLARE_TYPEINFO_BODY(QWeakPointer<T>, Q_MOVABLE_TYPE); +template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedPointer<T>, Q_MOVABLE_TYPE); + + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index b2fe2da..ac8ccba 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -72,7 +72,12 @@ QT_BEGIN_NAMESPACE -#if defined (Q_OS_WINCE) +#if defined (Q_OS_NACL) +static inline uint detectProcessorFeatures() +{ + return 0; +} +#elif defined (Q_OS_WINCE) static inline uint detectProcessorFeatures() { uint features = 0; diff --git a/src/corelib/tools/qstack.cpp b/src/corelib/tools/qstack.cpp index fa14900..b42fe3b 100644 --- a/src/corelib/tools/qstack.cpp +++ b/src/corelib/tools/qstack.cpp @@ -91,6 +91,14 @@ */ /*! + \fn void QStack::swap(QStack<T> &other) + \since 4.8 + + Swaps stack \a other with this stack. This operation is very fast and + never fails. +*/ + +/*! \fn void QStack::push(const T& t) Adds element \a t to the top of the stack. diff --git a/src/corelib/tools/qstack.h b/src/corelib/tools/qstack.h index 526c705..6ddc381 100644 --- a/src/corelib/tools/qstack.h +++ b/src/corelib/tools/qstack.h @@ -56,6 +56,7 @@ class QStack : public QVector<T> public: inline QStack() {} inline ~QStack() {} + inline void swap(QStack<T> &other) { QVector<T>::swap(other); } // prevent QVector<->QStack swaps inline void push(const T &t) { QVector<T>::append(t); } T pop(); T &top(); diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index bfbdb73..a3d89f2 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -111,7 +111,23 @@ int qFindString(const QChar *haystack, int haystackLen, int from, const QChar *needle, int needleLen, Qt::CaseSensitivity cs); int qFindStringBoyerMoore(const QChar *haystack, int haystackLen, int from, const QChar *needle, int needleLen, Qt::CaseSensitivity cs); - +static inline int qt_last_index_of(const QChar *haystack, int haystackLen, const QChar &needle, + int from, Qt::CaseSensitivity cs); +static inline int qt_string_count(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, + Qt::CaseSensitivity cs); +static inline int qt_string_count(const QChar *haystack, int haystackLen, + const QChar &needle, Qt::CaseSensitivity cs); +static inline int qt_find_latin1_string(const QChar *hay, int size, const QLatin1String &needle, + int from, Qt::CaseSensitivity cs); +static inline bool qt_starts_with(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs); +static inline bool qt_starts_with(const QChar *haystack, int haystackLen, + const QLatin1String &needle, Qt::CaseSensitivity cs); +static inline bool qt_ends_with(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs); +static inline bool qt_ends_with(const QChar *haystack, int haystackLen, + const QLatin1String &needle, Qt::CaseSensitivity cs); // Unicode case-insensitive comparison static int ucstricmp(const ushort *a, const ushort *ae, const ushort *b, const ushort *be) @@ -350,11 +366,7 @@ inline char qToLower(char ch) return ch; } -#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 -const QString::Null QString::null; -#else const QString::Null QString::null = { }; -#endif /*! \macro QT_NO_CAST_FROM_ASCII @@ -945,6 +957,24 @@ QString QString::fromWCharArray(const wchar_t *string, int size) \sa utf16(), toAscii(), toLatin1(), toUtf8(), toLocal8Bit() */ +template<typename T> int toUcs4_helper(const unsigned short *uc, int length, T *out) +{ + int i = 0; + for (; i < length; ++i) { + uint u = uc[i]; + if (QChar::isHighSurrogate(u) && i < length-1) { + ushort low = uc[i+1]; + if (QChar::isLowSurrogate(low)) { + ++i; + u = QChar::surrogateToUcs4(u, low); + } + } + *out = T(u); + ++out; + } + return i; +} + /*! \since 4.2 @@ -969,21 +999,7 @@ int QString::toWCharArray(wchar_t *array) const memcpy(array, utf16(), sizeof(wchar_t)*length()); return length(); } else { - wchar_t *a = array; - const unsigned short *uc = utf16(); - for (int i = 0; i < length(); ++i) { - uint u = uc[i]; - if (QChar::isHighSurrogate(u) && i + 1 < length()) { - ushort low = uc[i+1]; - if (QChar::isLowSurrogate(low)) { - u = QChar::surrogateToUcs4(u, low); - ++i; - } - } - *a = wchar_t(u); - ++a; - } - return a - array; + return toUcs4_helper<wchar_t>(utf16(), length(), array); } } @@ -1158,6 +1174,13 @@ QString::QString(QChar ch) */ +/*! \fn void QString::swap(QString &other) + \since 4.8 + + Swaps string \a other with this string. This operation is very fast and + never fails. +*/ + /*! \fn void QString::detach() \internal @@ -1316,7 +1339,9 @@ void QString::realloc(int alloc) asciiCache->remove(d); } #endif - d = static_cast<Data *>(q_check_ptr(qRealloc(d, sizeof(Data) + alloc * sizeof(QChar)))); + Data *p = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc * sizeof(QChar))); + Q_CHECK_PTR(p); + d = p; d->alloc = alloc; d->data = d->array; } @@ -2480,14 +2505,10 @@ int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const \sa lastIndexOf(), contains(), count() */ + int QString::indexOf(const QLatin1String &str, int from, Qt::CaseSensitivity cs) const { - int len = qstrlen(str.latin1()); - QVarLengthArray<ushort> s(len); - for (int i = 0; i < len; ++i) - s[i] = str.latin1()[i]; - - return qFindString(unicode(), length(), from, (const QChar *)s.data(), len, cs); + return qt_find_latin1_string(unicode(), size(), str, from, cs); } int qFindString( @@ -2577,6 +2598,23 @@ int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const return findChar(unicode(), length(), ch, from, cs); } +/*! + \since 4.8 + + \overload indexOf() + + Returns the index position of the first occurrence of the string + reference \a str in this string, searching forward from index + position \a from. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. +*/ +int QString::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const +{ + return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs); +} + static int lastIndexOfHelper(const ushort *haystack, int from, const ushort *needle, int sl, Qt::CaseSensitivity cs) { /* @@ -2656,12 +2694,13 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c if (from > delta) from = delta; - return lastIndexOfHelper(d->data, from, str.d->data, str.d->size, cs); } /*! \since 4.5 + \overload lastIndexOf() + Returns the index position of the last occurrence of the string \a str in this string, searching backward from index position \a from. If \a from is -1 (default), the search starts at the last @@ -2709,26 +2748,43 @@ int QString::lastIndexOf(const QLatin1String &str, int from, Qt::CaseSensitivity */ int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const { - ushort c = ch.unicode(); - if (from < 0) - from += d->size; - if (from < 0 || from >= d->size) - return -1; - if (from >= 0) { - const ushort *n = d->data + from; - const ushort *b = d->data; - if (cs == Qt::CaseSensitive) { - for (; n >= b; --n) - if (*n == c) - return n - b; - } else { - c = foldCase(c); - for (; n >= b; --n) - if (foldCase(*n) == c) - return n - b; - } + return qt_last_index_of(unicode(), size(), ch, from, cs); } + +/*! + \since 4.8 + \overload lastIndexOf() + + Returns the index position of the last occurrence of the string + reference \a str in this string, searching backward from index + position \a from. If \a from is -1 (default), the search starts at + the last character; if \a from is -2, at the next to last character + and so on. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa indexOf(), contains(), count() +*/ +int QString::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const +{ + const int sl = str.size(); + if (sl == 1) + return lastIndexOf(str.at(0), from, cs); + + const int l = d->size; + if (from < 0) + from += l; + int delta = l - sl; + if (from == l && sl == 0) + return from; + if (from < 0 || from >= l || delta < 0) return -1; + if (from > delta) + from = delta; + + return lastIndexOfHelper(d->data, from, reinterpret_cast<const ushort*>(str.unicode()), + str.size(), cs); } #ifndef QT_NO_REGEXP @@ -2903,19 +2959,10 @@ QString& QString::replace(const QRegExp &rx, const QString &after) \sa contains(), indexOf() */ + int QString::count(const QString &str, Qt::CaseSensitivity cs) const { - int num = 0; - int i = -1; - if (d->size > 500 && str.d->size > 5) { - QStringMatcher matcher(str, cs); - while ((i = matcher.indexIn(*this, i + 1)) != -1) - ++num; - } else { - while ((i = indexOf(str, i + 1, cs)) != -1) - ++num; - } - return num; + return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs); } /*! @@ -2923,25 +2970,29 @@ int QString::count(const QString &str, Qt::CaseSensitivity cs) const Returns the number of occurrences of character \a ch in the string. */ + int QString::count(QChar ch, Qt::CaseSensitivity cs) const { - ushort c = ch.unicode(); - int num = 0; - const ushort *i = d->data + d->size; - const ushort *b = d->data; - if (cs == Qt::CaseSensitive) { - while (i != b) - if (*--i == c) - ++num; - } else { - c = foldCase(c); - while (i != b) - if (foldCase(*(--i)) == c) - ++num; + return qt_string_count(unicode(), size(), ch, cs); } - return num; + +/*! + \since 4.8 + \overload count() + Returns the number of (potentially overlapping) occurrences of the + string reference \a str in this string. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa contains(), indexOf() +*/ +int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const +{ + return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs); } + /*! \fn bool QString::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Returns true if this string contains an occurrence of the string @@ -2964,6 +3015,18 @@ int QString::count(QChar ch, Qt::CaseSensitivity cs) const character \a ch; otherwise returns false. */ +/*! \fn bool QString::contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + \since 4.8 + + Returns true if this string contains an occurrence of the string + reference \a str; otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa indexOf(), count() +*/ + /*! \fn bool QString::contains(const QRegExp &rx) const \overload contains() @@ -3365,22 +3428,8 @@ QString QString::mid(int position, int n) const */ bool QString::startsWith(const QString& s, Qt::CaseSensitivity cs) const { - if (d == &shared_null) - return (s.d == &shared_null); - if (d->size == 0) - return s.d->size == 0; - if (s.d->size > d->size) - return false; - if (cs == Qt::CaseSensitive) { - return qMemEquals(d->data, s.d->data, s.d->size); - } else { - uint last = 0; - uint olast = 0; - for (int i = 0; i < s.d->size; ++i) - if (foldCase(d->data[i], last) != foldCase(s.d->data[i], olast)) - return false; - } - return true; + return qt_starts_with(isNull() ? 0 : unicode(), size(), + s.isNull() ? 0 : s.unicode(), s.size(), cs); } /*! @@ -3388,24 +3437,7 @@ bool QString::startsWith(const QString& s, Qt::CaseSensitivity cs) const */ bool QString::startsWith(const QLatin1String& s, Qt::CaseSensitivity cs) const { - if (d == &shared_null) - return (s.latin1() == 0); - if (d->size == 0) - return !s.latin1() || *s.latin1() == 0; - int slen = qstrlen(s.latin1()); - if (slen > d->size) - return false; - const uchar *latin = (const uchar *)s.latin1(); - if (cs == Qt::CaseSensitive) { - for (int i = 0; i < slen; ++i) - if (d->data[i] != latin[i]) - return false; - } else { - for (int i = 0; i < slen; ++i) - if (foldCase(d->data[i]) != foldCase((ushort)latin[i])) - return false; - } - return true; + return qt_starts_with(isNull() ? 0 : unicode(), size(), s, cs); } /*! @@ -3423,6 +3455,23 @@ bool QString::startsWith(const QChar &c, Qt::CaseSensitivity cs) const } /*! + \since 4.8 + \overload + Returns true if the string starts with the string reference \a s; + otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa endsWith() +*/ +bool QString::startsWith(const QStringRef &s, Qt::CaseSensitivity cs) const +{ + return qt_starts_with(isNull() ? 0 : unicode(), size(), + s.isNull() ? 0 : s.unicode(), s.size(), cs); +} + +/*! Returns true if the string ends with \a s; otherwise returns false. @@ -3435,49 +3484,34 @@ bool QString::startsWith(const QChar &c, Qt::CaseSensitivity cs) const */ bool QString::endsWith(const QString& s, Qt::CaseSensitivity cs) const { - if (d == &shared_null) - return (s.d == &shared_null); - if (d->size == 0) - return s.d->size == 0; - int pos = d->size - s.d->size; - if (pos < 0) - return false; - if (cs == Qt::CaseSensitive) { - return qMemEquals(d->data + pos, s.d->data, s.d->size); - } else { - uint last = 0; - uint olast = 0; - for (int i = 0; i < s.length(); i++) - if (foldCase(d->data[pos+i], last) != foldCase(s.d->data[i], olast)) - return false; + return qt_ends_with(isNull() ? 0 : unicode(), size(), + s.isNull() ? 0 : s.unicode(), s.size(), cs); } - return true; + +/*! + \since 4.8 + \overload endsWith() + Returns true if the string ends with the string reference \a s; + otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa startsWith() +*/ +bool QString::endsWith(const QStringRef &s, Qt::CaseSensitivity cs) const +{ + return qt_ends_with(isNull() ? 0 : unicode(), size(), + s.isNull() ? 0 : s.unicode(), s.size(), cs); } + /*! \overload endsWith() */ bool QString::endsWith(const QLatin1String& s, Qt::CaseSensitivity cs) const { - if (d == &shared_null) - return (s.latin1() == 0); - if (d->size == 0) - return !s.latin1() || *s.latin1() == 0; - int slen = qstrlen(s.latin1()); - int pos = d->size - slen; - const uchar *latin = (const uchar *)s.latin1(); - if (pos < 0) - return false; - if (cs == Qt::CaseSensitive) { - for (int i = 0; i < slen; i++) - if (d->data[pos+i] != latin[i]) - return false; - } else { - for (int i = 0; i < slen; i++) - if (foldCase(d->data[pos+i]) != foldCase((ushort)latin[i])) - return false; - } - return true; + return qt_ends_with(isNull() ? 0 : unicode(), size(), s, cs); } /*! @@ -3716,20 +3750,8 @@ QVector<uint> QString::toUcs4() const { QVector<uint> v(length()); uint *a = v.data(); - const unsigned short *uc = utf16(); - for (int i = 0; i < length(); ++i) { - uint u = uc[i]; - if (QChar(u).isHighSurrogate() && i < length()-1) { - ushort low = uc[i+1]; - if (QChar(low).isLowSurrogate()) { - ++i; - u = QChar::surrogateToUcs4(u, low); - } - } - *a = u; - ++a; - } - v.resize(a - v.data()); + int len = toUcs4_helper<uint>(utf16(), length(), a); + v.resize(len); return v; } @@ -7445,31 +7467,17 @@ QDataStream &operator<<(QDataStream &out, const QString &str) out << str.toLatin1(); } else { if (!str.isNull() || out.version() < 3) { - int byteOrder = out.byteOrder(); - const QChar* ub = str.unicode(); - static const uint auto_size = 1024; - char t[auto_size]; - char *b; - if (str.length()*sizeof(QChar) > auto_size) { - b = new char[str.length()*sizeof(QChar)]; + if ((out.byteOrder() == QDataStream::BigEndian) == (QSysInfo::ByteOrder == QSysInfo::BigEndian)) { + out.writeBytes(reinterpret_cast<const char *>(str.unicode()), sizeof(QChar) * str.length()); } else { - b = t; - } - int l = str.length(); - char *c=b; - while (l--) { - if (byteOrder == QDataStream::BigEndian) { - *c++ = (char)ub->row(); - *c++ = (char)ub->cell(); - } else { - *c++ = (char)ub->cell(); - *c++ = (char)ub->row(); + QVarLengthArray<ushort> buffer(str.length()); + const ushort *data = reinterpret_cast<const ushort *>(str.constData()); + for (int i = 0; i < str.length(); i++) { + buffer[i] = qbswap(*data); + ++data; } - ub++; + out.writeBytes(reinterpret_cast<const char *>(buffer.data()), sizeof(ushort) * buffer.size()); } - out.writeBytes(b, sizeof(QChar)*str.length()); - if (str.length()*sizeof(QChar) > auto_size) - delete [] b; } else { // write null marker out << (quint32)0xffffffff; @@ -7662,6 +7670,7 @@ QDataStream &operator>>(QDataStream &in, QString &str) Use the startsWith(QString, Qt::CaseSensitive) overload instead. */ + /*! \fn bool QString::endsWith(const QString &s, bool cs) const @@ -8367,4 +8376,717 @@ QStringRef QString::midRef(int position, int n) const return QStringRef(this, position, n); } +/*! + \since 4.8 + + Returns the index position of the first occurrence of the string \a + str in this string reference, searching forward from index position + \a from. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + If \a from is -1, the search starts at the last character; if it is + -2, at the next to last character and so on. + + \sa QString::indexOf(), lastIndexOf(), contains(), count() +*/ +int QStringRef::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const +{ + return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs); +} + +/*! + \since 4.8 + \overload indexOf() + + Returns the index position of the first occurrence of the + character \a ch in the string reference, searching forward from + index position \a from. Returns -1 if \a ch could not be found. + + \sa QString::indexOf(), lastIndexOf(), contains(), count() +*/ +int QStringRef::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const +{ + return findChar(unicode(), length(), ch, from, cs); +} + +/*! + \since 4.8 + + Returns the index position of the first occurrence of the string \a + str in this string reference, searching forward from index position + \a from. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + If \a from is -1, the search starts at the last character; if it is + -2, at the next to last character and so on. + + \sa QString::indexOf(), lastIndexOf(), contains(), count() +*/ +int QStringRef::indexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const +{ + return qt_find_latin1_string(unicode(), size(), str, from, cs); +} + +/*! + \since 4.8 + + \overload indexOf() + + Returns the index position of the first occurrence of the string + reference \a str in this string reference, searching forward from + index position \a from. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::indexOf(), lastIndexOf(), contains(), count() +*/ +int QStringRef::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const +{ + return qFindString(unicode(), size(), from, str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + + Returns the index position of the last occurrence of the string \a + str in this string reference, searching backward from index position + \a from. If \a from is -1 (default), the search starts at the last + character; if \a from is -2, at the next to last character and so + on. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::lastIndexOf(), indexOf(), contains(), count() +*/ +int QStringRef::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const +{ + const int sl = str.size(); + if (sl == 1) + return lastIndexOf(str.at(0), from, cs); + + const int l = size();; + if (from < 0) + from += l; + int delta = l - sl; + if (from == l && sl == 0) + return from; + if (from < 0 || from >= l || delta < 0) + return -1; + if (from > delta) + from = delta; + + return lastIndexOfHelper(reinterpret_cast<const ushort*>(unicode()), from, + reinterpret_cast<const ushort*>(str.unicode()), str.size(), cs); +} + +/*! + \since 4.8 + \overload lastIndexOf() + + Returns the index position of the last occurrence of the character + \a ch, searching backward from position \a from. + + \sa QString::lastIndexOf(), indexOf(), contains(), count() +*/ +int QStringRef::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const +{ + return qt_last_index_of(unicode(), size(), ch, from, cs); +} + +/*! + \since 4.8 + \overload lastIndexOf() + + Returns the index position of the last occurrence of the string \a + str in this string reference, searching backward from index position + \a from. If \a from is -1 (default), the search starts at the last + character; if \a from is -2, at the next to last character and so + on. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::lastIndexOf(), indexOf(), contains(), count() +*/ +int QStringRef::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const +{ + const int sl = qstrlen(str.latin1()); + if (sl == 1) + return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs); + + const int l = size(); + if (from < 0) + from += l; + int delta = l - sl; + if (from == l && sl == 0) + return from; + if (from < 0 || from >= l || delta < 0) + return -1; + if (from > delta) + from = delta; + + QVarLengthArray<ushort> s(sl); + for (int i = 0; i < sl; ++i) + s[i] = str.latin1()[i]; + + return lastIndexOfHelper(reinterpret_cast<const ushort*>(unicode()), from, s.data(), sl, cs); +} + +/*! + \since 4.8 + \overload lastIndexOf() + + Returns the index position of the last occurrence of the string + reference \a str in this string reference, searching backward from + index position \a from. If \a from is -1 (default), the search + starts at the last character; if \a from is -2, at the next to last + character and so on. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::lastIndexOf(), indexOf(), contains(), count() +*/ +int QStringRef::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) const +{ + const int sl = str.size(); + if (sl == 1) + return lastIndexOf(str.at(0), from, cs); + + const int l = size(); + if (from < 0) + from += l; + int delta = l - sl; + if (from == l && sl == 0) + return from; + if (from < 0 || from >= l || delta < 0) + return -1; + if (from > delta) + from = delta; + + return lastIndexOfHelper(reinterpret_cast<const ushort*>(unicode()), from, + reinterpret_cast<const ushort*>(str.unicode()), + str.size(), cs); +} + +/*! + \since 4.8 + Returns the number of (potentially overlapping) occurrences of + the string \a str in this string reference. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa QString::count(), contains(), indexOf() +*/ +int QStringRef::count(const QString &str, Qt::CaseSensitivity cs) const +{ + return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + \overload count() + + Returns the number of occurrences of the character \a ch in the + string reference. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa QString::count(), contains(), indexOf() +*/ +int QStringRef::count(QChar ch, Qt::CaseSensitivity cs) const +{ + return qt_string_count(unicode(), size(), ch, cs); +} + +/*! + \since 4.8 + \overload count() + + Returns the number of (potentially overlapping) occurrences of the + string reference \a str in this string reference. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa QString::count(), contains(), indexOf() +*/ +int QStringRef::count(const QStringRef &str, Qt::CaseSensitivity cs) const +{ + return qt_string_count(unicode(), size(), str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + + Returns true if the string reference starts with \a str; otherwise + returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa QString::startsWith(), endsWith() +*/ +bool QStringRef::startsWith(const QString &str, Qt::CaseSensitivity cs) const +{ + return qt_starts_with(isNull() ? 0 : unicode(), size(), + str.isNull() ? 0 : str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + \overload startsWith() + \sa QString::startsWith(), endsWith() +*/ +bool QStringRef::startsWith(QLatin1String str, Qt::CaseSensitivity cs) const +{ + return qt_starts_with(isNull() ? 0 : unicode(), size(), str, cs); +} + +/*! + \since 4.8 + \overload startsWith() + \sa QString::startsWith(), endsWith() +*/ +bool QStringRef::startsWith(const QStringRef &str, Qt::CaseSensitivity cs) const +{ + return qt_starts_with(isNull() ? 0 : unicode(), size(), + str.isNull() ? 0 : str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + \overload startsWith() + + Returns true if the string reference starts with \a ch; otherwise + returns false. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::startsWith(), endsWith() +*/ +bool QStringRef::startsWith(QChar ch, Qt::CaseSensitivity cs) const +{ + if (!isEmpty()) { + const ushort *data = reinterpret_cast<const ushort*>(unicode()); + return (cs == Qt::CaseSensitive + ? data[0] == ch + : foldCase(data[0]) == foldCase(ch.unicode())); + } else { + return false; + } +} + +/*! + \since 4.8 + Returns true if the string reference ends with \a str; otherwise + returns false. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::endsWith(), startsWith() +*/ +bool QStringRef::endsWith(const QString &str, Qt::CaseSensitivity cs) const +{ + return qt_ends_with(isNull() ? 0 : unicode(), size(), + str.isNull() ? 0 : str.unicode(), str.size(), cs); +} + +/*! + \since 4.8 + \overload endsWith() + + Returns true if the string reference ends with \a ch; otherwise + returns false. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \sa QString::endsWith(), endsWith() +*/ +bool QStringRef::endsWith(QChar ch, Qt::CaseSensitivity cs) const +{ + if (!isEmpty()) { + const ushort *data = reinterpret_cast<const ushort*>(unicode()); + const int size = length(); + return (cs == Qt::CaseSensitive + ? data[size - 1] == ch + : foldCase(data[size - 1]) == foldCase(ch.unicode())); + } else { + return false; + } +} + +/*! + \since 4.8 + \overload endsWith() + \sa QString::endsWith(), endsWith() +*/ +bool QStringRef::endsWith(QLatin1String str, Qt::CaseSensitivity cs) const +{ + return qt_ends_with(isNull() ? 0 : unicode(), size(), str, cs); +} + +/*! + \since 4.8 + \overload endsWith() + \sa QString::endsWith(), endsWith() +*/ +bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const +{ + return qt_ends_with(isNull() ? 0 : unicode(), size(), + str.isNull() ? 0 : str.unicode(), str.size(), cs); +} + + +/*! \fn bool QStringRef::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + + \since 4.8 + Returns true if this string reference contains an occurrence of + the string \a str; otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa indexOf(), count() +*/ + +/*! \fn bool QStringRef::contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + + \overload contains() + \since 4.8 + + Returns true if this string contains an occurrence of the + character \a ch; otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + +*/ + +/*! \fn bool QStringRef::contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + \overload contains() + \since 4.8 + + Returns true if this string reference contains an occurrence of + the string reference \a str; otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa indexOf(), count() +*/ + +/*! \fn bool QStringRef::contains(QLatin1String str, Qt::CaseSensitivity cs) const + \since 4,8 + \overload contains() + + Returns true if this string reference contains an occurrence of + the string \a str; otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa indexOf(), count() +*/ + +static inline int qt_last_index_of(const QChar *haystack, int haystackLen, const QChar &needle, + int from, Qt::CaseSensitivity cs) +{ + ushort c = needle.unicode(); + if (from < 0) + from += haystackLen; + if (from < 0 || from >= haystackLen) + return -1; + if (from >= 0) { + const ushort *b = reinterpret_cast<const ushort*>(haystack); + const ushort *n = b + from; + if (cs == Qt::CaseSensitive) { + for (; n >= b; --n) + if (*n == c) + return n - b; + } else { + c = foldCase(c); + for (; n >= b; --n) + if (foldCase(*n) == c) + return n - b; + } + } + return -1; + + +} + +static inline int qt_string_count(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, + Qt::CaseSensitivity cs) +{ + int num = 0; + int i = -1; + if (haystackLen > 500 && needleLen > 5) { + QStringMatcher matcher(needle, needleLen, cs); + while ((i = matcher.indexIn(haystack, haystackLen, i + 1)) != -1) + ++num; + } else { + while ((i = qFindString(haystack, haystackLen, i + 1, needle, needleLen, cs)) != -1) + ++num; + } + return num; +} + +static inline int qt_string_count(const QChar *unicode, int size, const QChar &ch, + Qt::CaseSensitivity cs) +{ + ushort c = ch.unicode(); + int num = 0; + const ushort *b = reinterpret_cast<const ushort*>(unicode); + const ushort *i = b + size; + if (cs == Qt::CaseSensitive) { + while (i != b) + if (*--i == c) + ++num; + } else { + c = foldCase(c); + while (i != b) + if (foldCase(*(--i)) == c) + ++num; + } + return num; +} + +static inline int qt_find_latin1_string(const QChar *haystack, int size, + const QLatin1String &needle, + int from, Qt::CaseSensitivity cs) +{ + const char *latin1 = needle.latin1(); + int len = qstrlen(latin1); + QVarLengthArray<ushort> s(len); + for (int i = 0; i < len; ++i) + s[i] = latin1[i]; + + return qFindString(haystack, size, from, + reinterpret_cast<const QChar*>(s.constData()), len, cs); +} + +static inline bool qt_starts_with(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs) +{ + if (!haystack) + return !needle; + if (haystackLen == 0) + return needleLen == 0; + if (needleLen > haystackLen) + return false; + + const ushort *h = reinterpret_cast<const ushort*>(haystack); + const ushort *n = reinterpret_cast<const ushort*>(needle); + + if (cs == Qt::CaseSensitive) { + return qMemEquals(h, n, needleLen); + } else { + uint last = 0; + uint olast = 0; + for (int i = 0; i < needleLen; ++i) + if (foldCase(h[i], last) != foldCase(n[i], olast)) + return false; + } + return true; +} + +static inline bool qt_starts_with(const QChar *haystack, int haystackLen, + const QLatin1String &needle, Qt::CaseSensitivity cs) +{ + if (!haystack) + return !needle.latin1(); + if (haystackLen == 0) + return !needle.latin1() || *needle.latin1() == 0; + const int slen = qstrlen(needle.latin1()); + if (slen > haystackLen) + return false; + const ushort *data = reinterpret_cast<const ushort*>(haystack); + const uchar *latin = reinterpret_cast<const uchar*>(needle.latin1()); + if (cs == Qt::CaseSensitive) { + for (int i = 0; i < slen; ++i) + if (data[i] != latin[i]) + return false; + } else { + for (int i = 0; i < slen; ++i) + if (foldCase(data[i]) != foldCase((ushort)latin[i])) + return false; + } + return true; +} + +static inline bool qt_ends_with(const QChar *haystack, int haystackLen, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs) +{ + if (!haystack) + return !needle; + if (haystackLen == 0) + return needleLen == 0; + const int pos = haystackLen - needleLen; + if (pos < 0) + return false; + + const ushort *h = reinterpret_cast<const ushort*>(haystack); + const ushort *n = reinterpret_cast<const ushort*>(needle); + + if (cs == Qt::CaseSensitive) { + return qMemEquals(h + pos, n, needleLen); + } else { + uint last = 0; + uint olast = 0; + for (int i = 0; i < needleLen; i++) + if (foldCase(h[pos+i], last) != foldCase(n[i], olast)) + return false; + } + return true; +} + + +static inline bool qt_ends_with(const QChar *haystack, int haystackLen, + const QLatin1String &needle, Qt::CaseSensitivity cs) +{ + if (!haystack) + return !needle.latin1(); + if (haystackLen == 0) + return !needle.latin1() || *needle.latin1() == 0; + const int slen = qstrlen(needle.latin1()); + int pos = haystackLen - slen; + if (pos < 0) + return false; + const uchar *latin = reinterpret_cast<const uchar*>(needle.latin1()); + const ushort *data = reinterpret_cast<const ushort*>(haystack); + if (cs == Qt::CaseSensitive) { + for (int i = 0; i < slen; i++) + if (data[pos+i] != latin[i]) + return false; + } else { + for (int i = 0; i < slen; i++) + if (foldCase(data[pos+i]) != foldCase((ushort)latin[i])) + return false; + } + return true; +} + +/*! + \since 4.8 + + Returns a Latin-1 representation of the string as a QByteArray. + + The returned byte array is undefined if the string contains non-Latin1 + characters. Those characters may be suppressed or replaced with a + question mark. + + \sa toAscii(), toUtf8(), toLocal8Bit(), QTextCodec +*/ +QByteArray QStringRef::toLatin1() const +{ + return toLatin1_helper(unicode(), length()); +} + +/*! + \since 4.8 + + Returns an 8-bit representation of the string as a QByteArray. + + If a codec has been set using QTextCodec::setCodecForCStrings(), + it is used to convert Unicode to 8-bit char; otherwise this + function does the same as toLatin1(). + + Note that, despite the name, this function does not necessarily return an US-ASCII + (ANSI X3.4-1986) string and its result may not be US-ASCII compatible. + + \sa toLatin1(), toUtf8(), toLocal8Bit(), QTextCodec +*/ +QByteArray QStringRef::toAscii() const +{ +#ifndef QT_NO_TEXTCODEC + if (QString::codecForCStrings) + return QString::codecForCStrings->fromUnicode(unicode(), length()); +#endif // QT_NO_TEXTCODEC + return toLatin1(); +} + +/*! + \since 4.8 + + Returns the local 8-bit representation of the string as a + QByteArray. The returned byte array is undefined if the string + contains characters not supported by the local 8-bit encoding. + + QTextCodec::codecForLocale() is used to perform the conversion from + Unicode. If the locale encoding could not be determined, this function + does the same as toLatin1(). + + If this string contains any characters that cannot be encoded in the + locale, the returned byte array is undefined. Those characters may be + suppressed or replaced by another. + + \sa toAscii(), toLatin1(), toUtf8(), QTextCodec +*/ +QByteArray QStringRef::toLocal8Bit() const +{ +#ifndef QT_NO_TEXTCODEC + if (QTextCodec::codecForLocale()) + return QTextCodec::codecForLocale()->fromUnicode(unicode(), length()); +#endif // QT_NO_TEXTCODEC + return toLatin1(); +} + +/*! + \since 4.8 + + Returns a UTF-8 representation of the string as a QByteArray. + + UTF-8 is a Unicode codec and can represent all characters in a Unicode + string like QString. + + However, in the Unicode range, there are certain codepoints that are not + considered characters. The Unicode standard reserves the last two + codepoints in each Unicode Plane (U+FFFE, U+FFFF, U+1FFFE, U+1FFFF, + U+2FFFE, etc.), as well as 16 codepoints in the range U+FDD0..U+FDDF, + inclusive, as non-characters. If any of those appear in the string, they + may be discarded and will not appear in the UTF-8 representation, or they + may be replaced by one or more replacement characters. + + \sa toAscii(), toLatin1(), toLocal8Bit(), QTextCodec +*/ +QByteArray QStringRef::toUtf8() const +{ + if (isNull()) + return QByteArray(); + + return QUtf8::convertFromUnicode(constData(), length(), 0); +} + +/*! + \since 4.8 + + Returns a UCS-4/UTF-32 representation of the string as a QVector<uint>. + + UCS-4 is a Unicode codec and is lossless. All characters from this string + can be encoded in UCS-4. + + \sa fromUtf8(), toAscii(), toLatin1(), toLocal8Bit(), QTextCodec, fromUcs4(), toWCharArray() +*/ +QVector<uint> QStringRef::toUcs4() const +{ + QVector<uint> v(length()); + uint *a = v.data(); + int len = toUcs4_helper<uint>(reinterpret_cast<const unsigned short *>(unicode()), length(), a); + v.resize(len); + return v; +} + QT_END_NAMESPACE diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 06e4d47..07f43ca 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -51,14 +51,7 @@ #endif #ifndef QT_NO_STL -# if defined (Q_CC_MSVC_NET) && _MSC_VER < 1310 // Avoids nasty warning for xlocale, line 450 -# pragma warning (push) -# pragma warning (disable : 4189) -# include <string> -# pragma warning (pop) -# else -# include <string> -# endif +# include <string> # ifndef QT_NO_STL_WCHAR // workaround for some headers not typedef'ing std::wstring @@ -111,7 +104,11 @@ public: QString &operator=(QChar c); QString &operator=(const QString &); inline QString &operator=(const QLatin1String &); - +#ifdef Q_COMPILER_RVALUE_REFS + inline QString &operator=(QString &&other) + { qSwap(d, other.d); return *this; } +#endif + inline void swap(QString &other) { qSwap(d, other.d); } inline int size() const { return d->size; } inline int count() const { return d->size; } inline int length() const; @@ -198,14 +195,18 @@ public: int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int indexOf(const QString &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int indexOf(const QLatin1String &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int indexOf(const QStringRef &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int lastIndexOf(QChar c, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int lastIndexOf(const QString &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int lastIndexOf(const QLatin1String &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(const QStringRef &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; inline QBool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; inline QBool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QBool contains(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int count(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; #ifndef QT_NO_REGEXP int indexOf(const QRegExp &, int from = 0) const; @@ -241,9 +242,11 @@ public: QStringRef midRef(int position, int n = -1) const Q_REQUIRED_RESULT; bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool startsWith(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool startsWith(const QLatin1String &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool startsWith(const QChar &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool endsWith(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool endsWith(const QLatin1String &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool endsWith(const QChar &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; @@ -902,6 +905,8 @@ inline QString::const_iterator QString::constEnd() const { return reinterpret_cast<const QChar*>(d->data + d->size); } inline QBool QString::contains(const QString &s, Qt::CaseSensitivity cs) const { return QBool(indexOf(s, 0, cs) != -1); } +inline QBool QString::contains(const QStringRef &s, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(s, 0, cs) != -1); } inline QBool QString::contains(QChar c, Qt::CaseSensitivity cs) const { return QBool(indexOf(c, 0, cs) != -1); } @@ -1123,6 +1128,34 @@ public: m_size = other.m_size; return *this; } + int indexOf(const QString &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int indexOf(QChar ch, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int indexOf(QLatin1String str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int indexOf(const QStringRef &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(const QString &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(QChar ch, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(QLatin1String str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(const QStringRef &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + inline QBool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QBool contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QBool contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QBool contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int count(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool startsWith(const QStringRef &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool endsWith(const QStringRef &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QStringRef &operator=(const QString *string); inline const QChar *unicode() const { @@ -1133,6 +1166,12 @@ public: inline const QChar *data() const { return unicode(); } inline const QChar *constData() const { return unicode(); } + QByteArray toAscii() const Q_REQUIRED_RESULT; + QByteArray toLatin1() const Q_REQUIRED_RESULT; + QByteArray toUtf8() const Q_REQUIRED_RESULT; + QByteArray toLocal8Bit() const Q_REQUIRED_RESULT; + QVector<uint> toUcs4() const Q_REQUIRED_RESULT; + inline void clear() { m_string = 0; m_position = m_size = 0; } QString toString() const; inline bool isEmpty() const { return m_size == 0; } @@ -1241,6 +1280,16 @@ inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QString &s inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QStringRef &s2) { return QString::localeAwareCompare_helper(s1.constData(), s1.length(), s2.constData(), s2.length()); } +inline QBool QStringRef::contains(const QString &s, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(s, 0, cs) != -1); } +inline QBool QStringRef::contains(QLatin1String s, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(s, 0, cs) != -1); } +inline QBool QStringRef::contains(QChar c, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(c, 0, cs) != -1); } +inline QBool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(s, 0, cs) != -1); } + + QT_END_NAMESPACE diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index 4a6bb4b..3882323 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -44,7 +44,10 @@ #include <QtCore/qcontainerfwd.h> #include <QtCore/qglobal.h> +#include <QtCore/qalgorithms.h> + #include <new> +#include <string.h> QT_BEGIN_HEADER @@ -123,6 +126,18 @@ public: } } void append(const T *buf, int size); + inline QVarLengthArray<T, Prealloc> &operator<<(const T &t) + { append(t); return *this; } + inline QVarLengthArray<T, Prealloc> &operator+=(const T &t) + { append(t); return *this; } + + void prepend(const T &t); + void insert(int i, const T &t); + void insert(int i, int n, const T &t); + void replace(int i, const T &t); + void remove(int i); + void remove(int i, int n); + inline T *data() { return ptr; } inline const T *data() const { return ptr; } @@ -135,6 +150,21 @@ public: typedef const value_type &const_reference; typedef qptrdiff difference_type; + + typedef T* iterator; + typedef const T* const_iterator; + + inline iterator begin() { return ptr; } + inline const_iterator begin() const { return ptr; } + inline const_iterator constBegin() const { return ptr; } + inline iterator end() { return ptr + s; } + inline const_iterator end() const { return ptr + s; } + inline const_iterator constEnd() const { return ptr + s; } + iterator insert(iterator before, int n, const T &x); + inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); } + iterator erase(iterator begin, iterator end); + inline iterator erase(iterator pos) { return erase(pos, pos+1); } + private: friend class QPodList<T, Prealloc>; void realloc(int size, int alloc); @@ -272,6 +302,100 @@ Q_OUTOFLINE_TEMPLATE T QVarLengthArray<T, Prealloc>::value(int i, const T &defau return (i < 0 || i >= size()) ? defaultValue : at(i); } +template <class T, int Prealloc> +inline void QVarLengthArray<T, Prealloc>::insert(int i, const T &t) +{ Q_ASSERT_X(i >= 0 && i <= s, "QVarLengthArray::insert", "index out of range"); + insert(begin() + i, 1, t); } +template <class T, int Prealloc> +inline void QVarLengthArray<T, Prealloc>::insert(int i, int n, const T &t) +{ Q_ASSERT_X(i >= 0 && i <= s, "QVarLengthArray::insert", "index out of range"); + insert(begin() + i, n, t); } +template <class T, int Prealloc> +inline void QVarLengthArray<T, Prealloc>::remove(int i, int n) +{ Q_ASSERT_X(i >= 0 && n >= 0 && i + n <= s, "QVarLengthArray::remove", "index out of range"); + erase(begin() + i, begin() + i + n); } +template <class T, int Prealloc> +inline void QVarLengthArray<T, Prealloc>::remove(int i) +{ Q_ASSERT_X(i >= 0 && i < s, "QVarLengthArray::remove", "index out of range"); + erase(begin() + i, begin() + i + 1); } +template <class T, int Prealloc> +inline void QVarLengthArray<T, Prealloc>::prepend(const T &t) +{ insert(begin(), 1, t); } + +template <class T, int Prealloc> +inline void QVarLengthArray<T, Prealloc>::replace(int i, const T &t) +{ + Q_ASSERT_X(i >= 0 && i < s, "QVarLengthArray::replace", "index out of range"); + const T copy(t); + data()[i] = copy; +} + + +template <class T, int Prealloc> +Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(iterator before, size_type n, const T &t) +{ + int offset = int(before - ptr); + if (n != 0) { + resize(s + n); + const T copy(t); + if (QTypeInfo<T>::isStatic) { + T *b = ptr + offset; + T *j = ptr + s; + T *i = j - n; + while (i != b) + *--j = *--i; + i = b + n; + while (i != b) + *--i = copy; + } else { + T *b = ptr + offset; + T *i = b + n; + memmove(i, b, (s - offset - n) * sizeof(T)); + while (i != b) + new (--i) T(copy); + } + } + return ptr + offset; +} + +template <class T, int Prealloc> +Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::erase(iterator abegin, iterator aend) +{ + int f = int(abegin - ptr); + int l = int(aend - ptr); + int n = l - f; + if (QTypeInfo<T>::isComplex) { + qCopy(ptr + l, ptr + s, ptr + f); + T *i = ptr + s; + T *b = ptr + s - n; + while (i != b) { + --i; + i->~T(); + } + } else { + memmove(ptr + f, ptr + l, (s - l) * sizeof(T)); + } + s -= n; + return ptr + f; +} + +template <typename T, int Prealloc1, int Prealloc2> +bool operator==(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r) +{ + if (l.size() != r.size()) + return false; + for (int i = 0; i < l.size(); i++) { + if (l.at(i) != r.at(i)) + return false; + } + return true; +} + +template <typename T, int Prealloc1, int Prealloc2> +bool operator!=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r) +{ + return !(l == r); +} QT_END_NAMESPACE diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc index 6f91bcc..4d5d5d1 100644 --- a/src/corelib/tools/qvarlengtharray.qdoc +++ b/src/corelib/tools/qvarlengtharray.qdoc @@ -337,3 +337,211 @@ Typedef for const T &. Provided for STL compatibility. */ +/*! \fn void QVarLengthArray::prepend(const T &value) + + \since 4.8 + Inserts \a value at the beginning of the array. + + + This is the same as vector.insert(0, \a value). + + For large arrays, this operation can be slow (\l{linear time}), + because it requires moving all the items in the vector by one + position further in memory. If you want a container class that + provides a fast prepend() function, use QList or QLinkedList + instead. + + \sa append(), insert() +*/ + +/*! \fn void QVarLengthArray::replace(int i, const T &value) + + \since 4.8 + Replaces the item at index position \a i with \a value. + + \a i must be a valid index position in the array (i.e., 0 <= \a + i < size()). + + \sa operator[](), remove() +*/ + +/*! \fn void QVarLengthArray::remove(int i) + + \overload + \since 4.8 + + Removes the element at index position \a i. + + \sa insert(), replace() +*/ + +/*! \fn void QVarLengthArray::remove(int i, int count) + + \overload + \since 4.8 + + Removes \a count elements from the middle of the array, starting at + index position \a i. + + \sa insert(), replace() +*/ + +/*! \fn QVarLengthArray::iterator QVarLengthArray::begin() + \since 4.8 + + Returns an \l{STL-style iterator} pointing to the first item in + the array. + + \sa constBegin(), end() +*/ + +/*! \fn QVarLengthArray::const_iterator QVarLengthArray::begin() const + \since 4.8 + \overload +*/ + +/*! \fn QVarLengthArray::const_iterator QVarLengthArray::constBegin() const + \since 4.8 + + Returns a const \l{STL-style iterator} pointing to the first item + in the array. + + \sa begin(), constEnd() +*/ + +/*! \fn QVarLengthArray::iterator QVarLengthArray::end() + \since 4.8 + + Returns an \l{STL-style iterator} pointing to the imaginary item + after the last item in the array. + + \sa begin(), constEnd() +*/ + +/*! \fn QVarLengthArray::const_iterator QVarLengthArray::end() const + \since 4.8 + + \overload +*/ + +/*! \fn QVarLengthArray::const_iterator QVarLengthArray::constEnd() const + \since 4.8 + + Returns a const \l{STL-style iterator} pointing to the imaginary + item after the last item in the array. + + \sa constBegin(), end() +*/ + +/*! \fn QVarLengthArray::iterator QVarLengthArray::erase(iterator pos) + \since 4.8 + + Removes the item pointed to by the iterator \a pos from the + vector, and returns an iterator to the next item in the vector + (which may be end()). + + \sa insert(), remove() +*/ + +/*! \fn QVarLengthArray::iterator QVarLengthArray::erase(iterator begin, iterator end) + + \overload + \since 4.8 + + Removes all the items from \a begin up to (but not including) \a + end. Returns an iterator to the same item that \a end referred to + before the call. +*/ + +/*! \fn void QVarLengthArray::insert(int i, const T &value) + \since 4.8 + + Inserts \a value at index position \a i in the array. If \a i is + 0, the value is prepended to the vector. If \a i is size(), the + value is appended to the vector. + + For large arrays, this operation can be slow (\l{linear time}), + because it requires moving all the items at indexes \a i and + above by one position further in memory. If you want a container + class that provides a fast insert() function, use QLinkedList + instead. + + \sa remove() +*/ + +/*! \fn void QVarLengthArray::insert(int i, int count, const T &value) + + \overload + \since 4.8 + + Inserts \a count copies of \a value at index position \a i in the + vector. +*/ + +/*! \fn QVarLengthArray::iterator QVarLengthArray::insert(iterator before, const T &value) + + \overload + \since 4.8 + + Inserts \a value in front of the item pointed to by the iterator + \a before. Returns an iterator pointing at the inserted item. +*/ + +/*! \fn QVarLengthArray::iterator QVarLengthArray::insert(iterator before, int count, const T &value) + + \since 4.8 + Inserts \a count copies of \a value in front of the item pointed to + by the iterator \a before. Returns an iterator pointing at the + first of the inserted items. +*/ + + + +/*! \fn bool operator==(const QVarLengthArray<T, Prealloc1> &left, const QVarLengthArray<T, Prealloc2> &right) + + \relates QVarLengthArray + \since 4.8 + Returns true if the two array are equal; + + Two arrays are considered equal if they contain the same values + in the same order. + + This function requires the value type to have an implementation + of \c operator==(). + + \sa operator!=() +*/ + +/*! \fn bool operator!=(const QVarLengthArray<T, Prealloc1> &left, const QVarLengthArray<T, Prealloc2> &right) + + \relates QVarLengthArray + \since 4.8 + Returns true if the two array are different; + + Two arrays are considered equal if they contain the same values + in the same order. + + This function requires the value type to have an implementation + of \c operator==(). + + \sa operator==() +*/ + +/*! \fn QVarLengthArray &QVarLengthArray::operator<<(const T &value) + + \since 4.8 + Appends \a value to the array and returns a reference to this + vector. + + \sa append(), operator+=() +*/ + +/*! \fn QVarLengthArray &QVarLengthArray::operator+=(const T &value) + + \since 4.8 + Appends \a value to the array and returns a reference to this + vector. + + \sa append(), operator<<() +*/ + diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp index 3a13540..0497211 100644 --- a/src/corelib/tools/qvector.cpp +++ b/src/corelib/tools/qvector.cpp @@ -285,6 +285,13 @@ int QVectorData::grow(int sizeofTypedData, int size, int sizeofT, bool excessive vector. */ +/*! \fn void QVector::swap(QVector<T> &other) + \since 4.8 + + Swaps vector \a other with this vector. This operation is very fast and + never fails. +*/ + /*! \fn bool QVector::operator==(const QVector<T> &other) const Returns true if \a other is equal to this vector; otherwise diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 2b8d054..4044a66 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -53,6 +53,9 @@ #endif #include <stdlib.h> #include <string.h> +#ifdef Q_COMPILER_INITIALIZER_LISTS +#include <initializer_list> +#endif QT_BEGIN_HEADER @@ -118,6 +121,14 @@ public: inline QVector(const QVector<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); } inline ~QVector() { if (!d) return; if (!d->ref.deref()) free(p); } QVector<T> &operator=(const QVector<T> &v); +#ifdef Q_COMPILER_RVALUE_REFS + inline QVector<T> operator=(QVector<T> &&other) + { qSwap(p, other.p); return *this; } +#endif + inline void swap(QVector<T> &other) { qSwap(d, other.d); } +#ifdef Q_COMPILER_INITIALIZER_LISTS + inline QVector(std::initializer_list<T> args); +#endif bool operator==(const QVector<T> &v) const; inline bool operator!=(const QVector<T> &v) const { return !(*this == v); } @@ -297,7 +308,6 @@ public: inline std::vector<T> toStdVector() const { std::vector<T> tmp; tmp.reserve(size()); qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; } #endif - private: friend class QRegion; // Optimization for QRegion::rects() @@ -426,6 +436,22 @@ QVector<T>::QVector(int asize, const T &t) new (--i) T(t); } +#ifdef Q_COMPILER_INITIALIZER_LISTS +template <typename T> +QVector<T>::QVector(std::initializer_list<T> args) +{ + d = malloc(args.size()); + d->ref = 1; + d->alloc = d->size = args.size(); + d->sharable = true; + d->capacity = false; + T* i = p->array + d->size; + auto it = args.end(); + while (i != p->array) + new (--i) T(*(--it)); +} +#endif + template <typename T> void QVector<T>::free(Data *x) { @@ -790,11 +816,8 @@ QT_END_INCLUDE_NAMESPACE #else #define Q_TEMPLATE_EXTERN extern #endif -# pragma warning(push) /* MSVC 6.0 doesn't care about the disabling in qglobal.h (why?), so do it here */ -# pragma warning(disable: 4231) /* nonstandard extension used : 'extern' before template explicit instantiation */ Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPointF>; Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPoint>; -# pragma warning(pop) #endif QT_END_NAMESPACE diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index d81ab04..03bb32d 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -83,7 +83,7 @@ SOURCES += \ symbian:SOURCES+=tools/qlocale_symbian.cpp -mac:SOURCES += tools/qelapsedtimer_mac.cpp +!nacl:mac:SOURCES += tools/qelapsedtimer_mac.cpp else:symbian:SOURCES += tools/qelapsedtimer_symbian.cpp else:unix:SOURCES += tools/qelapsedtimer_unix.cpp else:win32:SOURCES += tools/qelapsedtimer_win.cpp diff --git a/src/corelib/xml/qxmlstream.h b/src/corelib/xml/qxmlstream.h index 402afa3..d7143bd 100644 --- a/src/corelib/xml/qxmlstream.h +++ b/src/corelib/xml/qxmlstream.h @@ -169,6 +169,7 @@ Q_DECLARE_TYPEINFO(QXmlStreamAttribute, Q_MOVABLE_TYPE); class Q_XMLSTREAM_EXPORT QXmlStreamAttributes : public QVector<QXmlStreamAttribute> { public: + inline QXmlStreamAttributes() {} QStringRef value(const QString &namespaceUri, const QString &name) const; QStringRef value(const QString &namespaceUri, const QLatin1String &name) const; QStringRef value(const QLatin1String &namespaceUri, const QLatin1String &name) const; diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp index 0ea8c8d..943b965 100644 --- a/src/dbus/qdbusabstractinterface.cpp +++ b/src/dbus/qdbusabstractinterface.cpp @@ -208,7 +208,7 @@ bool QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const Q QLatin1String(DBUS_INTERFACE_PROPERTIES), QLatin1String("Set")); QDBusMessagePrivate::setParametersValidated(msg, true); - msg << interface << QString::fromUtf8(mp.name()) << qVariantFromValue(QDBusVariant(value)); + msg << interface << QString::fromUtf8(mp.name()) << QVariant::fromValue(QDBusVariant(value)); QDBusMessage reply = connection.call(msg, QDBus::Block); if (reply.type() != QDBusMessage::ReplyMessage) { diff --git a/src/dbus/qdbusdemarshaller.cpp b/src/dbus/qdbusdemarshaller.cpp index 6e19218..0df4c6b 100644 --- a/src/dbus/qdbusdemarshaller.cpp +++ b/src/dbus/qdbusdemarshaller.cpp @@ -188,11 +188,11 @@ QVariant QDBusDemarshaller::toVariantInternal() { switch (q_dbus_message_iter_get_arg_type(&iterator)) { case DBUS_TYPE_BYTE: - return qVariantFromValue(toByte()); + return QVariant::fromValue(toByte()); case DBUS_TYPE_INT16: - return qVariantFromValue(toShort()); + return QVariant::fromValue(toShort()); case DBUS_TYPE_UINT16: - return qVariantFromValue(toUShort()); + return QVariant::fromValue(toUShort()); case DBUS_TYPE_INT32: return toInt(); case DBUS_TYPE_UINT32: @@ -208,11 +208,11 @@ QVariant QDBusDemarshaller::toVariantInternal() case DBUS_TYPE_STRING: return toString(); case DBUS_TYPE_OBJECT_PATH: - return qVariantFromValue(toObjectPath()); + return QVariant::fromValue(toObjectPath()); case DBUS_TYPE_SIGNATURE: - return qVariantFromValue(toSignature()); + return QVariant::fromValue(toSignature()); case DBUS_TYPE_VARIANT: - return qVariantFromValue(toVariant()); + return QVariant::fromValue(toVariant()); case DBUS_TYPE_ARRAY: switch (q_dbus_message_iter_get_element_type(&iterator)) { @@ -222,14 +222,14 @@ QVariant QDBusDemarshaller::toVariantInternal() case DBUS_TYPE_STRING: return toStringList(); case DBUS_TYPE_DICT_ENTRY: - return qVariantFromValue(duplicate()); + return QVariant::fromValue(duplicate()); default: - return qVariantFromValue(duplicate()); + return QVariant::fromValue(duplicate()); } case DBUS_TYPE_STRUCT: - return qVariantFromValue(duplicate()); + return QVariant::fromValue(duplicate()); default: qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'", diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index a5d8ada..c7f62aa 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -820,14 +820,14 @@ bool QDBusConnectionPrivate::activateCall(QObject* object, int flags, const QDBu slotData.slotIdx = -1; slotData.metaTypes.clear(); slotCache.hash.insert(cacheKey, slotData); - object->setProperty(cachePropertyName, qVariantFromValue(slotCache)); + object->setProperty(cachePropertyName, QVariant::fromValue(slotCache)); return false; } } // save to the cache slotCache.hash.insert(cacheKey, slotData); - object->setProperty(cachePropertyName, qVariantFromValue(slotCache)); + object->setProperty(cachePropertyName, QVariant::fromValue(slotCache)); // found the slot to be called deliverCall(object, flags, msg, slotData.metaTypes, slotData.slotIdx); diff --git a/src/dbus/qdbusinternalfilters.cpp b/src/dbus/qdbusinternalfilters.cpp index 78abf94..b6cf1fd 100644 --- a/src/dbus/qdbusinternalfilters.cpp +++ b/src/dbus/qdbusinternalfilters.cpp @@ -264,7 +264,7 @@ QDBusMessage qDBusPropertyGet(const QDBusConnectionPrivate::ObjectTreeNode &node return propertyNotFoundError(msg, interface_name, property_name); } - return msg.createReply(qVariantFromValue(QDBusVariant(value))); + return msg.createReply(QVariant::fromValue(QDBusVariant(value))); } enum PropertyWriteResult { @@ -334,7 +334,7 @@ static int writeProperty(QObject *obj, const QByteArray &property_name, QVariant // we have to demarshall before writing void *null = 0; QVariant other(id, null); - if (!QDBusMetaType::demarshall(qVariantValue<QDBusArgument>(value), id, other.data())) { + if (!QDBusMetaType::demarshall(qvariant_cast<QDBusArgument>(value), id, other.data())) { qWarning("QDBusConnection: type `%s' (%d) is not registered with QtDBus. " "Use qDBusRegisterMetaType to register it", mp.typeName(), id); @@ -495,7 +495,7 @@ QDBusMessage qDBusPropertyGetAll(const QDBusConnectionPrivate::ObjectTreeNode &n return interfaceNotFoundError(msg, interface_name); } - return msg.createReply(qVariantFromValue(result)); + return msg.createReply(QVariant::fromValue(result)); } QT_END_NAMESPACE diff --git a/src/declarative/debugger/qdeclarativedebug.cpp b/src/declarative/debugger/qdeclarativedebug.cpp index 7a5e5f6..ed0ceba 100644 --- a/src/declarative/debugger/qdeclarativedebug.cpp +++ b/src/declarative/debugger/qdeclarativedebug.cpp @@ -210,7 +210,7 @@ void QDeclarativeEngineDebugPrivate::decode(QDataStream &ds, QDeclarativeDebugOb { QDeclarativeDebugObjectReference obj; obj.m_debugId = prop.m_value.toInt(); - prop.m_value = qVariantFromValue(obj); + prop.m_value = QVariant::fromValue(obj); break; } case QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::Unknown: diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index b737785..6fe1522 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -1069,71 +1069,50 @@ void QDeclarativeFlickablePrivate::data_append(QDeclarativeListProperty<QObject> } } -static inline int children_count_helper(QGraphicsObject *object) +int QDeclarativeFlickablePrivate::data_count(QDeclarativeListProperty<QObject> *property) { - QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(object); - return d->children.count(); + QDeclarativeItem *contentItem= static_cast<QDeclarativeFlickablePrivate*>(property->data)->contentItem; + return contentItem->childItems().count() + contentItem->children().count(); } -static inline QObject *children_at_helper(QGraphicsObject *object, int index) +QObject *QDeclarativeFlickablePrivate::data_at(QDeclarativeListProperty<QObject> *property, int index) { - QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(object); - if (index >= 0 && index < d->children.count()) - return d->children.at(index)->toGraphicsObject(); - else + QDeclarativeItem *contentItem = static_cast<QDeclarativeFlickablePrivate*>(property->data)->contentItem; + + int childItemCount = contentItem->childItems().count(); + + if (index < 0) return 0; -} -static inline void children_clear_helper(QGraphicsObject *object) -{ - QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(object); - int childCount = d->children.count(); - if (static_cast<QDeclarativeItemPrivate*>(d)->componentComplete) { - for (int index = 0 ;index < childCount; index++) { - d->children.at(0)->setParentItem(0); - } + if (index < childItemCount) { + return contentItem->childItems().at(index)->toGraphicsObject(); } else { - for (int index = 0 ;index < childCount; index++) { - QGraphicsItemPrivate::get(d->children.at(0))->setParentItemHelper(0, /*newParentVariant=*/0, /*thisPointerVariant=*/0); - } + return contentItem->children().at(index - childItemCount); } + return 0; } -int QDeclarativeFlickablePrivate::data_count(QDeclarativeListProperty<QObject> *prop) +void QDeclarativeFlickablePrivate::data_clear(QDeclarativeListProperty<QObject> *property) { - return QDeclarativeItemPrivate::resources_count(prop) + - children_count_helper(static_cast<QDeclarativeFlickablePrivate*>(prop->data)->contentItem); -} + QDeclarativeItem *contentItem = static_cast<QDeclarativeFlickablePrivate*>(property->data)->contentItem; -QObject *QDeclarativeFlickablePrivate::data_at(QDeclarativeListProperty<QObject> *prop, int i) -{ - int resourcesCount = QDeclarativeItemPrivate::resources_count(prop); - if (i < resourcesCount) - return QDeclarativeItemPrivate::resources_at(prop, i); - const int j = i - resourcesCount; - QGraphicsObject *contentObject = static_cast<QDeclarativeFlickablePrivate*>(prop->data)->contentItem; - if (j < children_count_helper(contentObject)) - return children_at_helper(contentObject, j); - return 0; -} + const QList<QGraphicsItem*> graphicsItems = contentItem->childItems(); + for (int i = 0; i < graphicsItems.count(); i++) + contentItem->scene()->removeItem(graphicsItems[i]); -void QDeclarativeFlickablePrivate::data_clear(QDeclarativeListProperty<QObject> *prop) -{ - QDeclarativeItemPrivate::resources_clear(prop); - QGraphicsObject *contentObject = - static_cast<QDeclarativeFlickablePrivate*>(prop->data)->contentItem; - children_clear_helper(contentObject); + const QList<QObject*> objects = contentItem->children(); + for (int i = 0; i < objects.count(); i++) + objects[i]->setParent(0); } QDeclarativeListProperty<QObject> QDeclarativeFlickable::flickableData() { Q_D(QDeclarativeFlickable); return QDeclarativeListProperty<QObject>(this, (void *)d, QDeclarativeFlickablePrivate::data_append, - QDeclarativeFlickablePrivate::data_count, - QDeclarativeFlickablePrivate::data_at, - QDeclarativeFlickablePrivate::data_clear - ); + QDeclarativeFlickablePrivate::data_count, + QDeclarativeFlickablePrivate::data_at, + QDeclarativeFlickablePrivate::data_clear); } QDeclarativeListProperty<QGraphicsObject> QDeclarativeFlickable::flickableChildren() diff --git a/src/declarative/qml/parser/qdeclarativejsengine_p.h b/src/declarative/qml/parser/qdeclarativejsengine_p.h index 1389244..d0b744d 100644 --- a/src/declarative/qml/parser/qdeclarativejsengine_p.h +++ b/src/declarative/qml/parser/qdeclarativejsengine_p.h @@ -88,12 +88,6 @@ uint qHash(const QDeclarativeJS::NameId &id); } // end of namespace QDeclarativeJS -#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 -//this ensures that code outside QDeclarativeJS can use the hash function -//it also a workaround for some compilers -inline uint qHash(const QDeclarativeJS::NameId &nameId) { return QDeclarativeJS::qHash(nameId); } -#endif - namespace QDeclarativeJS { class Lexer; diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 6906f21..a11455d 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -1327,7 +1327,7 @@ QScriptValue QDeclarativeEnginePrivate::vector3d(QScriptContext *ctxt, QScriptEn qsreal x = ctxt->argument(0).toNumber(); qsreal y = ctxt->argument(1).toNumber(); qsreal z = ctxt->argument(2).toNumber(); - return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(qVariantFromValue(QVector3D(x, y, z))); + return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QVector3D(x, y, z))); } /*! @@ -1347,14 +1347,14 @@ QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptE QScriptValue formatArg = ctxt->argument(1); if (formatArg.isString()) { QString format = formatArg.toString(); - return engine->newVariant(qVariantFromValue(date.toString(format))); + return engine->newVariant(QVariant::fromValue(date.toString(format))); } else if (formatArg.isNumber()) { enumFormat = Qt::DateFormat(formatArg.toUInt32()); } else { return ctxt->throwError(QLatin1String("Qt.formatDate(): Invalid date format")); } } - return engine->newVariant(qVariantFromValue(date.toString(enumFormat))); + return engine->newVariant(QVariant::fromValue(date.toString(enumFormat))); } /*! @@ -1375,14 +1375,14 @@ QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptE QScriptValue formatArg = ctxt->argument(1); if (formatArg.isString()) { QString format = formatArg.toString(); - return engine->newVariant(qVariantFromValue(date.toString(format))); + return engine->newVariant(QVariant::fromValue(date.toString(format))); } else if (formatArg.isNumber()) { enumFormat = Qt::DateFormat(formatArg.toUInt32()); } else { return ctxt->throwError(QLatin1String("Qt.formatTime(): Invalid time format")); } } - return engine->newVariant(qVariantFromValue(date.toString(enumFormat))); + return engine->newVariant(QVariant::fromValue(date.toString(enumFormat))); } /*! @@ -1466,14 +1466,14 @@ QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScr QScriptValue formatArg = ctxt->argument(1); if (formatArg.isString()) { QString format = formatArg.toString(); - return engine->newVariant(qVariantFromValue(date.toString(format))); + return engine->newVariant(QVariant::fromValue(date.toString(format))); } else if (formatArg.isNumber()) { enumFormat = Qt::DateFormat(formatArg.toUInt32()); } else { return ctxt->throwError(QLatin1String("Qt.formatDateTime(): Invalid datetime format")); } } - return engine->newVariant(qVariantFromValue(date.toString(enumFormat))); + return engine->newVariant(QVariant::fromValue(date.toString(enumFormat))); } #endif // QT_NO_DATESTRING @@ -1502,7 +1502,7 @@ QScriptValue QDeclarativeEnginePrivate::rgba(QScriptContext *ctxt, QScriptEngine if (a < 0.0) a=0.0; if (a > 1.0) a=1.0; - return qScriptValueFromValue(engine, qVariantFromValue(QColor::fromRgbF(r, g, b, a))); + return engine->toScriptValue(QVariant::fromValue(QColor::fromRgbF(r, g, b, a))); } /*! @@ -1530,7 +1530,7 @@ QScriptValue QDeclarativeEnginePrivate::hsla(QScriptContext *ctxt, QScriptEngine if (a < 0.0) a=0.0; if (a > 1.0) a=1.0; - return qScriptValueFromValue(engine, qVariantFromValue(QColor::fromHslF(h, s, l, a))); + return engine->toScriptValue(QVariant::fromValue(QColor::fromHslF(h, s, l, a))); } /*! @@ -1553,7 +1553,7 @@ QScriptValue QDeclarativeEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine if (w < 0 || h < 0) return engine->nullValue(); - return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(qVariantFromValue(QRectF(x, y, w, h))); + return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QRectF(x, y, w, h))); } /*! @@ -1566,7 +1566,7 @@ QScriptValue QDeclarativeEnginePrivate::point(QScriptContext *ctxt, QScriptEngin return ctxt->throwError(QLatin1String("Qt.point(): Invalid arguments")); qsreal x = ctxt->argument(0).toNumber(); qsreal y = ctxt->argument(1).toNumber(); - return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(qVariantFromValue(QPointF(x, y))); + return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QPointF(x, y))); } /*! @@ -1579,7 +1579,7 @@ QScriptValue QDeclarativeEnginePrivate::size(QScriptContext *ctxt, QScriptEngine return ctxt->throwError(QLatin1String("Qt.size(): Invalid arguments")); qsreal w = ctxt->argument(0).toNumber(); qsreal h = ctxt->argument(1).toNumber(); - return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(qVariantFromValue(QSizeF(w, h))); + return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QSizeF(w, h))); } /*! @@ -1615,7 +1615,7 @@ QScriptValue QDeclarativeEnginePrivate::lighter(QScriptContext *ctxt, QScriptEng if (ctxt->argumentCount() == 2) factor = ctxt->argument(1).toNumber(); color = color.lighter(int(qRound(factor*100.))); - return qScriptValueFromValue(engine, qVariantFromValue(color)); + return engine->toScriptValue(QVariant::fromValue(color)); } /*! @@ -1652,7 +1652,7 @@ QScriptValue QDeclarativeEnginePrivate::darker(QScriptContext *ctxt, QScriptEngi if (ctxt->argumentCount() == 2) factor = ctxt->argument(1).toNumber(); color = color.darker(int(qRound(factor*100.))); - return qScriptValueFromValue(engine, qVariantFromValue(color)); + return engine->toScriptValue(QVariant::fromValue(color)); } /*! @@ -1892,7 +1892,7 @@ QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine a + inv_a * color.alphaF()); } - return qScriptValueFromValue(engine, qVariantFromValue(finalColor)); + return engine->toScriptValue(QVariant::fromValue(finalColor)); } QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val) @@ -1922,7 +1922,7 @@ QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &v if (objOk) { return objectClass->newQObject(obj); } else { - return qScriptValueFromValue(&scriptEngine, val); + return scriptEngine.toScriptValue(val); } } diff --git a/src/declarative/qml/qdeclarativesqldatabase.cpp b/src/declarative/qml/qdeclarativesqldatabase.cpp index 45f277e..42b596a 100644 --- a/src/declarative/qml/qdeclarativesqldatabase.cpp +++ b/src/declarative/qml/qdeclarativesqldatabase.cpp @@ -237,7 +237,7 @@ static QScriptValue qmlsqldatabase_executeSql(QScriptContext *context, QScriptEn if (!qmlengine->sqlQueryClass) qmlengine->sqlQueryClass = new QDeclarativeSqlQueryScriptClass(engine); QScriptValue rows = engine->newObject(qmlengine->sqlQueryClass); - rows.setData(engine->newVariant(qVariantFromValue(query))); + rows.setData(engine->newVariant(QVariant::fromValue(query))); rows.setProperty(QLatin1String("item"), engine->newFunction(qmlsqldatabase_item,1), QScriptValue::SkipInEnumeration); result.setProperty(QLatin1String("rows"),rows); result.setProperty(QLatin1String("rowsAffected"),query.numRowsAffected()); @@ -275,7 +275,7 @@ static QScriptValue qmlsqldatabase_change_version(QScriptContext *context, QScri QScriptValue instance = engine->newObject(); instance.setProperty(QLatin1String("executeSql"), engine->newFunction(qmlsqldatabase_executeSql,1)); - QScriptValue tx = engine->newVariant(instance,qVariantFromValue(db)); + QScriptValue tx = engine->newVariant(instance,QVariant::fromValue(db)); QString foundvers = context->thisObject().property(QLatin1String("version")).toString(); if (from_version!=foundvers) { @@ -319,7 +319,7 @@ static QScriptValue qmlsqldatabase_transaction_shared(QScriptContext *context, Q QScriptValue instance = engine->newObject(); instance.setProperty(QLatin1String("executeSql"), engine->newFunction(readOnly ? qmlsqldatabase_executeSql_readonly : qmlsqldatabase_executeSql,1)); - QScriptValue tx = engine->newVariant(instance,qVariantFromValue(db)); + QScriptValue tx = engine->newVariant(instance,QVariant::fromValue(db)); db.transaction(); callback.call(QScriptValue(), QScriptValueList() << tx); @@ -403,7 +403,7 @@ static QScriptValue qmlsqldatabase_open_sync(QScriptContext *context, QScriptEng instance.setProperty(QLatin1String("version"), version, QScriptValue::ReadOnly); instance.setProperty(QLatin1String("changeVersion"), engine->newFunction(qmlsqldatabase_change_version,3)); - QScriptValue result = engine->newVariant(instance,qVariantFromValue(database)); + QScriptValue result = engine->newVariant(instance,QVariant::fromValue(database)); if (created && dbcreationCallback.isFunction()) { dbcreationCallback.call(QScriptValue(), QScriptValueList() << result); diff --git a/src/declarative/qml/qdeclarativestringconverters.cpp b/src/declarative/qml/qdeclarativestringconverters.cpp index 7534a2c..8ec68ff 100644 --- a/src/declarative/qml/qdeclarativestringconverters.cpp +++ b/src/declarative/qml/qdeclarativestringconverters.cpp @@ -92,7 +92,7 @@ QVariant QDeclarativeStringConverters::variantFromString(const QString &s) QSizeF sz = sizeFFromString(s, &ok); if (ok) return QVariant(sz); QVector3D v = vector3DFromString(s, &ok); - if (ok) return qVariantFromValue(v); + if (ok) return QVariant::fromValue(v); return QVariant(s); } diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp index 789116e..509ca6b 100644 --- a/src/declarative/qml/qdeclarativeworkerscript.cpp +++ b/src/declarative/qml/qdeclarativeworkerscript.cpp @@ -331,7 +331,7 @@ QVariant QDeclarativeWorkerScriptEnginePrivate::scriptValueToVariant(const QScri QDeclarativeListModelWorkerAgent *agent = lm->agent(); if (agent) { QDeclarativeListModelWorkerAgent::VariantRef v(agent); - return qVariantFromValue(v); + return QVariant::fromValue(v); } else { return QVariant(); } diff --git a/src/declarative/qml/qdeclarativexmlhttprequest.cpp b/src/declarative/qml/qdeclarativexmlhttprequest.cpp index 332acc4..adfdbb3 100644 --- a/src/declarative/qml/qdeclarativexmlhttprequest.cpp +++ b/src/declarative/qml/qdeclarativexmlhttprequest.cpp @@ -58,6 +58,8 @@ #include <QtCore/qstack.h> #include <QtCore/qdebug.h> +#include <QtCore/QStringBuilder> + #ifndef QT_NO_XMLSTREAMREADER // From DOM-Level-3-Core spec @@ -510,7 +512,7 @@ QScriptValue Node::create(QScriptEngine *engine, NodeImpl *data) node.d = data; if (data) A(data); - return engine->newVariant(instance, qVariantFromValue(node)); + return engine->newVariant(instance, QVariant::fromValue(node)); } QScriptValue Element::prototype(QScriptEngine *engine) @@ -710,7 +712,7 @@ QScriptValue Document::load(QScriptEngine *engine, const QByteArray &data) instance.setPrototype(Document::prototype(engine)); Node documentNode; documentNode.d = document; - return engine->newVariant(instance, qVariantFromValue(documentNode)); + return engine->newVariant(instance, QVariant::fromValue(documentNode)); } Node::Node() @@ -761,7 +763,7 @@ QScriptValue NamedNodeMap::create(QScriptEngine *engine, NodeImpl *data, QList<N map.list = list; if (data) A(data); - instance.setData(engine->newVariant(qVariantFromValue(map))); + instance.setData(engine->newVariant(QVariant::fromValue(map))); if (!QDeclarativeScriptEngine::get(engine)->namedNodeMapClass) QDeclarativeScriptEngine::get(engine)->namedNodeMapClass= new NamedNodeMapClass(engine); @@ -818,7 +820,7 @@ QScriptValue NodeList::create(QScriptEngine *engine, NodeImpl *data) list.d = data; if (data) A(data); - instance.setData(engine->newVariant(qVariantFromValue(list))); + instance.setData(engine->newVariant(QVariant::fromValue(list))); if (!QDeclarativeScriptEngine::get(engine)->nodeListClass) QDeclarativeScriptEngine::get(engine)->nodeListClass= new NodeListClass(engine); @@ -1090,10 +1092,9 @@ QString QDeclarativeXMLHttpRequest::headers() foreach (const HeaderPair &header, m_headersList) { if (ret.length()) - ret.append(QString::fromUtf8("\r\n")); - ret.append(QString::fromUtf8(header.first)); - ret.append(QString::fromUtf8(": ")); - ret.append(QString::fromUtf8(header.second)); + ret.append(QLatin1String("\r\n")); + ret = ret % QString::fromUtf8(header.first) % QLatin1String(": ") + % QString::fromUtf8(header.second); } return ret; } @@ -1105,9 +1106,9 @@ void QDeclarativeXMLHttpRequest::fillHeadersList() m_headersList.clear(); foreach (const QByteArray &header, headerList) { HeaderPair pair (header.toLower(), m_network->rawHeader(header)); - if (pair.first == "set-cookie" || - pair.first == "set-cookie2") - continue; + if (pair.first == "set-cookie" || + pair.first == "set-cookie2") + continue; m_headersList << pair; } diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index f2e6217..58444bd 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -2949,4 +2949,8 @@ void QDeclarativeAnchorAnimation::transition(QDeclarativeStateActions &actions, } } +QDeclarativeScriptActionPrivate::QDeclarativeScriptActionPrivate() + : QDeclarativeAbstractAnimationPrivate(), hasRunScriptScript(false), reversing(false), proxy(this), rsa(0) {} + + QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativeanimation_p_p.h b/src/declarative/util/qdeclarativeanimation_p_p.h index 6305fbd..b8c2c6d 100644 --- a/src/declarative/util/qdeclarativeanimation_p_p.h +++ b/src/declarative/util/qdeclarativeanimation_p_p.h @@ -247,8 +247,7 @@ class QDeclarativeScriptActionPrivate : public QDeclarativeAbstractAnimationPriv { Q_DECLARE_PUBLIC(QDeclarativeScriptAction) public: - QDeclarativeScriptActionPrivate() - : QDeclarativeAbstractAnimationPrivate(), hasRunScriptScript(false), reversing(false), proxy(this), rsa(0) {} + QDeclarativeScriptActionPrivate(); void init(); diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index 398480e..bbd20ac 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -793,7 +793,7 @@ void QDeclarativeListModelParser::setCustomData(QObject *obj, const QByteArray & { ModelNode *n = nodes.top(); ModelNode *n2 = new ModelNode(rv->m_nested); - n->values << qVariantFromValue(n2); + n->values << QVariant::fromValue(n2); nodes.push(n2); if (processingSet) n->isArray = true; @@ -1314,7 +1314,7 @@ bool NestedListModel::insert(int index, const QScriptValue& valuemap) ModelNode *mn = new ModelNode(this); mn->listIndex = index; mn->setObjectValue(valuemap); - _root->values.insert(index,qVariantFromValue(mn)); + _root->values.insert(index,QVariant::fromValue(mn)); return true; } @@ -1477,7 +1477,7 @@ void ModelNode::setListValue(const QScriptValue& valuelist) { value->listIndex = i; value->values << v.toVariant(); } - values.append(qVariantFromValue(value)); + values.append(QVariant::fromValue(value)); } } diff --git a/src/declarative/util/qdeclarativeview.cpp b/src/declarative/util/qdeclarativeview.cpp index 0e31a20..c4d8dde 100644 --- a/src/declarative/util/qdeclarativeview.cpp +++ b/src/declarative/util/qdeclarativeview.cpp @@ -710,6 +710,23 @@ void QDeclarativeView::paintEvent(QPaintEvent *event) if (frameRateDebug()) qDebug() << "paintEvent:" << d->frameTimer.elapsed() << "time since last frame:" << time; + +#if QT_SHOW_DECLARATIVEVIEW_FPS + static QTime timer; + static int frames; + + if (frames == 0) { + timer.start(); + } else if (timer.elapsed() > 5000) { + qreal avgtime = timer.elapsed() / (qreal) frames; + qDebug("Average time per frame: %f ms (%i fps)", avgtime, int(1000 / avgtime)); + timer.start(); + frames = 0; + } + ++frames; + scene()->update(); +#endif + } QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index ce5b483..337b1e0 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -806,7 +806,7 @@ QScriptValue QDeclarativeXmlListModel::get(int index) const QScriptValue sv = sengine->newObject(); for (int i=0; i<d->roleObjects.count(); i++) - sv.setProperty(d->roleObjects[i]->name(), qScriptValueFromValue(sengine, d->data.value(i).value(index))); + sv.setProperty(d->roleObjects[i]->name(), sengine->toScriptValue(d->data.value(i).value(index))); return sv; } diff --git a/src/gui/accessible/accessible.pri b/src/gui/accessible/accessible.pri index ad2fb4c..31362ff 100644 --- a/src/gui/accessible/accessible.pri +++ b/src/gui/accessible/accessible.pri @@ -12,7 +12,7 @@ contains(QT_CONFIG, accessibility) { accessible/qaccessiblewidget.cpp \ accessible/qaccessibleplugin.cpp - mac:!embedded { + mac:!embedded:!qpa { HEADERS += accessible/qaccessible_mac_p.h OBJECTIVE_SOURCES += accessible/qaccessible_mac.mm \ accessible/qaccessible_mac_cocoa.mm diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index 0921bdb..a6d1dbd 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -409,13 +409,18 @@ static void qAccessibleCleanup() /*! \typedef QAccessible::InterfaceFactory - A function pointer type. Use a function with this prototype to install - interface factories with installFactory(). + This is a typedef for a pointer to a function with the following + signature: - The function receives a QObject pointer. If the QObject - provides a QAccessibleInterface, it sets the second parameter to - point to the corresponding QAccessibleInterface, and returns true; - otherwise returns false. + \snippet doc/src/snippets/code/src_gui_accessible_qaccessible.cpp 1 + + The function receives a QString and a QObject pointer, where the + QString is the key identifying the interface. The QObject is used + to pass on to the QAccessibleInterface so that it can hold a reference + to it. + + If the key and the QObject does not have a corresponding + QAccessibleInterface, a null-pointer will be returned. Installed factories are called by queryAccessibilityInterface() until one provides an interface. diff --git a/src/gui/accessible/qaccessibleobject.cpp b/src/gui/accessible/qaccessibleobject.cpp index 7b2e7ce..3a4809e 100644 --- a/src/gui/accessible/qaccessibleobject.cpp +++ b/src/gui/accessible/qaccessibleobject.cpp @@ -276,7 +276,7 @@ QAccessible::Relation QAccessibleApplication::relationTo(int child, const for (int i = 0; i < tlw.count(); ++i) { QWidget *w = tlw.at(i); - QObjectList cl = qFindChildren<QObject *>(w, QString()); + QObjectList cl = w->findChildren<QObject *>(QString()); if (cl.contains(o)) return Ancestor; } diff --git a/src/gui/accessible/qaccessiblewidget.cpp b/src/gui/accessible/qaccessiblewidget.cpp index 7c13367..5b439a9 100644 --- a/src/gui/accessible/qaccessiblewidget.cpp +++ b/src/gui/accessible/qaccessiblewidget.cpp @@ -1015,7 +1015,7 @@ QVariant QAccessibleWidgetEx::invokeMethodEx(Method method, int child, const QVa case ListSupportedMethods: { QSet<QAccessible::Method> set; set << ListSupportedMethods << ForegroundColor << BackgroundColor; - return qVariantFromValue(set); + return QVariant::fromValue(set); } case ForegroundColor: return widget()->palette().color(widget()->foregroundRole()); diff --git a/src/gui/dialogs/dialogs.pri b/src/gui/dialogs/dialogs.pri index 4e1b9a7..cd8e71a 100644 --- a/src/gui/dialogs/dialogs.pri +++ b/src/gui/dialogs/dialogs.pri @@ -27,7 +27,7 @@ HEADERS += \ dialogs/qwizard.h \ dialogs/qprintpreviewdialog.h -!embedded:mac { +!embedded:!qpa:mac { OBJECTIVE_SOURCES += dialogs/qfiledialog_mac.mm \ dialogs/qfontdialog_mac.mm \ dialogs/qnspanelproxy_mac.mm \ @@ -61,7 +61,7 @@ win32 { !win32-borland:!wince*: LIBS += -lshell32 # the filedialog needs this library } -!mac:!embedded:!symbian:unix { +!mac:!embedded:!symbian:unix|qpa { HEADERS += dialogs/qpagesetupdialog_unix_p.h SOURCES += dialogs/qprintdialog_unix.cpp \ dialogs/qpagesetupdialog_unix.cpp diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp index b7a0026..6970b76 100644 --- a/src/gui/dialogs/qdialog.cpp +++ b/src/gui/dialogs/qdialog.cpp @@ -337,7 +337,7 @@ void QDialogPrivate::setDefault(QPushButton *pushButton) { Q_Q(QDialog); bool hasMain = false; - QList<QPushButton*> list = qFindChildren<QPushButton*>(q); + QList<QPushButton*> list = q->findChildren<QPushButton*>(); for (int i=0; i<list.size(); ++i) { QPushButton *pb = list.at(i); if (pb->window() == q) { @@ -372,7 +372,7 @@ void QDialogPrivate::setMainDefault(QPushButton *pushButton) void QDialogPrivate::hideDefault() { Q_Q(QDialog); - QList<QPushButton*> list = qFindChildren<QPushButton*>(q); + QList<QPushButton*> list = q->findChildren<QPushButton*>(); for (int i=0; i<list.size(); ++i) { list.at(i)->setDefault(false); } @@ -675,7 +675,7 @@ void QDialog::keyPressEvent(QKeyEvent *e) switch (e->key()) { case Qt::Key_Enter: case Qt::Key_Return: { - QList<QPushButton*> list = qFindChildren<QPushButton*>(this); + QList<QPushButton*> list = findChildren<QPushButton*>(); for (int i=0; i<list.size(); ++i) { QPushButton *pb = list.at(i); if (pb->isDefault() && pb->isVisible()) { diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp index fc3c186..1b9d127 100644 --- a/src/gui/dialogs/qfiledialog.cpp +++ b/src/gui/dialogs/qfiledialog.cpp @@ -2208,9 +2208,9 @@ void QFileDialogPrivate::createWidgets() #ifndef QT_NO_FSCOMPLETER completer = new QFSCompleter(model, q); qFileDialogUi->fileNameEdit->setCompleter(completer); +#endif // QT_NO_FSCOMPLETER QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)), q, SLOT(_q_autoCompleteFileName(QString))); -#endif // QT_NO_FSCOMPLETER QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)), q, SLOT(_q_updateOkButton())); @@ -3261,7 +3261,10 @@ QString QFSCompleter::pathFromIndex(const QModelIndex &index) const if (currentLocation == QDir::separator()) return path.mid(currentLocation.length()); #endif - return path.mid(currentLocation.length() + 1); + if (currentLocation.endsWith('/')) + return path.mid(currentLocation.length()); + else + return path.mid(currentLocation.length()+1); } return index.data(QFileSystemModel::FilePathRole).toString(); } diff --git a/src/gui/dialogs/qfiledialog_mac.mm b/src/gui/dialogs/qfiledialog_mac.mm index 87850a7..6c1d7f6 100644 --- a/src/gui/dialogs/qfiledialog_mac.mm +++ b/src/gui/dialogs/qfiledialog_mac.mm @@ -63,6 +63,7 @@ #include <qdesktopwidget.h> #include <stdlib.h> #include <qabstracteventdispatcher.h> +#import <AppKit/NSSavePanel.h> #include "ui_qfiledialog.h" QT_BEGIN_NAMESPACE @@ -84,7 +85,13 @@ QT_USE_NAMESPACE @class QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate); -@interface QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) : NSObject { +@interface QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + : NSObject<NSOpenSavePanelDelegate> +#else + : NSObject +#endif +{ @public NSOpenPanel *mOpenPanel; NSSavePanel *mSavePanel; diff --git a/src/gui/dialogs/qfiledialog_win.cpp b/src/gui/dialogs/qfiledialog_win.cpp index 5b192b4..feec804 100644 --- a/src/gui/dialogs/qfiledialog_win.cpp +++ b/src/gui/dialogs/qfiledialog_win.cpp @@ -60,7 +60,6 @@ #endif #ifdef Q_WS_WINCE -#include <shlobj.h> #include <commdlg.h> bool qt_priv_ptr_valid = false; #else @@ -603,7 +602,7 @@ QString qt_win_CID_get_existing_directory(const QFileDialogArgs &args) // Set the FOS_PICKFOLDERS flag DWORD newOptions; hr = pfd->GetOptions(&newOptions); - newOptions |= FOS_PICKFOLDERS; + newOptions |= (FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM); if (SUCCEEDED(hr) && SUCCEEDED((hr = pfd->SetOptions(newOptions)))) { QWidget *parentWindow = args.parent; if (parentWindow) diff --git a/src/gui/dialogs/qfileinfogatherer_p.h b/src/gui/dialogs/qfileinfogatherer_p.h index 8681eb5..b28509b 100644 --- a/src/gui/dialogs/qfileinfogatherer_p.h +++ b/src/gui/dialogs/qfileinfogatherer_p.h @@ -84,10 +84,13 @@ public: && permissions() == fileInfo.permissions(); } +#ifndef QT_NO_FSFILEENGINE bool isCaseSensitive() const { QFSFileEngine fe(mFileInfo.absoluteFilePath()); return fe.caseSensitive(); } +#endif + QFile::Permissions permissions() const { return mFileInfo.permissions(); } diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp index 8a9f8ae..5002beb 100644 --- a/src/gui/dialogs/qfilesystemmodel.cpp +++ b/src/gui/dialogs/qfilesystemmodel.cpp @@ -1313,6 +1313,10 @@ QString QFileSystemModelPrivate::filePath(const QModelIndex &index) const if ((fullPath.length() > 2) && fullPath[0] == QLatin1Char('/') && fullPath[1] == QLatin1Char('/')) fullPath = fullPath.mid(1); #endif +#if defined(Q_OS_WIN) + if (fullPath.length() == 2 && fullPath.endsWith(QLatin1Char(':'))) + fullPath.append(QLatin1Char('/')); +#endif return fullPath; } @@ -1631,6 +1635,14 @@ bool QFileSystemModel::event(QEvent *event) return QAbstractItemModel::event(event); } +bool QFileSystemModel::rmdir(const QModelIndex &aindex) const +{ + QString path = filePath(aindex); + QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func()); + d->fileInfoGatherer.removePath(path); + return QDir().rmdir(path); +} + /*! \internal diff --git a/src/gui/dialogs/qfilesystemmodel.h b/src/gui/dialogs/qfilesystemmodel.h index d8178c7..741f22b 100644 --- a/src/gui/dialogs/qfilesystemmodel.h +++ b/src/gui/dialogs/qfilesystemmodel.h @@ -139,7 +139,7 @@ public: QDateTime lastModified(const QModelIndex &index) const; QModelIndex mkdir(const QModelIndex &parent, const QString &name); - inline bool rmdir(const QModelIndex &index) const; + bool rmdir(const QModelIndex &index) const; // ### Qt5: should not be const inline QString fileName(const QModelIndex &index) const; inline QIcon fileIcon(const QModelIndex &index) const; QFile::Permissions permissions(const QModelIndex &index) const; @@ -163,8 +163,6 @@ private: friend class QFileDialogPrivate; }; -inline bool QFileSystemModel::rmdir(const QModelIndex &aindex) const -{ QDir dir; return dir.rmdir(filePath(aindex)); } inline QString QFileSystemModel::fileName(const QModelIndex &aindex) const { return aindex.data(Qt::DisplayRole).toString(); } inline QIcon QFileSystemModel::fileIcon(const QModelIndex &aindex) const diff --git a/src/gui/dialogs/qfontdialog_mac.mm b/src/gui/dialogs/qfontdialog_mac.mm index 9c63dfa..6fb363b 100644 --- a/src/gui/dialogs/qfontdialog_mac.mm +++ b/src/gui/dialogs/qfontdialog_mac.mm @@ -496,7 +496,7 @@ void QFontDialogPrivate::setFont(void *delegate, const QFont &font) QMacCocoaAutoReleasePool pool; QFontEngine *fe = font.d->engineForScript(QUnicodeTables::Common); NSFontManager *mgr = [NSFontManager sharedFontManager]; - NSFont *nsFont = 0; + const NSFont *nsFont = 0; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 if (qstrcmp(fe->name(), "CoreText") == 0) { @@ -522,7 +522,7 @@ void QFontDialogPrivate::setFont(void *delegate, const QFont &font) size:fontInfo.pointSize()]; } - [mgr setSelectedFont:nsFont isMultiple:NO]; + [mgr setSelectedFont:const_cast<NSFont *>(nsFont) isMultiple:NO]; [static_cast<QT_MANGLE_NAMESPACE(QCocoaFontPanelDelegate) *>(delegate) setQtFont:font]; } diff --git a/src/gui/dialogs/qinputdialog.cpp b/src/gui/dialogs/qinputdialog.cpp index ce27bd3..9e4b9b6 100644 --- a/src/gui/dialogs/qinputdialog.cpp +++ b/src/gui/dialogs/qinputdialog.cpp @@ -1134,6 +1134,8 @@ void QInputDialog::done(int result) be entered). \a text is the default text which is placed in the line edit. \a mode is the echo mode the line edit will use. + \a inputMethodHints is the input method hints that will be used in the + edit widget if an input method is active. If \a ok is nonnull \e *\a ok will be set to true if the user pressed \gui OK and to false if the user pressed \gui Cancel. The dialog's parent @@ -1156,13 +1158,14 @@ void QInputDialog::done(int result) QString QInputDialog::getText(QWidget *parent, const QString &title, const QString &label, QLineEdit::EchoMode mode, const QString &text, bool *ok, - Qt::WindowFlags flags) + Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints) { QInputDialog dialog(parent, flags); dialog.setWindowTitle(title); dialog.setLabelText(label); dialog.setTextValue(text); dialog.setTextEchoMode(mode); + dialog.setInputMethodHints(inputMethodHints); int ret = dialog.exec(); if (ok) @@ -1175,6 +1178,17 @@ QString QInputDialog::getText(QWidget *parent, const QString &title, const QStri } /*! + \internal +*/ +// ### Qt 5: Use only the version above. +QString QInputDialog::getText(QWidget *parent, const QString &title, const QString &label, + QLineEdit::EchoMode mode, const QString &text, bool *ok, + Qt::WindowFlags flags) +{ + return getText(parent, title, label, mode, text, ok, flags, Qt::ImhNone); +} + +/*! \since 4.5 Static convenience function to get an integer input from the user. @@ -1284,6 +1298,8 @@ double QInputDialog::getDouble(QWidget *parent, const QString &title, const QStr be entered). \a items is the string list which is inserted into the combobox. \a current is the number of the item which should be the current item. + \a inputMethodHints is the input method hints that will be used if the + combobox is editable and an input method is active. If \a editable is true the user can enter their own text; otherwise the user may only select one of the existing items. @@ -1308,7 +1324,7 @@ double QInputDialog::getDouble(QWidget *parent, const QString &title, const QStr QString QInputDialog::getItem(QWidget *parent, const QString &title, const QString &label, const QStringList &items, int current, bool editable, bool *ok, - Qt::WindowFlags flags) + Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints) { QString text(items.value(current)); @@ -1318,6 +1334,7 @@ QString QInputDialog::getItem(QWidget *parent, const QString &title, const QStri dialog.setComboBoxItems(items); dialog.setTextValue(text); dialog.setComboBoxEditable(editable); + dialog.setInputMethodHints(inputMethodHints); int ret = dialog.exec(); if (ok) @@ -1330,6 +1347,17 @@ QString QInputDialog::getItem(QWidget *parent, const QString &title, const QStri } /*! + \internal +*/ +// ### Qt 5: Use only the version above. +QString QInputDialog::getItem(QWidget *parent, const QString &title, const QString &label, + const QStringList &items, int current, bool editable, bool *ok, + Qt::WindowFlags flags) +{ + return getItem(parent, title, label, items, current, editable, ok, flags, Qt::ImhNone); +} + +/*! \obsolete Use getInt() instead. diff --git a/src/gui/dialogs/qinputdialog.h b/src/gui/dialogs/qinputdialog.h index 02868c1..25e27b0 100644 --- a/src/gui/dialogs/qinputdialog.h +++ b/src/gui/dialogs/qinputdialog.h @@ -167,18 +167,37 @@ public: void setVisible(bool visible); +#ifdef Q_QDOC + static QString getText(QWidget *parent, const QString &title, const QString &label, + QLineEdit::EchoMode echo = QLineEdit::Normal, + const QString &text = QString(), bool *ok = 0, Qt::WindowFlags flags = 0, + Qt::InputMethodHints inputMethodHints = Qt::ImhNone); + static QString getItem(QWidget *parent, const QString &title, const QString &label, + const QStringList &items, int current = 0, bool editable = true, + bool *ok = 0, Qt::WindowFlags flags = 0, + Qt::InputMethodHints inputMethodHints = Qt::ImhNone); +#else static QString getText(QWidget *parent, const QString &title, const QString &label, QLineEdit::EchoMode echo = QLineEdit::Normal, const QString &text = QString(), bool *ok = 0, Qt::WindowFlags flags = 0); + static QString getItem(QWidget *parent, const QString &title, const QString &label, + const QStringList &items, int current = 0, bool editable = true, + bool *ok = 0, Qt::WindowFlags flags = 0); + static QString getText(QWidget *parent, const QString &title, const QString &label, + QLineEdit::EchoMode echo, + const QString &text, bool *ok, Qt::WindowFlags flags, + Qt::InputMethodHints inputMethodHints); + static QString getItem(QWidget *parent, const QString &title, const QString &label, + const QStringList &items, int current, bool editable, + bool *ok, Qt::WindowFlags flags, + Qt::InputMethodHints inputMethodHints); +#endif static int getInt(QWidget *parent, const QString &title, const QString &label, int value = 0, int minValue = -2147483647, int maxValue = 2147483647, int step = 1, bool *ok = 0, Qt::WindowFlags flags = 0); static double getDouble(QWidget *parent, const QString &title, const QString &label, double value = 0, double minValue = -2147483647, double maxValue = 2147483647, int decimals = 1, bool *ok = 0, Qt::WindowFlags flags = 0); - static QString getItem(QWidget *parent, const QString &title, const QString &label, - const QStringList &items, int current = 0, bool editable = true, - bool *ok = 0, Qt::WindowFlags flags = 0); // obsolete static int getInteger(QWidget *parent, const QString &title, const QString &label, int value = 0, diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp index fe25b0f..f849996 100644 --- a/src/gui/dialogs/qmessagebox.cpp +++ b/src/gui/dialogs/qmessagebox.cpp @@ -412,7 +412,7 @@ void QMessageBoxPrivate::updateSize() void QMessageBoxPrivate::hideSpecial() { Q_Q(QMessageBox); - QList<QPushButton*> list = qFindChildren<QPushButton*>(q); + QList<QPushButton*> list = q->findChildren<QPushButton*>(); for (int i=0; i<list.size(); ++i) { QPushButton *pb = list.at(i); QString text = pb->text(); @@ -1266,7 +1266,7 @@ bool QMessageBox::event(QEvent *e) (e->type() == QEvent::OkRequest) ? QApplication::translate("QMessageBox", "OK") : QApplication::translate("QMessageBox", "Help"); - QList<QPushButton*> list = qFindChildren<QPushButton*>(this); + QList<QPushButton*> list = findChildren<QPushButton*>(); for (int i=0; i<list.size(); ++i) { QPushButton *pb = list.at(i); if (pb->text() == bName) { @@ -1513,7 +1513,7 @@ static QMessageBox::StandardButton showNewMessageBox(QWidget *parent, int(defaultButton), 0); QMessageBox msgBox(icon, title, text, QMessageBox::NoButton, parent); - QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox*>(&msgBox); + QDialogButtonBox *buttonBox = msgBox.findChild<QDialogButtonBox*>(); Q_ASSERT(buttonBox != 0); uint mask = QMessageBox::FirstButton; diff --git a/src/gui/dialogs/qnspanelproxy_mac.mm b/src/gui/dialogs/qnspanelproxy_mac.mm index 0bd5c63..0e8d64d 100644 --- a/src/gui/dialogs/qnspanelproxy_mac.mm +++ b/src/gui/dialogs/qnspanelproxy_mac.mm @@ -42,6 +42,7 @@ #include <qdialogbuttonbox.h> #if defined(Q_WS_MAC) #include <private/qt_mac_p.h> +#include <private/qcocoaintrospection_p.h> #import <AppKit/AppKit.h> #import <Foundation/Foundation.h> #import <objc/objc-class.h> @@ -137,46 +138,6 @@ QT_USE_NAMESPACE QT_BEGIN_NAMESPACE -void macStartIntercept(SEL originalSel, SEL fakeSel, Class baseClass, Class proxyClass) -{ -#ifndef QT_MAC_USE_COCOA - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) -#endif - { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - // The following code replaces the _implementation_ for the selector we want to hack - // (originalSel) with the implementation found in proxyClass. Then it creates - // a new 'backup' method inside baseClass containing the old, original, - // implementation (fakeSel). You can let the proxy implementation of originalSel - // call fakeSel if needed (similar approach to calling a super class implementation). - // fakeSel must also be implemented in proxyClass, as the signature is used - // as template for the method one we add into baseClass. - // NB: You will typically never create any instances of proxyClass; we use it - // only for stealing its contents and put it into baseClass. - Method originalMethod = class_getInstanceMethod(baseClass, originalSel); - Method newMethod = class_getInstanceMethod(proxyClass, originalSel); - Method fakeMethod = class_getInstanceMethod(proxyClass, fakeSel); - - IMP originalImp = method_setImplementation(originalMethod, method_getImplementation(newMethod)); - class_addMethod(baseClass, fakeSel, originalImp, method_getTypeEncoding(fakeMethod)); -#endif - } -} - -void macStopIntercept(SEL originalSel, SEL fakeSel, Class baseClass, Class /* proxyClass */) -{ -#ifndef QT_MAC_USE_COCOA - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) -#endif - { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - Method originalMethod = class_getInstanceMethod(baseClass, originalSel); - Method fakeMethodInBaseClass = class_getInstanceMethod(baseClass, fakeSel); - method_setImplementation(originalMethod, method_getImplementation(fakeMethodInBaseClass)); -#endif - } -} - /* Intercept the NSColorPanel constructor if the shared color panel doesn't exist yet. What's going on here is @@ -188,12 +149,18 @@ void macStopIntercept(SEL originalSel, SEL fakeSel, Class baseClass, Class /* pr */ void macStartInterceptNSPanelCtor() { - macStartIntercept(@selector(initWithContentRect:styleMask:backing:defer:), - @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:), - [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]); - macStartIntercept(@selector(initWithContentRect:styleMask:backing:defer:screen:), - @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:), - [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]); + qt_cocoa_change_implementation( + [NSPanel class], + @selector(initWithContentRect:styleMask:backing:defer:), + [QT_MANGLE_NAMESPACE(QNSPanelProxy) class], + @selector(initWithContentRect:styleMask:backing:defer:), + @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:)); + qt_cocoa_change_implementation( + [NSPanel class], + @selector(initWithContentRect:styleMask:backing:defer:screen:), + [QT_MANGLE_NAMESPACE(QNSPanelProxy) class], + @selector(initWithContentRect:styleMask:backing:defer:screen:), + @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:)); } /* @@ -201,12 +168,14 @@ void macStartInterceptNSPanelCtor() */ void macStopInterceptNSPanelCtor() { - macStopIntercept(@selector(initWithContentRect:styleMask:backing:defer:screen:), - @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:), - [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]); - macStopIntercept(@selector(initWithContentRect:styleMask:backing:defer:), - @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:), - [NSPanel class], [QT_MANGLE_NAMESPACE(QNSPanelProxy) class]); + qt_cocoa_change_back_implementation( + [NSPanel class], + @selector(initWithContentRect:styleMask:backing:defer:screen:), + @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:screen:)); + qt_cocoa_change_back_implementation( + [NSPanel class], + @selector(initWithContentRect:styleMask:backing:defer:), + @selector(qt_fakeInitWithContentRect:styleMask:backing:defer:)); } /* @@ -216,8 +185,12 @@ void macStopInterceptNSPanelCtor() void macStartInterceptWindowTitle(QWidget *window) { currentWindow = window; - macStartIntercept(@selector(setTitle:), @selector(qt_fakeSetTitle:), - [NSWindow class], [QT_MANGLE_NAMESPACE(QNSWindowProxy) class]); + qt_cocoa_change_implementation( + [NSWindow class], + @selector(setTitle:), + [QT_MANGLE_NAMESPACE(QNSWindowProxy) class], + @selector(setTitle:), + @selector(qt_fakeSetTitle:)); } /* @@ -226,8 +199,10 @@ void macStartInterceptWindowTitle(QWidget *window) void macStopInterceptWindowTitle() { currentWindow = 0; - macStopIntercept(@selector(setTitle:), @selector(qt_fakeSetTitle:), - [NSWindow class], [QT_MANGLE_NAMESPACE(QNSWindowProxy) class]); + qt_cocoa_change_back_implementation( + [NSWindow class], + @selector(setTitle:), + @selector(qt_fakeSetTitle:)); } /* diff --git a/src/gui/egl/egl.pri b/src/gui/egl/egl.pri index c6c020d..8e8664c 100644 --- a/src/gui/egl/egl.pri +++ b/src/gui/egl/egl.pri @@ -6,9 +6,21 @@ contains(QT_CONFIG, egl): { egl/qeglcontext_p.h \ egl/qeglproperties_p.h - SOURCES += \ - egl/qegl.cpp \ - egl/qeglproperties.cpp + SOURCES += \ + egl/qegl.cpp \ + egl/qeglproperties.cpp + unix { + !isEmpty(QMAKE_INCDIR_EGL){ + INCLUDEPATH += $$QMAKE_INCDIR_EGL + } + !isEmpty(QMAKE_LIBDIR_EGL){ + for(p, QMAKE_LIBDIR_EGL) { + exists($$p):LIBS += -L$$p + } + } + + !isEmpty(QMAKE_LIBS_EGL): LIBS += $$QMAKE_LIBS_EGL + } wince*: SOURCES += egl/qegl_wince.cpp @@ -16,10 +28,14 @@ contains(QT_CONFIG, egl): { embedded { SOURCES += egl/qegl_qws.cpp } else { - symbian { - SOURCES += egl/qegl_symbian.cpp + qpa { + SOURCES += egl/qegl_qpa.cpp } else { - SOURCES += egl/qegl_x11.cpp + symbian { + SOURCES += egl/qegl_symbian.cpp + } else { + SOURCES += egl/qegl_x11.cpp + } } } } diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index af3b79a..2a82427 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -394,7 +394,7 @@ bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties } } if (ctx == EGL_NO_CONTEXT) { - ctx = eglCreateContext(display(), cfg, 0, contextProps.properties()); + ctx = eglCreateContext(display(), cfg, EGL_NO_CONTEXT, contextProps.properties()); if (ctx == EGL_NO_CONTEXT) { qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << QEgl::errorString(); return false; diff --git a/src/gui/egl/qegl_qpa.cpp b/src/gui/egl/qegl_qpa.cpp new file mode 100644 index 0000000..10caf46 --- /dev/null +++ b/src/gui/egl/qegl_qpa.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** 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 QtGui 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 <QtGui/qpaintdevice.h> +#include <QtGui/qpixmap.h> +#include <QtGui/qwidget.h> +#include "qeglcontext_p.h" + +#if !defined(QT_NO_EGL) + +#include <QtGui/private/qgraphicssystem_p.h> +#include <QtGui/private/qapplication_p.h> +#include <QtGui/qdesktopwidget.h> + +QT_BEGIN_NAMESPACE + +EGLNativeDisplayType QEgl::nativeDisplay() +{ + return EGLNativeDisplayType(EGL_DEFAULT_DISPLAY); +} + +EGLNativeWindowType QEgl::nativeWindow(QWidget* widget) +{ + return (EGLNativeWindowType)(widget->winId()); +} + +EGLNativePixmapType QEgl::nativePixmap(QPixmap* pixmap) +{ + Q_UNUSED(pixmap); + return 0; +} + +//EGLDisplay QEglContext::display() +//{ +// return eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY)); +//} + +static QPlatformScreen *screenForDevice(QPaintDevice *device) +{ + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + + QList<QPlatformScreen *> screens = pi->screens(); + + int screenNumber; + if (device && device->devType() == QInternal::Widget) + screenNumber = qApp->desktop()->screenNumber(static_cast<QWidget *>(device)); + else + screenNumber = 0; + if (screenNumber < 0 || screenNumber >= screens.size()) + return 0; + return screens[screenNumber]; +} + +// Set pixel format and other properties based on a paint device. +void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) +{ + if (!dev) + return; + + // Find the QGLScreen for this paint device. + QPlatformScreen *screen = screenForDevice(dev); + if (!screen) + return; + int devType = dev->devType(); + if (devType == QInternal::Image) + setPixelFormat(static_cast<QImage *>(dev)->format()); + else + setPixelFormat(screen->format()); +} + +QT_END_NAMESPACE + +#endif // !QT_NO_EGL diff --git a/src/gui/embedded/qkbd_defaultmap_qws_p.h b/src/gui/embedded/qkbd_defaultmap_qws_p.h index 16c3459..703dfcd 100644 --- a/src/gui/embedded/qkbd_defaultmap_qws_p.h +++ b/src/gui/embedded/qkbd_defaultmap_qws_p.h @@ -642,7 +642,14 @@ const QWSKeyboard::Mapping QWSKbPrivate::s_keymap_default[] = { { 111, 0xffff, 0x01000007, 0x00, 0x00, 0x0000 }, { 111, 0xffff, 0x01000000, 0x06, 0x08, 0x0200 }, { 111, 0xffff, 0x01000000, 0x0c, 0x08, 0x0200 }, + { 113, 0xffff, 0x01000071, 0x00, 0x00, 0x0000 }, + { 114, 0xffff, 0x01000070, 0x00, 0x00, 0x0000 }, + { 115, 0xffff, 0x01000072, 0x00, 0x00, 0x0000 }, + { 116, 0xffff, 0x0100010b, 0x00, 0x00, 0x0000 }, { 119, 0xffff, 0x01000008, 0x00, 0x00, 0x0000 }, + { 138, 0xffff, 0x01000058, 0x00, 0x00, 0x0000 }, + { 139, 0xffff, 0x01000055, 0x00, 0x00, 0x0000 }, + }; const QWSKeyboard::Composing QWSKbPrivate::s_keycompose_default[] = { diff --git a/src/gui/embedded/qkbd_qws.cpp b/src/gui/embedded/qkbd_qws.cpp index a6c8002..1999ddb 100644 --- a/src/gui/embedded/qkbd_qws.cpp +++ b/src/gui/embedded/qkbd_qws.cpp @@ -48,8 +48,16 @@ #include <QDataStream> #include <QStringList> +#ifdef Q_WS_QWS #include "qwindowsystem_qws.h" #include "qscreen_qws.h" +#endif + +#ifdef Q_WS_QPA +#include <QWindowSystemInterface> +#include <QKeyEvent> +#endif + #include "qtimer.h" #include <stdlib.h> @@ -352,7 +360,15 @@ QWSKeyboardHandler::~QWSKeyboardHandler() void QWSKeyboardHandler::processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers, bool isPress, bool autoRepeat) { +#if defined(Q_WS_QWS) qwsServer->processKeyEvent(unicode, keycode, modifiers, isPress, autoRepeat); +#elif defined(Q_WS_QPA) + QEvent::Type type = isPress ? QEvent::KeyPress : QEvent::KeyRelease; + QString str; + if (unicode != 0xffff) + str = QString(unicode); + QWindowSystemInterface::handleKeyEvent(0, type, keycode, modifiers, str); +#endif } /*! @@ -375,6 +391,7 @@ void QWSKeyboardHandler::processKeyEvent(int unicode, int keycode, Qt::KeyboardM */ int QWSKeyboardHandler::transformDirKey(int key) { +#ifdef Q_WS_QWS static int dir_keyrot = -1; if (dir_keyrot < 0) { // get the rotation @@ -387,6 +404,9 @@ int QWSKeyboardHandler::transformDirKey(int key) } int xf = qt_screen->transformOrientation() + dir_keyrot; return (key-Qt::Key_Left+xf)%4+Qt::Key_Left; +#else + return 0; +#endif } /*! @@ -454,7 +474,7 @@ void QWSKeyboardHandler::endAutoRepeat() Maps \a keycode according to a keymap and sends that key event to the \l{Qt for Embedded Linux} server application. - + Please see the \l{Qt for Embedded Linux Character Input} and the \l {kmap2qmap} documentations for a description on how to create and use keymap files. diff --git a/src/gui/graphicsview/qgraphicsgridlayout.cpp b/src/gui/graphicsview/qgraphicsgridlayout.cpp index 3fc7f10..4104834 100644 --- a/src/gui/graphicsview/qgraphicsgridlayout.cpp +++ b/src/gui/graphicsview/qgraphicsgridlayout.cpp @@ -589,6 +589,18 @@ void QGraphicsGridLayout::removeAt(int index) } /*! + Removes the layout item \a item without destroying it. + Ownership of the item is transferred to the caller. + + \sa addItem() +*/ +void QGraphicsGridLayout::removeItem(QGraphicsLayoutItem *item) +{ + Q_D(QGraphicsGridLayout); + int index = d->engine.indexOf(item); + removeAt(index); +} +/*! \reimp */ void QGraphicsGridLayout::invalidate() diff --git a/src/gui/graphicsview/qgraphicsgridlayout.h b/src/gui/graphicsview/qgraphicsgridlayout.h index 6580a02..d10235c 100644 --- a/src/gui/graphicsview/qgraphicsgridlayout.h +++ b/src/gui/graphicsview/qgraphicsgridlayout.h @@ -109,11 +109,12 @@ public: int columnCount() const; QGraphicsLayoutItem *itemAt(int row, int column) const; - + // inherited from QGraphicsLayout int count() const; QGraphicsLayoutItem *itemAt(int index) const; void removeAt(int index); + void removeItem(QGraphicsLayoutItem *item); void invalidate(); diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 7ab49cb..e9a2f9f 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1703,12 +1703,12 @@ void QGraphicsItem::setParentItem(QGraphicsItem *newParent) return; const QVariant newParentVariant(itemChange(QGraphicsItem::ItemParentChange, - qVariantFromValue<QGraphicsItem *>(newParent))); - newParent = qVariantValue<QGraphicsItem *>(newParentVariant); + QVariant::fromValue<QGraphicsItem *>(newParent))); + newParent = qvariant_cast<QGraphicsItem *>(newParentVariant); if (newParent == d_ptr->parent) return; - const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(this)); + const QVariant thisPointerVariant(QVariant::fromValue<QGraphicsItem *>(this)); d_ptr->setParentItemHelper(newParent, &newParentVariant, &thisPointerVariant); } @@ -2132,7 +2132,7 @@ void QGraphicsItem::setToolTip(const QString &toolTip) */ QCursor QGraphicsItem::cursor() const { - return qVariantValue<QCursor>(d_ptr->extra(QGraphicsItemPrivate::ExtraCursor)); + return qvariant_cast<QCursor>(d_ptr->extra(QGraphicsItemPrivate::ExtraCursor)); } /*! @@ -2152,8 +2152,8 @@ QCursor QGraphicsItem::cursor() const */ void QGraphicsItem::setCursor(const QCursor &cursor) { - const QVariant cursorVariant(itemChange(ItemCursorChange, qVariantFromValue<QCursor>(cursor))); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qVariantValue<QCursor>(cursorVariant)); + const QVariant cursorVariant(itemChange(ItemCursorChange, QVariant::fromValue<QCursor>(cursor))); + d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qvariant_cast<QCursor>(cursorVariant)); d_ptr->hasCursor = 1; if (d_ptr->scene) { d_ptr->scene->d_func()->allItemsUseDefaultCursor = false; @@ -2279,7 +2279,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo // Schedule redrawing if (update) { - QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData)); + QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData)); if (c) c->purge(); if (scene) { @@ -3717,7 +3717,7 @@ void QGraphicsItem::setPos(const QPointF &pos) } // Notify the item that the position is changing. - const QVariant newPosVariant(itemChange(ItemPositionChange, qVariantFromValue<QPointF>(pos))); + const QVariant newPosVariant(itemChange(ItemPositionChange, QVariant::fromValue<QPointF>(pos))); QPointF newPos = newPosVariant.toPointF(); if (newPos == d_ptr->pos) return; @@ -4071,7 +4071,7 @@ void QGraphicsItem::setTransformOriginPoint(const QPointF &origin) if (d_ptr->flags & ItemSendsGeometryChanges) { // Notify the item that the origin point is changing. const QVariant newOriginVariant(itemChange(ItemTransformOriginPointChange, - qVariantFromValue<QPointF>(origin))); + QVariant::fromValue<QPointF>(origin))); newOrigin = newOriginVariant.toPointF(); } @@ -4090,7 +4090,7 @@ void QGraphicsItem::setTransformOriginPoint(const QPointF &origin) // Send post-notification. if (d_ptr->flags & ItemSendsGeometryChanges) - itemChange(ItemTransformOriginPointHasChanged, qVariantFromValue<QPointF>(newOrigin)); + itemChange(ItemTransformOriginPointHasChanged, QVariant::fromValue<QPointF>(newOrigin)); } /*! @@ -4352,8 +4352,8 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) } // Notify the item that the transformation matrix is changing. - const QVariant newMatrixVariant = qVariantFromValue<QMatrix>(newTransform.toAffine()); - newTransform = QTransform(qVariantValue<QMatrix>(itemChange(ItemMatrixChange, newMatrixVariant))); + const QVariant newMatrixVariant = QVariant::fromValue<QMatrix>(newTransform.toAffine()); + newTransform = QTransform(qvariant_cast<QMatrix>(itemChange(ItemMatrixChange, newMatrixVariant))); if (d_ptr->transformData->transform == newTransform) return; @@ -4361,7 +4361,7 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) d_ptr->setTransformHelper(newTransform); // Send post-notification. - itemChange(ItemTransformHasChanged, qVariantFromValue<QTransform>(newTransform)); + itemChange(ItemTransformHasChanged, QVariant::fromValue<QTransform>(newTransform)); } /*! @@ -4404,8 +4404,8 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) // Notify the item that the transformation matrix is changing. const QVariant newTransformVariant(itemChange(ItemTransformChange, - qVariantFromValue<QTransform>(newTransform))); - newTransform = qVariantValue<QTransform>(newTransformVariant); + QVariant::fromValue<QTransform>(newTransform))); + newTransform = qvariant_cast<QTransform>(newTransformVariant); if (d_ptr->transformData->transform == newTransform) return; @@ -5258,7 +5258,7 @@ QRegion QGraphicsItem::boundingRegion(const QTransform &itemToDeviceTransform) c qreal QGraphicsItem::boundingRegionGranularity() const { return d_ptr->hasBoundingRegionGranularity - ? qVariantValue<qreal>(d_ptr->extra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity)) + ? qvariant_cast<qreal>(d_ptr->extra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity)) : 0; } @@ -5294,7 +5294,7 @@ void QGraphicsItem::setBoundingRegionGranularity(qreal granularity) } d_ptr->hasBoundingRegionGranularity = 1; d_ptr->setExtra(QGraphicsItemPrivate::ExtraBoundingRegionGranularity, - qVariantFromValue<qreal>(granularity)); + QVariant::fromValue<qreal>(granularity)); } /*! @@ -5469,7 +5469,7 @@ void QGraphicsItemPrivate::removeChild(QGraphicsItem *child) */ QGraphicsItemCache *QGraphicsItemPrivate::maybeExtraItemCache() const { - return (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData)); + return (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData)); } /*! @@ -5477,11 +5477,11 @@ QGraphicsItemCache *QGraphicsItemPrivate::maybeExtraItemCache() const */ QGraphicsItemCache *QGraphicsItemPrivate::extraItemCache() const { - QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData)); + QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData)); if (!c) { QGraphicsItemPrivate *that = const_cast<QGraphicsItemPrivate *>(this); c = new QGraphicsItemCache; - that->setExtra(ExtraCacheData, qVariantFromValue<void *>(c)); + that->setExtra(ExtraCacheData, QVariant::fromValue<void *>(c)); } return c; } @@ -5491,7 +5491,7 @@ QGraphicsItemCache *QGraphicsItemPrivate::extraItemCache() const */ void QGraphicsItemPrivate::removeExtraItemCache() { - QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData)); + QGraphicsItemCache *c = (QGraphicsItemCache *)qvariant_cast<void *>(extra(ExtraCacheData)); if (c) { c->purge(); delete c; @@ -8110,6 +8110,8 @@ QPen QAbstractGraphicsShapeItem::pen() const void QAbstractGraphicsShapeItem::setPen(const QPen &pen) { Q_D(QAbstractGraphicsShapeItem); + if (d->pen == pen) + return; prepareGeometryChange(); d->pen = pen; d->boundingRect = QRectF(); @@ -8140,6 +8142,8 @@ QBrush QAbstractGraphicsShapeItem::brush() const void QAbstractGraphicsShapeItem::setBrush(const QBrush &brush) { Q_D(QAbstractGraphicsShapeItem); + if (d->brush == brush) + return; d->brush = brush; update(); } @@ -9270,6 +9274,8 @@ QPen QGraphicsLineItem::pen() const void QGraphicsLineItem::setPen(const QPen &pen) { Q_D(QGraphicsLineItem); + if (d->pen == pen) + return; prepareGeometryChange(); d->pen = pen; update(); diff --git a/src/gui/graphicsview/qgraphicsitemanimation.cpp b/src/gui/graphicsview/qgraphicsitemanimation.cpp index 9cb9a8d..9689616 100644 --- a/src/gui/graphicsview/qgraphicsitemanimation.cpp +++ b/src/gui/graphicsview/qgraphicsitemanimation.cpp @@ -49,20 +49,20 @@ The QGraphicsItemAnimation class animates a QGraphicsItem. You can schedule changes to the item's transformation matrix at - specified steps. The QGraphicsItemAnimation class has a - current step value. When this value changes the transformations - scheduled at that step are performed. The current step of the + specified steps. The QGraphicsItemAnimation class has a + current step value. When this value changes the transformations + scheduled at that step are performed. The current step of the animation is set with the \c setStep() function. QGraphicsItemAnimation will do a simple linear interpolation - between the nearest adjacent scheduled changes to calculate the + between the nearest adjacent scheduled changes to calculate the matrix. For instance, if you set the position of an item at values 0.0 and 1.0, the animation will show the item moving in a straight - line between these positions. The same is true for scaling and + line between these positions. The same is true for scaling and rotation. It is usual to use the class with a QTimeLine. The timeline's - \l{QTimeLine::}{valueChanged()} signal is then connected to the + \l{QTimeLine::}{valueChanged()} signal is then connected to the \c setStep() slot. For example, you can set up an item for rotation by calling \c setRotationAt() for different step values. The animations timeline is set with the setTimeLine() function. @@ -286,7 +286,7 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::posList() const QList<QPair<qreal, QPointF> > list; for (int i = 0; i < d->xPosition.size(); ++i) list << QPair<qreal, QPointF>(d->xPosition.at(i).step, QPointF(d->xPosition.at(i).value, d->yPosition.at(i).value)); - + return list; } @@ -343,7 +343,7 @@ QList<QPair<qreal, qreal> > QGraphicsItemAnimation::rotationList() const QList<QPair<qreal, qreal> > list; for (int i = 0; i < d->rotation.size(); ++i) list << QPair<qreal, qreal>(d->rotation.at(i).step, d->rotation.at(i).value); - + return list; } @@ -395,7 +395,7 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::translationList() const QList<QPair<qreal, QPointF> > list; for (int i = 0; i < d->xTranslation.size(); ++i) list << QPair<qreal, QPointF>(d->xTranslation.at(i).step, QPointF(d->xTranslation.at(i).value, d->yTranslation.at(i).value)); - + return list; } @@ -447,7 +447,7 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::scaleList() const QList<QPair<qreal, QPointF> > list; for (int i = 0; i < d->horizontalScale.size(); ++i) list << QPair<qreal, QPointF>(d->horizontalScale.at(i).step, QPointF(d->horizontalScale.at(i).value, d->verticalScale.at(i).value)); - + return list; } @@ -499,7 +499,7 @@ QList<QPair<qreal, QPointF> > QGraphicsItemAnimation::shearList() const QList<QPair<qreal, QPointF> > list; for (int i = 0; i < d->horizontalShear.size(); ++i) list << QPair<qreal, QPointF>(d->horizontalShear.at(i).step, QPointF(d->horizontalShear.at(i).value, d->verticalShear.at(i).value)); - + return list; } diff --git a/src/gui/graphicsview/qgraphicslayout.cpp b/src/gui/graphicsview/qgraphicslayout.cpp index 86b4589..91f386f 100644 --- a/src/gui/graphicsview/qgraphicslayout.cpp +++ b/src/gui/graphicsview/qgraphicslayout.cpp @@ -145,7 +145,7 @@ QT_BEGIN_NAMESPACE /*! Contructs a QGraphicsLayout object. - + \a parent is passed to QGraphicsLayoutItem's constructor and the QGraphicsLayoutItem's isLayout argument is set to \e true. @@ -259,7 +259,7 @@ void QGraphicsLayout::activate() return; d->activateRecursive(this); - + // we don't call activate on a sublayout, but somebody might. // Therefore, we walk to the parentitem of the toplevel layout. QGraphicsLayoutItem *parentItem = this; @@ -270,7 +270,7 @@ void QGraphicsLayout::activate() Q_ASSERT(!parentItem->isLayout()); setGeometry(parentItem->contentsRect()); // relayout children - + // ### bug, should be parentItem ? parentLayoutItem()->updateGeometry(); // bubble up; will set activated to false // ### too many resizes? maybe we should walk up the chain to the @@ -307,7 +307,7 @@ void QGraphicsLayout::invalidate() // does not call the base implementation? In addition, updateGeometry() // does more than we need. layoutItem->d_func()->sizeHintCacheDirty = true; - layoutItem = layoutItem->parentLayoutItem(); + layoutItem = layoutItem->parentLayoutItem(); } if (layoutItem) layoutItem->d_func()->sizeHintCacheDirty = true; @@ -347,7 +347,7 @@ void QGraphicsLayout::updateGeometry() widget. QGraphicsLayout uses this event handler to listen for layout related events such as geometry changes, layout changes or layout direction changes. - + \a e is a pointer to the event. You can reimplement this event handler to track similar events for your diff --git a/src/gui/graphicsview/qgraphicslayout_p.cpp b/src/gui/graphicsview/qgraphicslayout_p.cpp index 88652ec..163fc65 100644 --- a/src/gui/graphicsview/qgraphicslayout_p.cpp +++ b/src/gui/graphicsview/qgraphicslayout_p.cpp @@ -136,13 +136,13 @@ static bool removeLayoutItemFromLayout(QGraphicsLayout *lay, QGraphicsLayoutItem /*! \internal - This function is called from subclasses to add a layout item \a layoutItem + This function is called from subclasses to add a layout item \a layoutItem to a layout. It takes care of automatically reparenting graphics items, if needed. If \a layoutItem is a is already in a layout, it will remove it from that layout. - + */ void QGraphicsLayoutPrivate::addChildLayoutItem(QGraphicsLayoutItem *layoutItem) { @@ -150,14 +150,14 @@ void QGraphicsLayoutPrivate::addChildLayoutItem(QGraphicsLayoutItem *layoutItem) if (QGraphicsLayoutItem *maybeLayout = layoutItem->parentLayoutItem()) { if (maybeLayout->isLayout()) removeLayoutItemFromLayout(static_cast<QGraphicsLayout*>(maybeLayout), layoutItem); - } + } layoutItem->setParentLayoutItem(q); if (layoutItem->isLayout()) { if (QGraphicsItem *parItem = parentItem()) { static_cast<QGraphicsLayout*>(layoutItem)->d_func()->reparentChildItems(parItem); } } else { - if (QGraphicsItem *item = layoutItem->graphicsItem()) { + if (QGraphicsItem *item = layoutItem->graphicsItem()) { QGraphicsItem *newParent = parentItem(); QGraphicsItem *oldParent = item->parentItem(); if (oldParent == newParent || !newParent) @@ -182,7 +182,7 @@ void QGraphicsLayoutPrivate::activateRecursive(QGraphicsLayoutItem *item) QGraphicsLayout *layout = static_cast<QGraphicsLayout *>(item); if (layout->d_func()->activated) layout->invalidate(); - + for (int i = layout->count() - 1; i >= 0; --i) { QGraphicsLayoutItem *childItem = layout->itemAt(i); if (childItem) @@ -194,5 +194,5 @@ void QGraphicsLayoutPrivate::activateRecursive(QGraphicsLayoutItem *item) QT_END_NAMESPACE - + #endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicslayout_p.h b/src/gui/graphicsview/qgraphicslayout_p.h index 3083555..5c8e706 100644 --- a/src/gui/graphicsview/qgraphicslayout_p.h +++ b/src/gui/graphicsview/qgraphicslayout_p.h @@ -84,7 +84,7 @@ class QLayoutStyleInfo public: inline QLayoutStyleInfo() { invalidate(); } inline QLayoutStyleInfo(QStyle *style, QWidget *widget) - : m_valid(true), m_style(style), m_widget(widget) + : m_valid(true), m_style(style), m_widget(widget) { Q_ASSERT(style); if (widget) //### @@ -112,7 +112,7 @@ public: return m_defaultSpacing[o - 1]; } - inline qreal perItemSpacing(QSizePolicy::ControlType control1, + inline qreal perItemSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation) const { @@ -132,7 +132,7 @@ class Q_AUTOTEST_EXPORT QGraphicsLayoutPrivate : public QGraphicsLayoutItemPriva Q_DECLARE_PUBLIC(QGraphicsLayout) public: - QGraphicsLayoutPrivate() : QGraphicsLayoutItemPrivate(0, true), left(-1.0), top(-1.0), right(-1.0), bottom(-1.0), + QGraphicsLayoutPrivate() : QGraphicsLayoutItemPrivate(0, true), left(-1.0), top(-1.0), right(-1.0), bottom(-1.0), activated(true) { } void reparentChildItems(QGraphicsItem *newParent); @@ -148,7 +148,7 @@ public: QT_END_NAMESPACE - + #endif //QT_NO_GRAPHICSVIEW #endif diff --git a/src/gui/graphicsview/qgraphicslayoutitem.cpp b/src/gui/graphicsview/qgraphicslayoutitem.cpp index e43f7fa..fab1bbb 100644 --- a/src/gui/graphicsview/qgraphicslayoutitem.cpp +++ b/src/gui/graphicsview/qgraphicslayoutitem.cpp @@ -283,10 +283,6 @@ bool QGraphicsLayoutItemPrivate::hasHeightForWidth() const bool QGraphicsLayoutItemPrivate::hasWidthForHeight() const { - // enable this code when we add QSizePolicy::hasWidthForHeight() (For 4.8) -#if 1 - return false; -#else Q_Q(const QGraphicsLayoutItem); if (isLayout) { const QGraphicsLayout *l = static_cast<const QGraphicsLayout *>(q); @@ -303,7 +299,6 @@ bool QGraphicsLayoutItemPrivate::hasWidthForHeight() const } } return q->sizePolicy().hasWidthForHeight(); -#endif } /*! @@ -695,7 +690,7 @@ void QGraphicsLayoutItem::setMaximumHeight(qreal height) is equivalent to the item's position in parent coordinates). You must reimplement this function in a subclass of QGraphicsLayoutItem to - receive geometry updates. The layout will call this function when it does a + receive geometry updates. The layout will call this function when it does a rearrangement. If \a rect is outside of the bounds of minimumSize and maximumSize, it diff --git a/src/gui/graphicsview/qgraphicslayoutitem.h b/src/gui/graphicsview/qgraphicslayoutitem.h index f707c62..cb894a4 100644 --- a/src/gui/graphicsview/qgraphicslayoutitem.h +++ b/src/gui/graphicsview/qgraphicslayoutitem.h @@ -118,7 +118,7 @@ protected: private: QSizeF *effectiveSizeHints(const QSizeF &constraint) const; Q_DECLARE_PRIVATE(QGraphicsLayoutItem) - + friend class QGraphicsLayout; }; diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp index 320395e..ce63659 100644 --- a/src/gui/graphicsview/qgraphicsproxywidget.cpp +++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp @@ -266,8 +266,8 @@ void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneMouseEvent } if (!lastWidgetUnderMouse) { - QApplicationPrivate::dispatchEnterLeave(embeddedMouseGrabber ? embeddedMouseGrabber : widget, 0); - lastWidgetUnderMouse = widget; + QApplicationPrivate::dispatchEnterLeave(embeddedMouseGrabber ? embeddedMouseGrabber : receiver, 0); + lastWidgetUnderMouse = receiver; } // Map event position from us to the receiver diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index a0015dc..981fbbc 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -2544,8 +2544,8 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Notify the item that its scene is changing, and allow the item to // react. const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, - qVariantFromValue<QGraphicsScene *>(this))); - QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant); + QVariant::fromValue<QGraphicsScene *>(this))); + QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant); if (targetScene != this) { if (targetScene && item->d_ptr->scene != targetScene) targetScene->addItem(item); @@ -2956,8 +2956,8 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) // Notify the item that it's scene is changing to 0, allowing the item to // react. const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, - qVariantFromValue<QGraphicsScene *>(0))); - QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant); + QVariant::fromValue<QGraphicsScene *>(0))); + QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant); if (targetScene != 0 && targetScene != this) { targetScene->addItem(item); return; @@ -3461,7 +3461,8 @@ bool QGraphicsScene::event(QEvent *event) break; } case QEvent::Leave: - d->leaveScene(); + // hackieshly unpacking the viewport pointer from the leave event. + d->leaveScene(reinterpret_cast<QWidget *>(event->d)); break; case QEvent::GraphicsSceneHelp: helpEvent(static_cast<QGraphicsSceneHelpEvent *>(event)); @@ -3933,20 +3934,19 @@ bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEv Handles all actions necessary to clean up the scene when the mouse leaves the view. */ -void QGraphicsScenePrivate::leaveScene() +void QGraphicsScenePrivate::leaveScene(QWidget *viewport) { - Q_Q(QGraphicsScene); #ifndef QT_NO_TOOLTIP QToolTip::hideText(); #endif + QGraphicsView *view = qobject_cast<QGraphicsView *>(viewport->parent()); // Send HoverLeave events to all existing hover items, topmost first. - QGraphicsView *senderWidget = qobject_cast<QGraphicsView *>(q->sender()); QGraphicsSceneHoverEvent hoverEvent; - hoverEvent.setWidget(senderWidget); + hoverEvent.setWidget(viewport); - if (senderWidget) { + if (view) { QPoint cursorPos = QCursor::pos(); - hoverEvent.setScenePos(senderWidget->mapToScene(senderWidget->mapFromGlobal(cursorPos))); + hoverEvent.setScenePos(view->mapToScene(viewport->mapFromGlobal(cursorPos))); hoverEvent.setLastScenePos(hoverEvent.scenePos()); hoverEvent.setScreenPos(cursorPos); hoverEvent.setLastScreenPos(hoverEvent.screenPos()); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index f28dfe9..2818fb2 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -201,7 +201,7 @@ public: bool dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent); bool itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const; - void leaveScene(); + void leaveScene(QWidget *viewport); void cloneDragDropEvent(QGraphicsSceneDragDropEvent *dest, QGraphicsSceneDragDropEvent *source); diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index a566c8e..0d39bb5 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2790,6 +2790,9 @@ bool QGraphicsView::viewportEvent(QEvent *event) d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.first()); } d->useLastMouseEvent = false; + // a hack to pass a viewport pointer to the scene inside the leave event + Q_ASSERT(event->d == 0); + event->d = reinterpret_cast<QEventPrivate *>(viewport()); QApplication::sendEvent(d->scene, event); break; #ifndef QT_NO_TOOLTIP @@ -3710,7 +3713,7 @@ void QGraphicsView::drawForeground(QPainter *painter, const QRectF &rect) } /*! - \obsolete + \obsolete Draws the items \a items in the scene using \a painter, after the background and before the foreground are drawn. \a numItems is the number diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index 7bd9ecb..38c3bca 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -62,6 +62,7 @@ #include "qgraphicssceneevent.h" #include <QtGui/qstyleoption.h> #include <private/qabstractscrollarea_p.h> +#include <private/qapplication_p.h> QT_BEGIN_NAMESPACE @@ -180,21 +181,24 @@ public: inline void dispatchPendingUpdateRequests() { -#ifndef Q_WS_MAC - // QWidget::update() works slightly different on the Mac; it's not part of - // our backing store so it needs special threatment. - if (qt_widget_private(viewport)->paintOnScreen()) - QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest); - else - QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest); -#else - // At this point either HIViewSetNeedsDisplay (Carbon) or setNeedsDisplay: YES (Cocoa) - // is called, which means there's a pending update request. We want to dispatch it - // now because otherwise graphics view updates would require two - // round-trips in the event loop before the item is painted. - extern void qt_mac_dispatchPendingUpdateRequests(QWidget *); - qt_mac_dispatchPendingUpdateRequests(viewport->window()); -#endif +#ifdef Q_WS_MAC + // QWidget::update() works slightly different on the Mac without the raster engine; + // it's not part of our backing store so it needs special threatment. + if (QApplicationPrivate::graphics_system_name != QLatin1String("raster")) { + // At this point either HIViewSetNeedsDisplay (Carbon) or setNeedsDisplay: YES (Cocoa) + // is called, which means there's a pending update request. We want to dispatch it + // now because otherwise graphics view updates would require two + // round-trips in the event loop before the item is painted. + extern void qt_mac_dispatchPendingUpdateRequests(QWidget *); + qt_mac_dispatchPendingUpdateRequests(viewport->window()); + } else +#endif // !Q_WS_MAC + { + if (qt_widget_private(viewport)->paintOnScreen()) + QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest); + else + QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest); + } } void setUpdateClip(QGraphicsItem *); diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp index 3466733..f99749c 100644 --- a/src/gui/graphicsview/qgraphicswidget_p.cpp +++ b/src/gui/graphicsview/qgraphicswidget_p.cpp @@ -46,6 +46,7 @@ #include <QtCore/qdebug.h> #include <QtCore/qnumeric.h> #include "qgraphicswidget_p.h" +#include "qgraphicslayoutitem_p.h" #include "qgraphicslayout.h" #include "qgraphicsscene_p.h" #include <QtGui/qapplication.h> @@ -415,8 +416,7 @@ static qreal minimumHeightForWidth(qreal width, qreal minh, qreal maxh, bool heightForWidth = true) { qreal minimumHeightForWidth = -1; - const QSizePolicy sp = widget->layout() ? widget->layout()->sizePolicy() : widget->sizePolicy(); - const bool hasHFW = sp.hasHeightForWidth(); + const bool hasHFW = QGraphicsLayoutItemPrivate::get(widget)->hasHeightForWidth(); if (hasHFW == heightForWidth) { minimumHeightForWidth = hasHFW ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(width, -1)).height() @@ -505,21 +505,31 @@ static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry, qreal width = qBound(min.width(), proposedRect.width(), max.width()); qreal height = qBound(min.height(), proposedRect.height(), max.height()); - QSizePolicy sp = widget->sizePolicy(); - if (const QGraphicsLayout *l = widget->layout()) { - sp = l->sizePolicy(); - } - const bool hasHFW = sp.hasHeightForWidth(); // || sp.hasWidthForHeight(); + const bool hasHFW = QGraphicsLayoutItemPrivate::get(widget)->hasHeightForWidth(); + const bool hasWFH = QGraphicsLayoutItemPrivate::get(widget)->hasWidthForHeight(); - const bool widthChanged = proposedRect.width() < widget->size().width(); - const bool heightChanged = proposedRect.height() < widget->size().height(); + const bool widthChanged = proposedRect.width() != widget->size().width(); + const bool heightChanged = proposedRect.height() != widget->size().height(); - if (hasHFW) { + if (hasHFW || hasWFH) { if (widthChanged || heightChanged) { - const qreal minh = min.height(); - const qreal maxh = max.height(); - const qreal proposedHFW = minimumHeightForWidth(width, minh, maxh, widget); - if (proposedHFW > proposedRect.height()) { + qreal minExtent; + qreal maxExtent; + qreal constraint; + qreal proposed; + if (hasHFW) { + minExtent = min.height(); + maxExtent = max.height(); + constraint = width; + proposed = proposedRect.height(); + } else { + // width for height + minExtent = min.width(); + maxExtent = max.width(); + constraint = height; + proposed = proposedRect.width(); + } + if (minimumHeightForWidth(constraint, minExtent, maxExtent, widget, hasHFW) > proposed) { QSizeF effectiveSize = closestAcceptableSize(QSizeF(width, height), widget); width = effectiveSize.width(); height = effectiveSize.height(); diff --git a/src/gui/graphicsview/qgridlayoutengine.cpp b/src/gui/graphicsview/qgridlayoutengine.cpp index e486b4d..7f8d574 100644 --- a/src/gui/graphicsview/qgridlayoutengine.cpp +++ b/src/gui/graphicsview/qgridlayoutengine.cpp @@ -803,6 +803,15 @@ QGridLayoutItem *QGridLayoutEngine::itemAt(int index) const return q_items.at(index); } +int QGridLayoutEngine::indexOf(QGraphicsLayoutItem *item) const +{ + for (int i = 0; i < q_items.size(); ++i) { + if (item == q_items.at(i)->layoutItem()) + return i; + } + return -1; +} + int QGridLayoutEngine::effectiveFirstRow(Qt::Orientation orientation) const { ensureEffectiveFirstAndLastRows(); diff --git a/src/gui/graphicsview/qgridlayoutengine_p.h b/src/gui/graphicsview/qgridlayoutengine_p.h index 02c74b0..7c77b2a 100644 --- a/src/gui/graphicsview/qgridlayoutengine_p.h +++ b/src/gui/graphicsview/qgridlayoutengine_p.h @@ -338,6 +338,7 @@ public: // returns the number of items inserted, which may be less than (rowCount * columnCount) int itemCount() const; QGridLayoutItem *itemAt(int index) const; + int indexOf(QGraphicsLayoutItem *item) const; int effectiveFirstRow(Qt::Orientation orientation = Qt::Vertical) const; int effectiveLastRow(Qt::Orientation orientation = Qt::Vertical) const; diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 90b5de5..f7228dc 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -5,7 +5,7 @@ DEFINES += QT_BUILD_GUI_LIB QT_NO_USING_NAMESPACE win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x65000000 irix-cc*:QMAKE_CXXFLAGS += -no_prelink -ptused -!win32:!embedded:!mac:!symbian:CONFIG += x11 +!win32:!embedded:!qpa:!mac:!symbian:CONFIG += x11 unix:QMAKE_PKGCONFIG_REQUIRES = QtCore diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index f89706c..92ea397 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -23,6 +23,7 @@ HEADERS += \ image/qpictureformatplugin.h \ image/qpixmap.h \ image/qpixmap_raster_p.h \ + image/qpixmap_blitter_p.h \ image/qpixmapcache.h \ image/qpixmapcache_p.h \ image/qpixmapdata_p.h \ @@ -50,6 +51,7 @@ SOURCES += \ image/qiconengineplugin.cpp \ image/qmovie.cpp \ image/qpixmap_raster.cpp \ + image/qpixmap_blitter.cpp \ image/qnativeimage.cpp \ image/qimagepixmapcleanuphooks.cpp @@ -59,6 +61,9 @@ win32 { else:embedded { SOURCES += image/qpixmap_qws.cpp } +else:qpa { + SOURCES += image/qpixmap_qpa.cpp +} else:x11 { HEADERS += image/qpixmap_x11_p.h SOURCES += image/qpixmap_x11.cpp diff --git a/src/gui/image/qbitmap.cpp b/src/gui/image/qbitmap.cpp index 91622f3..9d90b3f 100644 --- a/src/gui/image/qbitmap.cpp +++ b/src/gui/image/qbitmap.cpp @@ -227,6 +227,14 @@ QBitmap::~QBitmap() } /*! + \fn void QBitmap::swap(QBitmap &other) + \since 4.8 + + Swaps bitmap \a other with this bitmap. This operation is very + fast and never fails. +*/ + +/*! Returns the bitmap as a QVariant. */ QBitmap::operator QVariant() const diff --git a/src/gui/image/qbitmap.h b/src/gui/image/qbitmap.h index 1bbe1cf..93be951 100644 --- a/src/gui/image/qbitmap.h +++ b/src/gui/image/qbitmap.h @@ -63,6 +63,7 @@ public: ~QBitmap(); QBitmap &operator=(const QPixmap &); + inline void swap(QBitmap &other) { QPixmap::swap(other); } // prevent QBitmap<->QPixmap swaps operator QVariant() const; inline void clear() { fill(Qt::color0); } diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index a2f429a..e54bb5f 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -613,6 +613,14 @@ QIcon &QIcon::operator=(const QIcon &other) } /*! + \fn void QIcon::swap(QIcon &other) + \since 4.8 + + Swaps icon \a other with this icon. This operation is very + fast and never fails. +*/ + +/*! Returns the icon as a QVariant. */ QIcon::operator QVariant() const diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h index faef07b..5091d03 100644 --- a/src/gui/image/qicon.h +++ b/src/gui/image/qicon.h @@ -71,6 +71,12 @@ public: explicit QIcon(QIconEngineV2 *engine); ~QIcon(); QIcon &operator=(const QIcon &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QIcon &operator=(QIcon &&other) + { qSwap(d, other.d); return *this; } +#endif + inline void swap(QIcon &other) { qSwap(d, other.d); } + operator QVariant() const; QPixmap pixmap(const QSize &size, Mode mode = Normal, State state = Off) const; diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 1157b93..d86021cb9 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -1329,6 +1329,14 @@ QImage &QImage::operator=(const QImage &image) } /*! + \fn void QImage::swap(QImage &other) + \since 4.8 + + Swaps image \a other with this image. This operation is very + fast and never fails. +*/ + +/*! \internal */ int QImage::devType() const @@ -2022,6 +2030,88 @@ void QImage::fill(uint pixel) 0, 0, d->width, d->height, d->bytes_per_line); } + +/*! + \fn void QImage::fill(Qt::GlobalColor color) + + \overload + + \since 4.8 + */ + +void QImage::fill(Qt::GlobalColor color) +{ + fill(QColor(color)); +} + + + +/*! + \fn void QImage::fill(Qt::GlobalColor color) + + \overload + + Fills the entire image with the given \a color. + + If the depth of the image is 1, the image will be filled with 1 if + \a color equals Qt::color0; it will otherwise be filled with 0. + + If the depth of the image is 8, the image will be filled with the + index corresponding the \a color in the color table if present; it + will otherwise be filled with 0.| + + \since 4.8 +*/ + +void QImage::fill(const QColor &color) +{ + if (!d) + return; + detach(); + + // In case we run out of memory + if (!d) + return; + + if (d->depth == 32) { + uint pixel = color.rgba(); + if (d->format == QImage::Format_ARGB32_Premultiplied) + pixel = PREMUL(pixel); + fill((uint) pixel); + + } else if (d->depth == 16 && d->format == QImage::Format_RGB16) { + qrgb565 p(color.rgba()); + fill((uint) p.rawValue()); + + } else if (d->depth == 1) { + if (color == Qt::color1) + fill((uint) 1); + else + fill((uint) 0); + + } else if (d->depth == 8) { + uint pixel = 0; + for (int i=0; i<d->colortable.size(); ++i) { + if (color.rgba() == d->colortable.at(i)) { + pixel = i; + break; + } + } + fill(pixel); + + } else { + QPainter p(this); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(rect(), color); + } + +} + + + + + + /*! Inverts all pixel values in the image. diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 896061f..c6a947e 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -140,6 +140,12 @@ public: ~QImage(); QImage &operator=(const QImage &); +#ifdef Q_COMPILER_RVALUE_REFS + inline QImage &operator=(QImage &&other) + { qSwap(d, other.d); return *this; } +#endif + inline void swap(QImage &other) { qSwap(d, other.d); } + bool isNull() const; int devType() const; @@ -210,6 +216,9 @@ public: void setColorTable(const QVector<QRgb> colors); void fill(uint pixel); + void fill(const QColor &color); + void fill(Qt::GlobalColor color); + bool hasAlphaChannel() const; void setAlphaChannel(const QImage &alphaChannel); @@ -326,6 +335,7 @@ private: QImageData *d; friend class QRasterPixmapData; + friend class QBlittablePixmapData; friend class QPixmapCacheEntry; friend Q_GUI_EXPORT qint64 qt_image_id(const QImage &image); friend const QVector<QRgb> *qt_image_colortable(const QImage &image); diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index ec56af2..03ee902 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -1092,7 +1092,7 @@ QColor QImageReader::backgroundColor() const if (!d->initHandler()) return QColor(); if (d->handler->supportsOption(QImageIOHandler::BackgroundColor)) - return qVariantValue<QColor>(d->handler->option(QImageIOHandler::BackgroundColor)); + return qvariant_cast<QColor>(d->handler->option(QImageIOHandler::BackgroundColor)); return QColor(); } diff --git a/src/gui/image/qmnghandler.cpp b/src/gui/image/qmnghandler.cpp index cf53af0..40f1b54 100644 --- a/src/gui/image/qmnghandler.cpp +++ b/src/gui/image/qmnghandler.cpp @@ -481,7 +481,7 @@ void QMngHandler::setOption(ImageOption option, const QVariant & value) { Q_D(QMngHandler); if (option == QImageIOHandler::BackgroundColor) - d->setBackgroundColor(qVariantValue<QColor>(value)); + d->setBackgroundColor(qvariant_cast<QColor>(value)); } /*! \reimp */ diff --git a/src/gui/image/qnativeimage.cpp b/src/gui/image/qnativeimage.cpp index 8446387..0f7872e 100644 --- a/src/gui/image/qnativeimage.cpp +++ b/src/gui/image/qnativeimage.cpp @@ -45,6 +45,9 @@ #include "private/qpaintengine_raster_p.h" +#include "private/qapplication_p.h" +#include "private/qgraphicssystem_p.h" + #if defined(Q_WS_X11) && !defined(QT_NO_MITSHM) #include <qx11info_x11.h> #include <sys/ipc.h> @@ -241,8 +244,19 @@ QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool /* : image(width, height, format) { - uint cgflags = kCGImageAlphaNoneSkipFirst; + switch (format) { + case QImage::Format_ARGB32: + cgflags = kCGImageAlphaFirst; + break; + case QImage::Format_ARGB32_Premultiplied: + case QImage::Format_ARGB8565_Premultiplied: + case QImage::Format_ARGB6666_Premultiplied: + case QImage::Format_ARGB8555_Premultiplied: + case QImage::Format_ARGB4444_Premultiplied: + cgflags = kCGImageAlphaPremultipliedFirst; + break; + } #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version cgflags |= kCGBitmapByteOrder32Host; @@ -284,7 +298,11 @@ QNativeImage::~QNativeImage() QImage::Format QNativeImage::systemFormat() { +#ifdef Q_WS_QPA + return QApplicationPrivate::platformIntegration()->screens().at(0)->format(); +#else return QImage::Format_RGB32; +#endif } #endif // platforms diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp index 48d2de3..fc81d23 100644 --- a/src/gui/image/qpicture.cpp +++ b/src/gui/image/qpicture.cpp @@ -1030,6 +1030,14 @@ QPicture& QPicture::operator=(const QPicture &p) } /*! + \fn void QPicture::swap(QPicture &other) + \since 4.8 + + Swaps picture \a other with this picture. This operation is very + fast and never fails. +*/ + +/*! \internal Constructs a QPicturePrivate diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h index 63ef42e..d24f23a 100644 --- a/src/gui/image/qpicture.h +++ b/src/gui/image/qpicture.h @@ -81,6 +81,11 @@ public: void setBoundingRect(const QRect &r); QPicture& operator=(const QPicture &p); +#ifdef Q_COMPILER_RVALUE_REFS + inline QPicture &operator=(QPicture &&other) + { qSwap(d_ptr, other.d_ptr); return *this; } +#endif + inline void swap(QPicture &other) { d_ptr.swap(other.d_ptr); } void detach(); bool isDetached() const; diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 64d8ed2..1b370c0 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -99,7 +99,7 @@ static bool qt_pixmap_thread_test() return false; } #ifndef Q_WS_WIN - if (qApp->thread() != QThread::currentThread()) { + if (!QApplication::testAttribute(Qt::AA_X11InitThreads) && qApp->thread() != QThread::currentThread()) { qWarning("QPixmap: It is not safe to use pixmaps outside the GUI thread"); return false; } @@ -440,6 +440,14 @@ QPixmap &QPixmap::operator=(const QPixmap &pixmap) } /*! + \fn void QPixmap::swap(QPixmap &other) + \since 4.8 + + Swaps pixmap \a other with this pixmap. This operation is very + fast and never fails. +*/ + +/*! Returns the pixmap as a QVariant. */ QPixmap::operator QVariant() const @@ -1175,7 +1183,12 @@ QPixmap QPixmap::grabWidget(QWidget * widget, const QRect &rect) \warning This function is X11 specific; using it is non-portable. + \warning Since 4.8, pixmaps do not have an X11 handle unless + created with \l {QPixmap::}{fromX11Pixmap()}, or if the native + graphics system is explicitly enabled. + \sa detach() + \sa QApplication::setGraphicsSystem() */ Qt::HANDLE QPixmap::handle() const @@ -1959,6 +1972,8 @@ int QPixmap::defaultDepth() return 32; #elif defined(Q_OS_SYMBIAN) return S60->screenDepth; +#elif defined(Q_WS_QPA) + return 32; //LITE: use graphicssystem (we should do that in general) #endif } diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h index 64ca8a3..15fe5fa 100644 --- a/src/gui/image/qpixmap.h +++ b/src/gui/image/qpixmap.h @@ -83,6 +83,12 @@ public: ~QPixmap(); QPixmap &operator=(const QPixmap &); +#ifdef Q_COMPILER_RVALUE_REFS + inline QPixmap &operator=(QPixmap &&other) + { qSwap(data, other.data); return *this; } +#endif + inline void swap(QPixmap &other) { qSwap(data, other.data); } + operator QVariant() const; bool isNull() const; // ### Qt 5: make inline diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp new file mode 100644 index 0000000..e8a7b89 --- /dev/null +++ b/src/gui/image/qpixmap_blitter.cpp @@ -0,0 +1,311 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qpixmap_blitter_p.h" + +#include <qpainter.h> +#include <qimage.h> + +#include <private/qapplication_p.h> +#include <private/qgraphicssystem_p.h> +#include <private/qblittable_p.h> + +#include <private/qdrawhelper_p.h> + +#ifndef QT_NO_BLITTABLE +QT_BEGIN_NAMESPACE + +static int global_ser_no = 0; + +QBlittablePixmapData::QBlittablePixmapData() + : QPixmapData(QPixmapData::PixmapType,BlitterClass), m_engine(0), m_blittable(0) +#ifdef QT_BLITTER_RASTEROVERLAY + ,m_rasterOverlay(0), m_unmergedCopy(0) +#endif //QT_BLITTER_RASTEROVERLAY +{ + setSerialNumber(++global_ser_no); +} + +QBlittablePixmapData::~QBlittablePixmapData() +{ + delete m_blittable; + delete m_engine; +#ifdef QT_BLITTER_RASTEROVERLAY + delete m_rasterOverlay; + delete m_unmergedCopy; +#endif //QT_BLITTER_RASTEROVERLAY +} + +QBlittable *QBlittablePixmapData::blittable() const +{ + if (!m_blittable) { + QBlittablePixmapData *that = const_cast<QBlittablePixmapData *>(this); + that->m_blittable = this->createBlittable(QSize(w,h)); + } + + return m_blittable; +} + +void QBlittablePixmapData::setBlittable(QBlittable *blittable) +{ + resize(blittable->size().width(),blittable->size().height()); + m_blittable = blittable; +} + +void QBlittablePixmapData::resize(int width, int height) +{ + + delete m_blittable; + m_blittable = 0; + delete m_engine; + m_engine = 0; +#ifdef Q_WS_QPA + d = QApplicationPrivate::platformIntegration()->screens().at(0)->depth(); +#endif + w = width; + h = height; + is_null = (w <= 0 || h <= 0); +} +Q_GUI_EXPORT extern int qt_defaultDpiX(); +Q_GUI_EXPORT extern int qt_defaultDpiY(); + +int QBlittablePixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const +{ + switch (metric) { + case QPaintDevice::PdmWidth: + return w; + case QPaintDevice::PdmHeight: + return h; + case QPaintDevice::PdmWidthMM: + return qRound(w * 25.4 / qt_defaultDpiX()); + case QPaintDevice::PdmHeightMM: + return qRound(h * 25.4 / qt_defaultDpiY()); + case QPaintDevice::PdmDepth: + return 32; + case QPaintDevice::PdmDpiX: // fall-through + case QPaintDevice::PdmPhysicalDpiX: + return qt_defaultDpiX(); + case QPaintDevice::PdmDpiY: // fall-through + case QPaintDevice::PdmPhysicalDpiY: + return qt_defaultDpiY(); + default: + qWarning("QRasterPixmapData::metric(): Unhandled metric type %d", metric); + break; + } + + return 0; +} + +void QBlittablePixmapData::fill(const QColor &color) +{ + //jlind: todo: change when blittables can support non opaque fillRects + if (color.alpha() == 255 && blittable()->capabilities() & QBlittable::SolidRectCapability) { + blittable()->unlock(); + blittable()->fillRect(QRectF(0,0,w,h),color); + }else { + uint pixel; + switch (blittable()->lock()->format()) { + case QImage::Format_ARGB32_Premultiplied: + pixel = PREMUL(color.rgba()); + break; + case QImage::Format_ARGB8565_Premultiplied: + pixel = qargb8565(color.rgba()).rawValue(); + break; + case QImage::Format_ARGB8555_Premultiplied: + pixel = qargb8555(color.rgba()).rawValue(); + break; + case QImage::Format_ARGB6666_Premultiplied: + pixel = qargb6666(color.rgba()).rawValue(); + break; + case QImage::Format_ARGB4444_Premultiplied: + pixel = qargb4444(color.rgba()).rawValue(); + break; + default: + pixel = color.rgba(); + break; + } + //so premultiplied formats are supported and ARGB32 and RGB32 + blittable()->lock()->fill(pixel); + } + +} + +QImage *QBlittablePixmapData::buffer() +{ + return blittable()->lock(); +} + +QImage QBlittablePixmapData::toImage() const +{ + return blittable()->lock()->copy(); +} + +bool QBlittablePixmapData::hasAlphaChannel() const +{ + return blittable()->lock()->hasAlphaChannel(); +} + +void QBlittablePixmapData::fromImage(const QImage &image, + Qt::ImageConversionFlags flags) +{ + resize(image.width(),image.height()); + markRasterOverlay(QRect(0,0,w,h)); + QImage *thisImg = buffer(); + + QImage correctFormatPic = image; + if (correctFormatPic.format() != thisImg->format()) + correctFormatPic = correctFormatPic.convertToFormat(thisImg->format(), flags); + + uchar *mem = thisImg->bits(); + const uchar *bits = correctFormatPic.bits(); + int bytesCopied = 0; + while (bytesCopied < correctFormatPic.byteCount()) { + memcpy(mem,bits,correctFormatPic.bytesPerLine()); + mem += thisImg->bytesPerLine(); + bits += correctFormatPic.bytesPerLine(); + bytesCopied+=correctFormatPic.bytesPerLine(); + } +} + +QPaintEngine *QBlittablePixmapData::paintEngine() const +{ + if (!m_engine) { + QBlittablePixmapData *that = const_cast<QBlittablePixmapData *>(this); + that->m_engine = new QBlitterPaintEngine(that); + } + return m_engine; +} + +#ifdef QT_BLITTER_RASTEROVERLAY + +static bool showRasterOverlay = !qgetenv("QT_BLITTER_RASTEROVERLAY").isEmpty(); + +void QBlittablePixmapData::mergeOverlay() +{ + if (m_unmergedCopy || !showRasterOverlay) + return; + m_unmergedCopy = new QImage(buffer()->copy()); + QPainter p(buffer()); + p.setCompositionMode(QPainter::CompositionMode_SourceOver); + p.drawImage(0,0,*overlay()); + p.end(); +} + +void QBlittablePixmapData::unmergeOverlay() +{ + if (!m_unmergedCopy || !showRasterOverlay) + return; + QPainter p(buffer()); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.drawImage(0,0,*m_unmergedCopy); + p.end(); + + delete m_unmergedCopy; + m_unmergedCopy = 0; +} + +QImage *QBlittablePixmapData::overlay() +{ + if (!m_rasterOverlay|| + m_rasterOverlay->size() != QSize(w,h)){ + m_rasterOverlay = new QImage(w,h,QImage::Format_ARGB32_Premultiplied); + m_rasterOverlay->fill(0x00000000); + uint color = (qrand() % 11)+7; + m_overlayColor = QColor(Qt::GlobalColor(color)); + m_overlayColor.setAlpha(0x88); + + } + return m_rasterOverlay; +} + +void QBlittablePixmapData::markRasterOverlayImpl(const QRectF &rect) +{ + if (!showRasterOverlay) + return; + QRectF transformationRect = clipAndTransformRect(rect); + if(!transformationRect.isEmpty()) { + QPainter p(overlay()); + p.setBrush(m_overlayColor); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(transformationRect,QBrush(m_overlayColor)); + } +} + +void QBlittablePixmapData::unmarkRasterOverlayImpl(const QRectF &rect) +{ + if (!showRasterOverlay) + return; + QRectF transformationRect = clipAndTransformRect(rect); + if (!transformationRect.isEmpty()) { + QPainter p(overlay()); + QColor color(0x00,0x00,0x00,0x00); + p.setBrush(color); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(transformationRect,QBrush(color)); + } +} + +QRectF QBlittablePixmapData::clipAndTransformRect(const QRectF &rect) const +{ + QRectF transformationRect = rect; + paintEngine(); + if (m_engine->state()) { + transformationRect = m_engine->state()->matrix.mapRect(rect); + const QClipData *clipData = m_engine->clip(); + if (clipData) { + if (clipData->hasRectClip) { + transformationRect &= clipData->clipRect; + } else if (clipData->hasRegionClip) { + const QVector<QRect> rects = clipData->clipRegion.rects(); + for (int i = 0; i < rects.size(); i++) { + transformationRect &= rects.at(i); + } + } + } + } + return transformationRect; +} + +#endif //QT_BLITTER_RASTEROVERLAY + +QT_END_NAMESPACE + +#endif //QT_NO_BLITTABLE diff --git a/src/gui/image/qpixmap_blitter_p.h b/src/gui/image/qpixmap_blitter_p.h new file mode 100644 index 0000000..55b5618 --- /dev/null +++ b/src/gui/image/qpixmap_blitter_p.h @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QPIXMAP_BLITTER_P_H +#define QPIXMAP_BLITTER_P_H + +#include <private/qpixmapdata_p.h> +#include <private/qpaintengine_blitter_p.h> + +#ifndef QT_NO_BLITTABLE +QT_BEGIN_NAMESPACE + +class Q_GUI_EXPORT QBlittablePixmapData : public QPixmapData +{ +// Q_DECLARE_PRIVATE(QBlittablePixmapData); +public: + QBlittablePixmapData(); + ~QBlittablePixmapData(); + + virtual QBlittable *createBlittable(const QSize &size) const = 0; + QBlittable *blittable() const; + void setBlittable(QBlittable *blittable); + + void resize(int width, int height); + int metric(QPaintDevice::PaintDeviceMetric metric) const; + void fill(const QColor &color); + QImage *buffer(); + QImage toImage() const; + bool hasAlphaChannel() const; + void fromImage(const QImage &image, Qt::ImageConversionFlags flags); + + QPaintEngine *paintEngine() const; + + void markRasterOverlay(const QRectF &); + void markRasterOverlay(const QPointF &, const QTextItem &); + void markRasterOverlay(const QVectorPath &); + void markRasterOverlay(const QRect *rects, int rectCount); + void markRasterOverlay(const QRectF *rects, int rectCount); + void unmarkRasterOverlay(const QRectF &); + +#ifdef QT_BLITTER_RASTEROVERLAY + void mergeOverlay(); + void unmergeOverlay(); + QImage *overlay(); + +#endif //QT_BLITTER_RASTEROVERLAY +protected: + QBlitterPaintEngine *m_engine; + QBlittable *m_blittable; + +#ifdef QT_BLITTER_RASTEROVERLAY + QImage *m_rasterOverlay; + QImage *m_unmergedCopy; + QColor m_overlayColor; + + void markRasterOverlayImpl(const QRectF &); + void unmarkRasterOverlayImpl(const QRectF &); + QRectF clipAndTransformRect(const QRectF &) const; +#endif //QT_BLITTER_RASTEROVERLAY + +}; + +inline void QBlittablePixmapData::markRasterOverlay(const QRectF &rect) +{ +#ifdef QT_BLITTER_RASTEROVERLAY + markRasterOverlayImpl(rect); +#else + Q_UNUSED(rect) +#endif +} + +inline void QBlittablePixmapData::markRasterOverlay(const QVectorPath &path) +{ +#ifdef QT_BLITTER_RASTEROVERLAY + markRasterOverlayImpl(path.convertToPainterPath().boundingRect()); +#else + Q_UNUSED(path) +#endif +} + +inline void QBlittablePixmapData::markRasterOverlay(const QPointF &pos, const QTextItem &ti) +{ +#ifdef QT_BLITTER_RASTEROVERLAY + QFontMetricsF fm(ti.font()); + QRectF rect = fm.tightBoundingRect(ti.text()); + rect.moveBottomLeft(pos); + markRasterOverlay(rect); +#else + Q_UNUSED(pos) + Q_UNUSED(ti) +#endif +} + +inline void QBlittablePixmapData::markRasterOverlay(const QRect *rects, int rectCount) +{ +#ifdef QT_BLITTER_RASTEROVERLAY + for (int i = 0; i < rectCount; i++) { + markRasterOverlay(rects[i]); + } +#else + Q_UNUSED(rects) + Q_UNUSED(rectCount) +#endif +} +inline void QBlittablePixmapData::markRasterOverlay(const QRectF *rects, int rectCount) +{ +#ifdef QT_BLITTER_RASTEROVERLAY + for (int i = 0; i < rectCount; i++) { + markRasterOverlay(rects[i]); + } +#else + Q_UNUSED(rects) + Q_UNUSED(rectCount) +#endif +} + +inline void QBlittablePixmapData::unmarkRasterOverlay(const QRectF &rect) +{ +#ifdef QT_BLITTER_RASTEROVERLAY + unmarkRasterOverlayImpl(rect); +#else + Q_UNUSED(rect) +#endif +} + +QT_END_NAMESPACE +#endif // QT_NO_BLITTABLE +#endif // QPIXMAP_BLITTER_P_H diff --git a/src/gui/image/qpixmap_qpa.cpp b/src/gui/image/qpixmap_qpa.cpp new file mode 100644 index 0000000..61be216 --- /dev/null +++ b/src/gui/image/qpixmap_qpa.cpp @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** 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 QtGui 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 <qpixmap.h> +#include <private/qgraphicssystem_p.h> +#include <private/qapplication_p.h> + +QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h) +{ + return QApplicationPrivate::platformIntegration()->grabWindow(window, x, y, w, h); +} diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp index 01f2c11..4e4f594 100644 --- a/src/gui/image/qpixmap_x11.cpp +++ b/src/gui/image/qpixmap_x11.cpp @@ -310,7 +310,7 @@ static int defaultScreen = -1; QPixmap member functions *****************************************************************************/ -static int qt_pixmap_serial = 0; +QBasicAtomicInt qt_pixmap_serial = Q_BASIC_ATOMIC_INITIALIZER(0); int Q_GUI_EXPORT qt_x11_preferred_pixmap_depth = 0; QX11PixmapData::QX11PixmapData(PixelType type) @@ -327,7 +327,7 @@ QPixmapData *QX11PixmapData::createCompatiblePixmapData() const void QX11PixmapData::resize(int width, int height) { - setSerialNumber(++qt_pixmap_serial); + setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); w = width; h = height; @@ -410,7 +410,7 @@ struct QX11AlphaDetector void QX11PixmapData::fromImage(const QImage &img, Qt::ImageConversionFlags flags) { - setSerialNumber(++qt_pixmap_serial); + setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); w = img.width(); h = img.height(); @@ -2013,7 +2013,7 @@ QPixmap QX11PixmapData::transformed(const QTransform &transform, x11Data->hd = (Qt::HANDLE)XCreatePixmap(X11->display, RootWindow(X11->display, xinfo.screen()), w, h, d); - x11Data->setSerialNumber(++qt_pixmap_serial); + x11Data->setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); #ifndef QT_NO_XRENDER if (X11->use_xrender) { @@ -2264,7 +2264,7 @@ void QX11PixmapData::copy(const QPixmapData *data, const QRect &rect) const QX11PixmapData *x11Data = static_cast<const QX11PixmapData*>(data); - setSerialNumber(++qt_pixmap_serial); + setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); flags &= ~Uninitialized; xinfo = x11Data->xinfo; @@ -2384,7 +2384,7 @@ QPixmap QPixmap::fromX11Pixmap(Qt::HANDLE pixmap, QPixmap::ShareMode mode) } QX11PixmapData *data = new QX11PixmapData(depth == 1 ? QPixmapData::BitmapType : QPixmapData::PixmapType); - data->setSerialNumber(++qt_pixmap_serial); + data->setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); data->flags = QX11PixmapData::Readonly; data->share_mode = mode; data->w = width; diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h index ec62b0b..f69eb3d 100644 --- a/src/gui/image/qpixmapdata_p.h +++ b/src/gui/image/qpixmapdata_p.h @@ -75,7 +75,8 @@ public: }; #endif enum ClassId { RasterClass, X11Class, MacClass, DirectFBClass, - OpenGLClass, OpenVGClass, RuntimeClass, CustomClass = 1024 }; + OpenGLClass, OpenVGClass, RuntimeClass, BlitterClass, + CustomClass = 1024 }; QPixmapData(PixelType pixelType, int classId); virtual ~QPixmapData(); diff --git a/src/gui/image/qpixmapdatafactory.cpp b/src/gui/image/qpixmapdatafactory.cpp index 7498a7c..50dad38 100644 --- a/src/gui/image/qpixmapdatafactory.cpp +++ b/src/gui/image/qpixmapdatafactory.cpp @@ -53,6 +53,9 @@ #ifdef Q_WS_MAC # include <private/qpixmap_mac_p.h> #endif +#ifdef Q_WS_QPA +# include <private/qpixmap_raster_p.h> +#endif #ifdef Q_OS_SYMBIAN # include <private/qpixmap_s60_p.h> #endif @@ -82,8 +85,10 @@ QPixmapData* QSimplePixmapDataFactory::create(QPixmapData::PixelType type) return new QRasterPixmapData(type); #elif defined(Q_WS_MAC) return new QMacPixmapData(type); +#elif defined(Q_WS_QPA) + return new QRasterPixmapData(type); #elif defined(Q_OS_SYMBIAN) - return new QS60PixmapData(type); + return new QS60PixmapData(type); #else #error QSimplePixmapDataFactory::create() not implemented #endif diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 935aba0..ea62cf8 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -331,6 +331,7 @@ public: float gamma; int quality; QString description; + QStringList readTexts; png_struct *png_ptr; png_info *info_ptr; @@ -389,25 +390,20 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngHeader() while (num_text--) { QString key, value; -#if defined(PNG_iTXt_SUPPORTED) && !defined(QT_NO_TEXTCODEC) - if (text_ptr->lang) { - QTextCodec *codec = QTextCodec::codecForName(text_ptr->lang); - if (codec) { - key = codec->toUnicode(text_ptr->lang_key); - value = codec->toUnicode(QByteArray(text_ptr->text, text_ptr->itxt_length)); - } else { - key = QString::fromLatin1(text_ptr->key); - value = QString::fromLatin1(QByteArray(text_ptr->text, int(text_ptr->text_length))); - } + key = QString::fromLatin1(text_ptr->key); +#if defined(PNG_iTXt_SUPPORTED) + if (text_ptr->itxt_length) { + value = QString::fromUtf8(text_ptr->text, int(text_ptr->itxt_length)); } else #endif { - key = QString::fromLatin1(text_ptr->key); value = QString::fromLatin1(QByteArray(text_ptr->text, int(text_ptr->text_length))); } if (!description.isEmpty()) description += QLatin1String("\n\n"); description += key + QLatin1String(": ") + value.simplified(); + readTexts.append(key); + readTexts.append(value); text_ptr++; } #endif @@ -485,25 +481,8 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage) outImage->setDotsPerMeterX(png_get_x_pixels_per_meter(png_ptr,info_ptr)); outImage->setDotsPerMeterY(png_get_y_pixels_per_meter(png_ptr,info_ptr)); -#ifndef QT_NO_IMAGE_TEXT - png_textp text_ptr; - int num_text=0; - png_get_text(png_ptr,info_ptr,&text_ptr,&num_text); - while (num_text--) { - outImage->setText(text_ptr->key,0,QString::fromAscii(text_ptr->text)); - text_ptr++; - } - - foreach (const QString &pair, description.split(QLatin1String("\n\n"))) { - int index = pair.indexOf(QLatin1Char(':')); - if (index >= 0 && pair.indexOf(QLatin1Char(' ')) < index) { - outImage->setText(QLatin1String("Description"), pair.simplified()); - } else { - QString key = pair.left(index); - outImage->setText(key, pair.mid(index + 2).simplified()); - } - } -#endif + for (int i = 0; i < readTexts.size()-1; i+=2) + outImage->setText(readTexts.at(i), readTexts.at(i+1)); png_read_end(png_ptr, end_info); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); @@ -634,29 +613,40 @@ static void set_text(const QImage &image, png_structp png_ptr, png_infop info_pt return; png_textp text_ptr = new png_text[text.size()]; + qMemSet(text_ptr, 0, text.size() * sizeof(png_text)); QMap<QString, QString>::ConstIterator it = text.constBegin(); int i = 0; while (it != text.constEnd()) { - QString t = it.value(); - if (t.length() < 40) - text_ptr[i].compression = PNG_TEXT_COMPRESSION_NONE; - else - text_ptr[i].compression = PNG_TEXT_COMPRESSION_zTXt; text_ptr[i].key = qstrdup(it.key().left(79).toLatin1().constData()); + bool noCompress = (it.value().length() < 40); -#ifndef PNG_iTXt_SUPPORTED - QByteArray value = it.value().toLatin1(); - text_ptr[i].text = qstrdup(value.constData()); - text_ptr[i].text_length = value.size(); -#else - QByteArray value = it.value().toUtf8(); - text_ptr[i].text = qstrdup(value.constData()); - text_ptr[i].text_length = 0; - text_ptr[i].itxt_length = value.size(); - text_ptr[i].lang = const_cast<char*>("UTF-8"); - text_ptr[i].lang_key = qstrdup(it.key().toUtf8().constData()); +#ifdef PNG_iTXt_SUPPORTED + bool needsItxt = false; + foreach(const QChar c, it.value()) { + uchar ch = c.cell(); + if (c.row() || (ch < 0x20 && ch != '\n') || (ch > 0x7e && ch < 0xa0)) { + needsItxt = true; + break; + } + } + + if (needsItxt) { + text_ptr[i].compression = noCompress ? PNG_ITXT_COMPRESSION_NONE : PNG_ITXT_COMPRESSION_zTXt; + QByteArray value = it.value().toUtf8(); + text_ptr[i].text = qstrdup(value.constData()); + text_ptr[i].itxt_length = value.size(); + text_ptr[i].lang = const_cast<char*>("UTF-8"); + text_ptr[i].lang_key = qstrdup(it.key().toUtf8().constData()); + } + else #endif + { + text_ptr[i].compression = noCompress ? PNG_TEXT_COMPRESSION_NONE : PNG_TEXT_COMPRESSION_zTXt; + QByteArray value = it.value().toLatin1(); + text_ptr[i].text = qstrdup(value.constData()); + text_ptr[i].text_length = value.size(); + } ++i; ++it; } diff --git a/src/gui/image/qtiffhandler.cpp b/src/gui/image/qtiffhandler.cpp index 1627917..dd2bd10 100644 --- a/src/gui/image/qtiffhandler.cpp +++ b/src/gui/image/qtiffhandler.cpp @@ -196,9 +196,12 @@ bool QTiffHandler::read(QImage *image) uint16 bitPerSample; if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample)) bitPerSample = 1; + uint16 samplesPerPixel; // they may be e.g. grayscale with 2 samples per pixel + if (!TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel)) + samplesPerPixel = 1; bool grayscale = photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_MINISWHITE; - if (grayscale && bitPerSample == 1) { + if (grayscale && bitPerSample == 1 && samplesPerPixel == 1) { if (image->size() != QSize(width, height) || image->format() != QImage::Format_Mono) *image = QImage(width, height, QImage::Format_Mono); QVector<QRgb> colortable(2); @@ -220,7 +223,7 @@ bool QTiffHandler::read(QImage *image) } } } else { - if ((grayscale || photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8) { + if ((grayscale || photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8 && samplesPerPixel == 1) { if (image->size() != QSize(width, height) || image->format() != QImage::Format_Indexed8) *image = QImage(width, height, QImage::Format_Indexed8); if (!image->isNull()) { diff --git a/src/gui/inputmethod/inputmethod.pri b/src/gui/inputmethod/inputmethod.pri index 02e3e57..d439438 100644 --- a/src/gui/inputmethod/inputmethod.pri +++ b/src/gui/inputmethod/inputmethod.pri @@ -19,7 +19,7 @@ embedded { HEADERS += inputmethod/qwsinputcontext_p.h SOURCES += inputmethod/qwsinputcontext_qws.cpp } -mac:!embedded { +mac:!embedded:!qpa { HEADERS += inputmethod/qmacinputcontext_p.h SOURCES += inputmethod/qmacinputcontext_mac.cpp } diff --git a/src/gui/itemviews/qabstractitemdelegate.cpp b/src/gui/itemviews/qabstractitemdelegate.cpp index 0ea6d67..edbeeb8 100644 --- a/src/gui/itemviews/qabstractitemdelegate.cpp +++ b/src/gui/itemviews/qabstractitemdelegate.cpp @@ -362,7 +362,7 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event, case QEvent::ToolTip: { QHelpEvent *he = static_cast<QHelpEvent*>(event); QVariant tooltip = index.data(Qt::ToolTipRole); - if (qVariantCanConvert<QString>(tooltip)) { + if (tooltip.canConvert<QString>()) { QToolTip::showText(he->globalPos(), tooltip.toString(), view); return true; } @@ -376,7 +376,7 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event, case QEvent::WhatsThis: { QHelpEvent *he = static_cast<QHelpEvent*>(event); QVariant whatsthis = index.data(Qt::WhatsThisRole); - if (qVariantCanConvert<QString>(whatsthis)) { + if (whatsthis.canConvert<QString>()) { QWhatsThis::showText(he->globalPos(), whatsthis.toString(), view); return true; } diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 95e92c9..a9612a2 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -79,6 +79,7 @@ QAbstractItemViewPrivate::QAbstractItemViewPrivate() pressedAlreadySelected(false), viewportEnteredNeeded(false), state(QAbstractItemView::NoState), + stateBeforeAnimation(QAbstractItemView::NoState), editTriggers(QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed), lastTrigger(QAbstractItemView::NoEditTriggers), tabKeyNavigation(false), @@ -652,7 +653,7 @@ void QAbstractItemView::setModel(QAbstractItemModel *model) "QAbstractItemView::setModel", "A model should return the exact same index " "(including its internal id/pointer) when asked for it twice in a row."); - Q_ASSERT_X(d->model->index(0,0).parent() == QModelIndex(), + Q_ASSERT_X(!d->model->index(0,0).parent().isValid(), "QAbstractItemView::setModel", "The parent of a top level index should be invalid"); @@ -1036,10 +1037,12 @@ void QAbstractItemView::reset() { Q_D(QAbstractItemView); d->delayedReset.stop(); //make sure we stop the timer - QList<QEditorInfo>::const_iterator it = d->editors.constBegin(); - for (; it != d->editors.constEnd(); ++it) - d->releaseEditor(it->editor); - d->editors.clear(); + foreach (const QEditorInfo &info, d->indexEditorHash) { + if (info.widget) + d->releaseEditor(info.widget.data()); + } + d->editorIndexHash.clear(); + d->indexEditorHash.clear(); d->persistent.clear(); d->currentIndexSet = false; setState(NoState); @@ -2333,7 +2336,7 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) case Qt::Key_Return: // Propagate the enter if you couldn't edit the item and there are no // current editors (if there are editors, the event was most likely propagated from it). - if (!edit(currentIndex(), EditKeyPressed, event) && d->editors.isEmpty()) + if (!edit(currentIndex(), EditKeyPressed, event) && d->editorIndexHash.isEmpty()) event->ignore(); break; #else @@ -2518,7 +2521,7 @@ bool QAbstractItemView::edit(const QModelIndex &index, EditTrigger trigger, QEve if (!d->isIndexValid(index)) return false; - if (QWidget *w = (d->persistent.isEmpty() ? static_cast<QWidget*>(0) : d->editorForIndex(index).editor.data())) { + if (QWidget *w = (d->persistent.isEmpty() ? static_cast<QWidget*>(0) : d->editorForIndex(index).widget.data())) { if (w->focusPolicy() == Qt::NoFocus) return false; w->setFocus(); @@ -2578,15 +2581,15 @@ void QAbstractItemView::updateEditorData() void QAbstractItemView::updateEditorGeometries() { Q_D(QAbstractItemView); - if(d->editors.isEmpty()) + if(d->editorIndexHash.isEmpty()) return; QStyleOptionViewItemV4 option = d->viewOptionsV4(); - QList<QEditorInfo>::iterator it = d->editors.begin(); + QEditorIndexHash::iterator it = d->editorIndexHash.begin(); QWidgetList editorsToRelease; QWidgetList editorsToHide; - while (it != d->editors.end()) { - QModelIndex index = it->index; - QWidget *editor = it->editor; + while (it != d->editorIndexHash.end()) { + QModelIndex index = it.value(); + QWidget *editor = it.key(); if (index.isValid() && editor) { option.rect = visualRect(index); if (option.rect.isValid()) { @@ -2599,13 +2602,14 @@ void QAbstractItemView::updateEditorGeometries() } ++it; } else { - it = d->editors.erase(it); + d->indexEditorHash.remove(it.value()); + it = d->editorIndexHash.erase(it); editorsToRelease << editor; } } //we hide and release the editor outside of the loop because it might change the focus and try - //to change the d->editors list. + //to change the editors hashes. for (int i = 0; i < editorsToHide.count(); ++i) { editorsToHide.at(i)->hide(); } @@ -2945,7 +2949,7 @@ int QAbstractItemView::sizeHintForRow(int row) const { Q_D(const QAbstractItemView); - if (row < 0 || row >= d->model->rowCount() || !model()) + if (row < 0 || row >= d->model->rowCount(d->root)) return -1; ensurePolished(); @@ -2956,8 +2960,8 @@ int QAbstractItemView::sizeHintForRow(int row) const QModelIndex index; for (int c = 0; c < colCount; ++c) { index = d->model->index(row, c, d->root); - if (QWidget *editor = d->editorForIndex(index).editor) - height = qMax(height, editor->size().height()); + if (QWidget *editor = d->editorForIndex(index).widget.data()) + height = qMax(height, editor->height()); int hint = d->delegateForIndex(index)->sizeHint(option, index).height(); height = qMax(height, hint); } @@ -2976,7 +2980,7 @@ int QAbstractItemView::sizeHintForColumn(int column) const { Q_D(const QAbstractItemView); - if (column < 0 || column >= d->model->columnCount() || !model()) + if (column < 0 || column >= d->model->columnCount(d->root)) return -1; ensurePolished(); @@ -2987,7 +2991,7 @@ int QAbstractItemView::sizeHintForColumn(int column) const QModelIndex index; for (int r = 0; r < rows; ++r) { index = d->model->index(r, column, d->root); - if (QWidget *editor = d->editorForIndex(index).editor) + if (QWidget *editor = d->editorForIndex(index).widget.data()) width = qMax(width, editor->sizeHint().width()); int hint = d->delegateForIndex(index)->sizeHint(option, index).width(); width = qMax(width, hint); @@ -3023,8 +3027,7 @@ void QAbstractItemView::openPersistentEditor(const QModelIndex &index) void QAbstractItemView::closePersistentEditor(const QModelIndex &index) { Q_D(QAbstractItemView); - QWidget *editor = d->editorForIndex(index).editor; - if (editor) { + if (QWidget *editor = d->editorForIndex(index).widget.data()) { if (index == selectionModel()->currentIndex()) closeEditor(editor, QAbstractItemDelegate::RevertModelCache); d->persistent.remove(editor); @@ -3088,9 +3091,11 @@ void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget QWidget* QAbstractItemView::indexWidget(const QModelIndex &index) const { Q_D(const QAbstractItemView); - if (!d->isIndexValid(index)) - return 0; - return d->editorForIndex(index).editor; + if (d->isIndexValid(index)) + if (QWidget *editor = d->editorForIndex(index).widget.data()) + return editor; + + return 0; } /*! @@ -3152,12 +3157,12 @@ void QAbstractItemView::dataChanged(const QModelIndex &topLeft, const QModelInde // Single item changed Q_D(QAbstractItemView); if (topLeft == bottomRight && topLeft.isValid()) { - const QEditorInfo editorInfo = d->editorForIndex(topLeft); + const QEditorInfo &editorInfo = d->editorForIndex(topLeft); //we don't update the edit data if it is static - if (!editorInfo.isStatic && editorInfo.editor) { + if (!editorInfo.isStatic && editorInfo.widget) { QAbstractItemDelegate *delegate = d->delegateForIndex(topLeft); if (delegate) { - delegate->setEditorData(editorInfo.editor, topLeft); + delegate->setEditorData(editorInfo.widget.data(), topLeft); } } if (isVisible() && !d->delayedPendingLayout) { @@ -3231,12 +3236,17 @@ void QAbstractItemView::rowsAboutToBeRemoved(const QModelIndex &parent, int star } // Remove all affected editors; this is more efficient than waiting for updateGeometries() to clean out editors for invalid indexes - for (int i = d->editors.size() - 1; i >= 0; --i) { - const QModelIndex index = d->editors.at(i).index; - QWidget *editor = d->editors.at(i).editor; + QEditorIndexHash::iterator i = d->editorIndexHash.begin(); + while (i != d->editorIndexHash.end()) { + const QModelIndex index = i.value(); if (index.row() >= start && index.row() <= end && d->model->parent(index) == parent) { - d->editors.removeAt(i); - d->releaseEditor(editor); + QWidget *editor = i.key(); + QEditorInfo info = d->indexEditorHash.take(index); + i = d->editorIndexHash.erase(i); + if (info.widget) + d->releaseEditor(editor); + } else { + ++i; } } } @@ -3293,17 +3303,20 @@ void QAbstractItemViewPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &par } // Remove all affected editors; this is more efficient than waiting for updateGeometries() to clean out editors for invalid indexes - QList<QEditorInfo>::iterator it = editors.begin(); - while (it != editors.end()) { - QModelIndex index = it->index; + QEditorIndexHash::iterator it = editorIndexHash.begin(); + while (it != editorIndexHash.end()) { + QModelIndex index = it.value(); if (index.column() <= start && index.column() >= end && model->parent(index) == parent) { - QWidget *editor = it->editor; - it = editors.erase(it); - releaseEditor(editor); + QWidget *editor = it.key(); + QEditorInfo info = indexEditorHash.take(it.value()); + it = editorIndexHash.erase(it); + if (info.widget) + releaseEditor(editor); } else { ++it; } } + } /*! @@ -3385,7 +3398,7 @@ void QAbstractItemView::currentChanged(const QModelIndex ¤t, const QModelI if (previous.isValid()) { QModelIndex buddy = d->model->buddy(previous); - QWidget *editor = d->editorForIndex(buddy).editor; + QWidget *editor = d->editorForIndex(buddy).widget.data(); if (editor && !d->persistent.contains(editor)) { commitData(editor); if (current.row() != previous.row()) @@ -3911,7 +3924,7 @@ QWidget *QAbstractItemViewPrivate::editor(const QModelIndex &index, const QStyleOptionViewItem &options) { Q_Q(QAbstractItemView); - QWidget *w = editorForIndex(index).editor; + QWidget *w = editorForIndex(index).widget.data(); if (!w) { QAbstractItemDelegate *delegate = delegateForIndex(index); if (!delegate) @@ -3942,6 +3955,7 @@ QWidget *QAbstractItemViewPrivate::editor(const QModelIndex &index, #endif } } + return w; } @@ -3950,11 +3964,11 @@ void QAbstractItemViewPrivate::updateEditorData(const QModelIndex &tl, const QMo // we are counting on having relatively few editors const bool checkIndexes = tl.isValid() && br.isValid(); const QModelIndex parent = tl.parent(); - QList<QEditorInfo>::const_iterator it = editors.constBegin(); - for (; it != editors.constEnd(); ++it) { - QWidget *editor = it->editor; - const QModelIndex index = it->index; - if (it->isStatic || editor == 0 || !index.isValid() || + QIndexEditorHash::const_iterator it = indexEditorHash.constBegin(); + for (; it != indexEditorHash.constEnd(); ++it) { + QWidget *editor = it.value().widget.data(); + const QModelIndex index = it.key(); + if (it.value().isStatic || !editor || !index.isValid() || (checkIndexes && (index.row() < tl.row() || index.row() > br.row() || index.column() < tl.column() || index.column() > br.column() @@ -4027,41 +4041,40 @@ void QAbstractItemViewPrivate::checkPersistentEditorFocus() } -QEditorInfo QAbstractItemViewPrivate::editorForIndex(const QModelIndex &index) const +const QEditorInfo & QAbstractItemViewPrivate::editorForIndex(const QModelIndex &index) const { - QList<QEditorInfo>::const_iterator it = editors.constBegin(); - for (; it != editors.constEnd(); ++it) { - if (it->index == index) - return *it; - } + static QEditorInfo nullInfo; + + QIndexEditorHash::const_iterator it = indexEditorHash.find(index); + if (it == indexEditorHash.end()) + return nullInfo; - return QEditorInfo(); + return it.value(); } QModelIndex QAbstractItemViewPrivate::indexForEditor(QWidget *editor) const { - QList<QEditorInfo>::const_iterator it = editors.constBegin(); - for (; it != editors.constEnd(); ++it) { - if (it->editor == editor) - return it->index; - } - return QModelIndex(); + QEditorIndexHash::const_iterator it = editorIndexHash.find(editor); + if (it == editorIndexHash.end()) + return QModelIndex(); + + return it.value(); } void QAbstractItemViewPrivate::removeEditor(QWidget *editor) { - QList<QEditorInfo>::iterator it = editors.begin(); - for (; it != editors.end(); ) { - if (it->editor == editor) - it = editors.erase(it); - else - ++it; + QEditorIndexHash::iterator it = editorIndexHash.find(editor); + if (it != editorIndexHash.end()) + { + indexEditorHash.remove(it.value()); + editorIndexHash.erase(it); } } void QAbstractItemViewPrivate::addEditor(const QModelIndex &index, QWidget *editor, bool isStatic) { - editors.append(QEditorInfo(index, editor, isStatic)); + editorIndexHash.insert(editor, index); + indexEditorHash.insert(index, QEditorInfo(editor, isStatic)); } bool QAbstractItemViewPrivate::sendDelegateEvent(const QModelIndex &index, QEvent *event) const @@ -4088,13 +4101,13 @@ bool QAbstractItemViewPrivate::openEditor(const QModelIndex &index, QEvent *even if (!w) return false; - if (event) - QApplication::sendEvent(w->focusProxy() ? w->focusProxy() : w, event); - q->setState(QAbstractItemView::EditingState); w->show(); w->setFocus(); + if (event) + QApplication::sendEvent(w->focusProxy() ? w->focusProxy() : w, event); + return true; } diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index fce74f3..03b413a 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -70,22 +70,18 @@ QT_BEGIN_NAMESPACE -struct QEditorInfo -{ - QEditorInfo() : isStatic(false) - { - } - - QEditorInfo(const QPersistentModelIndex &i, QWidget *e, bool b) : index(i), editor(e), isStatic(b) - { - } - - QPersistentModelIndex index; - QPointer<QWidget> editor; - bool isStatic; //true when called from setIndexWidget +struct QEditorInfo { + QEditorInfo(QWidget *e, bool s): widget(QWeakPointer<QWidget>(e)), isStatic(s) {} + QEditorInfo(): isStatic(false) {} + QWeakPointer<QWidget> widget; + bool isStatic; }; +// Fast associativity between Persistent editors and indices. +typedef QHash<QWidget *, QPersistentModelIndex> QEditorIndexHash; +typedef QHash<QPersistentModelIndex, QEditorInfo> QIndexEditorHash; + typedef QPair<QRect, QModelIndex> QItemViewPaintPair; typedef QList<QItemViewPaintPair> QItemViewPaintPairs; @@ -135,8 +131,9 @@ public: } void stopAutoScroll() { autoScrollTimer.stop(); autoScrollCount = 0;} - - bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index); +#ifndef QT_NO_DRAGANDDROP + virtual bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index); +#endif bool droppingOnItself(QDropEvent *event, const QModelIndex &index); QWidget *editor(const QModelIndex &index, const QStyleOptionViewItem &options); @@ -247,9 +244,9 @@ public: : q->horizontalOffset(), q->verticalOffset()); } - QEditorInfo editorForIndex(const QModelIndex &index) const; + const QEditorInfo &editorForIndex(const QModelIndex &index) const; inline bool hasEditor(const QModelIndex &index) const { - return editorForIndex(index).editor != 0; + return indexEditorHash.find(index) != indexEditorHash.constEnd(); } QModelIndex indexForEditor(QWidget *editor) const; @@ -352,7 +349,8 @@ public: QAbstractItemView::SelectionMode selectionMode; QAbstractItemView::SelectionBehavior selectionBehavior; - QList<QEditorInfo> editors; + QEditorIndexHash editorIndexHash; + QIndexEditorHash indexEditorHash; QSet<QWidget*> persistent; QWidget *currentlyCommittingEditor; @@ -367,6 +365,7 @@ public: bool viewportEnteredNeeded; QAbstractItemView::State state; + QAbstractItemView::State stateBeforeAnimation; QAbstractItemView::EditTriggers editTriggers; QAbstractItemView::EditTrigger lastTrigger; diff --git a/src/gui/itemviews/qabstractproxymodel.cpp b/src/gui/itemviews/qabstractproxymodel.cpp index 1c600e2..b9574f1 100644 --- a/src/gui/itemviews/qabstractproxymodel.cpp +++ b/src/gui/itemviews/qabstractproxymodel.cpp @@ -45,6 +45,9 @@ #include "qitemselectionmodel.h" #include <private/qabstractproxymodel_p.h> +#include <QtCore/QSize> +#include <QtCore/QStringList> + QT_BEGIN_NAMESPACE @@ -118,12 +121,15 @@ QAbstractProxyModel::~QAbstractProxyModel() void QAbstractProxyModel::setSourceModel(QAbstractItemModel *sourceModel) { Q_D(QAbstractProxyModel); - if (d->model) + if (d->model) { disconnect(d->model, SIGNAL(destroyed()), this, SLOT(_q_sourceModelDestroyed())); + disconnect(d->model, SIGNAL(modelReset()), this, SLOT(resetInternalData())); + } if (sourceModel) { d->model = sourceModel; connect(d->model, SIGNAL(destroyed()), this, SLOT(_q_sourceModelDestroyed())); + connect(d->model, SIGNAL(modelReset()), this, SLOT(resetInternalData())); } else { d->model = QAbstractItemModelPrivate::staticEmptyModel(); } @@ -270,6 +276,15 @@ bool QAbstractProxyModel::setData(const QModelIndex &index, const QVariant &valu /*! \reimp */ +bool QAbstractProxyModel::setItemData(const QModelIndex &index, const QMap< int, QVariant >& roles) +{ + Q_D(QAbstractProxyModel); + return d->model->setItemData(mapToSource(index), roles); +} + +/*! + \reimp + */ bool QAbstractProxyModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) { Q_D(QAbstractProxyModel); @@ -284,6 +299,109 @@ bool QAbstractProxyModel::setHeaderData(int section, Qt::Orientation orientation return d->model->setHeaderData(sourceSection, orientation, value, role); } +/*! + \reimp + */ +QModelIndex QAbstractProxyModel::buddy(const QModelIndex &index) const +{ + Q_D(const QAbstractProxyModel); + return mapFromSource(d->model->buddy(mapToSource(index))); +} + +/*! + \reimp + */ +bool QAbstractProxyModel::canFetchMore(const QModelIndex &parent) const +{ + Q_D(const QAbstractProxyModel); + return d->model->canFetchMore(mapToSource(parent)); +} + +/*! + \reimp + */ +void QAbstractProxyModel::fetchMore(const QModelIndex &parent) +{ + Q_D(QAbstractProxyModel); + d->model->fetchMore(mapToSource(parent)); +} + +/*! + \reimp + */ +void QAbstractProxyModel::sort(int column, Qt::SortOrder order) +{ + Q_D(QAbstractProxyModel); + d->model->sort(column, order); +} + +/*! + \reimp + */ +QSize QAbstractProxyModel::span(const QModelIndex &index) const +{ + Q_D(const QAbstractProxyModel); + return d->model->span(mapToSource(index)); +} + +/*! + \reimp + */ +bool QAbstractProxyModel::hasChildren(const QModelIndex &parent) const +{ + Q_D(const QAbstractProxyModel); + return d->model->hasChildren(mapToSource(parent)); +} + +/*! + \reimp + */ +QMimeData* QAbstractProxyModel::mimeData(const QModelIndexList &indexes) const +{ + Q_D(const QAbstractProxyModel); + QModelIndexList list; + foreach(const QModelIndex &index, indexes) + list << mapToSource(index); + return d->model->mimeData(list); +} + +/*! + \reimp + */ +QStringList QAbstractProxyModel::mimeTypes() const +{ + Q_D(const QAbstractProxyModel); + return d->model->mimeTypes(); +} + +/*! + \reimp + */ +Qt::DropActions QAbstractProxyModel::supportedDropActions() const +{ + Q_D(const QAbstractProxyModel); + return d->model->supportedDropActions(); +} + +/* + \since 4.8 + + This slot is called just after the internal data of a model is cleared + while it is being reset. + + This slot is provided the convenience of subclasses of concrete proxy + models, such as subclasses of QSortFilterProxyModel which maintain extra + data. + + \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 10 + + \sa modelAboutToBeReset(), modelReset() +*/ +void QAbstractProxyModel::resetInternalData() +{ + +} + QT_END_NAMESPACE #include "moc_qabstractproxymodel.cpp" diff --git a/src/gui/itemviews/qabstractproxymodel.h b/src/gui/itemviews/qabstractproxymodel.h index c6bb985..0daa7f8 100644 --- a/src/gui/itemviews/qabstractproxymodel.h +++ b/src/gui/itemviews/qabstractproxymodel.h @@ -81,8 +81,23 @@ public: Qt::ItemFlags flags(const QModelIndex &index) const; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + bool setItemData(const QModelIndex& index, const QMap<int, QVariant> &roles); bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole); + QModelIndex buddy(const QModelIndex &index) const; + bool canFetchMore(const QModelIndex &parent) const; + void fetchMore(const QModelIndex &parent); + void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); + QSize span(const QModelIndex &index) const; + bool hasChildren(const QModelIndex &parent = QModelIndex()) const; + + QMimeData* mimeData(const QModelIndexList &indexes) const; + QStringList mimeTypes() const; + Qt::DropActions supportedDropActions() const; + +protected Q_SLOTS: + void resetInternalData(); + protected: QAbstractProxyModel(QAbstractProxyModelPrivate &, QObject *parent); diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp index 67854a3..7eb3ddc 100644 --- a/src/gui/itemviews/qheaderview.cpp +++ b/src/gui/itemviews/qheaderview.cpp @@ -2105,7 +2105,7 @@ void QHeaderView::paintEvent(QPaintEvent *e) QVariant variant = d->model->headerData(logical, d->orientation, Qt::FontRole); - if (variant.isValid() && qVariantCanConvert<QFont>(variant)) { + if (variant.isValid() && variant.canConvert<QFont>()) { QFont sectionFont = qvariant_cast<QFont>(variant); painter.setFont(sectionFont); } @@ -2485,13 +2485,13 @@ void QHeaderView::paintSection(QPainter *painter, const QRect &rect, int logical opt.icon = qvariant_cast<QPixmap>(variant); QVariant foregroundBrush = d->model->headerData(logicalIndex, d->orientation, Qt::ForegroundRole); - if (qVariantCanConvert<QBrush>(foregroundBrush)) + if (foregroundBrush.canConvert<QBrush>()) opt.palette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(foregroundBrush)); QPointF oldBO = painter->brushOrigin(); QVariant backgroundBrush = d->model->headerData(logicalIndex, d->orientation, Qt::BackgroundRole); - if (qVariantCanConvert<QBrush>(backgroundBrush)) { + if (backgroundBrush.canConvert<QBrush>()) { opt.palette.setBrush(QPalette::Button, qvariant_cast<QBrush>(backgroundBrush)); opt.palette.setBrush(QPalette::Window, qvariant_cast<QBrush>(backgroundBrush)); painter->setBrushOrigin(opt.rect.topLeft()); @@ -2552,7 +2552,7 @@ QSize QHeaderView::sectionSizeFromContents(int logicalIndex) const QVariant var = d->model->headerData(logicalIndex, d->orientation, Qt::FontRole); QFont fnt; - if (var.isValid() && qVariantCanConvert<QFont>(var)) + if (var.isValid() && var.canConvert<QFont>()) fnt = qvariant_cast<QFont>(var); else fnt = font(); diff --git a/src/gui/itemviews/qitemdelegate.cpp b/src/gui/itemviews/qitemdelegate.cpp index 9bbfc23..6556a3e 100644 --- a/src/gui/itemviews/qitemdelegate.cpp +++ b/src/gui/itemviews/qitemdelegate.cpp @@ -850,7 +850,7 @@ void QItemDelegate::drawBackground(QPainter *painter, painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight)); } else { QVariant value = index.data(Qt::BackgroundRole); - if (qVariantCanConvert<QBrush>(value)) { + if (value.canConvert<QBrush>()) { QPointF oldBO = painter->brushOrigin(); painter->setBrushOrigin(option.rect.topLeft()); painter->fillRect(option.rect, qvariant_cast<QBrush>(value)); @@ -1278,7 +1278,8 @@ bool QItemDelegate::editorEvent(QEvent *event, // make sure that we have the right event type if ((event->type() == QEvent::MouseButtonRelease) - || (event->type() == QEvent::MouseButtonDblClick)) { + || (event->type() == QEvent::MouseButtonDblClick) + || (event->type() == QEvent::MouseButtonPress)) { QRect checkRect = check(option, option.rect, Qt::Checked); QRect emptyRect; doLayout(option, &checkRect, &emptyRect, &emptyRect, false); @@ -1287,7 +1288,8 @@ bool QItemDelegate::editorEvent(QEvent *event, return false; // eat the double click events inside the check rect - if (event->type() == QEvent::MouseButtonDblClick) + if ((event->type() == QEvent::MouseButtonPress) + || (event->type() == QEvent::MouseButtonDblClick)) return true; } else if (event->type() == QEvent::KeyPress) { @@ -1326,7 +1328,7 @@ QStyleOptionViewItem QItemDelegate::setOptions(const QModelIndex &index, // set foreground brush value = index.data(Qt::ForegroundRole); - if (qVariantCanConvert<QBrush>(value)) + if (value.canConvert<QBrush>()) opt.palette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value)); return opt; diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp index e2a16b1..7b892c5 100644 --- a/src/gui/itemviews/qitemselectionmodel.cpp +++ b/src/gui/itemviews/qitemselectionmodel.cpp @@ -212,6 +212,7 @@ bool QItemSelectionRange::intersects(const QItemSelectionRange &other) const { return (isValid() && other.isValid() && parent() == other.parent() + && model() == other.model() && ((top() <= other.top() && bottom() >= other.top()) || (top() >= other.top() && top() <= other.bottom())) && ((left() <= other.left() && right() >= other.left()) @@ -508,7 +509,7 @@ void QItemSelection::merge(const QItemSelection &other, QItemSelectionModel::Sel void QItemSelection::split(const QItemSelectionRange &range, const QItemSelectionRange &other, QItemSelection *result) { - if (range.parent() != other.parent()) + if (range.parent() != other.parent() || range.model() != other.model()) return; QModelIndex parent = other.parent(); @@ -634,6 +635,7 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare } QItemSelection deselected; + QItemSelection newParts; QItemSelection::iterator it = ranges.begin(); while (it != ranges.end()) { if (it->topLeft().parent() != parent) { // Check parents until reaching root or contained in range @@ -659,13 +661,20 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare deselected.append(QItemSelectionRange(model->index(start, it->right(), it->parent()), it->bottomRight())); *it = QItemSelectionRange(it->topLeft(), model->index(start - 1, it->right(), it->parent())); ++it; - } else { - if (it->top() < start && end < it->bottom()) // Middle intersection (do nothing) - deselected.append(QItemSelectionRange(model->index(start, it->right(), it->parent()), - model->index(end, it->left(), it->parent()))); + } else if (it->top() < start && end < it->bottom()) { // Middle intersection + // If the parent contains (1, 2, 3, 4, 5, 6, 7, 8) and [3, 4, 5, 6] is selected, + // and [4, 5] is removed, we need to split [3, 4, 5, 6] into [3], [4, 5] and [6]. + // [4, 5] is appended to deselected, and [3] and [6] remain part of the selection + // in ranges. + const QItemSelectionRange removedRange(model->index(start, it->right(), it->parent()), + model->index(end, it->left(), it->parent())); + deselected.append(removedRange); + QItemSelection::split(*it, removedRange, &newParts); + it = ranges.erase(it); + } else ++it; - } } + ranges.append(newParts); if (!deselected.isEmpty()) emit q->selectionChanged(QItemSelection(), deselected); diff --git a/src/gui/itemviews/qitemselectionmodel.h b/src/gui/itemviews/qitemselectionmodel.h index 436514f..e2bd06b 100644 --- a/src/gui/itemviews/qitemselectionmodel.h +++ b/src/gui/itemviews/qitemselectionmodel.h @@ -101,6 +101,30 @@ public: { return (tl == other.tl && br == other.br); } inline bool operator!=(const QItemSelectionRange &other) const { return !operator==(other); } + inline bool operator<(const QItemSelectionRange &other) const + { + // Comparing parents will compare the models, but if two equivalent ranges + // in two different models have invalid parents, they would appear the same + if (other.tl.model() == tl.model()) { + // parent has to be calculated, so we only do so once. + const QModelIndex topLeftParent = tl.parent(); + const QModelIndex otherTopLeftParent = other.tl.parent(); + if (topLeftParent == otherTopLeftParent) { + if (other.tl.row() == tl.row()) { + if (other.tl.column() == tl.column()) { + if (other.br.row() == br.row()) { + return br.column() < other.br.column(); + } + return br.row() < other.br.row(); + } + return tl.column() < other.tl.column(); + } + return tl.row() < other.tl.row(); + } + return topLeftParent < otherTopLeftParent; + } + return tl.model() < other.tl.model(); + } inline bool isValid() const { diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 76d7642..d1ef354 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -756,10 +756,13 @@ void QListView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e // if the parent is above d->root in the tree, nothing will happen QAbstractItemView::rowsAboutToBeRemoved(parent, start, end); if (parent == d->root) { - for (int i = d->hiddenRows.count() - 1; i >= 0; --i) { - int hiddenRow = d->hiddenRows.at(i).row(); + QSet<QPersistentModelIndex>::iterator it = d->hiddenRows.begin(); + while (it != d->hiddenRows.end()) { + int hiddenRow = it->row(); if (hiddenRow >= start && hiddenRow <= end) { - d->hiddenRows.remove(i); + it = d->hiddenRows.erase(it); + } else { + ++it; } } } @@ -1033,16 +1036,7 @@ void QListView::paintEvent(QPaintEvent *e) previousRow = row; } - if (const QWidget *widget = d->editorForIndex(*it).editor) { - QRegion itemGeometry(option.rect); - QRegion widgetGeometry(widget->geometry()); - painter.save(); - painter.setClipRegion(itemGeometry.subtracted(widgetGeometry)); - d->delegateForIndex(*it)->paint(&painter, option, *it); - painter.restore(); - } else { - d->delegateForIndex(*it)->paint(&painter, option, *it); - } + d->delegateForIndex(*it)->paint(&painter, option, *it); } #ifndef QT_NO_DRAGANDDROP @@ -1496,19 +1490,20 @@ void QListView::updateGeometries() // if the scroll bars are turned off, we resize the contents to the viewport if (d->movement == Static && !d->isWrapping()) { - d->layoutChildren(); // we need the viewport size to be updated + const QSize maxSize = maximumViewportSize(); if (d->flow == TopToBottom) { if (horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOff) { - d->setContentsSize(viewport()->width(), contentsSize().height()); + d->setContentsSize(maxSize.width(), contentsSize().height()); horizontalScrollBar()->setRange(0, 0); // we see all the contents anyway } } else { // LeftToRight if (verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOff) { - d->setContentsSize(contentsSize().width(), viewport()->height()); + d->setContentsSize(contentsSize().width(), maxSize.height()); verticalScrollBar()->setRange(0, 0); // we see all the contents anyway } } } + } /*! @@ -1833,6 +1828,14 @@ QAbstractItemView::DropIndicatorPosition QListViewPrivate::position(const QPoint else return QAbstractItemViewPrivate::position(pos, rect, idx); } + +bool QListViewPrivate::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QModelIndex *dropIndex) +{ + if (viewMode == QListView::ListMode && flow == QListView::LeftToRight) + return static_cast<QListModeViewBase *>(commonListView)->dropOn(event, dropRow, dropCol, dropIndex); + else + return QAbstractItemViewPrivate::dropOn(event, dropRow, dropCol, dropIndex); +} #endif /* @@ -1841,12 +1844,12 @@ QAbstractItemView::DropIndicatorPosition QListViewPrivate::position(const QPoint void QCommonListViewBase::appendHiddenRow(int row) { - dd->hiddenRows.append(dd->model->index(row, 0, qq->rootIndex())); + dd->hiddenRows.insert(dd->model->index(row, 0, qq->rootIndex())); } void QCommonListViewBase::removeHiddenRow(int row) { - dd->hiddenRows.remove(dd->hiddenRows.indexOf(dd->model->index(row, 0, qq->rootIndex()))); + dd->hiddenRows.remove(dd->model->index(row, 0, qq->rootIndex())); } void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step) @@ -1960,7 +1963,13 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) // ignore by default event->ignore(); - QModelIndex index = qq->indexAt(event->pos()); + // can't use indexAt, doesn't account for spacing. + QPoint p = event->pos(); + QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1); + rect.adjust(-dd->spacing(), -dd->spacing(), dd->spacing(), dd->spacing()); + const QVector<QModelIndex> intersectVector = dd->intersectingSet(rect); + QModelIndex index = intersectVector.count() > 0 + ? intersectVector.last() : QModelIndex(); dd->hover = index; if (!dd->droppingOnItself(event, index) && dd->canDecode(event)) { @@ -1968,10 +1977,11 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) if (index.isValid() && dd->showDropIndicator) { QRect rect = qq->visualRect(index); dd->dropIndicatorPosition = position(event->pos(), rect, index); + // if spacing, should try to draw between items, not just next to item. switch (dd->dropIndicatorPosition) { case QAbstractItemView::AboveItem: if (dd->isIndexDropEnabled(index.parent())) { - dd->dropIndicatorRect = QRect(rect.left(), rect.top(), 0, rect.height()); + dd->dropIndicatorRect = QRect(rect.left()-dd->spacing(), rect.top(), 0, rect.height()); event->accept(); } else { dd->dropIndicatorRect = QRect(); @@ -1979,7 +1989,7 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) break; case QAbstractItemView::BelowItem: if (dd->isIndexDropEnabled(index.parent())) { - dd->dropIndicatorRect = QRect(rect.right(), rect.top(), 0, rect.height()); + dd->dropIndicatorRect = QRect(rect.right()+dd->spacing(), rect.top(), 0, rect.height()); event->accept(); } else { dd->dropIndicatorRect = QRect(); @@ -2014,6 +2024,68 @@ void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) qq->startAutoScroll(); } +/*! + If the event hasn't already been accepted, determines the index to drop on. + + if (row == -1 && col == -1) + // append to this drop index + else + // place at row, col in drop index + + If it returns true a drop can be done, and dropRow, dropCol and dropIndex reflects the position of the drop. + \internal + */ +bool QListModeViewBase::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QModelIndex *dropIndex) +{ + if (event->isAccepted()) + return false; + + QModelIndex index; + if (dd->viewport->rect().contains(event->pos())) { + // can't use indexAt, doesn't account for spacing. + QPoint p = event->pos(); + QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1); + rect.adjust(-dd->spacing(), -dd->spacing(), dd->spacing(), dd->spacing()); + const QVector<QModelIndex> intersectVector = dd->intersectingSet(rect); + index = intersectVector.count() > 0 + ? intersectVector.last() : QModelIndex(); + if (!index.isValid()) + index = dd->root; + } + + // If we are allowed to do the drop + if (dd->model->supportedDropActions() & event->dropAction()) { + int row = -1; + int col = -1; + if (index != dd->root) { + dd->dropIndicatorPosition = position(event->pos(), qq->visualRect(index), index); + switch (dd->dropIndicatorPosition) { + case QAbstractItemView::AboveItem: + row = index.row(); + col = index.column(); + index = index.parent(); + break; + case QAbstractItemView::BelowItem: + row = index.row() + 1; + col = index.column(); + index = index.parent(); + break; + case QAbstractItemView::OnItem: + case QAbstractItemView::OnViewport: + break; + } + } else { + dd->dropIndicatorPosition = QAbstractItemView::OnViewport; + } + *dropIndex = index; + *dropRow = row; + *dropCol = col; + if (!dd->droppingOnItself(event, index)) + return true; + } + return false; +} + #endif //QT_NO_DRAGANDDROP void QListModeViewBase::updateVerticalScrollBar(const QSize &step) @@ -2107,7 +2179,7 @@ int QListModeViewBase::verticalOffset() const int value = verticalScrollBar()->value(); if (value >= segmentPositions.count()) return 0; - return segmentPositions.at(value); + return segmentPositions.at(value) - spacing(); } } else if (flow() == QListView::TopToBottom && !flowPositions.isEmpty()) { int value = verticalScrollBar()->value(); @@ -2155,14 +2227,14 @@ void QListModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand) if (horizontal && flow() == QListView::TopToBottom && dx != 0) { int currentValue = qBound(0, horizontalValue, max); int previousValue = qBound(0, currentValue + dx, max); - int currentCoordinate = segmentPositions.at(currentValue); - int previousCoordinate = segmentPositions.at(previousValue); + int currentCoordinate = segmentPositions.at(currentValue) - spacing(); + int previousCoordinate = segmentPositions.at(previousValue) - spacing(); dx = previousCoordinate - currentCoordinate; } else if (vertical && flow() == QListView::LeftToRight && dy != 0) { int currentValue = qBound(0, verticalValue, max); int previousValue = qBound(0, currentValue + dy, max); - int currentCoordinate = segmentPositions.at(currentValue); - int previousCoordinate = segmentPositions.at(previousValue); + int currentCoordinate = segmentPositions.at(currentValue) - spacing(); + int previousCoordinate = segmentPositions.at(previousValue) - spacing(); dy = previousCoordinate - currentCoordinate; } } else { @@ -2330,6 +2402,8 @@ void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info) segmentExtents.append(flowPosition); flowPosition = info.spacing + segStartPosition; segPosition += deltaSegPosition; + if (info.wrap) + segPosition += info.spacing; segmentPositions.append(segPosition); segmentStartRows.append(row); deltaSegPosition = 0; diff --git a/src/gui/itemviews/qlistview_p.h b/src/gui/itemviews/qlistview_p.h index bf7657b..1b71131 100644 --- a/src/gui/itemviews/qlistview_p.h +++ b/src/gui/itemviews/qlistview_p.h @@ -237,6 +237,7 @@ public: // WARNING: Plenty of duplicated code from QAbstractItemView{,Private}. QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; void dragMoveEvent(QDragMoveEvent *e); + bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index); #endif private: @@ -364,6 +365,7 @@ public: #ifndef QT_NO_DRAGANDDROP virtual QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; + bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index); #endif inline void setGridSize(const QSize &size) { grid = size; } @@ -376,7 +378,10 @@ public: inline bool isSelectionRectVisible() const { return showElasticBand; } inline QModelIndex modelIndex(int row) const { return model->index(row, column, root); } - inline bool isHidden(int row) const { return hiddenRows.contains(model->index(row, 0, root)); } + inline bool isHidden(int row) const { + QModelIndex idx = model->index(row, 0, root); + return isPersistent(idx) && hiddenRows.contains(idx); + } inline bool isHiddenOrDisabled(int row) const { return isHidden(row) || !isIndexEnabled(modelIndex(row)); } inline void removeCurrentAndDisabled(QVector<QModelIndex> *indexes, const QModelIndex ¤t) const { @@ -430,7 +435,7 @@ public: QBasicTimer batchLayoutTimer; // used for hidden items - QVector<QPersistentModelIndex> hiddenRows; + QSet<QPersistentModelIndex> hiddenRows; int column; bool uniformItemSizes; diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp index dc8d938..fe866e5 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.cpp +++ b/src/gui/itemviews/qsortfilterproxymodel.cpp @@ -362,6 +362,7 @@ QModelIndex QSortFilterProxyModelPrivate::proxy_to_source(const QModelIndex &pro return QModelIndex(); // for now; we may want to be able to set a root index later if (proxy_index.model() != q_func()) { qWarning() << "QSortFilterProxyModel: index from wrong model passed to mapToSource"; + Q_ASSERT(!"QSortFilterProxyModel: index from wrong model passed to mapToSource"); return QModelIndex(); } IndexMap::const_iterator it = index_to_iterator(proxy_index); @@ -379,6 +380,7 @@ QModelIndex QSortFilterProxyModelPrivate::source_to_proxy(const QModelIndex &sou return QModelIndex(); // for now; we may want to be able to set a root index later if (source_index.model() != model) { qWarning() << "QSortFilterProxyModel: index from wrong model passed to mapFromSource"; + Q_ASSERT(!"QSortFilterProxyModel: index from wrong model passed to mapFromSource"); return QModelIndex(); } QModelIndex source_parent = source_index.parent(); diff --git a/src/gui/itemviews/qstringlistmodel.cpp b/src/gui/itemviews/qstringlistmodel.cpp index 8d69ee4..60ff952 100644 --- a/src/gui/itemviews/qstringlistmodel.cpp +++ b/src/gui/itemviews/qstringlistmodel.cpp @@ -290,8 +290,9 @@ QStringList QStringListModel::stringList() const */ void QStringListModel::setStringList(const QStringList &strings) { + emit beginResetModel(); lst = strings; - reset(); + emit endResetModel(); } /*! diff --git a/src/gui/itemviews/qstyleditemdelegate.cpp b/src/gui/itemviews/qstyleditemdelegate.cpp index 880f8ab..9ccfb76 100644 --- a/src/gui/itemviews/qstyleditemdelegate.cpp +++ b/src/gui/itemviews/qstyleditemdelegate.cpp @@ -326,7 +326,7 @@ void QStyledItemDelegate::initStyleOption(QStyleOptionViewItem *option, option->displayAlignment = Qt::Alignment(value.toInt()); value = index.data(Qt::ForegroundRole); - if (qVariantCanConvert<QBrush>(value)) + if (value.canConvert<QBrush>()) option->palette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value)); if (QStyleOptionViewItemV4 *v4 = qstyleoption_cast<QStyleOptionViewItemV4 *>(option)) { @@ -727,7 +727,8 @@ bool QStyledItemDelegate::editorEvent(QEvent *event, // make sure that we have the right event type if ((event->type() == QEvent::MouseButtonRelease) - || (event->type() == QEvent::MouseButtonDblClick)) { + || (event->type() == QEvent::MouseButtonDblClick) + || (event->type() == QEvent::MouseButtonPress)) { QStyleOptionViewItemV4 viewOpt(option); initStyleOption(&viewOpt, index); QRect checkRect = style->subElementRect(QStyle::SE_ItemViewItemCheckIndicator, &viewOpt, widget); @@ -735,8 +736,8 @@ bool QStyledItemDelegate::editorEvent(QEvent *event, if (me->button() != Qt::LeftButton || !checkRect.contains(me->pos())) return false; - // eat the double click events inside the check rect - if (event->type() == QEvent::MouseButtonDblClick) + if ((event->type() == QEvent::MouseButtonPress) + || (event->type() == QEvent::MouseButtonDblClick)) return true; } else if (event->type() == QEvent::KeyPress) { diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp index 4492e53..d8fef55 100644 --- a/src/gui/itemviews/qtableview.cpp +++ b/src/gui/itemviews/qtableview.cpp @@ -926,14 +926,7 @@ void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItemV4 q->style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, q); - if (const QWidget *widget = editorForIndex(index).editor) { - painter->save(); - painter->setClipRect(widget->geometry()); - q->itemDelegate(index)->paint(painter, opt, index); - painter->restore(); - } else { - q->itemDelegate(index)->paint(painter, opt, index); - } + q->itemDelegate(index)->paint(painter, opt, index); } /*! @@ -2166,7 +2159,7 @@ int QTableView::sizeHintForRow(int row) const option.rect.setWidth(columnWidth(index.column())); } - QWidget *editor = d->editorForIndex(index).editor; + QWidget *editor = d->editorForIndex(index).widget.data(); if (editor && d->persistent.contains(editor)) { hint = qMax(hint, editor->sizeHint().height()); int min = editor->minimumSize().height(); @@ -2219,7 +2212,7 @@ int QTableView::sizeHintForColumn(int column) const continue; index = d->model->index(logicalRow, column, d->root); - QWidget *editor = d->editorForIndex(index).editor; + QWidget *editor = d->editorForIndex(index).widget.data(); if (editor && d->persistent.contains(editor)) { hint = qMax(hint, editor->sizeHint().width()); int min = editor->minimumSize().width(); diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index 40b51fe..2bbf63b 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -1493,7 +1493,7 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option, // when the row contains an index widget which has focus, // we want to paint the entire row as active bool indexWidgetHasFocus = false; - if ((current.row() == index.row()) && !d->editors.isEmpty()) { + if ((current.row() == index.row()) && !d->editorIndexHash.isEmpty()) { const int r = index.row(); QWidget *fw = QApplication::focusWidget(); for (int c = 0; c < header->count(); ++c) { @@ -1669,14 +1669,7 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option, opt.state = oldState; } - if (const QWidget *widget = d->editorForIndex(modelIndex).editor) { - painter->save(); - painter->setClipRect(widget->geometry()); - d->delegateForIndex(modelIndex)->paint(painter, opt, modelIndex); - painter->restore(); - } else { - d->delegateForIndex(modelIndex)->paint(painter, opt, modelIndex); - } + d->delegateForIndex(modelIndex)->paint(painter, opt, modelIndex); } if (currentRowHasFocus) { @@ -2395,7 +2388,7 @@ void QTreeView::scrollContentsBy(int dx, int dy) int viewCount = d->viewport->height() / itemHeight; int maxDeltaY = qMin(d->viewItems.count(), viewCount); // no need to do a lot of work if we are going to redraw the whole thing anyway - if (qAbs(dy) > qAbs(maxDeltaY) && d->editors.isEmpty()) { + if (qAbs(dy) > qAbs(maxDeltaY) && d->editorIndexHash.isEmpty()) { verticalScrollBar()->update(); d->viewport->update(); return; @@ -2469,11 +2462,9 @@ void QTreeView::rowsInserted(const QModelIndex &parent, int start, int end) } const int parentItem = d->viewIndex(parent); - if (((parentItem != -1) && d->viewItems.at(parentItem).expanded && updatesEnabled()) + if (((parentItem != -1) && d->viewItems.at(parentItem).expanded) || (parent == d->root)) { d->doDelayedItemsLayout(); - } else if ((parentItem != -1) && d->viewItems.at(parentItem).expanded) { - d->doDelayedItemsLayout(); } else if (parentItem != -1 && (d->model->rowCount(parent) == end - start + 1)) { // the parent just went from 0 children to more. update to re-paint the decoration d->viewItems[parentItem].hasChildren = true; @@ -2727,7 +2718,7 @@ int QTreeView::sizeHintForColumn(int column) const continue; // we have no good size hint QModelIndex index = viewItems.at(i).index; index = index.sibling(index.row(), column); - QWidget *editor = d->editorForIndex(index).editor; + QWidget *editor = d->editorForIndex(index).widget.data(); if (editor && d->persistent.contains(editor)) { w = qMax(w, editor->sizeHint().width()); int min = editor->minimumSize().width(); @@ -2791,7 +2782,7 @@ int QTreeView::indexRowSizeHint(const QModelIndex &index) const continue; QModelIndex idx = d->model->index(index.row(), logicalColumn, parent); if (idx.isValid()) { - QWidget *editor = d->editorForIndex(idx).editor; + QWidget *editor = d->editorForIndex(idx).widget.data(); if (editor && d->persistent.contains(editor)) { height = qMax(height, editor->sizeHint().height()); int min = editor->minimumSize().height(); @@ -2870,13 +2861,13 @@ void QTreeViewPrivate::expand(int item, bool emitSignal) if (emitSignal && animationsEnabled) prepareAnimatedOperation(item, QVariantAnimation::Forward); #endif //QT_NO_ANIMATION - QAbstractItemView::State oldState = state; + stateBeforeAnimation = state; q->setState(QAbstractItemView::ExpandingState); const QModelIndex index = viewItems.at(item).index; storeExpanded(index); viewItems[item].expanded = true; layout(item); - q->setState(oldState); + q->setState(stateBeforeAnimation); if (model->canFetchMore(index)) model->fetchMore(index); @@ -2945,7 +2936,7 @@ void QTreeViewPrivate::collapse(int item, bool emitSignal) prepareAnimatedOperation(item, QVariantAnimation::Backward); #endif //QT_NO_ANIMATION - QAbstractItemView::State oldState = state; + stateBeforeAnimation = state; q->setState(QAbstractItemView::CollapsingState); expandedIndexes.erase(it); viewItems[item].expanded = false; @@ -2955,7 +2946,7 @@ void QTreeViewPrivate::collapse(int item, bool emitSignal) index = viewItems[index].parentItem; } removeViewItems(item + 1, total); // collapse - q->setState(oldState); + q->setState(stateBeforeAnimation); if (emitSignal) { emit q->collapsed(modelIndex); @@ -3040,9 +3031,9 @@ QPixmap QTreeViewPrivate::renderTreeToPixmapForAnimation(const QRect &rect) cons //and now let's render the editors the editors QStyleOptionViewItemV4 option = viewOptionsV4(); - for (QList<QEditorInfo>::const_iterator it = editors.constBegin(); it != editors.constEnd(); ++it) { - QWidget *editor = it->editor; - QModelIndex index = it->index; + for (QEditorIndexHash::const_iterator it = editorIndexHash.constBegin(); it != editorIndexHash.constEnd(); ++it) { + QWidget *editor = it.key(); + const QModelIndex &index = it.value(); option.rect = q->visualRect(index); if (option.rect.isValid()) { @@ -3066,7 +3057,7 @@ QPixmap QTreeViewPrivate::renderTreeToPixmapForAnimation(const QRect &rect) cons void QTreeViewPrivate::_q_endAnimatedOperation() { Q_Q(QTreeView); - q->setState(QAbstractItemView::NoState); + q->setState(stateBeforeAnimation); q->updateGeometries(); viewport->update(); } diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index f9c84c1..4261e93 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -32,8 +32,6 @@ HEADERS += \ kernel/qshortcutmap_p.h \ kernel/qsizepolicy.h \ kernel/qpalette.h \ - kernel/qsound.h \ - kernel/qsound_p.h \ kernel/qstackedlayout.h \ kernel/qtooltip.h \ kernel/qwhatsthis.h \ @@ -50,7 +48,7 @@ HEADERS += \ kernel/qgesturemanager_p.h \ kernel/qsoftkeymanager_p.h \ kernel/qsoftkeymanager_common_p.h \ - kernel/qguiplatformplugin_p.h + kernel/qguiplatformplugin_p.h \ SOURCES += \ kernel/qaction.cpp \ @@ -72,7 +70,6 @@ SOURCES += \ kernel/qpalette.cpp \ kernel/qshortcut.cpp \ kernel/qshortcutmap.cpp \ - kernel/qsound.cpp \ kernel/qstackedlayout.cpp \ kernel/qtooltip.cpp \ kernel/qguivariant.cpp \ @@ -200,7 +197,66 @@ embedded { } } -!embedded:!x11:mac { +!qpa { + HEADERS += \ + kernel/qsound.h \ + kernel/qsound_p.h + + SOURCES += \ + kernel/qsound.cpp +} + +qpa { + HEADERS += \ + kernel/qgenericpluginfactory_qpa.h \ + kernel/qgenericplugin_qpa.h \ + kernel/qeventdispatcher_qpa_p.h \ + kernel/qwindowsysteminterface_qpa.h \ + kernel/qwindowsysteminterface_qpa_p.h \ + kernel/qplatformintegration_qpa.h \ + kernel/qplatformscreen_qpa.h \ + kernel/qplatformintegrationfactory_qpa_p.h \ + kernel/qplatformintegrationplugin_qpa.h \ + kernel/qplatformwindow_qpa.h \ + kernel/qplatformwindowformat_qpa.h \ + kernel/qplatformglcontext_qpa.h \ + kernel/qdesktopwidget_qpa_p.h \ + kernel/qplatformeventloopintegration_qpa.h \ + kernel/qplatformcursor_qpa.h + + SOURCES += \ + kernel/qapplication_qpa.cpp \ + kernel/qclipboard_qpa.cpp \ + kernel/qcursor_qpa.cpp \ + kernel/qdnd_qws.cpp \ + kernel/qdesktopwidget_qpa.cpp \ + kernel/qgenericpluginfactory_qpa.cpp \ + kernel/qgenericplugin_qpa.cpp \ + kernel/qkeymapper_qws.cpp \ + kernel/qwidget_qpa.cpp \ + kernel/qeventdispatcher_qpa.cpp \ + kernel/qwindowsysteminterface_qpa.cpp \ + kernel/qplatformintegration_qpa.cpp \ + kernel/qplatformscreen_qpa.cpp \ + kernel/qplatformintegrationfactory_qpa.cpp \ + kernel/qplatformintegrationplugin_qpa.cpp \ + kernel/qplatformwindow_qpa.cpp \ + kernel/qplatformwindowformat_qpa.cpp \ + kernel/qplatformeventloopintegration_qpa.cpp \ + kernel/qplatformglcontext_qpa.cpp \ + kernel/qplatformcursor_qpa.cpp + + contains(QT_CONFIG, glib) { + SOURCES += \ + kernel/qeventdispatcher_glib_qpa.cpp + HEADERS += \ + kernel/qeventdispatcher_glib_qpa_p.h + QMAKE_CXXFLAGS += $$QT_CFLAGS_GLIB + LIBS_PRIVATE +=$$QT_LIBS_GLIB + } +} + +!embedded:!qpa:!x11:mac { SOURCES += \ kernel/qclipboard_mac.cpp \ kernel/qmime_mac.cpp \ @@ -216,7 +272,8 @@ embedded { qcocoaapplicationdelegate_mac_p.h \ qmacgesturerecognizer_mac_p.h \ qmultitouch_mac_p.h \ - qcocoasharedwindowmethods_mac_p.h + qcocoasharedwindowmethods_mac_p.h \ + qcocoaintrospection_p.h OBJECTIVE_SOURCES += \ kernel/qcursor_mac.mm \ @@ -236,7 +293,8 @@ embedded { kernel/qeventdispatcher_mac.mm \ kernel/qcocoawindowcustomthemeframe_mac.mm \ kernel/qmacgesturerecognizer_mac.mm \ - kernel/qmultitouch_mac.mm + kernel/qmultitouch_mac.mm \ + kernel/qcocoaintrospection_mac.mm HEADERS += \ kernel/qt_cocoa_helpers_mac_p.h \ diff --git a/src/gui/kernel/mac.pri b/src/gui/kernel/mac.pri index 1538510..21acd06 100644 --- a/src/gui/kernel/mac.pri +++ b/src/gui/kernel/mac.pri @@ -1,4 +1,4 @@ -!x11:!embedded:mac { +!x11:!embedded:!qpa:mac { LIBS_PRIVATE += -framework Carbon -lz *-mwerks:INCLUDEPATH += compat } diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index a4ae46b..833e803 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -153,8 +153,6 @@ QT_BEGIN_NAMESPACE Q_CORE_EXPORT void qt_call_post_routines(); -int QApplicationPrivate::app_compile_version = 0x040000; //we don't know exactly, but it's at least 4.0.0 - QApplication::Type qt_appType=QApplication::Tty; QApplicationPrivate *QApplicationPrivate::self = 0; @@ -169,8 +167,8 @@ bool QApplicationPrivate::autoSipEnabled = false; bool QApplicationPrivate::autoSipEnabled = true; #endif -QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type) - : QCoreApplicationPrivate(argc, argv) +QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type, int flags) + : QCoreApplicationPrivate(argc, argv, flags) { application_type = type; qt_appType = type; @@ -452,6 +450,9 @@ QPalette *QApplicationPrivate::sys_pal = 0; // default system palette QPalette *QApplicationPrivate::set_pal = 0; // default palette set by programmer QGraphicsSystem *QApplicationPrivate::graphics_system = 0; // default graphics system +#if defined(Q_WS_QPA) +QPlatformIntegration *QApplicationPrivate::platform_integration = 0; +#endif QString QApplicationPrivate::graphics_system_name; // graphics system id - for delayed initialization bool QApplicationPrivate::runtime_graphics_system = false; @@ -514,7 +515,7 @@ inline bool QApplicationPrivate::isAlien(QWidget *widget) { if (!widget) return false; -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) return !widget->isWindow() # ifdef Q_BACKINGSTORE_SUBSURFACES && !(widget->d_func()->maybeTopData() && widget->d_func()->maybeTopData()->windowSurface) @@ -724,12 +725,12 @@ void QApplicationPrivate::process_cmdline() */ QApplication::QApplication(int &argc, char **argv) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, 0x040000)) { Q_D(QApplication); d->construct(); } QApplication::QApplication(int &argc, char **argv, int _internal) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) -{ Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;} + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, _internal)) +{ Q_D(QApplication); d->construct(); } /*! @@ -758,12 +759,12 @@ QApplication::QApplication(int &argc, char **argv, int _internal) */ QApplication::QApplication(int &argc, char **argv, bool GUIenabled ) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty, 0x040000)) { Q_D(QApplication); d->construct(); } QApplication::QApplication(int &argc, char **argv, bool GUIenabled , int _internal) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty)) -{ Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;} + : QCoreApplication(*new QApplicationPrivate(argc, argv, GUIenabled ? GuiClient : Tty, _internal)) +{ Q_D(QApplication); d->construct();} @@ -781,12 +782,12 @@ QApplication::QApplication(int &argc, char **argv, bool GUIenabled , int _intern \c -qws option). */ QApplication::QApplication(int &argc, char **argv, Type type) - : QCoreApplication(*new QApplicationPrivate(argc, argv, type)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, type, 0x040000)) { Q_D(QApplication); d->construct(); } QApplication::QApplication(int &argc, char **argv, Type type , int _internal) - : QCoreApplication(*new QApplicationPrivate(argc, argv, type)) -{ Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;} + : QCoreApplication(*new QApplicationPrivate(argc, argv, type, _internal)) +{ Q_D(QApplication); d->construct(); } #if defined(Q_WS_X11) && !defined(QT_NO_EGL) static int qt_matchLibraryName(dl_phdr_info *info, size_t, void *data) @@ -806,6 +807,7 @@ void QApplicationPrivate::construct( ) { initResources(); + graphics_system_name = QLatin1String(qgetenv("QT_DEFAULT_GRAPHICS_SYSTEM")); qt_is_gui_used = (qt_appType != QApplication::Tty); process_cmdline(); @@ -892,7 +894,7 @@ static char *aargv[] = { (char*)"unknown", 0 }; This function is only available on X11. */ QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap) - : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient, 0x040000)) { if (! dpy) qWarning("QApplication: Invalid Display* argument"); @@ -901,7 +903,7 @@ QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap) } QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap, int _internal) - : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(aargc, aargv, GuiClient, _internal)) { if (! dpy) qWarning("QApplication: Invalid Display* argument"); @@ -926,7 +928,7 @@ QApplication::QApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap, */ QApplication::QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE colormap) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, 0x040000)) { if (! dpy) qWarning("QApplication: Invalid Display* argument"); @@ -936,7 +938,7 @@ QApplication::QApplication(Display *dpy, int &argc, char **argv, QApplication::QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE colormap, int _internal) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, _internal)) { if (! dpy) qWarning("QApplication: Invalid Display* argument"); @@ -966,10 +968,11 @@ void QApplicationPrivate::initialize() QWidgetPrivate::mapper = new QWidgetMapper; QWidgetPrivate::allWidgets = new QWidgetSet; -#if !defined(Q_WS_X11) && !defined(Q_WS_QWS) +#if !defined(Q_WS_X11) && !defined(Q_WS_QWS) && !defined(Q_WS_QPA) // initialize the graphics system - on X11 this is initialized inside // qt_init() in qapplication_x11.cpp because of several reasons. // On QWS, the graphics system is set by the QScreen plugin. + // We don't use graphics systems in Qt QPA graphics_system = QGraphicsSystemFactory::create(graphics_system_name); #endif @@ -1643,14 +1646,18 @@ QStyle* QApplication::setStyle(const QString& style) void QApplication::setGraphicsSystem(const QString &system) { -#ifdef QT_GRAPHICSSYSTEM_RUNTIME +#ifdef Q_WS_QPA + Q_UNUSED(system); +#else +# ifdef QT_GRAPHICSSYSTEM_RUNTIME if (QApplicationPrivate::graphics_system_name == QLatin1String("runtime")) { QRuntimeGraphicsSystem *r = static_cast<QRuntimeGraphicsSystem *>(QApplicationPrivate::graphics_system); r->setGraphicsSystem(system); } else -#endif +# endif QApplicationPrivate::graphics_system_name = system; +#endif } /*! @@ -2796,7 +2803,7 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) { // Update cursor for alien/graphics widgets. const bool enterOnAlien = (enter && (isAlien(enter) || enter->testAttribute(Qt::WA_DontShowOnScreen))); -#if defined(Q_WS_X11) +#if defined(Q_WS_X11) || defined(Q_WS_QPA) //Whenever we leave an alien widget on X11, we need to reset its nativeParentWidget()'s cursor. // This is not required on Windows as the cursor is reset on every single mouse move. QWidget *parentOfLeavingCursor = 0; @@ -2820,7 +2827,15 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) { if (!parentOfLeavingCursor->window()->graphicsProxyWidget()) #endif { +#if defined(Q_WS_X11) qt_x11_enforce_cursor(parentOfLeavingCursor,true); +#elif defined(Q_WS_QPA) + if (enter == QApplication::desktop()) { + qt_qpa_set_cursor(enter, true); + } else { + qt_qpa_set_cursor(parentOfLeavingCursor, true); + } +#endif } } #endif @@ -2844,6 +2859,8 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) { qt_x11_enforce_cursor(cursorWidget, true); #elif defined(Q_OS_SYMBIAN) qt_symbian_set_cursor(cursorWidget, true); +#elif defined(Q_WS_QPA) + qt_qpa_set_cursor(cursorWidget, true); #endif } } @@ -3148,7 +3165,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, return result; } -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_MAC) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA) /* This function should only be called when the widget changes visibility, i.e. when the \a widget is shown, hidden or deleted. This function does nothing @@ -3160,7 +3177,7 @@ extern QWidget *qt_button_down; void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget) { #ifndef QT_NO_CURSOR -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) if (!widget || widget->isWindow()) return; #else @@ -3754,11 +3771,6 @@ bool QApplication::notify(QObject *receiver, QEvent *e) d->checkReceiverThread(receiver); #endif -#ifdef QT3_SUPPORT - if (e->type() == QEvent::ChildRemoved && !receiver->d_func()->pendingChildInsertedEvents.isEmpty()) - receiver->d_func()->removePendingChildInsertedEvents(static_cast<QChildEvent *>(e)->child()); -#endif // QT3_SUPPORT - // capture the current mouse/keyboard state if(e->spontaneous()) { if (e->type() == QEvent::KeyPress @@ -5861,12 +5873,12 @@ Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window, #ifndef QT_NO_GESTURES QGestureManager* QGestureManager::instance() { - if (QApplicationPrivate *qAppPriv = QApplicationPrivate::instance()) { - if (!qAppPriv->gestureManager) - qAppPriv->gestureManager = new QGestureManager(qApp); - return qAppPriv->gestureManager; - } - return 0; + QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); + if (!qAppPriv) + return 0; + if (!qAppPriv->gestureManager) + qAppPriv->gestureManager = new QGestureManager(qApp); + return qAppPriv->gestureManager; } #endif // QT_NO_GESTURES @@ -6090,6 +6102,8 @@ QPixmap QApplicationPrivate::getPixmapCursor(Qt::CursorShape cshape) default: break; } +#else + Q_UNUSED(cshape); #endif return QPixmap(); } diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h index 0242582..a790c69 100644 --- a/src/gui/kernel/qapplication.h +++ b/src/gui/kernel/qapplication.h @@ -123,15 +123,15 @@ public: #endif #ifndef qdoc - QApplication(int &argc, char **argv, int = QT_VERSION); - QApplication(int &argc, char **argv, bool GUIenabled, int = QT_VERSION); - QApplication(int &argc, char **argv, Type, int = QT_VERSION); + QApplication(int &argc, char **argv, int = ApplicationFlags); + QApplication(int &argc, char **argv, bool GUIenabled, int = ApplicationFlags); + QApplication(int &argc, char **argv, Type, int = ApplicationFlags); #if defined(Q_WS_X11) - QApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0, int = QT_VERSION); - QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0, int = QT_VERSION); + QApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0, int = ApplicationFlags); + QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0, int = ApplicationFlags); #endif #if defined(Q_OS_SYMBIAN) - QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int = QT_VERSION); + QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int = ApplicationFlags); #endif #endif virtual ~QApplication(); diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index dd819e5..e5364d0 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -1243,8 +1243,10 @@ void qt_init(QApplicationPrivate *priv, int) // Cocoa application delegate #ifdef QT_MAC_USE_COCOA NSApplication *cocoaApp = [QNSApplication sharedApplication]; + qt_redirectNSApplicationSendEvent(); + QMacCocoaAutoReleasePool pool; - NSObject *oldDelegate = [cocoaApp delegate]; + id oldDelegate = [cocoaApp delegate]; QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate]; Q_ASSERT(newDelegate); [newDelegate setQtPrivate:priv]; @@ -2608,25 +2610,26 @@ OSStatus QApplicationPrivate::globalAppleEventProcessor(const AppleEvent *ae, Ap /*! \fn bool QApplication::macEventFilter(EventHandlerCallRef caller, EventRef event) - \warning This virtual function is only implemented under Mac OS X when against Carbon. + \warning This virtual function is only used under Mac OS X, and behaves different + depending on if Qt is based on Carbon or Cocoa. - If you create an application that inherits QApplication and reimplement + For the Carbon port, If you create an application that inherits QApplication and reimplement this function, you get direct access to all Carbon Events that Qt registers for from Mac OS X with this function being called with the \a caller and the \a event. + For the Cocoa port, If you create an application that inherits QApplication and reimplement + this function, you get direct access to all Cocoa Events that Qt receives + from Mac OS X with this function being called with the \a caller being 0 and + the \a event being an NSEvent pointer: + + NSEvent *e = reinterpret_cast<NSEvent *>(event); + Return true if you want to stop the event from being processed. Return false for normal event dispatching. The default implementation returns false. - Cocoa uses a different event system which means this function is NOT CALLED - when building Qt against Cocoa. If you want similar functionality subclass - NSApplication and reimplement the sendEvent: message to handle all the - NSEvents. You also will need to to instantiate your custom NSApplication - before creating a QApplication. See \l - {http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/Reference/Reference.html}{Apple's - NSApplication Reference} for more information. - + \sa macEventFilter(void *nsevent) */ bool QApplication::macEventFilter(EventHandlerCallRef, EventRef) { @@ -3107,11 +3110,7 @@ void onApplicationChangedActivation( bool activated ) } if (!app->activeWindow()) { -#if QT_MAC_USE_COCOA - OSWindowRef wp = [NSApp keyWindow]; -#else - OSWindowRef wp = ActiveNonFloatingWindow(); -#endif + OSWindowRef wp = [NSApp keyWindow]; if (QWidget *tmp_w = qt_mac_find_window(wp)) app->setActiveWindow(tmp_w); } diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index a0e1452..7b49999 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -65,8 +65,10 @@ #include "QtCore/qhash.h" #include "QtCore/qpointer.h" #include "private/qcoreapplication_p.h" -#include "private/qshortcutmap_p.h" +#include "QtGui/private/qshortcutmap_p.h" #include <private/qthread_p.h> +#include "QtCore/qpoint.h" +#include <QTime> #ifdef Q_WS_QWS #include "QtGui/qscreen_qws.h" #include <private/qgraphicssystem_qws_p.h> @@ -74,6 +76,11 @@ #ifdef Q_OS_SYMBIAN #include <w32std.h> #endif +#ifdef Q_WS_QPA +#include <QWindowSystemInterface> +#include "qwindowsysteminterface_qpa_p.h" +#include "QtGui/qplatformintegration_qpa.h" +#endif QT_BEGIN_NAMESPACE @@ -291,7 +298,7 @@ class Q_GUI_EXPORT QApplicationPrivate : public QCoreApplicationPrivate { Q_DECLARE_PUBLIC(QApplication) public: - QApplicationPrivate(int &argc, char **argv, QApplication::Type type); + QApplicationPrivate(int &argc, char **argv, QApplication::Type type, int flags); ~QApplicationPrivate(); #if defined(Q_WS_X11) @@ -312,10 +319,18 @@ public: static QString desktopStyleKey(); static QGraphicsSystem *graphicsSystem() -#if !defined(Q_WS_QWS) - { return graphics_system; } -#else +#if defined(Q_WS_QWS) { return QScreen::instance()->graphicsSystem(); } +#else + { return graphics_system; } +#endif + +#if defined(Q_WS_QPA) + static QPlatformIntegration *platformIntegration() + { return platform_integration; } + + static QAbstractEventDispatcher *qt_qpa_core_dispatcher() + { return QCoreApplication::instance()->d_func()->threadData->eventDispatcher; } #endif void createEventDispatcher(); @@ -418,6 +433,9 @@ public: static QGraphicsSystem *graphics_system; static QString graphics_system_name; static bool runtime_graphics_system; +#ifdef Q_WS_QPA + static QPlatformIntegration *platform_integration; +#endif private: static QFont *app_font; // private for a reason! Always use QApplication::font() instead! @@ -477,6 +495,30 @@ public: static bool qt_mac_apply_settings(); #endif +#ifdef Q_WS_QPA + static void processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent *e); + static void processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent *e); + static void processWheelEvent(QWindowSystemInterfacePrivate::WheelEvent *e); + static void processTouchEvent(QWindowSystemInterfacePrivate::TouchEvent *e); + + static void processCloseEvent(QWindowSystemInterfacePrivate::CloseEvent *e); + + static void processGeometryChangeEvent(QWindowSystemInterfacePrivate::GeometryChangeEvent *e); + + static void processEnterEvent(QWindowSystemInterfacePrivate::EnterEvent *e); + static void processLeaveEvent(QWindowSystemInterfacePrivate::LeaveEvent *e); + + static void processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e); + +// static void reportScreenCount(int count); + static void reportScreenCount(QWindowSystemInterfacePrivate::ScreenCountEvent *e); +// static void reportGeometryChange(int screenIndex); + static void reportGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent *e); +// static void reportAvailableGeometryChange(int screenIndex); + static void reportAvailableGeometryChange(QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e); + +#endif + #ifdef Q_WS_QWS QPointer<QWSManager> last_manager; QWSServerCleaner qwsServerCleaner; @@ -492,8 +534,6 @@ public: static QString styleOverride; - static int app_compile_version; - #ifdef QT_KEYPAD_NAVIGATION static QWidget *oldEditFocus; static Qt::NavigationMode navigationMode; @@ -524,7 +564,7 @@ public: void _q_aboutToQuit(); #endif -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA) void sendSyntheticEnterLeave(QWidget *widget); #endif @@ -632,6 +672,8 @@ Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window, extern void qt_x11_enforce_cursor(QWidget *); #elif defined(Q_OS_SYMBIAN) extern void qt_symbian_set_cursor(QWidget *, bool); +#elif defined (Q_WS_QPA) + extern void qt_qpa_set_cursor(QWidget *, bool); #endif QT_END_NAMESPACE diff --git a/src/gui/kernel/qapplication_qpa.cpp b/src/gui/kernel/qapplication_qpa.cpp new file mode 100644 index 0000000..ece035c --- /dev/null +++ b/src/gui/kernel/qapplication_qpa.cpp @@ -0,0 +1,928 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qapplication_p.h" +#include "qcolormap.h" +#include "qpixmapcache.h" +#if !defined(QT_NO_GLIB) +#include "qeventdispatcher_glib_qpa_p.h" +#endif +#include "qeventdispatcher_qpa_p.h" +#ifndef QT_NO_CURSOR +#include "private/qcursor_p.h" +#endif + +#include "private/qwidget_p.h" + +#include "qgenericpluginfactory_qpa.h" +#include "qplatformintegrationfactory_qpa_p.h" +#include <qdesktopwidget.h> + +#include <qinputcontext.h> +#include <QPlatformCursor> +#include <qdebug.h> +#include <QWindowSystemInterface> +#include "qwindowsysteminterface_qpa_p.h" +#include <QPlatformIntegration> + +#include "qdesktopwidget_qpa_p.h" + +QT_BEGIN_NAMESPACE + +static QString appName; +static QString appFont; + +QWidget *qt_button_down = 0; // widget got last button-down + +static bool app_do_modal = false; +extern QWidgetList *qt_modal_stack; // stack of modal widgets + +int qt_last_x = 0; +int qt_last_y = 0; +QPointer<QWidget> qt_last_mouse_receiver = 0; + +static Qt::KeyboardModifiers modifiers = Qt::NoModifier; +static Qt::MouseButtons buttons = Qt::NoButton; +static ulong mousePressTime; +static Qt::MouseButton mousePressButton = Qt::NoButton; +static int mousePressX; +static int mousePressY; +static int mouse_double_click_distance = 5; + +void QApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e) +{ + switch(e->type) { + case QWindowSystemInterfacePrivate::Mouse: + QApplicationPrivate::processMouseEvent(static_cast<QWindowSystemInterfacePrivate::MouseEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::Wheel: + QApplicationPrivate::processWheelEvent(static_cast<QWindowSystemInterfacePrivate::WheelEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::Key: + QApplicationPrivate::processKeyEvent(static_cast<QWindowSystemInterfacePrivate::KeyEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::Touch: + QApplicationPrivate::processTouchEvent(static_cast<QWindowSystemInterfacePrivate::TouchEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::GeometryChange: + QApplicationPrivate::processGeometryChangeEvent(static_cast<QWindowSystemInterfacePrivate::GeometryChangeEvent*>(e)); + break; + case QWindowSystemInterfacePrivate::Enter: + QApplicationPrivate::processEnterEvent(static_cast<QWindowSystemInterfacePrivate::EnterEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::Leave: + QApplicationPrivate::processLeaveEvent(static_cast<QWindowSystemInterfacePrivate::LeaveEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::Close: + QApplicationPrivate::processCloseEvent( + static_cast<QWindowSystemInterfacePrivate::CloseEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::ScreenCountChange: + QApplicationPrivate::reportScreenCount( + static_cast<QWindowSystemInterfacePrivate::ScreenCountEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::ScreenGeometry: + QApplicationPrivate::reportGeometryChange( + static_cast<QWindowSystemInterfacePrivate::ScreenGeometryEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::ScreenAvailableGeometry: + QApplicationPrivate::reportAvailableGeometryChange( + static_cast<QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *>(e)); + break; + default: + qWarning() << "Unknown user input event type:" << e->type; + break; + } +} + +QString QApplicationPrivate::appName() const +{ + return QT_PREPEND_NAMESPACE(appName); +} + +void QApplicationPrivate::createEventDispatcher() +{ + Q_Q(QApplication); +#if !defined(QT_NO_GLIB) + if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported()) + eventDispatcher = new QPAEventDispatcherGlib(q); + else +#endif + eventDispatcher = new QEventDispatcherQPA(q); +} + +static bool qt_try_modal(QWidget *widget, QEvent::Type type) +{ + QWidget * top = 0; + + if (QApplicationPrivate::tryModalHelper(widget, &top)) + return true; + + bool block_event = false; + bool paint_event = false; + + switch (type) { +#if 0 + case QEvent::Focus: + if (!static_cast<QWSFocusEvent*>(event)->simpleData.get_focus) + break; + // drop through +#endif + case QEvent::MouseButtonPress: // disallow mouse/key events + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + case QEvent::KeyPress: + case QEvent::KeyRelease: + block_event = true; + break; + default: + break; + } + + if ((block_event || paint_event) && top->parentWidget() == 0) + top->raise(); + + return !block_event; +} + + + +void QApplicationPrivate::enterModal_sys(QWidget *widget) +{ + if (!qt_modal_stack) + qt_modal_stack = new QWidgetList; + qt_modal_stack->insert(0, widget); + app_do_modal = true; +} + +void QApplicationPrivate::leaveModal_sys(QWidget *widget ) +{ + if (qt_modal_stack && qt_modal_stack->removeAll(widget)) { + if (qt_modal_stack->isEmpty()) { + delete qt_modal_stack; + qt_modal_stack = 0; + } + } + app_do_modal = qt_modal_stack != 0; +} + +bool QApplicationPrivate::modalState() +{ + return app_do_modal; +} + +void QApplicationPrivate::closePopup(QWidget *popup) +{ + Q_Q(QApplication); + if (!popupWidgets) + return; + popupWidgets->removeAll(popup); + +//### +// if (popup == qt_popup_down) { +// qt_button_down = 0; +// qt_popup_down = 0; +// } + + if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup + delete QApplicationPrivate::popupWidgets; + QApplicationPrivate::popupWidgets = 0; + + //### replay mouse event? + + //### transfer/release mouse grab + + //### transfer/release keyboard grab + + //give back focus + + if (active_window) { + if (QWidget *fw = active_window->focusWidget()) { + if (fw != QApplication::focusWidget()) { + fw->setFocus(Qt::PopupFocusReason); + } else { + QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason); + q->sendEvent(fw, &e); + } + } + } + + } else { + // A popup was closed, so the previous popup gets the focus. + + QWidget* aw = QApplicationPrivate::popupWidgets->last(); + if (QWidget *fw = aw->focusWidget()) + fw->setFocus(Qt::PopupFocusReason); + + //### regrab the keyboard and mouse in case 'popup' lost the grab + + + } + +} + +static int openPopupCount = 0; +void QApplicationPrivate::openPopup(QWidget *popup) +{ + openPopupCount++; + if (!popupWidgets) { // create list + popupWidgets = new QWidgetList; + + /* only grab if you are the first/parent popup */ + //#### ->grabMouse(popup,true); + //#### ->grabKeyboard(popup,true); + //### popupGrabOk = true; + } + popupWidgets->append(popup); // add to end of list + + // popups are not focus-handled by the window system (the first + // popup grabbed the keyboard), so we have to do that manually: A + // new popup gets the focus + if (popup->focusWidget()) { + popup->focusWidget()->setFocus(Qt::PopupFocusReason); + } else if (popupWidgets->count() == 1) { // this was the first popup + if (QWidget *fw = QApplication::focusWidget()) { + QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason); + QApplication::sendEvent(fw, &e); + } + } +} + +void QApplicationPrivate::initializeMultitouch_sys() +{ +} + +void QApplicationPrivate::cleanupMultitouch_sys() +{ +} + +void QApplicationPrivate::initializeWidgetPaletteHash() +{ +} + +void QApplication::setCursorFlashTime(int msecs) +{ + QApplicationPrivate::cursor_flash_time = msecs; +} + +int QApplication::cursorFlashTime() +{ + return QApplicationPrivate::cursor_flash_time; +} + +void QApplication::setDoubleClickInterval(int ms) +{ + QApplicationPrivate::mouse_double_click_time = ms; +} + +int QApplication::doubleClickInterval() +{ + return QApplicationPrivate::mouse_double_click_time; +} + +void QApplication::setKeyboardInputInterval(int ms) +{ + QApplicationPrivate::keyboard_input_time = ms; +} + +int QApplication::keyboardInputInterval() +{ + return QApplicationPrivate::keyboard_input_time; +} + +#ifndef QT_NO_WHEELEVENT +void QApplication::setWheelScrollLines(int lines) +{ + QApplicationPrivate::wheel_scroll_lines = lines; +} + +int QApplication::wheelScrollLines() +{ + return QApplicationPrivate::wheel_scroll_lines; +} +#endif + +void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable) +{ + switch (effect) { + case Qt::UI_AnimateMenu: + QApplicationPrivate::animate_menu = enable; + break; + case Qt::UI_FadeMenu: + if (enable) + QApplicationPrivate::animate_menu = true; + QApplicationPrivate::fade_menu = enable; + break; + case Qt::UI_AnimateCombo: + QApplicationPrivate::animate_combo = enable; + break; + case Qt::UI_AnimateTooltip: + QApplicationPrivate::animate_tooltip = enable; + break; + case Qt::UI_FadeTooltip: + if (enable) + QApplicationPrivate::animate_tooltip = true; + QApplicationPrivate::fade_tooltip = enable; + break; + case Qt::UI_AnimateToolBox: + QApplicationPrivate::animate_toolbox = enable; + break; + default: + QApplicationPrivate::animate_ui = enable; + break; + } +} + +bool QApplication::isEffectEnabled(Qt::UIEffect effect) +{ + if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui) + return false; + + switch(effect) { + case Qt::UI_AnimateMenu: + return QApplicationPrivate::animate_menu; + case Qt::UI_FadeMenu: + return QApplicationPrivate::fade_menu; + case Qt::UI_AnimateCombo: + return QApplicationPrivate::animate_combo; + case Qt::UI_AnimateTooltip: + return QApplicationPrivate::animate_tooltip; + case Qt::UI_FadeTooltip: + return QApplicationPrivate::fade_tooltip; + case Qt::UI_AnimateToolBox: + return QApplicationPrivate::animate_toolbox; + default: + return QApplicationPrivate::animate_ui; + } +} + +#ifndef QT_NO_CURSOR +void QApplication::setOverrideCursor(const QCursor &cursor) +{ + qApp->d_func()->cursor_list.prepend(cursor); + qt_qpa_set_cursor(0, false); +} + +void QApplication::restoreOverrideCursor() +{ + if (qApp->d_func()->cursor_list.isEmpty()) + return; + qApp->d_func()->cursor_list.removeFirst(); + qt_qpa_set_cursor(0, false); +} + +#endif// QT_NO_CURSOR + +QWidget *QApplication::topLevelAt(const QPoint &pos) +{ + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + + QList<QPlatformScreen *> screens = pi->screens(); + QList<QPlatformScreen *>::const_iterator screen = screens.constBegin(); + QList<QPlatformScreen *>::const_iterator end = screens.constEnd(); + + // The first screen in a virtual environment should know about all top levels + if (pi->isVirtualDesktop()) { + QWidget *w = (*screen)->topLevelAt(pos); + return w; + } + + while (screen != end) { + if ((*screen)->geometry().contains(pos)) + return (*screen)->topLevelAt(pos); + ++screen; + } + return 0; +} + +void QApplication::beep() +{ +} + +void QApplication::alert(QWidget *, int) +{ +} + +static void init_platform(const QString &name) +{ + QApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name); + if (!QApplicationPrivate::platform_integration) { + QStringList keys = QPlatformIntegrationFactory::keys(); + QString fatalMessage = + QString::fromLatin1("Failed to load platform plugin \"%1\". Available platforms are: \n").arg(name); + foreach(QString key, keys) { + fatalMessage.append(key + QString::fromLatin1("\n")); + } + qFatal("%s", fatalMessage.toLocal8Bit().constData()); + + } + +} + + +static void cleanup_platform() +{ + delete QApplicationPrivate::platform_integration; + QApplicationPrivate::platform_integration = 0; +} + +static void init_plugins(const QList<QByteArray> pluginList) +{ + for (int i = 0; i < pluginList.count(); ++i) { + QByteArray pluginSpec = pluginList.at(i); + qDebug() << "init_plugins" << i << pluginSpec; + int colonPos = pluginSpec.indexOf(':'); + QObject *plugin; + if (colonPos < 0) + plugin = QGenericPluginFactory::create(QLatin1String(pluginSpec), QString()); + else + plugin = QGenericPluginFactory::create(QLatin1String(pluginSpec.mid(0, colonPos)), + QLatin1String(pluginSpec.mid(colonPos+1))); + qDebug() << " created" << plugin; + } +} + +#ifndef QT_NO_QWS_INPUTMETHODS +class QDummyInputContext : public QInputContext +{ +public: + explicit QDummyInputContext(QObject* parent = 0) : QInputContext(parent) {} + ~QDummyInputContext() {} + QString identifierName() { return QString(); } + QString language() { return QString(); } + + void reset() {} + bool isComposing() const { return false; } + +}; +#endif // QT_NO_QWS_INPUTMETHODS + +void qt_init(QApplicationPrivate *priv, int type) +{ + Q_UNUSED(type); + + qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); + char *p; + char **argv = priv->argv; + int argc = priv->argc; + + if (argv && *argv) { //apparently, we allow people to pass 0 on the other platforms + p = strrchr(argv[0], '/'); + appName = QString::fromLocal8Bit(p ? p + 1 : argv[0]); + } + + QList<QByteArray> pluginList; + QString platformName = QLatin1String(qgetenv("QT_QPA_PLATFORM")); + + // Get command line params + + int j = argc ? 1 : 0; + for (int i=1; i<argc; i++) { + if (argv[i] && *argv[i] != '-') { + argv[j++] = argv[i]; + continue; + } + QByteArray arg = argv[i]; + if (arg == "-fn" || arg == "-font") { + if (++i < argc) + appFont = QString::fromLocal8Bit(argv[i]); + } else if (arg == "-platform") { + if (++i < argc) + platformName = QLatin1String(argv[i]); + } else if (arg == "-plugin") { + if (++i < argc) + pluginList << argv[i]; + } else { + argv[j++] = argv[i]; + } + } + + if (j < priv->argc) { + priv->argv[j] = 0; + priv->argc = j; + } + +#if 0 + QByteArray pluginEnv = qgetenv("QT_QPA_PLUGINS"); + if (!pluginEnv.isEmpty()) { + pluginList.append(pluginEnv.split(';')); + } +#endif + + init_platform(platformName); + init_plugins(pluginList); + + QColormap::initialize(); + QFont::initialize(); +#ifndef QT_NO_CURSOR +// QCursorData::initialize(); +#endif + + qApp->setObjectName(appName); + +#ifndef QT_NO_QWS_INPUTMETHODS + qApp->setInputContext(new QDummyInputContext(qApp)); +#endif +} + +void qt_cleanup() +{ + cleanup_platform(); + + QPixmapCache::clear(); +#ifndef QT_NO_CURSOR + QCursorData::cleanup(); +#endif + QFont::cleanup(); + QColormap::cleanup(); + delete QApplicationPrivate::inputContext; + QApplicationPrivate::inputContext = 0; + + QApplicationPrivate::active_window = 0; //### this should not be necessary +} + + +#ifdef QT3_SUPPORT +void QApplication::setMainWidget(QWidget *mainWidget) +{ + QApplicationPrivate::main_widget = mainWidget; + if (QApplicationPrivate::main_widget && windowIcon().isNull() + && QApplicationPrivate::main_widget->testAttribute(Qt::WA_SetWindowIcon)) + setWindowIcon(QApplicationPrivate::main_widget->windowIcon()); +} +#endif + +void QApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent *e) +{ + // qDebug() << "handleMouseEvent" << tlw << ev.pos() << ev.globalPos() << hex << ev.buttons(); + static QWeakPointer<QWidget> implicit_mouse_grabber; + + QEvent::Type type; + // move first + Qt::MouseButtons stateChange = e->buttons ^ buttons; + if (e->globalPos != QPoint(qt_last_x, qt_last_y) && (stateChange != Qt::NoButton)) { + QWindowSystemInterfacePrivate::MouseEvent * newMouseEvent = + new QWindowSystemInterfacePrivate::MouseEvent(e->widget.data(), e->timestamp, e->localPos, e->globalPos, e->buttons); + QWindowSystemInterfacePrivate::windowSystemEventQueue.prepend(newMouseEvent); // just in case the move triggers a new event loop + stateChange = Qt::NoButton; + } + + QWidget * tlw = e->widget.data(); + + QPoint localPoint = e->localPos; + QPoint globalPoint = e->globalPos; + QWidget *mouseWindow = tlw; + + Qt::MouseButton button = Qt::NoButton; + + + if (qt_last_x != globalPoint.x() || qt_last_y != globalPoint.y()) { + type = QEvent::MouseMove; + qt_last_x = globalPoint.x(); + qt_last_y = globalPoint.y(); + if (qAbs(globalPoint.x() - mousePressX) > mouse_double_click_distance|| + qAbs(globalPoint.y() - mousePressY) > mouse_double_click_distance) + mousePressButton = Qt::NoButton; + } + else { // check to see if a new button has been pressed/released + for (int check = Qt::LeftButton; + check <= Qt::XButton2; + check = check << 1) { + if (check & stateChange) { + button = Qt::MouseButton(check); + break; + } + } + if (button == Qt::NoButton) { + // Ignore mouse events that don't change the current state + return; + } + buttons = e->buttons; + if (button & e->buttons) { + if ((e->timestamp - mousePressTime) < static_cast<ulong>(QApplication::doubleClickInterval()) && button == mousePressButton) { + type = QEvent::MouseButtonDblClick; + mousePressButton = Qt::NoButton; + } + else { + type = QEvent::MouseButtonPress; + mousePressTime = e->timestamp; + mousePressButton = button; + mousePressX = qt_last_x; + mousePressY = qt_last_y; + } + } + else + type = QEvent::MouseButtonRelease; + } + + if (self->inPopupMode()) { + //popup mouse handling is magical... + mouseWindow = qApp->activePopupWidget(); + + implicit_mouse_grabber.clear(); + //### how should popup mode and implicit mouse grab interact? + + } else if (tlw && app_do_modal && !qt_try_modal(tlw, QEvent::MouseButtonRelease) ) { + //even if we're blocked by modality, we should deliver the mouse release event.. + //### this code is not completely correct: multiple buttons can be pressed simultaneously + if (!(implicit_mouse_grabber && buttons == Qt::NoButton)) { + //qDebug() << "modal blocked mouse event to" << tlw; + return; + } + } + + // find the tlw if we didn't get it from the plugin + if (!mouseWindow) { + mouseWindow = QApplication::topLevelAt(globalPoint); + } + + if (!mouseWindow && !implicit_mouse_grabber) + mouseWindow = QApplication::desktop(); + + if (mouseWindow && mouseWindow != tlw) { + //we did not get a sensible localPoint from the window system, so let's calculate it + localPoint = mouseWindow->mapFromGlobal(globalPoint); + } + + // which child should have it? + QWidget *mouseWidget = mouseWindow; + if (mouseWindow) { + QWidget *w = mouseWindow->childAt(localPoint); + if (w) { + mouseWidget = w; + } + } + + //handle implicit mouse grab + if (type == QEvent::MouseButtonPress && !implicit_mouse_grabber) { + implicit_mouse_grabber = mouseWidget; + + Q_ASSERT(mouseWindow); + mouseWindow->activateWindow(); //focus + } else if (implicit_mouse_grabber) { + mouseWidget = implicit_mouse_grabber.data(); + mouseWindow = mouseWidget->window(); + if (mouseWindow != tlw) + localPoint = mouseWindow->mapFromGlobal(globalPoint); + } + + Q_ASSERT(mouseWidget); + + //localPoint is local to mouseWindow, but it needs to be local to mouseWidget + localPoint = mouseWidget->mapFrom(mouseWindow, localPoint); + + if (buttons == Qt::NoButton) { + //qDebug() << "resetting mouse grabber"; + implicit_mouse_grabber.clear(); + } + + if (mouseWidget != qt_last_mouse_receiver) { + dispatchEnterLeave(mouseWidget, qt_last_mouse_receiver); + qt_last_mouse_receiver = mouseWidget; + } + + // Remember, we might enter a modal event loop when sending the event, + // so think carefully before adding code below this point. + + // qDebug() << "sending mouse ev." << ev.type() << localPoint << globalPoint << ev.button() << ev.buttons() << mouseWidget << "mouse grabber" << implicit_mouse_grabber; + + QMouseEvent ev(type, localPoint, globalPoint, button, buttons, modifiers); + + QList<QWeakPointer<QPlatformCursor> > cursors = QPlatformCursorPrivate::getInstances(); + foreach (QWeakPointer<QPlatformCursor> cursor, cursors) { + if (cursor) + cursor.data()->pointerEvent(ev); + } + + QApplication::sendSpontaneousEvent(mouseWidget, &ev); +} + + +//### there's a lot of duplicated logic here -- refactoring required! + +void QApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::WheelEvent *e) +{ +// QPoint localPoint = ev.pos(); + QPoint globalPoint = e->globalPos; +// bool trustLocalPoint = !!tlw; //is there something the local point can be local to? + QWidget *mouseWidget; + + qt_last_x = globalPoint.x(); + qt_last_y = globalPoint.y(); + + QWidget *mouseWindow = e->widget.data(); + + // find the tlw if we didn't get it from the plugin + if (!mouseWindow) { + mouseWindow = QApplication::topLevelAt(globalPoint); + } + + if (!mouseWindow) + return; + + mouseWidget = mouseWindow; + + if (app_do_modal && !qt_try_modal(mouseWindow, QEvent::Wheel) ) { + qDebug() << "modal blocked wheel event" << mouseWindow; + return; + } + QPoint p = mouseWindow->mapFromGlobal(globalPoint); + QWidget *w = mouseWindow->childAt(p); + if (w) { + mouseWidget = w; + p = mouseWidget->mapFromGlobal(globalPoint); + } + + QWheelEvent ev(p, globalPoint, e->delta, buttons, modifiers, + e->orient); + QApplication::sendSpontaneousEvent(mouseWidget, &ev); +} + + + +// Remember, Qt convention is: keyboard state is state *before* + +void QApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent *e) +{ + QWidget *focusW = 0; + if (self->inPopupMode()) { + QWidget *popupW = qApp->activePopupWidget(); + focusW = popupW->focusWidget() ? popupW->focusWidget() : popupW; + } + if (!focusW) + focusW = QApplication::focusWidget(); + if (!focusW) { + focusW = e->widget.data(); + } + if (!focusW) + focusW = QApplication::activeWindow(); + + //qDebug() << "handleKeyEvent" << hex << e->key() << e->modifiers() << e->text() << "widget" << focusW; + + if (!focusW) + return; + if (app_do_modal && !qt_try_modal(focusW, e->keyType)) + return; + + modifiers = e->modifiers; + QKeyEvent ev(e->keyType, e->key, e->modifiers, e->unicode, e->repeat, e->repeatCount); + QApplication::sendSpontaneousEvent(focusW, &ev); +} + +void QApplicationPrivate::processEnterEvent(QWindowSystemInterfacePrivate::EnterEvent *e) +{ + QApplicationPrivate::dispatchEnterLeave(e->enter.data(),0); + qt_last_mouse_receiver = e->enter.data(); +} + +void QApplicationPrivate::processLeaveEvent(QWindowSystemInterfacePrivate::LeaveEvent *e) +{ + QApplicationPrivate::dispatchEnterLeave(0,qt_last_mouse_receiver); + + if (e->leave.data() && !e->leave.data()->isAncestorOf(qt_last_mouse_receiver)) //(???) this should not happen + QApplicationPrivate::dispatchEnterLeave(0, e->leave.data()); + qt_last_mouse_receiver = 0; + +} + + +void QApplicationPrivate::processGeometryChangeEvent(QWindowSystemInterfacePrivate::GeometryChangeEvent *e) +{ + if (e->tlw.isNull()) + return; + QWidget *tlw = e->tlw.data(); + if (!tlw->isWindow()) + return; //geo of native child widgets is controlled by lighthouse + //so we already have sent the events; besides this new rect + //is not mapped to parent + + QRect newRect = e->newGeometry; + QRect cr(tlw->geometry()); + bool isResize = cr.size() != newRect.size(); + bool isMove = cr.topLeft() != newRect.topLeft(); + tlw->data->crect = newRect; + if (isResize) { + QResizeEvent e(tlw->data->crect.size(), cr.size()); + QApplication::sendSpontaneousEvent(tlw, &e); + tlw->update(); + } + + if (isMove) { + //### frame geometry + QMoveEvent e(tlw->data->crect.topLeft(), cr.topLeft()); + QApplication::sendSpontaneousEvent(tlw, &e); + } +} + +void QApplicationPrivate::processCloseEvent(QWindowSystemInterfacePrivate::CloseEvent *e) +{ + if (e->topLevel.isNull()) { + //qDebug() << "QApplicationPrivate::processCloseEvent NULL"; + return; + } + e->topLevel.data()->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); +} + +void QApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::TouchEvent *e) +{ + translateRawTouchEvent(e->widget.data(), e->devType, e->points); +} + +void QApplicationPrivate::reportScreenCount(QWindowSystemInterfacePrivate::ScreenCountEvent *e) +{ + // This operation only makes sense after the QApplication constructor runs + if (QCoreApplication::startingUp()) + return; + + QApplication::desktop()->d_func()->updateScreenList(); + // signal anything listening for creation or deletion of screens + QDesktopWidget *desktop = QApplication::desktop(); + emit desktop->screenCountChanged(e->count); +} + +void QApplicationPrivate::reportGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent *e) +{ + // This operation only makes sense after the QApplication constructor runs + if (QCoreApplication::startingUp()) + return; + + QApplication::desktop()->d_func()->updateScreenList(); + + // signal anything listening for screen geometry changes + QDesktopWidget *desktop = QApplication::desktop(); + emit desktop->resized(e->index); + + // make sure maximized and fullscreen windows are updated + QWidgetList list = QApplication::topLevelWidgets(); + for (int i = list.size() - 1; i >= 0; --i) { + QWidget *w = list.at(i); + if (w->isFullScreen()) + w->d_func()->setFullScreenSize_helper(); + else if (w->isMaximized()) + w->d_func()->setMaxWindowState_helper(); + } +} + +void QApplicationPrivate::reportAvailableGeometryChange( + QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e) +{ + // This operation only makes sense after the QApplication constructor runs + if (QCoreApplication::startingUp()) + return; + + QApplication::desktop()->d_func()->updateScreenList(); + + // signal anything listening for screen geometry changes + QDesktopWidget *desktop = QApplication::desktop(); + emit desktop->workAreaResized(e->index); + + // make sure maximized and fullscreen windows are updated + QWidgetList list = QApplication::topLevelWidgets(); + for (int i = list.size() - 1; i >= 0; --i) { + QWidget *w = list.at(i); + if (w->isFullScreen()) + w->d_func()->setFullScreenSize_helper(); + else if (w->isMaximized()) + w->d_func()->setMaxWindowState_helper(); + } +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index ae7070e..96856b8 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -1391,7 +1391,7 @@ bool QSymbianControl::isControlActive() This function is only available on S60. */ QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, 0x040000)) { Q_D(QApplication); S60->s60ApplicationFactory = factory; @@ -1399,7 +1399,7 @@ QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int } QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int _internal) - : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient, _internal)) { Q_D(QApplication); S60->s60ApplicationFactory = factory; diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 78028eb..1dab738 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -115,12 +115,25 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c # if defined(Q_WS_WINCE) # include <bldver.h> # endif -# include <winable.h> +# if !defined(Q_WS_WINCE) +# include <winable.h> +# endif +#endif + +#ifndef QT_NO_GESTURES +# ifndef GID_ZOOM +# define GID_ZOOM 3 +# define GID_TWOFINGERTAP 6 +# define GID_PRESSANDTAP 7 +# define GID_ROLLOVER GID_PRESSANDTAP +# endif #endif #ifndef WM_TOUCH # define WM_TOUCH 0x0240 +#endif +#ifndef TOUCHEVENTF_MOVE # define TOUCHEVENTF_MOVE 0x0001 # define TOUCHEVENTF_DOWN 0x0002 # define TOUCHEVENTF_UP 0x0004 @@ -207,8 +220,6 @@ static void resolveAygLibs() if (!aygResolved) { aygResolved = true; QSystemLibrary ayglib(QLatin1String("aygshell")); - if (!ayglib.load()) - return; ptrRecognizeGesture = (AygRecognizeGesture) ayglib.resolve("SHRecognizeGesture"); } } @@ -944,29 +955,36 @@ bool qt_nograb() // application no-grab option typedef QHash<QString, int> WinClassNameHash; Q_GLOBAL_STATIC(WinClassNameHash, winclassNames) +// +// If 0 is passed as the widget pointer, register a window class +// for QWidget as default. This is used in QGLTemporaryContext +// during GL initialization, where we don't want to use temporary +// QWidgets or QGLWidgets, neither do we want to have separate code +// to register window classes. +// const QString qt_reg_winclass(QWidget *w) // register window class { - int flags = w->windowFlags(); - int type = flags & Qt::WindowType_Mask; + Qt::WindowFlags flags = w ? w->windowFlags() : (Qt::WindowFlags)0; + Qt::WindowFlags type = flags & Qt::WindowType_Mask; uint style; bool icon; QString cname; - if (qt_widget_private(w)->isGLWidget) { + if (w && qt_widget_private(w)->isGLWidget) { cname = QLatin1String("QGLWidget"); style = CS_DBLCLKS; #ifndef Q_WS_WINCE style |= CS_OWNDC; #endif icon = true; - } else if (flags & Qt::MSWindowsOwnDC) { + } else if (w && (flags & Qt::MSWindowsOwnDC)) { cname = QLatin1String("QWidgetOwnDC"); style = CS_DBLCLKS; #ifndef Q_WS_WINCE style |= CS_OWNDC; #endif icon = true; - } else if (type == Qt::Tool || type == Qt::ToolTip){ + } else if (w && (type == Qt::Tool || type == Qt::ToolTip)) { style = CS_DBLCLKS; if (w->inherits("QTipLabel") || w->inherits("QAlphaWidget")) { if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP @@ -981,7 +999,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class style |= CS_SAVEBITS; #endif icon = false; - } else if (type == Qt::Popup) { + } else if (w && (type == Qt::Popup)) { cname = QLatin1String("QPopup"); style = CS_DBLCLKS; #ifndef Q_WS_WINCE @@ -1052,7 +1070,10 @@ const QString qt_reg_winclass(QWidget *w) // register window class } wc.hCursor = 0; #ifndef Q_WS_WINCE - wc.hbrBackground = qt_widget_private(w)->isGLWidget ? 0 : (HBRUSH)GetSysColorBrush(COLOR_WINDOW); + HBRUSH brush = 0; + if (w && !qt_widget_private(w)->isGLWidget) + brush = (HBRUSH)GetSysColorBrush(COLOR_WINDOW); + wc.hbrBackground = brush; #else wc.hbrBackground = 0; #endif @@ -1074,8 +1095,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class Q_GUI_EXPORT const QString qt_getRegisteredWndClass() { - QWidget w; - return qt_reg_winclass(&w); + return qt_reg_winclass(0); } static void unregWinClasses() @@ -2324,7 +2344,7 @@ extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wPa case WM_GETOBJECT: { // Ignoring all requests while starting up - if (QApplication::startingUp() || QApplication::closingDown() || (LONG)lParam != OBJID_CLIENT) { + if (QApplication::startingUp() || QApplication::closingDown() || lParam != (LPARAM)OBJID_CLIENT) { result = false; break; } @@ -3676,13 +3696,11 @@ static void initWinTabFunctions() return; QSystemLibrary library(QLatin1String("wintab32")); - if (library.load()) { - ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); - ptrWTGet = (PtrWTGet)library.resolve("WTGetW"); - ptrWTEnable = (PtrWTEnable)library.resolve("WTEnable"); - ptrWTOverlap = (PtrWTEnable)library.resolve("WTOverlap"); - ptrWTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet"); - } + ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); + ptrWTGet = (PtrWTGet)library.resolve("WTGetW"); + ptrWTEnable = (PtrWTEnable)library.resolve("WTEnable"); + ptrWTOverlap = (PtrWTEnable)library.resolve("WTOverlap"); + ptrWTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet"); #endif // Q_OS_WINCE } #endif // QT_NO_TABLETEVENT diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 7c68170..ff98229 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -483,11 +483,9 @@ static void* qt_load_library_runtime(const char *library, int vernum, Q_FOREACH(int version, versions) { QLatin1String libName(library); QLibrary xfixesLib(libName, version); - if (xfixesLib.load()) { - void *ptr = xfixesLib.resolve(symbol); - if (ptr) - return ptr; - } + void *ptr = xfixesLib.resolve(symbol); + if (ptr) + return ptr; } return 0; } @@ -1739,6 +1737,9 @@ void qt_init(QApplicationPrivate *priv, int, } else { // Qt controls everything (default) + if (QApplication::testAttribute(Qt::AA_X11InitThreads)) + XInitThreads(); + // Set application name and class char *app_class = 0; if (argv && argv[0]) { @@ -2608,22 +2609,20 @@ void qt_init(QApplicationPrivate *priv, int, #if !defined (Q_OS_IRIX) && !defined (QT_NO_TABLET) QLibrary wacom(QString::fromLatin1("wacomcfg"), 0); // version 0 is the latest release at time of writing this. - if (wacom.load()) { - // NOTE: C casts instead of reinterpret_cast for GCC 3.3.x - ptrWacomConfigInit = (PtrWacomConfigInit)wacom.resolve("WacomConfigInit"); - ptrWacomConfigOpenDevice = (PtrWacomConfigOpenDevice)wacom.resolve("WacomConfigOpenDevice"); - ptrWacomConfigGetRawParam = (PtrWacomConfigGetRawParam)wacom.resolve("WacomConfigGetRawParam"); - ptrWacomConfigCloseDevice = (PtrWacomConfigCloseDevice)wacom.resolve("WacomConfigCloseDevice"); - ptrWacomConfigTerm = (PtrWacomConfigTerm)wacom.resolve("WacomConfigTerm"); - - if (ptrWacomConfigInit == 0 || ptrWacomConfigOpenDevice == 0 || ptrWacomConfigGetRawParam == 0 - || ptrWacomConfigCloseDevice == 0 || ptrWacomConfigTerm == 0) { // either we have all, or we have none. + // NOTE: C casts instead of reinterpret_cast for GCC 3.3.x + ptrWacomConfigInit = (PtrWacomConfigInit)wacom.resolve("WacomConfigInit"); + ptrWacomConfigOpenDevice = (PtrWacomConfigOpenDevice)wacom.resolve("WacomConfigOpenDevice"); + ptrWacomConfigGetRawParam = (PtrWacomConfigGetRawParam)wacom.resolve("WacomConfigGetRawParam"); + ptrWacomConfigCloseDevice = (PtrWacomConfigCloseDevice)wacom.resolve("WacomConfigCloseDevice"); + ptrWacomConfigTerm = (PtrWacomConfigTerm)wacom.resolve("WacomConfigTerm"); + + if (ptrWacomConfigInit == 0 || ptrWacomConfigOpenDevice == 0 || ptrWacomConfigGetRawParam == 0 + || ptrWacomConfigCloseDevice == 0 || ptrWacomConfigTerm == 0) { // either we have all, or we have none. ptrWacomConfigInit = 0; ptrWacomConfigOpenDevice = 0; ptrWacomConfigGetRawParam = 0; ptrWacomConfigCloseDevice = 0; ptrWacomConfigTerm = 0; - } } #endif } diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp index f7c0b6e..8c7c333 100644 --- a/src/gui/kernel/qclipboard.cpp +++ b/src/gui/kernel/qclipboard.cpp @@ -631,7 +631,7 @@ QByteArray QMimeDataWrapper::encodedData(const char *format) const return data->data(QLatin1String(format)); } else{ QVariant variant = data->imageData(); - QImage img = qVariantValue<QImage>(variant); + QImage img = qvariant_cast<QImage>(variant); QByteArray ba; QBuffer buffer(&ba); buffer.open(QIODevice::WriteOnly); diff --git a/src/gui/kernel/qclipboard_qpa.cpp b/src/gui/kernel/qclipboard_qpa.cpp new file mode 100644 index 0000000..92b9e83 --- /dev/null +++ b/src/gui/kernel/qclipboard_qpa.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qclipboard.h" + +#ifndef QT_NO_CLIPBOARD + +#include "qmimedata.h" +#include "qapplication.h" + +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + + +class QClipboardData +{ +public: + QClipboardData(); + ~QClipboardData(); + + void setSource(QMimeData* s) + { + if (s == src) + return; + delete src; + src = s; + } + QMimeData* source() + { return src; } + + void clear(); + +private: + QMimeData* src; +}; + +QClipboardData::QClipboardData() +{ + src = 0; +} + +QClipboardData::~QClipboardData() +{ + delete src; +} + +void QClipboardData::clear() +{ + delete src; + src = 0; +} + + +static QClipboardData *internalCbData = 0; + +static void cleanupClipboardData() +{ + delete internalCbData; + internalCbData = 0; +} + +static QClipboardData *clipboardData() +{ + if (internalCbData == 0) { + internalCbData = new QClipboardData; + qAddPostRoutine(cleanupClipboardData); + } + return internalCbData; +} + + +void QClipboard::clear(Mode mode) +{ + setText(QString(), mode); +} + + +bool QClipboard::event(QEvent *e) +{ + return QObject::event(e); +} + +const QMimeData* QClipboard::mimeData(Mode mode) const +{ + if (mode != Clipboard) return 0; + + QClipboardData *d = clipboardData(); + return d->source(); +} + +void QClipboard::setMimeData(QMimeData* src, Mode mode) +{ + if (mode != Clipboard) return; + + QClipboardData *d = clipboardData(); + + d->setSource(src); + + emitChanged(QClipboard::Clipboard); +} + +bool QClipboard::supportsMode(Mode mode) const +{ + return (mode == Clipboard); +} + +bool QClipboard::ownsMode(Mode mode) const +{ + if (mode == Clipboard) + qWarning("QClipboard::ownsClipboard: UNIMPLEMENTED!"); + return false; +} + +void QClipboard::connectNotify( const char * ) +{ +} + +void QClipboard::ownerDestroyed() +{ +} + +#endif // QT_NO_CLIPBOARD + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qcocoaapplication_mac.mm b/src/gui/kernel/qcocoaapplication_mac.mm index 4962863..1b30efd 100644 --- a/src/gui/kernel/qcocoaapplication_mac.mm +++ b/src/gui/kernel/qcocoaapplication_mac.mm @@ -78,6 +78,7 @@ #include <private/qcocoaapplication_mac_p.h> #include <private/qcocoaapplicationdelegate_mac_p.h> #include <private/qt_cocoa_helpers_mac_p.h> +#include <private/qcocoaintrospection_p.h> QT_USE_NAMESPACE @@ -116,12 +117,30 @@ QT_USE_NAMESPACE quint64 lower = [event data1]; quint64 upper = [event data2]; QCocoaPostMessageArgs *args = reinterpret_cast<QCocoaPostMessageArgs *>(lower | (upper << 32)); - [args->target performSelector:args->selector]; + // Special case for convenience: if the argument is an NSNumber, we unbox it directly. + // Use NSValue instead if this behaviour is unwanted. + id a1 = ([args->arg1 isKindOfClass:[NSNumber class]]) ? (id)[args->arg1 intValue] : args->arg1; + id a2 = ([args->arg2 isKindOfClass:[NSNumber class]]) ? (id)[args->arg2 intValue] : args->arg2; + switch (args->argCount) { + case 0: + [args->target performSelector:args->selector]; + break; + case 1: + [args->target performSelector:args->selector withObject:a1]; + break; + case 3: + [args->target performSelector:args->selector withObject:a1 withObject:a2]; + break; + } + delete args; } -- (BOOL)qt_sendEvent:(NSEvent *)event +- (BOOL)qt_filterEvent:(NSEvent *)event { + if (qApp->macEventFilter(0, reinterpret_cast<EventRef>(event))) + return true; + if ([event type] == NSApplicationDefined) { switch ([event subtype]) { case QtCocoaEventSubTypePostMessage: @@ -138,20 +157,66 @@ QT_USE_NAMESPACE @implementation QNSApplication -// WARNING: If Qt did not create NSApplication (this can e.g. -// happend if Qt is used as a plugin from a 3rd-party cocoa -// application), QNSApplication::sendEvent will never be called. -// SO DO NOT RELY ON THIS FUNCTION BEING AVAILABLE. -// Plugin developers that _do_ control the NSApplication sub-class -// implementation of the 3rd-party application can call qt_sendEvent -// from the sub-class event handler (like we do here) to work around -// any issues. +- (void)qt_sendEvent_original:(NSEvent *)event +{ + Q_UNUSED(event); + // This method will only be used as a signature + // template for the method we add into NSApplication + // containing the original [NSApplication sendEvent:] implementation +} + +- (void)qt_sendEvent_replacement:(NSEvent *)event +{ + // This method (or its implementation to be precise) will + // be called instead of sendEvent if redirection occurs. + // 'self' will then be an instance of NSApplication + // (and not QNSApplication) + if (![NSApp qt_filterEvent:event]) + [self qt_sendEvent_original:event]; +} + - (void)sendEvent:(NSEvent *)event { - if (![self qt_sendEvent:event]) + // This method will be called if + // no redirection occurs + if (![NSApp qt_filterEvent:event]) [super sendEvent:event]; } +- (void)qtDispatcherToQAction:(id)sender +{ + // Forward actions sendt from the menu bar (e.g. quit) to the menu loader. + // Having this method here means that we are the last stop in the responder + // chain, and that we are able to handle menu actions even when no window is + // visible on screen. Note: If Qt is used as a plugin, Qt will not use a + // native menu bar. Hence, we will also not need to do any redirection etc. as + // we do with sendEvent. + [[NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)] qtDispatcherToQAction:sender]; +} + @end +QT_BEGIN_NAMESPACE + +void qt_redirectNSApplicationSendEvent() +{ + if ([NSApp isMemberOfClass:[QNSApplication class]]) { + // No need to change implementation since Qt + // already controls a subclass of NSApplication + return; + } + + // Change the implementation of [NSApplication sendEvent] to the + // implementation of qt_sendEvent_replacement found in QNSApplication. + // And keep the old implementation that gets overwritten inside a new + // method 'qt_sendEvent_original' that we add to NSApplication + qt_cocoa_change_implementation( + [NSApplication class], + @selector(sendEvent:), + [QNSApplication class], + @selector(qt_sendEvent_replacement:), + @selector(qt_sendEvent_original:)); + } + +QT_END_NAMESPACE #endif diff --git a/src/gui/kernel/qcocoaapplication_mac_p.h b/src/gui/kernel/qcocoaapplication_mac_p.h index 5569feb..c89ff36 100644 --- a/src/gui/kernel/qcocoaapplication_mac_p.h +++ b/src/gui/kernel/qcocoaapplication_mac_p.h @@ -101,11 +101,17 @@ QT_FORWARD_DECLARE_CLASS(QApplicationPrivate) - (int)QT_MANGLE_NAMESPACE(qt_validModesForFontPanel):(NSFontPanel *)fontPanel; - (void)qt_sendPostedMessage:(NSEvent *)event; -- (BOOL)qt_sendEvent:(NSEvent *)event; +- (BOOL)qt_filterEvent:(NSEvent *)event; @end @interface QNSApplication : NSApplication { } @end +QT_BEGIN_NAMESPACE + +void qt_redirectNSApplicationSendEvent(); + +QT_END_NAMESPACE + #endif diff --git a/src/gui/kernel/qcocoaintrospection_mac.mm b/src/gui/kernel/qcocoaintrospection_mac.mm new file mode 100644 index 0000000..9b536b7 --- /dev/null +++ b/src/gui/kernel/qcocoaintrospection_mac.mm @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +/**************************************************************************** +** +** Copyright (c) 2007-2008, Apple, Inc. +** +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** +** * Neither the name of Apple, Inc. nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include <private/qcocoaintrospection_p.h> + +QT_BEGIN_NAMESPACE + +void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class proxyClass, SEL replacementSel, SEL backupSel) +{ +#ifndef QT_MAC_USE_COCOA + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) +#endif + { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + // The following code replaces the _implementation_ for the selector we want to hack + // (originalSel) with the implementation found in proxyClass. Then it creates + // a new 'backup' method inside baseClass containing the old, original, + // implementation (fakeSel). You can let the proxy implementation of originalSel + // call fakeSel if needed (similar approach to calling a super class implementation). + // fakeSel must also be implemented in proxyClass, as the signature is used + // as template for the method one we add into baseClass. + // NB: You will typically never create any instances of proxyClass; we use it + // only for stealing its contents and put it into baseClass. + if (!replacementSel) + replacementSel = originalSel; + + Method originalMethod = class_getInstanceMethod(baseClass, originalSel); + Method replacementMethod = class_getInstanceMethod(proxyClass, replacementSel); + IMP originalImp = method_setImplementation(originalMethod, method_getImplementation(replacementMethod)); + + if (backupSel) { + Method backupMethod = class_getInstanceMethod(proxyClass, backupSel); + class_addMethod(baseClass, backupSel, originalImp, method_getTypeEncoding(backupMethod)); + } +#endif + } +} + +void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL backupSel) +{ +#ifndef QT_MAC_USE_COCOA + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) +#endif + { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + Method originalMethod = class_getInstanceMethod(baseClass, originalSel); + Method backupMethodInBaseClass = class_getInstanceMethod(baseClass, backupSel); + method_setImplementation(originalMethod, method_getImplementation(backupMethodInBaseClass)); +#endif + } +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qcocoaintrospection_p.h b/src/gui/kernel/qcocoaintrospection_p.h new file mode 100644 index 0000000..b9422e8 --- /dev/null +++ b/src/gui/kernel/qcocoaintrospection_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +/**************************************************************************** +** +** Copyright (c) 2007-2008, Apple, Inc. +** +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** +** * Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** +** * Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** +** * Neither the name of Apple, Inc. nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include <qglobal.h> +#import <objc/objc-class.h> + +QT_BEGIN_NAMESPACE + +void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class proxyClass, SEL replacementSel = 0, SEL backupSel = 0); +void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL backupSel); + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qcocoamenuloader_mac.mm b/src/gui/kernel/qcocoamenuloader_mac.mm index 4bf6ed9..b963b3c 100644 --- a/src/gui/kernel/qcocoamenuloader_mac.mm +++ b/src/gui/kernel/qcocoamenuloader_mac.mm @@ -70,13 +70,13 @@ QT_USE_NAMESPACE showAllItem = [[appMenu itemWithTitle:@"Show All"] retain]; // Get the names in the nib to match the app name set by Qt. - NSString *appName = reinterpret_cast<const NSString*>(QCFString::toCFStringRef(qAppName())); + const NSString *appName = reinterpret_cast<const NSString*>(QCFString::toCFStringRef(qAppName())); [quitItem setTitle:[[quitItem title] stringByReplacingOccurrencesOfString:@"NewApplication" - withString:appName]]; + withString:const_cast<NSString *>(appName)]]; [hideItem setTitle:[[hideItem title] stringByReplacingOccurrencesOfString:@"NewApplication" - withString:appName]]; + withString:const_cast<NSString *>(appName)]]; [aboutItem setTitle:[[aboutItem title] stringByReplacingOccurrencesOfString:@"NewApplication" - withString:appName]]; + withString:const_cast<NSString *>(appName)]]; [appName release]; // Disable the items that don't do anything. If someone associates a QAction with them // They should get synced back in. diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h index ddf1a27..efe045c 100644 --- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -136,16 +136,6 @@ QT_END_NAMESPACE qt_dispatchTabletProximityEvent(tabletEvent); } -- (void)qtDispatcherToQAction:(id)sender -{ - // If this window is modal, the menu bar will be modally shaddowed. - // In that case, since the window will be in the first responder chain, - // we can still catch the trigger here and forward it to the menu bar. - // This is needed as a single modal dialog on Qt should be able to access - // the application menu (e.g. quit). - [[NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)] qtDispatcherToQAction:sender]; -} - - (void)terminate:(id)sender { // This function is called from the quit item in the menubar when this window @@ -155,17 +145,6 @@ QT_END_NAMESPACE - (void)sendEvent:(NSEvent *)event { - if ([event type] == NSApplicationDefined) { - switch ([event subtype]) { - case QtCocoaEventSubTypePostMessage: - [NSApp qt_sendPostedMessage:event]; - return; - default: - break; - } - return; - } - QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; // Cocoa can hold onto the window after we've disavowed its knowledge. So, // if we get sent an event afterwards just have it go through the super's diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index f759fe0..dfcc2e6 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -207,6 +207,7 @@ static int qCocoaViewCount = 0; composing = false; sendKeyEvents = true; + fromKeyDownEvent = false; [self setHidden:YES]; return self; } @@ -508,7 +509,7 @@ static int qCocoaViewCount = 0; } // Make sure the opengl context is updated on resize. - if (qwidgetprivate && qwidgetprivate->isGLWidget) { + if (qwidgetprivate && qwidgetprivate->isGLWidget && [self window]) { qwidgetprivate->needWindowChange = true; QEvent event(QEvent::MacGLWindowChange); qApp->sendEvent(qwidget, &event); @@ -532,16 +533,40 @@ static int qCocoaViewCount = 0; if (!qwidget) return; - if (QApplicationPrivate::graphicsSystem() != 0) { - if (qwidgetprivate->maybeBackingStore()) { - // Drawing is handled on the window level - // See qcocoasharedwindowmethods_mac_p.h - if (!qwidget->testAttribute(Qt::WA_PaintOnScreen)) - return; + // We use a different graphics system. + if (QApplicationPrivate::graphicsSystem() != 0 && !qwidgetprivate->isInUnifiedToolbar) { + + // Qt handles the painting occuring inside the window. + // Cocoa also keeps track of all widgets as NSView and therefore might + // ask for a repainting of a widget even if Qt is already taking care of it. + // + // The only valid reason for Cocoa to call drawRect: is for window manipulation + // (ie. resize, ...). + // + // Qt will then forward the update to the children. + if (qwidget->isWindow()) { + qwidget->update(qwidget->rect()); + qwidgetprivate->syncBackingStore(qwidget->rect()); } + + // Since we don't want to use the native engine, we must exit, however + // widgets that are set to paint on screen, spesifically QGLWidget, + // requires the following code to execute in order to be drawn. + if (!qwidget->testAttribute(Qt::WA_PaintOnScreen)) + return; } + CGContextRef cg = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; qwidgetprivate->hd = cg; + + // We steal the CGContext for flushing in the unified toolbar with the raster engine. + if (QApplicationPrivate::graphicsSystem() != 0 && qwidgetprivate->isInUnifiedToolbar) { + qwidgetprivate->cgContext = cg; + qwidgetprivate->hasOwnContext = true; + qwidgetprivate->unifiedSurface->flush(qwidget, qwidgetprivate->ut_rg, qwidgetprivate->ut_pt); + return; + } + CGContextSaveGState(cg); if (qwidget->isVisible() && qwidget->updatesEnabled()) { //process the actual paint event. @@ -1199,7 +1224,9 @@ static int qCocoaViewCount = 0; && !(widgetToGetKey->inputMethodHints() & Qt::ImhDigitsOnly || widgetToGetKey->inputMethodHints() & Qt::ImhFormattedNumbersOnly || widgetToGetKey->inputMethodHints() & Qt::ImhHiddenText)) { + fromKeyDownEvent = true; [qt_mac_nativeview_for(widgetToGetKey) interpretKeyEvents:[NSArray arrayWithObject: theEvent]]; + fromKeyDownEvent = false; } if (sendKeyEvents && !composing) { bool keyOK = qt_dispatchKeyEvent(theEvent, widgetToGetKey); @@ -1269,7 +1296,10 @@ static int qCocoaViewCount = 0; }; } - if ([aString length] && composing) { + // When entering characters through Character Viewer or Keyboard Viewer, the text is passed + // through this insertText method. Since we dont receive a keyDown Event in such cases, the + // composing flag will be false. + if (([aString length] && composing) || !fromKeyDownEvent) { // Send the commit string to the widget. composing = false; sendKeyEvents = false; @@ -1383,7 +1413,7 @@ static int qCocoaViewCount = 0; if (!selectedText.isEmpty()) { QCFString string(selectedText.mid(theRange.location, theRange.length)); const NSString *tmpString = reinterpret_cast<const NSString *>((CFStringRef)string); - return [[[NSAttributedString alloc] initWithString:tmpString] autorelease]; + return [[[NSAttributedString alloc] initWithString:const_cast<NSString *>(tmpString)] autorelease]; } else { return nil; } diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h index b6b63ca..511423357 100644 --- a/src/gui/kernel/qcocoaview_mac_p.h +++ b/src/gui/kernel/qcocoaview_mac_p.h @@ -86,6 +86,7 @@ Q_GUI_EXPORT bool composing; int composingLength; bool sendKeyEvents; + bool fromKeyDownEvent; QString *composingText; NSInteger dragEnterSequence; } diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h index 2490d20..62d2f41 100644 --- a/src/gui/kernel/qcursor.h +++ b/src/gui/kernel/qcursor.h @@ -96,6 +96,10 @@ public: QCursor(const QCursor &cursor); ~QCursor(); QCursor &operator=(const QCursor &cursor); +#ifdef Q_COMPILER_RVALUE_REFS + inline QCursor &operator=(QCursor &&other) + { qSwap(d, other.d); return *this; } +#endif operator QVariant() const; Qt::CursorShape shape() const; @@ -126,7 +130,7 @@ public: static int x11Screen(); #elif defined(Q_WS_MAC) Qt::HANDLE handle() const; -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_QPA) int handle() const; #elif defined(Q_OS_SYMBIAN) Qt::HANDLE handle() const; diff --git a/src/gui/kernel/qcursor_p.h b/src/gui/kernel/qcursor_p.h index 23798b4..bfd6eac 100644 --- a/src/gui/kernel/qcursor_p.h +++ b/src/gui/kernel/qcursor_p.h @@ -91,7 +91,7 @@ public: short hx, hy; #if defined (Q_WS_MAC) int mId; -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_QPA) int id; #endif #if defined (Q_WS_WIN) diff --git a/src/gui/kernel/qcursor_qpa.cpp b/src/gui/kernel/qcursor_qpa.cpp new file mode 100644 index 0000000..a6ae7d3 --- /dev/null +++ b/src/gui/kernel/qcursor_qpa.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** 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 QtGui 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 <qcursor.h> +#include <private/qcursor_p.h> +#include <qbitmap.h> + +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + +#ifndef QT_NO_CURSOR + +static int nextCursorId = Qt::BitmapCursor; + +/***************************************************************************** + Internal QCursorData class + *****************************************************************************/ + +QCursorData::QCursorData(Qt::CursorShape s) + : cshape(s), bm(0), bmm(0), hx(0), hy(0), id(s) +{ + ref = 1; +} + +QCursorData::~QCursorData() +{ + delete bm; + delete bmm; +} + + +/***************************************************************************** + Global cursors + *****************************************************************************/ + +extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; // qcursor.cpp + +int QCursor::handle() const +{ + return d->id; +} + + +QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY) +{ + if (!QCursorData::initialized) + QCursorData::initialize(); + if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) { + qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)"); + QCursorData *c = qt_cursorTable[0]; + c->ref.ref(); + return c; + } + QCursorData *d = new QCursorData; + d->bm = new QBitmap(bitmap); + d->bmm = new QBitmap(mask); + d->cshape = Qt::BitmapCursor; + d->id = ++nextCursorId; + d->hx = hotX >= 0 ? hotX : bitmap.width() / 2; + d->hy = hotY >= 0 ? hotY : bitmap.height() / 2; + + return d; +} + +void QCursorData::update() +{ +} + +#endif //QT_NO_CURSOR + +extern int qt_last_x,qt_last_y; + +QPoint QCursor::pos() +{ + return QPoint(qt_last_x, qt_last_y); +} + +void QCursor::setPos(int x, int y) +{ + // Need to check, since some X servers generate null mouse move + // events, causing looping in applications which call setPos() on + // every mouse move event. + // + if (pos() == QPoint(x, y)) + return; +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qdesktopwidget_qpa.cpp b/src/gui/kernel/qdesktopwidget_qpa.cpp new file mode 100644 index 0000000..cff05f5 --- /dev/null +++ b/src/gui/kernel/qdesktopwidget_qpa.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qdesktopwidget.h" +#include "private/qapplication_p.h" +#include "private/qgraphicssystem_p.h" +#include <QWidget> +#include "private/qwidget_p.h" +#include "private/qdesktopwidget_qpa_p.h" +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + +void QDesktopWidgetPrivate::updateScreenList() +{ + QList<QPlatformScreen *> screenList = QApplicationPrivate::platformIntegration()->screens(); + int targetLength = screenList.length(); + int currentLength = screens.length(); + + // Add or remove screen widgets as necessary + if(currentLength > targetLength) { + QDesktopScreenWidget *screen; + while (currentLength-- > targetLength) { + screen = screens.takeLast(); + delete screen; + } + } + else if (currentLength < targetLength) { + QDesktopScreenWidget *screen; + while (currentLength < targetLength) { + screen = new QDesktopScreenWidget(currentLength++); + screens.append(screen); + } + } + + QRegion virtualGeometry; + bool doVirtualGeometry = QApplicationPrivate::platformIntegration()->isVirtualDesktop(); + + // update the geometry of each screen widget + for (int i = 0; i < screens.length(); i++) { + QRect screenGeometry = screenList.at(i)->geometry(); + screens.at(i)->setGeometry(screenGeometry); + if (doVirtualGeometry) + virtualGeometry += screenGeometry; + } + + virtualScreen.setGeometry(virtualGeometry.boundingRect()); + Q_Q(QDesktopWidget); + q->setGeometry(virtualScreen.geometry()); +} + +QDesktopWidget::QDesktopWidget() + : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop) +{ + Q_D(QDesktopWidget); + setObjectName(QLatin1String("desktop")); + d->updateScreenList(); +} + +QDesktopWidget::~QDesktopWidget() +{ +} + +bool QDesktopWidget::isVirtualDesktop() const +{ + return QApplicationPrivate::platformIntegration()->isVirtualDesktop(); +} + +int QDesktopWidget::primaryScreen() const +{ + return 0; +} + +int QDesktopWidget::numScreens() const +{ + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + return qMax(pi->screens().size(), 1); +} + +QWidget *QDesktopWidget::screen(int screen) +{ + Q_D(QDesktopWidget); + if (QApplicationPrivate::platformIntegration()->isVirtualDesktop()) + return &d->virtualScreen; + if (screen < 0 || screen >= d->screens.length()) + return d->screens.at(0); + return d->screens.at(screen); +} + +const QRect QDesktopWidget::availableGeometry(int screenNo) const +{ + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + QList<QPlatformScreen *> screens = pi->screens(); + if (screenNo == -1) + screenNo = 0; + if (screenNo < 0 || screenNo >= screens.size()) + return QRect(); + else + return screens[screenNo]->availableGeometry(); +} + +const QRect QDesktopWidget::screenGeometry(int screenNo) const +{ + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + QList<QPlatformScreen *> screens = pi->screens(); + if (screenNo == -1) + screenNo = 0; + if (screenNo < 0 || screenNo >= screens.size()) + return QRect(); + else + return screens[screenNo]->geometry(); +} + +int QDesktopWidget::screenNumber(const QWidget *w) const +{ + if (!w) + return 0; + + QRect frame = w->frameGeometry(); + if (!w->isWindow()) + frame.moveTopLeft(w->mapToGlobal(QPoint(0, 0))); + const QPoint midpoint = (frame.topLeft() + frame.bottomRight()) / 2; + return screenNumber(midpoint); +} + +int QDesktopWidget::screenNumber(const QPoint &p) const +{ + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + QList<QPlatformScreen *> screens = pi->screens(); + + for (int i = 0; i < screens.size(); ++i) + if (screens[i]->geometry().contains(p)) + return i; + + return primaryScreen(); //even better would be closest screen +} + +void QDesktopWidget::resizeEvent(QResizeEvent *) +{ +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qdesktopwidget_qpa_p.h b/src/gui/kernel/qdesktopwidget_qpa_p.h new file mode 100644 index 0000000..8bed09d --- /dev/null +++ b/src/gui/kernel/qdesktopwidget_qpa_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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 QtGui 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 for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifndef QDESKTOPWIDGET_QPA_P_H +#define QDESKTOPWIDGET_QPA_P_H + +#include "QDesktopWidget" +#include "private/qwidget_p.h" + +class QDesktopScreenWidget : public QWidget { + Q_OBJECT +public: + QDesktopScreenWidget(int screenNumber = -1) { setWindowFlags(Qt::Desktop); setVisible(false); d_func()->screenNumber = screenNumber; } +}; + +class QDesktopWidgetPrivate : public QWidgetPrivate { + Q_DECLARE_PUBLIC(QDesktopWidget) + +public: + ~QDesktopWidgetPrivate() {foreach(QDesktopScreenWidget *s, screens) delete s; } + void updateScreenList(); + + QList<QDesktopScreenWidget *> screens; + QDesktopScreenWidget virtualScreen; +}; + +#endif // QDESKTOPWIDGET_QPA_P_H diff --git a/src/gui/kernel/qdesktopwidget_win.cpp b/src/gui/kernel/qdesktopwidget_win.cpp index 1b2dfe7..f65af9c 100644 --- a/src/gui/kernel/qdesktopwidget_win.cpp +++ b/src/gui/kernel/qdesktopwidget_win.cpp @@ -156,10 +156,8 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that) #ifndef Q_OS_WINCE QSystemLibrary user32Lib(QLatin1String("user32")); - if (user32Lib.load()) { - enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors"); - getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW"); - } + enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors"); + getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW"); if (!enumDisplayMonitors || !getMonitorInfo) { screenCount = GetSystemMetrics(80); // SM_CMONITORS @@ -174,11 +172,9 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that) getMonitorInfo = 0; #else QSystemLibrary coreLib(QLatin1String("coredll")); - if (coreLib.load()) { - // CE >= 4.0 case - enumDisplayMonitors = (EnumFunc)coreLib.resolve("EnumDisplayMonitors"); - getMonitorInfo = (InfoFunc)coreLib.resolve("GetMonitorInfo"); - } + // CE >= 4.0 case + enumDisplayMonitors = (EnumFunc)coreLib.resolve("EnumDisplayMonitors"); + getMonitorInfo = (InfoFunc)coreLib.resolve("GetMonitorInfo"); if ((!enumDisplayMonitors || !getMonitorInfo)) { screenCount = GetSystemMetrics(SM_CMONITORS); diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h index 033e6a6..598a9de 100644 --- a/src/gui/kernel/qdnd_p.h +++ b/src/gui/kernel/qdnd_p.h @@ -261,11 +261,11 @@ public: #endif private: -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) Qt::DropAction currentActionForOverrideCursor; #endif #ifdef Q_OS_SYMBIAN -#ifndef QT_NO_CURSOR +#ifndef QT_NO_CURSOR QCursor overrideCursor; #endif #endif diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index eade02e..d2b2098 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -4392,7 +4392,7 @@ void QGestureEvent::accept(QGesture *gesture) of calling \l{QGestureEvent::setAccepted()}{setAccepted(gesture, false)}. Clearing the accept flag indicates that the event receiver does not - want the gesture. Unwanted gestures may be propgated to the parent widget. + want the gesture. Unwanted gestures may be propagated to the parent widget. \sa QGestureEvent::accept() */ diff --git a/src/gui/kernel/qeventdispatcher_glib_qpa.cpp b/src/gui/kernel/qeventdispatcher_glib_qpa.cpp new file mode 100644 index 0000000..01d40ca --- /dev/null +++ b/src/gui/kernel/qeventdispatcher_glib_qpa.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** 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 "qeventdispatcher_glib_qpa_p.h" + +#include "qapplication.h" + +#include "qplatformdefs.h" +#include "qapplication.h" + +#include <glib.h> +#include "qapplication_p.h" + +#include <qdebug.h> + +QT_BEGIN_NAMESPACE + +struct GUserEventSource +{ + GSource source; + QPAEventDispatcherGlib *q; +}; + +static gboolean userEventSourcePrepare(GSource *s, gint *timeout) +{ + Q_UNUSED(s) + Q_UNUSED(timeout) + + return QWindowSystemInterfacePrivate::windowSystemEventsQueued() > 0; +} + +static gboolean userEventSourceCheck(GSource *source) +{ + return userEventSourcePrepare(source, 0); +} + +static gboolean userEventSourceDispatch(GSource *s, GSourceFunc, gpointer) +{ + GUserEventSource * source = reinterpret_cast<GUserEventSource *>(s); + + QWindowSystemInterfacePrivate::WindowSystemEvent * event; + while (QWindowSystemInterfacePrivate::windowSystemEventsQueued()) { + event = QWindowSystemInterfacePrivate::getWindowSystemEvent(); + if (!event) + break; + + // send through event filter + if (source->q->filterEvent(event)) { + delete event; + continue; + } + QApplicationPrivate::processWindowSystemEvent(event); + delete event; + } + + return true; +} + + +static GSourceFuncs userEventSourceFuncs = { + userEventSourcePrepare, + userEventSourceCheck, + userEventSourceDispatch, + NULL, + NULL, + NULL +}; + +QPAEventDispatcherGlibPrivate::QPAEventDispatcherGlibPrivate(GMainContext *context) + : QEventDispatcherGlibPrivate(context) +{ + userEventSource = reinterpret_cast<GUserEventSource *>(g_source_new(&userEventSourceFuncs, + sizeof(GUserEventSource))); + userEventSource->q = 0; + g_source_set_can_recurse(&userEventSource->source, true); + g_source_attach(&userEventSource->source, mainContext); +} + + +QPAEventDispatcherGlib::QPAEventDispatcherGlib(QObject *parent) + : QEventDispatcherGlib(*new QPAEventDispatcherGlibPrivate, parent) +{ + Q_D(QPAEventDispatcherGlib); + d->userEventSource->q = this; +} + +QPAEventDispatcherGlib::~QPAEventDispatcherGlib() +{ + Q_D(QPAEventDispatcherGlib); + + g_source_destroy(&d->userEventSource->source); + g_source_unref(&d->userEventSource->source); + d->userEventSource = 0; +} + +bool QPAEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags) +{ + static bool init = false; + if (!init) { + if (QApplicationPrivate::platformIntegration()->createEventLoopIntegration()) { + qWarning("Eventloop integration is not supported by the glib event dispatcher"); + qWarning("Use the UNIX event dispatcher by defining environment variable QT_NO_GLIB=1"); + } + init = true; + } + return QEventDispatcherGlib::processEvents(flags); +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qeventdispatcher_glib_qpa_p.h b/src/gui/kernel/qeventdispatcher_glib_qpa_p.h new file mode 100644 index 0000000..1c32ab2 --- /dev/null +++ b/src/gui/kernel/qeventdispatcher_glib_qpa_p.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QEVENTDISPATCHER_GLIB_QPA_P_H +#define QEVENTDISPATCHER_GLIB_QPA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the QLibrary class. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/private/qeventdispatcher_glib_p.h> + +typedef struct _GMainContext GMainContext; + +QT_BEGIN_NAMESPACE +class QPAEventDispatcherGlibPrivate; + +class QPAEventDispatcherGlib : public QEventDispatcherGlib +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QPAEventDispatcherGlib) + +public: + explicit QPAEventDispatcherGlib(QObject *parent = 0); + ~QPAEventDispatcherGlib(); + + bool processEvents(QEventLoop::ProcessEventsFlags flags); +}; + +struct GUserEventSource; + +class QPAEventDispatcherGlibPrivate : public QEventDispatcherGlibPrivate +{ + Q_DECLARE_PUBLIC(QPAEventDispatcherGlib) +public: + QPAEventDispatcherGlibPrivate(GMainContext *context = 0); + GUserEventSource *userEventSource; +}; + + +QT_END_NAMESPACE + +#endif // QEVENTDISPATCHER_GLIB_QPA_P_H diff --git a/src/gui/kernel/qeventdispatcher_qpa.cpp b/src/gui/kernel/qeventdispatcher_qpa.cpp new file mode 100644 index 0000000..cb70141 --- /dev/null +++ b/src/gui/kernel/qeventdispatcher_qpa.cpp @@ -0,0 +1,302 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qplatformdefs.h" +#include "qapplication.h" +#include "qeventdispatcher_qpa_p.h" +#include "private/qeventdispatcher_unix_p.h" +#include "qapplication_p.h" +#include "qplatformeventloopintegration_qpa.h" + +#include <QWindowSystemInterface> +#include <QtCore/QElapsedTimer> +#include <QtCore/QAtomicInt> +#include <QtCore/QSemaphore> + +#include <errno.h> + +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + +class Rendezvous +{ +public: + void checkpoint() + { + if (state.testAndSetOrdered(0,1)) { + semaphore.acquire(); + } else if (state.testAndSetAcquire(1,0)) { + semaphore.release(); + } else { + qWarning("Barrier internal error"); + } + } +private: + QSemaphore semaphore; + QAtomicInt state; +}; + +class SelectWorker : public QThread +{ +public: + SelectWorker(QEventDispatcherQPAPrivate *eventDispatcherPrivate) + : QThread(), + m_edPrivate(eventDispatcherPrivate), + m_retVal(0) + { + } + + void setSelectValues(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds) + { + m_nfds = nfds; + m_readfds = readfds; + m_writefds = writefds; + m_exceptfds = exceptfds; + + + } + + int retVal() const { + return m_retVal; + } + +protected: + void run(); + +private: + QEventDispatcherQPAPrivate *m_edPrivate; + int m_retVal; + + int m_nfds; + fd_set *m_readfds, *m_writefds, *m_exceptfds; +}; + +class QEventDispatcherQPAPrivate : public QEventDispatcherUNIXPrivate +{ + Q_DECLARE_PUBLIC(QEventDispatcherQPA) +public: + QEventDispatcherQPAPrivate() + : eventLoopIntegration(0), + barrierBeforeBlocking(0), + barrierReturnValue(0), + selectReturnMutex(0), + selectWorkerNeedsSync(true), + selectWorkerHasResult(false), + m_integrationInitialised(false), + m_hasIntegration(false) + { + + } + + ~QEventDispatcherQPAPrivate() + { + delete selectWorker; + delete eventLoopIntegration; + delete barrierBeforeBlocking; + delete barrierReturnValue; + delete selectReturnMutex; + } + + bool hasIntegration() const + { + if (!m_integrationInitialised) { + QEventDispatcherQPAPrivate *that = const_cast<QEventDispatcherQPAPrivate *>(this); + if (qApp && (qApp->thread() == QThread::currentThread())) { // guiThread + if (QApplicationPrivate::platformIntegration()) { + that->eventLoopIntegration = QApplicationPrivate::platformIntegration()->createEventLoopIntegration(); + if (that->eventLoopIntegration) { + that->selectWorker = new SelectWorker(that); + that->barrierBeforeBlocking = new Rendezvous; + that->barrierReturnValue = new Rendezvous; + that->selectReturnMutex = new QMutex; + that->selectWorker->start(); + that->m_hasIntegration = true; + if (!QElapsedTimer::isMonotonic()) + qWarning("Having eventloop integration without monotonic timers can lead to undefined behaviour"); + } + } + } + that->m_integrationInitialised = true; + } + return m_hasIntegration; + } + + QPlatformEventLoopIntegration *eventLoopIntegration; + Rendezvous *barrierBeforeBlocking; + Rendezvous *barrierReturnValue; + + QMutex *selectReturnMutex; + bool selectWorkerNeedsSync; + bool selectWorkerHasResult; + + SelectWorker *selectWorker; +private: + bool m_integrationInitialised; + bool m_hasIntegration; +}; + +QEventDispatcherQPA::QEventDispatcherQPA(QObject *parent) + : QEventDispatcherUNIX(*new QEventDispatcherQPAPrivate, parent) +{ } + +QEventDispatcherQPA::~QEventDispatcherQPA() +{ } + +bool QEventDispatcherQPA::processEvents(QEventLoop::ProcessEventsFlags flags) +{ + Q_D(QEventDispatcherQPA); + int nevents = 0; + + // handle gui and posted events + d->interrupt = false; + QApplication::sendPostedEvents(); + + while (!d->interrupt) { // also flushes output buffer ###can be optimized + QWindowSystemInterfacePrivate::WindowSystemEvent *event; + if (!(flags & QEventLoop::ExcludeUserInputEvents) + && QWindowSystemInterfacePrivate::windowSystemEventsQueued() > 0) { + // process a pending user input event + event = QWindowSystemInterfacePrivate::getWindowSystemEvent(); + if (!event) + break; + } else { + break; + } + + if (filterEvent(event)) { + delete event; + continue; + } + nevents++; + + QApplicationPrivate::processWindowSystemEvent(event); + delete event; + } + + if (!d->interrupt) { + if (QEventDispatcherUNIX::processEvents(flags)) + return true; + } + return (nevents > 0); +} + +bool QEventDispatcherQPA::hasPendingEvents() +{ + extern uint qGlobalPostedEventsCount(); // from qapplication.cpp + return qGlobalPostedEventsCount() || QWindowSystemInterfacePrivate::windowSystemEventsQueued(); +} + +void QEventDispatcherQPA::registerSocketNotifier(QSocketNotifier *notifier) +{ + Q_D(QEventDispatcherQPA); + QEventDispatcherUNIX::registerSocketNotifier(notifier); + if (d->hasIntegration()) + wakeUp(); + +} + +void QEventDispatcherQPA::unregisterSocketNotifier(QSocketNotifier *notifier) +{ + Q_D(QEventDispatcherQPA); + QEventDispatcherUNIX::unregisterSocketNotifier(notifier); + if (d->hasIntegration()) + wakeUp(); +} + +void QEventDispatcherQPA::flush() +{ + if(qApp) + qApp->sendPostedEvents(); +} + + +int QEventDispatcherQPA::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + timeval *timeout) +{ + Q_D(QEventDispatcherQPA); + int retVal = 0; + if (d->hasIntegration()) { + qint64 timeoutmsec = 0; + if (timeout) + timeoutmsec = timeout->tv_sec * 1000 + (timeout->tv_usec/1000); + d->selectReturnMutex->lock(); + if (d->selectWorkerNeedsSync) { + if (d->selectWorkerHasResult) { + retVal = d->selectWorker->retVal(); + d->selectWorkerHasResult = false; + + d->selectReturnMutex->unlock(); + d->barrierReturnValue->checkpoint(); + return retVal; + } else { + d->selectWorkerNeedsSync = false; + d->selectWorker->setSelectValues(nfds,readfds, writefds, exceptfds); + d->barrierBeforeBlocking->checkpoint(); + } + } + d->selectReturnMutex->unlock(); + d->eventLoopIntegration->processEvents(timeoutmsec); + retVal = 0; //is 0 if select has not returned + } else { + retVal = QEventDispatcherUNIX::select(nfds, readfds, writefds, exceptfds, timeout); + } + return retVal; +} + +void SelectWorker::run() +{ + while(true) { + m_retVal = 0; + m_edPrivate->barrierBeforeBlocking->checkpoint(); // wait for mainthread + int tmpRet = qt_safe_select(m_nfds,m_readfds,m_writefds,m_exceptfds,0); + m_edPrivate->selectReturnMutex->lock(); + m_edPrivate->eventLoopIntegration->wakeup(); + + m_edPrivate->selectWorkerNeedsSync = true; + m_edPrivate->selectWorkerHasResult = true; + m_retVal = tmpRet; + + m_edPrivate->selectReturnMutex->unlock(); + m_edPrivate->barrierReturnValue->checkpoint(); + } +} +QT_END_NAMESPACE diff --git a/src/gui/kernel/qeventdispatcher_qpa_p.h b/src/gui/kernel/qeventdispatcher_qpa_p.h new file mode 100644 index 0000000..8065c3e --- /dev/null +++ b/src/gui/kernel/qeventdispatcher_qpa_p.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QEVENTDISPATCHER_QPA_P_H +#define QEVENTDISPATCHER_QPA_P_H + +// +// 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. +// + +#include "private/qeventdispatcher_unix_p.h" + +QT_BEGIN_NAMESPACE + +class QEventDispatcherQPAPrivate; + +class QEventDispatcherQPA : public QEventDispatcherUNIX +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QEventDispatcherQPA) + +public: + explicit QEventDispatcherQPA(QObject *parent = 0); + ~QEventDispatcherQPA(); + + bool processEvents(QEventLoop::ProcessEventsFlags flags); + bool hasPendingEvents(); + + void registerSocketNotifier(QSocketNotifier *notifier); + void unregisterSocketNotifier(QSocketNotifier *notifier); + + void flush(); + +protected: + int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + timeval *timeout); +}; + +QT_END_NAMESPACE + +#endif // QEVENTDISPATCHER_QPA_P_H diff --git a/src/gui/kernel/qgenericplugin_qpa.cpp b/src/gui/kernel/qgenericplugin_qpa.cpp new file mode 100644 index 0000000..43d6525 --- /dev/null +++ b/src/gui/kernel/qgenericplugin_qpa.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qgenericplugin_qpa.h" + +#ifndef QT_NO_LIBRARY + +QT_BEGIN_NAMESPACE + +/*! + \class QGenericPlugin + \ingroup plugins + \ingroup qpa + + \brief The QGenericPlugin class is an abstract base class for + window-system related plugins in Qt QPA. + + Note that this class is only available in \l{Qt QPA}. + + A mouse plugin can be created by subclassing + QGenericPlugin and reimplementing the pure virtual keys() and + create() functions. By exporting the derived class using the + Q_EXPORT_PLUGIN2() macro, The default implementation of the + QGenericPluginFactory class will automatically detect the plugin and + load the driver into the server application at run-time. See \l + {How to Create Qt Plugins} for details. + + \sa QGenericPluginFactory +*/ + +/*! + \fn QStringList QGenericPlugin::keys() const + + Implement this function to return the list of valid keys, i.e. the + drivers supported by this plugin. + + \sa create() +*/ + +/*! + Constructs a plugin with the given \a parent. + + Note that this constructor is invoked automatically by the + Q_EXPORT_PLUGIN2() macro, so there is no need for calling it + explicitly. +*/ +QGenericPlugin::QGenericPlugin(QObject *parent) + : QObject(parent) +{ +} + +/*! + Destroys the plugin. + + Note that Qt destroys a plugin automatically when it is no longer + used, so there is no need for calling the destructor explicitly. +*/ +QGenericPlugin::~QGenericPlugin() +{ +} + +/*! + \fn QObject* QGenericPlugin::create(const QString &key, const QString& specification) + + Implement this function to create a driver matching the type + specified by the given \a key and \a specification parameters. Note that + keys are case-insensitive. + + \sa keys() +*/ + +QT_END_NAMESPACE + +#endif // QT_NO_LIBRARY diff --git a/src/gui/kernel/qgenericplugin_qpa.h b/src/gui/kernel/qgenericplugin_qpa.h new file mode 100644 index 0000000..e1792cd --- /dev/null +++ b/src/gui/kernel/qgenericplugin_qpa.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QGENERICPLUGIN_QPA_H +#define QGENERICPLUGIN_QPA_H + +#include <QtCore/qplugin.h> +#include <QtCore/qfactoryinterface.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#ifndef QT_NO_LIBRARY + +//class QGenericObject; ????? + + struct Q_GUI_EXPORT QGenericPluginFactoryInterface : public QFactoryInterface +{ + virtual QObject* create(const QString &name, const QString &spec) = 0; +}; + +#define QGenericPluginFactoryInterface_iid "com.trolltech.Qt.QGenericPluginFactoryInterface" +Q_DECLARE_INTERFACE(QGenericPluginFactoryInterface, QGenericPluginFactoryInterface_iid) + +class Q_GUI_EXPORT QGenericPlugin : public QObject, public QGenericPluginFactoryInterface +{ + Q_OBJECT + Q_INTERFACES(QGenericPluginFactoryInterface:QFactoryInterface) +public: + explicit QGenericPlugin(QObject *parent = 0); + ~QGenericPlugin(); + + virtual QStringList keys() const = 0; + virtual QObject* create(const QString& name, const QString &spec) = 0; +}; + +#endif // QT_NO_LIBRARY + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGENERICPLUGIN_QPA_H diff --git a/src/gui/kernel/qgenericpluginfactory_qpa.cpp b/src/gui/kernel/qgenericpluginfactory_qpa.cpp new file mode 100644 index 0000000..abc575a --- /dev/null +++ b/src/gui/kernel/qgenericpluginfactory_qpa.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qgenericpluginfactory_qpa.h" + +#include "qapplication.h" +#include "private/qfactoryloader_p.h" +#include "qgenericplugin_qpa.h" +#include "qdebug.h" + +QT_BEGIN_NAMESPACE + +#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL) +#ifndef QT_NO_LIBRARY + +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, + (QGenericPluginFactoryInterface_iid, + QLatin1String("/generic"), Qt::CaseInsensitive)) + +#endif //QT_NO_LIBRARY +#endif //QT_MAKEDLL + +/*! + \class QGenericPluginFactory + \ingroup qpa + + \brief The QGenericPluginFactory class creates window-system + related plugin drivers in Qt QPA. + + Note that this class is only available in \l{Qt QPA}. + + + \sa QGenericPlugin +*/ + +/*! + Creates the driver specified by \a key, using the given \a specification. + + Note that the keys are case-insensitive. + + \sa keys() +*/ +QObject *QGenericPluginFactory::create(const QString& key, const QString &specification) +{ + QString driver = key.toLower(); + +#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL) +#ifndef QT_NO_LIBRARY + if (QGenericPluginFactoryInterface *factory = qobject_cast<QGenericPluginFactoryInterface*>(loader()->instance(driver))) + return factory->create(driver, specification); +#endif +#endif + return 0; +} + +/*! + Returns the list of valid keys, i.e. the available mouse drivers. + + \sa create() +*/ +QStringList QGenericPluginFactory::keys() +{ + QStringList list; + +#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL) +#ifndef QT_NO_LIBRARY + QStringList plugins = loader()->keys(); + for (int i = 0; i < plugins.size(); ++i) { + if (!list.contains(plugins.at(i))) + list += plugins.at(i); + } +#endif //QT_NO_LIBRARY +#endif //QT_MAKEDLL + return list; +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qgenericpluginfactory_qpa.h b/src/gui/kernel/qgenericpluginfactory_qpa.h new file mode 100644 index 0000000..59eac38 --- /dev/null +++ b/src/gui/kernel/qgenericpluginfactory_qpa.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QGENERICPLUGINFACTORY_QPA_H +#define QGENERICPLUGINFACTORY_QPA_H + +#include <QtCore/qstringlist.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QString; +class QObject; + +class Q_GUI_EXPORT QGenericPluginFactory +{ +public: + static QStringList keys(); + static QObject *create(const QString&, const QString &); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGENERICPLUGINFACTORY_QPA_H diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 6dd8127..8dd2db7 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -239,52 +239,53 @@ bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *, // TODO: sort contexts by the gesture type and check if one of the contexts // is already active. - bool ret = false; + bool consumeEventHint = false; // filter the event through recognizers typedef QMultiMap<QObject *, Qt::GestureType>::const_iterator ContextIterator; - for (ContextIterator cit = contexts.begin(), ce = contexts.end(); cit != ce; ++cit) { - Qt::GestureType gestureType = cit.value(); + ContextIterator contextEnd = contexts.end(); + for (ContextIterator context = contexts.begin(); context != contextEnd; ++context) { + Qt::GestureType gestureType = context.value(); QMap<Qt::GestureType, QGestureRecognizer *>::const_iterator - rit = m_recognizers.lowerBound(gestureType), - re = m_recognizers.upperBound(gestureType); - for (; rit != re; ++rit) { - QGestureRecognizer *recognizer = rit.value(); - QObject *target = cit.key(); + typeToRecognizerIterator = m_recognizers.lowerBound(gestureType), + typeToRecognizerEnd = m_recognizers.upperBound(gestureType); + for (; typeToRecognizerIterator != typeToRecognizerEnd; ++typeToRecognizerIterator) { + QGestureRecognizer *recognizer = typeToRecognizerIterator.value(); + QObject *target = context.key(); QGesture *state = getState(target, recognizer, gestureType); if (!state) continue; - QGestureRecognizer::Result result = recognizer->recognize(state, target, event); - QGestureRecognizer::Result type = result & QGestureRecognizer::ResultState_Mask; - result &= QGestureRecognizer::ResultHint_Mask; - if (type == QGestureRecognizer::TriggerGesture) { + QGestureRecognizer::Result recognizerResult = recognizer->recognize(state, target, event); + QGestureRecognizer::Result recognizerState = recognizerResult & QGestureRecognizer::ResultState_Mask; + QGestureRecognizer::Result resultHint = recognizerResult & QGestureRecognizer::ResultHint_Mask; + if (recognizerState == QGestureRecognizer::TriggerGesture) { DEBUG() << "QGestureManager:Recognizer: gesture triggered: " << state; triggeredGestures << state; - } else if (type == QGestureRecognizer::FinishGesture) { + } else if (recognizerState == QGestureRecognizer::FinishGesture) { DEBUG() << "QGestureManager:Recognizer: gesture finished: " << state; finishedGestures << state; - } else if (type == QGestureRecognizer::MayBeGesture) { + } else if (recognizerState == QGestureRecognizer::MayBeGesture) { DEBUG() << "QGestureManager:Recognizer: maybe gesture: " << state; newMaybeGestures << state; - } else if (type == QGestureRecognizer::CancelGesture) { + } else if (recognizerState == QGestureRecognizer::CancelGesture) { DEBUG() << "QGestureManager:Recognizer: not gesture: " << state; notGestures << state; - } else if (type == QGestureRecognizer::Ignore) { + } else if (recognizerState == QGestureRecognizer::Ignore) { DEBUG() << "QGestureManager:Recognizer: ignored the event: " << state; } else { DEBUG() << "QGestureManager:Recognizer: hm, lets assume the recognizer" << "ignored the event: " << state; } - if (result & QGestureRecognizer::ConsumeEventHint) { + if (resultHint & QGestureRecognizer::ConsumeEventHint) { DEBUG() << "QGestureManager: we were asked to consume the event: " << state; - ret = true; + consumeEventHint = true; } } } if (triggeredGestures.isEmpty() && finishedGestures.isEmpty() && newMaybeGestures.isEmpty() && notGestures.isEmpty()) - return ret; + return consumeEventHint; QSet<QGesture *> startedGestures = triggeredGestures - m_activeGestures; triggeredGestures &= m_activeGestures; @@ -381,7 +382,7 @@ bool QGestureManager::filterEventThroughContexts(const QMultiMap<QObject *, recycle(gesture); m_gestureTargets.remove(gesture); } - return ret; + return consumeEventHint; } // Cancel all gestures of children of the widget that original is associated with diff --git a/src/gui/kernel/qguifunctions_wince.cpp b/src/gui/kernel/qguifunctions_wince.cpp index 377dfe3..572698e 100644 --- a/src/gui/kernel/qguifunctions_wince.cpp +++ b/src/gui/kernel/qguifunctions_wince.cpp @@ -112,6 +112,9 @@ struct AygSIPINFO #ifndef SPI_GETSIPINFO #define SPI_GETSIPINFO 225 #endif +#ifndef SPI_GETPLATFORMTYPE +#define SPI_GETPLATFORMTYPE 257 +#endif typedef BOOL (*AygInitDialog)(AygSHINITDLGINFO*); typedef BOOL (*AygFullScreen)(HWND, DWORD); @@ -129,8 +132,6 @@ static void resolveAygLibs() if (!aygResolved) { aygResolved = true; QLibrary ayglib(QLatin1String("aygshell")); - if (!ayglib.load()) - return; ptrAygInitDialog = (AygInitDialog) ayglib.resolve("SHInitDialog"); ptrAygFullScreen = (AygFullScreen) ayglib.resolve("SHFullScreen"); ptrAygSHSipInfo = (AygSHSipInfo) ayglib.resolve("SHSipInfo"); diff --git a/src/gui/kernel/qguiplatformplugin.cpp b/src/gui/kernel/qguiplatformplugin.cpp index 2dd251b..98b9c4a 100644 --- a/src/gui/kernel/qguiplatformplugin.cpp +++ b/src/gui/kernel/qguiplatformplugin.cpp @@ -152,7 +152,7 @@ QString QGuiPlatformPlugin::styleName() return QLatin1String("Windows"); // default style for Symbian without S60 #elif defined(Q_WS_X11) && defined(Q_OS_IRIX) return QLatin1String("SGI"); // default style for X11 on IRIX -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_QPA) return QLatin1String("Plastique"); // default style for X11 and small devices #elif defined(Q_WS_MAC) return QLatin1String("Macintosh"); // default style for all Mac's diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 50b2354..b4a360a 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -76,7 +76,7 @@ static const MacSpecialKey entries[NumEntries] = { { Qt::Key_Backtab, 0x21E4 }, { Qt::Key_Backspace, 0x232B }, { Qt::Key_Return, 0x21B5 }, - { Qt::Key_Enter, 0x21B5 }, + { Qt::Key_Enter, 0x2324 }, { Qt::Key_Delete, 0x2326 }, { Qt::Key_Home, 0x2196 }, { Qt::Key_End, 0x2198 }, @@ -240,7 +240,7 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni \row \i Paste \i Ctrl+V, Shift+Ins \i Ctrl+V \i Ctrl+V, F18, Shift+Ins \i Ctrl+V, F18, Shift+Ins \i Ctrl+V \row \i Preferences \i \i Ctrl+, \i \i \i (none) \row \i Undo \i Ctrl+Z, Alt+Backspace \i Ctrl+Z \i Ctrl+Z, F14 \i Ctrl+Z, F14 \i Ctrl+Z - \row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z, Ctrl+Y \i Ctrl+Shift+Z \i Ctrl+Shift+Z \i (none) + \row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z \i Ctrl+Shift+Z \i Ctrl+Shift+Z \i (none) \row \i Back \i Alt+Left, Backspace \i Ctrl+[ \i Alt+Left \i Alt+Left \i (none) \row \i Forward \i Alt+Right, Shift+Backspace \i Ctrl+] \i Alt+Right \i Alt+Right \i (none) \row \i Refresh \i F5 \i F5 \i F5 \i Ctrl+R, F5 \i (none) @@ -718,7 +718,6 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::Close, 1, Qt::CTRL | Qt::Key_W, QApplicationPrivate::KB_Mac}, {QKeySequence::Cut, 1, Qt::CTRL | Qt::Key_X, QApplicationPrivate::KB_All}, {QKeySequence::Redo, 1, Qt::CTRL | Qt::Key_Y, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_S60}, - {QKeySequence::Redo, 0, Qt::CTRL | Qt::Key_Y, QApplicationPrivate::KB_Mac},//different priority from above {QKeySequence::Undo, 1, Qt::CTRL | Qt::Key_Z, QApplicationPrivate::KB_All}, {QKeySequence::Back, 1, Qt::CTRL | Qt::Key_BracketLeft, QApplicationPrivate::KB_Mac}, {QKeySequence::Forward, 1, Qt::CTRL | Qt::Key_BracketRight, QApplicationPrivate::KB_Mac}, @@ -747,7 +746,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::AddTab, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_N, QApplicationPrivate::KB_KDE}, {QKeySequence::SaveAs, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_S, QApplicationPrivate::KB_Gnome | QApplicationPrivate::KB_Mac}, {QKeySequence::Redo, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, - {QKeySequence::Redo, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Mac}, //different priority from above + {QKeySequence::Redo, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Mac}, {QKeySequence::PreviousChild, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, {QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Mac },//different priority from above {QKeySequence::Paste, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Insert, QApplicationPrivate::KB_X11}, @@ -1522,6 +1521,14 @@ QKeySequence &QKeySequence::operator=(const QKeySequence &other) } /*! + \fn void QKeySequence::swap(QKeySequence &other) + \since 4.8 + + Swaps key sequence \a other with this key sequence. This operation is very + fast and never fails. +*/ + +/*! \fn bool QKeySequence::operator!=(const QKeySequence &other) const Returns true if this key sequence is not equal to the \a other diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h index 5a973e3..a2352eb 100644 --- a/src/gui/kernel/qkeysequence.h +++ b/src/gui/kernel/qkeysequence.h @@ -179,6 +179,11 @@ public: operator int() const; int operator[](uint i) const; QKeySequence &operator=(const QKeySequence &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QKeySequence &operator=(QKeySequence &&other) + { qSwap(d, other.d); return *this; } +#endif + inline void swap(QKeySequence &other) { qSwap(d, other.d); } bool operator==(const QKeySequence &other) const; inline bool operator!= (const QKeySequence &other) const { return !(*this == other); } diff --git a/src/gui/kernel/qlayoutitem.cpp b/src/gui/kernel/qlayoutitem.cpp index 6a91d95..d1a82c2 100644 --- a/src/gui/kernel/qlayoutitem.cpp +++ b/src/gui/kernel/qlayoutitem.cpp @@ -516,9 +516,7 @@ bool QWidgetItem::hasHeightForWidth() const { if (isEmpty()) return false; - if (wid->layout()) - return wid->layout()->hasHeightForWidth(); - return wid->sizePolicy().hasHeightForWidth(); + return wid->d_func()->hasHeightForWidth(); } /*! diff --git a/src/gui/kernel/qmacdefines_mac.h b/src/gui/kernel/qmacdefines_mac.h index d767470..d190d23 100644 --- a/src/gui/kernel/qmacdefines_mac.h +++ b/src/gui/kernel/qmacdefines_mac.h @@ -94,12 +94,6 @@ Yes, it is an informative comment ;-) #include <QtCore/qglobal.h> -#undef OLD_DEBUG -#ifdef DEBUG -# define OLD_DEBUG DEBUG -# undef DEBUG -#endif -#define DEBUG 0 #ifdef qDebug # define old_qDebug qDebug # undef qDebug @@ -179,12 +173,6 @@ typedef AERecord AppleEvent; #undef check #endif -#undef DEBUG -#ifdef OLD_DEBUG -# define DEBUG OLD_DEBUG -# undef OLD_DEBUG -#endif - #ifdef old_qDebug # undef qDebug # define qDebug QT_NO_QDEBUG_MACRO diff --git a/src/gui/kernel/qpalette.h b/src/gui/kernel/qpalette.h index f797f86..7b7b41d 100644 --- a/src/gui/kernel/qpalette.h +++ b/src/gui/kernel/qpalette.h @@ -78,6 +78,14 @@ public: QPalette(const QPalette &palette); ~QPalette(); QPalette &operator=(const QPalette &palette); +#ifdef Q_COMPILER_RVALUE_REFS + inline QPalette &operator=(QPalette &&other) + { + resolve_mask = other.resolve_mask; + current_group = other.current_group; + qSwap(d, other.d); return *this; + } +#endif operator QVariant() const; // Do not change the order, the serialization format depends on it diff --git a/src/gui/kernel/qplatformcursor_qpa.cpp b/src/gui/kernel/qplatformcursor_qpa.cpp new file mode 100644 index 0000000..ac557b9 --- /dev/null +++ b/src/gui/kernel/qplatformcursor_qpa.cpp @@ -0,0 +1,660 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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 "qplatformcursor_qpa.h" + +#include <QWidget> +#include <QPainter> +#include <QBitmap> +#include <QApplication> + +#include <QDebug> + +QT_BEGIN_NAMESPACE + +QList <QWeakPointer<QPlatformCursor> > QPlatformCursorPrivate::instances; + +/*! + \class QGraphicsSystemCursor + + \brief The QGraphicsSystemCursor class provides information about + pointer device events (movement, buttons), and requests to change + the currently displayed cursor. + + Note that QGraphicsSystemCursor does not include any graphics for + display. An application that sets a QCursor may provide its own + graphics. + + \sa QGraphicsSystemCursorImage +*/ + +/*! + \fn virtual void QGraphicsSystemCursor::pointerEvent(const QMouseEvent & event) + + This method is called by Qt whenever a QMouseEvent is generated by the + underlying pointer input. \a event is a reference to the QMouseEvent in + question. A default do-nothing implementation is provided. + + \sa QApplicationPrivate::handleMouseEvent() +*/ + +/*! + \fn virtual void QGraphicsSystemCursor::changeCursor(QCursor * widgetCursor, QWidget * widget) + + \brief This method is called by Qt whenever the cursor graphic should be changed. + + Implementation of this method is mandatory for a subclass of QGraphicsSystemCursor. + + \a widgetCursor is a pointer to the QCursor that should be displayed. + + \a widget is a pointer to the widget currently displayed at QCursor::pos(). Note + that this may be 0 if the current position is not occupied by a displayed widget. + + \sa QApplicationPrivate::handleMouseEvent(), QCursor::pos() +*/ + +/*! + \fn QGraphicsSystemCursor::QGraphicsSystemCursor() + + \brief Constructs a QGraphicsSystemCursor +*/ +QPlatformCursor::QPlatformCursor(QPlatformScreen *scr ) + : screen(scr) +{ + QPlatformCursorPrivate::instances.append(this); +} + +// End of display and pointer event handling code +// Beginning of built-in cursor graphics +// from src/gui/embedded/QGraphicsSystemCursorImage_qws.cpp + +/*! + \class QGraphicsSystemCursorImage + + \brief The QGraphicsSystemCursorImage class provides a set of graphics + intended to be used as cursors. + + \sa QGraphicsSystemCursor +*/ + +static QPlatformCursorImage *systemCursorTable[Qt::LastCursor+1]; +static bool systemCursorTableInit = false; + +// 16 x 16 +static const uchar cur_arrow_bits[] = { + 0x07, 0x00, 0x39, 0x00, 0xc1, 0x01, 0x02, 0x0e, 0x02, 0x10, 0x02, 0x08, + 0x04, 0x04, 0x04, 0x02, 0x04, 0x04, 0x88, 0x08, 0x48, 0x11, 0x28, 0x22, + 0x10, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 0x00 }; +static const uchar mcur_arrow_bits[] = { + 0x07, 0x00, 0x3f, 0x00, 0xff, 0x01, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x0f, + 0xfc, 0x07, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x0f, 0x78, 0x1f, 0x38, 0x3e, + 0x10, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00 }; + +static const unsigned char cur_up_arrow_bits[] = { + 0x80, 0x00, 0x40, 0x01, 0x40, 0x01, 0x20, 0x02, 0x20, 0x02, 0x10, 0x04, + 0x10, 0x04, 0x08, 0x08, 0x78, 0x0f, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, + 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0xc0, 0x01}; +static const unsigned char mcur_up_arrow_bits[] = { + 0x80, 0x00, 0xc0, 0x01, 0xc0, 0x01, 0xe0, 0x03, 0xe0, 0x03, 0xf0, 0x07, + 0xf0, 0x07, 0xf8, 0x0f, 0xf8, 0x0f, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, + 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01}; + +static const unsigned char cur_cross_bits[] = { + 0xc0, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, + 0x7f, 0x7f, 0x01, 0x40, 0x7f, 0x7f, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, + 0x40, 0x01, 0x40, 0x01, 0xc0, 0x01, 0x00, 0x00}; +static const unsigned char mcur_cross_bits[] = { + 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, + 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, + 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0x00, 0x00}; + +static const uchar cur_ibeam_bits[] = { + 0x00, 0x00, 0xe0, 0x03, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, + 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, + 0x80, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00 }; +static const uchar mcur_ibeam_bits[] = { + 0xf0, 0x07, 0xf0, 0x07, 0xf0, 0x07, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, + 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, + 0xf0, 0x07, 0xf0, 0x07, 0xf0, 0x07, 0x00, 0x00 }; + +static const uchar cur_ver_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, + 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf0, 0x0f, + 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00 }; +static const uchar mcur_ver_bits[] = { + 0x00, 0x00, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0, 0x1f, 0xf8, 0x3f, + 0xfc, 0x7f, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xfc, 0x7f, 0xf8, 0x3f, + 0xf0, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03 }; + +static const uchar cur_hor_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x30, 0x18, + 0x38, 0x38, 0xfc, 0x7f, 0xfc, 0x7f, 0x38, 0x38, 0x30, 0x18, 0x20, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar mcur_hor_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x60, 0x0c, 0x70, 0x1c, 0x78, 0x3c, + 0xfc, 0x7f, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfc, 0x7f, 0x78, 0x3c, + 0x70, 0x1c, 0x60, 0x0c, 0x40, 0x04, 0x00, 0x00 }; +static const uchar cur_bdiag_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x3e, + 0x00, 0x37, 0x88, 0x23, 0xd8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0xf8, 0x00, + 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar mcur_bdiag_bits[] = { + 0x00, 0x00, 0xc0, 0x7f, 0x80, 0x7f, 0x00, 0x7f, 0x00, 0x7e, 0x04, 0x7f, + 0x8c, 0x7f, 0xdc, 0x77, 0xfc, 0x63, 0xfc, 0x41, 0xfc, 0x00, 0xfc, 0x01, + 0xfc, 0x03, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00 }; +static const uchar cur_fdiag_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, + 0xf8, 0x00, 0xd8, 0x01, 0x88, 0x23, 0x00, 0x37, 0x00, 0x3e, 0x00, 0x3c, + 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00 }; +static const uchar mcur_fdiag_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x03, 0xfc, 0x01, 0xfc, 0x00, + 0xfc, 0x41, 0xfc, 0x63, 0xdc, 0x77, 0x8c, 0x7f, 0x04, 0x7f, 0x00, 0x7e, + 0x00, 0x7f, 0x80, 0x7f, 0xc0, 0x7f, 0x00, 0x00 }; + +// 20 x 20 +static const uchar forbidden_bits[] = { + 0x00,0x00,0x00,0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xf0,0x00,0x38,0xc0,0x01, + 0x7c,0x80,0x03,0xec,0x00,0x03,0xce,0x01,0x07,0x86,0x03,0x06,0x06,0x07,0x06, + 0x06,0x0e,0x06,0x06,0x1c,0x06,0x0e,0x38,0x07,0x0c,0x70,0x03,0x1c,0xe0,0x03, + 0x38,0xc0,0x01,0xf0,0xe0,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00,0x00,0x00,0x00 }; + +static const uchar forbiddenm_bits[] = { + 0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xff,0x00,0xf8,0xff,0x01,0xfc,0xf0,0x03, + 0xfe,0xc0,0x07,0xfe,0x81,0x07,0xff,0x83,0x0f,0xcf,0x07,0x0f,0x8f,0x0f,0x0f, + 0x0f,0x1f,0x0f,0x0f,0x3e,0x0f,0x1f,0xfc,0x0f,0x1e,0xf8,0x07,0x3e,0xf0,0x07, + 0xfc,0xe0,0x03,0xf8,0xff,0x01,0xf0,0xff,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00}; + +// 32 x 32 +static const uchar wait_data_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, + 0x00, 0x04, 0x40, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x08, 0x20, 0x00, + 0x00, 0x08, 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, + 0x00, 0x50, 0x15, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x40, 0x05, 0x00, + 0x00, 0x80, 0x02, 0x00, 0x00, 0x40, 0x04, 0x00, 0x00, 0x20, 0x08, 0x00, + 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x88, 0x22, 0x00, + 0x00, 0x48, 0x25, 0x00, 0x00, 0xa8, 0x2a, 0x00, 0x00, 0xfc, 0x7f, 0x00, + 0x00, 0x04, 0x40, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar wait_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, + 0x00, 0xfc, 0x7f, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0xf8, 0x3f, 0x00, + 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00, + 0x00, 0xf0, 0x1f, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xc0, 0x07, 0x00, + 0x00, 0x80, 0x03, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00, + 0x00, 0xf0, 0x1f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00, + 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x7f, 0x00, + 0x00, 0xfc, 0x7f, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +static const uchar hsplit_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, + 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, + 0x00, 0x41, 0x82, 0x00, 0x80, 0x41, 0x82, 0x01, 0xc0, 0x7f, 0xfe, 0x03, + 0x80, 0x41, 0x82, 0x01, 0x00, 0x41, 0x82, 0x00, 0x00, 0x40, 0x02, 0x00, + 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, + 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar hsplitm_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, + 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe3, 0xc7, 0x00, + 0x80, 0xe3, 0xc7, 0x01, 0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07, + 0xc0, 0xff, 0xff, 0x03, 0x80, 0xe3, 0xc7, 0x01, 0x00, 0xe3, 0xc7, 0x00, + 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, + 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar vsplit_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, + 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar vsplitm_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00, + 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, + 0x00, 0xc0, 0x01, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, + 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, + 0x80, 0xff, 0xff, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, + 0x00, 0xc0, 0x01, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00, + 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar phand_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, + 0x7e, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00, + 0x08, 0x08, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, 0x08, 0x22, 0x00, 0x00, + 0x30, 0x41, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0x40, 0x12, 0x00, 0x00, + 0x80, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar phandm_bits[] = { + 0xfe, 0x01, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, + 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, + 0xfc, 0x1f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, + 0xf8, 0xff, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, + 0xc0, 0x1f, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +static const uchar size_all_data_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x80, 0x81, 0xc0, 0x00, + 0xc0, 0xff, 0xff, 0x01, 0x80, 0x81, 0xc0, 0x00, 0x00, 0x81, 0x40, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar size_all_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00, + 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc2, 0x21, 0x00, + 0x00, 0xc3, 0x61, 0x00, 0x80, 0xc3, 0xe1, 0x00, 0xc0, 0xff, 0xff, 0x01, + 0xe0, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x01, 0x80, 0xc3, 0xe1, 0x00, + 0x00, 0xc3, 0x61, 0x00, 0x00, 0xc2, 0x21, 0x00, 0x00, 0xc0, 0x01, 0x00, + 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x03, 0x00, + 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +static const uchar whatsthis_bits[] = { + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0xf0, 0x07, 0x00, + 0x09, 0x18, 0x0e, 0x00, 0x11, 0x1c, 0x0e, 0x00, 0x21, 0x1c, 0x0e, 0x00, + 0x41, 0x1c, 0x0e, 0x00, 0x81, 0x1c, 0x0e, 0x00, 0x01, 0x01, 0x07, 0x00, + 0x01, 0x82, 0x03, 0x00, 0xc1, 0xc7, 0x01, 0x00, 0x49, 0xc0, 0x01, 0x00, + 0x95, 0xc0, 0x01, 0x00, 0x93, 0xc0, 0x01, 0x00, 0x21, 0x01, 0x00, 0x00, + 0x20, 0xc1, 0x01, 0x00, 0x40, 0xc2, 0x01, 0x00, 0x40, 0x02, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; +static const uchar whatsthism_bits[] = { + 0x01, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0x00, 0x07, 0xf8, 0x0f, 0x00, + 0x0f, 0xfc, 0x1f, 0x00, 0x1f, 0x3e, 0x1f, 0x00, 0x3f, 0x3e, 0x1f, 0x00, + 0x7f, 0x3e, 0x1f, 0x00, 0xff, 0x3e, 0x1f, 0x00, 0xff, 0x9d, 0x0f, 0x00, + 0xff, 0xc3, 0x07, 0x00, 0xff, 0xe7, 0x03, 0x00, 0x7f, 0xe0, 0x03, 0x00, + 0xf7, 0xe0, 0x03, 0x00, 0xf3, 0xe0, 0x03, 0x00, 0xe1, 0xe1, 0x03, 0x00, + 0xe0, 0xe1, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; + +static const uchar busy_bits[] = { + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x41, 0xe0, 0xff, 0x00, 0x81, 0x20, 0x80, 0x00, 0x01, 0xe1, 0xff, 0x00, + 0x01, 0x42, 0x40, 0x00, 0xc1, 0x47, 0x40, 0x00, 0x49, 0x40, 0x55, 0x00, + 0x95, 0x80, 0x2a, 0x00, 0x93, 0x00, 0x15, 0x00, 0x21, 0x01, 0x0a, 0x00, + 0x20, 0x01, 0x11, 0x00, 0x40, 0x82, 0x20, 0x00, 0x40, 0x42, 0x44, 0x00, + 0x80, 0x41, 0x4a, 0x00, 0x00, 0x40, 0x55, 0x00, 0x00, 0xe0, 0xff, 0x00, + 0x00, 0x20, 0x80, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uchar busym_bits[] = { + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, + 0x7f, 0xe0, 0xff, 0x00, 0xff, 0xe0, 0xff, 0x00, 0xff, 0xe1, 0xff, 0x00, + 0xff, 0xc3, 0x7f, 0x00, 0xff, 0xc7, 0x7f, 0x00, 0x7f, 0xc0, 0x7f, 0x00, + 0xf7, 0x80, 0x3f, 0x00, 0xf3, 0x00, 0x1f, 0x00, 0xe1, 0x01, 0x0e, 0x00, + 0xe0, 0x01, 0x1f, 0x00, 0xc0, 0x83, 0x3f, 0x00, 0xc0, 0xc3, 0x7f, 0x00, + 0x80, 0xc1, 0x7f, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, 0xe0, 0xff, 0x00, + 0x00, 0xe0, 0xff, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +// 16 x 16 +static const uchar openhand_bits[] = { + 0x80,0x01,0x58,0x0e,0x64,0x12,0x64,0x52,0x48,0xb2,0x48,0x92, + 0x16,0x90,0x19,0x80,0x11,0x40,0x02,0x40,0x04,0x40,0x04,0x20, + 0x08,0x20,0x10,0x10,0x20,0x10,0x00,0x00}; +static const uchar openhandm_bits[] = { + 0x80,0x01,0xd8,0x0f,0xfc,0x1f,0xfc,0x5f,0xf8,0xff,0xf8,0xff, + 0xfe,0xff,0xff,0xff,0xff,0x7f,0xfe,0x7f,0xfc,0x7f,0xfc,0x3f, + 0xf8,0x3f,0xf0,0x1f,0xe0,0x1f,0x00,0x00}; +static const uchar closedhand_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0x48,0x32,0x08,0x50, + 0x10,0x40,0x18,0x40,0x04,0x40,0x04,0x20,0x08,0x20,0x10,0x10, + 0x20,0x10,0x20,0x10,0x00,0x00,0x00,0x00}; +static const uchar closedhandm_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0xf8,0x3f,0xf8,0x7f, + 0xf0,0x7f,0xf8,0x7f,0xfc,0x7f,0xfc,0x3f,0xf8,0x3f,0xf0,0x1f, + 0xe0,0x1f,0xe0,0x1f,0x00,0x00,0x00,0x00}; + +void QPlatformCursorImage::createSystemCursor(int id) +{ + if (!systemCursorTableInit) { + for (int i = 0; i <= Qt::LastCursor; i++) + systemCursorTable[i] = 0; + systemCursorTableInit = true; + } + switch (id) { + // 16x16 cursors + case Qt::ArrowCursor: + systemCursorTable[Qt::ArrowCursor] = + new QPlatformCursorImage(cur_arrow_bits, mcur_arrow_bits, 16, 16, 0, 0); + break; + + case Qt::UpArrowCursor: + systemCursorTable[Qt::UpArrowCursor] = + new QPlatformCursorImage(cur_up_arrow_bits, mcur_up_arrow_bits, 16, 16, 7, 0); + break; + + case Qt::CrossCursor: + systemCursorTable[Qt::CrossCursor] = + new QPlatformCursorImage(cur_cross_bits, mcur_cross_bits, 16, 16, 7, 7); + break; + + case Qt::IBeamCursor: + systemCursorTable[Qt::IBeamCursor] = + new QPlatformCursorImage(cur_ibeam_bits, mcur_ibeam_bits, 16, 16, 7, 7); + break; + + case Qt::SizeVerCursor: + systemCursorTable[Qt::SizeVerCursor] = + new QPlatformCursorImage(cur_ver_bits, mcur_ver_bits, 16, 16, 7, 7); + break; + + case Qt::SizeHorCursor: + systemCursorTable[Qt::SizeHorCursor] = + new QPlatformCursorImage(cur_hor_bits, mcur_hor_bits, 16, 16, 7, 7); + break; + + case Qt::SizeBDiagCursor: + systemCursorTable[Qt::SizeBDiagCursor] = + new QPlatformCursorImage(cur_bdiag_bits, mcur_bdiag_bits, 16, 16, 7, 7); + break; + + case Qt::SizeFDiagCursor: + systemCursorTable[Qt::SizeFDiagCursor] = + new QPlatformCursorImage(cur_fdiag_bits, mcur_fdiag_bits, 16, 16, 7, 7); + break; + + case Qt::BlankCursor: + systemCursorTable[Qt::BlankCursor] = + new QPlatformCursorImage(0, 0, 0, 0, 0, 0); + break; + + // 20x20 cursors + case Qt::ForbiddenCursor: + systemCursorTable[Qt::ForbiddenCursor] = + new QPlatformCursorImage(forbidden_bits, forbiddenm_bits, 20, 20, 10, 10); + break; + + // 32x32 cursors + case Qt::WaitCursor: + systemCursorTable[Qt::WaitCursor] = + new QPlatformCursorImage(wait_data_bits, wait_mask_bits, 32, 32, 15, 15); + break; + + case Qt::SplitVCursor: + systemCursorTable[Qt::SplitVCursor] = + new QPlatformCursorImage(vsplit_bits, vsplitm_bits, 32, 32, 15, 15); + break; + + case Qt::SplitHCursor: + systemCursorTable[Qt::SplitHCursor] = + new QPlatformCursorImage(hsplit_bits, hsplitm_bits, 32, 32, 15, 15); + break; + + case Qt::SizeAllCursor: + systemCursorTable[Qt::SizeAllCursor] = + new QPlatformCursorImage(size_all_data_bits, size_all_mask_bits, 32, 32, 15, 15); + break; + + case Qt::PointingHandCursor: + systemCursorTable[Qt::PointingHandCursor] = + new QPlatformCursorImage(phand_bits, phandm_bits, 32, 32, 0, 0); + break; + + case Qt::WhatsThisCursor: + systemCursorTable[Qt::WhatsThisCursor] = + new QPlatformCursorImage(whatsthis_bits, whatsthism_bits, 32, 32, 0, 0); + break; + case Qt::BusyCursor: + systemCursorTable[Qt::BusyCursor] = + new QPlatformCursorImage(busy_bits, busym_bits, 32, 32, 0, 0); + break; + + case Qt::OpenHandCursor: + systemCursorTable[Qt::OpenHandCursor] = + new QPlatformCursorImage(openhand_bits, openhandm_bits, 16, 16, 8, 8); + break; + case Qt::ClosedHandCursor: + systemCursorTable[Qt::ClosedHandCursor] = + new QPlatformCursorImage(closedhand_bits, closedhandm_bits, 16, 16, 8, 8); + break; + default: + qWarning("Unknown system cursor %d", id); + } +} + +/*! + \fn void QGraphicsSystemCursorImage::set(Qt::CursorShape id) + + \brief Calling this method sets the cursor image to the specified shape + + \a id is one of the defined Qt::CursorShape values. + + If id is invalid, Qt::BitmapCursor, or unknown by the implementation, + Qt::ArrowCursor is used instead. +*/ + +void QPlatformCursorImage::set(Qt::CursorShape id) +{ + QPlatformCursorImage *cursor = 0; + if (id >= 0 && id <= Qt::LastCursor) { + if (!systemCursorTable[id]) + createSystemCursor(id); + cursor = systemCursorTable[id]; + } + + if (cursor == 0) { + if (!systemCursorTable[Qt::ArrowCursor]) + createSystemCursor(Qt::ArrowCursor); + cursor = systemCursorTable[Qt::ArrowCursor]; + } + cursorImage = cursor->cursorImage; + hot = cursor->hot; +} + +/*! + \fn void QGraphicsSystemCursorImage::set(const QImage * image, int hx, int hy) + + \brief Set the cursor image to the specified QImage, with the hotsport at (hx, hy) + + \a image A pointer to a QImage + + \a hx The x coordinate of the cursor's hotspot + + \a hy the y coordinate of the cursor's hotspot +*/ + +void QPlatformCursorImage::set(const QImage &image, int hx, int hy) +{ + hot.setX(hx); + hot.setY(hy); + cursorImage = image; +} + +/*! + \fn void QGraphicsSystemCursorImage::set(const uchar *data, const uchar *mask, int width, int height, int hx, int hy) + + \brief set the cursor image to the graphic represented by the combination of data, mask, + width, and height + + \a data The pixel data of the graphic + + \a mask Mask data for the graphic. pixels in data with a corresponding mask bit of 0 are not drawn + + \a width The width of the graphic in pixels + + \a height The height of the graphic in pixels + + \a hx The X hotspot of the cursor graphic + + \a hy The Y hotspot of the cursor graphic +*/ +void QPlatformCursorImage::set(const uchar *data, const uchar *mask, + int width, int height, int hx, int hy) +{ + hot.setX(hx); + hot.setY(hy); + + cursorImage = QImage(width,height, QImage::Format_Indexed8); + + if (!width || !height || !data || !mask || cursorImage.isNull()) + return; + + cursorImage.setNumColors(3); + cursorImage.setColor(0, 0xff000000); + cursorImage.setColor(1, 0xffffffff); + cursorImage.setColor(2, 0x00000000); + + int bytesPerLine = (width + 7) / 8; + int p = 0; + int d, m; + + int x = -1, w = 0; + + uchar *cursor_data = cursorImage.bits(); + int bpl = cursorImage.bytesPerLine(); + for (int i = 0; i < height; i++) + { + for (int j = 0; j < bytesPerLine; j++, data++, mask++) + { + for (int b = 0; b < 8 && j*8+b < width; b++) + { + d = *data & (1 << b); + m = *mask & (1 << b); + if (d && m) p = 0; + else if (!d && m) p = 1; + else p = 2; + cursor_data[j*8+b] = p; + + // calc region + if (x < 0 && m) + x = j*8+b; + else if (x >= 0 && !m) { + x = -1; + w = 0; + } + if (m) + w++; + } + } + if (x >= 0) { + x = -1; + w = 0; + } + cursor_data += bpl; + } + +} + +/*! + \fn QGraphicsSystemCursorImage::QGraphicsSystemCursorImage(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY) + + \brief set the cursor image to the graphic represented by the combination of data, mask, + width, and height + + \a data The pixel data of the graphic + + \a mask Mask data for the graphic. pixels in data with a corresponding mask bit of 0 are not drawn + + \a width The width of the graphic in pixels + + \a height The height of the graphic in pixels + + \a hotX The X hotspot of the cursor graphic + + \a hotY The Y hotspot of the cursor graphic + + \sa set +*/ + +/*! + \fn QImage *QGraphicsSystemCursorImage::image() + + \brief Return the cursor graphic as a pointer to a QImage +*/ + +/*! + \fn QPoint QGraphicsSystemCursorImage::hotspot() + + \brief Return the cursor's hotspot +*/ + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformcursor_qpa.h b/src/gui/kernel/qplatformcursor_qpa.h new file mode 100644 index 0000000..71d0e87 --- /dev/null +++ b/src/gui/kernel/qplatformcursor_qpa.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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$ +** +****************************************************************************/ +#ifndef QGRAPHICSSYSTEMCURSOR_H +#define QGRAPHICSSYSTEMCURSOR_H + +#include <QtCore/QList> +#include <QtGui/QImage> +#include <QtGui/QMouseEvent> +#include <QtCore/QWeakPointer> +#include <QtCore/QObject> +#include <QtGui/QPlatformScreen> +#include <QtGui/QCursor> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +// Cursor graphics management +class Q_GUI_EXPORT QPlatformCursorImage { +public: + QPlatformCursorImage(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY) + { set(data, mask, width, height, hotX, hotY); } + QImage * image() { return &cursorImage; } + QPoint hotspot() { return hot; } + void set(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY); + void set(const QImage &image, int hx, int hy); + void set(Qt::CursorShape); +private: + static void createSystemCursor(int id); + QImage cursorImage; + QPoint hot; +}; + +class QPlatformCursor; + +class QPlatformCursorPrivate { +public: + static QList<QWeakPointer<QPlatformCursor> > getInstances() { return instances; } + static QList<QWeakPointer<QPlatformCursor> > instances; +}; + +class Q_GUI_EXPORT QPlatformCursor : public QObject { +public: + QPlatformCursor(QPlatformScreen *); + + // input methods + virtual void pointerEvent(const QMouseEvent & event) { Q_UNUSED(event); } + virtual void changeCursor(QCursor * widgetCursor, QWidget * widget) = 0; + +protected: + QPlatformScreen* screen; // Where to request an update + +private: + Q_DECLARE_PRIVATE(QPlatformCursor); + friend void qt_qpa_set_cursor(QWidget * w, bool force); + friend class QApplicationPrivate; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGRAPHICSSYSTEMCURSOR_H diff --git a/src/gui/kernel/qplatformeventloopintegration_qpa.cpp b/src/gui/kernel/qplatformeventloopintegration_qpa.cpp new file mode 100644 index 0000000..8bdba5e --- /dev/null +++ b/src/gui/kernel/qplatformeventloopintegration_qpa.cpp @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + diff --git a/src/gui/kernel/qplatformeventloopintegration_qpa.h b/src/gui/kernel/qplatformeventloopintegration_qpa.h new file mode 100644 index 0000000..a06fecf --- /dev/null +++ b/src/gui/kernel/qplatformeventloopintegration_qpa.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QPLATFORMEVENTLOOPINTEGRATION_QPA_H +#define QPLATFORMEVENTLOOPINTEGRATION_QPA_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QPlatformEventLoopIntegration +{ +public: + virtual void processEvents( qint64 msec ) = 0; + virtual void wakeup() = 0; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLATFORMEVENTLOOPINTEGRATION_QPA_H diff --git a/src/gui/kernel/qplatformglcontext_qpa.cpp b/src/gui/kernel/qplatformglcontext_qpa.cpp new file mode 100644 index 0000000..36db2b0 --- /dev/null +++ b/src/gui/kernel/qplatformglcontext_qpa.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qplatformglcontext_qpa.h" + +QPlatformGLContext::~QPlatformGLContext() +{ } + +static QPlatformGLContext *staticSharedContext = 0; + +void QPlatformGLContext::setDefaultSharedContext(QPlatformGLContext *sharedContext) +{ + staticSharedContext = sharedContext; +} + +QPlatformGLContext *QPlatformGLContext::defaultSharedContext() +{ + return staticSharedContext; +} diff --git a/src/gui/kernel/qplatformglcontext_qpa.h b/src/gui/kernel/qplatformglcontext_qpa.h new file mode 100644 index 0000000..ed41723 --- /dev/null +++ b/src/gui/kernel/qplatformglcontext_qpa.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QPLATFORM_GL_CONTEXT_H +#define QPLATFORM_GL_CONTEXT_H + +#include <QtCore/qnamespace.h> +#include <QtGui/QPlatformWindowFormat> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class Q_OPENGL_EXPORT QPlatformGLContext +{ +public: + virtual ~QPlatformGLContext(); + + virtual void makeCurrent() = 0; + virtual void doneCurrent() = 0; + virtual void swapBuffers() = 0; + virtual void* getProcAddress(const QString& procName) = 0; + + virtual QPlatformWindowFormat platformWindowFormat() const = 0; + + static QPlatformGLContext *defaultSharedContext(); + +protected: + + static void setDefaultSharedContext(QPlatformGLContext *sharedContext); + +}; + +QT_END_NAMESPACE + +QT_END_HEADER + + +#endif // QPLATFORM_GL_INTEGRATION_P_H diff --git a/src/gui/kernel/qplatformintegration_qpa.cpp b/src/gui/kernel/qplatformintegration_qpa.cpp new file mode 100644 index 0000000..e2a493d --- /dev/null +++ b/src/gui/kernel/qplatformintegration_qpa.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qplatformintegration_qpa.h" + +#include <QtGui/QPlatformFontDatabase> + +QT_BEGIN_NAMESPACE + +QPixmap QPlatformIntegration::grabWindow(WId window, int x, int y, int width, int height) const +{ + Q_UNUSED(window); + Q_UNUSED(x); + Q_UNUSED(y); + Q_UNUSED(width); + Q_UNUSED(height); + return QPixmap(); +} + +QPlatformEventLoopIntegration *QPlatformIntegration::createEventLoopIntegration() const +{ + return 0; +} + +bool QPlatformIntegration::hasOpenGL() const +{ + return false; +} + +QPlatformFontDatabase *QPlatformIntegration::fontDatabase() const +{ + static QPlatformFontDatabase *db = 0; + if (!db) { + db = new QPlatformFontDatabase; + } + return db; +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformintegration_qpa.h b/src/gui/kernel/qplatformintegration_qpa.h new file mode 100644 index 0000000..b1f4e5f --- /dev/null +++ b/src/gui/kernel/qplatformintegration_qpa.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QPLATFORMINTEGRATION_H +#define QPLATFORMINTEGRATION_H + +#include <QtGui/qwindowdefs.h> +#include <QtGui/private/qwindowsurface_p.h> +#include <QtGui/private/qpixmapdata_p.h> +#include <QtGui/qplatformscreen_qpa.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QPlatformWindow; +class QWindowSurface; +class QBlittable; +class QWidget; +class QPlatformEventLoopIntegration; +class QPlatformFontDatabase; + +class Q_GUI_EXPORT QPlatformIntegration +{ +public: + virtual ~QPlatformIntegration() { } + +// GraphicsSystem functions + virtual QPixmapData *createPixmapData(QPixmapData::PixelType type) const = 0; + virtual QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId = 0) const = 0; + virtual QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const = 0; + virtual void moveToScreen(QWidget *window, int screen) {Q_UNUSED(window); Q_UNUSED(screen);} + +// Window System functions + virtual QList<QPlatformScreen *> screens() const = 0; + virtual bool isVirtualDesktop() { return false; } + virtual QPixmap grabWindow(WId window, int x, int y, int width, int height) const; + +//Fontdatabase integration. + virtual QPlatformFontDatabase *fontDatabase() const; + +// Experimental in mainthread eventloop integration +// This should only be used if it is only possible to do window system event processing in +// the gui thread. All of the functions in QWindowSystemInterface are thread safe. + virtual QPlatformEventLoopIntegration *createEventLoopIntegration() const; + +//jl:XXX should it be hasGLContext and do we need it at all? + virtual bool hasOpenGL() const; + + +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLATFORMINTEGRATION_H diff --git a/src/gui/kernel/qplatformintegrationfactory_qpa.cpp b/src/gui/kernel/qplatformintegrationfactory_qpa.cpp new file mode 100644 index 0000000..9122e1a --- /dev/null +++ b/src/gui/kernel/qplatformintegrationfactory_qpa.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qplatformintegrationfactory_qpa_p.h" +#include <QPlatformIntegrationPlugin> +#include "private/qfactoryloader_p.h" +#include "qmutex.h" + +#include "qapplication.h" +#include "qdebug.h" + +QT_BEGIN_NAMESPACE + +#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, + (QPlatformIntegrationFactoryInterface_iid, QLatin1String("/platforms"), Qt::CaseInsensitive)) +#endif + +QPlatformIntegration *QPlatformIntegrationFactory::create(const QString& key) +{ + QPlatformIntegration *ret = 0; + QStringList paramList = key.split(QLatin1Char(':')); + QString platform = paramList.takeFirst().toLower(); + +#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) + if (QPlatformIntegrationFactoryInterface *factory = qobject_cast<QPlatformIntegrationFactoryInterface*>(loader()->instance(platform))) + ret = factory->create(platform, paramList); +#endif + + return ret; +} + +/*! + Returns the list of valid keys, i.e. the keys this factory can + create styles for. + + \sa create() +*/ +QStringList QPlatformIntegrationFactory::keys() +{ +#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) + QStringList list = loader()->keys(); +#else + QStringList list; +#endif + return list; +} + +QT_END_NAMESPACE + diff --git a/src/gui/kernel/qplatformintegrationfactory_qpa_p.h b/src/gui/kernel/qplatformintegrationfactory_qpa_p.h new file mode 100644 index 0000000..ba02d2c --- /dev/null +++ b/src/gui/kernel/qplatformintegrationfactory_qpa_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QPLATFORMINTEGRATIONFACTORY_H +#define QPLATFORMINTEGRATIONFACTORY_H + +// +// 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. +// + +#include <QtCore/qstringlist.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QPlatformIntegration; + +class QPlatformIntegrationFactory +{ +public: + static QStringList keys(); + static QPlatformIntegration *create(const QString&); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLATFORMINTEGRATIONFACTORY_H + diff --git a/src/gui/kernel/qplatformintegrationplugin_qpa.cpp b/src/gui/kernel/qplatformintegrationplugin_qpa.cpp new file mode 100644 index 0000000..3bf2474 --- /dev/null +++ b/src/gui/kernel/qplatformintegrationplugin_qpa.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qplatformintegrationplugin_qpa.h" + +QT_BEGIN_NAMESPACE + +QPlatformIntegrationPlugin::QPlatformIntegrationPlugin(QObject *parent) + : QObject(parent) +{ +} + +QPlatformIntegrationPlugin::~QPlatformIntegrationPlugin() +{ +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformintegrationplugin_qpa.h b/src/gui/kernel/qplatformintegrationplugin_qpa.h new file mode 100644 index 0000000..9c37cf7 --- /dev/null +++ b/src/gui/kernel/qplatformintegrationplugin_qpa.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QPLATFORMINTEGRATIONPLUGIN_H +#define QPLATFORMINTEGRATIONPLUGIN_H + +// +// 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. +// + +#include <QtCore/qplugin.h> +#include <QtCore/qfactoryinterface.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QPlatformIntegration; + +struct QPlatformIntegrationFactoryInterface : public QFactoryInterface +{ + virtual QPlatformIntegration *create(const QString &key, const QStringList ¶mList) = 0; +}; + +#define QPlatformIntegrationFactoryInterface_iid "com.nokia.Qt.QPlatformIntegrationFactoryInterface" + +Q_DECLARE_INTERFACE(QPlatformIntegrationFactoryInterface, QPlatformIntegrationFactoryInterface_iid) + +class Q_GUI_EXPORT QPlatformIntegrationPlugin : public QObject, public QPlatformIntegrationFactoryInterface +{ + Q_OBJECT + Q_INTERFACES(QPlatformIntegrationFactoryInterface:QFactoryInterface) +public: + explicit QPlatformIntegrationPlugin(QObject *parent = 0); + ~QPlatformIntegrationPlugin(); + + virtual QStringList keys() const = 0; + virtual QPlatformIntegration *create(const QString &key, const QStringList ¶mList) = 0; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLATFORMINTEGRATIONPLUGIN_H diff --git a/src/gui/kernel/qplatformscreen_qpa.cpp b/src/gui/kernel/qplatformscreen_qpa.cpp new file mode 100644 index 0000000..478d2d6 --- /dev/null +++ b/src/gui/kernel/qplatformscreen_qpa.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qplatformscreen_qpa.h" +#include <QtGui/qapplication.h> +#include <QtGui/qdesktopwidget.h> + +QWidget *QPlatformScreen::topLevelAt(const QPoint & pos) const +{ + QWidgetList list = QApplication::topLevelWidgets(); + for (int i = list.size()-1; i >= 0; --i) { + QWidget *w = list[i]; + //### mask is ignored + if (w != QApplication::desktop() && w->isVisible() && w->geometry().contains(pos)) + return w; + } + + return 0; +} + +QSize QPlatformScreen::physicalSize() const +{ + static const int dpi = 100; + int width = geometry().width() / dpi * qreal(25.4) ; + int height = geometry().height() / dpi * qreal(25.4) ; + return QSize(width,height); +} + diff --git a/src/gui/kernel/qplatformscreen_qpa.h b/src/gui/kernel/qplatformscreen_qpa.h new file mode 100644 index 0000000..1704f0f --- /dev/null +++ b/src/gui/kernel/qplatformscreen_qpa.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QPLATFORMSCREEN_H +#define QPLATFORMSCREEN_H + +#include <QtCore/qmetatype.h> +#include <QtCore/qnamespace.h> +#include <QtCore/qcoreevent.h> +#include <QtCore/qvariant.h> +#include <QtCore/qrect.h> +#include <QtCore/qobject.h> + +#include <QtGui/qcursor.h> +#include <QtGui/qimage.h> +#include <QtGui/qwidget.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class Q_GUI_EXPORT QPlatformScreen : public QObject +{ + Q_OBJECT +public: + virtual ~QPlatformScreen() { } + + virtual QRect geometry() const = 0; + virtual QRect availableGeometry() const {return geometry();} + virtual int depth() const = 0; + virtual QImage::Format format() const = 0; + virtual QSize physicalSize() const; + virtual void setDirty(const QRect &) {} + virtual QWidget *topLevelAt(const QPoint &point) const; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLATFORMSCREEN_H diff --git a/src/gui/kernel/qplatformwindow_qpa.cpp b/src/gui/kernel/qplatformwindow_qpa.cpp new file mode 100644 index 0000000..9d722d8 --- /dev/null +++ b/src/gui/kernel/qplatformwindow_qpa.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qplatformwindow_qpa.h" + +#include <QtGui/qwidget.h> + +class QPlatformWindowPrivate +{ + QWidget *tlw; + QRect rect; + Qt::WindowFlags flags; + friend class QPlatformWindow; +}; + +QPlatformWindow::QPlatformWindow(QWidget *tlw) + : d_ptr(new QPlatformWindowPrivate) +{ + Q_D(QPlatformWindow); + d->tlw = tlw; + tlw->setPlatformWindow(this); +} + +QPlatformWindow::~QPlatformWindow() +{ +} + +QWidget *QPlatformWindow::widget() const +{ + Q_D(const QPlatformWindow); + return d->tlw; +} + +void QPlatformWindow::setGeometry(const QRect &rect) +{ + Q_D(QPlatformWindow); + d->rect = rect; +} + +QRect QPlatformWindow::geometry() const +{ + Q_D(const QPlatformWindow); + return d->rect; +} + +/*! +Reimplemented in subclasses to show the surface if \a visible is \c true, and hide it if \a visible is \c false. +*/ +void QPlatformWindow::setVisible(bool visible) +{ + Q_UNUSED(visible); +} +/*! +Requests setting the window flags of this surface to \a type. Returns the actual flags set. +*/ +Qt::WindowFlags QPlatformWindow::setWindowFlags(Qt::WindowFlags flags) +{ + Q_D(QPlatformWindow); + d->flags = flags; + return flags; +} + +/*! + Returns the effective window flags for this surface. +*/ +Qt::WindowFlags QPlatformWindow::windowFlags() const +{ + Q_D(const QPlatformWindow); + return d->flags; +} + +WId QPlatformWindow::winId() const { return WId(0); } + +void QPlatformWindow::setParent(const QPlatformWindow *) { qWarning("This plugin does not support setParent!"); } + +void QPlatformWindow::setWindowTitle(const QString &) {} + +void QPlatformWindow::raise() { qWarning("This plugin does not support raise()"); } + +void QPlatformWindow::lower() { qWarning("This plugin does not support lower()"); } + +void QPlatformWindow::setOpacity(qreal level) +{ + Q_UNUSED(level); + qWarning("This plugin does not support setting window opacity"); +} + +QPlatformGLContext *QPlatformWindow::glContext() const +{ + return 0; +} diff --git a/src/gui/kernel/qplatformwindow_qpa.h b/src/gui/kernel/qplatformwindow_qpa.h new file mode 100644 index 0000000..6dfba05 --- /dev/null +++ b/src/gui/kernel/qplatformwindow_qpa.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ +#ifndef QPLATFORMWINDOW_H +#define QPLATFORMWINDOW_H + + +#include <QtCore/qscopedpointer.h> +#include <QtCore/qrect.h> +#include <QtCore/qstring.h> +#include <QtGui/qwindowdefs.h> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QPlatformWindowPrivate; +class QWidget; +class QPlatformGLContext; + +class Q_GUI_EXPORT QPlatformWindow +{ + Q_DECLARE_PRIVATE(QPlatformWindow); +public: + QPlatformWindow(QWidget *tlw); + virtual ~QPlatformWindow(); + + QWidget *widget() const; + virtual void setGeometry(const QRect &rect); + virtual QRect geometry() const; + + virtual void setVisible(bool visible); + virtual Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags); + virtual Qt::WindowFlags windowFlags() const; + virtual WId winId() const; + virtual void setParent(const QPlatformWindow *window); + + virtual void setWindowTitle(const QString &); + virtual void raise(); + virtual void lower(); + + virtual void setOpacity(qreal level); + + virtual QPlatformGLContext *glContext() const; +protected: + QScopedPointer<QPlatformWindowPrivate> d_ptr; +private: + Q_DISABLE_COPY(QPlatformWindow); +}; + +QT_END_NAMESPACE + +QT_END_HEADER +#endif //QPLATFORMWINDOW_H diff --git a/src/gui/kernel/qplatformwindowformat_qpa.cpp b/src/gui/kernel/qplatformwindowformat_qpa.cpp new file mode 100644 index 0000000..d497e85 --- /dev/null +++ b/src/gui/kernel/qplatformwindowformat_qpa.cpp @@ -0,0 +1,1012 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qplatformwindowformat_qpa.h" + +#include <QtCore/QDebug> + +Q_GLOBAL_STATIC(QPlatformWindowFormat, q_platformwindow_default_format); + +class QPlatformWindowFormatPrivate +{ +public: + QPlatformWindowFormatPrivate() + : ref(1) + , opts(QPlatformWindowFormat::DoubleBuffer | QPlatformWindowFormat::DepthBuffer + | QPlatformWindowFormat::Rgba | QPlatformWindowFormat::DirectRendering + | QPlatformWindowFormat::StencilBuffer | QPlatformWindowFormat::DeprecatedFunctions + | QPlatformWindowFormat::UseDefaultSharedContext) + , depthSize(-1) + , accumSize(-1) + , stencilSize(-1) + , redSize(-1) + , greenSize(-1) + , blueSize(-1) + , alphaSize(-1) + , numSamples(-1) + , swapInterval(-1) + , windowApi(QPlatformWindowFormat::Raster) + , sharedContext(0) + { + } + + QPlatformWindowFormatPrivate(const QPlatformWindowFormatPrivate *other) + : ref(1), + opts(other->opts), + depthSize(other->depthSize), + accumSize(other->accumSize), + stencilSize(other->stencilSize), + redSize(other->redSize), + greenSize(other->greenSize), + blueSize(other->blueSize), + alphaSize(other->alphaSize), + numSamples(other->numSamples), + swapInterval(other->swapInterval), + windowApi(other->windowApi), + sharedContext(other->sharedContext) + { + } + QAtomicInt ref; + QPlatformWindowFormat::FormatOptions opts; + int depthSize; + int accumSize; + int stencilSize; + int redSize; + int greenSize; + int blueSize; + int alphaSize; + int numSamples; + int swapInterval; + QPlatformWindowFormat::WindowApi windowApi; + QPlatformGLContext *sharedContext; +}; + +/*! + \class QPlatformWindowFormat + \brief The QPlatformWindowFormat class specifies the display format of an OpenGL + rendering context. + + \ingroup painting-3D + + A display format has several characteristics: + \list + \i \link setDoubleBuffer() Double or single buffering.\endlink + \i \link setDepth() Depth buffer.\endlink + \i \link setRgba() RGBA or color index mode.\endlink + \i \link setAlpha() Alpha channel.\endlink + \i \link setAccum() Accumulation buffer.\endlink + \i \link setStencil() Stencil buffer.\endlink + \i \link setStereo() Stereo buffers.\endlink + \i \link setDirectRendering() Direct rendering.\endlink + \i \link setOverlay() Presence of an overlay.\endlink + \i \link setPlane() Plane of an overlay.\endlink + \i \link setSampleBuffers() Multisample buffers.\endlink + \endlist + + You can also specify preferred bit depths for the color buffer, + depth buffer, alpha buffer, accumulation buffer and the stencil + buffer with the functions: setRedBufferSize(), setGreenBufferSize(), + setBlueBufferSize(), setDepthBufferSize(), setAlphaBufferSize(), + setAccumBufferSize() and setStencilBufferSize(). + + Note that even if you specify that you prefer a 32 bit depth + buffer (e.g. with setDepthBufferSize(32)), the format that is + chosen may not have a 32 bit depth buffer, even if there is a + format available with a 32 bit depth buffer. The main reason for + this is how the system dependant picking algorithms work on the + different platforms, and some format options may have higher + precedence than others. + + You create and tell a QPlatformWindowFormat object what rendering options you + want from an OpenGL rendering context. + + OpenGL drivers or accelerated hardware may or may not support + advanced features such as alpha channel or stereographic viewing. + If you request some features that the driver/hardware does not + provide when you create a QGLWidget, you will get a rendering + context with the nearest subset of features. + + There are different ways to define the display characteristics of + a rendering context. One is to create a QPlatformWindowFormat and make it the + default for the entire application: + \snippet doc/src/snippets/code/src_opengl_qgl.cpp 0 + + Or you can specify the desired format when creating an object of + your QGLWidget subclass: + \snippet doc/src/snippets/code/src_opengl_qgl.cpp 1 + + After the widget has been created, you can find out which of the + requested features the system was able to provide: + \snippet doc/src/snippets/code/src_opengl_qgl.cpp 2 + + \legalese + OpenGL is a trademark of Silicon Graphics, Inc. in the + United States and other countries. + \endlegalese + + \sa QGLContext, QGLWidget +*/ + +/*! + Constructs a QPlatformWindowFormat object with the following default settings: + \list + \i \link setDoubleBuffer() Double buffer:\endlink Enabled. + \i \link setDepth() Depth buffer:\endlink Enabled. + \i \link setRgba() RGBA:\endlink Enabled (i.e., color index disabled). + \i \link setAlpha() Alpha channel:\endlink Disabled. + \i \link setAccum() Accumulator buffer:\endlink Disabled. + \i \link setStencil() Stencil buffer:\endlink Enabled. + \i \link setStereo() Stereo:\endlink Disabled. + \i \link setDirectRendering() Direct rendering:\endlink Enabled. + \i \link setOverlay() Overlay:\endlink Disabled. + \i \link setPlane() Plane:\endlink 0 (i.e., normal plane). + \i \link setSampleBuffers() Multisample buffers:\endlink Disabled. + \endlist +*/ + +QPlatformWindowFormat::QPlatformWindowFormat() +{ + d = new QPlatformWindowFormatPrivate; +} + + +/*! + Creates a QPlatformWindowFormat object that is a copy of the current + defaultFormat(). + + If \a options is not 0, the default format is modified by the + specified format options. The \a options parameter should be + QGL::FormatOption values OR'ed together. + + This constructor makes it easy to specify a certain desired format + in classes derived from QGLWidget, for example: + \snippet doc/src/snippets/code/src_opengl_qgl.cpp 3 + + Note that there are QGL::FormatOption values to turn format settings + both on and off, e.g. QGL::DepthBuffer and QGL::NoDepthBuffer, + QGL::DirectRendering and QGL::IndirectRendering, etc. + + The \a plane parameter defaults to 0 and is the plane which this + format should be associated with. Not all OpenGL implementations + supports overlay/underlay rendering planes. + + \sa defaultFormat(), setOption(), setPlane() +*/ + +QPlatformWindowFormat::QPlatformWindowFormat(QPlatformWindowFormat::FormatOptions options) +{ + d = new QPlatformWindowFormatPrivate; + QPlatformWindowFormat::FormatOptions newOpts = options; + d->opts = defaultFormat().d->opts; + d->opts |= (newOpts & 0xffff); + d->opts &= ~(newOpts >> 16); +} + +/*! + \internal +*/ +void QPlatformWindowFormat::detach() +{ + if (d->ref != 1) { + QPlatformWindowFormatPrivate *newd = new QPlatformWindowFormatPrivate(d); + if (!d->ref.deref()) + delete d; + d = newd; + } +} + +/*! + Constructs a copy of \a other. +*/ + +QPlatformWindowFormat::QPlatformWindowFormat(const QPlatformWindowFormat &other) +{ + d = other.d; + d->ref.ref(); +} + +/*! + Assigns \a other to this object. +*/ + +QPlatformWindowFormat &QPlatformWindowFormat::operator=(const QPlatformWindowFormat &other) +{ + if (d != other.d) { + other.d->ref.ref(); + if (!d->ref.deref()) + delete d; + d = other.d; + } + return *this; +} + +/*! + Destroys the QPlatformWindowFormat. +*/ +QPlatformWindowFormat::~QPlatformWindowFormat() +{ + if (!d->ref.deref()) + delete d; +} + +/*! + \fn bool QPlatformWindowFormat::doubleBuffer() const + + Returns true if double buffering is enabled; otherwise returns + false. Double buffering is enabled by default. + + \sa setDoubleBuffer() +*/ + +/*! + If \a enable is true sets double buffering; otherwise sets single + buffering. + + Double buffering is enabled by default. + + Double buffering is a technique where graphics are rendered on an + off-screen buffer and not directly to the screen. When the drawing + has been completed, the program calls a swapBuffers() function to + exchange the screen contents with the buffer. The result is + flicker-free drawing and often better performance. + + \sa doubleBuffer(), QGLContext::swapBuffers(), + QGLWidget::swapBuffers() +*/ + +void QPlatformWindowFormat::setDoubleBuffer(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::DoubleBuffer : QPlatformWindowFormat::SingleBuffer); +} + + +/*! + \fn bool QPlatformWindowFormat::depth() const + + Returns true if the depth buffer is enabled; otherwise returns + false. The depth buffer is enabled by default. + + \sa setDepth(), setDepthBufferSize() +*/ + +/*! + If \a enable is true enables the depth buffer; otherwise disables + the depth buffer. + + The depth buffer is enabled by default. + + The purpose of a depth buffer (or Z-buffering) is to remove hidden + surfaces. Pixels are assigned Z values based on the distance to + the viewer. A pixel with a high Z value is closer to the viewer + than a pixel with a low Z value. This information is used to + decide whether to draw a pixel or not. + + \sa depth(), setDepthBufferSize() +*/ + +void QPlatformWindowFormat::setDepth(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::DepthBuffer : QPlatformWindowFormat::NoDepthBuffer); +} + + +/*! + \fn bool QPlatformWindowFormat::rgba() const + + Returns true if RGBA color mode is set. Returns false if color + index mode is set. The default color mode is RGBA. + + \sa setRgba() +*/ + +/*! + If \a enable is true sets RGBA mode. If \a enable is false sets + color index mode. + + The default color mode is RGBA. + + RGBA is the preferred mode for most OpenGL applications. In RGBA + color mode you specify colors as red + green + blue + alpha + quadruplets. + + In color index mode you specify an index into a color lookup + table. + + \sa rgba() +*/ + +void QPlatformWindowFormat::setRgba(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::Rgba : QPlatformWindowFormat::ColorIndex); +} + + +/*! + \fn bool QPlatformWindowFormat::alpha() const + + Returns true if the alpha buffer in the framebuffer is enabled; + otherwise returns false. The alpha buffer is disabled by default. + + \sa setAlpha(), setAlphaBufferSize() +*/ + +/*! + If \a enable is true enables the alpha buffer; otherwise disables + the alpha buffer. + + The alpha buffer is disabled by default. + + The alpha buffer is typically used for implementing transparency + or translucency. The A in RGBA specifies the transparency of a + pixel. + + \sa alpha(), setAlphaBufferSize() +*/ + +void QPlatformWindowFormat::setAlpha(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::AlphaChannel : QPlatformWindowFormat::NoAlphaChannel); +} + + +/*! + \fn bool QPlatformWindowFormat::accum() const + + Returns true if the accumulation buffer is enabled; otherwise + returns false. The accumulation buffer is disabled by default. + + \sa setAccum(), setAccumBufferSize() +*/ + +/*! + If \a enable is true enables the accumulation buffer; otherwise + disables the accumulation buffer. + + The accumulation buffer is disabled by default. + + The accumulation buffer is used to create blur effects and + multiple exposures. + + \sa accum(), setAccumBufferSize() +*/ + +void QPlatformWindowFormat::setAccum(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::AccumBuffer : QPlatformWindowFormat::NoAccumBuffer); +} + + +/*! + \fn bool QPlatformWindowFormat::stencil() const + + Returns true if the stencil buffer is enabled; otherwise returns + false. The stencil buffer is enabled by default. + + \sa setStencil(), setStencilBufferSize() +*/ + +/*! + If \a enable is true enables the stencil buffer; otherwise + disables the stencil buffer. + + The stencil buffer is enabled by default. + + The stencil buffer masks certain parts of the drawing area so that + masked parts are not drawn on. + + \sa stencil(), setStencilBufferSize() +*/ + +void QPlatformWindowFormat::setStencil(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::StencilBuffer: QPlatformWindowFormat::NoStencilBuffer); +} + + +/*! + \fn bool QPlatformWindowFormat::stereo() const + + Returns true if stereo buffering is enabled; otherwise returns + false. Stereo buffering is disabled by default. + + \sa setStereo() +*/ + +/*! + If \a enable is true enables stereo buffering; otherwise disables + stereo buffering. + + Stereo buffering is disabled by default. + + Stereo buffering provides extra color buffers to generate left-eye + and right-eye images. + + \sa stereo() +*/ + +void QPlatformWindowFormat::setStereo(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::StereoBuffers : QPlatformWindowFormat::NoStereoBuffers); +} + + +/*! + \fn bool QPlatformWindowFormat::directRendering() const + + Returns true if direct rendering is enabled; otherwise returns + false. + + Direct rendering is enabled by default. + + \sa setDirectRendering() +*/ + +/*! + If \a enable is true enables direct rendering; otherwise disables + direct rendering. + + Direct rendering is enabled by default. + + Enabling this option will make OpenGL bypass the underlying window + system and render directly from hardware to the screen, if this is + supported by the system. + + \sa directRendering() +*/ + +void QPlatformWindowFormat::setDirectRendering(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::DirectRendering : QPlatformWindowFormat::IndirectRendering); +} + +/*! + \fn bool QPlatformWindowFormat::sampleBuffers() const + + Returns true if multisample buffer support is enabled; otherwise + returns false. + + The multisample buffer is disabled by default. + + \sa setSampleBuffers() +*/ + +/*! + If \a enable is true, a GL context with multisample buffer support + is picked; otherwise ignored. + + \sa sampleBuffers(), setSamples(), samples() +*/ +void QPlatformWindowFormat::setSampleBuffers(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::SampleBuffers : QPlatformWindowFormat::NoSampleBuffers); +} + +void QPlatformWindowFormat::setUseDefaultSharedContext(bool enable) +{ + if (enable) { + setOption(QPlatformWindowFormat::UseDefaultSharedContext); + d->sharedContext = 0; + } else { + setOption(QPlatformWindowFormat::NoDefaultSharedContext); + } +} + +/*! + Returns the number of samples per pixel when multisampling is + enabled. By default, the highest number of samples that is + available is used. + + \sa setSampleBuffers(), sampleBuffers(), setSamples() +*/ +int QPlatformWindowFormat::samples() const +{ + return d->numSamples; +} + +/*! + Set the preferred number of samples per pixel when multisampling + is enabled to \a numSamples. By default, the highest number of + samples available is used. + + \sa setSampleBuffers(), sampleBuffers(), samples() +*/ +void QPlatformWindowFormat::setSamples(int numSamples) +{ + detach(); + if (numSamples < 0) { + qWarning("QPlatformWindowFormat::setSamples: Cannot have negative number of samples per pixel %d", numSamples); + return; + } + d->numSamples = numSamples; + setSampleBuffers(numSamples > 0); +} + +/*! + \since 4.2 + + Set the preferred swap interval. This can be used to sync the GL + drawing into a system window to the vertical refresh of the screen. + Setting an \a interval value of 0 will turn the vertical refresh syncing + off, any value higher than 0 will turn the vertical syncing on. + + Under Windows and under X11, where the \c{WGL_EXT_swap_control} + and \c{GLX_SGI_video_sync} extensions are used, the \a interval + parameter can be used to set the minimum number of video frames + that are displayed before a buffer swap will occur. In effect, + setting the \a interval to 10, means there will be 10 vertical + retraces between every buffer swap. + + Under Windows the \c{WGL_EXT_swap_control} extension has to be present, + and under X11 the \c{GLX_SGI_video_sync} extension has to be present. +*/ +void QPlatformWindowFormat::setSwapInterval(int interval) +{ + detach(); + d->swapInterval = interval; +} + +/*! + \since 4.2 + + Returns the currently set swap interval. -1 is returned if setting + the swap interval isn't supported in the system GL implementation. +*/ +int QPlatformWindowFormat::swapInterval() const +{ + return d->swapInterval; +} + +void QPlatformWindowFormat::setWindowApi(QPlatformWindowFormat::WindowApi api) +{ + detach(); + d->windowApi = api; +} + +QPlatformWindowFormat::WindowApi QPlatformWindowFormat::windowApi() const +{ + return d->windowApi; +} + +void QPlatformWindowFormat::setSharedContext(QPlatformGLContext *context) +{ + setUseDefaultSharedContext(false); + d->sharedContext = context; +} + +QPlatformGLContext *QPlatformWindowFormat::sharedGLContext() const +{ + return d->sharedContext; +} + +///*! +// \fn bool QPlatformWindowFormat::hasOverlay() const + +// Returns true if overlay plane is enabled; otherwise returns false. + +// Overlay is disabled by default. + +// \sa setOverlay() +//*/ + +///*! +// If \a enable is true enables an overlay plane; otherwise disables +// the overlay plane. + +// Enabling the overlay plane will cause QGLWidget to create an +// additional context in an overlay plane. See the QGLWidget +// documentation for further information. + +// \sa hasOverlay() +//*/ + +//void QPlatformWindowFormat::setOverlay(bool enable) +//{ +// setOption(enable ? QPlatformWindowFormat::HasOverlay : QPlatformWindowFormat::NoOverlay); +//} + +/*! + Sets the format option to \a opt. + + \sa testOption() +*/ + +void QPlatformWindowFormat::setOption(QPlatformWindowFormat::FormatOptions opt) +{ + detach(); + if (opt & 0xffff) + d->opts |= opt; + else + d->opts &= ~(opt >> 16); +} + + + +/*! + Returns true if format option \a opt is set; otherwise returns false. + + \sa setOption() +*/ + +bool QPlatformWindowFormat::testOption(QPlatformWindowFormat::FormatOptions opt) const +{ + if (opt & 0xffff) + return (d->opts & opt) != 0; + else + return (d->opts & (opt >> 16)) == 0; +} + +/*! + Set the minimum depth buffer size to \a size. + + \sa depthBufferSize(), setDepth(), depth() +*/ +void QPlatformWindowFormat::setDepthBufferSize(int size) +{ + detach(); + if (size < 0) { + qWarning("QPlatformWindowFormat::setDepthBufferSize: Cannot set negative depth buffer size %d", size); + return; + } + d->depthSize = size; + setDepth(size > 0); +} + +/*! + Returns the depth buffer size. + + \sa depth(), setDepth(), setDepthBufferSize() +*/ +int QPlatformWindowFormat::depthBufferSize() const +{ + return d->depthSize; +} + +/*! + \since 4.2 + + Set the preferred red buffer size to \a size. + + \sa setGreenBufferSize(), setBlueBufferSize(), setAlphaBufferSize() +*/ +void QPlatformWindowFormat::setRedBufferSize(int size) +{ + detach(); + if (size < 0) { + qWarning("QPlatformWindowFormat::setRedBufferSize: Cannot set negative red buffer size %d", size); + return; + } + d->redSize = size; +} + +/*! + \since 4.2 + + Returns the red buffer size. + + \sa setRedBufferSize() +*/ +int QPlatformWindowFormat::redBufferSize() const +{ + return d->redSize; +} + +/*! + \since 4.2 + + Set the preferred green buffer size to \a size. + + \sa setRedBufferSize(), setBlueBufferSize(), setAlphaBufferSize() +*/ +void QPlatformWindowFormat::setGreenBufferSize(int size) +{ + detach(); + if (size < 0) { + qWarning("QPlatformWindowFormat::setGreenBufferSize: Cannot set negative green buffer size %d", size); + return; + } + d->greenSize = size; +} + +/*! + \since 4.2 + + Returns the green buffer size. + + \sa setGreenBufferSize() +*/ +int QPlatformWindowFormat::greenBufferSize() const +{ + return d->greenSize; +} + +/*! + \since 4.2 + + Set the preferred blue buffer size to \a size. + + \sa setRedBufferSize(), setGreenBufferSize(), setAlphaBufferSize() +*/ +void QPlatformWindowFormat::setBlueBufferSize(int size) +{ + detach(); + if (size < 0) { + qWarning("QPlatformWindowFormat::setBlueBufferSize: Cannot set negative blue buffer size %d", size); + return; + } + d->blueSize = size; +} + +/*! + \since 4.2 + + Returns the blue buffer size. + + \sa setBlueBufferSize() +*/ +int QPlatformWindowFormat::blueBufferSize() const +{ + return d->blueSize; +} + +/*! + Set the preferred alpha buffer size to \a size. + This function implicitly enables the alpha channel. + + \sa setRedBufferSize(), setGreenBufferSize(), alphaBufferSize() +*/ +void QPlatformWindowFormat::setAlphaBufferSize(int size) +{ + detach(); + if (size < 0) { + qWarning("QPlatformWindowFormat::setAlphaBufferSize: Cannot set negative alpha buffer size %d", size); + return; + } + d->alphaSize = size; + setAlpha(size > 0); +} + +/*! + Returns the alpha buffer size. + + \sa alpha(), setAlpha(), setAlphaBufferSize() +*/ +int QPlatformWindowFormat::alphaBufferSize() const +{ + return d->alphaSize; +} + +/*! + Set the preferred accumulation buffer size, where \a size is the + bit depth for each RGBA component. + + \sa accum(), setAccum(), accumBufferSize() +*/ +void QPlatformWindowFormat::setAccumBufferSize(int size) +{ + detach(); + if (size < 0) { + qWarning("QPlatformWindowFormat::setAccumBufferSize: Cannot set negative accumulate buffer size %d", size); + return; + } + d->accumSize = size; + setAccum(size > 0); +} + +/*! + Returns the accumulation buffer size. + + \sa setAccumBufferSize(), accum(), setAccum() +*/ +int QPlatformWindowFormat::accumBufferSize() const +{ + return d->accumSize; +} + +/*! + Set the preferred stencil buffer size to \a size. + + \sa stencilBufferSize(), setStencil(), stencil() +*/ +void QPlatformWindowFormat::setStencilBufferSize(int size) +{ + detach(); + if (size < 0) { + qWarning("QPlatformWindowFormat::setStencilBufferSize: Cannot set negative stencil buffer size %d", size); + return; + } + d->stencilSize = size; + setStencil(size > 0); +} + +/*! + Returns the stencil buffer size. + + \sa stencil(), setStencil(), setStencilBufferSize() +*/ +int QPlatformWindowFormat::stencilBufferSize() const +{ + return d->stencilSize; +} + +/*! + Returns the default QPlatformWindowFormat for the application. All QGLWidget + objects that are created use this format unless another format is + specified, e.g. when they are constructed. + + If no special default format has been set using + setDefaultFormat(), the default format is the same as that created + with QPlatformWindowFormat(). + + \sa setDefaultFormat() +*/ + +QPlatformWindowFormat QPlatformWindowFormat::defaultFormat() +{ + return *q_platformwindow_default_format(); +} + +/*! + Sets a new default QPlatformWindowFormat for the application to \a f. For + example, to set single buffering as the default instead of double + buffering, your main() might contain code like this: + \snippet doc/src/snippets/code/src_opengl_qgl.cpp 4 + + \sa defaultFormat() +*/ + +void QPlatformWindowFormat::setDefaultFormat(const QPlatformWindowFormat &f) +{ + *q_platformwindow_default_format() = f; +} + + +/*! + Returns the default QPlatformWindowFormat for overlay contexts. + + The default overlay format is: + \list + \i \link setDoubleBuffer() Double buffer:\endlink Disabled. + \i \link setDepth() Depth buffer:\endlink Disabled. + \i \link setRgba() RGBA:\endlink Disabled (i.e., color index enabled). + \i \link setAlpha() Alpha channel:\endlink Disabled. + \i \link setAccum() Accumulator buffer:\endlink Disabled. + \i \link setStencil() Stencil buffer:\endlink Disabled. + \i \link setStereo() Stereo:\endlink Disabled. + \i \link setDirectRendering() Direct rendering:\endlink Enabled. + \i \link setOverlay() Overlay:\endlink Disabled. + \i \link setSampleBuffers() Multisample buffers:\endlink Disabled. + \i \link setPlane() Plane:\endlink 1 (i.e., first overlay plane). + \endlist + + \sa setDefaultFormat() +*/ + +//QPlatformWindowFormat QPlatformWindowFormat::defaultOverlayFormat() +//{ +// return *defaultOverlayFormatInstance(); +//} + +///*! +// Sets a new default QPlatformWindowFormat for overlay contexts to \a f. This +// format is used whenever a QGLWidget is created with a format that +// hasOverlay() enabled. + +// For example, to get a double buffered overlay context (if +// available), use code like this: + +// \snippet doc/src/snippets/code/src_opengl_qgl.cpp 5 + +// As usual, you can find out after widget creation whether the +// underlying OpenGL system was able to provide the requested +// specification: + +// \snippet doc/src/snippets/code/src_opengl_qgl.cpp 6 + +// \sa defaultOverlayFormat() +//*/ + +//void QPlatformWindowFormat::setDefaultOverlayFormat(const QPlatformWindowFormat &f) +//{ +// QPlatformWindowFormat *defaultFormat = defaultOverlayFormatInstance(); +// *defaultFormat = f; +// // Make sure the user doesn't request that the overlays themselves +// // have overlays, since it is unlikely that the system supports +// // infinitely many planes... +// defaultFormat->setOverlay(false); +//} + + +/*! + Returns true if all the options of the two QPlatformWindowFormat objects + \a a and \a b are equal; otherwise returns false. + + \relates QPlatformWindowFormat +*/ + +bool operator==(const QPlatformWindowFormat& a, const QPlatformWindowFormat& b) +{ + return (a.d == b.d) || ((int) a.d->opts == (int) b.d->opts + && a.d->alphaSize == b.d->alphaSize + && a.d->accumSize == b.d->accumSize + && a.d->stencilSize == b.d->stencilSize + && a.d->depthSize == b.d->depthSize + && a.d->redSize == b.d->redSize + && a.d->greenSize == b.d->greenSize + && a.d->blueSize == b.d->blueSize + && a.d->numSamples == b.d->numSamples + && a.d->swapInterval == b.d->swapInterval + && a.d->windowApi == b.d->windowApi); +} + + +/*! + Returns false if all the options of the two QPlatformWindowFormat objects + \a a and \a b are equal; otherwise returns true. + + \relates QPlatformWindowFormat +*/ + +bool operator!=(const QPlatformWindowFormat& a, const QPlatformWindowFormat& b) +{ + return !(a == b); +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QPlatformWindowFormat &f) +{ + const QPlatformWindowFormatPrivate * const d = f.d; + + dbg.nospace() << "QGLFormat(" + << "options " << d->opts + << ", depthBufferSize " << d->depthSize + << ", accumBufferSize " << d->accumSize + << ", stencilBufferSize " << d->stencilSize + << ", redBufferSize " << d->redSize + << ", greenBufferSize " << d->greenSize + << ", blueBufferSize " << d->blueSize + << ", alphaBufferSize " << d->alphaSize + << ", samples " << d->numSamples + << ", swapInterval " << d->swapInterval + << ')'; + + return dbg.space(); +} +#endif diff --git a/src/gui/kernel/qplatformwindowformat_qpa.h b/src/gui/kernel/qplatformwindowformat_qpa.h new file mode 100644 index 0000000..63df76a --- /dev/null +++ b/src/gui/kernel/qplatformwindowformat_qpa.h @@ -0,0 +1,241 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ +#ifndef QPLATFORMWINDOWFORMAT_QPA_H +#define QPLATFORMWINDOWFORMAT_QPA_H + +#include <QtGui/QPlatformWindow> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QPlatformWindowFormatPrivate; + +class Q_GUI_EXPORT QPlatformWindowFormat +{ +public: + enum FormatOption { + DoubleBuffer = 0x0001, + DepthBuffer = 0x0002, + Rgba = 0x0004, + AlphaChannel = 0x0008, + AccumBuffer = 0x0010, + StencilBuffer = 0x0020, + StereoBuffers = 0x0040, + DirectRendering = 0x0080, + HasOverlay = 0x0100, + SampleBuffers = 0x0200, + DeprecatedFunctions = 0x0400, + UseDefaultSharedContext = 0x0800, + SingleBuffer = DoubleBuffer << 16, + NoDepthBuffer = DepthBuffer << 16, + ColorIndex = Rgba << 16, + NoAlphaChannel = AlphaChannel << 16, + NoAccumBuffer = AccumBuffer << 16, + NoStencilBuffer = StencilBuffer << 16, + NoStereoBuffers = StereoBuffers << 16, + IndirectRendering = DirectRendering << 16, + NoOverlay = HasOverlay << 16, + NoSampleBuffers = SampleBuffers << 16, + NoDeprecatedFunctions = DeprecatedFunctions << 16, + NoDefaultSharedContext = UseDefaultSharedContext << 16 + + }; + Q_DECLARE_FLAGS(FormatOptions, FormatOption) + + enum WindowApi { + Raster, + OpenGL, + OpenVG + }; + + QPlatformWindowFormat(); + QPlatformWindowFormat(FormatOptions options); + QPlatformWindowFormat(const QPlatformWindowFormat &other); + QPlatformWindowFormat &operator=(const QPlatformWindowFormat &other); + ~QPlatformWindowFormat(); + + void setDepthBufferSize(int size); + int depthBufferSize() const; + + void setAccumBufferSize(int size); + int accumBufferSize() const; + + void setRedBufferSize(int size); + int redBufferSize() const; + + void setGreenBufferSize(int size); + int greenBufferSize() const; + + void setBlueBufferSize(int size); + int blueBufferSize() const; + + void setAlphaBufferSize(int size); + int alphaBufferSize() const; + + void setStencilBufferSize(int size); + int stencilBufferSize() const; + + void setSampleBuffers(bool enable); + bool sampleBuffers() const; + + void setSamples(int numSamples); + int samples() const; + + void setSwapInterval(int interval); + int swapInterval() const; + + void setWindowApi(QPlatformWindowFormat::WindowApi api); + WindowApi windowApi() const; + + void setSharedContext(QPlatformGLContext *context); + QPlatformGLContext *sharedGLContext() const; + + bool doubleBuffer() const; + void setDoubleBuffer(bool enable); + bool depth() const; + void setDepth(bool enable); + bool rgba() const; + void setRgba(bool enable); + bool alpha() const; + void setAlpha(bool enable); + bool accum() const; + void setAccum(bool enable); + bool stencil() const; + void setStencil(bool enable); + bool stereo() const; + void setStereo(bool enable); + bool directRendering() const; + void setDirectRendering(bool enable); + bool useDefaultSharedContext() const; + void setUseDefaultSharedContext(bool enable); +// bool hasOverlay() const; +// void setOverlay(bool enable); + + void setOption(QPlatformWindowFormat::FormatOptions opt); + bool testOption(QPlatformWindowFormat::FormatOptions opt) const; + + static QPlatformWindowFormat defaultFormat(); + static void setDefaultFormat(const QPlatformWindowFormat& f); + +private: + QPlatformWindowFormatPrivate *d; + + void detach(); + + friend Q_GUI_EXPORT bool operator==(const QPlatformWindowFormat&, const QPlatformWindowFormat&); + friend Q_GUI_EXPORT bool operator!=(const QPlatformWindowFormat&, const QPlatformWindowFormat&); +#ifndef QT_NO_DEBUG_STREAM + friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QPlatformWindowFormat &); +#endif +}; + +Q_GUI_EXPORT bool operator==(const QPlatformWindowFormat&, const QPlatformWindowFormat&); +Q_GUI_EXPORT bool operator!=(const QPlatformWindowFormat&, const QPlatformWindowFormat&); + +#ifndef QT_NO_DEBUG_STREAM +Q_OPENGL_EXPORT QDebug operator<<(QDebug, const QPlatformWindowFormat &); +#endif + +Q_DECLARE_OPERATORS_FOR_FLAGS(QPlatformWindowFormat::FormatOptions) + +inline bool QPlatformWindowFormat::doubleBuffer() const +{ + return testOption(QPlatformWindowFormat::DoubleBuffer); +} + +inline bool QPlatformWindowFormat::depth() const +{ + return testOption(QPlatformWindowFormat::DepthBuffer); +} + +inline bool QPlatformWindowFormat::rgba() const +{ + return testOption(QPlatformWindowFormat::Rgba); +} + +inline bool QPlatformWindowFormat::alpha() const +{ + return testOption(QPlatformWindowFormat::AlphaChannel); +} + +inline bool QPlatformWindowFormat::accum() const +{ + return testOption(QPlatformWindowFormat::AccumBuffer); +} + +inline bool QPlatformWindowFormat::stencil() const +{ + return testOption(QPlatformWindowFormat::StencilBuffer); +} + +inline bool QPlatformWindowFormat::stereo() const +{ + return testOption(QPlatformWindowFormat::StereoBuffers); +} + +inline bool QPlatformWindowFormat::directRendering() const +{ + return testOption(QPlatformWindowFormat::DirectRendering); +} + +//inline bool QPlatformWindowFormat::hasOverlay() const +//{ +// return testOption(QPlatformWindowFormat::HasOverlay); +//} + +inline bool QPlatformWindowFormat::sampleBuffers() const +{ + return testOption(QPlatformWindowFormat::SampleBuffers); +} + +inline bool QPlatformWindowFormat::useDefaultSharedContext() const +{ + return testOption(QPlatformWindowFormat::UseDefaultSharedContext); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif //QPLATFORMWINDOWFORMAT_QPA_H diff --git a/src/gui/kernel/qsizepolicy.h b/src/gui/kernel/qsizepolicy.h index ff7b9ee..26cc1e1 100644 --- a/src/gui/kernel/qsizepolicy.h +++ b/src/gui/kernel/qsizepolicy.h @@ -62,12 +62,12 @@ private: HSize = 4, HMask = 0x0f, VMask = HMask << HSize, - CTShift = 9, - CTSize = 5, - WFHShift = CTShift + CTSize, - CTMask = ((0x1 << CTSize) - 1) << CTShift, - UnusedShift = CTShift + CTSize, - UnusedSize = 2 + CTShift = 9, + CTSize = 5, + CTMask = ((0x1 << CTSize) - 1) << CTShift, + WFHShift = CTShift + CTSize, + UnusedShift = WFHShift + 1, + UnusedSize = 1 }; public: @@ -134,6 +134,8 @@ public: void setHeightForWidth(bool b) { data = b ? (data | (1 << 2*HSize)) : (data & ~(1 << 2*HSize)); } bool hasHeightForWidth() const { return data & (1 << 2*HSize); } + void setWidthForHeight(bool b) { data = b ? (data | (1 << (WFHShift))) : (data & ~(1 << (WFHShift))); } + bool hasWidthForHeight() const { return data & (1 << (WFHShift)); } bool operator==(const QSizePolicy& s) const { return data == s.data; } bool operator!=(const QSizePolicy& s) const { return data != s.data; } @@ -200,15 +202,18 @@ private: QSizePolicy(int i) : data(i) { } quint32 data; -/* use bit flags instead, keep it here for improved readability for now +/* Qt5: Use bit flags instead, keep it here for improved readability for now. + We can maybe change it for Qt4, but we'd have to be careful, since the behaviour + is implementation defined. It usually varies between little- and big-endian compilers, but + it might also not vary. quint32 horzPolicy : 4; quint32 vertPolicy : 4; quint32 hfw : 1; quint32 ctype : 5; quint32 wfh : 1; quint32 padding : 1; // we cannot use the highest bit - quint32 horStretch : 8; quint32 verStretch : 8; + quint32 horStretch : 8; */ }; diff --git a/src/gui/kernel/qsizepolicy.qdoc b/src/gui/kernel/qsizepolicy.qdoc index 1bb13fe..504821e 100644 --- a/src/gui/kernel/qsizepolicy.qdoc +++ b/src/gui/kernel/qsizepolicy.qdoc @@ -249,7 +249,7 @@ Sets the flag determining whether the widget's preferred height depends on its width, to \a dependent. - \sa hasHeightForWidth() + \sa hasHeightForWidth(), setWidthForHeight() */ /*! @@ -262,6 +262,28 @@ */ /*! + \fn void QSizePolicy::setWidthForHeight(bool dependent) + + Sets the flag determining whether the widget's width + depends on its height, to \a dependent. + + This is only supported for QGraphicsLayout's subclasses. + It is not possible to have a layout with both height-for-width + and width-for-height constraints at the same time. + + \sa hasWidthForHeight(), setHeightForWidth() +*/ + +/*! + \fn bool QSizePolicy::hasWidthForHeight() const + + Returns true if the widget's width depends on its + height; otherwise returns false. + + \sa setWidthForHeight() +*/ + +/*! \fn bool QSizePolicy::operator==(const QSizePolicy &other) const Returns true if this policy is equal to \a other; otherwise diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 3945754..5a522f9 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -470,7 +470,6 @@ void qt_dispatchTabletProximityEvent(const ::TabletProximityRec &proxRec) qt_sendSpontaneousEvent(qApp, &qtabletProximity); } -#ifdef QT_MAC_USE_COCOA // Use this method to keep all the information in the TextSegment. As long as it is ordered // we are in OK shape, and we can influence that ourselves. struct KeyPair @@ -494,69 +493,107 @@ bool operator<(QChar qchar, const KeyPair &entry) return qchar < entry.cocoaKey; } +bool operator<(const Qt::Key &key, const KeyPair &entry) +{ + return key < entry.qtKey; +} + +bool operator<(const KeyPair &entry, const Qt::Key &key) +{ + return entry.qtKey < key; +} + +static bool qtKey2CocoaKeySortLessThan(const KeyPair &entry1, const KeyPair &entry2) +{ + return entry1.qtKey < entry2.qtKey; +} + +static const int NumEntries = 59; +static const KeyPair entries[NumEntries] = { + { NSEnterCharacter, Qt::Key_Enter }, + { NSBackspaceCharacter, Qt::Key_Backspace }, + { NSTabCharacter, Qt::Key_Tab }, + { NSNewlineCharacter, Qt::Key_Return }, + { NSCarriageReturnCharacter, Qt::Key_Return }, + { NSBackTabCharacter, Qt::Key_Backtab }, + { NSDeleteCharacter, Qt::Key_Delete }, + { kEscapeCharCode, Qt::Key_Escape }, + { NSUpArrowFunctionKey, Qt::Key_Up }, + { NSDownArrowFunctionKey, Qt::Key_Down }, + { NSLeftArrowFunctionKey, Qt::Key_Left }, + { NSRightArrowFunctionKey, Qt::Key_Right }, + { NSF1FunctionKey, Qt::Key_F1 }, + { NSF2FunctionKey, Qt::Key_F2 }, + { NSF3FunctionKey, Qt::Key_F3 }, + { NSF4FunctionKey, Qt::Key_F4 }, + { NSF5FunctionKey, Qt::Key_F5 }, + { NSF6FunctionKey, Qt::Key_F6 }, + { NSF7FunctionKey, Qt::Key_F7 }, + { NSF8FunctionKey, Qt::Key_F8 }, + { NSF9FunctionKey, Qt::Key_F8 }, + { NSF10FunctionKey, Qt::Key_F10 }, + { NSF11FunctionKey, Qt::Key_F11 }, + { NSF12FunctionKey, Qt::Key_F12 }, + { NSF13FunctionKey, Qt::Key_F13 }, + { NSF14FunctionKey, Qt::Key_F14 }, + { NSF15FunctionKey, Qt::Key_F15 }, + { NSF16FunctionKey, Qt::Key_F16 }, + { NSF17FunctionKey, Qt::Key_F17 }, + { NSF18FunctionKey, Qt::Key_F18 }, + { NSF19FunctionKey, Qt::Key_F19 }, + { NSF20FunctionKey, Qt::Key_F20 }, + { NSF21FunctionKey, Qt::Key_F21 }, + { NSF22FunctionKey, Qt::Key_F22 }, + { NSF23FunctionKey, Qt::Key_F23 }, + { NSF24FunctionKey, Qt::Key_F24 }, + { NSF25FunctionKey, Qt::Key_F25 }, + { NSF26FunctionKey, Qt::Key_F26 }, + { NSF27FunctionKey, Qt::Key_F27 }, + { NSF28FunctionKey, Qt::Key_F28 }, + { NSF29FunctionKey, Qt::Key_F29 }, + { NSF30FunctionKey, Qt::Key_F30 }, + { NSF31FunctionKey, Qt::Key_F31 }, + { NSF32FunctionKey, Qt::Key_F32 }, + { NSF33FunctionKey, Qt::Key_F33 }, + { NSF34FunctionKey, Qt::Key_F34 }, + { NSF35FunctionKey, Qt::Key_F35 }, + { NSInsertFunctionKey, Qt::Key_Insert }, + { NSDeleteFunctionKey, Qt::Key_Delete }, + { NSHomeFunctionKey, Qt::Key_Home }, + { NSEndFunctionKey, Qt::Key_End }, + { NSPageUpFunctionKey, Qt::Key_PageUp }, + { NSPageDownFunctionKey, Qt::Key_PageDown }, + { NSPrintScreenFunctionKey, Qt::Key_Print }, + { NSScrollLockFunctionKey, Qt::Key_ScrollLock }, + { NSPauseFunctionKey, Qt::Key_Pause }, + { NSSysReqFunctionKey, Qt::Key_SysReq }, + { NSMenuFunctionKey, Qt::Key_Menu }, + { NSHelpFunctionKey, Qt::Key_Help }, +}; +static const KeyPair * const end = entries + NumEntries; + +QChar qtKey2CocoaKey(Qt::Key key) +{ + // The first time this function is called, create a reverse + // looup table sorted on Qt Key rather than Cocoa key: + static QVector<KeyPair> rev_entries(NumEntries); + static bool mustInit = true; + if (mustInit){ + mustInit = false; + for (int i=0; i<NumEntries; ++i) + rev_entries[i] = entries[i]; + qSort(rev_entries.begin(), rev_entries.end(), qtKey2CocoaKeySortLessThan); + } + const QVector<KeyPair>::iterator i + = qBinaryFind(rev_entries.begin(), rev_entries.end(), key); + if (i == rev_entries.end()) + return QChar(); + return i->cocoaKey; +} + +#ifdef QT_MAC_USE_COCOA static Qt::Key cocoaKey2QtKey(QChar keyCode) { - static const int NumEntries = 57; - static const KeyPair entries[NumEntries] = { - { NSEnterCharacter, Qt::Key_Enter }, - { NSTabCharacter, Qt::Key_Tab }, - { NSCarriageReturnCharacter, Qt::Key_Return }, - { NSBackTabCharacter, Qt::Key_Backtab }, - { kEscapeCharCode, Qt::Key_Escape }, - { NSDeleteCharacter, Qt::Key_Backspace }, - { NSUpArrowFunctionKey, Qt::Key_Up }, - { NSDownArrowFunctionKey, Qt::Key_Down }, - { NSLeftArrowFunctionKey, Qt::Key_Left }, - { NSRightArrowFunctionKey, Qt::Key_Right }, - { NSF1FunctionKey, Qt::Key_F1 }, - { NSF2FunctionKey, Qt::Key_F2 }, - { NSF3FunctionKey, Qt::Key_F3 }, - { NSF4FunctionKey, Qt::Key_F4 }, - { NSF5FunctionKey, Qt::Key_F5 }, - { NSF6FunctionKey, Qt::Key_F6 }, - { NSF7FunctionKey, Qt::Key_F7 }, - { NSF8FunctionKey, Qt::Key_F8 }, - { NSF9FunctionKey, Qt::Key_F8 }, - { NSF10FunctionKey, Qt::Key_F10 }, - { NSF11FunctionKey, Qt::Key_F11 }, - { NSF12FunctionKey, Qt::Key_F12 }, - { NSF13FunctionKey, Qt::Key_F13 }, - { NSF14FunctionKey, Qt::Key_F14 }, - { NSF15FunctionKey, Qt::Key_F15 }, - { NSF16FunctionKey, Qt::Key_F16 }, - { NSF17FunctionKey, Qt::Key_F17 }, - { NSF18FunctionKey, Qt::Key_F18 }, - { NSF19FunctionKey, Qt::Key_F19 }, - { NSF20FunctionKey, Qt::Key_F20 }, - { NSF21FunctionKey, Qt::Key_F21 }, - { NSF22FunctionKey, Qt::Key_F22 }, - { NSF23FunctionKey, Qt::Key_F23 }, - { NSF24FunctionKey, Qt::Key_F24 }, - { NSF25FunctionKey, Qt::Key_F25 }, - { NSF26FunctionKey, Qt::Key_F26 }, - { NSF27FunctionKey, Qt::Key_F27 }, - { NSF28FunctionKey, Qt::Key_F28 }, - { NSF29FunctionKey, Qt::Key_F29 }, - { NSF30FunctionKey, Qt::Key_F30 }, - { NSF31FunctionKey, Qt::Key_F31 }, - { NSF32FunctionKey, Qt::Key_F32 }, - { NSF33FunctionKey, Qt::Key_F33 }, - { NSF34FunctionKey, Qt::Key_F34 }, - { NSF35FunctionKey, Qt::Key_F35 }, - { NSInsertFunctionKey, Qt::Key_Insert }, - { NSDeleteFunctionKey, Qt::Key_Delete }, - { NSHomeFunctionKey, Qt::Key_Home }, - { NSEndFunctionKey, Qt::Key_End }, - { NSPageUpFunctionKey, Qt::Key_PageUp }, - { NSPageDownFunctionKey, Qt::Key_PageDown }, - { NSPrintScreenFunctionKey, Qt::Key_Print }, - { NSScrollLockFunctionKey, Qt::Key_ScrollLock }, - { NSPauseFunctionKey, Qt::Key_Pause }, - { NSSysReqFunctionKey, Qt::Key_SysReq }, - { NSMenuFunctionKey, Qt::Key_Menu }, - { NSHelpFunctionKey, Qt::Key_Help }, - }; - static const KeyPair * const end = entries + NumEntries; const KeyPair *i = qBinaryFind(entries, end, keyCode); if (i == end) return Qt::Key(keyCode.unicode()); @@ -1205,7 +1242,7 @@ void qt_mac_replaceDrawRect(void * /*OSWindowRef */window, QWidgetPrivate *widge // We have the original method here. Proceed and swap the methods. method_exchangeImplementations(m1, m0); widget->originalDrawMethod = false; - [window display]; + [theWindow display]; } } @@ -1228,7 +1265,7 @@ void qt_mac_replaceDrawRectOriginal(void * /*OSWindowRef */window, QWidgetPrivat } method_exchangeImplementations(m1, m0); widget->originalDrawMethod = true; - [window display]; + [theWindow display]; } #endif // QT_MAC_USE_COCOA @@ -1298,7 +1335,7 @@ CGContextRef qt_mac_graphicsContextFor(QWidget *widget) CGrafPtr port = GetWindowPort(qt_mac_window_for(widget)); QDBeginCGContext(port, &context); #else - CGContextRef context = reinterpret_cast<CGContextRef>([[qt_mac_window_for(widget) graphicsContext] graphicsPort]); + CGContextRef context = (CGContextRef)[[NSGraphicsContext graphicsContextWithWindow:qt_mac_window_for(widget)] graphicsPort]; #endif return context; } @@ -1328,11 +1365,11 @@ QString qt_mac_get_pasteboardString(OSPasteboardRef paste) QMacCocoaAutoReleasePool pool; NSPasteboard *pb = nil; CFStringRef pbname; - if (PasteboardCopyName (paste, &pbname)) { - pb = [NSPasteboard generalPasteboard]; + if (PasteboardCopyName(paste, &pbname) == noErr) { + pb = [NSPasteboard pasteboardWithName:const_cast<NSString *>(reinterpret_cast<const NSString *>(pbname))]; + CFRelease(pbname); } else { - pb = [NSPasteboard pasteboardWithName:reinterpret_cast<const NSString *>(pbname)]; - CFRelease (pbname); + pb = [NSPasteboard generalPasteboard]; } if (pb) { NSString *text = [pb stringForType:NSStringPboardType]; @@ -1427,39 +1464,17 @@ void qt_cocoaChangeOverrideCursor(const QCursor &cursor) [static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursor)) set]; } -// WARNING: If Qt did not create NSApplication (e.g. in case it is -// used as a plugin), and at the same time, there is no window on -// screen (or the window that the event is sendt to becomes hidden etc -// before the event gets delivered), the message will not be performed. -bool qt_cocoaPostMessage(id target, SEL selector) +void qt_cocoaPostMessage(id target, SEL selector, int argCount, id arg1, id arg2) { - if (!target) - return false; - - NSInteger windowNumber = 0; - if (![NSApp isMemberOfClass:[QNSApplication class]]) { - // INVARIANT: Cocoa is not using our NSApplication subclass. That means - // we don't control the main event handler either. So target the event - // for one of the windows on screen: - NSWindow *nswin = [NSApp mainWindow]; - if (!nswin) { - nswin = [NSApp keyWindow]; - if (!nswin) - return false; - } - windowNumber = [nswin windowNumber]; - } - - // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5! + // WARNING: data1 and data2 is truncated to from 64-bit to 32-bit on OS 10.5! // That is why we need to split the address in two parts: - QCocoaPostMessageArgs *args = new QCocoaPostMessageArgs(target, selector); + QCocoaPostMessageArgs *args = new QCocoaPostMessageArgs(target, selector, argCount, arg1, arg2); quint32 lower = quintptr(args); quint32 upper = quintptr(args) >> 32; NSEvent *e = [NSEvent otherEventWithType:NSApplicationDefined - location:NSZeroPoint modifierFlags:0 timestamp:0 windowNumber:windowNumber + location:NSZeroPoint modifierFlags:0 timestamp:0 windowNumber:0 context:nil subtype:QtCocoaEventSubTypePostMessage data1:lower data2:upper]; [NSApp postEvent:e atStart:NO]; - return true; } #endif @@ -1498,7 +1513,7 @@ void macDrawRectOnTop(void * /*OSWindowRef */window) NSRect contentRect = [contentView frame]; // Draw a line on top of the already drawn line. // We need to check if we are active or not to use the proper color. - if([window isKeyWindow] || [window isMainWindow]) { + if([theWindow isKeyWindow] || [theWindow isMainWindow]) { [[NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0] set]; } else { [[NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:1.0] set]; @@ -1518,7 +1533,7 @@ void macSyncDrawingOnFirstInvocation(void * /*OSWindowRef */window) { OSWindowRef theWindow = static_cast<OSWindowRef>(window); NSApplication *application = [NSApplication sharedApplication]; - NSToolbar *toolbar = [window toolbar]; + NSToolbar *toolbar = [theWindow toolbar]; if([application isActive]) { // Launched from finder [toolbar setShowsBaselineSeparator:NO]; @@ -1546,6 +1561,13 @@ void qt_cocoaStackChildWindowOnTopOfOtherChildren(QWidget *childWidget) } } +void qt_mac_display(QWidget *widget) +{ + NSView *theNSView = qt_mac_nativeview_for(widget); + [theNSView display]; + return; +} + #endif // QT_MAC_USE_COCOA QT_END_NAMESPACE diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index c6c2db2..04c2d06 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -202,23 +202,33 @@ class QCocoaPostMessageArgs { public: id target; SEL selector; - QCocoaPostMessageArgs(id target, SEL selector) : target(target), selector(selector) + int argCount; + id arg1; + id arg2; + QCocoaPostMessageArgs(id target, SEL selector, int argCount=0, id arg1=0, id arg2=0) + : target(target), selector(selector), argCount(argCount), arg1(arg1), arg2(arg2) { [target retain]; + [arg1 retain]; + [arg2 retain]; } ~QCocoaPostMessageArgs() { + [arg2 release]; + [arg1 release]; [target release]; } }; -bool qt_cocoaPostMessage(id target, SEL selector); +void qt_cocoaPostMessage(id target, SEL selector, int argCount=0, id arg1=0, id arg2=0); #endif #endif void qt_mac_post_retranslateAppMenu(); +void qt_mac_display(QWidget *widget); + QT_END_NAMESPACE #endif // QT_COCOA_HELPERS_MAC_P_H diff --git a/src/gui/kernel/qtooltip.cpp b/src/gui/kernel/qtooltip.cpp index c8fcf45..88fdbc6 100644 --- a/src/gui/kernel/qtooltip.cpp +++ b/src/gui/kernel/qtooltip.cpp @@ -353,7 +353,7 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w) #ifndef QT_NO_STYLE_STYLESHEET if (testAttribute(Qt::WA_StyleSheet) || (w && qobject_cast<QStyleSheetStyle *>(w->style()))) { //the stylesheet need to know the real parent - QTipLabel::instance->setProperty("_q_stylesheet_parent", qVariantFromValue(w)); + QTipLabel::instance->setProperty("_q_stylesheet_parent", QVariant::fromValue(w)); //we force the style to be the QStyleSheetStyle, and force to clear the cache as well. QTipLabel::instance->setStyleSheet(QLatin1String("/* */")); diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index e22ec55..25450ce 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -76,6 +76,9 @@ # include "qpaintengine.h" // for PorterDuff # include "private/qwindowsurface_qws_p.h" #endif +#if defined(Q_WS_QPA) +#include "qplatformwindow_qpa.h" +#endif #include "qpainter.h" #include "qtooltip.h" #include "qwhatsthis.h" @@ -300,6 +303,8 @@ QWidgetPrivate::QWidgetPrivate(int version) , hasAlienChildren(0) , window_event(0) , qd_hd(0) +#elif defined (Q_WS_QPA) + , screenNumber(0) #endif { if (!qApp) { @@ -316,6 +321,9 @@ QWidgetPrivate::QWidgetPrivate(int version) drawRectOriginalAdded = false; originalDrawMethod = true; changeMethods = false; + hasOwnContext = false; + isInUnifiedToolbar = false; + unifiedSurface = 0; #endif // QT_MAC_USE_COCOA #ifdef QWIDGET_EXTRA_DEBUG static int count = 0; @@ -1267,6 +1275,12 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) // programmer specified desktop widget xinfo = desktopWidget->d_func()->xinfo; } +#elif defined(Q_WS_QPA) + if (desktopWidget) { + int screen = desktopWidget->d_func()->screenNumber; + QPlatformIntegration *platform = QApplicationPrivate::platformIntegration(); + platform->moveToScreen(q, screen); + } #else Q_UNUSED(desktopWidget); #endif @@ -1398,6 +1412,7 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow) flags |= Qt::Window; } +#ifndef Q_WS_QPA if (QWidget *parent = parentWidget()) { #ifdef Q_WS_MAC if (testAttribute(Qt::WA_NativeWindow) == false) @@ -1418,6 +1433,7 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow) return; } } +#endif //Q_WS_QPA #ifdef QT3_SUPPORT if (flags & Qt::WStaticContents) @@ -1576,13 +1592,13 @@ QWidget::~QWidget() } } -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) +#if defined(Q_WS_WIN) || defined(Q_WS_X11)|| defined(Q_WS_MAC) else if (!internalWinId() && isVisible()) { qApp->d_func()->sendSyntheticEnterLeave(this); -#ifdef Q_WS_QWS - } else if (isVisible()) { + } +#elif defined(Q_WS_QWS) || defined(Q_WS_QPA) + else if (isVisible()) { qApp->d_func()->sendSyntheticEnterLeave(this); -#endif } #endif @@ -1607,7 +1623,8 @@ QWidget::~QWidget() d->needsFlush = 0; // set all QPointers for this object to zero - QObjectPrivate::clearGuards(this); + if (d->hasGuards) + QObjectPrivate::clearGuards(this); if (d->declarativeData) { QAbstractDeclarativeData::destroyed(d->declarativeData, this); @@ -1714,6 +1731,10 @@ void QWidgetPrivate::createTLExtra() static int count = 0; qDebug() << "tlextra" << ++count; #endif +#if defined(Q_WS_QPA) + x->platformWindow = 0; + x->platformWindowFormat = QPlatformWindowFormat::defaultFormat(); +#endif } } @@ -1835,13 +1856,7 @@ void QWidgetPrivate::syncBackingStore() repaint_sys(dirty); dirty = QRegion(); } else if (QWidgetBackingStore *bs = maybeBackingStore()) { -#ifdef QT_MAC_USE_COCOA - Q_UNUSED(bs); - void qt_mac_set_needs_display(QWidget *, QRegion); - qt_mac_set_needs_display(q_func(), QRegion()); -#else bs->sync(); -#endif } } @@ -1850,13 +1865,7 @@ void QWidgetPrivate::syncBackingStore(const QRegion ®ion) if (paintOnScreen()) repaint_sys(region); else if (QWidgetBackingStore *bs = maybeBackingStore()) { -#ifdef QT_MAC_USE_COCOA - Q_UNUSED(bs); - void qt_mac_set_needs_display(QWidget *, QRegion); - qt_mac_set_needs_display(q_func(), region); -#else bs->sync(q_func(), region); -#endif } } @@ -2460,7 +2469,9 @@ WId QWidget::winId() const qDebug() << "QWidget::winId: creating native window for" << this; #endif QWidget *that = const_cast<QWidget*>(this); +#ifndef Q_WS_QPA that->setAttribute(Qt::WA_NativeWindow); +#endif that->d_func()->createWinId(); return that->data->winid; } @@ -2477,6 +2488,7 @@ void QWidgetPrivate::createWinId(WId winid) #endif const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow); if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) { +#ifndef Q_WS_QPA if (!q->isWindow()) { QWidget *parent = q->parentWidget(); QWidgetPrivate *pd = parent->d_func(); @@ -2504,6 +2516,11 @@ void QWidgetPrivate::createWinId(WId winid) } else { q->create(); } +#else + Q_UNUSED(winid); + q->create(); +#endif //Q_WS_QPA + } } @@ -5387,6 +5404,14 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP if (rgn.isEmpty()) return; +#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA) + // We disable the rendering of QToolBar in the backingStore if + // it's supposed to be in the unified toolbar on Mac OS X. + if (backingStore && isInUnifiedToolbar) + return; +#endif // Q_WS_MAC && QT_MAC_USE_COCOA + + Q_Q(QWidget); #ifndef QT_NO_GRAPHICSEFFECT if (graphicsEffect && graphicsEffect->isEnabled()) { @@ -5449,6 +5474,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP QPaintEngine *paintEngine = pdev->paintEngine(); if (paintEngine) { setRedirected(pdev, -offset); + #ifdef Q_WS_MAC // (Alien support) Special case for Mac when redirecting: If the paint device // is of the Widget type we need to set WA_WState_InPaintEvent since painting @@ -5491,7 +5517,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP //actually send the paint event QPaintEvent e(toBePainted); QCoreApplication::sendSpontaneousEvent(q, &e); -#if !defined(Q_WS_MAC) && !defined(Q_WS_QWS) +#if !defined(Q_WS_QWS) && !defined(Q_WS_QPA) if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow())) backingStore->markDirtyOnScreen(toBePainted, q, offset); #endif @@ -6638,7 +6664,7 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second) // that can take keyboard focus so that second is inserted after // that last child, and the focus order within first is (more // likely to be) preserved. - QList<QWidget *> l = qFindChildren<QWidget *>(first); + QList<QWidget *> l = first->findChildren<QWidget *>(); for (int i = l.size()-1; i >= 0; --i) { QWidget * next = l.at(i); if (next->window() == fp->window()) { @@ -7529,7 +7555,7 @@ void QWidgetPrivate::hide_helper() // next bit tries to move the focus if the focus widget is now // hidden. if (wasVisible) { -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA) qApp->d_func()->sendSyntheticEnterLeave(q); #endif @@ -7661,7 +7687,7 @@ void QWidget::setVisible(bool visible) d->show_helper(); -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA) qApp->d_func()->sendSyntheticEnterLeave(this); #endif } @@ -7793,7 +7819,7 @@ void QWidgetPrivate::hideChildren(bool spontaneous) widget->d_func()->hide_sys(); } } -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA) qApp->d_func()->sendSyntheticEnterLeave(widget); #endif #ifndef QT_NO_ACCESSIBILITY @@ -9802,6 +9828,23 @@ int QWidget::heightForWidth(int w) const return -1; } + +/*! + \internal + + *virtual private* + + This is a bit hackish, but ideally we would have created a virtual function + in the public API (however, too late...) so that subclasses could reimplement + their own function. + Instead we add a virtual function to QWidgetPrivate. + ### Qt5: move to public class and make virtual +*/ +bool QWidgetPrivate::hasHeightForWidth() const +{ + return layout ? layout->hasHeightForWidth() : size_policy.hasHeightForWidth(); +} + /*! \fn QWidget *QWidget::childAt(int x, int y) const @@ -10554,7 +10597,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) Q_ASSERT_X(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8), "QWidget::setAttribute(WidgetAttribute, bool)", "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute"); - #ifdef Q_WS_WIN // ### Don't use PaintOnScreen+paintEngine() to do native painting in 5.0 if (attribute == Qt::WA_PaintOnScreen && on && !inherits("QGLWidget")) { diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 941bd68..eea7cca 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -56,6 +56,10 @@ #include <QtGui/qcursor.h> #include <QtGui/qkeysequence.h> +#ifdef Q_WS_QPA //should this go somewhere else? +#include <QtGui/qplatformwindowformat_qpa.h> +#endif + #ifdef QT_INCLUDE_COMPAT #include <QtGui/qevent.h> #endif @@ -94,9 +98,12 @@ class QHideEvent; class QInputContext; class QIcon; class QWindowSurface; +class QPlatformWindow; class QLocale; class QGraphicsProxyWidget; class QGraphicsEffect; +class QRasterWindowSurface; +class QUnifiedToolbarSurface; #if defined(Q_WS_X11) class QX11Info; #endif @@ -627,6 +634,16 @@ public: void setWindowSurface(QWindowSurface *surface); QWindowSurface *windowSurface() const; +#if defined(Q_WS_QPA) + void setPlatformWindow(QPlatformWindow *window); + QPlatformWindow *platformWindow() const; + + void setPlatformWindowFormat(const QPlatformWindowFormat &format); + QPlatformWindowFormat platformWindowFormat() const; + + friend class QDesktopScreenWidget; +#endif + Q_SIGNALS: void customContextMenuRequested(const QPoint &pos); @@ -758,6 +775,8 @@ private: friend OSViewRef qt_mac_nativeview_for(const QWidget *w); friend void qt_event_request_window_change(QWidget *widget); friend bool qt_mac_sendMacEventToWidget(QWidget *widget, EventRef ref); + friend class QRasterWindowSurface; + friend class QUnifiedToolbarSurface; #endif #ifdef Q_WS_QWS friend class QWSBackingStore; @@ -898,13 +917,6 @@ protected: Q_DECLARE_OPERATORS_FOR_FLAGS(QWidget::RenderFlags) -#if defined Q_CC_MSVC && _MSC_VER < 1300 -template <> inline QWidget *qobject_cast_helper<QWidget*>(QObject *o, QWidget *) -{ - if (!o || !o->isWidgetType()) return 0; - return (QWidget*)(o); -} -#else template <> inline QWidget *qobject_cast<QWidget*>(QObject *o) { if (!o || !o->isWidgetType()) return 0; @@ -915,7 +927,6 @@ template <> inline const QWidget *qobject_cast<const QWidget*>(const QObject *o) if (!o || !o->isWidgetType()) return 0; return static_cast<const QWidget*>(o); } -#endif inline QWidget *QWidget::childAt(int ax, int ay) const { return childAt(QPoint(ax, ay)); } diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 997419b..fc94616 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -226,6 +226,8 @@ static NSDrawer *qt_mac_drawer_for(const QWidget *widget) for (NSWindow *window in windows) { NSArray *drawers = [window drawers]; for (NSDrawer *drawer in drawers) { + if ([drawer contentView] == widgetView) + return drawer; NSArray *views = [[drawer contentView] subviews]; for (NSView *view in views) { if (view == widgetView) @@ -240,6 +242,9 @@ static NSDrawer *qt_mac_drawer_for(const QWidget *widget) static void qt_mac_destructView(OSViewRef view) { #ifdef QT_MAC_USE_COCOA + NSWindow *window = [view window]; + if ([window contentView] == view) + [window setContentView:[[NSView alloc] initWithFrame:[view bounds]]]; [view removeFromSuperview]; [view release]; #else @@ -2294,28 +2299,23 @@ void QWidgetPrivate::finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ voidWin Q_UNUSED(dialog); data.fstrut_dirty = true; // when we create a toplevel widget, the frame strut should be dirty + OSViewRef nsview = (OSViewRef)data.winid; - OSViewRef window_contentview = qt_mac_get_contentview_for(windowRef); if (!nsview) { - nsview = qt_mac_create_widget(q, this, window_contentview); + nsview = qt_mac_create_widget(q, this, 0); setWinId(WId(nsview)); - } else { - [window_contentview addSubview:nsview]; } - if (nsview) { - NSRect bounds = [window_contentview bounds]; - [nsview setFrame:bounds]; - [nsview setHidden:NO]; - if (q->testAttribute(Qt::WA_DropSiteRegistered)) - registerDropSite(true); - transferChildren(); + [windowRef setContentView:nsview]; + [nsview setHidden:NO]; + if (q->testAttribute(Qt::WA_DropSiteRegistered)) + registerDropSite(true); + transferChildren(); - // Tell Cocoa explicit that we wan't the view to receive key events - // (regardless of focus policy) because this is how it works on other - // platforms (and in the carbon port): - if (!qApp->focusWidget()) - [windowRef makeFirstResponder:nsview]; - } + // Tell Cocoa explicit that we wan't the view to receive key events + // (regardless of focus policy) because this is how it works on other + // platforms (and in the carbon port): + if (!qApp->focusWidget()) + [windowRef makeFirstResponder:nsview]; if (topExtra->posFromMove) { updateFrameStrut(); @@ -3198,7 +3198,7 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset) if (iconButton == nil) { QCFString string(q->windowTitle()); const NSString *tmpString = reinterpret_cast<const NSString *>((CFStringRef)string); - [qt_mac_window_for(q) setRepresentedURL:[NSURL fileURLWithPath:tmpString]]; + [qt_mac_window_for(q) setRepresentedURL:[NSURL fileURLWithPath:const_cast<NSString *>(tmpString)]]; iconButton = [qt_mac_window_for(q) standardWindowButton:NSWindowDocumentIconButton]; } if (icon.isNull()) { diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index ca1e3fc..4b35238 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -102,6 +102,9 @@ class QWSManager; #if defined(Q_WS_MAC) class QCoreGraphicsPaintEnginePrivate; #endif +#if defined(Q_WS_QPA) +class QPlatformWindow; +#endif class QPaintEngine; class QPixmap; class QWidgetBackingStore; @@ -226,6 +229,9 @@ struct QTLWExtra { #endif #elif defined(Q_OS_SYMBIAN) uint inExpose : 1; // Prevents drawing recursion +#elif defined(Q_WS_QPA) + QPlatformWindow *platformWindow; + QPlatformWindowFormat platformWindowFormat; #endif }; @@ -543,6 +549,7 @@ public: bool setMinimumSize_helper(int &minw, int &minh); bool setMaximumSize_helper(int &maxw, int &maxh); + virtual bool hasHeightForWidth() const; void setConstraints_sys(); bool pointInsideRectAndMask(const QPoint &) const; QWidget *childAt_helper(const QPoint &, bool) const; @@ -843,6 +850,13 @@ public: bool originalDrawMethod; // Do we need to change the methods? bool changeMethods; + bool hasOwnContext; + CGContextRef cgContext; + QRegion ut_rg; + QPoint ut_pt; + bool isInUnifiedToolbar; + QWindowSurface *unifiedSurface; + QPoint toolbar_offset; #endif void determineWindowClass(); void transferChildren(); @@ -870,6 +884,14 @@ public: void updateCursor() const; #endif QScreen* getScreen() const; +#elif defined(Q_WS_QPA) + void setMaxWindowState_helper(); + void setFullScreenSize_helper(); + + int screenNumber; // screen the widget should be displayed on +#ifndef QT_NO_CURSOR + void updateCursor() const; +#endif #elif defined(Q_OS_SYMBIAN) // <--------------------------------------------------------- SYMBIAN static QWidget *mouseGrabber; static QWidget *keyboardGrabber; diff --git a/src/gui/kernel/qwidget_qpa.cpp b/src/gui/kernel/qwidget_qpa.cpp new file mode 100644 index 0000000..ac8b37d --- /dev/null +++ b/src/gui/kernel/qwidget_qpa.cpp @@ -0,0 +1,895 @@ +/**************************************************************************** +** +** 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 QtGui 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 "QtGui/qwidget.h" +#include "QtGui/qevent.h" +#include "QtGui/qapplication.h" +#include "QtGui/private/qbackingstore_p.h" +#include "QtGui/private/qwidget_p.h" +#include "QtGui/private/qgraphicssystem_p.h" +#include "QtGui/private/qapplication_p.h" +#include "QtGui/qdesktopwidget.h" +#include "QtGui/qplatformwindow_qpa.h" + +#include <QtGui/QPlatformCursor> + +QT_BEGIN_NAMESPACE +static QPlatformScreen *qt_screenForWidget(const QWidget *w); + +void q_createNativeChildrenAndSetParent(QPlatformWindow *parentWindow, const QWidget *parentWidget) +{ + QObjectList children = parentWidget->children(); + for (int i = 0; i < children.size(); i++) { + if (children.at(i)->isWidgetType()) { + const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i)); + if (childWidget) { // should not be necessary + if (childWidget->testAttribute(Qt::WA_NativeWindow)) { + if (!childWidget->platformWindow()) + childWidget->winId(); + } + if (childWidget->platformWindow()) { + childWidget->platformWindow()->setParent(parentWindow); + } else { + q_createNativeChildrenAndSetParent(parentWindow,childWidget); + } + } + } + } + +} + +void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow) +{ + Q_Q(QWidget); + + Q_UNUSED(window); + Q_UNUSED(initializeWindow); + Q_UNUSED(destroyOldWindow); + + Qt::WindowFlags flags = data.window_flags; + + if ((!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow()) || q->windowType() == Qt::Desktop ) + return; // we only care about real toplevels + + QWindowSurface *surface = q->windowSurface(); + QPlatformWindow *platformWindow = q->platformWindow(); + + if (!platformWindow) { + platformWindow = QApplicationPrivate::platformIntegration()->createPlatformWindow(q); + } + Q_ASSERT(platformWindow); + + if (!surface) { + surface = QApplicationPrivate::platformIntegration()->createWindowSurface(q,platformWindow->winId()); + } + + data.window_flags = q->platformWindow()->setWindowFlags(data.window_flags); + + setWinId(q->platformWindow()->winId()); + + //first check children. and create them if necessary + q_createNativeChildrenAndSetParent(q->platformWindow(),q); + + //if we we have a parent, then set correct parent; + if (!q->isWindow()) { + if (QWidget *nativeParent = q->nativeParentWidget()) { + if (nativeParent->platformWindow()) { + platformWindow->setParent(nativeParent->platformWindow()); + } + } + } + + QApplicationPrivate::platformIntegration()->moveToScreen(q, screenNumber); +// qDebug() << "create_sys" << q << q->internalWinId(); +} + +void QWidget::destroy(bool destroyWindow, bool destroySubWindows) +{ + Q_D(QWidget); + + if ((windowType() == Qt::Popup)) + qApp->d_func()->closePopup(this); + + //### we don't have proper focus event handling yet + if (this == QApplicationPrivate::active_window) + QApplication::setActiveWindow(0); + + if (windowType() != Qt::Desktop) { + if (destroySubWindows) { + QObjectList childList(children()); + for (int i = 0; i < childList.size(); i++) { + QWidget *widget = qobject_cast<QWidget *>(childList.at(i)); + if (widget && widget->testAttribute(Qt::WA_NativeWindow)) { + if (widget->platformWindow()) { + widget->destroy(); + } + } + } + } + if (destroyWindow) { + d->deleteTLSysExtra(); + } else { + if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) { + d->hide_sys(); + } + } + } +} + +void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) +{ + Q_Q(QWidget); + + // QWidget *oldParent = q->parentWidget(); + Qt::WindowFlags oldFlags = data.window_flags; + + int targetScreen = -1; + // Handle a request to move the widget to a particular screen + if (newparent && newparent->windowType() == Qt::Desktop) { + // make sure the widget is created on the same screen as the + // programmer specified desktop widget + + // get the desktop's screen number + targetScreen = newparent->d_func()->screenNumber; + newparent = 0; + } + + if (parent != newparent) { + QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function??? + if (q->platformWindow() && newparent) { + QWidget * parentWithWindow = newparent->platformWindow()? newparent : newparent->nativeParentWidget(); + if (parentWithWindow && parentWithWindow->platformWindow()) { + q->platformWindow()->setParent(parentWithWindow->platformWindow()); + } + } + + } + + if (!newparent) { + f |= Qt::Window; + if (targetScreen == -1) { + if (parent) + targetScreen = qobject_cast<QWidget *>(parent)->d_func()->screenNumber; + } + } + + bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide); + + // Reparenting toplevel to child + if (!(f&Qt::Window) && (oldFlags&Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) { + //qDebug() << "setParent_sys() change from toplevel"; + q->destroy(); + } + + data.window_flags = f; + q->setAttribute(Qt::WA_WState_Created, false); + q->setAttribute(Qt::WA_WState_Visible, false); + q->setAttribute(Qt::WA_WState_Hidden, false); + + if (f & Qt::Window) { + //qDebug() << "setParent_sys" << q << newparent << hex << f; + if (QPlatformWindow *window = q->platformWindow()) + data.window_flags = window->setWindowFlags(data.window_flags); + } + + // Reparenting child to toplevel + if ((f&Qt::Window) && !(oldFlags&Qt::Window)) { + //qDebug() << "setParent_sys() change to toplevel"; + q->create(); //### too early: this ought to happen at show() time + } + + + if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden) + q->setAttribute(Qt::WA_WState_Hidden); + q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden); + + // move the window to the selected screen + if (!newparent && targetScreen != -1) { + screenNumber = targetScreen; + // only if it is already created + if (q->testAttribute(Qt::WA_WState_Created)) { + QPlatformIntegration *platform = QApplicationPrivate::platformIntegration(); + platform->moveToScreen(q, targetScreen); + } + } +} + +QPoint QWidget::mapToGlobal(const QPoint &pos) const +{ + int x=pos.x(), y=pos.y(); + const QWidget* w = this; + while (w) { + x += w->data->crect.x(); + y += w->data->crect.y(); + w = w->isWindow() ? 0 : w->parentWidget(); + } + return QPoint(x, y); +} + +QPoint QWidget::mapFromGlobal(const QPoint &pos) const +{ + int x=pos.x(), y=pos.y(); + const QWidget* w = this; + while (w) { + x -= w->data->crect.x(); + y -= w->data->crect.y(); + w = w->isWindow() ? 0 : w->parentWidget(); + } + return QPoint(x, y); +} + +void QWidgetPrivate::updateSystemBackground() {} + +#ifndef QT_NO_CURSOR +void QWidgetPrivate::setCursor_sys(const QCursor &cursor) +{ + Q_UNUSED(cursor); + Q_Q(QWidget); + if (q->isVisible()) + qt_qpa_set_cursor(q, false); +} + +void QWidgetPrivate::unsetCursor_sys() +{ + Q_Q(QWidget); + if (q->isVisible()) + qt_qpa_set_cursor(q, false); +} + +void QWidgetPrivate::updateCursor() const +{ + // XXX +} + +#endif //QT_NO_CURSOR + +void QWidgetPrivate::setWindowTitle_sys(const QString &caption) +{ + Q_Q(QWidget); + if (!q->isWindow()) + return; + + if (QPlatformWindow *window = q->platformWindow()) + window->setWindowTitle(caption); + +} + +void QWidgetPrivate::setWindowIcon_sys(bool /*forceReset*/) +{ +} + +void QWidgetPrivate::setWindowIconText_sys(const QString &iconText) +{ + Q_UNUSED(iconText); +} + +QWidget *qt_pressGrab = 0; +QWidget *qt_mouseGrb = 0; +static QWidget *keyboardGrb = 0; + +void QWidget::grabMouse() +{ + if (qt_mouseGrb) + qt_mouseGrb->releaseMouse(); + + // XXX + //qwsDisplay()->grabMouse(this,true); + + qt_mouseGrb = this; + qt_pressGrab = 0; +} + +#ifndef QT_NO_CURSOR +void QWidget::grabMouse(const QCursor &cursor) +{ + Q_UNUSED(cursor); + + if (qt_mouseGrb) + qt_mouseGrb->releaseMouse(); + + // XXX + //qwsDisplay()->grabMouse(this,true); + //qwsDisplay()->selectCursor(this, cursor.handle()); + qt_mouseGrb = this; + qt_pressGrab = 0; +} +#endif + +void QWidget::releaseMouse() +{ + if (qt_mouseGrb == this) { + // XXX + //qwsDisplay()->grabMouse(this,false); + qt_mouseGrb = 0; + } +} + +void QWidget::grabKeyboard() +{ + if (keyboardGrb) + keyboardGrb->releaseKeyboard(); + // XXX + //qwsDisplay()->grabKeyboard(this, true); + keyboardGrb = this; +} + +void QWidget::releaseKeyboard() +{ + if (keyboardGrb == this) { + // XXX + //qwsDisplay()->grabKeyboard(this, false); + keyboardGrb = 0; + } +} + +QWidget *QWidget::mouseGrabber() +{ + if (qt_mouseGrb) + return qt_mouseGrb; + return qt_pressGrab; +} + +QWidget *QWidget::keyboardGrabber() +{ + return keyboardGrb; +} + +void QWidget::activateWindow() +{ + // XXX +// qDebug() << "QWidget::activateWindow" << this; + QApplication::setActiveWindow(this); //##### +} + +void QWidgetPrivate::show_sys() +{ + Q_Q(QWidget); + q->setAttribute(Qt::WA_Mapped); + if (q->testAttribute(Qt::WA_DontShowOnScreen)) { + invalidateBuffer(q->rect()); + return; + } + + QApplication::postEvent(q, new QUpdateLaterEvent(q->rect())); + + QPlatformWindow *window = q->platformWindow(); + if (window) { + const QRect geomRect = q->geometry(); + const QRect windowRect = window->geometry(); + if (windowRect != geomRect) { + window->setGeometry(geomRect); + } + if (q->isWindow()) { + if (QWindowSurface *surface = q->windowSurface()) { + if (windowRect.size() != geomRect.size()) { + surface->resize(geomRect.size()); + } + } + + if (window) + window->setVisible(true); + + if (q->windowType() != Qt::Popup && q->windowType() != Qt::ToolTip && !(q->windowFlags() & Qt::X11BypassWindowManagerHint)) + q->activateWindow(); //### + } + } +} + + +void QWidgetPrivate::hide_sys() +{ + Q_Q(QWidget); + q->setAttribute(Qt::WA_Mapped, false); + if (!q->isWindow()) { + QWidget *p = q->parentWidget(); + if (p &&p->isVisible()) { + invalidateBuffer(q->rect()); + } + return; + } + if (QPlatformWindow *window = q->platformWindow()) { + window->setVisible(false); + } + + //### we don't yet have proper focus event handling + if (q == QApplicationPrivate::active_window) + QApplication::setActiveWindow(0); + +} + +void QWidgetPrivate::setMaxWindowState_helper() +{ + setFullScreenSize_helper(); //### decoration size +} + +void QWidgetPrivate::setFullScreenSize_helper() +{ + Q_Q(QWidget); + + const uint old_state = data.in_set_window_state; + data.in_set_window_state = 1; + + const QRect screen = qApp->desktop()->screenGeometry(qApp->desktop()->screenNumber(q)); + q->move(screen.topLeft()); + q->resize(screen.size()); + + data.in_set_window_state = old_state; +} + +static Qt::WindowStates effectiveState(Qt::WindowStates state) + { + if (state & Qt::WindowMinimized) + return Qt::WindowMinimized; + else if (state & Qt::WindowFullScreen) + return Qt::WindowFullScreen; + else if (state & Qt::WindowMaximized) + return Qt::WindowMaximized; + return Qt::WindowNoState; + } + +void QWidget::setWindowState(Qt::WindowStates newstate) +{ + Q_D(QWidget); + Qt::WindowStates oldstate = windowState(); + if (oldstate == newstate) + return; + if (isWindow() && !testAttribute(Qt::WA_WState_Created)) + create(); + + data->window_state = newstate; + data->in_set_window_state = 1; + bool needShow = false; + Qt::WindowStates newEffectiveState = effectiveState(newstate); + Qt::WindowStates oldEffectiveState = effectiveState(oldstate); + if (isWindow() && newEffectiveState != oldEffectiveState) { + d->createTLExtra(); + if (oldEffectiveState == Qt::WindowNoState) { //normal + d->topData()->normalGeometry = geometry(); + } else if (oldEffectiveState == Qt::WindowFullScreen) { + setParent(0, d->topData()->savedFlags); + needShow = true; + } else if (oldEffectiveState == Qt::WindowMinimized) { + needShow = true; + } + + if (newEffectiveState == Qt::WindowMinimized) { + //### not ideal... + hide(); + needShow = false; + } else if (newEffectiveState == Qt::WindowFullScreen) { + d->topData()->savedFlags = windowFlags(); + setParent(0, Qt::FramelessWindowHint | (windowFlags() & Qt::WindowStaysOnTopHint)); + d->setFullScreenSize_helper(); + raise(); + needShow = true; + } else if (newEffectiveState == Qt::WindowMaximized) { + createWinId(); + d->setMaxWindowState_helper(); + } else { //normal + QRect r = d->topData()->normalGeometry; + if (r.width() >= 0) { + d->topData()->normalGeometry = QRect(0,0,-1,-1); + setGeometry(r); + } + } + } + data->in_set_window_state = 0; + + if (needShow) + show(); + + if (newstate & Qt::WindowActive) + activateWindow(); + + QWindowStateChangeEvent e(oldstate); + QApplication::sendEvent(this, &e); +} + +void QWidgetPrivate::setFocus_sys() +{ + +} + +void QWidgetPrivate::raise_sys() +{ + Q_Q(QWidget); + if (q->isWindow()) { + q->platformWindow()->raise(); + } +} + +void QWidgetPrivate::lower_sys() +{ + Q_Q(QWidget); + if (q->isWindow()) { + Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); + q->platformWindow()->lower(); + } else if (QWidget *p = q->parentWidget()) { + setDirtyOpaqueRegion(); + p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); + } +} + +void QWidgetPrivate::stackUnder_sys(QWidget*) +{ + Q_Q(QWidget); + if (QWidget *p = q->parentWidget()) { + setDirtyOpaqueRegion(); + p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); + } +} + +void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) +{ + Q_Q(QWidget); + if (extra) { // any size restrictions? + w = qMin(w,extra->maxw); + h = qMin(h,extra->maxh); + w = qMax(w,extra->minw); + h = qMax(h,extra->minh); + } + + QPoint oldp = q->geometry().topLeft(); + QSize olds = q->size(); + QRect r(x, y, w, h); + + bool isResize = olds != r.size(); + isMove = oldp != r.topLeft(); //### why do we have isMove as a parameter? + + + // We only care about stuff that changes the geometry, or may + // cause the window manager to change its state + if (r.size() == olds && oldp == r.topLeft()) + return; + + if (!data.in_set_window_state) { + q->data->window_state &= ~Qt::WindowMaximized; + q->data->window_state &= ~Qt::WindowFullScreen; + if (q->isWindow()) + topData()->normalGeometry = QRect(0, 0, -1, -1); + } + + QPoint oldPos = q->pos(); + data.crect = r; + + if (q->isVisible()) { + if (q->platformWindow()) { + if (q->isWindow()) { + q->platformWindow()->setGeometry(q->frameGeometry()); + } else { + QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint()); + q->platformWindow()->setGeometry(QRect(posInNativeParent,r.size())); + } + const QWidgetBackingStore *bs = maybeBackingStore(); + if (bs->windowSurface) { + if (isResize) + bs->windowSurface->resize(r.size()); + } + } else { + if (isMove && !isResize) + moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y()); + else + invalidateBuffer_resizeHelper(oldPos, olds); + } + + if (isMove) { + QMoveEvent e(q->pos(), oldPos); + QApplication::sendEvent(q, &e); + } + if (isResize) { + QResizeEvent e(r.size(), olds); + QApplication::sendEvent(q, &e); + if (q->platformWindow()) + q->update(); + } + } else { // not visible + if (isMove && q->pos() != oldPos) + q->setAttribute(Qt::WA_PendingMoveEvent, true); + if (isResize) + q->setAttribute(Qt::WA_PendingResizeEvent, true); + } + +} + +void QWidgetPrivate::setConstraints_sys() +{ +} + +void QWidgetPrivate::scroll_sys(int dx, int dy) +{ + Q_Q(QWidget); + scrollChildren(dx, dy); + scrollRect(q->rect(), dx, dy); +} + +void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) +{ + scrollRect(r, dx, dy); +} + +static QPlatformScreen *qt_screenForWidget(const QWidget *w) +{ + if (!w) + return 0; + QRect frame = w->frameGeometry(); + if (!w->isWindow()) + frame.moveTopLeft(w->mapToGlobal(QPoint(0, 0))); + const QPoint p = (frame.topLeft() + frame.bottomRight()) / 2; + + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + QList<QPlatformScreen *> screens = pi->screens(); + + for (int i = 0; i < screens.size(); ++i) { + if (screens[i]->geometry().contains(p)) + return screens[i]; + } + + // Assume screen zero if we have it. + if (!screens.isEmpty()) + return screens[0]; + else + qWarning("qt_screenForWidget: no screens"); + + return 0; +} + +int QWidget::metric(PaintDeviceMetric m) const +{ + Q_D(const QWidget); + + QPlatformScreen *screen = qt_screenForWidget(this); + if (!screen) { + if (m == PdmDpiX || m == PdmDpiY) + return 72; + return QPaintDevice::metric(m); + } + int val; + if (m == PdmWidth) { + val = data->crect.width(); + } else if (m == PdmWidthMM) { + val = data->crect.width() * screen->physicalSize().width() / screen->geometry().width(); + } else if (m == PdmHeight) { + val = data->crect.height(); + } else if (m == PdmHeightMM) { + val = data->crect.height() * screen->physicalSize().height() / screen->geometry().height(); + } else if (m == PdmDepth) { + return screen->depth(); + } else if (m == PdmDpiX || m == PdmPhysicalDpiX) { + if (d->extra && d->extra->customDpiX) + return d->extra->customDpiX; + else if (d->parent) + return static_cast<QWidget *>(d->parent)->metric(m); + return qRound(screen->geometry().width() / double(screen->physicalSize().width() / 25.4)); + } else if (m == PdmDpiY || m == PdmPhysicalDpiY) { + if (d->extra && d->extra->customDpiY) + return d->extra->customDpiY; + else if (d->parent) + return static_cast<QWidget *>(d->parent)->metric(m); + return qRound(screen->geometry().height() / double(screen->physicalSize().height() / 25.4)); + } else { + val = QPaintDevice::metric(m);// XXX + } + return val; +} + +/*! + \preliminary + + Sets the window to be the \a window specified. + The QWidget takes ownership of the \a surface. +*/ +void QWidget::setPlatformWindow(QPlatformWindow *window) +{ + Q_D(QWidget); + + QTLWExtra *topData = d->topData(); + if (topData->platformWindow == window) + return; + + delete topData->platformWindow; + topData->platformWindow = window; +} + +/*! + \preliminary + + Returns the QPlatformWindow this widget will be drawn into. +*/ +QPlatformWindow *QWidget::platformWindow() const +{ + Q_D(const QWidget); + QTLWExtra *extra = d->maybeTopData(); + if (extra && extra->platformWindow) + return extra->platformWindow; + + return 0; +} + +void QWidget::setPlatformWindowFormat(const QPlatformWindowFormat &format) +{ + if (isWindow() || testAttribute(Qt::WA_NativeWindow)) { + Q_D(QWidget); + QTLWExtra *topData = d->topData(); + topData->platformWindowFormat = format; + if (testAttribute(Qt::WA_WState_Created)) { + bool wasVisible = testAttribute(Qt::WA_WState_Visible); + destroy(); + d->create_sys(0,true,true); + if (wasVisible) + topData->platformWindow->setVisible(true); + } + } +} + +QPlatformWindowFormat QWidget::platformWindowFormat() const +{ + Q_D(const QWidget); + + QTLWExtra *extra = d->maybeTopData(); + if (extra){ + return extra->platformWindowFormat; + } else { + return QPlatformWindowFormat::defaultFormat(); + } +} + +void QWidgetPrivate::createSysExtra() +{ +} + +void QWidgetPrivate::deleteSysExtra() +{ + +} + +void QWidgetPrivate::createTLSysExtra() +{ +} + +void QWidgetPrivate::deleteTLSysExtra() +{ + if (extra && extra->topextra) { + delete extra->topextra->platformWindow; + extra->topextra->platformWindow = 0; + extra->topextra->backingStore.destroy(); + } +} + +void QWidgetPrivate::registerDropSite(bool on) +{ + Q_UNUSED(on); +} + +void QWidgetPrivate::setMask_sys(const QRegion ®ion) +{ + Q_UNUSED(region); + // XXX +} + +void QWidgetPrivate::updateFrameStrut() +{ + // XXX +} + +void QWidgetPrivate::setWindowOpacity_sys(qreal level) +{ + Q_Q(QWidget); + q->platformWindow()->setOpacity(level); +} + +void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect) +{ + Q_UNUSED(dontShow); + Q_UNUSED(oldRect); + // XXX +} + +QPaintEngine *QWidget::paintEngine() const +{ + qWarning("QWidget::paintEngine: Should no longer be called"); + return 0; //##### @@@ +} + +QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys() +{ + Q_Q(QWidget); + return QApplicationPrivate::platformIntegration()->createWindowSurface(q,0); +} + +void QWidgetPrivate::setModal_sys() +{ +} + +#ifndef QT_NO_CURSOR +void qt_qpa_set_cursor(QWidget * w, bool force) +{ + static QCursor arrowCursor(Qt::ArrowCursor); + static QPointer<QWidget> lastUnderMouse = 0; + + QCursor * override = QApplication::overrideCursor(); + + if (override && w != 0) + return; + + QWidget *cursorWidget; + QCursor cursorCursor; + + do { + if (w == 0) { + if (override) { + cursorCursor = *override; + cursorWidget = QApplication::topLevelAt(QCursor::pos()); + break; + } + w = QApplication::widgetAt(QCursor::pos()); + if (w == 0) // clear the override cursor while over empty space + w = QApplication::desktop(); + } else if (force) { + lastUnderMouse = w; + } else if (w->testAttribute(Qt::WA_WState_Created) && lastUnderMouse + && lastUnderMouse->effectiveWinId() == w->effectiveWinId()) { + w = lastUnderMouse; + } + if (w == QApplication::desktop() && !override) { + cursorCursor = arrowCursor; + cursorWidget = w; + break; + } + + QWidget * curWin = QApplication::activeWindow(); + if (!curWin && w && w->internalWinId()) + return; + QWidget* cW = w && !w->internalWinId() ? w : curWin; + + if (!cW || cW->window() != w->window() || + !cW->isVisible() || !cW->underMouse() || override) + return; + + cursorCursor = w->cursor(); + cursorWidget = w; + } while (0); + foreach (QWeakPointer<QPlatformCursor> cursor, QPlatformCursorPrivate::getInstances()) + if (cursor) + cursor.data()->changeCursor(&cursorCursor, cursorWidget); +} +#endif //QT_NO_CURSOR + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index cf4bdf1..636b306 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -361,7 +361,9 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de if (!q->testAttribute(Qt::WA_Moved) && !q->testAttribute(Qt::WA_DontShowOnScreen)) data.crect.moveTopLeft(QPoint(clientRect.iTl.iX, clientRect.iTl.iY)); - QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) ); + QScopedPointer<QSymbianControl> control( new QSymbianControl(q) ); + Q_CHECK_PTR(control); + QT_TRAP_THROWING(control->ConstructL(true, desktop)); control->SetMopParent(static_cast<CEikAppUi*>(S60->appUi())); @@ -406,7 +408,9 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create native child widget - QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) ); + QScopedPointer<QSymbianControl> control( new QSymbianControl(q) ); + Q_CHECK_PTR(control); + QT_TRAP_THROWING(control->ConstructL(!parentWidget)); // Symbian windows are always created in an inactive state diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 3d206fd..39ed750 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -1635,8 +1635,6 @@ void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) } } -extern Q_GUI_EXPORT HDC qt_win_display_dc(); - int QWidget::metric(PaintDeviceMetric m) const { Q_D(const QWidget); @@ -1646,7 +1644,7 @@ int QWidget::metric(PaintDeviceMetric m) const } else if (m == PdmHeight) { val = data->crect.height(); } else { - HDC gdc = qt_win_display_dc(); + HDC gdc = GetDC(0); switch (m) { case PdmDpiX: case PdmPhysicalDpiX: @@ -1697,6 +1695,7 @@ int QWidget::metric(PaintDeviceMetric m) const val = 0; qWarning("QWidget::metric: Invalid metric command"); } + ReleaseDC(0, gdc); } return val; } diff --git a/src/gui/kernel/qwindowdefs.h b/src/gui/kernel/qwindowdefs.h index a721c7d..1dc7203 100644 --- a/src/gui/kernel/qwindowdefs.h +++ b/src/gui/kernel/qwindowdefs.h @@ -131,6 +131,12 @@ QT_END_HEADER #endif // Q_WS_QWS +#if defined(Q_WS_QPA) + +typedef unsigned long WId; + +#endif // Q_WS_QPA + #if defined(Q_OS_SYMBIAN) class CCoeControl; typedef CCoeControl * WId; diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.cpp b/src/gui/kernel/qwindowsysteminterface_qpa.cpp new file mode 100644 index 0000000..bb29cbf --- /dev/null +++ b/src/gui/kernel/qwindowsysteminterface_qpa.cpp @@ -0,0 +1,255 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qwindowsysteminterface_qpa.h" +#include "qwindowsysteminterface_qpa_p.h" +#include "qapplication_p.h" +#include <QAbstractEventDispatcher> + +QT_BEGIN_NAMESPACE + + +QTime QWindowSystemInterfacePrivate::eventTime; + +//------------------------------------------------------------ +// +// Callback functions for plugins: +// + +QList<QWindowSystemInterfacePrivate::WindowSystemEvent *> QWindowSystemInterfacePrivate::windowSystemEventQueue; +QMutex QWindowSystemInterfacePrivate::queueMutex; + +extern QPointer<QWidget> qt_last_mouse_receiver; + + +void QWindowSystemInterface::handleEnterEvent(QWidget *tlw) +{ + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + return; + + QWindowSystemInterfacePrivate::EnterEvent *e = new QWindowSystemInterfacePrivate::EnterEvent(tlw); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); + } +} + +void QWindowSystemInterface::handleLeaveEvent(QWidget *tlw) +{ + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + return; + } + QWindowSystemInterfacePrivate::LeaveEvent *e = new QWindowSystemInterfacePrivate::LeaveEvent(tlw); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +void QWindowSystemInterface::handleGeometryChange(QWidget *tlw, const QRect &newRect) +{ + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + return; + } + QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(tlw,newRect); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + + +void QWindowSystemInterface::handleCloseEvent(QWidget *tlw) +{ + if (tlw) { + QWindowSystemInterfacePrivate::CloseEvent *e = + new QWindowSystemInterfacePrivate::CloseEvent(tlw); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); + } +} + +/*! + +\a tlw == 0 means that \a ev is in global coords only + + +*/ +void QWindowSystemInterface::handleMouseEvent(QWidget *w, const QPoint & local, const QPoint & global, Qt::MouseButtons b) { + unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); + handleMouseEvent(w, time, local, global, b); +} + +void QWindowSystemInterface::handleMouseEvent(QWidget *tlw, ulong timestamp, const QPoint & local, const QPoint & global, Qt::MouseButtons b) +{ + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + tlw = 0; + } + QWindowSystemInterfacePrivate::MouseEvent * e = + new QWindowSystemInterfacePrivate::MouseEvent(tlw, timestamp, local, global, b); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +void QWindowSystemInterface::handleKeyEvent(QWidget *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) { + unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); + handleKeyEvent(w, time, t, k, mods, text, autorep, count); +} + +void QWindowSystemInterface::handleKeyEvent(QWidget *tlw, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) +{ + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + tlw = 0; + } + + QWindowSystemInterfacePrivate::KeyEvent * e = + new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, t, k, mods, text, autorep, count); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +void QWindowSystemInterface::handleWheelEvent(QWidget *w, const QPoint & local, const QPoint & global, int d, Qt::Orientation o) { + unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); + handleWheelEvent(w, time, local, global, d, o); +} + +void QWindowSystemInterface::handleWheelEvent(QWidget *tlw, ulong timestamp, const QPoint & local, const QPoint & global, int d, Qt::Orientation o) +{ + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + tlw = 0; + } + + QWindowSystemInterfacePrivate::WheelEvent *e = + new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, local, global, d, o); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +int QWindowSystemInterfacePrivate::windowSystemEventsQueued() +{ + queueMutex.lock(); + int ret = windowSystemEventQueue.count(); + queueMutex.unlock(); + return ret; +} + +QWindowSystemInterfacePrivate::WindowSystemEvent * QWindowSystemInterfacePrivate::getWindowSystemEvent() +{ + queueMutex.lock(); + QWindowSystemInterfacePrivate::WindowSystemEvent *ret; + if (windowSystemEventQueue.isEmpty()) + ret = 0; + else + ret = windowSystemEventQueue.takeFirst(); + queueMutex.unlock(); + return ret; +} + +void QWindowSystemInterfacePrivate::queueWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *ev) +{ + queueMutex.lock(); + windowSystemEventQueue.append(ev); + queueMutex.unlock(); + + QAbstractEventDispatcher *dispatcher = QApplicationPrivate::qt_qpa_core_dispatcher(); + if (dispatcher) + dispatcher->wakeUp(); +} + +void QWindowSystemInterface::handleTouchEvent(QWidget *w, QEvent::Type type, QTouchEvent::DeviceType devType, const QList<struct TouchPoint> &points) { + unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); + handleTouchEvent(w, time, type, devType, points); +} + +void QWindowSystemInterface::handleTouchEvent(QWidget *tlw, ulong timestamp, QEvent::Type type, QTouchEvent::DeviceType devType, const QList<struct TouchPoint> &points) +{ + if (!points.size()) // Touch events must have at least one point + return; + + QList<QTouchEvent::TouchPoint> touchPoints; + Qt::TouchPointStates states; + QTouchEvent::TouchPoint p; + + QList<struct TouchPoint>::const_iterator point = points.constBegin(); + QList<struct TouchPoint>::const_iterator end = points.constEnd(); + while (point != end) { + p.setId(point->id); + p.setPressure(point->pressure); + states |= point->state; + Qt::TouchPointStates state = point->state; + if (point->isPrimary) { + state |= Qt::TouchPointPrimary; + } + p.setState(state); + p.setRect(point->area); + p.setScreenPos(point->area.center()); + p.setNormalizedPos(point->normalPosition); + + touchPoints.append(p); + ++point; + } + + QWindowSystemInterfacePrivate::TouchEvent *e = + new QWindowSystemInterfacePrivate::TouchEvent(tlw, timestamp, type, devType, touchPoints); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +void QWindowSystemInterface::handleScreenGeometryChange(int screenIndex) +{ + QWindowSystemInterfacePrivate::ScreenGeometryEvent *e = + new QWindowSystemInterfacePrivate::ScreenGeometryEvent(screenIndex); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +void QWindowSystemInterface::handleScreenAvailableGeometryChange(int screenIndex) +{ + QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e = + new QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent(screenIndex); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +void QWindowSystemInterface::handleScreenCountChange(int count) +{ + QWindowSystemInterfacePrivate::ScreenCountEvent *e = + new QWindowSystemInterfacePrivate::ScreenCountEvent(count); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.h b/src/gui/kernel/qwindowsysteminterface_qpa.h new file mode 100644 index 0000000..1c79f2a --- /dev/null +++ b/src/gui/kernel/qwindowsysteminterface_qpa.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ +#ifndef QWINDOWSYSTEMINTERFACE_H +#define QWINDOWSYSTEMINTERFACE_H + +#include <QtCore/QTime> +#include <QtGui/qwindowdefs.h> +#include <QtCore/QEvent> +#include <QtGui/QWidget> +#include <QtCore/QWeakPointer> +#include <QtCore/QMutex> +#include <QtGui/QTouchEvent> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class Q_GUI_EXPORT QWindowSystemInterface +{ +public: + static void handleMouseEvent(QWidget *w, const QPoint & local, const QPoint & global, Qt::MouseButtons b); + static void handleMouseEvent(QWidget *w, ulong timestamp, const QPoint & local, const QPoint & global, Qt::MouseButtons b); + + static void handleKeyEvent(QWidget *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); + static void handleKeyEvent(QWidget *w, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); + + static void handleWheelEvent(QWidget *w, const QPoint & local, const QPoint & global, int d, Qt::Orientation o); + static void handleWheelEvent(QWidget *w, ulong timestamp, const QPoint & local, const QPoint & global, int d, Qt::Orientation o); + + struct TouchPoint { + int id; // for application use + bool isPrimary; // for application use + QPointF normalPosition; // touch device coordinates, (0 to 1, 0 to 1) + QRectF area; // the touched area, centered at position in screen coordinates + qreal pressure; // 0 to 1 + Qt::TouchPointState state; //Qt::TouchPoint{Pressed|Moved|Stationary|Released} + }; + + static void handleTouchEvent(QWidget *w, QEvent::Type type, QTouchEvent::DeviceType devType, const QList<struct TouchPoint> &points); + static void handleTouchEvent(QWidget *w, ulong timestamp, QEvent::Type type, QTouchEvent::DeviceType devType, const QList<struct TouchPoint> &points); + + static void handleGeometryChange(QWidget *w, const QRect &newRect); + static void handleCloseEvent(QWidget *w); + static void handleEnterEvent(QWidget *w); + static void handleLeaveEvent(QWidget *w); + + // Changes to the screen + static void handleScreenGeometryChange(int screenIndex); + static void handleScreenAvailableGeometryChange(int screenIndex); + static void handleScreenCountChange(int count); +}; + +QT_END_NAMESPACE +QT_END_HEADER +#endif // QWINDOWSYSTEMINTERFACE_H diff --git a/src/gui/kernel/qwindowsysteminterface_qpa_p.h b/src/gui/kernel/qwindowsysteminterface_qpa_p.h new file mode 100644 index 0000000..78e1f33 --- /dev/null +++ b/src/gui/kernel/qwindowsysteminterface_qpa_p.h @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ +#ifndef QWINDOWSYSTEMINTERFACE_QPA_P_H +#define QWINDOWSYSTEMINTERFACE_QPA_P_H + +#include "qwindowsysteminterface_qpa.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QWindowSystemInterfacePrivate { +public: + enum EventType { + Close, + GeometryChange, + Enter, + Leave, + Mouse, + Wheel, + Key, + Touch, + ScreenGeometry, + ScreenAvailableGeometry, + ScreenCountChange + }; + + class WindowSystemEvent { + public: + WindowSystemEvent(EventType t) + : type(t) { } + EventType type; + }; + + class CloseEvent : public WindowSystemEvent { + public: + CloseEvent(QWidget *tlw) + : WindowSystemEvent(Close), topLevel(tlw) { } + QWeakPointer<QWidget> topLevel; + }; + + class GeometryChangeEvent : public WindowSystemEvent { + public: + GeometryChangeEvent(QWidget *tlw, const QRect &newGeometry) + : WindowSystemEvent(GeometryChange), tlw(tlw), newGeometry(newGeometry) + { } + QWeakPointer<QWidget> tlw; + QRect newGeometry; + }; + + class EnterEvent : public WindowSystemEvent { + public: + EnterEvent(QWidget *enter) + : WindowSystemEvent(Enter), enter(enter) + { } + QWeakPointer<QWidget> enter; + }; + + class LeaveEvent : public WindowSystemEvent { + public: + LeaveEvent(QWidget *leave) + : WindowSystemEvent(Leave), leave(leave) + { } + QWeakPointer<QWidget> leave; + }; + + class UserEvent : public WindowSystemEvent { + public: + UserEvent(QWidget * w, ulong time, EventType t) + : WindowSystemEvent(t), widget(w), timestamp(time) { } + QWeakPointer<QWidget> widget; + unsigned long timestamp; + }; + + class MouseEvent : public UserEvent { + public: + MouseEvent(QWidget * w, ulong time, const QPoint & local, const QPoint & global, Qt::MouseButtons b) + : UserEvent(w, time, Mouse), localPos(local), globalPos(global), buttons(b) { } + QPoint localPos; + QPoint globalPos; + Qt::MouseButtons buttons; + }; + + class WheelEvent : public UserEvent { + public: + WheelEvent(QWidget *w, ulong time, const QPoint & local, const QPoint & global, int d, Qt::Orientation o) + : UserEvent(w, time, Wheel), delta(d), localPos(local), globalPos(global), orient(o) { } + int delta; + QPoint localPos; + QPoint globalPos; + Qt::Orientation orient; + }; + + class KeyEvent : public UserEvent { + public: + KeyEvent(QWidget *w, ulong time, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1) + :UserEvent(w, time, Key), key(k), unicode(text), repeat(autorep), + repeatCount(count), modifiers(mods), keyType(t) { } + int key; + QString unicode; + bool repeat; + ushort repeatCount; + Qt::KeyboardModifiers modifiers; + QEvent::Type keyType; + }; + + class TouchEvent : public UserEvent { + public: + TouchEvent(QWidget *w, ulong time, QEvent::Type t, QTouchEvent::DeviceType d, const QList<QTouchEvent::TouchPoint> &p) + :UserEvent(w, time, Touch), devType(d), points(p), touchType(t) { } + QTouchEvent::DeviceType devType; + QList<QTouchEvent::TouchPoint> points; + QEvent::Type touchType; + + }; + + class ScreenCountEvent : public WindowSystemEvent { + public: + ScreenCountEvent (int count) + : WindowSystemEvent(ScreenCountChange) , count(count) { } + int count; + }; + + class ScreenGeometryEvent : public WindowSystemEvent { + public: + ScreenGeometryEvent(int index) + : WindowSystemEvent(ScreenGeometry), index(index) { } + int index; + }; + + class ScreenAvailableGeometryEvent : public WindowSystemEvent { + public: + ScreenAvailableGeometryEvent(int index) + : WindowSystemEvent(ScreenAvailableGeometry), index(index) { } + int index; + }; + + static QList<WindowSystemEvent *> windowSystemEventQueue; + static QMutex queueMutex; + + static int windowSystemEventsQueued(); + static WindowSystemEvent * getWindowSystemEvent(); + static void queueWindowSystemEvent(WindowSystemEvent *ev); + + static QTime eventTime; +}; + +QT_END_HEADER +QT_END_NAMESPACE + +#endif // QWINDOWSYSTEMINTERFACE_QPA_P_H diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp index 16c7f97..2f03bd0 100644 --- a/src/gui/math3d/qmatrix4x4.cpp +++ b/src/gui/math3d/qmatrix4x4.cpp @@ -102,8 +102,6 @@ QMatrix4x4::QMatrix4x4(const qreal *values) \sa optimize() */ -#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC) - /*! \fn QMatrix4x4::QMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix) @@ -112,7 +110,7 @@ QMatrix4x4::QMatrix4x4(const qreal *values) the remaining elements are filled with elements from the identity matrix. - \sa toGenericMatrix(), qGenericMatrixToMatrix4x4() + \sa toGenericMatrix() */ /*! @@ -122,34 +120,32 @@ QMatrix4x4::QMatrix4x4(const qreal *values) top-most M rows of this 4x4 matrix. If N or M is greater than 4, then the remaining elements are filled with elements from the identity matrix. - - \sa qGenericMatrixFromMatrix4x4() */ -#endif - /*! \fn QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix) \relates QMatrix4x4 + \obsolete Returns a 4x4 matrix constructed from the left-most 4 columns and top-most 4 rows of \a matrix. If \a matrix has less than 4 columns or rows, the remaining elements are filled with elements from the identity matrix. - \sa qGenericMatrixFromMatrix4x4() + \sa QMatrix4x4(const QGenericMatrix &) */ /*! \fn QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix) \relates QMatrix4x4 + \obsolete Returns a NxM generic matrix constructed from the left-most N columns and top-most M rows of \a matrix. If N or M is greater than 4, then the remaining elements are filled with elements from the identity matrix. - \sa qGenericMatrixToMatrix4x4(), QMatrix4x4::toGenericMatrix() + \sa QMatrix4x4::toGenericMatrix() */ /*! diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h index 0671fa8..598058c 100644 --- a/src/gui/math3d/qmatrix4x4.h +++ b/src/gui/math3d/qmatrix4x4.h @@ -69,10 +69,10 @@ public: qreal m21, qreal m22, qreal m23, qreal m24, qreal m31, qreal m32, qreal m33, qreal m34, qreal m41, qreal m42, qreal m43, qreal m44); -#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC) + template <int N, int M> explicit QMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix); -#endif + QMatrix4x4(const qreal *values, int cols, int rows); QMatrix4x4(const QTransform& transform); QMatrix4x4(const QMatrix& matrix); @@ -169,10 +169,8 @@ public: QRect mapRect(const QRect& rect) const; QRectF mapRect(const QRectF& rect) const; -#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC) template <int N, int M> QGenericMatrix<N, M, qreal> toGenericMatrix() const; -#endif inline qreal *data(); inline const qreal *data() const { return m[0]; } @@ -223,8 +221,6 @@ inline QMatrix4x4::QMatrix4x4 flagBits = General; } -#if !defined(QT_NO_MEMBER_TEMPLATES) - template <int N, int M> Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4 (const QGenericMatrix<N, M, qreal>& matrix) @@ -261,8 +257,6 @@ QGenericMatrix<N, M, qreal> QMatrix4x4::toGenericMatrix() const return result; } -#endif - inline const qreal& QMatrix4x4::operator()(int aRow, int aColumn) const { Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4); @@ -992,14 +986,15 @@ Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix4x4 &); Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix4x4 &); #endif +#ifdef QT_DEPRECATED template <int N, int M> -QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix) +QT_DEPRECATED QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix) { return QMatrix4x4(matrix.constData(), N, M); } template <int N, int M> -QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix) +QT_DEPRECATED QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix) { QGenericMatrix<N, M, qreal> result; const qreal *m = matrix.constData(); @@ -1016,6 +1011,7 @@ QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix } return result; } +#endif #endif diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index bd37d9f..099619c 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -87,14 +87,18 @@ SOURCES += \ painting/qpaintengine_raster.cpp \ painting/qdrawhelper.cpp \ painting/qimagescale.cpp \ - painting/qgrayraster.c + painting/qgrayraster.c \ + painting/qpaintengine_blitter.cpp \ + painting/qblittable.cpp \ HEADERS += \ painting/qpaintengine_raster_p.h \ painting/qdrawhelper_p.h \ painting/qblendfunctions_p.h \ painting/qrasterdefs_p.h \ - painting/qgrayraster_p.h + painting/qgrayraster_p.h \ + painting/qpaintengine_blitter_p.h \ + painting/qblittable_p.h \ win32 { HEADERS += painting/qprintengine_win_p.h @@ -115,20 +119,20 @@ embedded { SOURCES += \ painting/qgraphicssystem_qws.cpp \ -} else { +} else: if(!qpa) { HEADERS += \ painting/qgraphicssystem_raster_p.h \ painting/qgraphicssystem_runtime_p.h \ painting/qgraphicssystemfactory_p.h \ painting/qgraphicssystemplugin_p.h \ - painting/qwindowsurface_raster_p.h \ + painting/qwindowsurface_raster_p.h SOURCES += \ painting/qgraphicssystem_raster.cpp \ painting/qgraphicssystem_runtime.cpp \ painting/qgraphicssystemfactory.cpp \ painting/qgraphicssystemplugin.cpp \ - painting/qwindowsurface_raster.cpp \ + painting/qwindowsurface_raster.cpp } unix:x11 { @@ -141,7 +145,7 @@ unix:x11 { painting/qpaintengine_x11.cpp } -!embedded:!x11:mac { +!embedded:!qpa:!x11:mac { HEADERS += \ painting/qpaintengine_mac_p.h \ painting/qgraphicssystem_mac_p.h \ @@ -157,14 +161,14 @@ unix:x11 { painting/qprintengine_mac.mm \ } -unix:!mac:!symbian { +unix:!mac:!symbian|qpa { HEADERS += \ painting/qprinterinfo_unix_p.h SOURCES += \ painting/qprinterinfo_unix.cpp } -win32|x11|mac|embedded|symbian { +win32|x11|mac|embedded|qpa|symbian { SOURCES += painting/qbackingstore.cpp HEADERS += painting/qbackingstore_p.h } @@ -181,6 +185,12 @@ embedded { painting/qpaintdevice_qws.cpp } +qpa { + SOURCES += \ + painting/qcolormap_qpa.cpp \ + painting/qpaintdevice_qpa.cpp +} + symbian { SOURCES += \ painting/qpaintengine_s60.cpp \ @@ -191,7 +201,7 @@ symbian { painting/qpaintengine_s60_p.h } -x11|embedded { +x11|embedded|qpa { contains(QT_CONFIG,qtopia) { DEFINES += QT_NO_CUPS QT_NO_LPR } else { @@ -221,7 +231,7 @@ x11 { SOURCES += painting/qwindowsurface_x11.cpp } -mac { +!embedded:!qpa:mac { HEADERS += painting/qwindowsurface_mac_p.h SOURCES += painting/qwindowsurface_mac.cpp } @@ -248,6 +258,12 @@ symbian { QMAKE_CXXFLAGS.ARMCC *= -O3 } +mac { + HEADERS += painting/qunifiedtoolbarsurface_mac_p.h + SOURCES += painting/qunifiedtoolbarsurface_mac.cpp +} + + NEON_SOURCES += painting/qdrawhelper_neon.cpp NEON_HEADERS += painting/qdrawhelper_neon_p.h NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 8a1c154..df1210f 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -98,6 +98,21 @@ static inline void qt_flush(QWidget *widget, const QRegion ®ion, QWindowSurfa QWidgetBackingStore::showYellowThing(widget, region, flushUpdate * 10, false); #endif + //The performance hit by doing this should be negligible. However, be aware that + //using this FPS when you have > 1 windowsurface can give you inaccurate FPS + static bool fpsDebug = qgetenv("QT_DEBUG_FPS").toInt(); + if (fpsDebug) { + static QTime time = QTime::currentTime(); + static int frames = 0; + + frames++; + + if(time.elapsed() > 5000) { + double fps = double(frames * 1000) /time.restart(); + fprintf(stderr,"FPS: %.1f\n",fps); + frames = 0; + } + } if (widget != tlw) windowSurface->flush(widget, region, tlwOffset + widget->mapTo(tlw, QPoint())); else @@ -271,7 +286,11 @@ bool QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *wi void QWidgetBackingStore::releaseBuffer() { if (windowSurface) +#if defined(Q_WS_QPA) + windowSurface->resize(QSize()); +#else windowSurface->setGeometry(QRect()); +#endif #ifdef Q_BACKINGSTORE_SUBSURFACES for (int i = 0; i < subSurfaces.size(); ++i) subSurfaces.at(i)->setGeometry(QRect()); @@ -401,7 +420,11 @@ QRegion QWidgetBackingStore::dirtyRegion(QWidget *widget) const { const bool widgetDirty = widget && widget != tlw; const QRect tlwRect(topLevelRect()); +#if defined(Q_WS_QPA) + const QRect surfaceGeometry(tlwRect.topLeft(), windowSurface->size()); +#else const QRect surfaceGeometry(windowSurface->geometry()); +#endif if (fullUpdatePending || (surfaceGeometry != tlwRect && surfaceGeometry.size() != tlwRect.size())) { if (widgetDirty) { const QRect dirtyTlwRect = QRect(QPoint(), tlwRect.size()); @@ -452,7 +475,11 @@ QRegion QWidgetBackingStore::dirtyRegion(QWidget *widget) const QRegion QWidgetBackingStore::staticContents(QWidget *parent, const QRect &withinClipRect) const { if (!parent && tlw->testAttribute(Qt::WA_StaticContents)) { +#if defined(Q_WS_QPA) + const QSize surfaceGeometry(windowSurface->size()); +#else const QRect surfaceGeometry(windowSurface->geometry()); +#endif QRect surfaceRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height()); if (!withinClipRect.isEmpty()) surfaceRect &= withinClipRect; @@ -720,9 +747,8 @@ void QWidgetBackingStore::markDirtyOnScreen(const QRegion ®ion, QWidget *widg } // Alien widgets. - if (!widget->internalWinId()) { - QWidget *nativeParent = widget->nativeParentWidget(); - // Alien widgets with the top-level as the native parent (common case). + if (!widget->internalWinId() && !widget->isWindow()) { + QWidget *nativeParent = widget->nativeParentWidget(); // Alien widgets with the top-level as the native parent (common case). if (nativeParent == tlw) { if (!widget->testAttribute(Qt::WA_WState_InPaintEvent)) dirtyOnScreen += region.translated(topLevelOffset); @@ -1152,12 +1178,16 @@ void QWidgetBackingStore::sync() return; } - const bool inTopLevelResize = tlwExtra->inTopLevelResize; const bool updatesDisabled = !tlw->updatesEnabled(); - const QRect tlwRect(topLevelRect()); - const QRect surfaceGeometry(windowSurface->geometry()); bool repaintAllWidgets = false; + const bool inTopLevelResize = tlwExtra->inTopLevelResize; + const QRect tlwRect(topLevelRect()); +#ifdef Q_WS_QPA + const QRect surfaceGeometry(tlwRect.topLeft(), windowSurface->size()); +#else + const QRect surfaceGeometry(windowSurface->geometry()); +#endif if ((fullUpdatePending || inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) { if (hasStaticContents()) { // Repaint existing dirty area and newly visible area. @@ -1177,8 +1207,13 @@ void QWidgetBackingStore::sync() } } +#ifdef Q_WS_QPA + if (inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) + windowSurface->resize(tlwRect.size()); +#else if (inTopLevelResize || surfaceGeometry != tlwRect) windowSurface->setGeometry(tlwRect); +#endif if (updatesDisabled) return; diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp index 0edf256..e0c2d16 100644 --- a/src/gui/painting/qblendfunctions.cpp +++ b/src/gui/painting/qblendfunctions.cpp @@ -309,9 +309,9 @@ template <typename T> void qt_blend_argb24_on_rgb16(uchar *destPixels, int dbpl, const uchar *src = srcPixels + y * sbpl; const uchar *srcEnd = src + srcOffset; while (src < srcEnd) { -#if defined(QT_ARCH_ARM) || defined(QT_ARCH_POWERPC) || defined(QT_ARCH_SH) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_WINDOWSCE) && !defined(_X86_)) || (defined(QT_ARCH_SPARC) && defined(Q_CC_GNU)) +#if defined(QT_ARCH_ARMV5) || defined(QT_ARCH_POWERPC) || defined(QT_ARCH_SH) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_WINDOWSCE) && !defined(_X86_)) || (defined(QT_ARCH_SPARC) && defined(Q_CC_GNU)) // non-16-bit aligned memory access is not possible on PowerPC, - // ARM <v6 (QT_ARCH_ARMV6) & SH & AVR32 & SPARC w/GCC + // ARM <v6 (QT_ARCH_ARMV5) & SH & AVR32 & SPARC w/GCC quint16 spix = (quint16(src[2])<<8) + src[1]; #else quint16 spix = *(quint16 *) (src + 1); diff --git a/src/gui/painting/qblittable.cpp b/src/gui/painting/qblittable.cpp new file mode 100644 index 0000000..f4b84a9 --- /dev/null +++ b/src/gui/painting/qblittable.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qblittable_p.h" + +#ifndef QT_NO_BLITTABLE +QT_BEGIN_NAMESPACE + +class QBlittablePrivate +{ +public: + QBlittablePrivate(const QSize &size, QBlittable::Capabilities caps) + : caps(caps), m_size(size), locked(false), cachedImg(0) + {} + QBlittable::Capabilities caps; + QSize m_size; + bool locked; + QImage *cachedImg; +}; + + +QBlittable::QBlittable(const QSize &size, Capabilities caps) + : d_ptr(new QBlittablePrivate(size,caps)) +{ +} + +QBlittable::~QBlittable() +{ + delete d_ptr; +} + + +QBlittable::Capabilities QBlittable::capabilities() const +{ + Q_D(const QBlittable); + return d->caps; +} + +QSize QBlittable::size() const +{ + Q_D(const QBlittable); + return d->m_size; +} + +QImage *QBlittable::lock() +{ + Q_D(QBlittable); + if (!d->locked) { + d->cachedImg = doLock(); + d->locked = true; + } + + return d->cachedImg; +} + +void QBlittable::unlock() +{ + Q_D(QBlittable); + if (d->locked) { + doUnlock(); + d->locked = false; + } +} + +QT_END_NAMESPACE +#endif //QT_NO_BLITTABLE + diff --git a/src/gui/painting/qblittable_p.h b/src/gui/painting/qblittable_p.h new file mode 100644 index 0000000..cb56cb2 --- /dev/null +++ b/src/gui/painting/qblittable_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QBLITTABLE_P_H +#define QBLITTABLE_P_H + +#include <QtCore/qsize.h> +#include <QtGui/private/qpixmap_blitter_p.h> + + +#ifndef QT_NO_BLITTABLE +QT_BEGIN_NAMESPACE + +class QImage; +class QBlittablePrivate; + +class Q_GUI_EXPORT QBlittable +{ + Q_DECLARE_PRIVATE(QBlittable); +public: + enum Capability { + + SolidRectCapability = 0x0001, + SourcePixmapCapability = 0x0002, + SourceOverPixmapCapability = 0x0004, + SourceOverScaledPixmapCapability = 0x0008, + + // Internal ones + OutlineCapability = 0x0001000, + }; + Q_DECLARE_FLAGS (Capabilities, Capability); + + QBlittable(const QSize &size, Capabilities caps); + virtual ~QBlittable(); + + Capabilities capabilities() const; + QSize size() const; + + virtual void fillRect(const QRectF &rect, const QColor &color) = 0; + virtual void drawPixmap(const QRectF &rect, const QPixmap &pixmap, const QRectF &subrect) = 0; + + QImage *lock(); + void unlock(); + +protected: + virtual QImage *doLock() = 0; + virtual void doUnlock() = 0; + QBlittablePrivate *d_ptr; +}; + +QT_END_NAMESPACE +#endif //QT_NO_BLITTABLE +#endif //QBLITTABLE_P_H diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index d0788c7..5b35fc5 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -635,6 +635,15 @@ QBrush &QBrush::operator=(const QBrush &b) return *this; } + +/*! + \fn void QBrush::swap(QBrush &other) + \since 4.8 + + Swaps brush \a other with this brush. This operation is very + fast and never fails. +*/ + /*! Returns the brush as a QVariant */ diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h index b657301..f9acded 100644 --- a/src/gui/painting/qbrush.h +++ b/src/gui/painting/qbrush.h @@ -92,6 +92,12 @@ public: ~QBrush(); QBrush &operator=(const QBrush &brush); +#ifdef Q_COMPILER_RVALUE_REFS + inline QBrush &operator=(QBrush &&other) + { qSwap(d, other.d); return *this; } +#endif + inline void swap(QBrush &other) { qSwap(d, other.d); } + operator QVariant() const; inline Qt::BrushStyle style() const; diff --git a/src/gui/painting/qcolormap_qpa.cpp b/src/gui/painting/qcolormap_qpa.cpp new file mode 100644 index 0000000..1f4fea8 --- /dev/null +++ b/src/gui/painting/qcolormap_qpa.cpp @@ -0,0 +1,231 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qcolormap.h" +#include "qcolor.h" +#include "qpaintdevice.h" +#include "private/qapplication_p.h" +#include "private/qgraphicssystem_p.h" + +QT_BEGIN_NAMESPACE + +class QColormapPrivate +{ +public: + inline QColormapPrivate() + : ref(1), mode(QColormap::Direct), depth(0), numcolors(0) + { } + + QAtomicInt ref; + + QColormap::Mode mode; + int depth; + int numcolors; +}; + +static QColormapPrivate *screenMap = 0; + +void QColormap::initialize() +{ + screenMap = new QColormapPrivate; + + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + QList<QPlatformScreen*> screens = pi->screens(); + + screenMap->depth = screens[0]->depth(); + if (screenMap->depth < 8) { + screenMap->mode = QColormap::Indexed; + screenMap->numcolors = 256; + } else { + screenMap->mode = QColormap::Direct; + screenMap->numcolors = -1; + } +} + +void QColormap::cleanup() +{ + delete screenMap; + screenMap = 0; +} + +QColormap QColormap::instance(int /*screen*/) +{ + return QColormap(); +} + +QColormap::QColormap() + : d(screenMap) +{ d->ref.ref(); } + +QColormap::QColormap(const QColormap &colormap) + :d (colormap.d) +{ d->ref.ref(); } + +QColormap::~QColormap() +{ + if (!d->ref.deref()) + delete d; +} + +QColormap::Mode QColormap::mode() const +{ return d->mode; } + + +int QColormap::depth() const +{ return d->depth; } + + +int QColormap::size() const +{ + return d->numcolors; +} + +#ifndef QT_QWS_DEPTH16_RGB +#define QT_QWS_DEPTH16_RGB 565 +#endif +static const int qt_rbits = (QT_QWS_DEPTH16_RGB/100); +static const int qt_gbits = (QT_QWS_DEPTH16_RGB/10%10); +static const int qt_bbits = (QT_QWS_DEPTH16_RGB%10); +static const int qt_red_shift = qt_bbits+qt_gbits-(8-qt_rbits); +static const int qt_green_shift = qt_bbits-(8-qt_gbits); +static const int qt_neg_blue_shift = 8-qt_bbits; +static const int qt_blue_mask = (1<<qt_bbits)-1; +static const int qt_green_mask = (1<<(qt_gbits+qt_bbits))-(1<<qt_bbits); +static const int qt_red_mask = (1<<(qt_rbits+qt_gbits+qt_bbits))-(1<<(qt_gbits+qt_bbits)); + +static const int qt_red_rounding_shift = qt_red_shift + qt_rbits; +static const int qt_green_rounding_shift = qt_green_shift + qt_gbits; +static const int qt_blue_rounding_shift = qt_bbits - qt_neg_blue_shift; + +inline ushort qt_convRgbTo16(QRgb c) +{ + const int tr = qRed(c) << qt_red_shift; + const int tg = qGreen(c) << qt_green_shift; + const int tb = qBlue(c) >> qt_neg_blue_shift; + + return (tb & qt_blue_mask) | (tg & qt_green_mask) | (tr & qt_red_mask); +} + +inline QRgb qt_conv16ToRgb(ushort c) +{ + const int r=(c & qt_red_mask); + const int g=(c & qt_green_mask); + const int b=(c & qt_blue_mask); + const int tr = r >> qt_red_shift | r >> qt_red_rounding_shift; + const int tg = g >> qt_green_shift | g >> qt_green_rounding_shift; + const int tb = b << qt_neg_blue_shift | b >> qt_blue_rounding_shift; + + return qRgb(tr,tg,tb); +} + +uint QColormap::pixel(const QColor &color) const +{ + QRgb rgb = color.rgba(); + if (d->mode == QColormap::Direct) { + switch(d->depth) { + case 16: + return qt_convRgbTo16(rgb); + case 24: + case 32: + { + const int r = qRed(rgb); + const int g = qGreen(rgb); + const int b = qBlue(rgb); + const int red_shift = 16; + const int green_shift = 8; + const int red_mask = 0xff0000; + const int green_mask = 0x00ff00; + const int blue_mask = 0x0000ff; + const int tg = g << green_shift; +#ifdef QT_QWS_DEPTH_32_BGR + if (qt_screen->pixelType() == QScreen::BGRPixel) { + const int tb = b << red_shift; + return 0xff000000 | (r & blue_mask) | (tg & green_mask) | (tb & red_mask); + } +#endif + const int tr = r << red_shift; + return 0xff000000 | (b & blue_mask) | (tg & green_mask) | (tr & red_mask); + } + } + } + //XXX + //return qt_screen->alloc(qRed(rgb), qGreen(rgb), qBlue(rgb)); + return 0; +} + +const QColor QColormap::colorAt(uint pixel) const +{ + if (d->mode == Direct) { + if (d->depth == 16) { + pixel = qt_conv16ToRgb(pixel); + } + const int red_shift = 16; + const int green_shift = 8; + const int red_mask = 0xff0000; + const int green_mask = 0x00ff00; + const int blue_mask = 0x0000ff; +#ifdef QT_QWS_DEPTH_32_BGR + if (qt_screen->pixelType() == QScreen::BGRPixel) { + return QColor((pixel & blue_mask), + (pixel & green_mask) >> green_shift, + (pixel & red_mask) >> red_shift); + } +#endif + return QColor((pixel & red_mask) >> red_shift, + (pixel & green_mask) >> green_shift, + (pixel & blue_mask)); + } +#if 0 // XXX + Q_ASSERT_X(int(pixel) < qt_screen->numCols(), "QColormap::colorAt", "pixel out of bounds of palette"); + return QColor(qt_screen->clut()[pixel]); +#endif + return QColor(); +} + +const QVector<QColor> QColormap::colormap() const +{ + return QVector<QColor>(); +} + +QColormap &QColormap::operator=(const QColormap &colormap) +{ qAtomicAssign(d, colormap.d); return *this; } + +QT_END_NAMESPACE diff --git a/src/gui/painting/qgraphicssystem.cpp b/src/gui/painting/qgraphicssystem.cpp index f06e309..f594136 100644 --- a/src/gui/painting/qgraphicssystem.cpp +++ b/src/gui/painting/qgraphicssystem.cpp @@ -50,6 +50,9 @@ #ifdef Q_WS_MAC # include <private/qpixmap_mac_p.h> #endif +#ifdef Q_WS_QPA +# include <QtGui/private/qapplication_p.h> +#endif #ifdef Q_OS_SYMBIAN # include <private/qpixmap_s60_p.h> #endif @@ -71,8 +74,10 @@ QPixmapData *QGraphicsSystem::createDefaultPixmapData(QPixmapData::PixelType typ return new QRasterPixmapData(type); #elif defined(Q_WS_MAC) return new QMacPixmapData(type); +#elif defined(Q_WS_QPA) + return QApplicationPrivate::platformIntegration()->createPixmapData(type); #elif defined(Q_OS_SYMBIAN) - return new QS60PixmapData(type); + return new QS60PixmapData(type); #elif !defined(Q_WS_QWS) #error QGraphicsSystem::createDefaultPixmapData() not implemented #endif diff --git a/src/gui/painting/qgraphicssystem_p.h b/src/gui/painting/qgraphicssystem_p.h index 1211505..a75ea61 100644 --- a/src/gui/painting/qgraphicssystem_p.h +++ b/src/gui/painting/qgraphicssystem_p.h @@ -55,10 +55,14 @@ #include "private/qpixmapdata_p.h" #include "private/qwindowsurface_p.h" +#include "private/qpaintengine_blitter_p.h" + +#include <qdebug.h> QT_BEGIN_NAMESPACE class QPixmapFilter; +class QBlittable; class Q_GUI_EXPORT QGraphicsSystem { @@ -67,7 +71,7 @@ public: virtual QPixmapData *createPixmapData(QPixmapData *origin); virtual QWindowSurface *createWindowSurface(QWidget *widget) const = 0; - virtual ~QGraphicsSystem() = 0; + virtual ~QGraphicsSystem(); //### Remove this & change qpixmap.cpp & qbitmap.cpp once every platform is gaurenteed // to have a graphics system. diff --git a/src/gui/painting/qgraphicssystemfactory.cpp b/src/gui/painting/qgraphicssystemfactory.cpp index ee6fbd8..3adeba4 100644 --- a/src/gui/painting/qgraphicssystemfactory.cpp +++ b/src/gui/painting/qgraphicssystemfactory.cpp @@ -73,7 +73,7 @@ QGraphicsSystem *QGraphicsSystemFactory::create(const QString& key) if (system.isEmpty()) { system = QLatin1String("runtime"); } -#elif defined (QT_GRAPHICSSYSTEM_RASTER) && !defined(Q_WS_WIN) && !defined(Q_OS_SYMBIAN) +#elif defined (QT_GRAPHICSSYSTEM_RASTER) && !defined(Q_WS_WIN) && !defined(Q_OS_SYMBIAN) || defined(Q_WS_X11) if (system.isEmpty()) { system = QLatin1String("raster"); } diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp index bf03545..72e5833 100644 --- a/src/gui/painting/qoutlinemapper.cpp +++ b/src/gui/painting/qoutlinemapper.cpp @@ -47,8 +47,6 @@ QT_BEGIN_NAMESPACE -static const qreal aliasedCoordinateDelta = 0.5 - 0.015625; - #define qreal_to_fixed_26_6(f) (int(f * 64)) @@ -216,13 +214,6 @@ void QOutlineMapper::endOutline() elements = m_elements_dev.data(); } - if (m_round_coords) { - // round coordinates to match outlines drawn with drawLine_midpoint_i - for (int i = 0; i < m_elements.size(); ++i) - elements[i] = QPointF(qFloor(elements[i].x() + aliasedCoordinateDelta), - qFloor(elements[i].y() + aliasedCoordinateDelta)); - } - controlPointRect = boundingRect(elements, element_count); #ifdef QT_DEBUG_CONVERT diff --git a/src/gui/painting/qoutlinemapper_p.h b/src/gui/painting/qoutlinemapper_p.h index d534f76..fcfc9bf 100644 --- a/src/gui/painting/qoutlinemapper_p.h +++ b/src/gui/painting/qoutlinemapper_p.h @@ -95,8 +95,7 @@ public: m_tags(0), m_contours(0), m_polygon_dev(0), - m_in_clip_elements(false), - m_round_coords(false) + m_in_clip_elements(false) { } @@ -202,8 +201,6 @@ public: QT_FT_Outline *convertPath(const QPainterPath &path); QT_FT_Outline *convertPath(const QVectorPath &path); - void setCoordinateRounding(bool coordinateRounding) { m_round_coords = coordinateRounding; } - inline QPainterPath::ElementType *elementTypes() const { return m_element_types.size() == 0 ? 0 : m_element_types.data(); } public: @@ -237,9 +234,6 @@ public: bool m_valid; bool m_in_clip_elements; - -private: - bool m_round_coords; }; QT_END_NAMESPACE diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp index 3a4c94c..d4a8213 100644 --- a/src/gui/painting/qpaintbuffer.cpp +++ b/src/gui/painting/qpaintbuffer.cpp @@ -130,7 +130,7 @@ QPaintBufferPrivate::~QPaintBufferPrivate() for (int i = 0; i < commands.size(); ++i) { const QPaintBufferCommand &cmd = commands.at(i); if (cmd.id == QPaintBufferPrivate::Cmd_DrawTextItem) - delete reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(variants.at(cmd.offset))); + delete reinterpret_cast<QTextItemIntCopy *>(qvariant_cast<void *>(variants.at(cmd.offset))); } } @@ -330,7 +330,7 @@ QString QPaintBuffer::commandDescription(int command) const break; } case QPaintBufferPrivate::Cmd_SetBrush: { - QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.offset)); + QBrush brush = qvariant_cast<QBrush>(d_ptr->variants.at(cmd.offset)); debug << "Cmd_SetBrush: " << brush; break; } @@ -354,27 +354,27 @@ QString QPaintBuffer::commandDescription(int command) const break; } case QPaintBufferPrivate::Cmd_StrokeVectorPath: { - QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.extra)); + QPen pen = qvariant_cast<QPen>(d_ptr->variants.at(cmd.extra)); debug << "ExCmd_StrokeVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] << "pts/elms:" << cmd.offset << cmd.offset2 << pen; break; } case QPaintBufferPrivate::Cmd_FillVectorPath: { - QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d_ptr->variants.at(cmd.extra)); debug << "ExCmd_FillVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] << "pts/elms:" << cmd.offset << cmd.offset2 << brush; break; } case QPaintBufferPrivate::Cmd_FillRectBrush: { - QBrush brush = qVariantValue<QBrush>(d_ptr->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d_ptr->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset); debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush; break; } case QPaintBufferPrivate::Cmd_FillRectColor: { - QColor color = qVariantValue<QColor>(d_ptr->variants.at(cmd.extra)); + QColor color = qvariant_cast<QColor>(d_ptr->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d_ptr->floats.constData() + cmd.offset); debug << "ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color; break; } @@ -451,12 +451,12 @@ QString QPaintBuffer::commandDescription(int command) const break; } case QPaintBufferPrivate::Cmd_SetPen: { - QPen pen = qVariantValue<QPen>(d_ptr->variants.at(cmd.offset)); + QPen pen = qvariant_cast<QPen>(d_ptr->variants.at(cmd.offset)); debug << "Cmd_SetPen: " << pen; break; } case QPaintBufferPrivate::Cmd_SetTransform: { - QTransform xform = qVariantValue<QTransform>(d_ptr->variants.at(cmd.offset)); + QTransform xform = qvariant_cast<QTransform>(d_ptr->variants.at(cmd.offset)); debug << "Cmd_SetTransform, offset: " << cmd.offset << xform; break; } @@ -532,7 +532,7 @@ QString QPaintBuffer::commandDescription(int command) const case QPaintBufferPrivate::Cmd_DrawTextItem: { QPointF pos(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1)); - QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(d_ptr->variants.at(cmd.offset))); + QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qvariant_cast<void *>(d_ptr->variants.at(cmd.offset))); QTextItemInt &ti = (*tiCopy)(); QString text(ti.text()); @@ -1287,7 +1287,7 @@ void QPaintBufferEngine::drawTextItem(const QPointF &pos, const QTextItem &ti) qDebug() << "QPaintBufferEngine: drawTextItem: pos:" << pos << ti.text(); #endif if (m_stream_raw_text_items) { - QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawTextItem, qVariantFromValue<void *>(new QTextItemIntCopy(ti))); + QPaintBufferCommand *cmd = buffer->addCommand(QPaintBufferPrivate::Cmd_DrawTextItem, QVariant::fromValue<void *>(new QTextItemIntCopy(ti))); QFont font(ti.font()); font.setUnderline(false); @@ -1429,7 +1429,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_SetPen: { - QPen pen = qVariantValue<QPen>(d->variants.at(cmd.offset)); + QPen pen = qvariant_cast<QPen>(d->variants.at(cmd.offset)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_SetPen: " << pen; #endif @@ -1437,7 +1437,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_SetBrush: { - QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.offset)); + QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.offset)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_SetBrush: " << brush; #endif @@ -1452,7 +1452,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_SetTransform: { - QTransform xform = qVariantValue<QTransform>(d->variants.at(cmd.offset)); + QTransform xform = qvariant_cast<QTransform>(d->variants.at(cmd.offset)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_SetTransform, offset: " << cmd.offset << xform; #endif @@ -1520,7 +1520,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_StrokeVectorPath: { - QPen pen = qVariantValue<QPen>(d->variants.at(cmd.extra)); + QPen pen = qvariant_cast<QPen>(d->variants.at(cmd.extra)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_StrokeVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] @@ -1531,7 +1531,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillVectorPath: { - QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_FillVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] @@ -1705,7 +1705,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillRectBrush: { - QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush; @@ -1714,7 +1714,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillRectColor: { - QColor color = qVariantValue<QColor>(d->variants.at(cmd.extra)); + QColor color = qvariant_cast<QColor>(d->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> Cmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color; @@ -1790,7 +1790,7 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) case QPaintBufferPrivate::Cmd_DrawTextItem: { QPointF pos(d->floats.at(cmd.extra), d->floats.at(cmd.extra+1)); - QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qVariantValue<void *>(d->variants.at(cmd.offset))); + QTextItemIntCopy *tiCopy = reinterpret_cast<QTextItemIntCopy *>(qvariant_cast<void *>(d->variants.at(cmd.offset))); QTextItemInt &ti = (*tiCopy)(); QString text(ti.text()); @@ -1885,7 +1885,7 @@ void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_StrokeVectorPath: { - QPen pen = qVariantValue<QPen>(d->variants.at(cmd.extra)); + QPen pen = qvariant_cast<QPen>(d->variants.at(cmd.extra)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> ExCmd_StrokeVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] @@ -1896,7 +1896,7 @@ void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillVectorPath: { - QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra)); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> ExCmd_FillVectorPath: size: " << cmd.size // << ", hints:" << d->ints[cmd.offset2+cmd.size] @@ -1907,7 +1907,7 @@ void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillRectBrush: { - QBrush brush = qVariantValue<QBrush>(d->variants.at(cmd.extra)); + QBrush brush = qvariant_cast<QBrush>(d->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " brush: " << brush; @@ -1916,7 +1916,7 @@ void QPaintEngineExReplayer::process(const QPaintBufferCommand &cmd) break; } case QPaintBufferPrivate::Cmd_FillRectColor: { - QColor color = qVariantValue<QColor>(d->variants.at(cmd.extra)); + QColor color = qvariant_cast<QColor>(d->variants.at(cmd.extra)); QRectF *rect = (QRectF *)(d->floats.constData() + cmd.offset); #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << " -> ExCmd_FillRectBrush, offset: " << cmd.offset << " rect: " << *rect << " color: " << color; diff --git a/src/gui/painting/qpaintdevice.cpp b/src/gui/painting/qpaintdevice.cpp index 4169df0..cde7bfa 100644 --- a/src/gui/painting/qpaintdevice.cpp +++ b/src/gui/painting/qpaintdevice.cpp @@ -59,11 +59,13 @@ QPaintDevice::~QPaintDevice() } +#ifndef Q_WS_QPA int QPaintDevice::metric(PaintDeviceMetric) const { qWarning("QPaintDevice::metrics: Device has no metric information"); return 0; } +#endif Q_GUI_EXPORT int qt_paint_device_metric(const QPaintDevice *device, QPaintDevice::PaintDeviceMetric metric) { diff --git a/src/gui/painting/qpaintdevice_qpa.cpp b/src/gui/painting/qpaintdevice_qpa.cpp new file mode 100644 index 0000000..0d1ca92 --- /dev/null +++ b/src/gui/painting/qpaintdevice_qpa.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qpaintdevice.h" +#include "qpainter.h" +#include "qwidget.h" +#include "qbitmap.h" +#include "qapplication.h" + +QT_BEGIN_NAMESPACE + +extern void qt_painter_removePaintDevice(QPaintDevice *); //qpainter.cpp + +int QPaintDevice::metric(PaintDeviceMetric m) const +{ + qWarning("QPaintDevice::metrics: Device has no metric information"); + if (m == PdmDpiX) { + return 72; + } else if (m == PdmDpiY) { + return 72; + } else if (m == PdmNumColors) { + // FIXME: does this need to be a real value? + return 256; + } else { + qDebug("Unrecognised metric %d!",m); + return 0; + } +} + +QT_END_NAMESPACE diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h index b860012..ee9b457 100644 --- a/src/gui/painting/qpaintengine.h +++ b/src/gui/painting/qpaintengine.h @@ -213,6 +213,7 @@ public: OpenVG, OpenGL2, PaintBuffer, + Blitter, User = 50, // first user type id MaxUser = 100 // last user type id @@ -270,6 +271,9 @@ private: friend class QtopiaPrintEnginePrivate; friend class QProxyFontEngine; #endif +#ifdef Q_WS_QPA + friend class QFontEngineQPA; +#endif friend class QPainter; friend class QPainterPrivate; friend class QWidget; diff --git a/src/gui/painting/qpaintengine_blitter.cpp b/src/gui/painting/qpaintengine_blitter.cpp new file mode 100644 index 0000000..2e8d9dd --- /dev/null +++ b/src/gui/painting/qpaintengine_blitter.cpp @@ -0,0 +1,663 @@ +/**************************************************************************** +** +** 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 QtGui 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 "private/qpaintengine_blitter_p.h" + +#include "private/qblittable_p.h" +#include "private/qpaintengine_raster_p.h" +#include "private/qpainter_p.h" +#include "private/qapplication_p.h" +#include "private/qpixmap_blitter_p.h" + +#ifndef QT_NO_BLITTABLE +QT_BEGIN_NAMESPACE + +#define STATE_XFORM_SCALE 0x00000001 +#define STATE_XFORM_COMPLEX 0x00000002 + +#define STATE_BRUSH_PATTERN 0x00000010 +#define STATE_BRUSH_ALPHA 0x00000020 + +#define STATE_PEN_ENABLED 0x00000100 + +#define STATE_ANTIALIASING 0x00001000 +#define STATE_ALPHA 0x00002000 +#define STATE_BLENDING_COMPLEX 0x00004000 + +#define STATE_CLIPSYS_COMPLEX 0x00010000 +#define STATE_CLIP_COMPLEX 0x00020000 + + +static inline void updateStateBits(uint *state, uint mask, bool on) +{ + *state = on ? (*state | mask) : (*state & ~mask); +} + +static inline bool checkStateAgainstMask(uint state, uint mask) +{ + return !state || (state & mask && !(state & ~mask)); +} + +class CapabilitiesToStateMask +{ +public: + CapabilitiesToStateMask(QBlittable::Capabilities capabilities) + : m_capabilities(capabilities), + fillRectMask(0), + drawRectMask(0), + drawPixmapMask(0), + capabillitiesState(0) + { + if (capabilities & QBlittable::SolidRectCapability) { + setFillRectMask(); + } + if (capabilities & QBlittable::SourcePixmapCapability) { + setSourcePixmapMask(); + } + if (capabilities & QBlittable::SourceOverPixmapCapability) { + setSourceOverPixmapMask(); + } + if (capabilities & QBlittable::SourceOverScaledPixmapCapability) { + setSourceOverScaledPixmapMask(); + } + } + + inline bool canBlitterFillRect() const + { + return checkStateAgainstMask(capabillitiesState,fillRectMask); + } + + inline bool canBlitterDrawRectMask() const + { + return checkStateAgainstMask(capabillitiesState,drawRectMask); + } + + bool canBlitterDrawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) const + { + if (pm.pixmapData()->classId() != QPixmapData::BlitterClass) + return false; + if (checkStateAgainstMask(capabillitiesState,drawPixmapMask)) { + if (m_capabilities & (QBlittable::SourceOverPixmapCapability + | QBlittable::SourceOverScaledPixmapCapability)) { + if (r.size() != sr.size()) { + return m_capabilities & QBlittable::SourceOverScaledPixmapCapability; + } else { + return m_capabilities & QBlittable::SourceOverPixmapCapability; + } + } + if ((m_capabilities & QBlittable::SourcePixmapCapability) && r.size() == sr.size() && !pm.hasAlphaChannel()) { + return m_capabilities & QBlittable::SourcePixmapCapability; + } + } + return false; + } + + inline void updateState(uint mask, bool on) { + updateStateBits(&capabillitiesState,mask,on); + } + +public: + + void setFillRectMask() { + updateStateBits(&fillRectMask, STATE_XFORM_SCALE, false); + updateStateBits(&fillRectMask, STATE_XFORM_COMPLEX, false); + + updateStateBits(&fillRectMask, STATE_BRUSH_PATTERN, false); + updateStateBits(&fillRectMask, STATE_BRUSH_ALPHA, false); + + updateStateBits(&fillRectMask, STATE_PEN_ENABLED, true); + + //Sub-pixel aliasing should not be sent to the blitter + updateStateBits(&fillRectMask, STATE_ANTIALIASING, true); + updateStateBits(&fillRectMask, STATE_ALPHA, false); + updateStateBits(&fillRectMask, STATE_BLENDING_COMPLEX, false); + + updateStateBits(&fillRectMask, STATE_CLIPSYS_COMPLEX, false); + updateStateBits(&fillRectMask, STATE_CLIP_COMPLEX, false); + } + + void setSourcePixmapMask() { + updateStateBits(&drawPixmapMask, STATE_XFORM_SCALE, true); + updateStateBits(&drawPixmapMask, STATE_XFORM_COMPLEX, false); + + updateStateBits(&drawPixmapMask, STATE_BRUSH_PATTERN, true); + updateStateBits(&drawPixmapMask, STATE_BRUSH_ALPHA, false); + + updateStateBits(&drawPixmapMask, STATE_PEN_ENABLED, true); + + updateStateBits(&drawPixmapMask, STATE_ANTIALIASING, true); + updateStateBits(&drawPixmapMask, STATE_ALPHA, false); + updateStateBits(&drawPixmapMask, STATE_BLENDING_COMPLEX, false); + + updateStateBits(&drawPixmapMask, STATE_CLIPSYS_COMPLEX, false); + updateStateBits(&drawPixmapMask, STATE_CLIP_COMPLEX, false); + } + + void setSourceOverPixmapMask() { + setSourcePixmapMask(); + } + + void setSourceOverScaledPixmapMask() { + setSourceOverPixmapMask(); + updateStateBits(&drawRectMask, STATE_XFORM_SCALE, true); + } + + QBlittable::Capabilities m_capabilities; + uint fillRectMask; + uint drawRectMask; + uint drawPixmapMask; + uint capabillitiesState; +}; + +class QBlitterPaintEnginePrivate : public QPaintEngineExPrivate +{ + Q_DECLARE_PUBLIC(QBlitterPaintEngine); +public: + QBlitterPaintEnginePrivate(QBlittablePixmapData *p) + : QPaintEngineExPrivate(), + pmData(p), + isBlitterLocked(false), + hasXForm(false) + + { + raster = new QRasterPaintEngine(p->buffer()); + capabillities = new CapabilitiesToStateMask(pmData->blittable()->capabilities()); + } + + inline void lock() { + if (!isBlitterLocked) { + raster->d_func()->rasterBuffer->prepare(pmData->blittable()->lock()); + isBlitterLocked = true; + } + } + + inline void unlock() { + if (isBlitterLocked) { + pmData->blittable()->unlock(); + isBlitterLocked = false; + } + } + + void fillRect(const QRectF &rect, const QColor &color) { + Q_Q(QBlitterPaintEngine); + pmData->unmarkRasterOverlay(rect); + QRectF targetRect = rect; + if (hasXForm) { + targetRect = q->state()->matrix.mapRect(rect); + } + const QClipData *clipData = q->clip(); + if (clipData) { + if (clipData->hasRectClip) { + unlock(); + pmData->blittable()->fillRect(targetRect & clipData->clipRect, color); + } else if (clipData->hasRegionClip) { + QVector<QRect> rects = clipData->clipRegion.rects(); + for ( int i = 0; i < rects.size(); i++ ) { + QRect intersectRect = rects.at(i).intersected(targetRect.toRect()); + if (!intersectRect.isEmpty()) { + unlock(); + pmData->blittable()->fillRect(intersectRect,color); + } + } + } + } else { + if (targetRect.x() >= 0 && targetRect.y() >= 0 + && targetRect.width() <= raster->paintDevice()->width() + && targetRect.height() <= raster->paintDevice()->height()) { + unlock(); + pmData->blittable()->fillRect(targetRect,color); + } else { + QRectF deviceRect(0,0,raster->paintDevice()->width(), raster->paintDevice()->height()); + unlock(); + pmData->blittable()->fillRect(deviceRect&targetRect,color); + } + } + } + + void clipAndDrawPixmap(const QRectF &clip, const QRectF &target, const QPixmap &pm, const QRectF &sr) { + QRectF intersectedRect = clip.intersected(target); + if (intersectedRect.isEmpty()) + return; + QRectF source = sr; + if(intersectedRect.size() != target.size()) { + qreal deltaTop = target.top() - intersectedRect.top(); + qreal deltaLeft = target.left() - intersectedRect.left(); + qreal deltaBottom = target.bottom() - intersectedRect.bottom(); + qreal deltaRight = target.right() - intersectedRect.right(); + source.adjust(-deltaLeft,-deltaTop,-deltaRight,-deltaBottom); + } + pmData->unmarkRasterOverlay(intersectedRect); + pmData->blittable()->drawPixmap(intersectedRect, pm, source); + } + + void updateClip() { + Q_Q(QBlitterPaintEngine); + const QClipData *clip = q->clip(); + bool complex = clip && !(clip->hasRectClip || clip->hasRegionClip); + capabillities->updateState(STATE_CLIP_COMPLEX, complex); + } + + void systemStateChanged() { + raster->d_func()->systemStateChanged(); + } + + QRasterPaintEngine *raster; + + QBlittablePixmapData *pmData; + bool isBlitterLocked; + + CapabilitiesToStateMask *capabillities; + + uint hasXForm; +}; + +QBlitterPaintEngine::QBlitterPaintEngine(QBlittablePixmapData *p) + : QPaintEngineEx(*(new QBlitterPaintEnginePrivate(p))) +{ +} + +QBlitterPaintEngine::~QBlitterPaintEngine() +{ +} + +QPainterState *QBlitterPaintEngine::createState(QPainterState *orig) const +{ + Q_D(const QBlitterPaintEngine); + return d->raster->createState(orig); +} + +bool QBlitterPaintEngine::begin(QPaintDevice *pdev) +{ + Q_D(QBlitterPaintEngine); + + setActive(true); + bool ok = d->raster->begin(pdev); +#ifdef QT_BLITTER_RASTEROVERLAY + d->pmData->unmergeOverlay(); +#endif + return ok; +} + + +bool QBlitterPaintEngine::end() +{ + Q_D(QBlitterPaintEngine); + + setActive(false); +#ifdef QT_BLITTER_RASTEROVERLAY + d->pmData->mergeOverlay(); +#endif + return d->raster->end(); +} + + +void QBlitterPaintEngine::fill(const QVectorPath &path, const QBrush &brush) +{ + Q_D(QBlitterPaintEngine); + if (path.shape() == QVectorPath::RectangleHint) { + QRectF rect(((QPointF *) path.points())[0], ((QPointF *) path.points())[2]); + fillRect(rect, brush); + } else { + d->lock(); + d->pmData->markRasterOverlay(path); + d->raster->fill(path, brush); + } +} + +void QBlitterPaintEngine::fillRect(const QRectF &rect, const QColor &color) +{ + Q_D(QBlitterPaintEngine); + if (d->capabillities->canBlitterFillRect() && color.alpha() == 0xff) { + d->fillRect(rect, color); + } else { + d->lock(); + d->pmData->markRasterOverlay(rect); + d->raster->fillRect(rect, color); + } +} + +void QBlitterPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) +{ + if(rect.size().isEmpty()) + return; + + Q_D(QBlitterPaintEngine); + + if (qbrush_style(brush) == Qt::SolidPattern + && qbrush_color(brush).alpha() == 0xff + && d->capabillities->canBlitterFillRect()) + { + d->fillRect(rect, qbrush_color(brush)); + }else if (brush.style() == Qt::TexturePattern + && d->capabillities->canBlitterDrawPixmap(rect,brush.texture(),rect)) + { + bool rectIsFilled = false; + QRectF transformedRect = state()->matrix.mapRect(rect); + qreal x = transformedRect.x(); + qreal y = transformedRect.y(); + QPixmap pm = brush.texture(); + d->unlock(); + int srcX = int(rect.x() - state()->brushOrigin.x()) % pm.width(); + if (srcX < 0) + srcX = pm.width() + srcX; + const int startX = srcX; + int srcY = int(rect.y() - state()->brushOrigin.y()) % pm.height(); + if (srcY < 0) + srcY = pm.height() + srcY; + while (!rectIsFilled) { + qreal blitWidth = (pm.width() ) - srcX; + qreal blitHeight = (pm.height() ) - srcY; + if (x + blitWidth > transformedRect.right()) + blitWidth = transformedRect.right() -x; + if (y + blitHeight > transformedRect.bottom()) + blitHeight = transformedRect.bottom() - y; + const QClipData *clipData = clip(); + if (clipData->hasRectClip) { + QRect targetRect = QRect(x,y,blitWidth,blitHeight).intersected(clipData->clipRect); + if (targetRect.isValid()) { + int tmpSrcX = srcX + (targetRect.x() - x); + int tmpSrcY = srcY + (targetRect.y() - y); + QRect srcRect(tmpSrcX,tmpSrcY,targetRect.width(),targetRect.height()); + d->pmData->blittable()->drawPixmap(targetRect,pm,srcRect); + } + } else if (clipData->hasRegionClip) { + QVector<QRect> clipRects = clipData->clipRegion.rects(); + QRect unclippedTargetRect(x,y,blitWidth,blitHeight); + QRegion intersectedRects = clipData->clipRegion.intersected(unclippedTargetRect); + + for ( int i = 0; i < intersectedRects.rects().size(); i++ ) { + QRect targetRect = intersectedRects.rects().at(i); + if (!targetRect.isValid() || targetRect.isEmpty()) + continue; + int tmpSrcX = srcX + (targetRect.x() - x); + int tmpSrcY = srcY + (targetRect.y() - y); + QRect srcRect(tmpSrcX,tmpSrcY,targetRect.width(),targetRect.height()); + d->pmData->blittable()->drawPixmap(targetRect,pm,srcRect); + } + } + x+=blitWidth; + if (x>=transformedRect.right()) { + x = transformedRect.x(); + srcX = startX; + srcY = 0; + y+=blitHeight; + if (y>=transformedRect.bottom()) + rectIsFilled = true; + } else + srcX = 0; + } + } else { + d->lock(); + d->pmData->markRasterOverlay(rect); + d->raster->fillRect(rect, brush); + } + +} + +void QBlitterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->pmData->markRasterOverlay(path); + d->raster->stroke(path, pen); +} + +void QBlitterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->raster->clip(path, op); + d->updateClip(); +} +void QBlitterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op){ + Q_D(QBlitterPaintEngine); + d->lock(); + d->raster->clip(rect,op); + d->updateClip(); +} +void QBlitterPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op) +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->raster->clip(region,op); + d->updateClip(); +} + +void QBlitterPaintEngine::clipEnabledChanged() +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->raster->clipEnabledChanged(); +} + +void QBlitterPaintEngine::penChanged() +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->raster->penChanged(); + d->capabillities->updateState(STATE_PEN_ENABLED,qpen_style(state()->pen) != Qt::NoPen); +} + +void QBlitterPaintEngine::brushChanged() +{ + Q_D(QBlitterPaintEngine); + d->raster->brushChanged(); + + bool solid = qbrush_style(state()->brush) == Qt::SolidPattern; + + d->capabillities->updateState(STATE_BRUSH_PATTERN, !solid); + d->capabillities->updateState(STATE_BRUSH_ALPHA, + qbrush_color(state()->brush).alpha() < 255); +} + +void QBlitterPaintEngine::brushOriginChanged() +{ + Q_D(QBlitterPaintEngine); + d->raster->brushOriginChanged(); +} + +void QBlitterPaintEngine::opacityChanged() +{ + Q_D(QBlitterPaintEngine); + d->raster->opacityChanged(); + + bool translucent = state()->opacity < 1; + d->capabillities->updateState(STATE_ALPHA,translucent); +} + +void QBlitterPaintEngine::compositionModeChanged() +{ + Q_D(QBlitterPaintEngine); + d->raster->compositionModeChanged(); + + bool nonTrivial = state()->composition_mode != QPainter::CompositionMode_SourceOver + && state()->composition_mode != QPainter::CompositionMode_Source; + + d->capabillities->updateState(STATE_BLENDING_COMPLEX,nonTrivial); +} + +void QBlitterPaintEngine::renderHintsChanged() +{ + Q_D(QBlitterPaintEngine); + d->raster->renderHintsChanged(); + + bool aa = state()->renderHints & QPainter::Antialiasing; + d->capabillities->updateState(STATE_ANTIALIASING, aa); + +} + +void QBlitterPaintEngine::transformChanged() +{ + Q_D(QBlitterPaintEngine); + d->raster->transformChanged(); + + QTransform::TransformationType type = state()->matrix.type(); + + d->capabillities->updateState(STATE_XFORM_COMPLEX, type > QTransform::TxScale); + d->capabillities->updateState(STATE_XFORM_SCALE, type > QTransform::TxTranslate); + + d->hasXForm = type >= QTransform::TxTranslate; + +} + +void QBlitterPaintEngine::drawRects(const QRect *rects, int rectCount) +{ + Q_D(QBlitterPaintEngine); + if (d->capabillities->canBlitterDrawRectMask()) { + for (int i=0; i<rectCount; ++i) { + d->fillRect(rects[i], qbrush_color(state()->brush)); + } + } else { + d->pmData->markRasterOverlay(rects,rectCount); + QPaintEngineEx::drawRects(rects, rectCount); + } +} + +void QBlitterPaintEngine::drawRects(const QRectF *rects, int rectCount) +{ + Q_D(QBlitterPaintEngine); + if (d->capabillities->canBlitterDrawRectMask()) { + for (int i=0; i<rectCount; ++i) { + d->fillRect(rects[i], qbrush_color(state()->brush)); + } + } else { + d->pmData->markRasterOverlay(rects,rectCount); + QPaintEngineEx::drawRects(rects, rectCount); + } +} + +void QBlitterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) +{ + Q_D(QBlitterPaintEngine); + if (d->capabillities->canBlitterDrawPixmap(r,pm,sr)) { + + d->unlock(); + QRectF targetRect = r; + if (d->hasXForm) { + targetRect = state()->matrix.mapRect(r); + } + const QClipData *clipData = clip(); + if (clipData) { + if (clipData->hasRectClip) { + d->clipAndDrawPixmap(clipData->clipRect,targetRect,pm,sr); + }else if (clipData->hasRegionClip) { + QVector<QRect>rects = clipData->clipRegion.rects(); + for (int i = 0; i<rects.size(); i++) { + d->clipAndDrawPixmap(rects.at(i),targetRect,pm,sr); + } + } + } else { + QRectF deviceRect(0,0,d->raster->paintDevice()->width(), d->raster->paintDevice()->height()); + d->clipAndDrawPixmap(deviceRect,targetRect,pm,sr); + } + }else { + d->lock(); + d->pmData->markRasterOverlay(r); + d->raster->drawPixmap(r, pm, sr); + } +} + +void QBlitterPaintEngine::drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, + Qt::ImageConversionFlags flags) +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->pmData->markRasterOverlay(r); + d->raster->drawImage(r, pm, sr, flags); +} + + +void QBlitterPaintEngine::drawTextItem(const QPointF &pos, const QTextItem &ti) +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->raster->drawTextItem(pos, ti); + d->pmData->markRasterOverlay(pos,ti); +} + +void QBlitterPaintEngine::drawStaticTextItem(QStaticTextItem *sti) +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->raster->drawStaticTextItem(sti); + +//#### d->pmData->markRasterOverlay(sti); + qWarning("not implemented: markRasterOverlay for QStaticTextItem"); + +} + + +void QBlitterPaintEngine::drawEllipse(const QRectF &r) +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->pmData->markRasterOverlay(r); + d->raster->drawEllipse(r); +} + +void QBlitterPaintEngine::setState(QPainterState *s) +{ + Q_D(QBlitterPaintEngine); + d->lock(); + QPaintEngineEx::setState(s); + d->raster->setState(s); + + clipEnabledChanged(); + penChanged(); + brushChanged(); + brushOriginChanged(); + opacityChanged(); + compositionModeChanged(); + renderHintsChanged(); + transformChanged(); + + d->updateClip(); +} + +inline QRasterPaintEngine *QBlitterPaintEngine::raster() const +{ + Q_D(const QBlitterPaintEngine); + return d->raster; +} + +QT_END_NAMESPACE +#endif //QT_NO_BLITTABLE + diff --git a/src/gui/painting/qpaintengine_blitter_p.h b/src/gui/painting/qpaintengine_blitter_p.h new file mode 100644 index 0000000..c8aa536 --- /dev/null +++ b/src/gui/painting/qpaintengine_blitter_p.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QPAINTENGINE_BLITTER_P_H +#define QPAINTENGINE_BLITTER_P_H + +#include "private/qpaintengineex_p.h" +#include "private/qpaintengine_raster_p.h" + +#ifndef QT_NO_BLITTABLE +QT_BEGIN_NAMESPACE + +class QBlitterPaintEnginePrivate; +class QBlittablePixmapData; +class QBlittable; + +class Q_GUI_EXPORT QBlitterPaintEngine : public QPaintEngineEx +{ + Q_DECLARE_PRIVATE(QBlitterPaintEngine); +public: + QBlitterPaintEngine(QBlittablePixmapData *p); + ~QBlitterPaintEngine(); + + virtual QPainterState *createState(QPainterState *orig) const; + + virtual QPaintEngine::Type type() const { return Blitter; } + + virtual bool begin(QPaintDevice *pdev); + virtual bool end(); + + virtual void fill(const QVectorPath &path, const QBrush &brush); + virtual void stroke(const QVectorPath &path, const QPen &pen); + + virtual void clip(const QVectorPath &path, Qt::ClipOperation op); + virtual void clip(const QRect &rect, Qt::ClipOperation op); + virtual void clip(const QRegion ®ion, Qt::ClipOperation op); + + virtual void clipEnabledChanged(); + virtual void penChanged(); + virtual void brushChanged(); + virtual void brushOriginChanged(); + virtual void opacityChanged(); + virtual void compositionModeChanged(); + virtual void renderHintsChanged(); + virtual void transformChanged(); + + virtual void fillRect(const QRectF &rect, const QBrush &brush); + virtual void fillRect(const QRectF &rect, const QColor &color); + + virtual void drawRects(const QRect *rects, int rectCount); + virtual void drawRects(const QRectF *rects, int rectCount); + + virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); + + virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags); + + virtual void drawTextItem(const QPointF &pos, const QTextItem &ti); + virtual void drawStaticTextItem(QStaticTextItem *); + + virtual void drawEllipse(const QRectF &r); + + virtual void setState(QPainterState *s); + + inline QPainterState *state() { return raster()->state(); } + inline const QPainterState *state() const { const QPainterState *state = raster()->state(); return state;} + inline const QClipData *clip(){return raster()->d_func()->clip();} + +private: + QRasterPaintEngine *raster() const; +}; + +QT_END_NAMESPACE +#endif //QT_NO_BLITTABLE +#endif // QPAINTENGINE_BLITTER_P_H + diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 3717ed9..a2da94c 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -96,6 +96,8 @@ # include <private/qabstractfontengine_p.h> #elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) # include <private/qfontengine_s60_p.h> +#elif defined(Q_WS_QPA) +# include <private/qfontengine_ft_p.h> #endif #if defined(Q_WS_WIN64) @@ -124,9 +126,6 @@ void dumpClip(int width, int height, const QClipData *clip); // 4 pixels. #define int_dim(pos, dim) (int(pos+dim) - int(pos)) -// use the same rounding as in qrasterizer.cpp (6 bit fixed point) -static const qreal aliasedCoordinateDelta = 0.5 - 0.015625; - #ifdef Q_WS_WIN extern bool qt_cleartype_enabled; #endif @@ -444,7 +443,7 @@ bool QRasterPaintEngine::begin(QPaintDevice *device) if (device->devType() == QInternal::Pixmap) { QPixmap *pixmap = static_cast<QPixmap *>(device); QPixmapData *pd = pixmap->pixmapData(); - if (pd->classId() == QPixmapData::RasterClass) + if (pd->classId() == QPixmapData::RasterClass || pd->classId() == QPixmapData::BlitterClass) d->device = pd->buffer(); } else { d->device = device; @@ -1754,10 +1753,10 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) static inline QRect toNormalizedFillRect(const QRectF &rect) { - int x1 = qRound(rect.x() + aliasedCoordinateDelta); - int y1 = qRound(rect.y() + aliasedCoordinateDelta); - int x2 = qRound(rect.right() + aliasedCoordinateDelta); - int y2 = qRound(rect.bottom() + aliasedCoordinateDelta); + int x1 = qRound(rect.x()); + int y1 = qRound(rect.y()); + int x2 = qRound(rect.right()); + int y2 = qRound(rect.bottom()); if (x2 < x1) qSwap(x1, x2); @@ -2026,7 +2025,6 @@ void QRasterPaintEngine::fillPolygon(const QPointF *points, int pointCount, Poly */ void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) { - Q_D(QRasterPaintEngine); QRasterPaintEngineState *s = state(); #ifdef QT_DEBUG_DRAW @@ -2047,9 +2045,7 @@ void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, Poly if (mode != PolylineMode) { // Do the fill... if (s->brushData.blend) { - d->outlineMapper->setCoordinateRounding(s->penData.blend && s->flags.fast_pen && s->lastPen.brush().isOpaque()); fillPolygon(points, pointCount, mode); - d->outlineMapper->setCoordinateRounding(false); } } @@ -2101,7 +2097,6 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg if (s->brushData.blend) { // Compose polygon fill.., ensureOutlineMapper(); - d->outlineMapper->setCoordinateRounding(s->penData.blend != 0); d->outlineMapper->beginOutline(mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill); d->outlineMapper->moveTo(*points); const QPoint *p = points; @@ -2115,7 +2110,6 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg ProcessSpans brushBlend = d->getBrushFunc(d->outlineMapper->controlPointRect, &s->brushData); d->rasterize(d->outlineMapper->outline(), brushBlend, &s->brushData, d->rasterBuffer.data()); - d->outlineMapper->setCoordinateRounding(false); } } @@ -2163,13 +2157,11 @@ void QRasterPaintEngine::strokePolygonCosmetic(const QPointF *points, int pointC : LineDrawNormal); int dashOffset = int(s->lastPen.dashOffset()); - const QPointF offs(aliasedCoordinateDelta, aliasedCoordinateDelta); - // Draw all the line segments. for (int i=1; i<pointCount; ++i) { - QPointF lp1 = points[i-1] * s->matrix + offs; - QPointF lp2 = points[i] * s->matrix + offs; + QPointF lp1 = points[i-1] * s->matrix; + QPointF lp2 = points[i] * s->matrix; const QRectF brect(lp1, lp2); ProcessSpans penBlend = d->getPenFunc(brect, &s->penData); @@ -2191,8 +2183,8 @@ void QRasterPaintEngine::strokePolygonCosmetic(const QPointF *points, int pointC // Polygons are implicitly closed. if (needs_closing) { - QPointF lp1 = points[pointCount-1] * s->matrix + offs; - QPointF lp2 = points[0] * s->matrix + offs; + QPointF lp1 = points[pointCount-1] * s->matrix; + QPointF lp2 = points[0] * s->matrix; const QRectF brect(lp1, lp2); ProcessSpans penBlend = d->getPenFunc(brect, &s->penData); @@ -2491,7 +2483,7 @@ void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img) const QClipData *clip = d->clip(); QPointF pt(p.x() + s->matrix.dx(), p.y() + s->matrix.dy()); - if (s->flags.fast_images) { + if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()]; if (func) { if (!clip) { @@ -2580,10 +2572,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe int sr_b = qCeil(sr.bottom()) - 1; if (s->matrix.type() <= QTransform::TxScale && !s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) { - // as fillRect will apply the aliased coordinate delta we need to - // subtract it here as we don't use it for image drawing QTransform old = s->matrix; - s->matrix = s->matrix * QTransform::fromTranslate(-aliasedCoordinateDelta, -aliasedCoordinateDelta); // Do whatever fillRect() does, but without premultiplying the color if it's already premultiplied. QRgb color = img.pixel(sr_l, sr_t); @@ -2675,7 +2664,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe bool exceedsPrecision = targetBounds.width() > 0xffff || targetBounds.height() > 0xffff; - if (s->flags.fast_images && !exceedsPrecision) { + if (!exceedsPrecision && d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { if (s->matrix.type() > QTransform::TxScale) { SrcOverTransformFunc func = qTransformFunctions[d->rasterBuffer->format][img.format()]; if (func && (!clip || clip->hasRectClip)) { @@ -2727,11 +2716,9 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe d->initializeRasterizer(&d->image_filler_xform); d->rasterizer->setAntialiased(s->flags.antialiased); - const QPointF offs = s->flags.antialiased ? QPointF() : QPointF(aliasedCoordinateDelta, aliasedCoordinateDelta); - const QRectF &rect = r.normalized(); - const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f) - offs; - const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f) - offs; + const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f); + const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f); if (s->flags.tx_noshear) d->rasterizer->rasterizeLine(a, b, rect.height() / rect.width()); @@ -2740,18 +2727,16 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe return; } #endif - const qreal offs = s->flags.antialiased ? qreal(0) : aliasedCoordinateDelta; QPainterPath path; path.addRect(r); QTransform m = s->matrix; s->matrix = QTransform(m.m11(), m.m12(), m.m13(), m.m21(), m.m22(), m.m23(), - m.m31() - offs, m.m32() - offs, m.m33()); + m.m31(), m.m32(), m.m33()); fillPath(path, &d->image_filler_xform); s->matrix = m; } else { - - if (s->flags.fast_images) { + if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()]; if (func) { QPointF pt(r.x() + s->matrix.dx(), r.y() + s->matrix.dy()); @@ -3100,6 +3085,7 @@ void QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, } cache->populate(fontEngine, numGlyphs, glyphs, positions); + cache->fillInPendingGlyphs(); const QImage &image = cache->image(); int bpl = image.bytesPerLine(); @@ -3114,13 +3100,19 @@ void QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, int margin = cache->glyphMargin(); - const QFixed offs = QFixed::fromReal(aliasedCoordinateDelta); + bool supportsSubPixelPositions = fontEngine->supportsSubPixelPositions(); const uchar *bits = image.bits(); for (int i=0; i<numGlyphs; ++i) { - const QTextureGlyphCache::Coord &c = cache->coords.value(glyphs[i]); - int x = qFloor(positions[i].x + offs) + c.baseLineX - margin; - int y = qFloor(positions[i].y + offs) - c.baseLineY - margin; + + QFixed subPixelPosition; + if (supportsSubPixelPositions) + subPixelPosition = cache->subPixelPositionForX(positions[i].x); + QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphs[i], subPixelPosition); + const QTextureGlyphCache::Coord &c = cache->coords.value(glyph); + + int x = qFloor(positions[i].x) + c.baseLineX - margin; + int y = qFloor(positions[i].y) - c.baseLineY - margin; // printf("drawing [%d %d %d %d] baseline [%d %d], glyph: %d, to: %d %d, pos: %d %d\n", // c.x, c.y, @@ -3158,15 +3150,13 @@ void QRasterPaintEngine::drawGlyphsS60(const QPointF &p, const QTextItemInt &ti) fe->setFontScale(matrix.m11()); ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - const QFixed aliasDelta = QFixed::fromReal(aliasedCoordinateDelta); - for (int i=0; i<glyphs.size(); ++i) { TOpenFontCharMetrics tmetrics; const TUint8 *glyphBitmapBytes; TSize glyphBitmapSize; fe->getCharacterData(glyphs[i], tmetrics, glyphBitmapBytes, glyphBitmapSize); - const int x = qFloor(positions[i].x + tmetrics.HorizBearingX() + aliasDelta); - const int y = qFloor(positions[i].y - tmetrics.HorizBearingY() + aliasDelta); + const int x = qFloor(positions[i].x + tmetrics.HorizBearingX()); + const int y = qFloor(positions[i].y - tmetrics.HorizBearingY()); alphaPenBlt(glyphBitmapBytes, glyphBitmapSize.iWidth, 8, x, y, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight); } @@ -3379,7 +3369,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte #if defined(Q_WS_QWS) if (fontEngine->type() == QFontEngine::Box) { - fontEngine->draw(this, qFloor(p.x() + aliasedCoordinateDelta), qFloor(p.y() + aliasedCoordinateDelta), ti); + fontEngine->draw(this, qFloor(p.x()), qFloor(p.y()), ti); return; } @@ -3388,11 +3378,38 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte || (fontEngine->type() == QFontEngine::Proxy && !(static_cast<QProxyFontEngine *>(fontEngine)->drawAsOutline())) )) { - fontEngine->draw(this, qFloor(p.x() + aliasedCoordinateDelta), qFloor(p.y() + aliasedCoordinateDelta), ti); + fontEngine->draw(this, qFloor(p.x()), qFloor(p.y()), ti); return; } #endif // Q_WS_QWS +#ifdef Q_WS_QPA + if (s->matrix.type() < QTransform::TxScale) { + + QVarLengthArray<QFixedPoint> positions; + QVarLengthArray<glyph_t> glyphs; + QTransform matrix = state()->transform(); + + qreal _x = qFloor(p.x()); + qreal _y = qFloor(p.y()); + matrix.translate(_x, _y); + + fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); + if (glyphs.size() == 0) + return; + + for(int i = 0; i < glyphs.size(); i++) { + QImage img = fontEngine->alphaMapForGlyph(glyphs[i]); + glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[i]); + alphaPenBlt(img.bits(), img.bytesPerLine(), img.depth(), + qRound(positions[i].x + metrics.x), + qRound(positions[i].y + metrics.y), + img.width(), img.height()); + } + return; + } +#endif //Q_WS_QPA + #if (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) #if defined(Q_WS_QWS) && !defined(QT_NO_QWS_QPF2) @@ -3449,7 +3466,6 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte return; } - QFixed offs = QFixed::fromReal(aliasedCoordinateDelta); FT_Face lockedFace = 0; int depth; @@ -3497,8 +3513,8 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte }; alphaPenBlt(glyph->data, pitch, depth, - qFloor(positions[i].x + offs) + glyph->x, - qFloor(positions[i].y + offs) - glyph->y, + qFloor(positions[i].x) + glyph->x, + qFloor(positions[i].y) - glyph->y, glyph->width, glyph->height); } if (lockedFace) @@ -3635,8 +3651,8 @@ void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount) int m11 = int(s->matrix.m11()); int m22 = int(s->matrix.m22()); - int dx = qFloor(s->matrix.dx() + aliasedCoordinateDelta); - int dy = qFloor(s->matrix.dy() + aliasedCoordinateDelta); + int dx = qFloor(s->matrix.dx()); + int dy = qFloor(s->matrix.dy()); for (int i=0; i<lineCount; ++i) { int dashOffset = int(s->lastPen.dashOffset()); if (s->flags.int_xform) { @@ -3740,7 +3756,7 @@ void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount) for (int i=0; i<lineCount; ++i) { int dashOffset = int(s->lastPen.dashOffset()); - QLineF line = (lines[i] * s->matrix).translated(aliasedCoordinateDelta, aliasedCoordinateDelta); + QLineF line = lines[i] * s->matrix; const QRectF brect(QPointF(line.x1(), line.y1()), QPointF(line.x2(), line.y2())); ProcessSpans penBlend = d->getPenFunc(brect, &s->penData); @@ -4274,11 +4290,19 @@ void QRasterPaintEnginePrivate::recalculateFastImages() QRasterPaintEngineState *s = q->state(); s->flags.fast_images = !(s->renderHints & QPainter::SmoothPixmapTransform) - && rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver && s->matrix.type() <= QTransform::TxShear; } +bool QRasterPaintEnginePrivate::canUseFastImageBlending(QPainter::CompositionMode mode, const QImage &image) const +{ + Q_Q(const QRasterPaintEngine); + const QRasterPaintEngineState *s = q->state(); + return s->flags.fast_images + && (mode == QPainter::CompositionMode_SourceOver + || (mode == QPainter::CompositionMode_Source + && !image.hasAlphaChannel())); +} QImage QRasterBuffer::colorizeBitmap(const QImage &image, const QColor &color) { @@ -4972,8 +4996,8 @@ protected: int size, int opacity) const; uint *addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) { if (cache.size() == maxCacheSize()) { - int elem_to_remove = qrand() % maxCacheSize(); - cache.remove(cache.keys()[elem_to_remove]); // may remove more than 1, but OK + // may remove more than 1, but OK + cache.erase(cache.begin() + (qrand() % maxCacheSize())); } CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode()); generateGradientColorTable(gradient, cache_entry.buffer, paletteSize(), opacity); diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index 1016f8d..404528c 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -254,6 +254,8 @@ protected: QRasterPaintEngine(QRasterPaintEnginePrivate &d, QPaintDevice *); private: friend struct QSpanData; + friend class QBlitterPaintEngine; + friend class QBlitterPaintEnginePrivate; void init(); void fillRect(const QRectF &rect, QSpanData *data); @@ -338,6 +340,7 @@ public: void initializeRasterizer(QSpanData *data); void recalculateFastImages(); + bool canUseFastImageBlending(QPainter::CompositionMode mode, const QImage &image) const; QPaintDevice *device; QScopedPointer<QOutlineMapper> outlineMapper; diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 7fed7e4..b0ca6ed 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -61,6 +61,8 @@ #include "qstyle.h" #include "qthread.h" #include "qvarlengtharray.h" +#include "qstatictext.h" +#include "qglyphs.h" #include <private/qfontengine_p.h> #include <private/qpaintengine_p.h> @@ -70,8 +72,8 @@ #include <private/qwidget_p.h> #include <private/qpaintengine_raster_p.h> #include <private/qmath_p.h> -#include <qstatictext.h> #include <private/qstatictext_p.h> +#include <private/qglyphs_p.h> #include <private/qstylehelper_p.h> QT_BEGIN_NAMESPACE @@ -92,7 +94,7 @@ void qt_format_text(const QFont &font, QPainter *painter); static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextCharFormat::UnderlineStyle underlineStyle, - const QTextItem::RenderFlags flags, qreal width, + QTextItem::RenderFlags flags, qreal width, const QTextCharFormat &charFormat); // Helper function to calculate left most position, width and flags for decoration drawing static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray, @@ -162,6 +164,10 @@ static bool qt_painter_thread_test(int devType, const char *what, bool extraCond #endif break; default: +#ifdef Q_WS_X11 + if (QApplication::testAttribute(Qt::AA_X11InitThreads)) + return true; +#endif if (!extraCondition && QThread::currentThread() != qApp->thread()) { qWarning("QPainter: It is not safe to use %s outside the GUI thread", what); return false; @@ -2701,6 +2707,63 @@ QPainterPath QPainter::clipPath() const } /*! + Returns the bounding rectangle of the current clip if there is a clip; + otherwise returns an empty rectangle. Note that the clip region is + given in logical coordinates. + + The bounding rectangle is not guaranteed to be tight. + + \sa setClipRect(), setClipPath(), setClipRegion() + + \since 4.8 + */ + +QRectF QPainter::clipBoundingRect() const +{ + Q_D(const QPainter); + + if (!d->engine) { + qWarning("QPainter::clipBoundingRect: Painter not active"); + return QRectF(); + } + + // Accumulate the bounding box in device space. This is not 100% + // precise, but it fits within the guarantee and it is resonably + // fast. + QRectF bounds; + for (int i=0; i<d->state->clipInfo.size(); ++i) { + QRectF r; + const QPainterClipInfo &info = d->state->clipInfo.at(i); + + if (info.clipType == QPainterClipInfo::RectClip) + r = info.rect; + else if (info.clipType == QPainterClipInfo::RectFClip) + r = info.rectf; + else if (info.clipType == QPainterClipInfo::RegionClip) + r = info.region.boundingRect(); + else + r = info.path.boundingRect(); + + r = info.matrix.mapRect(r); + + if (i == 0) + bounds = r; + else if (info.operation == Qt::IntersectClip) + bounds &= r; + else if (info.operation == Qt::UniteClip) + bounds |= r; + } + + + // Map the rectangle back into logical space using the inverse + // matrix. + if (!d->txinv) + const_cast<QPainter *>(this)->d_ptr->updateInvMatrix(); + + return d->invMatrix.mapRect(bounds); +} + +/*! \fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation) Enables clipping, and sets the clip region to the given \a @@ -5256,7 +5319,7 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm) return; #ifndef QT_NO_DEBUG - qt_painter_thread_test(d->device->devType(), "drawPixmap()"); + qt_painter_thread_test(d->device->devType(), "drawPixmap()", true); #endif if (d->extended) { @@ -5326,7 +5389,7 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) if (!d->engine || pm.isNull()) return; #ifndef QT_NO_DEBUG - qt_painter_thread_test(d->device->devType(), "drawPixmap()"); + qt_painter_thread_test(d->device->devType(), "drawPixmap()", true); #endif qreal x = r.x(); @@ -5711,17 +5774,50 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags); } +/*! + Draws the glyphs represented by \a glyphs at \a position. The \a position gives the + edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font + selected on \a glyphs and at offsets given by the positions in \a glyphs. + + \since 4.8 + + \sa QGlyphs::setFont(), QGlyphs::setPositions(), QGlyphs::setGlyphIndexes() +*/ +void QPainter::drawGlyphs(const QPointF &position, const QGlyphs &glyphs) +{ + Q_D(QPainter); + + QFont oldFont = d->state->font; + d->state->font = glyphs.font(); + + QVector<quint32> glyphIndexes = glyphs.glyphIndexes(); + QVector<QPointF> glyphPositions = glyphs.positions(); + + int count = qMin(glyphIndexes.size(), glyphPositions.size()); + QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count); + for (int i=0; i<count; ++i) + fixedPointPositions[i] = QFixedPoint::fromPointF(position + glyphPositions.at(i)); + + d->drawGlyphs(glyphIndexes.data(), fixedPointPositions.data(), count); + + d->state->font = oldFont; +} void qt_draw_glyphs(QPainter *painter, const quint32 *glyphArray, const QPointF *positionArray, int glyphCount) { + QVarLengthArray<QFixedPoint, 128> positions(glyphCount); + for (int i=0; i<glyphCount; ++i) + positions[i] = QFixedPoint::fromPointF(positionArray[i]); + QPainterPrivate *painter_d = QPainterPrivate::get(painter); - painter_d->drawGlyphs(glyphArray, positionArray, glyphCount); + painter_d->drawGlyphs(const_cast<quint32 *>(glyphArray), positions.data(), glyphCount); } -void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray, - int glyphCount) +void QPainterPrivate::drawGlyphs(quint32 *glyphArray, QFixedPoint *positions, int glyphCount) { + Q_Q(QPainter); + updateState(state); QFontEngine *fontEngine = state->font.d->engineForScript(QUnicodeTables::Common); @@ -5736,12 +5832,27 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit fontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx); } - QVarLengthArray<QFixedPoint, 128> positions; + QFixed leftMost; + QFixed rightMost; + QFixed baseLine; for (int i=0; i<glyphCount; ++i) { - QFixedPoint fp = QFixedPoint::fromPointF(positionArray[i]); - positions.append(fp); + glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]); + if (i == 0 || leftMost > positions[i].x) + leftMost = positions[i].x; + + // We don't support glyphs that do not share a common baseline. If this turns out to + // be a relevant use case, then we need to find clusters of glyphs that share a baseline + // and do a drawTextItemDecorations call per cluster. + if (i == 0 || baseLine < positions[i].y) + baseLine = positions[i].y; + + // We use the advance rather than the actual bounds to match the algorithm in drawText() + if (i == 0 || rightMost < positions[i].x + gm.xoff) + rightMost = positions[i].x + gm.xoff; } + QFixed width = rightMost - leftMost; + if (extended != 0) { QStaticTextItem staticTextItem; staticTextItem.color = state->pen.color(); @@ -5749,7 +5860,7 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit staticTextItem.fontEngine = fontEngine; staticTextItem.numGlyphs = glyphCount; staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray)); - staticTextItem.glyphPositions = positions.data(); + staticTextItem.glyphPositions = positions; extended->drawStaticTextItem(&staticTextItem); } else { @@ -5766,7 +5877,7 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit textItem.glyphs.numGlyphs = glyphCount; textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray)); - textItem.glyphs.offsets = positions.data(); + textItem.glyphs.offsets = positions; textItem.glyphs.advances_x = advances.data(); textItem.glyphs.advances_y = advances.data(); textItem.glyphs.justifications = glyphJustifications.data(); @@ -5774,6 +5885,21 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit engine->drawTextItem(QPointF(0, 0), textItem); } + + QTextItemInt::RenderFlags flags; + if (state->font.underline()) + flags |= QTextItemInt::Underline; + if (state->font.overline()) + flags |= QTextItemInt::Overline; + if (state->font.strikeOut()) + flags |= QTextItemInt::StrikeOut; + + drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()), + fontEngine, + (state->font.underline() + ? QTextCharFormat::SingleUnderline + : QTextCharFormat::NoUnderline), + flags, width.toReal(), QTextCharFormat()); } /*! @@ -6309,7 +6435,7 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen) static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextCharFormat::UnderlineStyle underlineStyle, - const QTextItem::RenderFlags flags, qreal width, + QTextItem::RenderFlags flags, qreal width, const QTextCharFormat &charFormat) { if (underlineStyle == QTextCharFormat::NoUnderline @@ -6697,7 +6823,7 @@ void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPo return; #ifndef QT_NO_DEBUG - qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()"); + qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()", true); #endif qreal sw = pixmap.width(); @@ -7877,7 +8003,7 @@ void qt_format_text(const QFont &fnt, const QRectF &_r, } void qt_format_text(const QFont &fnt, const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect, - int tabstops, int *, int tabarraylen, + int tabstops, int *ta, int tabarraylen, QPainter *painter) { @@ -7997,6 +8123,16 @@ start_lengthVariant: engine.option = *option; } + if (engine.option.tabStop() < 0 && tabstops > 0) + engine.option.setTabStop(tabstops); + + if (engine.option.tabs().isEmpty() && ta) { + QList<qreal> tabs; + for (int i = 0; i < tabarraylen; i++) + tabs.append(qreal(ta[i])); + engine.option.setTabArray(tabs); + } + engine.option.setTextDirection(layout_direction); if (tf & Qt::AlignJustify) engine.option.setAlignment(Qt::AlignJustify); diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index edfb67e..96305e3 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -79,6 +79,7 @@ class QTextItem; class QMatrix; class QTransform; class QStaticText; +class QGlyphs; class QPainterPrivateDeleter; @@ -221,6 +222,8 @@ public: void setClipping(bool enable); bool hasClipping() const; + QRectF clipBoundingRect() const; + void save(); void restore(); @@ -396,6 +399,8 @@ public: void setLayoutDirection(Qt::LayoutDirection direction); Qt::LayoutDirection layoutDirection() const; + void drawGlyphs(const QPointF &position, const QGlyphs &glyphs); + void drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText); inline void drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText); inline void drawStaticText(int left, int top, const QStaticText &staticText); diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h index 9362dbe..a61f5ca 100644 --- a/src/gui/painting/qpainter_p.h +++ b/src/gui/painting/qpainter_p.h @@ -70,6 +70,7 @@ QT_BEGIN_NAMESPACE class QPaintEngine; class QEmulationPaintEngine; class QPaintEngineEx; +struct QFixedPoint; struct QTLWExtra; @@ -228,7 +229,7 @@ public: void draw_helper(const QPainterPath &path, DrawOperation operation = StrokeAndFillDraw); void drawStretchedGradient(const QPainterPath &path, DrawOperation operation); void drawOpaqueBackground(const QPainterPath &path, DrawOperation operation); - void drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray, int glyphCount); + void drawGlyphs(quint32 *glyphArray, QFixedPoint *positionArray, int glyphCount); void updateMatrix(); void updateInvMatrix(); diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index ffd0d5c..7d6ea12 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -576,6 +576,14 @@ QPainterPath &QPainterPath::operator=(const QPainterPath &other) } /*! + \fn void QPainterPath::swap(QPainterPath &other) + \since 4.8 + + Swaps painter path \a other with this painter path. This operation is very + fast and never fails. +*/ + +/*! Destroys this QPainterPath object. */ QPainterPath::~QPainterPath() diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h index 15d83b8..82facf8 100644 --- a/src/gui/painting/qpainterpath.h +++ b/src/gui/painting/qpainterpath.h @@ -95,7 +95,12 @@ public: explicit QPainterPath(const QPointF &startPoint); QPainterPath(const QPainterPath &other); QPainterPath &operator=(const QPainterPath &other); +#ifdef Q_COMPILER_RVALUE_REFS + inline QPainterPath &operator=(QPainterPath &&other) + { qSwap(d_ptr, other.d_ptr); return *this; } +#endif ~QPainterPath(); + inline void swap(QPainterPath &other) { d_ptr.swap(other.d_ptr); } void closeSubpath(); diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index ba5d164..45af03a 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -915,7 +915,6 @@ const char *QPdf::paperSizeToString(QPrinter::PaperSize paperSize) return psToStr[paperSize]; } - // -------------------------- base engine, shared code between PS and PDF ----------------------- QPdfBaseEngine::QPdfBaseEngine(QPdfBaseEnginePrivate &dd, PaintEngineFeatures f) diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp index 2e43984..0137763 100644 --- a/src/gui/painting/qpen.cpp +++ b/src/gui/painting/qpen.cpp @@ -383,6 +383,14 @@ QPen &QPen::operator=(const QPen &p) } /*! + \fn void QPen::swap(QPen &other) + \since 4.8 + + Swaps pen \a other with this pen. This operation is very + fast and never fails. +*/ + +/*! Returns the pen as a QVariant. */ QPen::operator QVariant() const diff --git a/src/gui/painting/qpen.h b/src/gui/painting/qpen.h index aff7071..a7b946c 100644 --- a/src/gui/painting/qpen.h +++ b/src/gui/painting/qpen.h @@ -74,6 +74,11 @@ public: ~QPen(); QPen &operator=(const QPen &pen); +#ifdef Q_COMPILER_RVALUE_REFS + inline QPen &operator=(QPen &&other) + { qSwap(d, other.d); return *this; } +#endif + inline void swap(QPen &other) { qSwap(d, other.d); } Qt::PenStyle style() const; void setStyle(Qt::PenStyle); diff --git a/src/gui/painting/qpolygon.cpp b/src/gui/painting/qpolygon.cpp index 2fb52b5..83323d0 100644 --- a/src/gui/painting/qpolygon.cpp +++ b/src/gui/painting/qpolygon.cpp @@ -700,6 +700,22 @@ QPolygon QPolygonF::toPolygon() const } /*! + \fn void QPolygon::swap(QPolygon &other) + \since 4.8 + + Swaps polygon \a other with this polygon. This operation is very + fast and never fails. +*/ + +/*! + \fn void QPolygonF::swap(QPolygonF &other) + \since 4.8 + + Swaps polygon \a other with this polygon. This operation is very + fast and never fails. +*/ + +/*! Returns the polygon as a QVariant */ QPolygon::operator QVariant() const diff --git a/src/gui/painting/qpolygon.h b/src/gui/painting/qpolygon.h index 7a49e29..5baffc8 100644 --- a/src/gui/painting/qpolygon.h +++ b/src/gui/painting/qpolygon.h @@ -67,6 +67,8 @@ public: inline QPolygon(const QVector<QPoint> &v) : QVector<QPoint>(v) {} QPolygon(const QRect &r, bool closed=false); QPolygon(int nPoints, const int *points); + inline void swap(QPolygon &other) { QVector<QPoint>::swap(other); } // prevent QVector<QPoint><->QPolygon swaps + operator QVariant() const; void translate(int dx, int dy); @@ -139,6 +141,7 @@ public: inline QPolygonF(const QVector<QPointF> &v) : QVector<QPointF>(v) {} QPolygonF(const QRectF &r); QPolygonF(const QPolygon &a); + inline void swap(QPolygonF &other) { QVector<QPointF>::swap(other); } // prevent QVector<QPointF><->QPolygonF swaps inline void translate(qreal dx, qreal dy); void translate(const QPointF &offset); diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp index 4fded1f..9d89b10 100644 --- a/src/gui/painting/qrasterizer.cpp +++ b/src/gui/painting/qrasterizer.cpp @@ -62,8 +62,8 @@ typedef int Q16Dot16; #define SPAN_BUFFER_SIZE 256 -#define COORD_ROUNDING 1 // 0: round up, 1: round down -#define COORD_OFFSET 32 // 26.6, 32 is half a pixel +#define COORD_ROUNDING 0 // 0: round up, 1: round down +#define COORD_OFFSET 0 // 26.6, 32 is half a pixel static inline QT_FT_Vector PointToVector(const QPointF &p) { diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index 3412f9b..cd997f4 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -391,6 +391,14 @@ void QRegion::exec(const QByteArray &buffer, int ver, QDataStream::ByteOrder byt */ /*! + \fn void QRegion::swap(QRegion &other) + \since 4.8 + + Swaps region \a other with this region. This operation is very + fast and never fails. +*/ + +/*! \relates QRegion Writes the region \a r to the stream \a s and returns a reference @@ -1620,7 +1628,7 @@ QT_END_INCLUDE_NAMESPACE QT_BEGIN_INCLUDE_NAMESPACE # include "qregion_win.cpp" QT_END_INCLUDE_NAMESPACE -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_QPA) static QRegionPrivate qrp; QRegion::QRegionData QRegion::shared_empty = {Q_BASIC_ATOMIC_INITIALIZER(1), &qrp}; #endif @@ -4231,7 +4239,7 @@ QRect QRegion::boundingRect() const Returns true if \a rect is guaranteed to be fully contained in \a region. A false return value does not guarantee the opposite. */ -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) Q_GUI_EXPORT #endif bool qt_region_strictContains(const QRegion ®ion, const QRect &rect) diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h index acb20c1..50052b3 100644 --- a/src/gui/painting/qregion.h +++ b/src/gui/painting/qregion.h @@ -59,7 +59,7 @@ QT_MODULE(Gui) template <class T> class QVector; class QVariant; -#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) struct QRegionPrivate; #endif @@ -81,7 +81,11 @@ public: QRegion(const QBitmap &bitmap); ~QRegion(); QRegion &operator=(const QRegion &); - +#ifdef Q_COMPILER_RVALUE_REFS + inline QRegion &operator=(QRegion &&other) + { qSwap(d, other.d); return *this; } +#endif + inline void swap(QRegion &other) { qSwap(d, other.d); } #ifdef QT3_SUPPORT inline QT3_SUPPORT bool isNull() const { return isEmpty(); } #endif @@ -163,7 +167,7 @@ public: #endif HIMutableShapeRef toHIMutableShape() const; static QRegion fromHIShapeRef(HIShapeRef shape); -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_QPA) inline void *handle() const { return d->qt_rgn; } #endif #endif @@ -203,7 +207,7 @@ private: #elif defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) mutable RgnHandle unused; // Here for binary compatibility reasons. ### Qt 5 remove. #endif -#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) QRegionPrivate *qt_rgn; #endif }; diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index b609f7b..78c1019 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -65,8 +65,60 @@ static inline int qt_next_power_of_two(int v) return v; } +int QTextureGlyphCache::calculateSubPixelPositionCount(glyph_t glyph) const +{ + // Test 12 different subpixel positions since it factors into 3*4 so it gives + // the coverage we need. + + QList<QImage> images; + for (int i=0; i<12; ++i) { + QImage img = textureMapForGlyph(glyph, QFixed::fromReal(i / 12.0)); + + if (images.isEmpty()) { + QPainterPath path; + QFixedPoint point; + m_current_fontengine->addGlyphsToPath(&glyph, &point, 1, &path, QTextItem::RenderFlags()); + + // Glyph is space, return 0 to indicate that we need to keep trying + if (path.isEmpty()) + break; + + images.append(img); + } else { + bool found = false; + for (int j=0; j<images.size(); ++j) { + if (images.at(j) == img) { + found = true; + break; + } + } + if (!found) + images.append(img); + } + } + + return images.size(); +} + +QFixed QTextureGlyphCache::subPixelPositionForX(QFixed x) const +{ + if (m_subPixelPositionCount == 0) + return QFixed(); + + QFixed subPixelPosition; + if (x != 0) { + subPixelPosition = x - x.floor(); + QFixed fraction = (subPixelPosition / QFixed::fromReal(1.0 / m_subPixelPositionCount)).floor(); + + // Compensate for precision loss in fixed point to make sure we are always drawing at a subpixel position over + // the lower boundary for the selected rasterization by adding 1/64. + subPixelPosition = fraction / QFixed(m_subPixelPositionCount) + QFixed::fromReal(0.015625); + } + return subPixelPosition; +} + void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs, - const QFixedPoint *) + const QFixedPoint *positions) { #ifdef CACHE_DEBUG printf("Populating with %d glyphs\n", numGlyphs); @@ -77,17 +129,42 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const const int margin = glyphMargin(); const int paddingDoubled = glyphPadding() * 2; - QHash<glyph_t, Coord> listItemCoordinates; + bool supportsSubPixelPositions = fontEngine->supportsSubPixelPositions(); + if (m_subPixelPositionCount == 0) { + if (!supportsSubPixelPositions) { + m_subPixelPositionCount = 1; + } else { + int i = 0; + while (m_subPixelPositionCount == 0 && i < numGlyphs) + m_subPixelPositionCount = calculateSubPixelPositionCount(glyphs[i++]); + } + } + + QHash<GlyphAndSubPixelPosition, Coord> listItemCoordinates; int rowHeight = 0; + QFontEngine::GlyphFormat format; + switch (m_type) { + case Raster_A8: format = QFontEngine::Format_A8; break; + case Raster_RGBMask: format = QFontEngine::Format_A32; break; + default: format = QFontEngine::Format_Mono; break; + } + // check each glyph for its metrics and get the required rowHeight. for (int i=0; i < numGlyphs; ++i) { const glyph_t glyph = glyphs[i]; - if (coords.contains(glyph)) + + QFixed subPixelPosition; + if (supportsSubPixelPositions) { + QFixed x = positions != 0 ? positions[i].x : QFixed(); + subPixelPosition = subPixelPositionForX(x); + } + + if (coords.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition))) continue; - if (listItemCoordinates.contains(glyph)) + if (listItemCoordinates.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition))) continue; - glyph_metrics_t metrics = fontEngine->boundingBox(glyph, m_transform); + glyph_metrics_t metrics = fontEngine->alphaMapBoundingBox(glyph, m_transform, format); #ifdef CACHE_DEBUG printf("(%4x): w=%.2f, h=%.2f, xoff=%.2f, yoff=%.2f, x=%.2f, y=%.2f\n", @@ -115,30 +192,35 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const metrics.x.round().truncate(), -metrics.y.truncate() }; // baseline for horizontal scripts - listItemCoordinates.insert(glyph, c); + listItemCoordinates.insert(GlyphAndSubPixelPosition(glyph, subPixelPosition), c); rowHeight = qMax(rowHeight, glyph_height); } if (listItemCoordinates.isEmpty()) return; rowHeight += margin * 2 + paddingDoubled; - if (isNull()) - createCache(QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH, qt_next_power_of_two(rowHeight)); + + if (m_w == 0) { + if (fontEngine->maxCharWidth() <= QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH) + m_w = QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH; + else + m_w = qt_next_power_of_two(fontEngine->maxCharWidth()); + } // now actually use the coords and paint the wanted glyps into cache. - QHash<glyph_t, Coord>::iterator iter = listItemCoordinates.begin(); + QHash<GlyphAndSubPixelPosition, Coord>::iterator iter = listItemCoordinates.begin(); + int requiredWidth = m_w; while (iter != listItemCoordinates.end()) { Coord c = iter.value(); m_currentRowHeight = qMax(m_currentRowHeight, c.h + margin * 2); - if (m_cx + c.w > m_w) { - int new_width = m_w*2; + if (m_cx + c.w > requiredWidth) { + int new_width = requiredWidth*2; while (new_width < m_cx + c.w) new_width *= 2; if (new_width <= maxTextureWidth()) { - resizeTextureData(new_width, m_h); - m_w = new_width; + requiredWidth = new_width; } else { // no room on the current line, start new glyph strip m_cx = 0; @@ -146,29 +228,56 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const m_currentRowHeight = 0; // New row } } - if (m_cy + c.h > m_h) { - int new_height = m_h*2; - while (new_height < m_cy + c.h) - new_height *= 2; - // if no room in the current texture - realloc a larger texture - resizeTextureData(m_w, new_height); - m_h = new_height; - } c.x = m_cx; c.y = m_cy; - fillTexture(c, iter.key()); coords.insert(iter.key(), c); + m_pendingGlyphs.insert(iter.key(), c); m_cx += c.w + paddingDoubled; ++iter; } +} +void QTextureGlyphCache::fillInPendingGlyphs() +{ + if (m_pendingGlyphs.isEmpty()) + return; + + int requiredHeight = m_h; + int requiredWidth = m_w; // Use a minimum size to avoid a lot of initial reallocations + { + QHash<GlyphAndSubPixelPosition, Coord>::iterator iter = m_pendingGlyphs.begin(); + while (iter != m_pendingGlyphs.end()) { + Coord c = iter.value(); + requiredHeight = qMax(requiredHeight, c.y + c.h); + requiredWidth = qMax(requiredWidth, c.x + c.w); + ++iter; + } + } + + if (isNull() || requiredHeight > m_h || requiredWidth > m_w) { + if (isNull()) + createCache(qt_next_power_of_two(requiredWidth), qt_next_power_of_two(requiredHeight)); + else + resizeCache(qt_next_power_of_two(requiredWidth), qt_next_power_of_two(requiredHeight)); + } + + { + QHash<GlyphAndSubPixelPosition, Coord>::iterator iter = m_pendingGlyphs.begin(); + while (iter != m_pendingGlyphs.end()) { + GlyphAndSubPixelPosition key = iter.key(); + fillTexture(iter.value(), key.glyph, key.subPixelPosition); + + ++iter; + } + } + m_pendingGlyphs.clear(); } -QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g) const +QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g, QFixed subPixelPosition) const { #if defined(Q_WS_X11) if (m_transform.type() > QTransform::TxTranslate) { @@ -201,7 +310,7 @@ QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g) const } else #endif if (m_type == QFontEngineGlyphCache::Raster_RGBMask) - return m_current_fontengine->alphaRGBMapForGlyph(g, glyphMargin(), m_transform); + return m_current_fontengine->alphaRGBMapForGlyph(g, subPixelPosition, glyphMargin(), m_transform); else return m_current_fontengine->alphaMapForGlyph(g, m_transform); @@ -247,9 +356,9 @@ int QImageTextureGlyphCache::glyphMargin() const #endif } -void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g) +void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subPixelPosition) { - QImage mask = textureMapForGlyph(g); + QImage mask = textureMapForGlyph(g, subPixelPosition); #ifdef CACHE_DEBUG printf("fillTexture of %dx%d at %d,%d in the cache of %dx%d\n", c.w, c.h, c.x, c.y, m_image.width(), m_image.height()); diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h index e6d2b22..82aaf0d 100644 --- a/src/gui/painting/qtextureglyphcache_p.h +++ b/src/gui/painting/qtextureglyphcache_p.h @@ -81,11 +81,24 @@ class Q_GUI_EXPORT QTextureGlyphCache : public QFontEngineGlyphCache public: QTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix) : QFontEngineGlyphCache(matrix, type), m_current_fontengine(0), - m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0) + m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0), m_subPixelPositionCount(0) { } virtual ~QTextureGlyphCache() { } + struct GlyphAndSubPixelPosition + { + GlyphAndSubPixelPosition(glyph_t g, QFixed spp) : glyph(g), subPixelPosition(spp) {} + + bool operator==(const GlyphAndSubPixelPosition &other) const + { + return glyph == other.glyph && subPixelPosition == other.subPixelPosition; + } + + glyph_t glyph; + QFixed subPixelPosition; + }; + struct Coord { int x; int y; @@ -98,13 +111,14 @@ public: void populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions); + void fillInPendingGlyphs(); virtual void createTextureData(int width, int height) = 0; virtual void resizeTextureData(int width, int height) = 0; virtual int glyphMargin() const { return 0; } virtual int glyphPadding() const { return 0; } - virtual void fillTexture(const Coord &coord, glyph_t glyph) = 0; + virtual void fillTexture(const Coord &coord, glyph_t glyph, QFixed subPixelPosition) = 0; inline void createCache(int width, int height) { m_w = width; @@ -112,24 +126,42 @@ public: createTextureData(width, height); } - inline bool isNull() const { return m_w <= 0 || m_h <= 0; } + inline void resizeCache(int width, int height) + { + resizeTextureData(width, height); + m_w = width; + m_h = height; + } - QHash<glyph_t, Coord> coords; + inline bool isNull() const { return m_h == 0; } - QImage textureMapForGlyph(glyph_t g) const; + QHash<GlyphAndSubPixelPosition, Coord> coords; virtual int maxTextureWidth() const { return QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH; } virtual int maxTextureHeight() const { return 32768; } + QImage textureMapForGlyph(glyph_t g, QFixed subPixelPosition) const; + + QFixed subPixelPositionForX(QFixed x) const; + protected: + int calculateSubPixelPositionCount(glyph_t) const; + QFontEngine *m_current_fontengine; + QHash<GlyphAndSubPixelPosition, Coord> m_pendingGlyphs; int m_w; // image width int m_h; // image height int m_cx; // current x int m_cy; // current y int m_currentRowHeight; // Height of last row + int m_subPixelPositionCount; // Number of positions within a single pixel for this cache }; +inline uint qHash(const QTextureGlyphCache::GlyphAndSubPixelPosition &g) +{ + return (g.glyph << 8) | (g.subPixelPosition * 10).round().toInt(); +} + class Q_GUI_EXPORT QImageTextureGlyphCache : public QTextureGlyphCache { @@ -139,7 +171,7 @@ public: virtual int glyphMargin() const; virtual void createTextureData(int width, int height); virtual void resizeTextureData(int width, int height); - virtual void fillTexture(const Coord &c, glyph_t glyph); + virtual void fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition); inline const QImage &image() const { return m_image; } diff --git a/src/gui/painting/qunifiedtoolbarsurface_mac.cpp b/src/gui/painting/qunifiedtoolbarsurface_mac.cpp new file mode 100644 index 0000000..3590993 --- /dev/null +++ b/src/gui/painting/qunifiedtoolbarsurface_mac.cpp @@ -0,0 +1,252 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qunifiedtoolbarsurface_mac_p.h" +#include <private/qt_cocoa_helpers_mac_p.h> +#include <private/qbackingstore_p.h> +#include <private/qmainwindowlayout_p.h> + +#include <QDebug> + +#ifdef QT_MAC_USE_COCOA + +QT_BEGIN_NAMESPACE + +QUnifiedToolbarSurface::QUnifiedToolbarSurface(QWidget *widget) + : QRasterWindowSurface(widget, false), d_ptr(new QUnifiedToolbarSurfacePrivate) +{ + d_ptr->image = 0; + d_ptr->inSetGeometry = false; + setStaticContentsSupport(true); + + setGeometry(QRect(QPoint(0, 0), QSize(widget->width(), 100))); // FIXME: Fix height. +} + +QUnifiedToolbarSurface::~QUnifiedToolbarSurface() +{ + if (d_ptr->image) + delete d_ptr->image; +} + +QPaintDevice *QUnifiedToolbarSurface::paintDevice() +{ + return &d_ptr->image->image; +} + +void QUnifiedToolbarSurface::recursiveRedirect(QObject *object, const QPoint &offset) +{ + if (object != 0) { + if (object->isWidgetType()) { + QWidget *widget = qobject_cast<QWidget *>(object); + widget->d_func()->unifiedSurface = this; + widget->d_func()->isInUnifiedToolbar = true; + widget->d_func()->toolbar_offset = offset; + } + + for (int i = 0; i < object->children().size(); ++i) { + recursiveRedirect(object->children().at(i), offset); + } + } +} + +void QUnifiedToolbarSurface::insertToolbar(QWidget *toolbar, const QPoint &offset) +{ + setGeometry(QRect(QPoint(0, 0), QSize(offset.x() + toolbar->width(), 100))); // FIXME + recursiveRedirect(toolbar, offset); +} + +void QUnifiedToolbarSurface::setGeometry(const QRect &rect) +{ + QWindowSurface::setGeometry(rect); + Q_D(QUnifiedToolbarSurface); + d->inSetGeometry = true; + if (d->image == 0 || d->image->width() < rect.width() || d->image->height() < rect.height()) + prepareBuffer(QImage::Format_ARGB32_Premultiplied, window()); + d->inSetGeometry = false; + + // FIXME: set unified toolbar height. +} + +void QUnifiedToolbarSurface::beginPaint(const QRegion &rgn) +{ + QPainter p(&d_ptr->image->image); + p.setCompositionMode(QPainter::CompositionMode_Source); + const QVector<QRect> rects = rgn.rects(); + const QColor blank = Qt::transparent; + for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) { + p.fillRect(*it, blank); + } +} + +void QUnifiedToolbarSurface::updateToolbarOffset(QWidget *widget) +{ + QMainWindowLayout *mlayout = qobject_cast<QMainWindowLayout*> (widget->window()->layout()); + mlayout->updateUnifiedToolbarOffset(); +} + +void QUnifiedToolbarSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) +{ + Q_D(QUnifiedToolbarSurface); + + QRegion flushingRegion(widget->rect()); + + if (!d->image || rgn.rectCount() == 0) { + return; + } + + Q_UNUSED(offset); + + // Get a context for the widget. + CGContextRef context; + if (!(widget->d_func()->hasOwnContext)) { + widget->d_func()->ut_rg = rgn; + widget->d_func()->ut_pt = offset; + qt_mac_display(widget); + return; + } else { + // We render the content of the toolbar in the surface. + updateToolbarOffset(widget); + QRect beginPaintRect(widget->d_func()->toolbar_offset.x(), widget->d_func()->toolbar_offset.y(), widget->geometry().width(), widget->geometry().height()); + QRegion beginPaintRegion(beginPaintRect); + + context = widget->d_func()->cgContext; + beginPaint(beginPaintRegion); + widget->render(widget->d_func()->unifiedSurface->paintDevice(), widget->d_func()->toolbar_offset, QRegion(), QWidget::DrawChildren); + } + + CGContextSaveGState(context); + + int areaX = widget->d_func()->toolbar_offset.x(); + int areaY = widget->d_func()->toolbar_offset.y(); + int areaWidth = widget->geometry().width(); + int areaHeight = widget->geometry().height(); + const CGRect area = CGRectMake(areaX, areaY, areaWidth, areaHeight); + + // Clip to region. + const QVector<QRect> &rects = flushingRegion.rects(); + for (int i = 0; i < rects.size(); ++i) { + const QRect &rect = rects.at(i); + CGContextAddRect(context, CGRectMake(rect.x(), rect.y(), rect.width(), rect.height())); + } + CGContextAddRect(context, area); + CGContextClip(context); + + + CGImageRef image = CGBitmapContextCreateImage(d->image->cg); + CGImageRef subImage = CGImageCreateWithImageInRect(image, area); + + const CGRect drawingArea = CGRectMake(0, 0, areaWidth, areaHeight); + qt_mac_drawCGImage(context, &drawingArea, subImage); + + CGImageRelease(subImage); + CGImageRelease(image); + + CGContextFlush(context); + + // Restore context. + CGContextRestoreGState(context); + widget->d_func()->hasOwnContext = false; +} + +void QUnifiedToolbarSurface::prepareBuffer(QImage::Format format, QWidget *widget) +{ + Q_D(QUnifiedToolbarSurface); + + int width = geometry().width(); + int height = geometry().height(); + if (d->image) { + width = qMax(d->image->width(), width); + height = qMax(d->image->height(), height); + } + + if (width == 0 || height == 0) { + delete d->image; + d->image = 0; + return; + } + + QNativeImage *oldImage = d->image; + + d->image = new QNativeImage(width, height, format, false, widget); + + if (oldImage && d->inSetGeometry && hasStaticContents()) { + // Make sure we use the const version of bits() (no detach). + const uchar *src = const_cast<const QImage &>(oldImage->image).bits(); + uchar *dst = d->image->image.bits(); + + const int srcBytesPerLine = oldImage->image.bytesPerLine(); + const int dstBytesPerLine = d->image->image.bytesPerLine(); + const int bytesPerPixel = oldImage->image.depth() >> 3; + + QRegion staticRegion(staticContents()); + // Make sure we're inside the boundaries of the old image. + staticRegion &= QRect(0, 0, oldImage->image.width(), oldImage->image.height()); + const QVector<QRect> &rects = staticRegion.rects(); + const QRect *srcRect = rects.constData(); + + // Copy the static content of the old image into the new one. + int numRectsLeft = rects.size(); + do { + const int bytesOffset = srcRect->x() * bytesPerPixel; + const int dy = srcRect->y(); + + // Adjust src and dst to point to the right offset. + const uchar *s = src + dy * srcBytesPerLine + bytesOffset; + uchar *d = dst + dy * dstBytesPerLine + bytesOffset; + const int numBytes = srcRect->width() * bytesPerPixel; + + int numScanLinesLeft = srcRect->height(); + do { + ::memcpy(d, s, numBytes); + d += dstBytesPerLine; + s += srcBytesPerLine; + } while (--numScanLinesLeft); + + ++srcRect; + } while (--numRectsLeft); + } + + delete oldImage; +} + +QT_END_NAMESPACE + +#endif // QT_MAC_USE_COCOA diff --git a/src/gui/painting/qunifiedtoolbarsurface_mac_p.h b/src/gui/painting/qunifiedtoolbarsurface_mac_p.h new file mode 100644 index 0000000..3bc0404 --- /dev/null +++ b/src/gui/painting/qunifiedtoolbarsurface_mac_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QUNIFIEDTOOLBARSURFACE_MAC_P_H +#define QUNIFIEDTOOLBARSURFACE_MAC_P_H + +// +// 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. +// + +#include <private/qwindowsurface_raster_p.h> +#include <QWidget> +#include <private/qwidget_p.h> +#include <private/qnativeimage_p.h> + +#ifdef QT_MAC_USE_COCOA + +QT_BEGIN_NAMESPACE + +class QNativeImage; + + +class QUnifiedToolbarSurfacePrivate +{ +public: + QNativeImage *image; + uint inSetGeometry : 1; +}; + +class Q_GUI_EXPORT QUnifiedToolbarSurface : public QRasterWindowSurface +{ +public: + QUnifiedToolbarSurface(QWidget *widget); + ~QUnifiedToolbarSurface(); + + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void setGeometry(const QRect &rect); + void beginPaint(const QRegion &rgn); + void insertToolbar(QWidget *toolbar, const QPoint &offset); + +private: + QPaintDevice *paintDevice(); + void updateToolbarOffset(QWidget *widget); + void prepareBuffer(QImage::Format format, QWidget *widget); + void recursiveRedirect(QObject *widget, const QPoint &offset); + + Q_DECLARE_PRIVATE(QUnifiedToolbarSurface) + QScopedPointer<QUnifiedToolbarSurfacePrivate> d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QT_MAC_USE_COCOA + +#endif // QUNIFIEDTOOLBARSURFACE_MAC_P_H diff --git a/src/gui/painting/qwindowsurface.cpp b/src/gui/painting/qwindowsurface.cpp index 02a8b80..e9eb9c5 100644 --- a/src/gui/painting/qwindowsurface.cpp +++ b/src/gui/painting/qwindowsurface.cpp @@ -58,7 +58,11 @@ public: } QWidget *window; +#if !defined(Q_WS_QPA) QRect geometry; +#else + QSize size; +#endif //Q_WS_QPA QRegion staticContents; QList<QImage*> bufferImages; uint staticContentsSupport : 1; @@ -114,11 +118,11 @@ public: /*! Constructs an empty surface for the given top-level \a window. */ -QWindowSurface::QWindowSurface(QWidget *window) +QWindowSurface::QWindowSurface(QWidget *window, bool setDefaultSurface) : d_ptr(new QWindowSurfacePrivate(window)) { if (!QApplicationPrivate::runtime_graphics_system) { - if(window) + if(setDefaultSurface && window) window->setWindowSurface(this); } } @@ -153,6 +157,7 @@ void QWindowSurface::endPaint(const QRegion &) d_ptr->bufferImages.clear(); } +#if !defined(Q_WS_QPA) /*! Sets the currently allocated area to be the given \a rect. @@ -173,6 +178,17 @@ QRect QWindowSurface::geometry() const { return d_ptr->geometry; } +#else +void QWindowSurface::resize(const QSize &size) +{ + d_ptr->size = size; +} + +QSize QWindowSurface::size() const +{ + return d_ptr->size; +} +#endif //Q_WS_QPA /*! Scrolls the given \a area \a dx pixels to the right and \a dy @@ -329,7 +345,13 @@ void QWindowSurface::setPartialUpdateSupport(bool enable) d_ptr->partialUpdateSupport = enable; } -void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset) +#ifdef Q_WS_QPA +#define Q_EXPORT_SCROLLRECT Q_GUI_EXPORT +#else +#define Q_EXPORT_SCROLLRECT +#endif + +void Q_EXPORT_SCROLLRECT qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset) { // make sure we don't detach uchar *mem = const_cast<uchar*>(const_cast<const QImage &>(img).bits()); diff --git a/src/gui/painting/qwindowsurface_p.h b/src/gui/painting/qwindowsurface_p.h index 6171ae8..82100c3 100644 --- a/src/gui/painting/qwindowsurface_p.h +++ b/src/gui/painting/qwindowsurface_p.h @@ -63,11 +63,12 @@ class QRect; class QPoint; class QImage; class QWindowSurfacePrivate; +class QPlatformWindow; class Q_GUI_EXPORT QWindowSurface { public: - QWindowSurface(QWidget *window); + QWindowSurface(QWidget *window, bool setDefaultSurface = true); virtual ~QWindowSurface(); QWidget *window() const; @@ -79,8 +80,14 @@ public: // can be larger than just the offset from the top-level widget as there may also be window // decorations which are painted into the window surface. virtual void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) = 0; +#if !defined(Q_WS_QPA) virtual void setGeometry(const QRect &rect); QRect geometry() const; +#else + virtual void resize(const QSize &size); + QSize size() const; + inline QRect geometry() const { return QRect(QPoint(), size()); } //### cleanup before Qt 5 +#endif virtual bool scroll(const QRegion &area, int dx, int dy); diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp index eee6bef..217723f 100644 --- a/src/gui/painting/qwindowsurface_raster.cpp +++ b/src/gui/painting/qwindowsurface_raster.cpp @@ -64,6 +64,9 @@ #ifdef Q_WS_MAC #include <private/qt_cocoa_helpers_mac_p.h> +#include <QMainWindow> +#include <private/qmainwindowlayout_p.h> +#include <QToolBar> #endif QT_BEGIN_NAMESPACE @@ -82,8 +85,8 @@ public: uint inSetGeometry : 1; }; -QRasterWindowSurface::QRasterWindowSurface(QWidget *window) - : QWindowSurface(window), d_ptr(new QRasterWindowSurfacePrivate) +QRasterWindowSurface::QRasterWindowSurface(QWidget *window, bool setDefaultSurface) + : QWindowSurface(window, setDefaultSurface), d_ptr(new QRasterWindowSurfacePrivate) { #ifdef Q_WS_X11 d_ptr->gc = XCreateGC(X11->display, window->handle(), 0, 0); @@ -248,9 +251,24 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi #ifdef Q_WS_MAC -// qDebug() << "Flushing" << widget << rgn << offset; - -// d->image->image.save("flush.png"); +#ifdef QT_MAC_USE_COCOA + // Unified toolbar hack. + QMainWindow* mWindow = qobject_cast<QMainWindow*>(widget->window()); + if (mWindow) { + QMainWindowLayout *mLayout = qobject_cast<QMainWindowLayout*>(mWindow->layout()); + QList<QToolBar *> toolbarList = mLayout->qtoolbarsInUnifiedToolbarList; + + for (int i = 0; i < toolbarList.size(); ++i) { + QToolBar* toolbar = toolbarList.at(i); + if (mLayout->toolBarArea(toolbar) == Qt::TopToolBarArea) { + QWidget* tbWidget = (QWidget*) toolbar; + if (tbWidget->d_func()->unifiedSurface) { + tbWidget->d_func()->unifiedSurface->flush(tbWidget, rgn, offset); + } + } + } + } +#endif // QT_MAC_USE_COCOA Q_UNUSED(offset); // Get a context for the widget. @@ -282,20 +300,19 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi CGImageRef subImage = CGImageCreateWithImageInRect(image, area); qt_mac_drawCGImage(context, &area, subImage); + CGImageRelease(subImage); CGImageRelease(image); -// CGSize size = { d->image->image.width(), d->image->image.height() }; -// CGLayerRef layer = CGLayerCreateWithContext(d->image->cg, size, 0); -// CGPoint pt = { 0, 0 }; -// CGContextDrawLayerAtPoint(context, pt, layer); -// CGLayerRelease(layer); - - // Restore context. - CGContextRestoreGState(context); #ifndef QT_MAC_USE_COCOA QDEndCGContext(port, &context); +#else + CGContextFlush(context); #endif + + // Restore context. + CGContextRestoreGState(context); + #endif // Q_WS_MAC #ifdef Q_OS_SYMBIAN @@ -323,6 +340,25 @@ void QRasterWindowSurface::setGeometry(const QRect &rect) prepareBuffer(QNativeImage::systemFormat(), window()); } d->inSetGeometry = false; + +#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA) + QMainWindow* mWindow = qobject_cast<QMainWindow*>(window()); + if (mWindow) { + QMainWindowLayout *mLayout = qobject_cast<QMainWindowLayout*>(mWindow->layout()); + QList<QToolBar *> toolbarList = mLayout->qtoolbarsInUnifiedToolbarList; + + for (int i = 0; i < toolbarList.size(); ++i) { + QToolBar* toolbar = toolbarList.at(i); + if (mLayout->toolBarArea(toolbar) == Qt::TopToolBarArea) { + QWidget* tbWidget = (QWidget*) toolbar; + if (tbWidget->d_func()->unifiedSurface) { + tbWidget->d_func()->unifiedSurface->setGeometry(rect); + } + } + } + } +#endif // Q_WS_MAC && QT_MAC_USE_COCOA + } // from qwindowsurface.cpp diff --git a/src/gui/painting/qwindowsurface_raster_p.h b/src/gui/painting/qwindowsurface_raster_p.h index 2b932a9..a7c3b9f 100644 --- a/src/gui/painting/qwindowsurface_raster_p.h +++ b/src/gui/painting/qwindowsurface_raster_p.h @@ -97,7 +97,7 @@ class QNativeImage; class Q_GUI_EXPORT QRasterWindowSurface : public QWindowSurface { public: - QRasterWindowSurface(QWidget *widget); + QRasterWindowSurface(QWidget *widget, bool setDefaultSurface = true); ~QRasterWindowSurface(); QPaintDevice *paintDevice(); diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp index ea19fcd..eb9eff2 100644 --- a/src/gui/painting/qwindowsurface_s60.cpp +++ b/src/gui/painting/qwindowsurface_s60.cpp @@ -77,7 +77,8 @@ QS60WindowSurface::QS60WindowSurface(QWidget* widget) } // We create empty CFbsBitmap here -> it will be resized in setGeometry - CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new + CFbsBitmap *bitmap = new CFbsBitmap; // CBase derived object needs check on new + Q_CHECK_PTR(bitmap); qt_symbian_throwIfError( bitmap->Create( TSize(0, 0), mode ) ); QS60PixmapData *data = new QS60PixmapData(QPixmapData::PixmapType); diff --git a/src/gui/painting/qwindowsurface_x11.cpp b/src/gui/painting/qwindowsurface_x11.cpp index cadf264..d7f54ea 100644 --- a/src/gui/painting/qwindowsurface_x11.cpp +++ b/src/gui/painting/qwindowsurface_x11.cpp @@ -149,6 +149,8 @@ void QX11WindowSurface::setGeometry(const QRect &rect) return; #ifndef QT_NO_XRENDER if (d_ptr->translucentBackground) { + QPixmap::x11SetDefaultScreen(d_ptr->widget->x11Info().screen()); + QX11PixmapData *data = new QX11PixmapData(QPixmapData::PixmapType); data->xinfo = d_ptr->widget->x11Info(); data->resize(size.width(), size.height()); diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp index 306219d..e280a51 100644 --- a/src/gui/styles/qcleanlooksstyle.cpp +++ b/src/gui/styles/qcleanlooksstyle.cpp @@ -3763,6 +3763,7 @@ int QCleanlooksStyle::pixelMetric(PixelMetric metric, const QStyleOption *option break; case PM_MenuBarItemSpacing: ret = 6; + break; case PM_MenuBarHMargin: ret = 0; break; diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index fb31ae4..3a05f40 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -1642,7 +1642,7 @@ bool QMacStylePrivate::eventFilter(QObject *o, QEvent *e) case QEvent::FocusOut: case QEvent::Show: case QEvent::WindowActivate: { - QList<QPushButton *> list = qFindChildren<QPushButton *>(btn->window()); + QList<QPushButton *> list = btn->window()->findChildren<QPushButton *>(); for (int i = 0; i < list.size(); ++i) { QPushButton *pBtn = list.at(i); if ((e->type() == QEvent::FocusOut @@ -5540,6 +5540,57 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, // hack to work around horrible sizeHint() code in QAbstractSpinBox sz.setHeight(sz.height() - 3); break; + case QStyle::CT_TabWidget: + // the size between the pane and the "contentsRect" (+4,+4) + // (the "contentsRect" is on the inside of the pane) + sz = QWindowsStyle::sizeFromContents(ct, opt, csz, widget); + /** + This is supposed to show the relationship between the tabBar and + the stack widget of a QTabWidget. + Unfortunately ascii is not a good way of representing graphics..... + PS: The '=' line is the painted frame. + + top ---+ + | + | + | + | vvv just outside the painted frame is the "pane" + - -|- - - - - - - - - - <-+ + TAB BAR +=====^============ | +2 pixels + - - -|- - -|- - - - - - - <-+ + | | ^ ^^^ just inside the painted frame is the "contentsRect" + | | | + | overlap | + | | | + bottom ------+ <-+ +14 pixels + | + v + ------------------------------ <- top of stack widget + + + To summarize: + * 2 is the distance between the pane and the contentsRect + * The 14 and the 1's are the distance from the contentsRect to the stack widget. + (same value as used in SE_TabWidgetTabContents) + * overlap is how much the pane should overlap the tab bar + */ + // then add the size between the stackwidget and the "contentsRect" + + if (const QStyleOptionTabWidgetFrame *twf + = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { + QSize extra(0,0); + const int overlap = pixelMetric(PM_TabBarBaseOverlap, opt, widget); + const int gapBetweenTabbarAndStackWidget = 2 + 14 - overlap; + + if (getTabDirection(twf->shape) == kThemeTabNorth || getTabDirection(twf->shape) == kThemeTabSouth) { + extra = QSize(2, gapBetweenTabbarAndStackWidget + 1); + } else { + extra = QSize(gapBetweenTabbarAndStackWidget + 1, 2); + } + sz+= extra; + } + + break; case QStyle::CT_TabBarTab: if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) { const QAquaWidgetSize AquaSize = d->aquaSizeConstrain(opt, widget); diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp index 20d9bd9..8772294 100644 --- a/src/gui/styles/qplastiquestyle.cpp +++ b/src/gui/styles/qplastiquestyle.cpp @@ -1054,7 +1054,7 @@ void QPlastiqueStylePrivate::drawPartialFrame(QPainter *painter, const QStyleOpt bool reverse = option->direction == Qt::RightToLeft; QStyleOptionFrame frameOpt; #ifndef QT_NO_LINEEDIT - if (QLineEdit *lineedit = qFindChild<QLineEdit *>(widget)) + if (QLineEdit *lineedit = widget->findChild<QLineEdit *>()) frameOpt.initFrom(lineedit); #else Q_UNUSED(widget) @@ -1362,11 +1362,8 @@ void QPlastiqueStyle::drawPrimitive(PrimitiveElement element, const QStyleOption if (const QStyleOptionFrame *lineEdit = qstyleoption_cast<const QStyleOptionFrame *>(option)) { // Panel of a line edit inside combo box or spin box is drawn in CC_ComboBox and CC_SpinBox if (widget) { -#ifndef QT_NO_COMBOBOX - if (qobject_cast<const QComboBox *>(widget->parentWidget())) - break; -#endif #ifndef QT_NO_SPINBOX + // Spinbox doesn't need a separate palette for the lineedit if (qobject_cast<const QAbstractSpinBox *>(widget->parentWidget())) break; #endif diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index f3fb2f5..6fb3689 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -1424,7 +1424,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, bool isScrollBarVisible = false; int scrollBarWidth = 0; - QList<QScrollBar *> scrollBars = qFindChildren<QScrollBar *>(widget); + QList<QScrollBar *> scrollBars = widget->findChildren<QScrollBar *>(); for (int i = 0; i < scrollBars.size(); ++i) { QScrollBar *scrollBar = scrollBars.at(i); if (scrollBar && scrollBar->orientation() == Qt::Vertical) { diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 92e2c81..4be439d 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -2342,7 +2342,7 @@ static QWidget *embeddedWidget(QWidget *w) #ifndef QT_NO_SPINBOX if (QAbstractSpinBox *sb = qobject_cast<QAbstractSpinBox *>(w)) - return qFindChild<QLineEdit *>(sb); + return sb->findChild<QLineEdit *>(); #endif #ifndef QT_NO_SCROLLAREA @@ -2583,7 +2583,7 @@ void QStyleSheetStyle::unsetPalette(QWidget *w) } QVariant oldFont = w->property("_q_styleSheetWidgetFont"); if (oldFont.isValid()) { - w->setFont(qVariantValue<QFont>(oldFont)); + w->setFont(qvariant_cast<QFont>(oldFont)); } if (autoFillDisabledWidgets->contains(w)) { embeddedWidget(w)->setAutoFillBackground(true); @@ -2795,7 +2795,7 @@ void QStyleSheetStyle::polish(QPalette &pal) void QStyleSheetStyle::repolish(QWidget *w) { - QList<const QWidget *> children = qFindChildren<const QWidget *>(w, QString()); + QList<const QWidget *> children = w->findChildren<const QWidget *>(QString()); children.append(w); styleSheetCache->remove(w); updateWidgets(children); @@ -3048,6 +3048,13 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC titleRule.configurePalette(&pal, QPalette::WindowText, QPalette::Window); drawItemText(p, labelRect, alignment, pal, gb->state & State_Enabled, gb->text, QPalette::WindowText); + + if (gb->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*gb); + fropt.rect = labelRect; + drawPrimitive(PE_FrameFocusRect, &fropt, p, w); + } } return; @@ -5074,7 +5081,7 @@ QIcon QStyleSheetStyle::standardIconImplementation(StandardPixmap standardIcon, if (!s.isEmpty()) { QRenderRule rule = renderRule(w, opt); if (rule.hasStyleHint(s)) - return qVariantValue<QIcon>(rule.styleHint(s)); + return qvariant_cast<QIcon>(rule.styleHint(s)); } return baseStyle()->standardIcon(standardIcon, opt, w); } @@ -5092,7 +5099,7 @@ QPixmap QStyleSheetStyle::standardPixmap(StandardPixmap standardPixmap, const QS if (!s.isEmpty()) { QRenderRule rule = renderRule(w, opt); if (rule.hasStyleHint(s)) { - QIcon icon = qVariantValue<QIcon>(rule.styleHint(s)); + QIcon icon = qvariant_cast<QIcon>(rule.styleHint(s)); return icon.pixmap(16, 16); // ###: unhard-code this if someone complains } } @@ -5186,7 +5193,7 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi case SH_ComboBox_PopupFrameStyle: #ifndef QT_NO_COMBOBOX if (qobject_cast<const QComboBox *>(w)) { - QAbstractItemView *view = qFindChild<QAbstractItemView *>(w); + QAbstractItemView *view = w->findChild<QAbstractItemView *>(); if (view) { view->ensurePolished(); QRenderRule subRule = renderRule(view, PseudoElement_None); diff --git a/src/gui/styles/qwindowscestyle.cpp b/src/gui/styles/qwindowscestyle.cpp index b027005..bd7246a 100644 --- a/src/gui/styles/qwindowscestyle.cpp +++ b/src/gui/styles/qwindowscestyle.cpp @@ -2294,6 +2294,7 @@ int QWindowsCEStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QW break; case SH_EtchDisabledText: ret = false; + break; case SH_RequestSoftwareInputPanel: ret = RSIP_OnMouseClick; break; diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp index 720dd6d..d994b9b 100644 --- a/src/gui/styles/qwindowsstyle.cpp +++ b/src/gui/styles/qwindowsstyle.cpp @@ -175,7 +175,7 @@ bool QWindowsStyle::eventFilter(QObject *o, QEvent *e) widget = widget->window(); // Alt has been pressed - find all widgets that care - QList<QWidget *> l = qFindChildren<QWidget *>(widget); + QList<QWidget *> l = widget->findChildren<QWidget *>(); for (int pos=0 ; pos < l.size() ; ++pos) { QWidget *w = l.at(pos); if (w->isWindow() || !w->isVisible() || @@ -198,7 +198,7 @@ bool QWindowsStyle::eventFilter(QObject *o, QEvent *e) // Update state and repaint the menu bars. d->alt_down = false; #ifndef QT_NO_MENUBAR - QList<QMenuBar *> l = qFindChildren<QMenuBar *>(widget); + QList<QMenuBar *> l = widget->findChildren<QMenuBar *>(); for (int i = 0; i < l.size(); ++i) l.at(i)->update(); #endif @@ -1160,7 +1160,7 @@ int QWindowsStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWid if (!menuBar && qobject_cast<const QMenu *>(widget)) { QWidget *w = QApplication::activeWindow(); if (w && w != widget) - menuBar = qFindChild<QMenuBar *>(w); + menuBar = w->findChild<QMenuBar *>(); } // If we paint a menu bar draw underlines if is in the keyboardState if (menuBar) { diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp index 58542e5..d6d3f10 100644 --- a/src/gui/styles/qwindowsvistastyle.cpp +++ b/src/gui/styles/qwindowsvistastyle.cpp @@ -588,10 +588,6 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt if (QAbstractSpinBox *spinbox = qobject_cast<QAbstractSpinBox*>(widget->parentWidget())) resolve_mask = spinbox->palette().resolve(); #endif // QT_NO_SPINBOX -#ifndef QT_NO_COMBOBOX - if (QComboBox *combobox = qobject_cast<QComboBox*>(widget->parentWidget())) - resolve_mask = combobox->palette().resolve(); -#endif // QT_NO_COMBOBOX } if (resolve_mask & (1 << QPalette::Base)) { // Base color is set for this widget, so use it @@ -842,10 +838,10 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt const QDialogButtonBox *buttonBox = 0; if (qobject_cast<const QMessageBox *> (widget)) - buttonBox = qFindChild<const QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox")); + buttonBox = widget->findChild<const QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox")); #ifndef QT_NO_INPUTDIALOG else if (qobject_cast<const QInputDialog *> (widget)) - buttonBox = qFindChild<const QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox")); + buttonBox = widget->findChild<const QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox")); #endif // QT_NO_INPUTDIALOG if (buttonBox) { @@ -2396,14 +2392,14 @@ void QWindowsVistaStyle::polish(QWidget *widget) } } else if (qobject_cast<QMessageBox *> (widget)) { widget->setAttribute(Qt::WA_StyledBackground); - QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox")); + QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox")); if (buttonBox) buttonBox->setContentsMargins(0, 9, 0, 0); } #ifndef QT_NO_INPUTDIALOG else if (qobject_cast<QInputDialog *> (widget)) { widget->setAttribute(Qt::WA_StyledBackground); - QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox")); + QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox")); if (buttonBox) buttonBox->setContentsMargins(0, 9, 0, 0); } @@ -2435,14 +2431,14 @@ void QWindowsVistaStyle::unpolish(QWidget *widget) widget->setAttribute(Qt::WA_Hover, false); else if (qobject_cast<QMessageBox *> (widget)) { widget->setAttribute(Qt::WA_StyledBackground, false); - QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_msgbox_buttonbox")); + QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox")); if (buttonBox) buttonBox->setContentsMargins(0, 0, 0, 0); } #ifndef QT_NO_INPUTDIALOG else if (qobject_cast<QInputDialog *> (widget)) { widget->setAttribute(Qt::WA_StyledBackground, false); - QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox *>(widget,QLatin1String("qt_inputdlg_buttonbox")); + QDialogButtonBox *buttonBox = widget->findChild<QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox")); if (buttonBox) buttonBox->setContentsMargins(0, 0, 0, 0); } diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp index da29440..6ded280 100644 --- a/src/gui/styles/qwindowsxpstyle.cpp +++ b/src/gui/styles/qwindowsxpstyle.cpp @@ -4054,7 +4054,7 @@ void QWindowsXPStylePrivate::dumpNativeDIB(int w, int h) bufferPos += sprintf(bufferPos, "\n};\n\n"); printf(bufferDump); - delete bufferDump; + delete[] bufferDump; ++pCount; } } diff --git a/src/gui/styles/styles.pri b/src/gui/styles/styles.pri index b22a908..b6eeec9 100644 --- a/src/gui/styles/styles.pri +++ b/src/gui/styles/styles.pri @@ -35,7 +35,7 @@ contains( styles, all ) { styles = mac windows windowsxp windowsvista } -x11|embedded|!macx-*:styles -= mac +x11|embedded|qpa|!macx-*:styles -= mac x11{ QMAKE_CXXFLAGS += $$QT_CFLAGS_QGTKSTYLE diff --git a/src/gui/symbian/qsymbianevent.cpp b/src/gui/symbian/qsymbianevent.cpp index c341413..a7cfeef 100644 --- a/src/gui/symbian/qsymbianevent.cpp +++ b/src/gui/symbian/qsymbianevent.cpp @@ -40,6 +40,9 @@ ****************************************************************************/ #include "qsymbianevent.h" +#include <qdebug.h> + +#include <w32std.h> QT_BEGIN_NAMESPACE @@ -140,4 +143,34 @@ int QSymbianEvent::resourceChangeType() const return (m_type == ResourceChangeEvent) ? m_eventValue : 0; } +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QSymbianEvent *o) +{ + if (!o) { + dbg << "QSymbianEvent(0x0)"; + return dbg; + } + dbg.nospace() << "QSymbianEvent("; + switch (o->type()) { + case QSymbianEvent::InvalidEvent: + dbg << "InvalidEvent"; + break; + case QSymbianEvent::WindowServerEvent: + dbg << "WindowServerEvent, Type = " << o->windowServerEvent()->Type(); + break; + case QSymbianEvent::CommandEvent: + dbg << "CommandEvent, command = " << o->command(); + break; + case QSymbianEvent::ResourceChangeEvent: + dbg << "ResourceChangeEvent, resourceChangeType = " << o->resourceChangeType(); + break; + default: + dbg << "Unknown event type"; + break; + } + dbg << ")"; + return dbg.space(); +} +#endif + QT_END_NAMESPACE diff --git a/src/gui/symbian/qsymbianevent.h b/src/gui/symbian/qsymbianevent.h index 5cad654..4c9ae65 100644 --- a/src/gui/symbian/qsymbianevent.h +++ b/src/gui/symbian/qsymbianevent.h @@ -95,6 +95,10 @@ inline bool QSymbianEvent::isValid() const return m_type != InvalidEvent; } +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QSymbianEvent *o); +#endif + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index b3d2526..dafc8e7 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -68,6 +68,8 @@ static const QCssKnownValue properties[NumProperties - 1] = { { "-qt-background-role", QtBackgroundRole }, { "-qt-block-indent", QtBlockIndent }, { "-qt-list-indent", QtListIndent }, + { "-qt-list-number-prefix", QtListNumberPrefix }, + { "-qt-list-number-suffix", QtListNumberSuffix }, { "-qt-paragraph-type", QtParagraphType }, { "-qt-style-features", QtStyleFeatures }, { "-qt-table-type", QtTableType }, @@ -403,7 +405,7 @@ int ValueExtractor::lengthValue(const Declaration &decl) if (decl.d->values.count() < 1) return 0; LengthData data = lengthValue(decl.d->values.at(0)); - decl.d->parsed = qVariantFromValue<LengthData>(data); + decl.d->parsed = QVariant::fromValue<LengthData>(data); return lengthValueFromData(data,f); } @@ -435,7 +437,7 @@ void ValueExtractor::lengthValues(const Declaration &decl, int *m) QList<QVariant> v; for (i = 0; i < 4; i++) { - v += qVariantFromValue<LengthData>(datas[i]); + v += QVariant::fromValue<LengthData>(datas[i]); m[i] = lengthValueFromData(datas[i], f); } decl.d->parsed = v; @@ -541,7 +543,7 @@ QSize ValueExtractor::sizeValue(const Declaration &decl) else x[1] = x[0]; QList<QVariant> v; - v << qVariantFromValue<LengthData>(x[0]) << qVariantFromValue<LengthData>(x[1]); + v << QVariant::fromValue<LengthData>(x[0]) << qVariantFromValue<LengthData>(x[1]); decl.d->parsed = v; return QSize(lengthValueFromData(x[0], f), lengthValueFromData(x[1], f)); } @@ -916,7 +918,7 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord data.width = lengthValue(decl.d->values.at(i)); *width = lengthValueFromData(data.width, f); if (++i >= decl.d->values.count()) { - decl.d->parsed = qVariantFromValue<BorderData>(data); + decl.d->parsed = QVariant::fromValue<BorderData>(data); return; } } @@ -925,7 +927,7 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord if (data.style != BorderStyle_Unknown) { *style = data.style; if (++i >= decl.d->values.count()) { - decl.d->parsed = qVariantFromValue<BorderData>(data); + decl.d->parsed = QVariant::fromValue<BorderData>(data); return; } } else { @@ -935,7 +937,7 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord data.color = parseBrushValue(decl.d->values.at(i), pal); *color = brushFromData(data.color, pal); if (data.color.type != BrushData::DependsOnThePalette) - decl.d->parsed = qVariantFromValue<BorderData>(data); + decl.d->parsed = QVariant::fromValue<BorderData>(data); } static void parseShorthandBackgroundProperty(const QVector<Value> &values, BrushData *brush, QString *image, Repeat *repeat, Qt::Alignment *alignment, const QPalette &pal) @@ -1032,16 +1034,8 @@ bool ValueExtractor::extractBackground(QBrush *brush, QString *image, Repeat *re parseShorthandBackgroundProperty(decl.d->values, &brushData, image, repeat, alignment, pal); *brush = brushFromData(brushData, pal); if (brushData.type != BrushData::DependsOnThePalette) { -#if defined Q_CC_MSVC && _MSC_VER <= 1300 - BackgroundData data; - data.brush = brushData; - data.image = *image; - data.repeat = *repeat; - data.alignment = *alignment; -#else BackgroundData data = { brushData, *image, *repeat, *alignment }; -#endif - decl.d->parsed = qVariantFromValue<BackgroundData>(data); + decl.d->parsed = QVariant::fromValue<BackgroundData>(data); } } break; @@ -1319,10 +1313,10 @@ QColor Declaration::colorValue(const QPalette &pal) const ColorData color = parseColorValue(d->values.at(0)); if(color.type == ColorData::Role) { - d->parsed = qVariantFromValue<int>(color.role); + d->parsed = QVariant::fromValue<int>(color.role); return pal.color((QPalette::ColorRole)(color.role)); } else { - d->parsed = qVariantFromValue<QColor>(color.color); + d->parsed = QVariant::fromValue<QColor>(color.color); return color.color; } } @@ -1342,11 +1336,11 @@ QBrush Declaration::brushValue(const QPalette &pal) const BrushData data = parseBrushValue(d->values.at(0), pal); if(data.type == BrushData::Role) { - d->parsed = qVariantFromValue<int>(data.role); + d->parsed = QVariant::fromValue<int>(data.role); return pal.color((QPalette::ColorRole)(data.role)); } else { if (data.type != BrushData::DependsOnThePalette) - d->parsed = qVariantFromValue<QBrush>(data.brush); + d->parsed = QVariant::fromValue<QBrush>(data.brush); return data.brush; } } @@ -1376,11 +1370,11 @@ void Declaration::brushValues(QBrush *c, const QPalette &pal) const continue; BrushData data = parseBrushValue(d->values.at(i), pal); if(data.type == BrushData::Role) { - v += qVariantFromValue<int>(data.role); + v += QVariant::fromValue<int>(data.role); c[i] = pal.color((QPalette::ColorRole)(data.role)); } else { if (data.type != BrushData::DependsOnThePalette) { - v += qVariantFromValue<QBrush>(data.brush); + v += QVariant::fromValue<QBrush>(data.brush); } else { v += QVariant(); } @@ -1453,7 +1447,7 @@ QSize Declaration::sizeValue() const else x[1] = x[0]; QSize size(x[0], x[1]); - d->parsed = qVariantFromValue<QSize>(size); + d->parsed = QVariant::fromValue<QSize>(size); return size; } @@ -1475,7 +1469,7 @@ QRect Declaration::rectValue() const if (args.count() != 4) return QRect(); QRect rect(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt()); - d->parsed = qVariantFromValue<QRect>(rect); + d->parsed = QVariant::fromValue<QRect>(rect); return rect; } @@ -1496,10 +1490,10 @@ void Declaration::colorValues(QColor *c, const QPalette &pal) const for (i = 0; i < qMin(d->values.count(), 4); i++) { ColorData color = parseColorValue(d->values.at(i)); if(color.type == ColorData::Role) { - v += qVariantFromValue<int>(color.role); + v += QVariant::fromValue<int>(color.role); c[i] = pal.color((QPalette::ColorRole)(color.role)); } else { - v += qVariantFromValue<QColor>(color.color); + v += QVariant::fromValue<QColor>(color.color); c[i] = color.color; } } @@ -1691,7 +1685,7 @@ QIcon Declaration::iconValue() const i++; } - d->parsed = qVariantFromValue<QIcon>(icon); + d->parsed = QVariant::fromValue<QIcon>(icon); return icon; } diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h index 138d506..ca9688e 100644 --- a/src/gui/text/qcssparser_p.h +++ b/src/gui/text/qcssparser_p.h @@ -178,6 +178,8 @@ enum Property { OutlineBottomRightRadius, FontVariant, TextTransform, + QtListNumberPrefix, + QtListNumberSuffix, NumProperties }; diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 3fe98e1..bdba10d 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -75,6 +75,10 @@ #ifdef Q_OS_SYMBIAN #include <private/qt_s60_p.h> #endif +#ifdef Q_WS_QPA +#include <QtGui/qplatformscreen_qpa.h> +#include <QtGui/private/qapplication_p.h> +#endif #include <QMutexLocker> @@ -172,6 +176,17 @@ Q_GUI_EXPORT int qt_defaultDpiX() if (!subScreens.isEmpty()) screen = subScreens.at(0); dpi = qRound(screen->width() / (screen->physicalWidth() / qreal(25.4))); +#elif defined(Q_WS_QPA) + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + if (pi) { + QPlatformScreen *screen = QApplicationPrivate::platformIntegration()->screens().at(0); + const QSize screenSize = screen->geometry().size(); + const QSize physicalSize = screen->physicalSize(); + dpi = qRound(screenSize.width() / (physicalSize.width() / qreal(25.4))); + } else { + //PI has not been initialised, or it is being initialised. Give a default dpi + dpi = 100; + } #elif defined(Q_OS_SYMBIAN) dpi = S60->defaultDpiX; #endif // Q_WS_X11 @@ -200,6 +215,17 @@ Q_GUI_EXPORT int qt_defaultDpiY() if (!subScreens.isEmpty()) screen = subScreens.at(0); dpi = qRound(screen->height() / (screen->physicalHeight() / qreal(25.4))); +#elif defined(Q_WS_QPA) + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + if (pi) { + QPlatformScreen *screen = QApplicationPrivate::platformIntegration()->screens().at(0); + const QSize screenSize = screen->geometry().size(); + const QSize physicalSize = screen->physicalSize(); + dpi = qRound(screenSize.height() / (physicalSize.height() / qreal(25.4))); + } else { + //PI has not been initialised, or it is being initialised. Give a default dpi + dpi = 100; + } #elif defined(Q_OS_SYMBIAN) dpi = S60->defaultDpiY; #endif // Q_WS_X11 diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h index 2cc41e1..d6f4dc5 100644 --- a/src/gui/text/qfont.h +++ b/src/gui/text/qfont.h @@ -226,7 +226,10 @@ public: bool operator<(const QFont &) const; operator QVariant() const; bool isCopyOf(const QFont &) const; - +#ifdef Q_COMPILER_RVALUE_REFS + inline QFont &operator=(QFont &&other) + { qSwap(d, other.d); return *this; } +#endif #ifdef Q_WS_WIN HFONT handle() const; @@ -315,6 +318,7 @@ private: friend class QPainterReplayer; friend class QPaintBufferEngine; friend class QCommandLinkButtonPrivate; + friend class QFontEngine; #ifndef QT_NO_DATASTREAM friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QFont &); diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h index 470c109..646a8b8 100644 --- a/src/gui/text/qfont_p.h +++ b/src/gui/text/qfont_p.h @@ -192,6 +192,11 @@ public: QFont smallCapsFont() const { return QFont(smallCapsFontPrivate()); } QFontPrivate *smallCapsFontPrivate() const; + static QFontPrivate *get(const QFont &font) + { + return font.d.data(); + } + void resolve(uint mask, const QFontPrivate *other); private: QFontPrivate &operator=(const QFontPrivate &) { return *this; } diff --git a/src/gui/text/qfont_qpa.cpp b/src/gui/text/qfont_qpa.cpp new file mode 100644 index 0000000..5fed18b --- /dev/null +++ b/src/gui/text/qfont_qpa.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** 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 QtGui 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 <QtGui/private/qapplication_p.h> +#include <QtGui/QPlatformFontDatabase> + +QT_BEGIN_NAMESPACE + +void QFont::initialize() +{ + QApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase(); +} + +void QFont::cleanup() +{ + QFontCache::cleanup(); +} + + +/***************************************************************************** + QFont member functions + *****************************************************************************/ + +Qt::HANDLE QFont::handle() const +{ + return 0; +} + +QString QFont::rawName() const +{ + return QLatin1String("unknown"); +} + +void QFont::setRawName(const QString &) +{ +} + +QString QFont::defaultFamily() const +{ + QString familyName; + switch(d->request.styleHint) { + case QFont::Times: + familyName = QString::fromLatin1("times"); + case QFont::Courier: + case QFont::Monospace: + familyName = QString::fromLatin1("monospace"); + case QFont::Decorative: + familyName = QString::fromLatin1("old english"); + case QFont::Helvetica: + case QFont::System: + default: + familyName = QString::fromLatin1("helvetica"); + } + + QStringList list = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(familyName,QFont::StyleNormal,QUnicodeTables::Common); + if (list.size()) { + familyName = list.at(0); + } + return familyName; +} + +QString QFont::lastResortFamily() const +{ + return QString::fromLatin1("helvetica"); +} + +QString QFont::lastResortFont() const +{ + qFatal("QFont::lastResortFont: Cannot find any reasonable font"); + // Shut compiler up + return QString(); +} + + +QT_END_NAMESPACE + diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index e6c36a4..bae2a20 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -50,13 +50,19 @@ #include "private/qunicodetables_p.h" #include "qfontengine_p.h" +#ifdef Q_WS_QPA +#include <QtGui/private/qapplication_p.h> +#include <QtGui/qplatformfontdatabase_qpa.h> +#include "qabstractfileengine.h" +#endif + #ifdef Q_WS_X11 #include <locale.h> #endif #include <stdlib.h> #include <limits.h> -#if (defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) +#if (defined(Q_WS_QWS)|| defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) # include <ft2build.h> # include FT_TRUETYPE_TABLES_H #endif @@ -75,10 +81,6 @@ # define FM_DEBUG if (false) qDebug #endif -#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) -# define for if(0){}else for -#endif - QT_BEGIN_NAMESPACE #define SMOOTH_SCALABLE 0xffff @@ -143,7 +145,7 @@ struct QtFontEncoding uchar pitch : 8; }; -struct QtFontSize +struct QtFontSize { #ifdef Q_WS_X11 QtFontEncoding *encodings; @@ -151,10 +153,14 @@ struct QtFontSize uint yres = 0, uint avgwidth = 0, bool add = false); unsigned short count : 16; #endif // Q_WS_X11 + #if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) QByteArray fileName; int fileIndex; -#endif // defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#endif // defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QPA) + void *handle; +#endif unsigned short pixelSize : 16; }; @@ -230,7 +236,7 @@ struct QtFontStyle delete [] weightName; delete [] setwidthName; #endif -#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) while (count) { // bitfield count-- in while condition does not work correctly in mwccsym2 count--; @@ -240,6 +246,12 @@ struct QtFontStyle #if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) pixelSizes[count].fileName.~QByteArray(); #endif +#if defined (Q_WS_QPA) + QPlatformIntegration *integration = QApplicationPrivate::platformIntegration(); + if (integration) { //on shut down there will be some that we don't release. + integration->fontDatabase()->releaseHandle(pixelSizes[count].handle); + } +#endif } #endif free(pixelSizes); @@ -255,7 +267,7 @@ struct QtFontStyle const char *weightName; const char *setwidthName; #endif // Q_WS_X11 -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) bool antialiased; #endif @@ -305,6 +317,9 @@ QtFontSize *QtFontStyle::pixelSize(unsigned short size, bool add) new (&pixelSizes[count].fileName) QByteArray; pixelSizes[count].fileIndex = 0; #endif +#if defined(Q_WS_QPA) + pixelSizes[count].handle = 0; +#endif return pixelSizes + (count++); } @@ -361,7 +376,7 @@ QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, bool create) } -struct QtFontFamily +struct QtFontFamily { enum WritingSystemStatus { Unknown = 0, @@ -387,9 +402,12 @@ struct QtFontFamily fixedPitchComputed(false), #endif name(n), count(0), foundries(0) -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) , bogusWritingSystems(false) #endif +#if defined(Q_WS_QPA) + , askedForFallback(false) +#endif { memset(writingSystems, 0, sizeof(writingSystems)); } @@ -427,10 +445,13 @@ struct QtFontFamily int count; QtFontFoundry **foundries; -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) bool bogusWritingSystems; QStringList fallbackFamilies; #endif +#if defined (Q_WS_QPA) + bool askedForFallback; +#endif unsigned char writingSystems[QFontDatabase::WritingSystemsCount]; QtFontFoundry *foundry(const QString &f, bool = false); @@ -475,6 +496,7 @@ QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create) // ### copied to tools/makeqpf/qpf2.cpp #if (defined(Q_WS_QWS) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || (defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)) + // see the Unicode subset bitfields in the MSDN docs static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = { // Any, @@ -667,7 +689,7 @@ public: bool loadFromCache(const QString &fontPath); void addQPF2File(const QByteArray &file); #endif // Q_WS_QWS -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) +#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) void addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize, const QByteArray &file, int fileIndex, bool antialiased, @@ -678,10 +700,12 @@ public: #endif #if defined(Q_WS_QWS) QDataStream *stream; - QStringList fallbackFamilies; #elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) const QSymbianFontDatabaseExtras *symbianExtras; #endif +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) + QStringList fallbackFamilies; +#endif }; void QFontDatabasePrivate::invalidate() @@ -730,7 +754,7 @@ QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create) return families[pos]; } -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) +#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize, const QByteArray &file, int fileIndex, bool antialiased, const QList<QFontDatabase::WritingSystem> &writingSystems) @@ -963,7 +987,7 @@ static void match(int script, const QFontDef &request, const QString &family_name, const QString &foundry_name, int force_encoding_id, QtFontDesc *desc, const QList<int> &blacklistedFamilies = QList<int>(), bool forceXLFD=false); -#if defined(Q_WS_X11) || defined(Q_WS_QWS) +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDef *fontDef) { fontDef->family = desc.family->name; @@ -992,7 +1016,7 @@ static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDe #endif #endif -#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || defined(Q_WS_QPA) static void getEngineData(const QFontPrivate *d, const QFontCache::Key &key) { // look for the requested font in the engine data cache @@ -1053,6 +1077,8 @@ QT_BEGIN_INCLUDE_NAMESPACE # include "qfontdatabase_win.cpp" #elif defined(Q_WS_QWS) # include "qfontdatabase_qws.cpp" +#elif defined(Q_WS_QPA) +# include "qfontdatabase_qpa.cpp" #elif defined(Q_OS_SYMBIAN) # include "qfontdatabase_s60.cpp" #endif @@ -1338,6 +1364,7 @@ static void match(int script, const QFontDef &request, styleKey.stretch = request.stretch; char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p'; + FM_DEBUG("QFontDatabase::match\n" " request:\n" " family: %s [%s], script: %d\n" @@ -2427,10 +2454,12 @@ QString QFontDatabase::writingSystemSample(WritingSystem writingSystem) sample += QChar(0x4f8b); break; case Japanese: - sample += QChar(0x3050); - sample += QChar(0x3060); - sample += QChar(0x30b0); - sample += QChar(0x30c0); + sample += QChar(0x30b5); + sample += QChar(0x30f3); + sample += QChar(0x30d7); + sample += QChar(0x30eb); + sample += QChar(0x3067); + sample += QChar(0x3059); break; case Korean: sample += QChar(0xac00); @@ -2483,7 +2512,7 @@ void QFontDatabase::createDatabase() { initializeDb(); } // used from qfontengine_ft.cpp -QByteArray qt_fontdata_from_index(int index) +Q_GUI_EXPORT QByteArray qt_fontdata_from_index(int index) { QMutexLocker locker(fontDatabaseMutex()); return privateDb()->applicationFonts.value(index).data; diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h index 719242c..f31c19c 100644 --- a/src/gui/text/qfontdatabase.h +++ b/src/gui/text/qfontdatabase.h @@ -152,7 +152,7 @@ public: private: static void createDatabase(); static void parseFontName(const QString &name, QString &foundry, QString &family); -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request); #endif static void load(const QFontPrivate *d, int script); @@ -167,6 +167,7 @@ private: friend class QFontEngineMultiXLFD; friend class QFontEngineMultiQWS; friend class QFontEngineMultiS60; + friend class QFontEngineMultiQPA; QFontDatabasePrivate *d; }; diff --git a/src/gui/text/qfontdatabase_mac.cpp b/src/gui/text/qfontdatabase_mac.cpp index 5a9fc35..712bdb4 100644 --- a/src/gui/text/qfontdatabase_mac.cpp +++ b/src/gui/text/qfontdatabase_mac.cpp @@ -293,8 +293,12 @@ void QFontDatabase::load(const QFontPrivate *d, int script) // previous versions family_list << QApplication::font().defaultFamily(); +#if defined(QT_MAC_USE_COCOA) + QCFString fontName = NULL, familyName = NULL; +#else ATSFontFamilyRef familyRef = 0; ATSFontRef fontRef = 0; +#endif QMutexLocker locker(fontDatabaseMutex()); QFontDatabasePrivate *db = privateDb(); @@ -304,26 +308,20 @@ void QFontDatabase::load(const QFontPrivate *d, int script) for (int k = 0; k < db->count; ++k) { if (db->families[k]->name.compare(family_list.at(i), Qt::CaseInsensitive) == 0) { QByteArray family_name = db->families[k]->name.toUtf8(); +#if defined(QT_MAC_USE_COCOA) + QCFType<CTFontRef> ctFont = CTFontCreateWithName(QCFString(db->families[k]->name), 12, NULL); + if (ctFont) { + fontName = CTFontCopyFullName(ctFont); + familyName = CTFontCopyFamilyName(ctFont); + goto FamilyFound; + } +#else familyRef = ATSFontFamilyFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault); if (familyRef) { fontRef = ATSFontFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault); goto FamilyFound; - } else { -#if defined(QT_MAC_USE_COCOA) - // ATS and CT disagrees on what the family name should be, - // use CT to look up the font if ATS fails. - QCFString familyName = QString::fromAscii(family_name); - QCFType<CTFontRef> CTfontRef = CTFontCreateWithName(familyName, 12, NULL); - QCFType<CTFontDescriptorRef> fontDescriptor = CTFontCopyFontDescriptor(CTfontRef); - QCFString displayName = (CFStringRef)CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontDisplayNameAttribute); - - familyRef = ATSFontFamilyFindFromName(displayName, kATSOptionFlagsDefault); - if (familyRef) { - fontRef = ATSFontFindFromName(displayName, kATSOptionFlagsDefault); - goto FamilyFound; - } -#endif } +#endif } } } @@ -331,92 +329,18 @@ FamilyFound: //fill in the engine's font definition QFontDef fontDef = d->request; //copy.. if(fontDef.pointSize < 0) - fontDef.pointSize = qt_mac_pointsize(fontDef, d->dpi); + fontDef.pointSize = qt_mac_pointsize(fontDef, d->dpi); else - fontDef.pixelSize = qt_mac_pixelsize(fontDef, d->dpi); -#if 0 - ItemCount name_count; - if(ATSUCountFontNames(fontID, &name_count) == noErr && name_count) { - ItemCount actualName_size; - if(ATSUGetIndFontName(fontID, 0, 0, 0, &actualName_size, 0, 0, 0, 0) == noErr && actualName_size) { - QByteArray actualName(actualName_size); - if(ATSUGetIndFontName(fontID, 0, actualName_size, actualName.data(), &actualName_size, 0, 0, 0, 0) == noErr && actualName_size) - fontDef.family = QString::fromUtf8(actualName); - } - } -#else - { - QCFString actualName; - if(ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr) - fontDef.family = actualName; - } -#endif + fontDef.pixelSize = qt_mac_pixelsize(fontDef, d->dpi); #ifdef QT_MAC_USE_COCOA - QFontEngine *engine = new QCoreTextFontEngineMulti(familyRef, fontRef, fontDef, d->kerning); -#elif 1 - QFontEngine *engine = new QFontEngineMacMulti(familyRef, fontRef, fontDef, d->kerning); + fontDef.family = familyName; + QFontEngine *engine = new QCoreTextFontEngineMulti(fontName, fontDef, d->kerning); #else - ATSFontFamilyRef atsFamily = familyRef; - ATSFontFamilyRef atsFontRef = fontRef; - - FMFont fontID; - FMFontFamily fmFamily; - FMFontStyle fntStyle = 0; - fmFamily = FMGetFontFamilyFromATSFontFamilyRef(atsFamily); - if (fmFamily == kInvalidFontFamily) { - // Use the ATSFont then... - fontID = FMGetFontFromATSFontRef(atsFontRef); - } else { - if (fontDef.weight >= QFont::Bold) - fntStyle |= ::bold; - if (fontDef.style != QFont::StyleNormal) - fntStyle |= ::italic; - - FMFontStyle intrinsicStyle; - FMFont fnt = 0; - if (FMGetFontFromFontFamilyInstance(fmFamily, fntStyle, &fnt, &intrinsicStyle) == noErr) - fontID = FMGetATSFontRefFromFont(fnt); - } - - OSStatus status; - - const int maxAttributeCount = 5; - ATSUAttributeTag tags[maxAttributeCount + 1]; - ByteCount sizes[maxAttributeCount + 1]; - ATSUAttributeValuePtr values[maxAttributeCount + 1]; - int attributeCount = 0; - - Fixed size = FixRatio(fontDef.pixelSize, 1); - tags[attributeCount] = kATSUSizeTag; - sizes[attributeCount] = sizeof(size); - values[attributeCount] = &size; - ++attributeCount; - - tags[attributeCount] = kATSUFontTag; - sizes[attributeCount] = sizeof(fontID); - values[attributeCount] = &fontID; - ++attributeCount; - - CGAffineTransform transform = CGAffineTransformIdentity; - if (fontDef.stretch != 100) { - transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); - tags[attributeCount] = kATSUFontMatrixTag; - sizes[attributeCount] = sizeof(transform); - values[attributeCount] = &transform; - ++attributeCount; - } - - ATSUStyle style; - status = ATSUCreateStyle(&style); - Q_ASSERT(status == noErr); - - Q_ASSERT(attributeCount < maxAttributeCount + 1); - status = ATSUSetAttributes(style, attributeCount, tags, sizes, values); - Q_ASSERT(status == noErr); - - QFontEngine *engine = new QFontEngineMac(style, fontID, fontDef, /*multiEngine*/ 0); - ATSUDisposeStyle(style); + QCFString actualName; + if (ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr) + fontDef.family = actualName; + QFontEngine *engine = new QFontEngineMacMulti(familyRef, fontRef, fontDef, d->kerning); #endif d->engineData->engine = engine; engine->ref.ref(); //a ref for the engineData->engine diff --git a/src/gui/text/qfontdatabase_qpa.cpp b/src/gui/text/qfontdatabase_qpa.cpp new file mode 100644 index 0000000..19ce1be --- /dev/null +++ b/src/gui/text/qfontdatabase_qpa.cpp @@ -0,0 +1,393 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qlibraryinfo.h" +#include <QtCore/qsettings.h> + +#include "qfontengine_qpa_p.h" +#include "qplatformdefs.h" + +#include <QtGui/private/qapplication_p.h> +#include <QtGui/qplatformfontdatabase_qpa.h> + +#include <QtCore/qmath.h> + +QT_BEGIN_NAMESPACE + +Q_GUI_EXPORT void qt_registerFont(const QString &familyName, const QString &foundryname, int weight, + QFont::Style style, int stretch, bool antialiased, bool scalable, int pixelSize, + const QSupportedWritingSystems &writingSystems, void *handle) +{ + QFontDatabasePrivate *d = privateDb(); + // qDebug() << "Adding font" << familyname << weight << italic << pixelSize << file << fileIndex << antialiased; + QtFontStyle::Key styleKey; + styleKey.style = style; + styleKey.weight = weight; + styleKey.stretch = stretch; + QtFontFamily *f = d->family(familyName, true); + + for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) { + if (writingSystems.supported(QFontDatabase::WritingSystem(i))) { + f->writingSystems[i] = QtFontFamily::Supported; + } else { + f->writingSystems[i] = QtFontFamily::Unsupported; + } + } + + QtFontFoundry *foundry = f->foundry(foundryname, true); + QtFontStyle *fontStyle = foundry->style(styleKey, true); + fontStyle->smoothScalable = scalable; + fontStyle->antialiased = antialiased; + QtFontSize *size = fontStyle->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true); + size->handle = handle; +} + +static QStringList fallbackFamilies(const QString &family, const QFont::Style &style, const QUnicodeTables::Script &script) +{ + QStringList retList = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,script); + QFontDatabasePrivate *db = privateDb(); + + QStringList::iterator i; + for (i = retList.begin(); i != retList.end(); ++i) { + bool contains = false; + for (int j = 0; j < db->count; j++) { + QtFontFamily *qtFamily = db->families[j]; + if (!(i->compare(qtFamily->name,Qt::CaseInsensitive))) { + contains = true; + break; + } + } + if (!contains) { + i = retList.erase(i); + i--; + } + } + return retList; +} + +static void initializeDb() +{ + static int initialized = false; + + if (!initialized) { + //init by asking for the platformfontdb for the first time :) + QApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase(); + initialized = true; + } +} + +#ifndef QT_NO_SETTINGS +// called from qapplication_qws.cpp +void qt_applyFontDatabaseSettings(const QSettings &settings) +{ + initializeDb(); + QFontDatabasePrivate *db = privateDb(); + for (int i = 0; i < db->count; ++i) { + QtFontFamily *family = db->families[i]; + if (settings.contains(family->name)) + family->fallbackFamilies = settings.value(family->name).toStringList(); + } + + if (settings.contains(QLatin1String("Global Fallbacks"))) + db->fallbackFamilies = settings.value(QLatin1String("Global Fallbacks")).toStringList(); +} +#endif // QT_NO_SETTINGS + +static inline void load(const QString & = QString(), int = -1) +{ + initializeDb(); +} + +static +QFontEngine *loadSingleEngine(int script, + const QFontDef &request, + QtFontFoundry *foundry, + QtFontStyle *style, QtFontSize *size) +{ + Q_UNUSED(foundry); + + Q_ASSERT(size); + int pixelSize = size->pixelSize; + if (!pixelSize || (style->smoothScalable && pixelSize == SMOOTH_SCALABLE)) + pixelSize = request.pixelSize; + + QFontDef def = request; + def.pixelSize = pixelSize; + + QFontCache::Key key(def,script); + QFontEngine *engine = QFontCache::instance()->findEngine(key); + if (!engine) { + QPlatformFontDatabase *pfdb = QApplicationPrivate::platformIntegration()->fontDatabase(); + if (size->handle) { + engine = pfdb->fontEngine(def,QUnicodeTables::Script(script),size->handle); + if (engine) { + QFontCache::Key key(def,script); + QFontCache::instance()->instance()->insertEngine(key,engine); + } + } + + } + return engine; +} + +static +QFontEngine *loadEngine(int script, const QFontDef &request, + QtFontFamily *family, QtFontFoundry *foundry, + QtFontStyle *style, QtFontSize *size) +{ + + QFontEngine *engine = loadSingleEngine(script, request, foundry, style, size); + //make sure that the db has all fallback families + if (engine + && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol ) { + + if (family && !family->askedForFallback) { + family->fallbackFamilies = fallbackFamilies(family->name,QFont::Style(style->key.style),QUnicodeTables::Script(script)); + + family->askedForFallback = true; + } + + QStringList fallbacks = privateDb()->fallbackFamilies; + if (family && !family->fallbackFamilies.isEmpty()) + fallbacks = family->fallbackFamilies; + + engine = new QFontEngineMultiQPA(engine, script, fallbacks); + } + + return engine; +} + +static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) +{ + QFontDatabasePrivate *db = privateDb(); + + fnt->families = QApplicationPrivate::platformIntegration()->fontDatabase()->addApplicationFont(fnt->data,fnt->fileName); + + db->reregisterAppFonts = true; +} + +bool QFontDatabase::removeApplicationFont(int handle) +{ + QMutexLocker locker(fontDatabaseMutex()); + + QFontDatabasePrivate *db = privateDb(); + if (handle < 0 || handle >= db->applicationFonts.count()) + return false; + + db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont(); + + db->reregisterAppFonts = true; + db->invalidate(); + return true; +} + +bool QFontDatabase::removeAllApplicationFonts() +{ + QMutexLocker locker(fontDatabaseMutex()); + + QFontDatabasePrivate *db = privateDb(); + if (db->applicationFonts.isEmpty()) + return false; + + db->applicationFonts.clear(); + db->invalidate(); + return true; +} + +bool QFontDatabase::supportsThreadedFontRendering() +{ + return true; +} + +/*! + \internal +*/ +QFontEngine * +QFontDatabase::findFont(int script, const QFontPrivate *fp, + const QFontDef &request) +{ + QMutexLocker locker(fontDatabaseMutex()); + + const int force_encoding_id = -1; + + if (!privateDb()->count) + initializeDb(); + + QFontEngine *engine; + QFontCache::Key key(request, script); + engine = QFontCache::instance()->findEngine(key); + if (engine) { + qDebug() << "Cache hit level 1"; + return engine; + } + + QString family_name, foundry_name; + + parseFontName(request.family, foundry_name, family_name); + + if (qt_enable_test_font && request.family == QLatin1String("__Qt__Box__Engine__")) { + engine =new QTestFontEngine(request.pixelSize); + engine->fontDef = request; + } + + QtFontDesc desc; + match(script, request, family_name, foundry_name, force_encoding_id, &desc); + if (desc.family != 0 && desc.foundry != 0 && desc.style != 0) { + engine = loadEngine(script, request, desc.family, desc.foundry, desc.style, desc.size); + } else { + FM_DEBUG(" NO MATCH FOUND\n"); + } + + if (engine) { + initFontDef(desc, request, &engine->fontDef); + + if (fp) { + QFontDef def = request; + if (def.family.isEmpty()) { + def.family = fp->request.family; + def.family = def.family.left(def.family.indexOf(QLatin1Char(','))); + } + } + } + + if (!engine) { + if (!request.family.isEmpty()) { + QStringList fallbacks = fallbackFamilies(request.family,QFont::Style(request.style),QUnicodeTables::Script(script)); + for (int i = 0; i < fallbacks.size(); i++) { + QFontDef def = request; + def.family = fallbacks.at(i); + QFontCache::Key key(def,script); + engine = QFontCache::instance()->findEngine(key); + if (!engine) { + QtFontDesc desc; + match(script, def, def.family, QLatin1String(""), 0, &desc); + if (desc.family == 0 && desc.foundry == 0 && desc.style == 0) { + continue; + } + engine = loadEngine(script, def, desc.family, desc.foundry, desc.style, desc.size); + if (engine) { + initFontDef(desc, def, &engine->fontDef); + break; + } + } + } + } + + if (!engine) + engine = new QFontEngineBox(request.pixelSize); + + FM_DEBUG("returning box engine"); + } + + if (fp && fp->dpi > 0) { + engine->fontDef.pointSize = qreal(double((engine->fontDef.pixelSize * 72) / fp->dpi)); + } else { + engine->fontDef.pointSize = request.pointSize; + } + + return engine; +} + +void QFontDatabase::load(const QFontPrivate *d, int script) +{ + QFontDef req = d->request; + + if (req.pixelSize == -1) { + req.pixelSize = floor(((req.pointSize * d->dpi) / 72) * 100 + 0.5) / 100; + req.pixelSize = qRound(req.pixelSize); + } + if (req.pointSize < 0) + req.pointSize = req.pixelSize*72.0/d->dpi; + if (req.weight == 0) + req.weight = QFont::Normal; + if (req.stretch == 0) + req.stretch = 100; + + QFontCache::Key key(req, script); + + if (!d->engineData) + getEngineData(d, key); + + // the cached engineData could have already loaded the engine we want + if (d->engineData->engines[script]) + return; + + QFontEngine *fe = QFontCache::instance()->findEngine(key); + + // list of families to try + QStringList family_list; + + if (!req.family.isEmpty()) { + family_list = familyList(req); + + // add the default family + QString defaultFamily = QApplication::font().family(); + if (! family_list.contains(defaultFamily)) + family_list << defaultFamily; + + } + + // null family means find the first font matching the specified script + family_list << QString(); + + QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd(); + for (; !fe && it != end; ++it) { + req.family = *it; + + fe = QFontDatabase::findFont(script, d, req); + if (fe && (fe->type()==QFontEngine::Box) && !req.family.isEmpty()) + fe = 0; + } + + if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) { + for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) { + if (!d->engineData->engines[i]) { + d->engineData->engines[i] = fe; + fe->ref.ref(); + } + } + } else { + d->engineData->engines[script] = fe; + fe->ref.ref(); + } +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qfontdatabase_qws.cpp b/src/gui/text/qfontdatabase_qws.cpp index a3d8d65..09fb07c 100644 --- a/src/gui/text/qfontdatabase_qws.cpp +++ b/src/gui/text/qfontdatabase_qws.cpp @@ -40,8 +40,10 @@ ****************************************************************************/ #include "qdir.h" +#if defined(Q_WS_QWS) #include "qscreen_qws.h" //so we can check for rotation #include "qwindowsystem_qws.h" +#endif #include "qlibraryinfo.h" #include "qabstractfileengine.h" #include <QtCore/qsettings.h> @@ -153,7 +155,11 @@ extern QString qws_fontCacheDir(); #ifndef QT_FONTS_ARE_RESOURCES bool QFontDatabasePrivate::loadFromCache(const QString &fontPath) { +#ifdef Q_WS_QWS const bool weAreTheServer = QWSServer::instance(); +#else + const bool weAreTheServer = true; // assume single-process +#endif QString fontDirFile = fontPath + QLatin1String("/fontdir"); @@ -382,12 +388,14 @@ static void initializeDb() } #endif +#ifndef QT_NO_QWS_QPF2 QDir dir(fontpath, QLatin1String("*.qpf2")); for (int i = 0; i < int(dir.count()); ++i) { const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i])); //qDebug() << "looking at" << file; db->addQPF2File(file); } +#endif #endif //QT_FONTS_ARE_RESOURCES @@ -688,6 +696,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, { QScopedPointer<QFontEngine> engine(loadSingleEngine(script, fp, request, family, foundry, style, size)); +#ifndef QT_NO_QWS_QPF if (!engine.isNull() && script == QUnicodeTables::Common && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol) { @@ -701,6 +710,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, engine.take(); engine.reset(fe); } +#endif return engine.take(); } diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 7e04180..f73b816 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -184,10 +184,6 @@ QFontEngine::QFontEngine() QFontEngine::~QFontEngine() { - for (QLinkedList<GlyphCacheEntry>::const_iterator it = m_glyphCaches.constBegin(), - end = m_glyphCaches.constEnd(); it != end; ++it) { - delete it->cache; - } m_glyphCaches.clear(); qHBFreeFace(hbFace); } @@ -241,6 +237,24 @@ glyph_metrics_t QFontEngine::boundingBox(glyph_t glyph, const QTransform &matrix return metrics; } +QFont QFontEngine::createExplicitFont() const +{ + return createExplicitFontWithName(fontDef.family); +} + +QFont QFontEngine::createExplicitFontWithName(const QString &familyName) const +{ + QFont font(familyName); + font.setStyleStrategy(QFont::NoFontMerging); + font.setWeight(fontDef.weight); + font.setItalic(fontDef.style == QFont::StyleItalic); + if (fontDef.pointSize < 0) + font.setPixelSize(fontDef.pixelSize); + else + font.setPointSizeF(fontDef.pointSize); + return font; +} + QFixed QFontEngine::xHeight() const { QGlyphLayoutArray<8> glyphs; @@ -480,7 +494,7 @@ static void collectSingleContour(qreal x0, qreal y0, uint *grid, int x, int y, i path->closeSubpath(); } -void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path) +Q_GUI_EXPORT void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path) { uint *grid = new uint[(w+1)*(h+1)]; // set up edges @@ -601,7 +615,7 @@ QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &t) return i; } -QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, int /* margin */, const QTransform &t) +QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed /*subPixelPosition*/, int /* margin */, const QTransform &t) { QImage alphaMask = alphaMapForGlyph(glyph, t); QImage rgbMask(alphaMask.width(), alphaMask.height(), QImage::Format_RGB32); @@ -711,14 +725,16 @@ void QFontEngine::setGlyphCache(void *key, QFontEngineGlyphCache *data) { Q_ASSERT(data); - GlyphCacheEntry entry = { key, data }; + GlyphCacheEntry entry; + entry.context = key; + entry.cache = data; if (m_glyphCaches.contains(entry)) return; // Limit the glyph caches to 4. This covers all 90 degree rotations and limits // memory use when there is continuous or random rotation if (m_glyphCaches.size() == 4) - delete m_glyphCaches.takeLast().cache; + m_glyphCaches.removeLast(); m_glyphCaches.push_front(entry); @@ -727,7 +743,7 @@ void QFontEngine::setGlyphCache(void *key, QFontEngineGlyphCache *data) QFontEngineGlyphCache *QFontEngine::glyphCache(void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const { for (QLinkedList<GlyphCacheEntry>::const_iterator it = m_glyphCaches.constBegin(), end = m_glyphCaches.constEnd(); it != end; ++it) { - QFontEngineGlyphCache *c = it->cache; + QFontEngineGlyphCache *c = it->cache.data(); if (key == it->context && type == c->cacheType() && qtransform_equals_no_translate(c->m_transform, transform)) { @@ -737,7 +753,7 @@ QFontEngineGlyphCache *QFontEngine::glyphCache(void *key, QFontEngineGlyphCache: return 0; } -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) static inline QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs) { uint left_right = (left << 16) + right; @@ -1181,7 +1197,7 @@ glyph_metrics_t QFontEngineBox::boundingBox(const QGlyphLayout &glyphs) return overall; } -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) void QFontEngineBox::draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &ti) { if (!ti.glyphs.numGlyphs) diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index cc6af7f..81e2594 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -723,7 +723,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format) metrics = face->size->metrics; -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) /* TrueType fonts with embedded bitmaps may have a bitmap font specific ascent/descent in the EBLC table. There is no direct public API @@ -755,16 +755,42 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format) return true; } -QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph) const +void QFontEngineFT::setDefaultHintStyle(HintStyle style) +{ + default_hint_style = style; +} + +QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph, GlyphFormat format) const { Glyph *g = set->getGlyph(glyph); - if (g) + if (g && g->format == format) return g; int load_flags = FT_LOAD_DEFAULT | default_load_flags; + int load_target = default_hint_style == HintLight + ? FT_LOAD_TARGET_LIGHT + : FT_LOAD_TARGET_NORMAL; + + if (format == Format_Mono) { + load_target = FT_LOAD_TARGET_MONO; + } else if (format == Format_A32) { + if (subpixelType == QFontEngineFT::Subpixel_RGB || subpixelType == QFontEngineFT::Subpixel_BGR) { + if (default_hint_style == HintFull) + load_target = FT_LOAD_TARGET_LCD; + } else if (subpixelType == QFontEngineFT::Subpixel_VRGB || subpixelType == QFontEngineFT::Subpixel_VBGR) { + if (default_hint_style == HintFull) + load_target = FT_LOAD_TARGET_LCD_V; + } + } + if (set->outline_drawing) load_flags = FT_LOAD_NO_BITMAP; + if (default_hint_style == HintNone) + load_flags |= FT_LOAD_NO_HINTING; + else + load_flags |= load_target; + // apply our matrix to this, but note that the metrics will not be affected by this. FT_Face face = lockFace(); FT_Matrix matrix = this->matrix; @@ -1758,6 +1784,11 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph) glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matrix) { + return alphaMapBoundingBox(glyph, matrix, QFontEngine::Format_None); +} + +glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, const QTransform &matrix, QFontEngine::GlyphFormat format) +{ FT_Face face = 0; glyph_metrics_t overall; QGlyphSet *glyphSet = 0; @@ -1801,9 +1832,9 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matr glyphSet = &defaultGlyphSet; } Glyph * g = glyphSet->getGlyph(glyph); - if (!g) { + if (!g || g->format != format) { face = lockFace(); - g = loadGlyphMetrics(glyphSet, glyph); + g = loadGlyphMetrics(glyphSet, glyph, format); } if (g) { @@ -1865,10 +1896,10 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g) return img; } -QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, int margin, const QTransform &t) +QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, int margin, const QTransform &t) { if (t.type() > QTransform::TxTranslate) - return QFontEngine::alphaRGBMapForGlyph(g, margin, t); + return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, margin, t); lockFace(); @@ -1877,7 +1908,7 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, int margin, const QTransfor Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, glyph_format); if (!glyph) { unlockFace(); - return QFontEngine::alphaRGBMapForGlyph(g, margin, t); + return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, margin, t); } QImage img(glyph->width, glyph->height, QImage::Format_RGB32); diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index 2f05a8b..f0f7153 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -130,13 +130,6 @@ private: class Q_GUI_EXPORT QFontEngineFT : public QFontEngine { public: - enum GlyphFormat { - Format_None, - Format_Render = Format_None, - Format_Mono, - Format_A8, - Format_A32 - }; /* we don't cache glyphs that are too large anyway, so we can make this struct rather small */ struct Glyph { @@ -241,7 +234,9 @@ private: virtual void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const; virtual QImage alphaMapForGlyph(glyph_t); - virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t); + virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t); + virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, const QTransform &matrix, + QFontEngine::GlyphFormat format); virtual void removeGlyphFromCache(glyph_t glyph); virtual int glyphCount() const; @@ -282,6 +277,14 @@ private: virtual HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints); + enum HintStyle { + HintNone, + HintLight, + HintMedium, + HintFull + }; + + void setDefaultHintStyle(HintStyle style); protected: void freeGlyphSets(); @@ -293,12 +296,6 @@ protected: QFreetypeFace *freetype; int default_load_flags; - enum HintStyle { - HintNone, - HintLight, - HintMedium, - HintFull - }; HintStyle default_hint_style; @@ -311,7 +308,7 @@ protected: bool embeddedbitmap; private: - QFontEngineFT::Glyph *loadGlyphMetrics(QGlyphSet *set, uint glyph) const; + QFontEngineFT::Glyph *loadGlyphMetrics(QGlyphSet *set, uint glyph, GlyphFormat format) const; GlyphFormat defaultFormat; FT_Matrix matrix; diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index b3efe6c..ebc1f6d 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -142,7 +142,7 @@ void qmacfontengine_gamma_correct(QImage *image) #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 -QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const ATSFontFamilyRef &, const ATSFontRef &atsFontRef, const QFontDef &fontDef, bool kerning) +QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const QCFString &name, const QFontDef &fontDef, bool kerning) : QFontEngineMulti(0) { this->fontDef = fontDef; @@ -158,9 +158,6 @@ QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const ATSFontFamilyRef &, con break; } - QCFString name; - ATSFontGetName(atsFontRef, kATSOptionFlagsDefault, &name); - transform = CGAffineTransformIdentity; if (fontDef.stretch != 100) { transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); @@ -421,8 +418,7 @@ QCoreTextFontEngine::QCoreTextFontEngine(CTFontRef font, const QFontDef &def, synthesisFlags = 0; ctfont = font; CFRetain(ctfont); - ATSFontRef atsfont = CTFontGetPlatformFont(ctfont, 0); - cgFont = CGFontCreateWithPlatformFont(&atsfont); + cgFont = CTFontCopyGraphicsFont(ctfont, NULL); CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctfont); if (fontDef.weight >= QFont::Bold && !(traits & kCTFontBoldTrait)) { synthesisFlags |= SynthesizedBold; @@ -442,8 +438,8 @@ QCoreTextFontEngine::QCoreTextFontEngine(CTFontRef font, const QFontDef &def, QCoreTextFontEngine::~QCoreTextFontEngine() { - CFRelease(ctfont); CFRelease(cgFont); + CFRelease(ctfont); } bool QCoreTextFontEngine::stringToCMap(const QChar *, int, QGlyphLayout *, int *, QTextEngine::ShaperFlags) const @@ -656,7 +652,13 @@ void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *position } } -QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, int margin, bool aa) +QFont QCoreTextFontEngine::createExplicitFont() const +{ + QString familyName = QCFString::toQString(CTFontCopyFamilyName(ctfont)); + return createExplicitFontWithName(familyName); +} + +QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, int /*margin*/, bool aa) { const glyph_metrics_t br = boundingBox(glyph); QImage im(qRound(br.width)+2, qRound(br.height)+2, QImage::Format_RGB32); @@ -689,11 +691,10 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, int margin, bool aa) CGContextSetRGBFillColor(ctx, 1, 1, 1, 1); CGContextSetTextDrawingMode(ctx, kCGTextFill); - ATSFontRef atsfont = CTFontGetPlatformFont(ctfont, 0); - QCFType<CGFontRef> cgFont = CGFontCreateWithPlatformFont(&atsfont); CGContextSetFont(ctx, cgFont); - qreal pos_x = -br.x.toReal()+1, pos_y = im.height()+br.y.toReal(); + qreal pos_x = -br.x.toReal() + subPixelPosition.toReal(); + qreal pos_y = im.height()+br.y.toReal(); CGContextSetTextPosition(ctx, pos_x, pos_y); CGSize advance; @@ -714,7 +715,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, int margin, bool aa) QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph) { - QImage im = imageForGlyph(glyph, 0, false); + QImage im = imageForGlyph(glyph, QFixed(), 0, false); QImage indexed(im.width(), im.height(), QImage::Format_Indexed8); QVector<QRgb> colors(256); @@ -735,12 +736,12 @@ QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph) return indexed; } -QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, int margin, const QTransform &x) +QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPosition, int margin, const QTransform &x) { if (x.type() >= QTransform::TxScale) - return QFontEngine::alphaRGBMapForGlyph(glyph, margin, x); + return QFontEngine::alphaRGBMapForGlyph(glyph, subPixelPosition, margin, x); - QImage im = imageForGlyph(glyph, margin, true); + QImage im = imageForGlyph(glyph, subPixelPosition, margin, true); qmacfontengine_gamma_correct(&im); return im; } @@ -1419,6 +1420,7 @@ static inline unsigned int getChar(const QChar *str, int &i, const int len) return uc; } +// Not used directly for shaping, only used to calculate m_averageCharWidth bool QFontEngineMac::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const { if (!cmap) { @@ -1591,6 +1593,27 @@ static void addGlyphsToPathHelper(ATSUStyle style, glyph_t *glyphs, QFixedPoint DisposeATSCubicClosePathUPP(closePath); } +QFont QFontEngineMac::createExplicitFont() const +{ + FMFont fmFont = FMGetFontFromATSFontRef(fontID); + + FMFontFamily fmFamily; + FMFontStyle fmStyle; + QString familyName; + if (!FMGetFontFamilyInstanceFromFont(fmFont, &fmFamily, &fmStyle)) { + ATSFontFamilyRef familyRef = FMGetATSFontFamilyRefFromFontFamily(fmFamily); + QCFString cfFamilyName;; + ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &cfFamilyName); + familyName = cfFamilyName; + } else { + QCFString cfFontName; + ATSFontGetName(fontID, kATSOptionFlagsDefault, &cfFontName); + familyName = cfFontName; + } + + return createExplicitFontWithName(familyName); +} + void QFontEngineMac::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags) { @@ -1677,7 +1700,7 @@ QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph) return indexed; } -QImage QFontEngineMac::alphaRGBMapForGlyph(glyph_t glyph, int margin, const QTransform &t) +QImage QFontEngineMac::alphaRGBMapForGlyph(glyph_t glyph, QFixed, int margin, const QTransform &t) { QImage im = imageForGlyph(glyph, margin, true); diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index fc26eef..6d6daaa 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -120,6 +120,14 @@ public: TestFontEngine = 0x1000 }; + enum GlyphFormat { + Format_None, + Format_Render = Format_None, + Format_Mono, + Format_A8, + Format_A32 + }; + QFontEngine(); virtual ~QFontEngine(); @@ -155,6 +163,7 @@ public: SynthesizedStretch = 0x4 }; virtual int synthesized() const { return 0; } + virtual bool supportsSubPixelPositions() const { return false; } virtual QFixed emSquareSize() const { return ascent(); } @@ -168,11 +177,15 @@ public: virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const {} virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const; -#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN) +#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN) && !defined(Q_WS_QPA) virtual void draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &si) = 0; #endif virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, QPainterPath *path, QTextItem::RenderFlags flags); + + /* Creates a QFont object to represent this particular QFontEngine */ + virtual QFont createExplicitFont() const; + void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags, QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions); @@ -184,7 +197,12 @@ public: */ virtual QImage alphaMapForGlyph(glyph_t); virtual QImage alphaMapForGlyph(glyph_t, const QTransform &t); - virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t); + virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t); + + virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, const QTransform &matrix, GlyphFormat /*format*/) + { + return boundingBox(glyph, matrix); + } virtual void removeGlyphFromCache(glyph_t); @@ -237,7 +255,7 @@ public: bool symbol; mutable HB_FontRec hbFont; mutable HB_Face hbFace; -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) struct KernPair { uint left_right; QFixed adjust; @@ -254,13 +272,14 @@ public: int glyphFormat; protected: + QFont createExplicitFontWithName(const QString &familyName) const; static const QVector<QRgb> &grayPalette(); QFixed lastRightBearing(const QGlyphLayout &glyphs, bool round = false); private: struct GlyphCacheEntry { void *context; - QFontEngineGlyphCache *cache; + QExplicitlySharedDataPointer<QFontEngineGlyphCache> cache; bool operator==(const GlyphCacheEntry &other) { return context == other.context && cache == other.cache; } }; @@ -445,6 +464,7 @@ public: virtual bool canRender(const QChar *string, int len); virtual int synthesized() const { return synthesisFlags; } + virtual bool supportsSubPixelPositions() const { return true; } virtual Type type() const { return QFontEngine::Mac; } @@ -454,13 +474,13 @@ public: virtual bool getSfntTableData(uint /*tag*/, uchar * /*buffer*/, uint * /*length*/) const; virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics); virtual QImage alphaMapForGlyph(glyph_t); - virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t); + virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t); virtual qreal minRightBearing() const; virtual qreal minLeftBearing() const; - + virtual QFont createExplicitFont() const; private: - QImage imageForGlyph(glyph_t glyph, int margin, bool colorful); + QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, int margin, bool colorful); CTFontRef ctfont; CGFontRef cgFont; QCoreTextFontEngineMulti *parentEngine; @@ -472,8 +492,7 @@ private: class QCoreTextFontEngineMulti : public QFontEngineMulti { public: - QCoreTextFontEngineMulti(const ATSFontFamilyRef &atsFamily, const ATSFontRef &atsFontRef, - const QFontDef &fontDef, bool kerning); + QCoreTextFontEngineMulti(const QCFString &name, const QFontDef &fontDef, bool kerning); ~QCoreTextFontEngineMulti(); virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, @@ -523,6 +542,8 @@ public: virtual qreal maxCharWidth() const; virtual QFixed averageCharWidth() const; + virtual QFont createExplicitFont() const; + virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path, QTextItem::RenderFlags); @@ -541,7 +562,7 @@ public: virtual Properties properties() const; virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics); virtual QImage alphaMapForGlyph(glyph_t); - virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t); + virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t); private: QImage imageForGlyph(glyph_t glyph, int margin, bool colorful); diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpa.cpp new file mode 100644 index 0000000..cccbc92 --- /dev/null +++ b/src/gui/text/qfontengine_qpa.cpp @@ -0,0 +1,691 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qfontengine_qpa_p.h" + +#include <QtCore/QFile> +#include <QtCore/QFileInfo> +#include <QtCore/QDir> +#include <QtCore/QBuffer> + +#include <QtGui/private/qapplication_p.h> +#include <QtGui/QPlatformFontDatabase> +#include <QtGui/private/qpaintengine_raster_p.h> + +QT_BEGIN_NAMESPACE + +//#define DEBUG_HEADER +//#define DEBUG_FONTENGINE + +static QFontEngineQPA::TagType tagTypes[QFontEngineQPA::NumTags] = { + QFontEngineQPA::StringType, // FontName + QFontEngineQPA::StringType, // FileName + QFontEngineQPA::UInt32Type, // FileIndex + QFontEngineQPA::UInt32Type, // FontRevision + QFontEngineQPA::StringType, // FreeText + QFontEngineQPA::FixedType, // Ascent + QFontEngineQPA::FixedType, // Descent + QFontEngineQPA::FixedType, // Leading + QFontEngineQPA::FixedType, // XHeight + QFontEngineQPA::FixedType, // AverageCharWidth + QFontEngineQPA::FixedType, // MaxCharWidth + QFontEngineQPA::FixedType, // LineThickness + QFontEngineQPA::FixedType, // MinLeftBearing + QFontEngineQPA::FixedType, // MinRightBearing + QFontEngineQPA::FixedType, // UnderlinePosition + QFontEngineQPA::UInt8Type, // GlyphFormat + QFontEngineQPA::UInt8Type, // PixelSize + QFontEngineQPA::UInt8Type, // Weight + QFontEngineQPA::UInt8Type, // Style + QFontEngineQPA::StringType, // EndOfHeader + QFontEngineQPA::BitFieldType// WritingSystems +}; + + +#if defined(DEBUG_HEADER) +# define DEBUG_VERIFY qDebug +#else +# define DEBUG_VERIFY if (0) qDebug +#endif + +#define READ_VERIFY(type, variable) \ + if (tagPtr + sizeof(type) > endPtr) { \ + DEBUG_VERIFY() << "read verify failed in line" << __LINE__; \ + return 0; \ + } \ + variable = qFromBigEndian<type>(tagPtr); \ + DEBUG_VERIFY() << "read value" << variable << "of type " #type; \ + tagPtr += sizeof(type) + +template <typename T> +T readValue(const uchar *&data) +{ + T value = qFromBigEndian<T>(data); + data += sizeof(T); + return value; +} + +#define VERIFY(condition) \ + if (!(condition)) { \ + DEBUG_VERIFY() << "condition " #condition " failed in line" << __LINE__; \ + return 0; \ + } + +#define VERIFY_TAG(condition) \ + if (!(condition)) { \ + DEBUG_VERIFY() << "verifying tag condition " #condition " failed in line" << __LINE__ << "with tag" << tag; \ + return 0; \ + } + +static inline const uchar *verifyTag(const uchar *tagPtr, const uchar *endPtr) +{ + quint16 tag, length; + READ_VERIFY(quint16, tag); + READ_VERIFY(quint16, length); + if (tag == QFontEngineQPA::Tag_EndOfHeader) + return endPtr; + if (tag < QFontEngineQPA::NumTags) { + switch (tagTypes[tag]) { + case QFontEngineQPA::BitFieldType: + case QFontEngineQPA::StringType: + // can't do anything... + break; + case QFontEngineQPA::UInt32Type: + VERIFY_TAG(length == sizeof(quint32)); + break; + case QFontEngineQPA::FixedType: + VERIFY_TAG(length == sizeof(quint32)); + break; + case QFontEngineQPA::UInt8Type: + VERIFY_TAG(length == sizeof(quint8)); + break; + } +#if defined(DEBUG_HEADER) + if (length == 1) + qDebug() << "tag data" << hex << *tagPtr; + else if (length == 4) + qDebug() << "tag data" << hex << tagPtr[0] << tagPtr[1] << tagPtr[2] << tagPtr[3]; +#endif + } + return tagPtr + length; +} + +const QFontEngineQPA::Glyph *QFontEngineQPA::findGlyph(glyph_t g) const +{ + if (!g || g >= glyphMapEntries) + return 0; + const quint32 *gmapPtr = reinterpret_cast<const quint32 *>(fontData + glyphMapOffset); + quint32 glyphPos = qFromBigEndian<quint32>(gmapPtr[g]); + if (glyphPos > glyphDataSize) { + if (glyphPos == 0xffffffff) + return 0; +#if defined(DEBUG_FONTENGINE) + qDebug() << "glyph" << g << "outside of glyphData, remapping font file"; +#endif + if (glyphPos > glyphDataSize) + return 0; + } + return reinterpret_cast<const Glyph *>(fontData + glyphDataOffset + glyphPos); +} + +bool QFontEngineQPA::verifyHeader(const uchar *data, int size) +{ + VERIFY(size >= int(sizeof(Header))); + const Header *header = reinterpret_cast<const Header *>(data); + if (header->magic[0] != 'Q' + || header->magic[1] != 'P' + || header->magic[2] != 'F' + || header->magic[3] != '2') + return false; + + VERIFY(header->majorVersion <= CurrentMajorVersion); + const quint16 dataSize = qFromBigEndian<quint16>(header->dataSize); + VERIFY(size >= int(sizeof(Header)) + dataSize); + + const uchar *tagPtr = data + sizeof(Header); + const uchar *tagEndPtr = tagPtr + dataSize; + while (tagPtr < tagEndPtr - 3) { + tagPtr = verifyTag(tagPtr, tagEndPtr); + VERIFY(tagPtr); + } + + VERIFY(tagPtr <= tagEndPtr); + return true; +} + +QVariant QFontEngineQPA::extractHeaderField(const uchar *data, HeaderTag requestedTag) +{ + const Header *header = reinterpret_cast<const Header *>(data); + const uchar *tagPtr = data + sizeof(Header); + const uchar *endPtr = tagPtr + qFromBigEndian<quint16>(header->dataSize); + while (tagPtr < endPtr - 3) { + quint16 tag = readValue<quint16>(tagPtr); + quint16 length = readValue<quint16>(tagPtr); + if (tag == requestedTag) { + switch (tagTypes[requestedTag]) { + case StringType: + return QVariant(QString::fromUtf8(reinterpret_cast<const char *>(tagPtr), length)); + case UInt32Type: + return QVariant(readValue<quint32>(tagPtr)); + case UInt8Type: + return QVariant(uint(*tagPtr)); + case FixedType: + return QVariant(QFixed::fromFixed(readValue<quint32>(tagPtr)).toReal()); + case BitFieldType: + return QVariant(QByteArray(reinterpret_cast<const char *>(tagPtr), length)); + } + return QVariant(); + } else if (tag == Tag_EndOfHeader) { + break; + } + tagPtr += length; + } + + return QVariant(); +} + + + +static inline unsigned int getChar(const QChar *str, int &i, const int len) +{ + unsigned int uc = str[i].unicode(); + if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) { + uint low = str[i+1].unicode(); + if (low >= 0xdc00 && low < 0xe000) { + uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; + ++i; + } + } + return uc; +} + +QFontEngineQPA::QFontEngineQPA(const QFontDef &def, const QByteArray &data) + : fontData(reinterpret_cast<const uchar *>(data.constData())), dataSize(data.size()) +{ + fontDef = def; + cache_cost = 100; + externalCMap = 0; + cmapOffset = 0; + cmapSize = 0; + glyphMapOffset = 0; + glyphMapEntries = 0; + glyphDataOffset = 0; + glyphDataSize = 0; + kerning_pairs_loaded = false; + readOnly = true; + +#if defined(DEBUG_FONTENGINE) + qDebug() << "QFontEngineQPA::QFontEngineQPA( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ')'; +#endif + + if (!verifyHeader(fontData, dataSize)) { +#if defined(DEBUG_FONTENGINE) + qDebug() << "verifyHeader failed!"; +#endif + return; + } + + const Header *header = reinterpret_cast<const Header *>(fontData); + + readOnly = (header->lock == 0xffffffff); + + const uchar *imgData = fontData + sizeof(Header) + qFromBigEndian<quint16>(header->dataSize); + const uchar *endPtr = fontData + dataSize; + while (imgData <= endPtr - 8) { + quint16 blockTag = readValue<quint16>(imgData); + imgData += 2; // skip padding + quint32 blockSize = readValue<quint32>(imgData); + + if (blockTag == CMapBlock) { + cmapOffset = imgData - fontData; + cmapSize = blockSize; + } else if (blockTag == GMapBlock) { + glyphMapOffset = imgData - fontData; + glyphMapEntries = blockSize / 4; + } else if (blockTag == GlyphBlock) { + glyphDataOffset = imgData - fontData; + glyphDataSize = blockSize; + } + + imgData += blockSize; + } + + face_id.filename = QFile::encodeName(extractHeaderField(fontData, Tag_FileName).toString()); + face_id.index = extractHeaderField(fontData, Tag_FileIndex).toInt(); + + // get the real cmap + if (cmapOffset) { + int tableSize = cmapSize; + const uchar *cmapPtr = getCMap(fontData + cmapOffset, tableSize, &symbol, &cmapSize); + if (cmapPtr) + cmapOffset = cmapPtr - fontData; + else + cmapOffset = 0; + } else if (externalCMap) { + int tableSize = cmapSize; + externalCMap = getCMap(externalCMap, tableSize, &symbol, &cmapSize); + } + + // verify all the positions in the glyphMap + if (glyphMapOffset) { + const quint32 *gmapPtr = reinterpret_cast<const quint32 *>(fontData + glyphMapOffset); + for (uint i = 0; i < glyphMapEntries; ++i) { + quint32 glyphDataPos = qFromBigEndian<quint32>(gmapPtr[i]); + if (glyphDataPos == 0xffffffff) + continue; + if (glyphDataPos >= glyphDataSize) { + // error + glyphMapOffset = 0; + glyphMapEntries = 0; + break; + } + } + } + +#if defined(DEBUG_FONTENGINE) + if (!isValid()) + qDebug() << "fontData" << fontData << "dataSize" << dataSize + << "externalCMap" << externalCMap << "cmapOffset" << cmapOffset + << "glyphMapOffset" << glyphMapOffset << "glyphDataOffset" << glyphDataOffset + << "fd" << fd << "glyphDataSize" << glyphDataSize; +#endif +} + +QFontEngineQPA::~QFontEngineQPA() +{ +} + +bool QFontEngineQPA::getSfntTableData(uint tag, uchar *buffer, uint *length) const +{ + Q_UNUSED(tag); + Q_UNUSED(buffer); + *length = 0; + return false; +} + +bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const +{ + if (*nglyphs < len) { + *nglyphs = len; + return false; + } + +#if defined(DEBUG_FONTENGINE) + QSet<QChar> seenGlyphs; +#endif + + const uchar *cmap = externalCMap ? externalCMap : (fontData + cmapOffset); + + bool mirrored = flags & QTextEngine::RightToLeft; + int glyph_pos = 0; + if (symbol) { + for (int i = 0; i < len; ++i) { + unsigned int uc = getChar(str, i, len); + if (mirrored) + uc = QChar::mirroredChar(uc); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); + if(!glyphs->glyphs[glyph_pos] && uc < 0x100) + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); + ++glyph_pos; + } + } else { + for (int i = 0; i < len; ++i) { + unsigned int uc = getChar(str, i, len); + if (mirrored) + uc = QChar::mirroredChar(uc); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); +#if 0 && defined(DEBUG_FONTENGINE) + QChar c(uc); + if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c)) + qDebug() << "glyph for character" << c << '/' << hex << uc << "is" << dec << glyphs[glyph_pos].glyph; + + seenGlyphs.insert(c); +#endif + ++glyph_pos; + } + } + + *nglyphs = glyph_pos; + glyphs->numGlyphs = glyph_pos; + recalcAdvances(glyphs, flags); + return true; +} + +void QFontEngineQPA::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags) const +{ + for (int i = 0; i < glyphs->numGlyphs; ++i) { + const Glyph *g = findGlyph(glyphs->glyphs[i]); + if (!g) { + glyphs->glyphs[i] = 0; + continue; + } + glyphs->advances_x[i] = g->advance; + glyphs->advances_y[i] = 0; + } +} + +QImage QFontEngineQPA::alphaMapForGlyph(glyph_t g) +{ + const Glyph *glyph = findGlyph(g); + if (!glyph) + return QImage(); + + const uchar *bits = ((const uchar *) glyph) + sizeof(Glyph); + + QImage image(bits,glyph->width, glyph->height, glyph->bytesPerLine, QImage::Format_Indexed8); + + return image; +} + +void QFontEngineQPA::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) +{ + addBitmapFontToPath(x, y, glyphs, path, flags); +} + +glyph_metrics_t QFontEngineQPA::boundingBox(const QGlyphLayout &glyphs) +{ + glyph_metrics_t overall; + // initialize with line height, we get the same behaviour on all platforms + overall.y = -ascent(); + overall.height = ascent() + descent() + 1; + + QFixed ymax = 0; + QFixed xmax = 0; + for (int i = 0; i < glyphs.numGlyphs; i++) { + const Glyph *g = findGlyph(glyphs.glyphs[i]); + if (!g) + continue; + + QFixed x = overall.xoff + glyphs.offsets[i].x + g->x; + QFixed y = overall.yoff + glyphs.offsets[i].y + g->y; + overall.x = qMin(overall.x, x); + overall.y = qMin(overall.y, y); + xmax = qMax(xmax, x + g->width); + ymax = qMax(ymax, y + g->height); + overall.xoff += g->advance; + } + overall.height = qMax(overall.height, ymax - overall.y); + overall.width = xmax - overall.x; + + return overall; +} + +glyph_metrics_t QFontEngineQPA::boundingBox(glyph_t glyph) +{ + glyph_metrics_t overall; + const Glyph *g = findGlyph(glyph); + if (!g) + return overall; + overall.x = g->x; + overall.y = g->y; + overall.width = g->width; + overall.height = g->height; + overall.xoff = g->advance; + return overall; +} + +QFixed QFontEngineQPA::ascent() const +{ + return QFixed::fromReal(extractHeaderField(fontData, Tag_Ascent).value<qreal>()); +} + +QFixed QFontEngineQPA::descent() const +{ + return QFixed::fromReal(extractHeaderField(fontData, Tag_Descent).value<qreal>()); +} + +QFixed QFontEngineQPA::leading() const +{ + return QFixed::fromReal(extractHeaderField(fontData, Tag_Leading).value<qreal>()); +} + +qreal QFontEngineQPA::maxCharWidth() const +{ + return extractHeaderField(fontData, Tag_MaxCharWidth).value<qreal>(); +} + +qreal QFontEngineQPA::minLeftBearing() const +{ + return extractHeaderField(fontData, Tag_MinLeftBearing).value<qreal>(); +} + +qreal QFontEngineQPA::minRightBearing() const +{ + return extractHeaderField(fontData, Tag_MinRightBearing).value<qreal>(); +} + +QFixed QFontEngineQPA::underlinePosition() const +{ + return QFixed::fromReal(extractHeaderField(fontData, Tag_UnderlinePosition).value<qreal>()); +} + +QFixed QFontEngineQPA::lineThickness() const +{ + return QFixed::fromReal(extractHeaderField(fontData, Tag_LineThickness).value<qreal>()); +} + +QFontEngine::Type QFontEngineQPA::type() const +{ + return QFontEngine::QPF2; +} + +bool QFontEngineQPA::canRender(const QChar *string, int len) +{ + const uchar *cmap = externalCMap ? externalCMap : (fontData + cmapOffset); + + if (symbol) { + for (int i = 0; i < len; ++i) { + unsigned int uc = getChar(string, i, len); + glyph_t g = getTrueTypeGlyphIndex(cmap, uc); + if(!g && uc < 0x100) + g = getTrueTypeGlyphIndex(cmap, uc + 0xf000); + if (!g) + return false; + } + } else { + for (int i = 0; i < len; ++i) { + unsigned int uc = getChar(string, i, len); + if (!getTrueTypeGlyphIndex(cmap, uc)) + return false; + } + } + return true; +} + +bool QFontEngineQPA::isValid() const +{ + return fontData && dataSize && (cmapOffset || externalCMap) + && glyphMapOffset && glyphDataOffset && glyphDataSize > 0; +} + +void QPAGenerator::generate() +{ + writeHeader(); + writeGMap(); + writeBlock(QFontEngineQPA::GlyphBlock, QByteArray()); + + dev->seek(4); // position of header.lock + writeUInt32(0); +} + +void QPAGenerator::writeHeader() +{ + QFontEngineQPA::Header header; + + header.magic[0] = 'Q'; + header.magic[1] = 'P'; + header.magic[2] = 'F'; + header.magic[3] = '2'; + header.lock = 1; + header.majorVersion = QFontEngineQPA::CurrentMajorVersion; + header.minorVersion = QFontEngineQPA::CurrentMinorVersion; + header.dataSize = 0; + dev->write((const char *)&header, sizeof(header)); + + writeTaggedString(QFontEngineQPA::Tag_FontName, fe->fontDef.family.toUtf8()); + + QFontEngine::FaceId face = fe->faceId(); + writeTaggedString(QFontEngineQPA::Tag_FileName, face.filename); + writeTaggedUInt32(QFontEngineQPA::Tag_FileIndex, face.index); + + { + uchar data[4]; + uint len = 4; + bool ok = fe->getSfntTableData(MAKE_TAG('h', 'e', 'a', 'd'), data, &len); + if (ok) { + const quint32 revision = qFromBigEndian<quint32>(data); + writeTaggedUInt32(QFontEngineQPA::Tag_FontRevision, revision); + } + } + + writeTaggedQFixed(QFontEngineQPA::Tag_Ascent, fe->ascent()); + writeTaggedQFixed(QFontEngineQPA::Tag_Descent, fe->descent()); + writeTaggedQFixed(QFontEngineQPA::Tag_Leading, fe->leading()); + writeTaggedQFixed(QFontEngineQPA::Tag_XHeight, fe->xHeight()); + writeTaggedQFixed(QFontEngineQPA::Tag_AverageCharWidth, fe->averageCharWidth()); + writeTaggedQFixed(QFontEngineQPA::Tag_MaxCharWidth, QFixed::fromReal(fe->maxCharWidth())); + writeTaggedQFixed(QFontEngineQPA::Tag_LineThickness, fe->lineThickness()); + writeTaggedQFixed(QFontEngineQPA::Tag_MinLeftBearing, QFixed::fromReal(fe->minLeftBearing())); + writeTaggedQFixed(QFontEngineQPA::Tag_MinRightBearing, QFixed::fromReal(fe->minRightBearing())); + writeTaggedQFixed(QFontEngineQPA::Tag_UnderlinePosition, fe->underlinePosition()); + writeTaggedUInt8(QFontEngineQPA::Tag_PixelSize, fe->fontDef.pixelSize); + writeTaggedUInt8(QFontEngineQPA::Tag_Weight, fe->fontDef.weight); + writeTaggedUInt8(QFontEngineQPA::Tag_Style, fe->fontDef.style); + + writeTaggedUInt8(QFontEngineQPA::Tag_GlyphFormat, QFontEngineQPA::AlphamapGlyphs); + + writeTaggedString(QFontEngineQPA::Tag_EndOfHeader, QByteArray()); + align4(); + + const quint64 size = dev->pos(); + header.dataSize = qToBigEndian<quint16>(size - sizeof(header)); + dev->seek(0); + dev->write((const char *)&header, sizeof(header)); + dev->seek(size); +} + +void QPAGenerator::writeGMap() +{ + const quint16 glyphCount = fe->glyphCount(); + + writeUInt16(QFontEngineQPA::GMapBlock); + writeUInt16(0); // padding + writeUInt32(glyphCount * 4); + + QByteArray &buffer = dev->buffer(); + const int numBytes = glyphCount * sizeof(quint32); + qint64 pos = buffer.size(); + buffer.resize(pos + numBytes); + qMemSet(buffer.data() + pos, 0xff, numBytes); + dev->seek(pos + numBytes); +} + +void QPAGenerator::writeBlock(QFontEngineQPA::BlockTag tag, const QByteArray &data) +{ + writeUInt16(tag); + writeUInt16(0); // padding + const int padSize = ((data.size() + 3) / 4) * 4 - data.size(); + writeUInt32(data.size() + padSize); + dev->write(data); + for (int i = 0; i < padSize; ++i) + writeUInt8(0); +} + +void QPAGenerator::writeTaggedString(QFontEngineQPA::HeaderTag tag, const QByteArray &string) +{ + writeUInt16(tag); + writeUInt16(string.length()); + dev->write(string); +} + +void QPAGenerator::writeTaggedUInt32(QFontEngineQPA::HeaderTag tag, quint32 value) +{ + writeUInt16(tag); + writeUInt16(sizeof(value)); + writeUInt32(value); +} + +void QPAGenerator::writeTaggedUInt8(QFontEngineQPA::HeaderTag tag, quint8 value) +{ + writeUInt16(tag); + writeUInt16(sizeof(value)); + writeUInt8(value); +} + +void QPAGenerator::writeTaggedQFixed(QFontEngineQPA::HeaderTag tag, QFixed value) +{ + writeUInt16(tag); + writeUInt16(sizeof(quint32)); + writeUInt32(value.value()); +} + + +/* + Creates a new multi QPA engine. + + This function takes ownership of the QFontEngine, increasing it's refcount. +*/ +QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script, const QStringList &fallbacks) + : QFontEngineMulti(fallbacks.size() + 1), + fallbackFamilies(fallbacks), script(_script) +{ + engines[0] = fe; + fe->ref.ref(); + fontDef = engines[0]->fontDef; +} + +void QFontEngineMultiQPA::loadEngine(int at) +{ + Q_ASSERT(at < engines.size()); + Q_ASSERT(engines.at(at) == 0); + + QFontDef request = fontDef; + request.styleStrategy |= QFont::NoFontMerging; + request.family = fallbackFamilies.at(at-1); + engines[at] = QFontDatabase::findFont(script, + /*fontprivate*/0, + request); + Q_ASSERT(engines[at]); + engines[at]->ref.ref(); + engines[at]->fontDef = request; +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_qpa_p.h b/src/gui/text/qfontengine_qpa_p.h new file mode 100644 index 0000000..467fca6 --- /dev/null +++ b/src/gui/text/qfontengine_qpa_p.h @@ -0,0 +1,262 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QFONTENGINE_QPA_P_H +#define QFONTENGINE_QPA_P_H + +// +// 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. +// +#include <QtCore/qconfig.h> +#include <QtCore/qglobal.h> +#include <QtCore/qendian.h> +#include <QtCore/QBuffer> + +#include "qfontengine_p.h" + +#include <QtCore/QFile> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QFontEngine; +class QFreetypeFace; +class QBuffer; + +class Q_GUI_EXPORT QFontEngineQPA : public QFontEngine +{ +public: + // if you add new tags please make sure to update the tables in + // qpfutil.cpp and tools/makeqpf/qpf2.cpp + enum HeaderTag { + Tag_FontName, // 0 string + Tag_FileName, // 1 string + Tag_FileIndex, // 2 quint32 + Tag_FontRevision, // 3 quint32 + Tag_FreeText, // 4 string + Tag_Ascent, // 5 QFixed + Tag_Descent, // 6 QFixed + Tag_Leading, // 7 QFixed + Tag_XHeight, // 8 QFixed + Tag_AverageCharWidth, // 9 QFixed + Tag_MaxCharWidth, // 10 QFixed + Tag_LineThickness, // 11 QFixed + Tag_MinLeftBearing, // 12 QFixed + Tag_MinRightBearing, // 13 QFixed + Tag_UnderlinePosition, // 14 QFixed + Tag_GlyphFormat, // 15 quint8 + Tag_PixelSize, // 16 quint8 + Tag_Weight, // 17 quint8 + Tag_Style, // 18 quint8 + Tag_EndOfHeader, // 19 string + Tag_WritingSystems, // 20 bitfield + + NumTags + }; + + enum TagType { + StringType, + FixedType, + UInt8Type, + UInt32Type, + BitFieldType + }; + + struct Tag + { + quint16 tag; + quint16 size; + }; + + enum GlyphFormat { + BitmapGlyphs = 1, + AlphamapGlyphs = 8 + }; + + enum { + CurrentMajorVersion = 2, + CurrentMinorVersion = 0 + }; + + // The CMap is identical to the TrueType CMap table format + // The GMap table is a normal array with the total number of + // covered glyphs in the TrueType font + enum BlockTag { + CMapBlock, + GMapBlock, + GlyphBlock + }; + + struct Q_PACKED Header + { + char magic[4]; // 'QPF2' + quint32 lock; // values: 0 = unlocked, 0xffffffff = read-only, otherwise qws client id of locking process + quint8 majorVersion; + quint8 minorVersion; + quint16 dataSize; + }; + + struct Q_PACKED Block + { + quint16 tag; + quint16 pad; + quint32 dataSize; + }; + + struct Q_PACKED Glyph + { + quint8 width; + quint8 height; + quint8 bytesPerLine; + qint8 x; + qint8 y; + qint8 advance; + }; + + QFontEngineQPA(const QFontDef &def, const QByteArray &data); + ~QFontEngineQPA(); + + FaceId faceId() const { return face_id; } + bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; + + bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; + void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const; + + void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags); + QImage alphaMapForGlyph(glyph_t t); + + glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); + glyph_metrics_t boundingBox(glyph_t glyph); + + QFixed ascent() const; + QFixed descent() const; + QFixed leading() const; + qreal maxCharWidth() const; + qreal minLeftBearing() const; + qreal minRightBearing() const; + QFixed underlinePosition() const; + QFixed lineThickness() const; + + Type type() const; + + bool canRender(const QChar *string, int len); + inline const char *name() const { return "QPF2"; } + + virtual int glyphCount() const { return glyphMapEntries; } + + bool isValid() const; + + const Glyph *findGlyph(glyph_t g) const; + + static bool verifyHeader(const uchar *data, int size); + static QVariant extractHeaderField(const uchar *data, HeaderTag tag); + +private: + + const uchar *fontData; + int dataSize; + const uchar *externalCMap; + quint32 cmapOffset; + int cmapSize; + quint32 glyphMapOffset; + quint32 glyphMapEntries; + quint32 glyphDataOffset; + quint32 glyphDataSize; + QString internalFileName; + QString encodedFileName; + bool readOnly; + + FaceId face_id; + QByteArray freetypeCMapTable; + mutable bool kerning_pairs_loaded; +}; + +struct QPAGenerator +{ + QPAGenerator(QBuffer *device, QFontEngine *engine) + : dev(device), fe(engine) {} + + void generate(); + void writeHeader(); + void writeGMap(); + void writeBlock(QFontEngineQPA::BlockTag tag, const QByteArray &data); + + void writeTaggedString(QFontEngineQPA::HeaderTag tag, const QByteArray &string); + void writeTaggedUInt32(QFontEngineQPA::HeaderTag tag, quint32 value); + void writeTaggedUInt8(QFontEngineQPA::HeaderTag tag, quint8 value); + void writeTaggedQFixed(QFontEngineQPA::HeaderTag tag, QFixed value); + + void writeUInt16(quint16 value) { value = qToBigEndian(value); dev->write((const char *)&value, sizeof(value)); } + void writeUInt32(quint32 value) { value = qToBigEndian(value); dev->write((const char *)&value, sizeof(value)); } + void writeUInt8(quint8 value) { dev->write((const char *)&value, sizeof(value)); } + void writeInt8(qint8 value) { dev->write((const char *)&value, sizeof(value)); } + + void align4() { while (dev->pos() & 3) { dev->putChar('\0'); } } + + QBuffer *dev; + QFontEngine *fe; +}; + +class QFontEngineMultiQPA : public QFontEngineMulti +{ +public: + QFontEngineMultiQPA(QFontEngine *fe, int script, const QStringList &fallbacks); + + void loadEngine(int at); + +private: + QStringList fallbackFamilies; + int script; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QFONTENGINE_QPA_P_H diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp index bf30e1c..134c1ed 100644 --- a/src/gui/text/qfontengine_s60.cpp +++ b/src/gui/text/qfontengine_s60.cpp @@ -123,7 +123,8 @@ QByteArray QSymbianTypeFaceExtras::getSfntTable(uint tag) const Q_ASSERT(m_trueTypeExtension->HasTrueTypeTable(tag)); TInt error = KErrNone; TInt tableByteLength = 0; - TAny *table = q_check_ptr(m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength)); + TAny *table = m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength); + Q_CHECK_PTR(table); QByteArray result(static_cast<const char*>(table), tableByteLength); m_trueTypeExtension->ReleaseTrueTypeTable(table); return result; @@ -137,8 +138,8 @@ bool QSymbianTypeFaceExtras::getSfntTableData(uint tag, uchar *buffer, uint *len bool result = true; TInt error = KErrNone; TInt tableByteLength; - TAny *table = - q_check_ptr(m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength)); + TAny *table = m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength); + Q_CHECK_PTR(table); if (error != KErrNone) { return false; diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp index 5f25752..cf4fbda 100644 --- a/src/gui/text/qfontengine_win.cpp +++ b/src/gui/text/qfontengine_win.cpp @@ -1251,7 +1251,7 @@ QImage QFontEngineWin::alphaMapForGlyph(glyph_t glyph, const QTransform &xform) #define SPI_GETFONTSMOOTHINGCONTRAST 0x200C #define SPI_SETFONTSMOOTHINGCONTRAST 0x200D -QImage QFontEngineWin::alphaRGBMapForGlyph(glyph_t glyph, int margin, const QTransform &t) +QImage QFontEngineWin::alphaRGBMapForGlyph(glyph_t glyph, QFixed, int margin, const QTransform &t) { HFONT font = hfont; diff --git a/src/gui/text/qfontengine_win_p.h b/src/gui/text/qfontengine_win_p.h index 68b53b5..d86f42e 100644 --- a/src/gui/text/qfontengine_win_p.h +++ b/src/gui/text/qfontengine_win_p.h @@ -104,7 +104,7 @@ public: virtual QImage alphaMapForGlyph(glyph_t t) { return alphaMapForGlyph(t, QTransform()); } virtual QImage alphaMapForGlyph(glyph_t, const QTransform &xform); - virtual QImage alphaRGBMapForGlyph(glyph_t t, int margin, const QTransform &xform); + virtual QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform); #ifndef Q_CC_MINGW virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0); diff --git a/src/gui/text/qfontengine_x11.cpp b/src/gui/text/qfontengine_x11.cpp index b7e4be2..aee21f6 100644 --- a/src/gui/text/qfontengine_x11.cpp +++ b/src/gui/text/qfontengine_x11.cpp @@ -992,7 +992,7 @@ QFontEngineX11FT::QFontEngineX11FT(FcPattern *pattern, const QFontDef &fd, int s face_id.filename = file_name; face_id.index = face_index; - canUploadGlyphsToServer = qApp->thread() == QThread::currentThread(); + canUploadGlyphsToServer = QApplication::testAttribute(Qt::AA_X11InitThreads) || (qApp->thread() == QThread::currentThread()); subpixelType = Subpixel_None; if (antialias) { diff --git a/src/gui/text/qfontengineglyphcache_p.h b/src/gui/text/qfontengineglyphcache_p.h index 7b82b46..eba16f7 100644 --- a/src/gui/text/qfontengineglyphcache_p.h +++ b/src/gui/text/qfontengineglyphcache_p.h @@ -72,7 +72,7 @@ QT_BEGIN_NAMESPACE -class QFontEngineGlyphCache +class QFontEngineGlyphCache: public QSharedData { public: enum Type { diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp index d02e841..f2591ce 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -443,6 +443,21 @@ bool QFontMetrics::inFont(QChar ch) const } /*! + Returns true if the character encoded in UCS-4/UTF-32 is a valid + character in the font; otherwise returns false. +*/ +bool QFontMetrics::inFontUcs4(uint ucs4) const +{ + const int script = QUnicodeTables::script(ucs4); + QFontEngine *engine = d->engineForScript(script); + Q_ASSERT(engine != 0); + if (engine->type() == QFontEngine::Box) + return false; + QString utf16 = QString::fromUcs4(&ucs4, 1); + return engine->canRender(utf16.data(), utf16.length()); +} + +/*! Returns the left bearing of character \a ch in the font. The left bearing is the right-ward distance of the left-most pixel @@ -1315,6 +1330,21 @@ bool QFontMetricsF::inFont(QChar ch) const } /*! + Returns true if the character encoded in UCS-4/UTF-32 is a valid + character in the font; otherwise returns false. +*/ +bool QFontMetricsF::inFontUcs4(uint ucs4) const +{ + const int script = QUnicodeTables::script(ucs4); + QFontEngine *engine = d->engineForScript(script); + Q_ASSERT(engine != 0); + if (engine->type() == QFontEngine::Box) + return false; + QString utf16 = QString::fromUcs4(&ucs4, 1); + return engine->canRender(utf16.data(), utf16.length()); +} + +/*! Returns the left bearing of character \a ch in the font. The left bearing is the right-ward distance of the left-most pixel @@ -1779,7 +1809,7 @@ qreal QFontMetricsF::lineWidth() const Use the boundingRect() function in combination with QString::left() instead. - + \oldcode QRect rect = boundingRect(text, len); \newcode diff --git a/src/gui/text/qfontmetrics.h b/src/gui/text/qfontmetrics.h index 2518b54..5a79429 100644 --- a/src/gui/text/qfontmetrics.h +++ b/src/gui/text/qfontmetrics.h @@ -71,6 +71,10 @@ public: ~QFontMetrics(); QFontMetrics &operator=(const QFontMetrics &); +#ifdef Q_COMPILER_RVALUE_REFS + inline QFontMetrics &operator=(QFontMetrics &&other) + { qSwap(d, other.d); return *this; } +#endif int ascent() const; int descent() const; @@ -85,6 +89,7 @@ public: int averageCharWidth() const; bool inFont(QChar) const; + bool inFontUcs4(uint ucs4) const; int leftBearing(QChar) const; int rightBearing(QChar) const; @@ -148,7 +153,10 @@ public: QFontMetricsF &operator=(const QFontMetricsF &); QFontMetricsF &operator=(const QFontMetrics &); - +#ifdef Q_COMPILER_RVALUE_REFS + inline QFontMetricsF &operator=(QFontMetricsF &&other) + { qSwap(d, other.d); return *this; } +#endif qreal ascent() const; qreal descent() const; qreal height() const; @@ -162,6 +170,7 @@ public: qreal averageCharWidth() const; bool inFont(QChar) const; + bool inFontUcs4(uint ucs4) const; qreal leftBearing(QChar) const; qreal rightBearing(QChar) const; diff --git a/src/gui/text/qglyphs.cpp b/src/gui/text/qglyphs.cpp new file mode 100644 index 0000000..2447752 --- /dev/null +++ b/src/gui/text/qglyphs.cpp @@ -0,0 +1,240 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qglyphs.h" +#include "qglyphs_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QGlyphs + \brief the QGlyphs class provides direct access to the internal glyphs in a font + \since 4.8 + + \ingroup text + \mainclass + + When Qt displays a string of text encoded in Unicode, it will first convert the Unicode points + into a list of glyph indexes and a list of positions based on one or more fonts. The Unicode + representation of the text and the QFont object will in this case serve as a convenient + abstraction that hides the details of what actually takes place when displaying the text + on-screen. For instance, by the time the text actually reaches the screen, it may be represented + by a set of fonts in addition to the one specified by the user, e.g. in case the originally + selected font did not support all the writing systems contained in the text. + + Under certain circumstances, it can be useful as an application developer to have more low-level + control over which glyphs in a specific font are drawn to the screen. This could for instance + be the case in applications that use an external font engine and text shaper together with Qt. + QGlyphs provides an interface to the raw data needed to get text on the screen. It + contains a list of glyph indexes, a position for each glyph and a font. + + It is the user's responsibility to ensure that the selected font actually contains the + provided glyph indexes. + + QTextLayout::glyphs() can be used to convert unicode encoded text into a list of QGlyphs + objects, and QPainter::drawGlyphs() can be used to draw the glyphs. +*/ + + +/*! + Constructs an empty QGlyphs object. +*/ +QGlyphs::QGlyphs() : d(new QGlyphsPrivate) +{ +} + +/*! + Constructs a QGlyphs object which is a copy of \a other. +*/ +QGlyphs::QGlyphs(const QGlyphs &other) +{ + d = other.d; +} + +/*! + Destroys the QGlyphs. +*/ +QGlyphs::~QGlyphs() +{ + // Required for QExplicitlySharedDataPointer +} + +/*! + \internal +*/ +void QGlyphs::detach() +{ + if (d->ref != 1) + d.detach(); +} + +/*! + Assigns \a other to this QGlyphs object. +*/ +QGlyphs &QGlyphs::operator=(const QGlyphs &other) +{ + d = other.d; + return *this; +} + +/*! + Compares \a other to this QGlyphs object. Returns true if the list of glyph indexes, + the list of positions and the font are all equal, otherwise returns false. +*/ +bool QGlyphs::operator==(const QGlyphs &other) const +{ + return ((d == other.d) + || (d->glyphIndexes == other.d->glyphIndexes + && d->glyphPositions == other.d->glyphPositions + && d->font == other.d->font)); +} + +/*! + Compares \a other to this QGlyphs object. Returns true if any of the list of glyph + indexes, the list of positions or the font are different, otherwise returns false. +*/ +bool QGlyphs::operator!=(const QGlyphs &other) const +{ + return !(*this == other); +} + +/*! + \internal + + Adds together the lists of glyph indexes and positions in \a other and this QGlyphs + object and returns the result. The font in the returned QGlyphs will be the same as in + this QGlyphs object. +*/ +QGlyphs QGlyphs::operator+(const QGlyphs &other) const +{ + QGlyphs ret(*this); + ret += other; + return ret; +} + +/*! + \internal + + Appends the glyph indexes and positions in \a other to this QGlyphs object and returns + a reference to the current object. +*/ +QGlyphs &QGlyphs::operator+=(const QGlyphs &other) +{ + detach(); + + d->glyphIndexes += other.d->glyphIndexes; + d->glyphPositions += other.d->glyphPositions; + + return *this; +} + +/*! + Returns the font selected for this QGlyphs object. + + \sa setFont() +*/ +QFont QGlyphs::font() const +{ + return d->font; +} + +/*! + Sets the font in which to look up the glyph indexes to \a font. This must be an explicitly + resolvable font which defines glyphs for the specified glyph indexes. + + \sa font(), setGlyphIndexes() +*/ +void QGlyphs::setFont(const QFont &font) +{ + detach(); + d->font = font; +} + +/*! + Returns the glyph indexes for this QGlyphs object. + + \sa setGlyphIndexes(), setPositions() +*/ +QVector<quint32> QGlyphs::glyphIndexes() const +{ + return d->glyphIndexes; +} + +/*! + Set the glyph indexes for this QGlyphs object to \a glyphIndexes. The glyph indexes must + be valid for the selected font. +*/ +void QGlyphs::setGlyphIndexes(const QVector<quint32> &glyphIndexes) +{ + detach(); + d->glyphIndexes = glyphIndexes; +} + +/*! + Returns the position of the edge of the baseline for each glyph in this set of glyph indexes. +*/ +QVector<QPointF> QGlyphs::positions() const +{ + return d->glyphPositions; +} + +/*! + Sets the positions of the edge of the baseline for each glyph in this set of glyph indexes to + \a positions. +*/ +void QGlyphs::setPositions(const QVector<QPointF> &positions) +{ + detach(); + d->glyphPositions = positions; +} + +/*! + Clears all data in the QGlyphs object. +*/ +void QGlyphs::clear() +{ + detach(); + d->glyphPositions = QVector<QPointF>(); + d->glyphIndexes = QVector<quint32>(); + d->font = QFont(); +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qglyphs.h b/src/gui/text/qglyphs.h new file mode 100644 index 0000000..282ecb4 --- /dev/null +++ b/src/gui/text/qglyphs.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QGLYPHS_H +#define QGLYPHS_H + +#include <QtCore/qsharedpointer.h> +#include <QtCore/qvector.h> +#include <QtCore/qpoint.h> +#include <QtGui/qfont.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QGlyphsPrivate; +class Q_GUI_EXPORT QGlyphs +{ +public: + QGlyphs(); + QGlyphs(const QGlyphs &other); + ~QGlyphs(); + + QFont font() const; + void setFont(const QFont &font); + + QVector<quint32> glyphIndexes() const; + void setGlyphIndexes(const QVector<quint32> &glyphIndexes); + + QVector<QPointF> positions() const; + void setPositions(const QVector<QPointF> &positions); + + void clear(); + + QGlyphs &operator=(const QGlyphs &other); + bool operator==(const QGlyphs &other) const; + bool operator!=(const QGlyphs &other) const; + +private: + friend class QGlyphsPrivate; + friend class QTextLine; + + QGlyphs operator+(const QGlyphs &other) const; + QGlyphs &operator+=(const QGlyphs &other); + + void detach(); + QExplicitlySharedDataPointer<QGlyphsPrivate> d; + +}; + +QT_END_NAMESPACE + +QT_END_HEADER + + +#endif // QGLYPHS_H diff --git a/src/gui/text/qglyphs_p.h b/src/gui/text/qglyphs_p.h new file mode 100644 index 0000000..c39f5d0 --- /dev/null +++ b/src/gui/text/qglyphs_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QGLYPHS_P_H +#define QGLYPHS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#include <qfont.h> +#include "qglyphs.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGlyphsPrivate: public QSharedData +{ +public: + QGlyphsPrivate() + { + } + + QGlyphsPrivate(const QGlyphsPrivate &other) + : QSharedData(other), glyphIndexes(other.glyphIndexes), glyphPositions(other.glyphPositions), font(other.font) + { + } + + QVector<quint32> glyphIndexes; + QVector<QPointF> glyphPositions; + QFont font; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGLYPHS_P_H diff --git a/src/gui/text/qpfutil.cpp b/src/gui/text/qpfutil.cpp index 376f49c..7f8c58e 100644 --- a/src/gui/text/qpfutil.cpp +++ b/src/gui/text/qpfutil.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -static QFontEngineQPF::TagType tagTypes[QFontEngineQPF::NumTags] = { +static const QFontEngineQPF::TagType tagTypes[QFontEngineQPF::NumTags] = { QFontEngineQPF::StringType, // FontName QFontEngineQPF::StringType, // FileName QFontEngineQPF::UInt32Type, // FileIndex diff --git a/src/gui/text/qplatformfontdatabase_qpa.cpp b/src/gui/text/qplatformfontdatabase_qpa.cpp new file mode 100644 index 0000000..370c921 --- /dev/null +++ b/src/gui/text/qplatformfontdatabase_qpa.cpp @@ -0,0 +1,241 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qplatformfontdatabase_qpa.h" +#include <QtGui/private/qfontengine_p.h> +#include <QtGui/private/qfontengine_qpa_p.h> +#include <QtCore/QLibraryInfo> +#include <QtCore/QDir> + +QT_BEGIN_NAMESPACE + +extern void qt_registerFont(const QString &familyname, const QString &foundryname, int weight, + QFont::Style style, int stretch, bool antialiased,bool scalable, int pixelSize, + const QSupportedWritingSystems &writingSystems, void *hanlde); + +void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *handle) +{ + if (dataArray.size() == 0) + return; + + const uchar *data = reinterpret_cast<const uchar *>(dataArray.constData()); + if (QFontEngineQPA::verifyHeader(data, dataArray.size())) { + QString fontName = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_FontName).toString(); + int pixelSize = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_PixelSize).toInt(); + QVariant weight = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_Weight); + QVariant style = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_Style); + QByteArray writingSystemBits = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_WritingSystems).toByteArray(); + + if (!fontName.isEmpty() && pixelSize) { + int fontWeight = 50; + if (weight.type() == QVariant::Int || weight.type() == QVariant::UInt) + fontWeight = weight.toInt(); + + QFont::Style fontStyle = static_cast<QFont::Style>(style.toInt()); + + QSupportedWritingSystems writingSystems; + for (int i = 0; i < writingSystemBits.count(); ++i) { + uchar currentByte = writingSystemBits.at(i); + for (int j = 0; j < 8; ++j) { + if (currentByte & 1) + writingSystems.setSupported(QFontDatabase::WritingSystem(i * 8 + j)); + currentByte >>= 1; + } + } + + registerFont(fontName,QString(),fontWeight,fontStyle,100,true,false,pixelSize,writingSystems,handle); + } + } else { + qDebug() << "header verification of QPF2 font failed. maybe it is corrupt?"; + } +} + +void QPlatformFontDatabase::registerFont(const QString &familyname, const QString &foundryname, int weight, + QFont::Style style, int stretch, bool antialiased, bool scalable, int pixelSize, + const QSupportedWritingSystems &writingSystems, void *usrPtr) +{ + if (scalable) + pixelSize = 0; + qt_registerFont(familyname,foundryname,weight,style,stretch,antialiased,scalable,pixelSize,writingSystems,usrPtr); +} + +class QWritingSystemsPrivate +{ +public: + QWritingSystemsPrivate() + : ref(1) + , vector(QFontDatabase::WritingSystemsCount,false) + { + } + + QWritingSystemsPrivate(const QWritingSystemsPrivate *other) + : ref(1) + , vector(other->vector) + { + } + + QAtomicInt ref; + QVector<bool> vector; +}; + +QSupportedWritingSystems::QSupportedWritingSystems() +{ + d = new QWritingSystemsPrivate; +} + +QSupportedWritingSystems::QSupportedWritingSystems(const QSupportedWritingSystems &other) +{ + d = other.d; + d->ref.ref(); +} + +QSupportedWritingSystems &QSupportedWritingSystems::operator=(const QSupportedWritingSystems &other) +{ + if (d != other.d) { + other.d->ref.ref(); + if (!d->ref.deref()) + delete d; + d = other.d; + } + return *this; +} + +QSupportedWritingSystems::~QSupportedWritingSystems() +{ + if (!d->ref.deref()) + delete d; +} + +void QSupportedWritingSystems::detach() +{ + if (d->ref != 1) { + QWritingSystemsPrivate *newd = new QWritingSystemsPrivate(d); + if (!d->ref.deref()) + delete d; + d = newd; + } +} + +void QSupportedWritingSystems::setSupported(QFontDatabase::WritingSystem writingSystem, bool support) +{ + detach(); + d->vector[writingSystem] = support; +} + +bool QSupportedWritingSystems::supported(QFontDatabase::WritingSystem writingSystem) const +{ + return d->vector.at(writingSystem); +} + +void QPlatformFontDatabase::populateFontDatabase() +{ + QString fontpath = fontDir(); + + if(!QFile::exists(fontpath)) { + qFatal("QFontDatabase: Cannot find font directory %s - is Qt installed correctly?", + qPrintable(fontpath)); + } + + QDir dir(fontpath); + dir.setNameFilters(QStringList() << QLatin1String("*.qpf2")); + dir.refresh(); + for (int i = 0; i < int(dir.count()); ++i) { + const QByteArray fileName = QFile::encodeName(dir.absoluteFilePath(dir[i])); + QFile file(QString::fromLocal8Bit(fileName)); + if (file.open(QFile::ReadOnly)) { + const QByteArray fileData = file.readAll(); + QByteArray *fileDataPtr = new QByteArray(fileData); + registerQPF2Font(fileData, fileDataPtr); + } + } +} + +QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle) +{ + Q_UNUSED(script); + Q_UNUSED(handle); + QByteArray *fileDataPtr = static_cast<QByteArray *>(handle); + QFontEngineQPA *engine = new QFontEngineQPA(fontDef,*fileDataPtr); + qDebug() << fontDef.pixelSize << fontDef.weight << fontDef.style << fontDef.stretch << fontDef.styleHint << fontDef.styleStrategy << fontDef.family << script; + return engine; +} + +QStringList QPlatformFontDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const +{ + Q_UNUSED(family); + Q_UNUSED(style); + Q_UNUSED(script); + return QStringList(); +} + +/*! + Adds an application font. Returns a list of family names, or an empty list if the font could + not be added +*/ +QStringList QPlatformFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) +{ + Q_UNUSED(fontData); + Q_UNUSED(fileName); + + qWarning("This plugin does not support application fonts"); + return QStringList(); +} + +void QPlatformFontDatabase::releaseHandle(void *handle) +{ + QByteArray *fileDataPtr = static_cast<QByteArray *>(handle); + delete fileDataPtr; +} + +QString QPlatformFontDatabase::fontDir() const +{ + QString fontpath = QString::fromLocal8Bit(qgetenv("QT_QPA_FONTDIR")); + if (fontpath.isEmpty()) { +#ifndef QT_NO_SETTINGS + fontpath = QLibraryInfo::location(QLibraryInfo::LibrariesPath); + fontpath += QLatin1String("/fonts"); +#endif + } + + return fontpath; +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qplatformfontdatabase_qpa.h b/src/gui/text/qplatformfontdatabase_qpa.h new file mode 100644 index 0000000..75b0a18 --- /dev/null +++ b/src/gui/text/qplatformfontdatabase_qpa.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QPLATFORMFONTDATABASE_QPA_H +#define QPLATFORMFONTDATABASE_QPA_H + +#include <QtCore/qconfig.h> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QList> +#include <QtGui/QFontDatabase> +#include <QtGui/private/qfont_p.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QWritingSystemsPrivate; + +class Q_GUI_EXPORT QSupportedWritingSystems +{ +public: + + QSupportedWritingSystems(); + QSupportedWritingSystems(const QSupportedWritingSystems &other); + QSupportedWritingSystems &operator=(const QSupportedWritingSystems &other); + ~QSupportedWritingSystems(); + + void setSupported(QFontDatabase::WritingSystem, bool supported = true); + bool supported(QFontDatabase::WritingSystem) const; + +private: + void detach(); + + QWritingSystemsPrivate *d; + + friend Q_GUI_EXPORT bool operator==(const QSupportedWritingSystems &, const QSupportedWritingSystems &); + friend Q_GUI_EXPORT bool operator!=(const QSupportedWritingSystems &, const QSupportedWritingSystems &); +}; + +Q_GUI_EXPORT bool operator==(const QSupportedWritingSystems &, const QSupportedWritingSystems &); +Q_GUI_EXPORT bool operator!=(const QSupportedWritingSystems &, const QSupportedWritingSystems &); + +class QFontRequestPrivate; + +class Q_GUI_EXPORT QPlatformFontDatabase +{ +public: + virtual void populateFontDatabase(); + virtual QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle); + virtual QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const; + virtual QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); + virtual void releaseHandle(void *handle); + + virtual QString fontDir() const; + + //callback + static void registerQPF2Font(const QByteArray &dataArray, void *handle); + static void registerFont(const QString &familyname, const QString &foundryname, int weight, + QFont::Style style, int stetch, bool antialiased, bool scalable, int pixelSize, + const QSupportedWritingSystems &writingSystems, void *handle); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLATFORMFONTDATABASE_QPA_H diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index 7f2c4e9..d0f71ae 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -2894,7 +2894,7 @@ QAbstractTextDocumentLayout::PaintContext QTextControl::getPaintContext(QWidget if (widget) style = widget->style(); style->styleHint(QStyle::SH_TextControl_FocusIndicatorTextCharFormat, &opt, widget, &ret); - selection.format = qVariantValue<QTextFormat>(ret.variant).toCharFormat(); + selection.format = qvariant_cast<QTextFormat>(ret.variant).toCharFormat(); } else { QPalette::ColorGroup cg = d->hasFocus ? QPalette::Active : QPalette::Inactive; selection.format.setBackground(ctx.palette.brush(cg, QPalette::Highlight)); diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index c35069f..3aa6795 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -1983,6 +1983,8 @@ QVariant QTextDocument::loadResource(int type, const QUrl &name) if (fi.exists()) { resourceUrl = QUrl::fromLocalFile(fi.absolutePath() + QDir::separator()).resolved(name); + } else if (currentURL.isEmpty()) { + resourceUrl.setScheme(QLatin1String("file")); } } @@ -2600,14 +2602,40 @@ void QTextHtmlExporter::emitBlock(const QTextBlock &block) default: html += QLatin1String("<ul"); // ### should not happen } - html += QLatin1String(" style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px;"); + QString styleString = QString::fromLatin1("margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px;"); if (format.hasProperty(QTextFormat::ListIndent)) { - html += QLatin1String(" -qt-list-indent: "); - html += QString::number(format.indent()); - html += QLatin1Char(';'); + styleString += QLatin1String(" -qt-list-indent: "); + styleString += QString::number(format.indent()); + styleString += QLatin1Char(';'); + } + + if (format.hasProperty(QTextFormat::ListNumberPrefix)) { + QString numberPrefix = format.numberPrefix(); + numberPrefix.replace('"', "\\22"); + numberPrefix.replace('\'', "\\27"); // FIXME: There's a problem in the CSS parser the prevents this from being correctly restored + styleString += QLatin1String(" -qt-list-number-prefix: "); + styleString += QLatin1Char('\''); + styleString += numberPrefix; + styleString += QLatin1Char('\''); + styleString += QLatin1Char(';'); } + if (format.hasProperty(QTextFormat::ListNumberSuffix)) { + if (format.numberSuffix() != QLatin1String(".")) { // this is our default + QString numberSuffix = format.numberSuffix(); + numberSuffix.replace('"', "\\22"); + numberSuffix.replace('\'', "\\27"); // see above + styleString += QLatin1String(" -qt-list-number-suffix: "); + styleString += QLatin1Char('\''); + styleString += numberSuffix; + styleString += QLatin1Char('\''); + styleString += QLatin1Char(';'); + } + } + + html += QLatin1String(" style=\""); + html += styleString; html += QLatin1String("\">"); } diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp index 26346ca..e36a6f0 100644 --- a/src/gui/text/qtextdocumentfragment.cpp +++ b/src/gui/text/qtextdocumentfragment.cpp @@ -682,6 +682,10 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processSpecialNodes() QTextListFormat listFmt; listFmt.setStyle(style); + if (!currentNode->textListNumberPrefix.isNull()) + listFmt.setNumberPrefix(currentNode->textListNumberPrefix); + if (!currentNode->textListNumberSuffix.isNull()) + listFmt.setNumberSuffix(currentNode->textListNumberSuffix); ++indent; if (currentNode->hasCssListIndent) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 3bd6122..f4f2168 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1389,6 +1389,7 @@ void QTextEngine::invalidate() maxWidth = 0; if (specialData) specialData->resolvedFormatIndices.clear(); + feCache.reset(); } void QTextEngine::clearLineData() @@ -1780,6 +1781,13 @@ QFont QTextEngine::font(const QScriptItem &si) const return font; } +QTextEngine::FontEngineCache::FontEngineCache() +{ + reset(); +} + +//we cache the previous results of this function, as calling it numerous times with the same effective +//input is common (and hard to cache at a higher level) QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFixed *descent, QFixed *leading) const { QFontEngine *engine = 0; @@ -1788,28 +1796,47 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix QFont font = fnt; if (hasFormats()) { - QTextCharFormat f = format(&si); - font = f.font(); - - if (block.docHandle() && block.docHandle()->layout()) { - // Make sure we get the right dpi on printers - QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); - if (pdev) - font = QFont(font, pdev); + if (feCache.prevFontEngine && feCache.prevPosition == si.position && feCache.prevLength == length(&si) && feCache.prevScript == script) { + engine = feCache.prevFontEngine; + scaledEngine = feCache.prevScaledFontEngine; } else { - font = font.resolve(fnt); - } - engine = font.d->engineForScript(script); - QTextCharFormat::VerticalAlignment valign = f.verticalAlignment(); - if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) { - if (font.pointSize() != -1) - font.setPointSize((font.pointSize() * 2) / 3); - else - font.setPixelSize((font.pixelSize() * 2) / 3); - scaledEngine = font.d->engineForScript(script); + QTextCharFormat f = format(&si); + font = f.font(); + + if (block.docHandle() && block.docHandle()->layout()) { + // Make sure we get the right dpi on printers + QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); + if (pdev) + font = QFont(font, pdev); + } else { + font = font.resolve(fnt); + } + engine = font.d->engineForScript(script); + QTextCharFormat::VerticalAlignment valign = f.verticalAlignment(); + if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) { + if (font.pointSize() != -1) + font.setPointSize((font.pointSize() * 2) / 3); + else + font.setPixelSize((font.pixelSize() * 2) / 3); + scaledEngine = font.d->engineForScript(script); + } + feCache.prevFontEngine = engine; + feCache.prevScaledFontEngine = scaledEngine; + feCache.prevScript = script; + feCache.prevPosition = si.position; + feCache.prevLength = length(&si); } } else { - engine = font.d->engineForScript(script); + if (feCache.prevFontEngine && feCache.prevScript == script && feCache.prevPosition == -1) + engine = feCache.prevFontEngine; + else { + engine = font.d->engineForScript(script); + feCache.prevFontEngine = engine; + feCache.prevScript = script; + feCache.prevPosition = -1; + feCache.prevLength = -1; + feCache.prevScaledFontEngine = 0; + } } if (si.analysis.flags == QScriptAnalysis::SmallCaps) { @@ -2353,30 +2380,29 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int if (flags & Qt::TextShowMnemonic) { itemize(); + HB_CharAttributes *attributes = const_cast<HB_CharAttributes *>(this->attributes()); + if (!attributes) + return QString(); for (int i = 0; i < layoutData->items.size(); ++i) { QScriptItem &si = layoutData->items[i]; if (!si.num_glyphs) shape(i); - HB_CharAttributes *attributes = const_cast<HB_CharAttributes *>(this->attributes()); - if (!attributes) - return QString(); - unsigned short *logClusters = this->logClusters(&si); QGlyphLayout glyphs = shapedGlyphs(&si); const int end = si.position + length(&si); - for (int i = si.position; i < end - 1; ++i) + for (int i = si.position; i < end - 1; ++i) { if (layoutData->string.at(i) == QLatin1Char('&')) { const int gp = logClusters[i - si.position]; glyphs.attributes[gp].dontPrint = true; attributes[i + 1].charStop = false; attributes[i + 1].whiteSpace = false; attributes[i + 1].lineBreakType = HB_NoBreak; - if (i < end - 1 - && layoutData->string.at(i + 1) == QLatin1Char('&')) + if (layoutData->string.at(i + 1) == QLatin1Char('&')) ++i; } + } } } @@ -2438,7 +2464,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int if (mode == Qt::ElideRight) { QFixed currentWidth; - int pos = 0; + int pos; int nextBreak = 0; do { @@ -2458,7 +2484,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int return layoutData->string.left(pos) + ellipsisText; } else if (mode == Qt::ElideLeft) { QFixed currentWidth; - int pos = layoutData->string.length(); + int pos; int nextBreak = layoutData->string.length(); do { diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 4cbe81f..b5faf20 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -128,7 +128,7 @@ struct Q_AUTOTEST_EXPORT QScriptAnalysis TabOrObject = Tab, Object = 7 }; - unsigned short script : 8; + unsigned short script : 7; unsigned short bidiLevel : 6; // Unicode Bidi algorithm embedding level (0-61) unsigned short flags : 3; inline bool operator == (const QScriptAnalysis &other) const { @@ -385,7 +385,7 @@ struct Q_AUTOTEST_EXPORT QScriptLine QFixed textWidth; QFixed textAdvance; int from; - signed int length : 29; + signed int length : 28; mutable uint justified : 1; mutable uint gridfitted : 1; uint hasTrailingSpaces : 1; @@ -435,7 +435,7 @@ public: uint hasBidi : 1; uint layoutState : 2; uint memory_on_stack : 1; - bool haveCharAttributes; + uint haveCharAttributes : 1; QString string; bool reallocate(int totalGlyphs); }; @@ -556,6 +556,23 @@ public: mutable QScriptLineArray lines; + struct FontEngineCache { + FontEngineCache(); + mutable QFontEngine *prevFontEngine; + mutable QFontEngine *prevScaledFontEngine; + mutable int prevScript; + mutable int prevPosition; + mutable int prevLength; + inline void reset() { + prevFontEngine = 0; + prevScaledFontEngine = 0; + prevScript = -1; + prevPosition = -1; + prevLength = -1; + } + }; + mutable FontEngineCache feCache; + QString text; QFont fnt; QTextBlock block; diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp index 46db253..ffa0ebc 100644 --- a/src/gui/text/qtextformat.cpp +++ b/src/gui/text/qtextformat.cpp @@ -925,7 +925,7 @@ qreal QTextFormat::doubleProperty(int propertyId) const const QVariant prop = d->property(propertyId); if (prop.userType() != QVariant::Double && prop.userType() != QMetaType::Float) return 0.; - return qVariantValue<qreal>(prop); + return qvariant_cast<qreal>(prop); } /*! @@ -1895,7 +1895,7 @@ void QTextBlockFormat::setTabPositions(const QList<QTextOption::Tab> &tabs) QList<QTextOption::Tab>::ConstIterator iter = tabs.constBegin(); while (iter != tabs.constEnd()) { QVariant v; - qVariantSetValue<QTextOption::Tab>(v, *iter); + v.setValue<QTextOption::Tab>(*iter); list.append(v); ++iter; } @@ -1917,7 +1917,7 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const QList<QVariant> variantsList = qvariant_cast<QList<QVariant> >(variant); QList<QVariant>::Iterator iter = variantsList.begin(); while(iter != variantsList.end()) { - answer.append( qVariantValue<QTextOption::Tab>(*iter)); + answer.append( qvariant_cast<QTextOption::Tab>(*iter)); ++iter; } return answer; @@ -2227,6 +2227,44 @@ QTextListFormat::QTextListFormat(const QTextFormat &fmt) \sa setIndent() */ +/*! + \fn void QTextListFormat::setNumberPrefix(const QString &numberPrefix) + \since 4.8 + + Sets the list format's number prefix. This can be used with all + sorted list types. It does not have any effect on unsorted list types. + + \sa numberPrefix() +*/ + +/*! + \fn int QTextListFormat::numberPrefix() const + \since 4.8 + + Returns the list format's number prefix. + + \sa setNumberPrefix() +*/ + +/*! + \fn void QTextListFormat::setNumberSuffix(const QString &numberSuffix) + \since 4.8 + + Sets the list format's number suffix. This can be used with all + sorted list types. It does not have any effect on unsorted list types. + The default suffix is ".". + + \sa numberSuffix() +*/ + +/*! + \fn int QTextListFormat::numberSuffix() const + \since 4.8 + + Returns the list format's number suffix. + + \sa setNumberSuffix() +*/ /*! \class QTextFrameFormat diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h index ecf48a2..bb6e71d 100644 --- a/src/gui/text/qtextformat.h +++ b/src/gui/text/qtextformat.h @@ -202,6 +202,8 @@ public: // list properties ListStyle = 0x3000, ListIndent = 0x3001, + ListNumberPrefix = 0x3002, + ListNumberSuffix = 0x3003, // table and frame properties FrameBorder = 0x4000, @@ -617,6 +619,14 @@ public: inline int indent() const { return intProperty(ListIndent); } + inline void setNumberPrefix(const QString &numberPrefix); + inline QString numberPrefix() const + { return stringProperty(ListNumberPrefix); } + + inline void setNumberSuffix(const QString &numberSuffix); + inline QString numberSuffix() const + { return stringProperty(ListNumberSuffix); } + protected: explicit QTextListFormat(const QTextFormat &fmt); friend class QTextFormat; @@ -628,6 +638,12 @@ inline void QTextListFormat::setStyle(Style astyle) inline void QTextListFormat::setIndent(int aindent) { setProperty(ListIndent, aindent); } +inline void QTextListFormat::setNumberPrefix(const QString &np) +{ setProperty(ListNumberPrefix, np); } + +inline void QTextListFormat::setNumberSuffix(const QString &ns) +{ setProperty(ListNumberSuffix, ns); } + class Q_GUI_EXPORT QTextImageFormat : public QTextCharFormat { public: diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp index ca0942e..5b9ab90 100644 --- a/src/gui/text/qtexthtmlparser.cpp +++ b/src/gui/text/qtexthtmlparser.cpp @@ -1323,6 +1323,12 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration> case QCss::ListStyle: setListStyle(decl.d->values); break; + case QCss::QtListNumberPrefix: + textListNumberPrefix = decl.d->values.first().variant.toString(); + break; + case QCss::QtListNumberSuffix: + textListNumberSuffix = decl.d->values.first().variant.toString(); + break; default: break; } } diff --git a/src/gui/text/qtexthtmlparser_p.h b/src/gui/text/qtexthtmlparser_p.h index 94cfa74..20188ab 100644 --- a/src/gui/text/qtexthtmlparser_p.h +++ b/src/gui/text/qtexthtmlparser_p.h @@ -180,6 +180,8 @@ struct QTextHtmlParserNode { uint displayMode : 3; // QTextHtmlElement::DisplayMode uint hasHref : 1; QTextListFormat::Style listStyle; + QString textListNumberPrefix; + QString textListNumberSuffix; QString imageName; qreal imageWidth; qreal imageHeight; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index f1278b9..dad5371 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -52,6 +52,8 @@ #include "qtextformat_p.h" #include "qstyleoption.h" #include "qpainterpath.h" +#include "qglyphs.h" +#include "qglyphs_p.h" #include <limits.h> #include <qdebug.h> @@ -165,7 +167,7 @@ static QFixed alignLine(QTextEngine *eng, const QScriptLine &line) /*! Returns the inline object's rectangle. - \sa ascent() descent() width() + \sa ascent(), descent(), width() */ QRectF QTextInlineObject::rect() const { @@ -176,7 +178,7 @@ QRectF QTextInlineObject::rect() const /*! Returns the inline object's width. - \sa ascent() descent() rect() + \sa ascent(), descent(), rect() */ qreal QTextInlineObject::width() const { @@ -186,7 +188,7 @@ qreal QTextInlineObject::width() const /*! Returns the inline object's ascent. - \sa descent() width() rect() + \sa descent(), width(), rect() */ qreal QTextInlineObject::ascent() const { @@ -196,7 +198,7 @@ qreal QTextInlineObject::ascent() const /*! Returns the inline object's descent. - \sa ascent() width() rect() + \sa ascent(), width(), rect() */ qreal QTextInlineObject::descent() const { @@ -207,18 +209,17 @@ qreal QTextInlineObject::descent() const Returns the inline object's total height. This is equal to ascent() + descent() + 1. - \sa ascent() descent() width() rect() + \sa ascent(), descent(), width(), rect() */ qreal QTextInlineObject::height() const { return eng->layoutData->items[itm].height().toReal(); } - /*! Sets the inline object's width to \a w. - \sa width() ascent() descent() rect() + \sa width(), ascent(), descent(), rect() */ void QTextInlineObject::setWidth(qreal w) { @@ -228,7 +229,7 @@ void QTextInlineObject::setWidth(qreal w) /*! Sets the inline object's ascent to \a a. - \sa ascent() setDescent() width() rect() + \sa ascent(), setDescent(), width(), rect() */ void QTextInlineObject::setAscent(qreal a) { @@ -238,7 +239,7 @@ void QTextInlineObject::setAscent(qreal a) /*! Sets the inline object's decent to \a d. - \sa descent() setAscent() width() rect() + \sa descent(), setAscent(), width(), rect() */ void QTextInlineObject::setDescent(qreal d) { @@ -246,7 +247,7 @@ void QTextInlineObject::setDescent(qreal d) } /*! - The position of the inline object within the text layout. + The position of the inline object within the text layout. */ int QTextInlineObject::textPosition() const { @@ -254,8 +255,8 @@ int QTextInlineObject::textPosition() const } /*! - Returns an integer describing the format of the inline object - within the text layout. + Returns an integer describing the format of the inline object + within the text layout. */ int QTextInlineObject::formatIndex() const { @@ -263,7 +264,7 @@ int QTextInlineObject::formatIndex() const } /*! - Returns format of the inline object within the text layout. + Returns format of the inline object within the text layout. */ QTextFormat QTextInlineObject::format() const { @@ -273,7 +274,7 @@ QTextFormat QTextInlineObject::format() const } /*! - Returns if the object should be laid out right-to-left or left-to-right. + Returns if the object should be laid out right-to-left or left-to-right. */ Qt::LayoutDirection QTextInlineObject::textDirection() const { @@ -325,7 +326,6 @@ Qt::LayoutDirection QTextInlineObject::textDirection() const boundingRect(), and a minimumWidth() and a maximumWidth(). \sa QStaticText - */ /*! @@ -398,16 +398,19 @@ QTextLayout::~QTextLayout() Sets the layout's font to the given \a font. The layout is invalidated and must be laid out again. - \sa text() + \sa font() */ void QTextLayout::setFont(const QFont &font) { d->fnt = font; + d->feCache.reset(); } /*! Returns the current font that is used for the layout, or a default font if none is set. + + \sa setFont() */ QFont QTextLayout::font() const { @@ -441,10 +444,10 @@ QString QTextLayout::text() const } /*! - Sets the text option structure that controls the layout process to the - given \a option. + Sets the text option structure that controls the layout process to the + given \a option. - \sa textOption() QTextOption + \sa textOption() */ void QTextLayout::setTextOption(const QTextOption &option) { @@ -452,9 +455,9 @@ void QTextLayout::setTextOption(const QTextOption &option) } /*! - Returns the current text option used to control the layout process. + Returns the current text option used to control the layout process. - \sa setTextOption() QTextOption + \sa setTextOption() */ QTextOption QTextLayout::textOption() const { @@ -464,6 +467,8 @@ QTextOption QTextLayout::textOption() const /*! Sets the \a position and \a text of the area in the layout that is processed before editing occurs. + + \sa preeditAreaPosition(), preeditAreaText() */ void QTextLayout::setPreeditArea(int position, const QString &text) { @@ -492,6 +497,8 @@ void QTextLayout::setPreeditArea(int position, const QString &text) /*! Returns the position of the area in the text layout that will be processed before editing occurs. + + \sa preeditAreaText() */ int QTextLayout::preeditAreaPosition() const { @@ -500,6 +507,8 @@ int QTextLayout::preeditAreaPosition() const /*! Returns the text that is inserted in the layout before editing occurs. + + \sa preeditAreaPosition() */ QString QTextLayout::preeditAreaText() const { @@ -508,8 +517,7 @@ QString QTextLayout::preeditAreaText() const /*! - Sets the additional formats supported by the text layout to \a - formatList. + Sets the additional formats supported by the text layout to \a formatList. \sa additionalFormats(), clearAdditionalFormats() */ @@ -535,6 +543,7 @@ void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList) } if (d->block.docHandle()) d->block.docHandle()->documentChange(d->block.position(), d->block.length()); + d->feCache.reset(); } /*! @@ -599,6 +608,8 @@ bool QTextLayout::cacheEnabled() const /*! Begins the layout process. + + \sa endLayout() */ void QTextLayout::beginLayout() { @@ -616,6 +627,8 @@ void QTextLayout::beginLayout() /*! Ends the layout process. + + \sa beginLayout() */ void QTextLayout::endLayout() { @@ -634,35 +647,33 @@ void QTextLayout::endLayout() d->freeMemory(); } -/*! \since 4.4 +/*! + \since 4.4 -Clears the line information in the layout. After having called -this function, lineCount() returns 0. - */ + Clears the line information in the layout. After having called + this function, lineCount() returns 0. +*/ void QTextLayout::clearLayout() { d->clearLineData(); } - /*! Returns the next valid cursor position after \a oldPos that respects the given cursor \a mode. + Returns value of \a oldPos, if \a oldPos is not a valid cursor position. - \sa isValidCursorPosition() previousCursorPosition() + \sa isValidCursorPosition(), previousCursorPosition() */ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const { -// qDebug("looking for next cursor pos for %d", oldPos); const HB_CharAttributes *attributes = d->attributes(); - if (!attributes) - return 0; - int len = d->block.isValid() ? - (d->block.length() - 1) - : d->layoutData->string.length(); - - if (oldPos >= len) + int len = d->block.isValid() ? d->block.length() - 1 + : d->layoutData->string.length(); + Q_ASSERT(len <= d->layoutData->string.length()); + if (!attributes || oldPos < 0 || oldPos >= len) return oldPos; + if (mode == SkipCharacters) { oldPos++; while (oldPos < len && !attributes[oldPos].charStop) @@ -679,22 +690,23 @@ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const while (oldPos < len && d->atSpace(oldPos)) oldPos++; } -// qDebug(" -> %d", oldPos); + return oldPos; } /*! Returns the first valid cursor position before \a oldPos that respects the given cursor \a mode. + Returns value of \a oldPos, if \a oldPos is not a valid cursor position. - \sa isValidCursorPosition() nextCursorPosition() + \sa isValidCursorPosition(), nextCursorPosition() */ int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const { -// qDebug("looking for previous cursor pos for %d", oldPos); const HB_CharAttributes *attributes = d->attributes(); - if (!attributes || oldPos <= 0) - return 0; + if (!attributes || oldPos <= 0 || oldPos > d->layoutData->string.length()) + return oldPos; + if (mode == SkipCharacters) { oldPos--; while (oldPos && !attributes[oldPos].charStop) @@ -712,7 +724,7 @@ int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const oldPos--; } } -// qDebug(" -> %d", oldPos); + return oldPos; } @@ -739,7 +751,6 @@ bool QTextLayout::isValidCursorPosition(int pos) const return attributes[pos].charStop; } - /*! Returns a new text line to be laid out if there is text to be inserted into the layout; otherwise returns an invalid text line. @@ -801,7 +812,7 @@ int QTextLayout::lineCount() const /*! Returns the \a{i}-th line of text in this text layout. - \sa lineCount() lineForTextPosition() + \sa lineCount(), lineForTextPosition() */ QTextLine QTextLayout::lineAt(int i) const { @@ -811,7 +822,7 @@ QTextLine QTextLayout::lineAt(int i) const /*! Returns the line that contains the cursor position specified by \a pos. - \sa isValidCursorPosition() lineAt() + \sa isValidCursorPosition(), lineAt() */ QTextLine QTextLayout::lineForTextPosition(int pos) const { @@ -902,8 +913,9 @@ qreal QTextLayout::maximumWidth() const return d->maxWidth.toReal(); } + /*! - \internal + \internal */ void QTextLayout::setFlags(int flags) { @@ -1028,6 +1040,35 @@ QScriptItem &QTextLineItemIterator::next() return *si; } +static QFixed offsetInLigature(const unsigned short *logClusters, + const QGlyphLayout &glyphs, + int pos, int max, int glyph_pos) +{ + int offsetInCluster = 0; + for (int i = pos - 1; i >= 0; i--) { + if (logClusters[i] == glyph_pos) + offsetInCluster++; + else + break; + } + + // in the case that the offset is inside a (multi-character) glyph, + // interpolate the position. + if (offsetInCluster > 0) { + int clusterLength = 0; + for (int i = pos - offsetInCluster; i < max; i++) { + if (logClusters[i] == glyph_pos) + clusterLength++; + else + break; + } + if (clusterLength) + return glyphs.advances_x[glyph_pos] * offsetInCluster / clusterLength; + } + + return 0; +} + bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selectionWidth) const { *selectionX = *selectionWidth = 0; @@ -1067,8 +1108,19 @@ bool QTextLineItemIterator::getSelectionBounds(QFixed *selectionX, QFixed *selec swidth += glyphs.effectiveAdvance(g); } - *selectionX = x + soff; - *selectionWidth = swidth; + // If the starting character is in the middle of a ligature, + // selection should only contain the right part of that ligature + // glyph, so we need to get the width of the left part here and + // add it to *selectionX + QFixed leftOffsetInLigature = offsetInLigature(logClusters, glyphs, from, + to, start_glyph); + *selectionX = x + soff + leftOffsetInLigature; + *selectionWidth = swidth - leftOffsetInLigature; + // If the ending character is also part of a ligature, swidth does + // not contain that part yet, we also need to find out the width of + // that left part + *selectionWidth += offsetInLigature(logClusters, glyphs, to, + eng->length(item), end_glyph); } return true; } @@ -1114,9 +1166,26 @@ static inline QRectF clipIfValid(const QRectF &rect, const QRectF &clip) return clip.isValid() ? (rect & clip) : rect; } + +/*! + Returns the glyph indexes and positions for all glyphs in this QTextLayout. This is an + expensive function, and should not be called in a time sensitive context. + + \since 4.8 + + \sa draw(), QPainter::drawGlyphs() +*/ +QList<QGlyphs> QTextLayout::glyphs() const +{ + QList<QGlyphs> glyphs; + for (int i=0; i<d->lines.size(); ++i) + glyphs += QTextLine(i, d).glyphs(-1, -1); + + return glyphs; +} + /*! - Draws the whole layout on the painter \a p at the position specified by - \a pos. + Draws the whole layout on the painter \a p at the position specified by \a pos. The rendered layout includes the given \a selections and is clipped within the rectangle specified by \a clip. */ @@ -1290,12 +1359,12 @@ void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVector<FormatRang } /*! - \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition) const - \overload + \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition) const + \overload - Draws a text cursor with the current pen at the given \a position using the - \a painter specified. - The corresponding position within the text is specified by \a cursorPosition. + Draws a text cursor with the current pen at the given \a position using the + \a painter specified. + The corresponding position within the text is specified by \a cursorPosition. */ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition) const { @@ -1303,11 +1372,11 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition } /*! - \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition, int width) const + \fn void QTextLayout::drawCursor(QPainter *painter, const QPointF &position, int cursorPosition, int width) const - Draws a text cursor with the current pen and the specified \a width at the given \a position using the - \a painter specified. - The corresponding position within the text is specified by \a cursorPosition. + Draws a text cursor with the current pen and the specified \a width at the given \a position using the + \a painter specified. + The corresponding position within the text is specified by \a cursorPosition. */ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition, int width) const { @@ -1438,7 +1507,7 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition /*! Returns the line's bounding rectangle. - \sa x() y() textLength() width() + \sa x(), y(), textLength(), width() */ QRectF QTextLine::rect() const { @@ -1464,7 +1533,7 @@ QRectF QTextLine::naturalTextRect() const /*! Returns the line's x position. - \sa rect() y() textLength() width() + \sa rect(), y(), textLength(), width() */ qreal QTextLine::x() const { @@ -1474,7 +1543,7 @@ qreal QTextLine::x() const /*! Returns the line's y position. - \sa x() rect() textLength() width() + \sa x(), rect(), textLength(), width() */ qreal QTextLine::y() const { @@ -1484,7 +1553,7 @@ qreal QTextLine::y() const /*! Returns the line's width as specified by the layout() function. - \sa naturalTextWidth() x() y() textLength() rect() + \sa naturalTextWidth(), x(), y(), textLength(), rect() */ qreal QTextLine::width() const { @@ -1495,7 +1564,7 @@ qreal QTextLine::width() const /*! Returns the line's ascent. - \sa descent() height() + \sa descent(), height() */ qreal QTextLine::ascent() const { @@ -1505,7 +1574,7 @@ qreal QTextLine::ascent() const /*! Returns the line's descent. - \sa ascent() height() + \sa ascent(), height() */ qreal QTextLine::descent() const { @@ -1517,7 +1586,7 @@ qreal QTextLine::descent() const if leading is not included. If leading is included, this equals to ascent() + descent() + leading() + 1. - \sa ascent() descent() leading() setLeadingIncluded() + \sa ascent(), descent(), leading(), setLeadingIncluded() */ qreal QTextLine::height() const { @@ -1529,24 +1598,25 @@ qreal QTextLine::height() const Returns the line's leading. - \sa ascent() descent() height() + \sa ascent(), descent(), height() */ qreal QTextLine::leading() const { return eng->lines[i].leading.toReal(); } -/*! \since 4.6 +/*! + \since 4.6 - Includes positive leading into the line's height if \a included is true; - otherwise does not include leading. + Includes positive leading into the line's height if \a included is true; + otherwise does not include leading. - By default, leading is not included. + By default, leading is not included. - Note that negative leading is ignored, it must be handled - in the code using the text lines by letting the lines overlap. + Note that negative leading is ignored, it must be handled + in the code using the text lines by letting the lines overlap. - \sa leadingIncluded() + \sa leadingIncluded() */ void QTextLine::setLeadingIncluded(bool included) @@ -1555,20 +1625,21 @@ void QTextLine::setLeadingIncluded(bool included) } -/*! \since 4.6 +/*! + \since 4.6 - Returns true if positive leading is included into the line's height; otherwise returns false. + Returns true if positive leading is included into the line's height; + otherwise returns false. - By default, leading is not included. + By default, leading is not included. - \sa setLeadingIncluded() + \sa setLeadingIncluded() */ bool QTextLine::leadingIncluded() const { return eng->lines[i].leadingIncluded; } - /*! Returns the width of the line that is occupied by text. This is always \<= to width(), and is the minimum width that could be used @@ -1579,14 +1650,15 @@ qreal QTextLine::naturalTextWidth() const return eng->lines[i].textWidth.toReal(); } -/*! \since 4.7 - Returns the horizontal advance of the text. The advance of the text - is the distance from its position to the next position at which - text would naturally be drawn. +/*! + \since 4.7 + Returns the horizontal advance of the text. The advance of the text + is the distance from its position to the next position at which + text would naturally be drawn. - By adding the advance to the position of the text line and using this - as the position of a second text line, you will be able to position - the two lines side-by-side without gaps in-between. + By adding the advance to the position of the text line and using this + as the position of a second text line, you will be able to position + the two lines side-by-side without gaps in-between. */ qreal QTextLine::horizontalAdvance() const { @@ -1764,7 +1836,8 @@ static inline void addNextCluster(int &pos, int end, QScriptLine &line, int &gly ++line.length; } while (pos < end && logClusters[pos] == glyphPosition); do { // calculate the textWidth for the rest of the current cluster. - line.textWidth += glyphs.advances_x[glyphPosition] * !glyphs.attributes[glyphPosition].dontPrint; + if (!glyphs.attributes[glyphPosition].dontPrint) + line.textWidth += glyphs.advances_x[glyphPosition]; ++glyphPosition; } while (glyphPosition < current.num_glyphs && !glyphs.attributes[glyphPosition].clusterStart); @@ -1842,14 +1915,14 @@ void QTextLine::layout_helper(int maxGlyphs) lbh.currentPosition = qMax(line.from, current.position); end = current.position + eng->length(item); lbh.glyphs = eng->shapedGlyphs(¤t); + QFontEngine *fontEngine = eng->fontEngine(current); + if (lbh.fontEngine != fontEngine) { + lbh.fontEngine = fontEngine; + lbh.minimumRightBearing = qMin(QFixed(), + QFixed::fromReal(fontEngine->minRightBearing())); + } } const QScriptItem ¤t = eng->layoutData->items[item]; - QFontEngine *fontEngine = eng->fontEngine(current); - if (lbh.fontEngine != fontEngine) { - lbh.fontEngine = fontEngine; - lbh.minimumRightBearing = qMin(QFixed(), - QFixed::fromReal(fontEngine->minRightBearing())); - } lbh.tmpData.leading = qMax(lbh.tmpData.leading + lbh.tmpData.ascent, current.leading + current.ascent) - qMax(lbh.tmpData.ascent, @@ -2014,9 +2087,10 @@ found: eng->maxWidth += lbh.spaceData.textWidth; if (eng->option.flags() & QTextOption::IncludeTrailingSpaces) line.textWidth += lbh.spaceData.textWidth; - line.length += lbh.spaceData.length; - if (lbh.spaceData.length) + if (lbh.spaceData.length) { + line.length += lbh.spaceData.length; line.hasTrailingSpaces = true; + } line.justified = false; line.gridfitted = false; @@ -2170,6 +2244,151 @@ static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const Q } +namespace { + struct GlyphInfo + { + GlyphInfo(const QGlyphLayout &layout, const QPointF &position, + const QTextItemInt::RenderFlags &renderFlags) + : glyphLayout(layout), itemPosition(position), flags(renderFlags) + { + } + + QGlyphLayout glyphLayout; + QPointF itemPosition; + QTextItem::RenderFlags flags; + }; +} + +/*! + \internal + + Returns the glyph indexes and positions for all glyphs in this QTextLine which reside in + QScriptItems that overlap with the range defined by \a from and \a length. The arguments + specify characters, relative to the text in the layout. Note that it is not possible to + use this function to retrieve a subset of the glyphs in a QScriptItem. + + \since 4.8 + + \sa QTextLayout::glyphs() +*/ +QList<QGlyphs> QTextLine::glyphs(int from, int length) const +{ + const QScriptLine &line = eng->lines[i]; + + if (line.length == 0) + return QList<QGlyphs>(); + + QHash<QFontEngine *, GlyphInfo> glyphLayoutHash; + + QTextLineItemIterator iterator(eng, i); + qreal y = line.y.toReal() + line.base().toReal(); + while (!iterator.atEnd()) { + QScriptItem &si = iterator.next(); + if (si.analysis.flags >= QScriptAnalysis::TabOrObject) + continue; + + QPointF pos(iterator.x.toReal(), y); + if (from >= 0 && length >= 0 && + (from >= si.position + eng->length(&si) || from + length <= si.position)) + continue; + + QFont font = eng->font(si); + + QTextItem::RenderFlags flags; + if (font.overline()) + flags |= QTextItem::Overline; + if (font.underline()) + flags |= QTextItem::Underline; + if (font.strikeOut()) + flags |= QTextItem::StrikeOut; + if (si.analysis.bidiLevel % 2) + flags |= QTextItem::RightToLeft; + + QGlyphLayout glyphLayout = eng->shapedGlyphs(&si).mid(iterator.glyphsStart, + iterator.glyphsEnd - iterator.glyphsStart); + + if (glyphLayout.numGlyphs > 0) { + QFontEngine *mainFontEngine = font.d->engineForScript(si.analysis.script); + if (mainFontEngine->type() == QFontEngine::Multi) { + QFontEngineMulti *multiFontEngine = static_cast<QFontEngineMulti *>(mainFontEngine); + int start = 0; + int end; + int which = glyphLayout.glyphs[0] >> 24; + for (end = 0; end < glyphLayout.numGlyphs; ++end) { + const int e = glyphLayout.glyphs[end] >> 24; + if (e == which) + continue; + + QGlyphLayout subLayout = glyphLayout.mid(start, end - start); + glyphLayoutHash.insertMulti(multiFontEngine->engine(which), + GlyphInfo(subLayout, pos, flags)); + + start = end; + which = e; + } + + QGlyphLayout subLayout = glyphLayout.mid(start, end - start); + glyphLayoutHash.insertMulti(multiFontEngine->engine(which), + GlyphInfo(subLayout, pos, flags)); + + } else { + glyphLayoutHash.insertMulti(mainFontEngine, + GlyphInfo(glyphLayout, pos, flags)); + } + } + } + + QHash<QPair<QFontEngine *, int>, QGlyphs> glyphsHash; + + QList<QFontEngine *> keys = glyphLayoutHash.uniqueKeys(); + for (int i=0; i<keys.size(); ++i) { + QFontEngine *fontEngine = keys.at(i); + + // Make a font for this particular engine + QFont font = fontEngine->createExplicitFont(); + + QList<GlyphInfo> glyphLayouts = glyphLayoutHash.values(fontEngine); + for (int j=0; j<glyphLayouts.size(); ++j) { + const QPointF &pos = glyphLayouts.at(j).itemPosition; + const QGlyphLayout &glyphLayout = glyphLayouts.at(j).glyphLayout; + const QTextItem::RenderFlags &flags = glyphLayouts.at(j).flags; + + font.setOverline(flags.testFlag(QTextItem::Overline)); + font.setUnderline(flags.testFlag(QTextItem::Underline)); + font.setStrikeOut(flags.testFlag(QTextItem::StrikeOut)); + + QVarLengthArray<glyph_t> glyphsArray; + QVarLengthArray<QFixedPoint> positionsArray; + + fontEngine->getGlyphPositions(glyphLayout, QTransform(), flags, glyphsArray, + positionsArray); + Q_ASSERT(glyphsArray.size() == positionsArray.size()); + + QVector<quint32> glyphs; + QVector<QPointF> positions; + for (int i=0; i<glyphsArray.size(); ++i) { + glyphs.append(glyphsArray.at(i) & 0xffffff); + positions.append(positionsArray.at(i).toPointF() + pos); + } + + QGlyphs glyphIndexes; + glyphIndexes.setGlyphIndexes(glyphs); + glyphIndexes.setPositions(positions); + + QPair<QFontEngine *, int> key(fontEngine, int(flags)); + + if (!glyphsHash.contains(key)) + glyphsHash.insert(key, QGlyphs()); + + QGlyphs &target = glyphsHash[key]; + target += glyphIndexes; + target.setFont(font); + } + } + + return glyphsHash.values(); +} + /*! \fn void QTextLine::draw(QPainter *painter, const QPointF &position, const QTextLayout::FormatRange *selection) const @@ -2219,8 +2438,12 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR QTextCharFormat format; if (eng->hasFormats() || selection) { - if (!suppressColors) - format = eng->format(&si); + format = eng->format(&si); + if (suppressColors) { + format.clearForeground(); + format.clearBackground(); + format.clearProperty(QTextFormat::TextUnderlineColor); + } if (selection) format.merge(selection->format); @@ -2366,21 +2589,20 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR } /*! - \fn int QTextLine::cursorToX(int cursorPos, Edge edge) const + \fn int QTextLine::cursorToX(int cursorPos, Edge edge) const - \overload + \overload */ - /*! - Converts the cursor position \a cursorPos to the corresponding x position - inside the line, taking account of the \a edge. + Converts the cursor position \a cursorPos to the corresponding x position + inside the line, taking account of the \a edge. - If \a cursorPos is not a valid cursor position, the nearest valid - cursor position will be used instead, and cpos will be modified to - point to this valid cursor position. + If \a cursorPos is not a valid cursor position, the nearest valid + cursor position will be used instead, and cpos will be modified to + point to this valid cursor position. - \sa xToCursor() + \sa xToCursor() */ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const { @@ -2479,14 +2701,6 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const if(pos == l) x += si->width; } else { - int offsetInCluster = 0; - for (int i=pos-1; i >= 0; i--) { - if (logClusters[i] == glyph_pos) - offsetInCluster++; - else - break; - } - if (reverse) { int end = qMin(lineEnd, si->position + l) - si->position; int glyph_end = end == l ? si->num_glyphs : logClusters[end]; @@ -2498,17 +2712,7 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const for (int i = glyph_start; i < glyph_pos; i++) x += glyphs.effectiveAdvance(i); } - if (offsetInCluster > 0) { // in the case that the offset is inside a (multi-character) glyph, interpolate the position. - int clusterLength = 0; - for (int i=pos - offsetInCluster; i < line.length; i++) { - if (logClusters[i] == glyph_pos) - clusterLength++; - else - break; - } - if (clusterLength) - x+= glyphs.advances_x[glyph_pos] * offsetInCluster / clusterLength; - } + x += offsetInLigature(logClusters, glyphs, pos, line.length, glyph_pos); } *cursorPos = pos + si->position; @@ -2516,12 +2720,12 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const } /*! - \fn int QTextLine::xToCursor(qreal x, CursorPosition cpos) const + \fn int QTextLine::xToCursor(qreal x, CursorPosition cpos) const - Converts the x-coordinate \a x, to the nearest matching cursor - position, depending on the cursor position type, \a cpos. + Converts the x-coordinate \a x, to the nearest matching cursor + position, depending on the cursor position type, \a cpos. - \sa cursorToX() + \sa cursorToX() */ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const { diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h index 8c93ed6..32d6d0e 100644 --- a/src/gui/text/qtextlayout.h +++ b/src/gui/text/qtextlayout.h @@ -49,6 +49,7 @@ #include <QtCore/qobject.h> #include <QtGui/qevent.h> #include <QtGui/qtextformat.h> +#include <QtGui/qglyphs.h> QT_BEGIN_HEADER @@ -166,6 +167,8 @@ public: qreal minimumWidth() const; qreal maximumWidth() const; + QList<QGlyphs> glyphs() const; + QTextEngine *engine() const { return d; } void setFlags(int flags); private: @@ -236,7 +239,10 @@ public: private: QTextLine(int line, QTextEngine *e) : i(line), eng(e) {} void layout_helper(int numGlyphs); + QList<QGlyphs> glyphs(int from, int length) const; + friend class QTextLayout; + friend class QTextFragment; int i; QTextEngine *eng; }; diff --git a/src/gui/text/qtextlist.cpp b/src/gui/text/qtextlist.cpp index a0ff520..c312d89 100644 --- a/src/gui/text/qtextlist.cpp +++ b/src/gui/text/qtextlist.cpp @@ -191,6 +191,13 @@ QString QTextList::itemText(const QTextBlock &blockIt) const QString result; const int style = format().style(); + QString numberPrefix; + QString numberSuffix = QLatin1String("."); + + if (format().hasProperty(QTextFormat::ListNumberPrefix)) + numberPrefix = format().numberPrefix(); + if (format().hasProperty(QTextFormat::ListNumberSuffix)) + numberSuffix = format().numberSuffix(); switch (style) { case QTextListFormat::ListDecimal: @@ -232,7 +239,7 @@ QString QTextList::itemText(const QTextBlock &blockIt) const if (q > 0) { int startDigit = i + (i+3)/4; int numDigits; - if (i % 4) { + if (i % 4) { // c[i] == 4|5|9|40|50|90|400|500|900 if ((i-2) % 4) { // c[i] == 4|9|40|90|400|900 => with substraction (IV, IX, XL, XC, ...) @@ -263,8 +270,9 @@ QString QTextList::itemText(const QTextBlock &blockIt) const Q_ASSERT(false); } if (blockIt.textDirection() == Qt::RightToLeft) - return result.prepend(QLatin1Char('.')); - return result + QLatin1Char('.'); + return numberSuffix + result + numberPrefix; + else + return numberPrefix + result + numberSuffix; } /*! diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index ea2ef2d..65fd36e 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -1655,6 +1655,35 @@ QTextBlock::iterator &QTextBlock::iterator::operator--() than the \a other text fragment; otherwise returns false. */ +/*! + Returns the glyphs of this text fragment. The positions of the glyphs are + relative to the position of the QTextBlock's layout. + + \sa QGlyphs, QTextBlock::layout(), QTextLayout::position(), QPainter::drawGlyphs() +*/ +QList<QGlyphs> QTextFragment::glyphs() const +{ + if (!p || !n) + return QList<QGlyphs>(); + + int pos = position(); + int len = length(); + if (len == 0) + return QList<QGlyphs>(); + + int blockNode = p->blockMap().findNode(pos); + + const QTextBlockData *blockData = p->blockMap().fragment(blockNode); + QTextLayout *layout = blockData->layout; + + QList<QGlyphs> ret; + for (int i=0; i<layout->lineCount(); ++i) { + QTextLine textLine = layout->lineAt(i); + ret += textLine.glyphs(pos, len); + } + + return ret; +} /*! Returns the position of this text fragment in the document. diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h index a573a26..332458d 100644 --- a/src/gui/text/qtextobject.h +++ b/src/gui/text/qtextobject.h @@ -44,6 +44,7 @@ #include <QtCore/qobject.h> #include <QtGui/qtextformat.h> +#include <QtGui/qglyphs.h> QT_BEGIN_HEADER @@ -315,6 +316,8 @@ public: int charFormatIndex() const; QString text() const; + QList<QGlyphs> glyphs() const; + private: const QTextDocumentPrivate *p; int n; diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp index 7992de5..04f6913 100644 --- a/src/gui/text/qtextodfwriter.cpp +++ b/src/gui/text/qtextodfwriter.cpp @@ -636,7 +636,15 @@ void QTextOdfWriter::writeListFormat(QXmlStreamWriter &writer, QTextListFormat f || style == QTextListFormat::ListUpperRoman) { writer.writeStartElement(textNS, QString::fromLatin1("list-level-style-number")); writer.writeAttribute(styleNS, QString::fromLatin1("num-format"), bulletChar(style)); - writer.writeAttribute(styleNS, QString::fromLatin1("num-suffix"), QString::fromLatin1(".")); + + if (format.hasProperty(QTextFormat::ListNumberSuffix)) + writer.writeAttribute(styleNS, QString::fromLatin1("num-suffix"), format.numberSuffix()); + else + writer.writeAttribute(styleNS, QString::fromLatin1("num-suffix"), QString::fromLatin1(".")); + + if (format.hasProperty(QTextFormat::ListNumberPrefix)) + writer.writeAttribute(styleNS, QString::fromLatin1("num-prefix"), format.numberPrefix()); + } else { writer.writeStartElement(textNS, QString::fromLatin1("list-level-style-bullet")); writer.writeAttribute(textNS, QString::fromLatin1("bullet-char"), bulletChar(style)); diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index af8daa5..0040b54 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -25,7 +25,7 @@ HEADERS += \ text/qabstracttextdocumentlayout.h \ text/qtextdocumentlayout_p.h \ text/qtextcursor.h \ - text/qtextcursor_p.h \ + text/qtextcursor_p.h \ text/qtextdocumentfragment.h \ text/qtextdocumentfragment_p.h \ text/qtextimagehandler_p.h \ @@ -39,7 +39,9 @@ HEADERS += \ text/qzipwriter_p.h \ text/qtextodfwriter_p.h \ text/qstatictext_p.h \ - text/qstatictext.h + text/qstatictext.h \ + text/qglyphs.h \ + text/qglyphs_p.h SOURCES += \ text/qfont.cpp \ @@ -69,7 +71,8 @@ SOURCES += \ text/qcssparser.cpp \ text/qzip.cpp \ text/qtextodfwriter.cpp \ - text/qstatictext.cpp + text/qstatictext.cpp \ + text/qglyphs.cpp win32 { SOURCES += \ @@ -89,7 +92,7 @@ unix:x11 { text/qfontengine_ft.cpp } -!embedded:!x11:mac { +!embedded:!qpa:!x11:mac { SOURCES += \ text/qfont_mac.cpp OBJECTIVE_SOURCES += text/qfontengine_mac.mm @@ -110,6 +113,19 @@ embedded { DEFINES += QT_NO_FONTCONFIG } +qpa { + SOURCES += \ + text/qfont_qpa.cpp \ + text/qfontengine_qpa.cpp \ + text/qplatformfontdatabase_qpa.cpp + + HEADERS += \ + text/qplatformfontdatabase_qpa.h + + DEFINES += QT_NO_FONTCONFIG + DEFINES += QT_NO_FREETYPE +} + symbian { SOURCES += \ text/qfont_s60.cpp @@ -129,6 +145,7 @@ symbian { } } +!qpa { contains(QT_CONFIG, freetype) { SOURCES += \ ../3rdparty/freetype/src/base/ftbase.c \ @@ -202,6 +219,7 @@ contains(QT_CONFIG, freetype) { contains(QT_CONFIG, fontconfig) { CONFIG += opentype } +}#!qpa DEFINES += QT_NO_OPENTYPE INCLUDEPATH += ../3rdparty/harfbuzz/src diff --git a/src/gui/util/qcompleter.cpp b/src/gui/util/qcompleter.cpp index bcd601b..71a0171 100644 --- a/src/gui/util/qcompleter.cpp +++ b/src/gui/util/qcompleter.cpp @@ -220,7 +220,7 @@ QModelIndex QCompletionModel::mapToSource(const QModelIndex& index) const { Q_D(const QCompletionModel); if (!index.isValid()) - return QModelIndex(); + return engine->curParent; int row; QModelIndex parent = engine->curParent; diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp index 8b36b32..39a160e 100644 --- a/src/gui/util/qdesktopservices.cpp +++ b/src/gui/util/qdesktopservices.cpp @@ -45,7 +45,7 @@ #include <qdebug.h> -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) #include "qdesktopservices_qws.cpp" #elif defined(Q_WS_X11) #include "qdesktopservices_x11.cpp" diff --git a/src/gui/util/util.pri b/src/gui/util/util.pri index bea520e..af6218a 100644 --- a/src/gui/util/util.pri +++ b/src/gui/util/util.pri @@ -33,12 +33,12 @@ unix:x11 { util/qsystemtrayicon_x11.cpp } -embedded { +embedded|qpa { SOURCES += \ util/qsystemtrayicon_qws.cpp } -!embedded:!x11:mac { +!embedded:!qpa:!x11:mac { OBJECTIVE_SOURCES += util/qsystemtrayicon_mac.mm } diff --git a/src/gui/widgets/qabstractbutton.cpp b/src/gui/widgets/qabstractbutton.cpp index 995d659..bd66843 100644 --- a/src/gui/widgets/qabstractbutton.cpp +++ b/src/gui/widgets/qabstractbutton.cpp @@ -319,7 +319,7 @@ QList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const return group->d_func()->buttonList; #endif - QList<QAbstractButton*>candidates = qFindChildren<QAbstractButton *>(parent); + QList<QAbstractButton*>candidates = parent->findChildren<QAbstractButton *>(); if (autoExclusive) { for (int i = candidates.count() - 1; i >= 0; --i) { QAbstractButton *candidate = candidates.at(i); diff --git a/src/gui/widgets/qcheckbox.cpp b/src/gui/widgets/qcheckbox.cpp index bc0900e..64b47b4 100644 --- a/src/gui/widgets/qcheckbox.cpp +++ b/src/gui/widgets/qcheckbox.cpp @@ -300,6 +300,15 @@ QSize QCheckBox::sizeHint() const return d->sizeHint; } + +/*! + \reimp +*/ +QSize QCheckBox::minimumSizeHint() const +{ + return sizeHint(); +} + /*! \reimp */ diff --git a/src/gui/widgets/qcheckbox.h b/src/gui/widgets/qcheckbox.h index 7b6292d..95da261 100644 --- a/src/gui/widgets/qcheckbox.h +++ b/src/gui/widgets/qcheckbox.h @@ -65,6 +65,7 @@ public: QSize sizeHint() const; + QSize minimumSizeHint() const; void setTristate(bool y = true); bool isTristate() const; diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index 7859bdc..ced0d73f 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -116,7 +116,7 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt QPalette resolvedpalette = option.palette.resolve(QApplication::palette("QMenu")); QVariant value = index.data(Qt::ForegroundRole); - if (qVariantCanConvert<QBrush>(value)) { + if (value.canConvert<QBrush>()) { resolvedpalette.setBrush(QPalette::WindowText, qvariant_cast<QBrush>(value)); resolvedpalette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(value)); resolvedpalette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value)); @@ -152,7 +152,7 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt menuOption.icon = qvariant_cast<QPixmap>(variant); break; } - if (qVariantCanConvert<QBrush>(index.data(Qt::BackgroundRole))) { + if (index.data(Qt::BackgroundRole).canConvert<QBrush>()) { menuOption.palette.setBrush(QPalette::All, QPalette::Background, qvariant_cast<QBrush>(index.data(Qt::BackgroundRole))); } @@ -369,6 +369,7 @@ void QComboBoxPrivateContainer::timerEvent(QTimerEvent *timerEvent) if (timerEvent->timerId() == adjustSizeTimer.timerId()) { adjustSizeTimer.stop(); if (combo->sizeAdjustPolicy() == QComboBox::AdjustToContents) { + combo->updateGeometry(); combo->adjustSize(); combo->update(); } @@ -1088,6 +1089,8 @@ void QComboBoxPrivate::updateViewContainerPaletteAndOpacity() container->setPalette(q->palette()); container->setWindowOpacity(1.0); } + if (lineEdit) + lineEdit->setPalette(q->palette()); } /*! @@ -1298,7 +1301,7 @@ QComboBox::~QComboBox() By default, this property has a value of 10. \note This property is ignored for non-editable comboboxes in styles that returns - false for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style. + true for QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style. */ int QComboBox::maxVisibleItems() const { @@ -2008,11 +2011,18 @@ void QComboBox::setCurrentIndex(int index) void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi) { Q_Q(QComboBox); - bool indexChanged = (mi != currentIndex); + + QModelIndex normalized; + if (mi.column() != modelColumn) + normalized = model->index(mi.row(), modelColumn, mi.parent()); + if (!normalized.isValid()) + normalized = mi; // Fallback to passed index. + + bool indexChanged = (normalized != currentIndex); if (indexChanged) - currentIndex = QPersistentModelIndex(mi); + currentIndex = QPersistentModelIndex(normalized); if (lineEdit) { - QString newText = q->itemText(currentIndex.row()); + QString newText = q->itemText(normalized.row()); if (lineEdit->text() != newText) lineEdit->setText(newText); updateLineEditGeometry(); diff --git a/src/gui/widgets/qcombobox.h b/src/gui/widgets/qcombobox.h index fb9af9f..81a4389 100644 --- a/src/gui/widgets/qcombobox.h +++ b/src/gui/widgets/qcombobox.h @@ -68,7 +68,7 @@ class Q_GUI_EXPORT QComboBox : public QWidget Q_PROPERTY(bool editable READ isEditable WRITE setEditable) Q_PROPERTY(int count READ count) Q_PROPERTY(QString currentText READ currentText) - Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) + Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged USER true) Q_PROPERTY(int maxVisibleItems READ maxVisibleItems WRITE setMaxVisibleItems) Q_PROPERTY(int maxCount READ maxCount WRITE setMaxCount) Q_PROPERTY(InsertPolicy insertPolicy READ insertPolicy WRITE setInsertPolicy) diff --git a/src/gui/widgets/qcombobox_p.h b/src/gui/widgets/qcombobox_p.h index 29a628c..c0727ed 100644 --- a/src/gui/widgets/qcombobox_p.h +++ b/src/gui/widgets/qcombobox_p.h @@ -337,7 +337,7 @@ private: QComboBox *mCombo; }; -class QComboBoxPrivate : public QWidgetPrivate +class Q_AUTOTEST_EXPORT QComboBoxPrivate : public QWidgetPrivate { Q_DECLARE_PUBLIC(QComboBox) public: diff --git a/src/gui/widgets/qdatetimeedit.cpp b/src/gui/widgets/qdatetimeedit.cpp index 8043747..f2e8fd2 100644 --- a/src/gui/widgets/qdatetimeedit.cpp +++ b/src/gui/widgets/qdatetimeedit.cpp @@ -890,7 +890,13 @@ void QDateTimeEdit::setDisplayFormat(const QString &format) const bool dateShown = (d->sections & DateSections_Mask); Q_ASSERT(dateShown || timeShown); if (timeShown && !dateShown) { + QTime time = d->value.toTime(); setDateRange(d->value.toDate(), d->value.toDate()); + if (d->minimum.toTime() >= d->maximum.toTime()) { + setTimeRange(QDATETIMEEDIT_TIME_MIN, QDATETIMEEDIT_TIME_MAX); + // if the time range became invalid during the adjustment, the time would have been reset + setTime(time); + } } else if (dateShown && !timeShown) { setTimeRange(QDATETIMEEDIT_TIME_MIN, QDATETIMEEDIT_TIME_MAX); d->value = QDateTime(d->value.toDate(), QTime(), d->spec); @@ -1654,6 +1660,15 @@ void QDateTimeEditPrivate::updateTimeSpec() minimum = minimum.toDateTime().toTimeSpec(spec); maximum = maximum.toDateTime().toTimeSpec(spec); value = value.toDateTime().toTimeSpec(spec); + + // time zone changes can lead to 00:00:00 becomes 01:00:00 and 23:59:59 becomes 00:59:59 (invalid range) + const bool dateShown = (sections & QDateTimeEdit::DateSections_Mask); + if (!dateShown) { + if (minimum.toTime() >= maximum.toTime()){ + minimum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MIN, spec); + maximum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MAX, spec); + } + } } void QDateTimeEditPrivate::updateEdit() diff --git a/src/gui/widgets/qdialogbuttonbox.cpp b/src/gui/widgets/qdialogbuttonbox.cpp index 732dbc9..9aea32a 100644 --- a/src/gui/widgets/qdialogbuttonbox.cpp +++ b/src/gui/widgets/qdialogbuttonbox.cpp @@ -1229,7 +1229,7 @@ bool QDialogButtonBox::event(QEvent *event) break; } - foreach (QPushButton *pb, qFindChildren<QPushButton *>(dialog ? dialog : this)) { + foreach (QPushButton *pb, (dialog ? dialog : this)->findChildren<QPushButton *>()) { if (pb->isDefault() && pb != firstAcceptButton) { hasDefault = true; break; diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp index 42be03b..15e2ff3 100644 --- a/src/gui/widgets/qlabel.cpp +++ b/src/gui/widgets/qlabel.cpp @@ -1072,7 +1072,7 @@ void QLabel::paintEvent(QPaintEvent *) else #endif if (d->isTextLabel) { - QRectF lr = d->layoutRect(); + QRectF lr = d->layoutRect().toAlignedRect(); QStyleOption opt; opt.initFrom(this); #ifndef QT_NO_STYLE_STYLESHEET diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index f338f40..a283da6 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -112,7 +112,7 @@ void QLineControl::updateDisplayText(bool forceUpdate) Copies the currently selected text into the clipboard using the given \a mode. - + \note If the echo mode is set to a mode other than Normal then copy will not work. This is to prevent using copy as a method of bypassing password features of the line control. @@ -486,7 +486,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) /*! \internal - Draws the display text for the line control using the given + Draws the display text for the line control using the given \a painter, \a clip, and \a offset. Which aspects of the display text are drawn is specified by the given \a flags. diff --git a/src/gui/widgets/qlineedit.h b/src/gui/widgets/qlineedit.h index 94e0dbe..667562b 100644 --- a/src/gui/widgets/qlineedit.h +++ b/src/gui/widgets/qlineedit.h @@ -283,6 +283,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_editFocusChange(bool)) #endif Q_PRIVATE_SLOT(d_func(), void _q_selectionChanged()) + Q_PRIVATE_SLOT(d_func(), void _q_updateNeeded(const QRect &)) }; #endif // QT_NO_LINEEDIT diff --git a/src/gui/widgets/qlineedit_p.cpp b/src/gui/widgets/qlineedit_p.cpp index 468c111..d705fa8 100644 --- a/src/gui/widgets/qlineedit_p.cpp +++ b/src/gui/widgets/qlineedit_p.cpp @@ -59,6 +59,13 @@ QT_BEGIN_NAMESPACE const int QLineEditPrivate::verticalMargin(1); const int QLineEditPrivate::horizontalMargin(2); +QRect QLineEditPrivate::adjustedControlRect(const QRect &rect) const +{ + QRect cr = adjustedContentsRect(); + int cix = cr.x() - hscroll + horizontalMargin; + return rect.translated(QPoint(cix, vscroll)); +} + int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const { QRect cr = adjustedContentsRect(); @@ -68,11 +75,7 @@ int QLineEditPrivate::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const QRect QLineEditPrivate::cursorRect() const { - QRect cr = adjustedContentsRect(); - int cix = cr.x() - hscroll + horizontalMargin; - QRect crect = control->cursorRect(); - crect.moveTo(crect.topLeft() + QPoint(cix, vscroll)); - return crect; + return adjustedControlRect(control->cursorRect()); } #ifndef QT_NO_COMPLETER @@ -141,6 +144,11 @@ void QLineEditPrivate::_q_selectionChanged() emit q->selectionChanged(); } +void QLineEditPrivate::_q_updateNeeded(const QRect &rect) +{ + q_func()->update(adjustedControlRect(rect)); +} + void QLineEditPrivate::init(const QString& txt) { Q_Q(QLineEdit); @@ -176,7 +184,7 @@ void QLineEditPrivate::init(const QString& txt) q, SLOT(update())); QObject::connect(control, SIGNAL(updateNeeded(QRect)), - q, SLOT(update())); + q, SLOT(_q_updateNeeded(QRect))); QStyleOptionFrameV2 opt; q->initStyleOption(&opt); @@ -216,9 +224,8 @@ void QLineEditPrivate::setCursorVisible(bool visible) if ((bool)cursorVisible == visible) return; cursorVisible = visible; - QRect r = cursorRect(); if (control->inputMask().isEmpty()) - q->update(r); + q->update(cursorRect()); else q->update(); } diff --git a/src/gui/widgets/qlineedit_p.h b/src/gui/widgets/qlineedit_p.h index 7a24cb3..b9f9c0b 100644 --- a/src/gui/widgets/qlineedit_p.h +++ b/src/gui/widgets/qlineedit_p.h @@ -94,6 +94,8 @@ public: #endif void init(const QString&); + QRect adjustedControlRect(const QRect &) const; + int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const; QRect cursorRect() const; void setCursorVisible(bool visible); @@ -129,6 +131,7 @@ public: void _q_editFocusChange(bool); #endif void _q_selectionChanged(); + void _q_updateNeeded(const QRect &); #ifndef QT_NO_COMPLETER void _q_completionHighlighted(QString); #endif diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index 2731182..da902d5 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -1516,14 +1516,21 @@ void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set) if (!isWindow() || d->useHIToolBar == set || QSysInfo::MacintoshVersion < QSysInfo::MV_10_3) return; - // ### Disable the unified toolbar when using anything but the native graphics system. - // ### Disable when using alien widgets as well - if (windowSurface() || testAttribute(Qt::WA_NativeWindow) == false) + // ### Disable when using alien widgets + if (testAttribute(Qt::WA_NativeWindow) == false) { return; + } d->useHIToolBar = set; createWinId(); // We need the hiview for down below. +#ifdef QT_MAC_USE_COCOA + // Activate the unified toolbar with the raster engine. + if (windowSurface()) { + d->layout->unifiedSurface = new QUnifiedToolbarSurface(this); + } +#endif // QT_MAC_USE_COCOA + d->layout->updateHIToolBarStatus(); // Enabling the unified toolbar clears the opaque size grip setting, update it. d->macUpdateOpaqueSizeGrip(); @@ -1634,7 +1641,7 @@ QMenu *QMainWindow::createPopupMenu() Q_D(QMainWindow); QMenu *menu = 0; #ifndef QT_NO_DOCKWIDGET - QList<QDockWidget *> dockwidgets = qFindChildren<QDockWidget *>(this); + QList<QDockWidget *> dockwidgets = findChildren<QDockWidget *>(); if (dockwidgets.size()) { menu = new QMenu(this); for (int i = 0; i < dockwidgets.size(); ++i) { @@ -1648,7 +1655,7 @@ QMenu *QMainWindow::createPopupMenu() } #endif // QT_NO_DOCKWIDGET #ifndef QT_NO_TOOLBAR - QList<QToolBar *> toolbars = qFindChildren<QToolBar *>(this); + QList<QToolBar *> toolbars = findChildren<QToolBar *>(); if (toolbars.size()) { if (!menu) menu = new QMenu(this); diff --git a/src/gui/widgets/qmainwindowlayout_mac.mm b/src/gui/widgets/qmainwindowlayout_mac.mm index 1bfc746..9e26423 100644 --- a/src/gui/widgets/qmainwindowlayout_mac.mm +++ b/src/gui/widgets/qmainwindowlayout_mac.mm @@ -43,6 +43,7 @@ #include <qtoolbar.h> #include <private/qtoolbarlayout_p.h> #include <private/qt_cocoa_helpers_mac_p.h> +#include <private/qtoolbar_p.h> #ifndef QT_MAC_USE_COCOA #include <Carbon/Carbon.h> @@ -408,6 +409,7 @@ void QMainWindowLayout::insertIntoMacToolbar(QToolBar *before, QToolBar *toolbar beforeIndex = qtoolbarsInUnifiedToolbarList.size(); int toolbarIndex = qtoolbarsInUnifiedToolbarList.indexOf(toolbar); + #ifndef QT_MAC_USE_COCOA HIToolbarRef macToolbar = NULL; if ((GetWindowToolbar(window, &macToolbar) == noErr) && !macToolbar) { @@ -444,6 +446,18 @@ void QMainWindowLayout::insertIntoMacToolbar(QToolBar *before, QToolBar *toolbar #endif } qtoolbarsInUnifiedToolbarList.insert(beforeIndex, toolbar); + + // Adding to the unified toolbar surface for the raster engine. + if (layoutState.mainWindow->windowSurface()) { + QPoint offset(0, 0); + for (int i = 0; i < beforeIndex; ++i) { + offset.setX(offset.x() + qtoolbarsInUnifiedToolbarList.at(i)->size().width()); + } +#ifdef QT_MAC_USE_COCOA + unifiedSurface->insertToolbar(toolbar, offset); +#endif // QT_MAC_USE_COCOA + } + #ifndef QT_MAC_USE_COCOA QCFType<HIToolbarItemRef> outItem; const QObject *stupidArray[] = { toolbar, this }; @@ -460,6 +474,19 @@ void QMainWindowLayout::insertIntoMacToolbar(QToolBar *before, QToolBar *toolbar #endif } +#ifdef QT_MAC_USE_COCOA +void QMainWindowLayout::updateUnifiedToolbarOffset() +{ + QPoint offset(0, 0); + + for (int i = 1; i < qtoolbarsInUnifiedToolbarList.length(); ++i) { + offset.setX(offset.x() + qtoolbarsInUnifiedToolbarList.at(i - 1)->size().width()); + qtoolbarsInUnifiedToolbarList.at(i)->d_func()->toolbar_offset = offset; + } +} +#endif // QT_MAC_USE_COCOA + + void QMainWindowLayout::removeFromMacToolbar(QToolBar *toolbar) { QHash<void *, QToolBar *>::iterator it = unifiedToolbarHash.begin(); @@ -533,11 +560,11 @@ void QMainWindowLayout::fixSizeInUnifiedToolbar(QToolBar *tb) const QMacCocoaAutoReleasePool pool; QWidgetItem layoutItem(tb); QSize size = layoutItem.maximumSize(); - NSSize nssize = NSMakeSize(size.width(), size.height() - 2); + NSSize nssize = NSMakeSize(size.width(), size.height()); [item setMaxSize:nssize]; size = layoutItem.minimumSize(); nssize.width = size.width(); - nssize.height = size.height() - 2; + nssize.height = size.height(); [item setMinSize:nssize]; } #else diff --git a/src/gui/widgets/qmainwindowlayout_p.h b/src/gui/widgets/qmainwindowlayout_p.h index 3e1a95d..661d49d 100644 --- a/src/gui/widgets/qmainwindowlayout_p.h +++ b/src/gui/widgets/qmainwindowlayout_p.h @@ -85,7 +85,11 @@ typedef HIObjectRef HIToolbarItemRef; typedef const void * CFTypeRef; typedef const struct __CFString * CFStringRef; -#endif +# ifdef QT_MAC_USE_COCOA +#include <private/qunifiedtoolbarsurface_mac_p.h> +# endif // QT_MAC_USE_COCOA + +#endif // Q_WS_MAC QT_BEGIN_NAMESPACE @@ -338,7 +342,13 @@ public: bool activateUnifiedToolbarAfterFullScreen; void syncUnifiedToolbarVisibility(); bool blockVisiblityCheck; -#endif + +#ifdef QT_MAC_USE_COCOA + QUnifiedToolbarSurface *unifiedSurface; + void updateUnifiedToolbarOffset(); +#endif // QT_MAC_USE_COCOA + +#endif // Q_WS_MAC }; QT_END_NAMESPACE diff --git a/src/gui/widgets/qmdisubwindow.cpp b/src/gui/widgets/qmdisubwindow.cpp index 62d297e..3f4cdc3 100644 --- a/src/gui/widgets/qmdisubwindow.cpp +++ b/src/gui/widgets/qmdisubwindow.cpp @@ -2203,7 +2203,7 @@ void QMdiSubWindowPrivate::setSizeGrip(QSizeGrip *newSizeGrip) void QMdiSubWindowPrivate::setSizeGripVisible(bool visible) const { // See if we can find any size grips - QList<QSizeGrip *> sizeGrips = qFindChildren<QSizeGrip *>(q_func()); + QList<QSizeGrip *> sizeGrips = q_func()->findChildren<QSizeGrip *>(); foreach (QSizeGrip *grip, sizeGrips) grip->setVisible(visible); } @@ -2319,7 +2319,7 @@ void QMdiSubWindow::setWidget(QWidget *widget) widget->setParent(this); #ifndef QT_NO_SIZEGRIP - QSizeGrip *sizeGrip = qFindChild<QSizeGrip *>(widget); + QSizeGrip *sizeGrip = widget->findChild<QSizeGrip *>(); if (sizeGrip) sizeGrip->installEventFilter(this); if (d->sizeGrip) diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 4bea6de..245657a 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -2804,7 +2804,7 @@ void QMenu::mouseMoveEvent(QMouseEvent *e) if (d->sloppyRegion.contains(e->pos())) { d->sloppyAction = action; QMenuPrivate::sloppyDelayTimer = startTimer(style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this)*6); - } else { + } else if (action != d->currentAction) { d->setCurrentAction(action, style()->styleHint(QStyle::SH_Menu_SubMenuPopupDelay, 0, this)); } } diff --git a/src/gui/widgets/qmenu.h b/src/gui/widgets/qmenu.h index 7708e05..77f3b1a 100644 --- a/src/gui/widgets/qmenu.h +++ b/src/gui/widgets/qmenu.h @@ -51,6 +51,10 @@ #include <QtGui/qpixmap.h> #endif +#ifdef Q_WS_WINCE +#include <windef.h> // for HMENU +#endif + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm index aaa113b..60023a8 100644 --- a/src/gui/widgets/qmenu_mac.mm +++ b/src/gui/widgets/qmenu_mac.mm @@ -1254,15 +1254,11 @@ QMenuPrivate::QMacMenuPrivate::addAction(QMacMenuAction *action, QMacMenuAction NSString *keySequenceToKeyEqivalent(const QKeySequence &accel) { quint32 accel_key = (accel[0] & ~(Qt::MODIFIER_MASK | Qt::UNICODE_ACCEL)); - extern QChar qt_macSymbolForQtKey(int key); // qkeysequence.cpp - QChar keyEquiv = qt_macSymbolForQtKey(accel_key); - if (keyEquiv.isNull()) { - if (accel_key >= Qt::Key_F1 && accel_key <= Qt::Key_F15) - keyEquiv = (accel_key - Qt::Key_F1) + NSF1FunctionKey; - else - keyEquiv = unichar(QChar(accel_key).toLower().unicode()); - } - return [NSString stringWithCharacters:&keyEquiv.unicode() length:1]; + extern QChar qtKey2CocoaKey(Qt::Key key); + QChar cocoa_key = qtKey2CocoaKey(Qt::Key(accel_key)); + if (cocoa_key.isNull()) + cocoa_key = QChar(accel_key).toLower().unicode(); + return [NSString stringWithCharacters:&cocoa_key.unicode() length:1]; } // return the cocoa modifier mask for the QKeySequence (currently only looks at the first one). @@ -2052,8 +2048,7 @@ bool QMenuBar::macUpdateMenuBar() { #ifdef QT_MAC_USE_COCOA QMacCocoaAutoReleasePool pool; - if (!qt_cocoaPostMessage(getMenuLoader(), @selector(qtUpdateMenubar))) - return QMenuBarPrivate::macUpdateMenuBarImmediatly(); + qt_cocoaPostMessage(getMenuLoader(), @selector(qtUpdateMenubar)); return true; #else return QMenuBarPrivate::macUpdateMenuBarImmediatly(); diff --git a/src/gui/widgets/qmenu_symbian.cpp b/src/gui/widgets/qmenu_symbian.cpp index 83ba15a..652e65c 100644 --- a/src/gui/widgets/qmenu_symbian.cpp +++ b/src/gui/widgets/qmenu_symbian.cpp @@ -264,7 +264,8 @@ void qt_symbian_show_submenu( CEikMenuPane* menuPane, int id) // However if we don't have any items, we still need the item array. Otherwise // menupane will crash. That's why we create item array here manually, and // AddMenuItemL will then use the existing array. - CEikMenuPane::CItemArray* itemArray = q_check_ptr(new CEikMenuPane::CItemArray); + CEikMenuPane::CItemArray* itemArray = new CEikMenuPane::CItemArray; + Q_CHECK_PTR(itemArray); menuPane->SetItemArray(itemArray); menuPane->SetItemArrayOwnedExternally(EFalse); diff --git a/src/gui/widgets/qmenu_wince.cpp b/src/gui/widgets/qmenu_wince.cpp index e088db6..15d0116 100644 --- a/src/gui/widgets/qmenu_wince.cpp +++ b/src/gui/widgets/qmenu_wince.cpp @@ -113,8 +113,6 @@ static void resolveAygLibs() if (!aygResolved) { aygResolved = true; QLibrary aygLib(QLatin1String("aygshell")); - if (!aygLib.load()) - return; ptrCreateMenuBar = (AygCreateMenuBar) aygLib.resolve("SHCreateMenuBar"); ptrEnableSoftKey = (AygEnableSoftKey) aygLib.resolve("SHEnableSoftkey"); } diff --git a/src/gui/widgets/qradiobutton.cpp b/src/gui/widgets/qradiobutton.cpp index 20b6c720..56bd709 100644 --- a/src/gui/widgets/qradiobutton.cpp +++ b/src/gui/widgets/qradiobutton.cpp @@ -207,6 +207,14 @@ QSize QRadioButton::sizeHint() const /*! \reimp */ +QSize QRadioButton::minimumSizeHint() const +{ + return sizeHint(); +} + +/*! + \reimp +*/ bool QRadioButton::hitButton(const QPoint &pos) const { QStyleOptionButton opt; diff --git a/src/gui/widgets/qradiobutton.h b/src/gui/widgets/qradiobutton.h index 887b747..b7031e2 100644 --- a/src/gui/widgets/qradiobutton.h +++ b/src/gui/widgets/qradiobutton.h @@ -62,6 +62,7 @@ public: explicit QRadioButton(const QString &text, QWidget *parent=0); QSize sizeHint() const; + QSize minimumSizeHint() const; protected: bool event(QEvent *e); diff --git a/src/gui/widgets/qsizegrip.cpp b/src/gui/widgets/qsizegrip.cpp index c9d613a..b5b611c 100644 --- a/src/gui/widgets/qsizegrip.cpp +++ b/src/gui/widgets/qsizegrip.cpp @@ -78,15 +78,6 @@ static QWidget *qt_sizegrip_topLevelWidget(QWidget* w) return w; } -static inline bool hasHeightForWidth(QWidget *widget) -{ - if (!widget) - return false; - if (QLayout *layout = widget->layout()) - return layout->hasHeightForWidth(); - return widget->sizePolicy().hasHeightForWidth(); -} - class QSizeGripPrivate : public QWidgetPrivate { Q_DECLARE_PUBLIC(QSizeGrip) @@ -318,7 +309,7 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e) #ifdef Q_WS_X11 // Use a native X11 sizegrip for "real" top-level windows if supported. if (tlw->isWindow() && X11->isSupportedByWM(ATOM(_NET_WM_MOVERESIZE)) - && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !hasHeightForWidth(tlw)) { + && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) { XEvent xev; xev.xclient.type = ClientMessage; xev.xclient.message_type = ATOM(_NET_WM_MOVERESIZE); @@ -340,7 +331,7 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e) } #endif // Q_WS_X11 #ifdef Q_WS_WIN - if (tlw->isWindow() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !hasHeightForWidth(tlw)) { + if (tlw->isWindow() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) { uint orientation = 0; if (d->atBottom()) orientation = d->atLeft() ? SZ_SIZEBOTTOMLEFT : SZ_SIZEBOTTOMRIGHT; @@ -429,12 +420,12 @@ void QSizeGrip::mouseMoveEvent(QMouseEvent * e) #ifdef Q_WS_X11 if (tlw->isWindow() && X11->isSupportedByWM(ATOM(_NET_WM_MOVERESIZE)) - && tlw->isTopLevel() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !hasHeightForWidth(tlw)) + && tlw->isTopLevel() && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) return; #endif #ifdef Q_WS_WIN if (tlw->isWindow() && GetSystemMenu(tlw->winId(), FALSE) != 0 && internalWinId() - && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !hasHeightForWidth(tlw)) { + && !tlw->testAttribute(Qt::WA_DontShowOnScreen) && !qt_widget_private(tlw)->hasHeightForWidth()) { MSG msg; while(PeekMessage(&msg, winId(), WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)); return; diff --git a/src/gui/widgets/qspinbox.cpp b/src/gui/widgets/qspinbox.cpp index 2d871d0..10ce144 100644 --- a/src/gui/widgets/qspinbox.cpp +++ b/src/gui/widgets/qspinbox.cpp @@ -697,6 +697,9 @@ void QDoubleSpinBox::setSuffix(const QString &suffix) d->suffix = suffix; d->updateEdit(); + + d->cachedSizeHint = QSize(); + updateGeometry(); } /*! diff --git a/src/gui/widgets/qsplashscreen.cpp b/src/gui/widgets/qsplashscreen.cpp index d1fb686..cc41daa 100644 --- a/src/gui/widgets/qsplashscreen.cpp +++ b/src/gui/widgets/qsplashscreen.cpp @@ -64,7 +64,6 @@ public: int currAlign; inline QSplashScreenPrivate(); - void drawContents(); }; /*! @@ -121,10 +120,9 @@ public: perhaps Qt::WindowStaysOnTopHint. */ QSplashScreen::QSplashScreen(const QPixmap &pixmap, Qt::WindowFlags f) - : QWidget(*(new QSplashScreenPrivate()), 0, Qt::SplashScreen | f) + : QWidget(*(new QSplashScreenPrivate()), 0, Qt::SplashScreen | Qt::FramelessWindowHint | f) { - d_func()->pixmap = pixmap; - setPixmap(d_func()->pixmap); // Does an implicit repaint + setPixmap(pixmap); // Does an implicit repaint } /*! @@ -165,7 +163,6 @@ void QSplashScreen::mousePressEvent(QMouseEvent *) */ void QSplashScreen::repaint() { - d_func()->drawContents(); QWidget::repaint(); QApplication::flush(); } @@ -241,23 +238,13 @@ void QSplashScreen::setPixmap(const QPixmap &pixmap) { Q_D(QSplashScreen); - if (pixmap.hasAlpha()) { - QPixmap opaque(pixmap.size()); - QPainter p(&opaque); - p.fillRect(0, 0, pixmap.width(), pixmap.height(), palette().background()); - p.drawPixmap(0, 0, pixmap); - p.end(); - d->pixmap = opaque; - } else { - d->pixmap = pixmap; - } + d->pixmap = pixmap; + setAttribute(Qt::WA_TranslucentBackground, pixmap.hasAlpha()); - QRect r(0, 0, d->pixmap.size().width(), d->pixmap.size().height()); - resize(d->pixmap.size()); + QRect r(QPoint(), d->pixmap.size()); + resize(r.size()); move(QApplication::desktop()->screenGeometry().center() - r.center()); - if (!isVisible()) - d->drawContents(); - else + if (isVisible()) repaint(); } @@ -271,23 +258,6 @@ const QPixmap QSplashScreen::pixmap() const } /*! - \internal -*/ -void QSplashScreenPrivate::drawContents() -{ - Q_Q(QSplashScreen); - QPixmap textPix = pixmap; - if (!textPix.isNull()) { - QPainter painter(&textPix); - painter.initFrom(q); - q->drawContents(&painter); - QPalette p = q->palette(); - p.setBrush(q->backgroundRole(), QBrush(textPix)); - q->setPalette(p); - } -} - -/*! \internal */ inline QSplashScreenPrivate::QSplashScreenPrivate() : currAlign(Qt::AlignLeft) @@ -304,8 +274,7 @@ void QSplashScreen::drawContents(QPainter *painter) { Q_D(QSplashScreen); painter->setPen(d->currColor); - QRect r = rect(); - r.setRect(r.x() + 5, r.y() + 5, r.width() - 10, r.height() - 10); + QRect r = rect().adjusted(5, 5, -5, -5); if (Qt::mightBeRichText(d->currStatus)) { QTextDocument doc; #ifdef QT_NO_TEXTHTMLPARSER @@ -346,6 +315,13 @@ void QSplashScreen::drawContents(QPainter *painter) /*! \reimp */ bool QSplashScreen::event(QEvent *e) { + if (e->type() == QEvent::Paint) { + Q_D(QSplashScreen); + QPainter painter(this); + if (!d->pixmap.isNull()) + painter.drawPixmap(QPoint(), d->pixmap); + drawContents(&painter); + } return QWidget::event(e); } diff --git a/src/gui/widgets/qstackedwidget.cpp b/src/gui/widgets/qstackedwidget.cpp index de8d3e6..57b43b5 100644 --- a/src/gui/widgets/qstackedwidget.cpp +++ b/src/gui/widgets/qstackedwidget.cpp @@ -49,12 +49,54 @@ QT_BEGIN_NAMESPACE +/** + QStackedLayout does not support height for width (simply because it does not reimplement + heightForWidth() and hasHeightForWidth()). That is not possible to fix without breaking + binary compatibility. (QLayout is subject to multiple inheritance). + However, we can fix QStackedWidget by simply using a modified version of QStackedLayout + that reimplements the hfw-related functions: + */ +class QStackedLayoutHFW : public QStackedLayout +{ +public: + QStackedLayoutHFW(QWidget *parent = 0) : QStackedLayout(parent) {} + bool hasHeightForWidth() const; + int heightForWidth(int width) const; +}; + +bool QStackedLayoutHFW::hasHeightForWidth() const +{ + const int n = count(); + + for (int i = 0; i < n; ++i) { + if (QLayoutItem *item = itemAt(i)) { + if (item->hasHeightForWidth()) + return true; + } + } + return false; +} + +int QStackedLayoutHFW::heightForWidth(int width) const +{ + const int n = count(); + + int hfw = 0; + for (int i = 0; i < n; ++i) { + if (QLayoutItem *item = itemAt(i)) { + hfw = qMax(hfw, item->heightForWidth(width)); + } + } + return hfw; +} + + class QStackedWidgetPrivate : public QFramePrivate { Q_DECLARE_PUBLIC(QStackedWidget) public: QStackedWidgetPrivate():layout(0){} - QStackedLayout *layout; + QStackedLayoutHFW *layout; bool blockChildAdd; }; @@ -138,7 +180,7 @@ QStackedWidget::QStackedWidget(QWidget *parent) : QFrame(*new QStackedWidgetPrivate, parent) { Q_D(QStackedWidget); - d->layout = new QStackedLayout(this); + d->layout = new QStackedLayoutHFW(this); connect(d->layout, SIGNAL(widgetRemoved(int)), this, SIGNAL(widgetRemoved(int))); connect(d->layout, SIGNAL(currentChanged(int)), this, SIGNAL(currentChanged(int))); } diff --git a/src/gui/widgets/qtabbar.cpp b/src/gui/widgets/qtabbar.cpp index bbc7e5d..8a470ee 100644 --- a/src/gui/widgets/qtabbar.cpp +++ b/src/gui/widgets/qtabbar.cpp @@ -1292,6 +1292,8 @@ QSize QTabBar::sizeHint() const QSize QTabBar::minimumSizeHint() const { Q_D(const QTabBar); + if (d->layoutDirty) + const_cast<QTabBarPrivate*>(d)->layoutTabs(); if (!d->useScrollButtons) { QRect r; for (int i = 0; i < d->tabList.count(); ++i) @@ -1304,22 +1306,23 @@ QSize QTabBar::minimumSizeHint() const return QSize(d->rightB->sizeHint().width() * 2 + 75, sizeHint().height()); } +// Compute the most-elided possible text, for minimumSizeHint static QString computeElidedText(Qt::TextElideMode mode, const QString &text) { - if (text.length() <= 7) + if (text.length() <= 3) return text; static const QLatin1String Ellipses("..."); QString ret; switch (mode) { case Qt::ElideRight: - ret = text.left(4) + Ellipses; + ret = text.left(2) + Ellipses; break; case Qt::ElideMiddle: - ret = text.left(2) + Ellipses + text.right(2); + ret = text.left(1) + Ellipses + text.right(1); break; case Qt::ElideLeft: - ret = Ellipses + text.right(4); + ret = Ellipses + text.right(2); break; case Qt::ElideNone: ret = text; @@ -1966,7 +1969,7 @@ void QTabBar::keyPressEvent(QKeyEvent *event) event->ignore(); return; } - int offset = event->key() == (isRightToLeft() ? Qt::Key_Right : Qt::Key_Left) ? -1 : 1; + int offset = event->key() == (isRightToLeft() ? Qt::Key_Right : Qt::Key_Left) ? -1 : 1; d->setCurrentNextEnabledIndex(offset); } diff --git a/src/gui/widgets/qtabwidget.cpp b/src/gui/widgets/qtabwidget.cpp index 4a61935..82dfdef 100644 --- a/src/gui/widgets/qtabwidget.cpp +++ b/src/gui/widgets/qtabwidget.cpp @@ -195,6 +195,7 @@ public: void _q_removeTab(int); void _q_tabMoved(int from, int to); void init(); + bool hasHeightForWidth() const; QTabBar *tabs; QStackedWidget *stack; @@ -246,6 +247,15 @@ void QTabWidgetPrivate::init() } +bool QTabWidgetPrivate::hasHeightForWidth() const +{ + bool has = size_policy.hasHeightForWidth(); + if (!has && stack) + has = qt_widget_private(stack)->hasHeightForWidth(); + return has; +} + + /*! Initialize \a option with the values from this QTabWidget. This method is useful for subclasses when they need a QStyleOptionTabWidgetFrame, but don't want to fill @@ -816,8 +826,8 @@ QSize QTabWidget::sizeHint() const { Q_D(const QTabWidget); QSize lc(0, 0), rc(0, 0); - QStyleOption opt(0); - opt.init(this); + QStyleOptionTabWidgetFrameV2 opt; + initStyleOption(&opt); opt.state = QStyle::State_None; if (d->leftCornerWidget) @@ -865,14 +875,58 @@ QSize QTabWidget::minimumSizeHint() const QSize sz = basicSize(d->pos == North || d->pos == South, lc, rc, s, t); - QStyleOption opt(0); - opt.rect = rect(); + QStyleOptionTabWidgetFrameV2 opt; + initStyleOption(&opt); opt.palette = palette(); opt.state = QStyle::State_None; return style()->sizeFromContents(QStyle::CT_TabWidget, &opt, sz, this) .expandedTo(QApplication::globalStrut()); } +/* + \reimp +*/ +int QTabWidget::heightForWidth(int width) const +{ + Q_D(const QTabWidget); + QStyleOptionTabWidgetFrameV2 opt; + initStyleOption(&opt); + opt.state = QStyle::State_None; + + QSize zero(0,0); + const QSize padding = style()->sizeFromContents(QStyle::CT_TabWidget, &opt, zero, this) + .expandedTo(QApplication::globalStrut()); + + QSize lc(0, 0), rc(0, 0); + if (d->leftCornerWidget) + lc = d->leftCornerWidget->sizeHint(); + if(d->rightCornerWidget) + rc = d->rightCornerWidget->sizeHint(); + if (!d->dirty) { + QTabWidget *that = (QTabWidget*)this; + that->setUpLayout(true); + } + QSize t(d->tabs->sizeHint()); + + if(usesScrollButtons()) + t = t.boundedTo(QSize(200,200)); + else + t = t.boundedTo(QApplication::desktop()->size()); + + const bool tabIsHorizontal = (d->pos == North || d->pos == South); + const int contentsWidth = width - padding.width(); + int stackWidth = contentsWidth; + if (!tabIsHorizontal) + stackWidth -= qMax(t.width(), qMax(lc.width(), rc.width())); + + int stackHeight = d->stack->heightForWidth(stackWidth); + QSize s(stackWidth, stackHeight); + + QSize contentSize = basicSize(tabIsHorizontal, lc, rc, s, t); + return (contentSize + padding).expandedTo(QApplication::globalStrut()).height(); +} + + /*! \reimp */ diff --git a/src/gui/widgets/qtabwidget.h b/src/gui/widgets/qtabwidget.h index 68200c8..ee50655 100644 --- a/src/gui/widgets/qtabwidget.h +++ b/src/gui/widgets/qtabwidget.h @@ -129,6 +129,7 @@ public: QSize sizeHint() const; QSize minimumSizeHint() const; + int heightForWidth(int width) const; void setCornerWidget(QWidget * w, Qt::Corner corner = Qt::TopRightCorner); QWidget * cornerWidget(Qt::Corner corner = Qt::TopRightCorner) const; diff --git a/src/gui/widgets/qtoolbutton.cpp b/src/gui/widgets/qtoolbutton.cpp index 1822db8..c18f660 100644 --- a/src/gui/widgets/qtoolbutton.cpp +++ b/src/gui/widgets/qtoolbutton.cpp @@ -394,9 +394,6 @@ void QToolButton::initStyleOption(QStyleOptionToolButton *option) const option->toolButtonStyle = Qt::ToolButtonTextOnly; else if (option->toolButtonStyle != Qt::ToolButtonTextOnly) option->toolButtonStyle = Qt::ToolButtonIconOnly; - } else { - if (d->text.isEmpty() && option->toolButtonStyle != Qt::ToolButtonIconOnly) - option->toolButtonStyle = Qt::ToolButtonIconOnly; } option->pos = pos(); diff --git a/src/gui/widgets/qworkspace.cpp b/src/gui/widgets/qworkspace.cpp index 7180c4d..5cf67a5 100644 --- a/src/gui/widgets/qworkspace.cpp +++ b/src/gui/widgets/qworkspace.cpp @@ -2923,7 +2923,7 @@ void QWorkspaceChild::setActive(bool b) iconw->setActive(act); update(); - QList<QWidget*> wl = qFindChildren<QWidget*>(childWidget); + QList<QWidget*> wl = childWidget->findChildren<QWidget*>(); if (act) { for (int i = 0; i < wl.size(); ++i) { QWidget *w = wl.at(i); diff --git a/src/gui/widgets/widgets.pri b/src/gui/widgets/widgets.pri index 937b8d6..669b838 100644 --- a/src/gui/widgets/widgets.pri +++ b/src/gui/widgets/widgets.pri @@ -144,7 +144,7 @@ SOURCES += \ widgets/qplaintextedit.cpp \ widgets/qprintpreviewwidget.cpp -!embedded:mac { +!embedded:!qpa:mac { HEADERS += widgets/qmacnativewidget_mac.h \ widgets/qmaccocoaviewcontainer_mac.h OBJECTIVE_HEADERS += widgets/qcocoatoolbardelegate_mac_p.h \ diff --git a/src/imports/folderlistmodel/folderlistmodel.pro b/src/imports/folderlistmodel/folderlistmodel.pro index 8964ab0..44764a9 100644 --- a/src/imports/folderlistmodel/folderlistmodel.pro +++ b/src/imports/folderlistmodel/folderlistmodel.pro @@ -16,8 +16,8 @@ qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH symbian:{ TARGET.UID3 = 0x20021320 - isEmpty(DESTDIR):importFiles.sources = qmlfolderlistmodelplugin$${QT_LIBINFIX}.dll qmldir - else:importFiles.sources = $$DESTDIR/qmlfolderlistmodelplugin$${QT_LIBINFIX}.dll qmldir + isEmpty(DESTDIR):importFiles.files = qmlfolderlistmodelplugin$${QT_LIBINFIX}.dll qmldir + else:importFiles.files = $$DESTDIR/qmlfolderlistmodelplugin$${QT_LIBINFIX}.dll qmldir importFiles.path = $$QT_IMPORTS_BASE_DIR/$$TARGETPATH DEPLOYMENT = importFiles diff --git a/src/imports/gestures/gestures.pro b/src/imports/gestures/gestures.pro index a4c914d..ad872ba 100644 --- a/src/imports/gestures/gestures.pro +++ b/src/imports/gestures/gestures.pro @@ -16,8 +16,8 @@ qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH symbian:{ TARGET.UID3 = 0x2002131F - isEmpty(DESTDIR):importFiles.sources = qmlgesturesplugin$${QT_LIBINFIX}.dll qmldir - else:importFiles.sources = $$DESTDIR/qmlgesturesplugin$${QT_LIBINFIX}.dll qmldir + isEmpty(DESTDIR):importFiles.files = qmlgesturesplugin$${QT_LIBINFIX}.dll qmldir + else:importFiles.files = $$DESTDIR/qmlgesturesplugin$${QT_LIBINFIX}.dll qmldir importFiles.path = $$QT_IMPORTS_BASE_DIR/$$TARGETPATH DEPLOYMENT = importFiles diff --git a/src/imports/particles/particles.pro b/src/imports/particles/particles.pro index bb9da01..90b50e4 100644 --- a/src/imports/particles/particles.pro +++ b/src/imports/particles/particles.pro @@ -20,8 +20,8 @@ qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH symbian:{ TARGET.UID3 = 0x2002131E - isEmpty(DESTDIR):importFiles.sources = qmlparticlesplugin$${QT_LIBINFIX}.dll qmldir - else:importFiles.sources = $$DESTDIR/qmlparticlesplugin$${QT_LIBINFIX}.dll qmldir + isEmpty(DESTDIR):importFiles.files = qmlparticlesplugin$${QT_LIBINFIX}.dll qmldir + else:importFiles.files = $$DESTDIR/qmlparticlesplugin$${QT_LIBINFIX}.dll qmldir importFiles.path = $$QT_IMPORTS_BASE_DIR/$$TARGETPATH DEPLOYMENT = importFiles diff --git a/src/multimedia/audio/audio.pri b/src/multimedia/audio/audio.pri index ae28a26..f03d0ac 100644 --- a/src/multimedia/audio/audio.pri +++ b/src/multimedia/audio/audio.pri @@ -42,8 +42,8 @@ mac { wince*:LIBS += -lcoredll } else:symbian { - INCLUDEPATH += /epoc32/include/mmf/common - INCLUDEPATH += /epoc32/include/mmf/server + INCLUDEPATH += $${EPOCROOT}/epoc32/include/mmf/common + INCLUDEPATH += $${EPOCROOT}/epoc32/include/mmf/server HEADERS += $$PWD/qaudio_symbian_p.h \ $$PWD/qaudiodeviceinfo_symbian_p.h \ diff --git a/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp b/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp index d3dfa5f..727f6a6 100644 --- a/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp +++ b/src/multimedia/audio/qaudiodeviceinfo_mac_p.cpp @@ -133,7 +133,7 @@ QAudioFormat QAudioDeviceInfoInternal::preferredFormat() const } } - delete streams; + delete[] streams; } } @@ -207,7 +207,7 @@ QList<int> QAudioDeviceInfoInternal::frequencyList() rc << vr[i].mMaximum; } - delete vr; + delete[] vr; } } @@ -351,7 +351,7 @@ QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode) } } - delete audioDevices; + delete[] audioDevices; } } diff --git a/src/multimedia/video/qvideosurfaceformat.cpp b/src/multimedia/video/qvideosurfaceformat.cpp index 3afbdc9..3ec40e8 100644 --- a/src/multimedia/video/qvideosurfaceformat.cpp +++ b/src/multimedia/video/qvideosurfaceformat.cpp @@ -502,11 +502,11 @@ QList<QByteArray> QVideoSurfaceFormat::propertyNames() const QVariant QVideoSurfaceFormat::property(const char *name) const { if (qstrcmp(name, "handleType") == 0) { - return qVariantFromValue(d->handleType); + return QVariant::fromValue(d->handleType); } else if (qstrcmp(name, "pixelFormat") == 0) { - return qVariantFromValue(d->pixelFormat); + return QVariant::fromValue(d->pixelFormat); } else if (qstrcmp(name, "handleType") == 0) { - return qVariantFromValue(d->handleType); + return QVariant::fromValue(d->handleType); } else if (qstrcmp(name, "frameSize") == 0) { return d->frameSize; } else if (qstrcmp(name, "frameWidth") == 0) { @@ -516,15 +516,15 @@ QVariant QVideoSurfaceFormat::property(const char *name) const } else if (qstrcmp(name, "viewport") == 0) { return d->viewport; } else if (qstrcmp(name, "scanLineDirection") == 0) { - return qVariantFromValue(d->scanLineDirection); + return QVariant::fromValue(d->scanLineDirection); } else if (qstrcmp(name, "frameRate") == 0) { - return qVariantFromValue(d->frameRate); + return QVariant::fromValue(d->frameRate); } else if (qstrcmp(name, "pixelAspectRatio") == 0) { - return qVariantFromValue(d->pixelAspectRatio); + return QVariant::fromValue(d->pixelAspectRatio); } else if (qstrcmp(name, "sizeHint") == 0) { return sizeHint(); } else if (qstrcmp(name, "yCbCrColorSpace") == 0) { - return qVariantFromValue(d->ycbcrColorSpace); + return QVariant::fromValue(d->ycbcrColorSpace); } else { int id = 0; for (; id < d->propertyNames.count() && d->propertyNames.at(id) != name; ++id) {} @@ -546,7 +546,7 @@ void QVideoSurfaceFormat::setProperty(const char *name, const QVariant &value) } else if (qstrcmp(name, "pixelFormat") == 0) { // read only. } else if (qstrcmp(name, "frameSize") == 0) { - if (qVariantCanConvert<QSize>(value)) { + if (value.canConvert<QSize>()) { d->frameSize = qvariant_cast<QSize>(value); d->viewport = QRect(QPoint(0, 0), d->frameSize); } @@ -555,21 +555,21 @@ void QVideoSurfaceFormat::setProperty(const char *name, const QVariant &value) } else if (qstrcmp(name, "frameHeight") == 0) { // read only. } else if (qstrcmp(name, "viewport") == 0) { - if (qVariantCanConvert<QRect>(value)) + if (value.canConvert<QRect>()) d->viewport = qvariant_cast<QRect>(value); } else if (qstrcmp(name, "scanLineDirection") == 0) { - if (qVariantCanConvert<Direction>(value)) + if (value.canConvert<Direction>()) d->scanLineDirection = qvariant_cast<Direction>(value); } else if (qstrcmp(name, "frameRate") == 0) { - if (qVariantCanConvert<qreal>(value)) + if (value.canConvert<qreal>()) d->frameRate = qvariant_cast<qreal>(value); } else if (qstrcmp(name, "pixelAspectRatio") == 0) { - if (qVariantCanConvert<QSize>(value)) + if (value.canConvert<QSize>()) d->pixelAspectRatio = qvariant_cast<QSize>(value); } else if (qstrcmp(name, "sizeHint") == 0) { // read only. } else if (qstrcmp(name, "yCbCrColorSpace") == 0) { - if (qVariantCanConvert<YCbCrColorSpace>(value)) + if (value.canConvert<YCbCrColorSpace>()) d->ycbcrColorSpace = qvariant_cast<YCbCrColorSpace>(value); } else { int id = 0; diff --git a/src/network/access/access.pri b/src/network/access/access.pri index 6a0cd32..4c21ba5 100644 --- a/src/network/access/access.pri +++ b/src/network/access/access.pri @@ -8,12 +8,10 @@ HEADERS += \ access/qhttpnetworkreply_p.h \ access/qhttpnetworkconnection_p.h \ access/qhttpnetworkconnectionchannel_p.h \ - access/qfilenetworkreply_p.h \ access/qnetworkaccessmanager.h \ access/qnetworkaccessmanager_p.h \ access/qnetworkaccesscache_p.h \ access/qnetworkaccessbackend_p.h \ - access/qnetworkaccessdatabackend_p.h \ access/qnetworkaccessdebugpipebackend_p.h \ access/qnetworkaccesshttpbackend_p.h \ access/qnetworkaccessfilebackend_p.h \ @@ -28,6 +26,8 @@ HEADERS += \ access/qnetworkreply.h \ access/qnetworkreply_p.h \ access/qnetworkreplyimpl_p.h \ + access/qnetworkreplydataimpl_p.h \ + access/qnetworkreplyfileimpl_p.h \ access/qabstractnetworkcache_p.h \ access/qabstractnetworkcache.h \ access/qnetworkdiskcache_p.h \ @@ -41,11 +41,9 @@ SOURCES += \ access/qhttpnetworkreply.cpp \ access/qhttpnetworkconnection.cpp \ access/qhttpnetworkconnectionchannel.cpp \ - access/qfilenetworkreply.cpp \ access/qnetworkaccessmanager.cpp \ access/qnetworkaccesscache.cpp \ access/qnetworkaccessbackend.cpp \ - access/qnetworkaccessdatabackend.cpp \ access/qnetworkaccessdebugpipebackend.cpp \ access/qnetworkaccessfilebackend.cpp \ access/qnetworkaccesscachebackend.cpp \ @@ -56,6 +54,8 @@ SOURCES += \ access/qnetworkrequest.cpp \ access/qnetworkreply.cpp \ access/qnetworkreplyimpl.cpp \ + access/qnetworkreplydataimpl.cpp \ + access/qnetworkreplyfileimpl.cpp \ access/qabstractnetworkcache.cpp \ access/qnetworkdiskcache.cpp diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 4d27531..1ce162c 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -119,6 +119,7 @@ void QHttpNetworkConnectionPrivate::init() { for (int i = 0; i < channelCount; i++) { channels[i].setConnection(this->q_func()); + channels[i].ssl = encrypt; channels[i].init(); } } @@ -559,33 +560,35 @@ void QHttpNetworkConnectionPrivate::fillPipeline(QAbstractSocket *socket) || channels[i].state == QHttpNetworkConnectionChannel::ReadingState)) return; - - //qDebug() << "QHttpNetworkConnectionPrivate::fillPipeline processing highPriorityQueue, size=" << highPriorityQueue.size() << " alreadyPipelined=" << channels[i].alreadyPipelinedRequests.length(); int lengthBefore; while (!highPriorityQueue.isEmpty()) { lengthBefore = channels[i].alreadyPipelinedRequests.length(); fillPipeline(highPriorityQueue, channels[i]); - if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) + if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) { + channels[i].pipelineFlush(); return; + } if (lengthBefore == channels[i].alreadyPipelinedRequests.length()) break; // did not process anything, now do the low prio queue } - //qDebug() << "QHttpNetworkConnectionPrivate::fillPipeline processing lowPriorityQueue, size=" << lowPriorityQueue.size() << " alreadyPipelined=" << channels[i].alreadyPipelinedRequests.length(); while (!lowPriorityQueue.isEmpty()) { lengthBefore = channels[i].alreadyPipelinedRequests.length(); fillPipeline(lowPriorityQueue, channels[i]); - if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) + if (channels[i].alreadyPipelinedRequests.length() >= defaultPipelineLength) { + channels[i].pipelineFlush(); return; + } if (lengthBefore == channels[i].alreadyPipelinedRequests.length()) break; // did not process anything } + channels[i].pipelineFlush(); } // returns true when the processing of a queue has been done diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 02daa50..fe5946a 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel() : socket(0) + , ssl(false) , state(IdleState) , reply(0) , written(0) @@ -90,11 +91,8 @@ void QHttpNetworkConnectionChannel::init() #else socket = new QTcpSocket; #endif - - // limit the socket read buffer size. we will read everything into - // the QHttpNetworkReply anyway, so let's grow only that and not - // here and there. - socket->setReadBufferSize(64*1024); + // Set by QNAM anyway, but let's be safe here + socket->setProxy(QNetworkProxy::NoProxy); QObject::connect(socket, SIGNAL(bytesWritten(qint64)), this, SLOT(_q_bytesWritten(qint64)), @@ -174,11 +172,12 @@ bool QHttpNetworkConnectionChannel::sendRequest() written = 0; // excluding the header bytesTotal = 0; - reply->d_func()->clear(); - reply->d_func()->connection = connection; - reply->d_func()->connectionChannel = this; - reply->d_func()->autoDecompress = request.d->autoDecompress; - reply->d_func()->pipeliningUsed = false; + QHttpNetworkReplyPrivate *replyPrivate = reply->d_func(); + replyPrivate->clear(); + replyPrivate->connection = connection; + replyPrivate->connectionChannel = this; + replyPrivate->autoDecompress = request.d->autoDecompress; + replyPrivate->pipeliningUsed = false; pendingEncrypt = false; // if the url contains authentication parameters, use the new ones @@ -338,7 +337,6 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() return; } - qint64 bytes = 0; QAbstractSocket::SocketState socketState = socket->state(); // connection might be closed to signal the end of data @@ -359,12 +357,14 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() } // read loop for the response - while (socket->bytesAvailable()) { + qint64 bytes = 0; + qint64 lastBytes = bytes; + do { + lastBytes = bytes; + QHttpNetworkReplyPrivate::ReplyState state = reply->d_func()->state; switch (state) { case QHttpNetworkReplyPrivate::NothingDoneState: { - // only eat whitespace on the first call - eatWhitespace(); state = reply->d_func()->state = QHttpNetworkReplyPrivate::ReadingStatusState; // fallthrough } @@ -388,6 +388,7 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() return; } bytes += headerBytes; + // If headers were parsed successfully now it is the ReadingDataState if (replyPrivate->state == QHttpNetworkReplyPrivate::ReadingDataState) { if (replyPrivate->isGzipped() && replyPrivate->autoDecompress) { // remove the Content-Length from header @@ -402,6 +403,10 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() } if (replyPrivate->shouldEmitSignals()) emit reply->headerChanged(); + // After headerChanged had been emitted + // we can suddenly have a replyPrivate->userProvidedDownloadBuffer + // this is handled in the ReadingDataState however + if (!replyPrivate->expectContent()) { replyPrivate->state = QHttpNetworkReplyPrivate::AllDoneState; allDone(); @@ -423,22 +428,29 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() // to the read buffer maximum size, but we don't care since they should be small. return; } - if (!replyPrivate->isChunked() && !replyPrivate->autoDecompress - && replyPrivate->bodyLength > 0) { - // bulk files like images should fulfill these properties and - // we can therefore save on memory copying - bytes = replyPrivate->readBodyFast(socket, &replyPrivate->responseData); - replyPrivate->totalProgress += bytes; + + if (replyPrivate->userProvidedDownloadBuffer) { + // the user provided a direct buffer where we should put all our data in. + // this only works when we can tell the user the content length and he/she can allocate + // the buffer in that size. + // note that this call will read only from the still buffered data + qint64 haveRead = replyPrivate->readBodyVeryFast(socket, replyPrivate->userProvidedDownloadBuffer + replyPrivate->totalProgress); + bytes += haveRead; + replyPrivate->totalProgress += haveRead; + + // the user will get notified of it via progress signal + if (haveRead > 0) + emit reply->dataReadProgress(replyPrivate->totalProgress, replyPrivate->bodyLength); + } else if (!replyPrivate->isChunked() && !replyPrivate->autoDecompress + && replyPrivate->bodyLength > 0) { + // bulk files like images should fulfill these properties and + // we can therefore save on memory copying + qint64 haveRead = replyPrivate->readBodyFast(socket, &replyPrivate->responseData); + bytes += haveRead; + replyPrivate->totalProgress += haveRead; if (replyPrivate->shouldEmitSignals()) { - QPointer<QHttpNetworkReply> replyPointer = reply; emit reply->readyRead(); - // make sure that the reply is valid - if (replyPointer.isNull()) - return; emit reply->dataReadProgress(replyPrivate->totalProgress, replyPrivate->bodyLength); - // make sure that the reply is valid - if (replyPointer.isNull()) - return; } } else @@ -446,8 +458,9 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() // use the traditional slower reading (for compressed encoding, chunked encoding, // no content-length etc) QByteDataBuffer byteDatas; - bytes = replyPrivate->readBody(socket, &byteDatas); - if (bytes) { + qint64 haveRead = replyPrivate->readBody(socket, &byteDatas); + if (haveRead) { + bytes += haveRead; if (replyPrivate->autoDecompress) replyPrivate->appendCompressedReplyData(byteDatas); else @@ -456,17 +469,10 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() if (!replyPrivate->autoDecompress) { replyPrivate->totalProgress += bytes; if (replyPrivate->shouldEmitSignals()) { - QPointer<QHttpNetworkReply> replyPointer = reply; // important: At the point of this readyRead(), the byteDatas list must be empty, // else implicit sharing will trigger memcpy when the user is reading data! emit reply->readyRead(); - // make sure that the reply is valid - if (replyPointer.isNull()) - return; emit reply->dataReadProgress(replyPrivate->totalProgress, replyPrivate->bodyLength); - // make sure that the reply is valid - if (replyPointer.isNull()) - return; } } #ifndef QT_NO_COMPRESS @@ -488,7 +494,7 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() default: break; } - } + } while (bytes != lastBytes && reply); } // called when unexpectedly reading a -1 or when data is expected but socket is closed @@ -531,7 +537,7 @@ bool QHttpNetworkConnectionChannel::ensureConnection() if (socketState != QAbstractSocket::ConnectedState) { // connect to the host if not already connected. state = QHttpNetworkConnectionChannel::ConnectingState; - pendingEncrypt = connection->d_func()->encrypt; + pendingEncrypt = ssl; // reset state pipeliningSupported = PipeliningSupportUnknown; @@ -554,23 +560,43 @@ bool QHttpNetworkConnectionChannel::ensureConnection() #ifndef QT_NO_NETWORKPROXY // HTTPS always use transparent proxy. - if (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy && !connection->d_func()->encrypt) { + if (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy && !ssl) { connectHost = connection->d_func()->networkProxy.hostName(); connectPort = connection->d_func()->networkProxy.port(); } #endif - if (connection->d_func()->encrypt) { + if (ssl) { #ifndef QT_NO_OPENSSL QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket); sslSocket->connectToHostEncrypted(connectHost, connectPort); if (ignoreAllSslErrors) sslSocket->ignoreSslErrors(); sslSocket->ignoreSslErrors(ignoreSslErrorsList); + + // limit the socket read buffer size. we will read everything into + // the QHttpNetworkReply anyway, so let's grow only that and not + // here and there. + socket->setReadBufferSize(64*1024); #else connection->d_func()->emitReplyError(socket, reply, QNetworkReply::ProtocolUnknownError); #endif } else { - socket->connectToHost(connectHost, connectPort); + // In case of no proxy we can use the Unbuffered QTcpSocket + if (connection->d_func()->networkProxy.type() == QNetworkProxy::NoProxy + && connection->cacheProxy().type() == QNetworkProxy::NoProxy + && connection->transparentProxy().type() == QNetworkProxy::NoProxy) { + socket->connectToHost(connectHost, connectPort, QIODevice::ReadWrite | QIODevice::Unbuffered); + // For an Unbuffered QTcpSocket, the read buffer size has a special meaning. + socket->setReadBufferSize(1*1024); + + } else { + socket->connectToHost(connectHost, connectPort); + + // limit the socket read buffer size. we will read everything into + // the QHttpNetworkReply anyway, so let's grow only that and not + // here and there. + socket->setReadBufferSize(64*1024); + } } return false; } @@ -600,18 +626,10 @@ bool QHttpNetworkConnectionChannel::expand(bool dataComplete) reply->d_func()->totalProgress += inflated.size(); reply->d_func()->appendUncompressedReplyData(inflated); if (reply->d_func()->shouldEmitSignals()) { - QPointer<QHttpNetworkReply> replyPointer = reply; // important: At the point of this readyRead(), inflated must be cleared, // else implicit sharing will trigger memcpy when the user is reading data! emit reply->readyRead(); - // make sure that the reply is valid - if (replyPointer.isNull()) - return true; emit reply->dataReadProgress(reply->d_func()->totalProgress, 0); - // make sure that the reply is valid - if (replyPointer.isNull()) - return true; - } } } else { @@ -689,10 +707,15 @@ void QHttpNetworkConnectionChannel::allDone() // this was wrong, allDone gets called from that function anyway. } } else if (alreadyPipelinedRequests.isEmpty() && socket->bytesAvailable() > 0) { - eatWhitespace(); // this is weird. we had nothing pipelined but still bytes available. better close it. - if (socket->bytesAvailable() > 0) - close(); + //if (socket->bytesAvailable() > 0) + // close(); + // + // FIXME + // We do not close it anymore now, but should introduce this again after having fixed + // the chunked decoder in QHttpNetworkReply to read the whitespace after the last chunk. + // (Currently this is worked around by readStatus in the QHttpNetworkReply ignoring + // leading whitespace. QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } else if (alreadyPipelinedRequests.isEmpty()) { if (qobject_cast<QHttpNetworkConnection*>(connection)) @@ -739,30 +762,6 @@ void QHttpNetworkConnectionChannel::requeueCurrentlyPipelinedRequests() QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } -void QHttpNetworkConnectionChannel::eatWhitespace() -{ - char c; - do { - qint64 ret = socket->peek(&c, 1); - - // nothing read, fine. - if (ret == 0) - return; - - // EOF from socket? - if (ret == -1) - return; // FIXME, we need to stop processing. however the next stuff done will also do that. - - // read all whitespace and line endings - if (c == 11 || c == '\n' || c == '\r' || c == ' ' || c == 31) { - socket->read(&c, 1); - continue; - } else { - break; - } - } while(true); -} - void QHttpNetworkConnectionChannel::handleStatus() { Q_ASSERT(socket); @@ -823,7 +822,7 @@ bool QHttpNetworkConnectionChannel::resetUploadData() } -void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair) +void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair) { // this is only called for simple GET @@ -836,16 +835,32 @@ void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair) reply->d_func()->pipeliningUsed = true; #ifndef QT_NO_NETWORKPROXY - QByteArray header = QHttpNetworkRequestPrivate::header(request, - (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy)); + pipeline.append(QHttpNetworkRequestPrivate::header(request, + (connection->d_func()->networkProxy.type() != QNetworkProxy::NoProxy))); #else - QByteArray header = QHttpNetworkRequestPrivate::header(request, false); + pipeline.append(QHttpNetworkRequestPrivate::header(request, false)); #endif - socket->write(header); alreadyPipelinedRequests.append(pair); + + // pipelineFlush() needs to be called at some point afterwards } +void QHttpNetworkConnectionChannel::pipelineFlush() +{ + if (pipeline.isEmpty()) + return; + + // The goal of this is so that we have everything in one TCP packet. + // For the Unbuffered QTcpSocket this is manually needed, the buffered + // QTcpSocket does it automatically. + // Also, sometimes the OS does it for us (Nagle's algorithm) but that + // happens only sometimes. + socket->write(pipeline); + pipeline.clear(); +} + + void QHttpNetworkConnectionChannel::closeAndResendCurrentRequest() { requeueCurrentlyPipelinedRequests(); @@ -878,6 +893,19 @@ bool QHttpNetworkConnectionChannel::isSocketReading() const //private slots void QHttpNetworkConnectionChannel::_q_readyRead() { + // We got a readyRead but no bytes are available.. + // This happens for the Unbuffered QTcpSocket + // Also check if socket is in ConnectedState since + // this function may also be invoked via the event loop. + if (socket->state() == QAbstractSocket::ConnectedState && socket->bytesAvailable() == 0) { + char c; + qint64 ret = socket->peek(&c, 1); + if (ret < 0) { + socket->disconnectFromHost(); + return; + } + } + if (isSocketWaiting() || isSocketReading()) { state = QHttpNetworkConnectionChannel::ReadingState; if (reply) diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index 442086a..07bb4a6 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -98,6 +98,7 @@ public: BusyState = (ConnectingState|WritingState|WaitingState|ReadingState) }; QAbstractSocket *socket; + bool ssl; ChannelState state; QHttpNetworkRequest request; // current request QHttpNetworkReply *reply; // current reply for this request @@ -124,7 +125,11 @@ public: }; PipeliningSupport pipeliningSupported; QList<HttpMessagePair> alreadyPipelinedRequests; - + QByteArray pipeline; // temporary buffer that gets sent to socket in pipelineFlush + void pipelineInto(HttpMessagePair &pair); + void pipelineFlush(); + void requeueCurrentlyPipelinedRequests(); + void detectPipeliningSupport(); QHttpNetworkConnectionChannel(); @@ -144,15 +149,9 @@ public: bool resetUploadData(); // return true if resetting worked or there is no upload data - void pipelineInto(HttpMessagePair &pair); - void requeueCurrentlyPipelinedRequests(); - void detectPipeliningSupport(); - void handleUnexpectedEOF(); void closeAndResendCurrentRequest(); - void eatWhitespace(); - bool isSocketBusy() const; bool isSocketWriting() const; bool isSocketWaiting() const; diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index e4eb7c4..3e98dcc 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -119,6 +119,7 @@ void QHttpNetworkReply::setRequest(const QHttpNetworkRequest &request) { Q_D(QHttpNetworkReply); d->request = request; + d->ssl = request.isSsl(); } int QHttpNetworkReply::statusCode() const @@ -195,6 +196,25 @@ void QHttpNetworkReply::setDownstreamLimited(bool dsl) d->connection->d_func()->readMoreLater(this); } +bool QHttpNetworkReply::supportsUserProvidedDownloadBuffer() +{ + Q_D(QHttpNetworkReply); + return (!d->isChunked() && !d->autoDecompress && d->bodyLength > 0); +} + +void QHttpNetworkReply::setUserProvidedDownloadBuffer(char* b) +{ + Q_D(QHttpNetworkReply); + if (supportsUserProvidedDownloadBuffer()) + d->userProvidedDownloadBuffer = b; +} + +char* QHttpNetworkReply::userProvidedDownloadBuffer() +{ + Q_D(QHttpNetworkReply); + return d->userProvidedDownloadBuffer; +} + bool QHttpNetworkReply::isFinished() const { return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState; @@ -212,7 +232,10 @@ QHttpNetworkConnection* QHttpNetworkReply::connection() QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) - : QHttpNetworkHeaderPrivate(newUrl), state(NothingDoneState), statusCode(100), + : QHttpNetworkHeaderPrivate(newUrl) + , state(NothingDoneState) + , ssl(false) + , statusCode(100), majorVersion(0), minorVersion(0), bodyLength(0), contentRead(0), totalProgress(0), chunkedTransferEncoding(false), connectionCloseEnabled(true), @@ -220,6 +243,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) currentChunkSize(0), currentChunkRead(0), connection(0), initInflate(false), autoDecompress(false), responseData(), requestIsPrepared(false) ,pipeliningUsed(false), downstreamLimited(false) + ,userProvidedDownloadBuffer(0) { } @@ -453,6 +477,8 @@ qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket) return -1; // unexpected EOF else if (haveRead == 0) break; // read more later + else if (haveRead == 1 && bytes == 0 && (c == 11 || c == '\n' || c == '\r' || c == ' ' || c == 31)) + continue; // Ignore all whitespace that was trailing froma previous request on that socket bytes++; @@ -628,12 +654,32 @@ bool QHttpNetworkReplyPrivate::isConnectionCloseEnabled() // note this function can only be used for non-chunked, non-compressed with // known content length +qint64 QHttpNetworkReplyPrivate::readBodyVeryFast(QAbstractSocket *socket, char *b) +{ + // This first read is to flush the buffer inside the socket + qint64 haveRead = 0; + haveRead = socket->read(b, bodyLength - contentRead); + if (haveRead == -1) { + return 0; // ### error checking here; + } + contentRead += haveRead; + + if (contentRead == bodyLength) { + state = AllDoneState; + } + + return haveRead; +} + +// note this function can only be used for non-chunked, non-compressed with +// known content length qint64 QHttpNetworkReplyPrivate::readBodyFast(QAbstractSocket *socket, QByteDataBuffer *rb) { + qint64 toBeRead = qMin(socket->bytesAvailable(), bodyLength - contentRead); QByteArray bd; bd.resize(toBeRead); - qint64 haveRead = socket->read(bd.data(), bd.size()); + qint64 haveRead = socket->read(bd.data(), toBeRead); if (haveRead == -1) { bd.clear(); return 0; // ### error checking here; @@ -655,29 +701,34 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QByteDataBuff { qint64 bytes = 0; if (isChunked()) { - bytes += readReplyBodyChunked(socket, out); // chunked transfer encoding (rfc 2616, sec 3.6) - } else if (bodyLength > 0) { // we have a Content-Length + // chunked transfer encoding (rfc 2616, sec 3.6) + bytes += readReplyBodyChunked(socket, out); + } else if (bodyLength > 0) { + // we have a Content-Length bytes += readReplyBodyRaw(socket, out, bodyLength - contentRead); if (contentRead + bytes == bodyLength) state = AllDoneState; } else { + // no content length. just read what's possible bytes += readReplyBodyRaw(socket, out, socket->bytesAvailable()); } contentRead += bytes; return bytes; } -qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QIODevice *in, QByteDataBuffer *out, qint64 size) +qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QAbstractSocket *socket, QByteDataBuffer *out, qint64 size) { + // FIXME get rid of this function and just use readBodyFast and give it socket->bytesAvailable() qint64 bytes = 0; - Q_ASSERT(in); + Q_ASSERT(socket); Q_ASSERT(out); - int toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, in->bytesAvailable())); + int toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, socket->bytesAvailable())); + while (toBeRead > 0) { QByteArray byteData; byteData.resize(toBeRead); - qint64 haveRead = in->read(byteData.data(), byteData.size()); + qint64 haveRead = socket->read(byteData.data(), byteData.size()); if (haveRead <= 0) { // ### error checking here byteData.clear(); @@ -689,25 +740,35 @@ qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QIODevice *in, QByteDataBuffer bytes += haveRead; size -= haveRead; - toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, in->bytesAvailable())); + toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, socket->bytesAvailable())); } return bytes; } -qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *in, QByteDataBuffer *out) +qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QAbstractSocket *socket, QByteDataBuffer *out) { qint64 bytes = 0; - while (in->bytesAvailable()) { // while we can read from input - // if we are done with the current chunk, get the size of the new chunk + while (socket->bytesAvailable()) { if (currentChunkRead >= currentChunkSize) { + // For the first chunk and when we're done with a chunk currentChunkSize = 0; currentChunkRead = 0; if (bytes) { + // After a chunk char crlf[2]; - bytes += in->read(crlf, 2); // read the "\r\n" after the chunk + // read the "\r\n" after the chunk + qint64 haveRead = socket->read(crlf, 2); + // FIXME: This code is slightly broken and not optimal. What if the 2 bytes are not available yet?! + // For nice reasons (the toLong in getChunkSize accepting \n at the beginning + // it right now still works, but we should definitely fix this. + + if (haveRead != 2) + return bytes; // FIXME + bytes += haveRead; } - bytes += getChunkSize(in, ¤tChunkSize); + // Note that chunk size gets stored in currentChunkSize, what is returned is the bytes read + bytes += getChunkSize(socket, ¤tChunkSize); if (currentChunkSize == -1) break; } @@ -717,8 +778,8 @@ qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *in, QByteDataBu break; } - // otherwise, try to read what is missing for this chunk - qint64 haveRead = readReplyBodyRaw (in, out, currentChunkSize - currentChunkRead); + // otherwise, try to begin reading this chunk / to read what is missing for this chunk + qint64 haveRead = readReplyBodyRaw (socket, out, currentChunkSize - currentChunkRead); currentChunkRead += haveRead; bytes += haveRead; @@ -728,22 +789,25 @@ qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *in, QByteDataBu return bytes; } -qint64 QHttpNetworkReplyPrivate::getChunkSize(QIODevice *in, qint64 *chunkSize) +qint64 QHttpNetworkReplyPrivate::getChunkSize(QAbstractSocket *socket, qint64 *chunkSize) { qint64 bytes = 0; char crlf[2]; *chunkSize = -1; - int bytesAvailable = in->bytesAvailable(); + + int bytesAvailable = socket->bytesAvailable(); + // FIXME rewrite to permanent loop without bytesAvailable while (bytesAvailable > bytes) { - qint64 sniffedBytes = in->peek(crlf, 2); + qint64 sniffedBytes = socket->peek(crlf, 2); int fragmentSize = fragment.size(); + // check the next two bytes for a "\r\n", skip blank lines if ((fragmentSize && sniffedBytes == 2 && crlf[0] == '\r' && crlf[1] == '\n') ||(fragmentSize > 1 && fragment.endsWith('\r') && crlf[0] == '\n')) { - bytes += in->read(crlf, 1); // read the \r or \n + bytes += socket->read(crlf, 1); // read the \r or \n if (crlf[0] == '\r') - bytes += in->read(crlf, 1); // read the \n + bytes += socket->read(crlf, 1); // read the \n bool ok = false; // ignore the chunk-extension fragment = fragment.mid(0, fragment.indexOf(';')).trimmed(); @@ -753,10 +817,15 @@ qint64 QHttpNetworkReplyPrivate::getChunkSize(QIODevice *in, qint64 *chunkSize) } else { // read the fragment to the buffer char c = 0; - bytes += in->read(&c, 1); + qint64 haveRead = socket->read(&c, 1); + if (haveRead < 0) { + return -1; // FIXME + } + bytes += haveRead; fragment.append(c); } } + return bytes; } diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index 3f79d81..65d1887 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -128,6 +128,10 @@ public: QByteArray readAny(); void setDownstreamLimited(bool t); + bool supportsUserProvidedDownloadBuffer(); + void setUserProvidedDownloadBuffer(char*); + char* userProvidedDownloadBuffer(); + bool isFinished() const; bool isPipeliningUsed() const; @@ -149,6 +153,7 @@ Q_SIGNALS: void finished(); void finishedWithError(QNetworkReply::NetworkError errorCode, const QString &detail = QString()); void headerChanged(); + // FIXME we need to change this to qint64! void dataReadProgress(int done, int total); void dataSendProgress(qint64 done, qint64 total); void cacheCredentials(const QHttpNetworkRequest &request, QAuthenticator *authenticator); @@ -174,15 +179,16 @@ public: qint64 readHeader(QAbstractSocket *socket); void parseHeader(const QByteArray &header); qint64 readBody(QAbstractSocket *socket, QByteDataBuffer *out); + qint64 readBodyVeryFast(QAbstractSocket *socket, char *b); qint64 readBodyFast(QAbstractSocket *socket, QByteDataBuffer *rb); bool findChallenge(bool forProxy, QByteArray &challenge) const; QAuthenticatorPrivate::Method authenticationMethod(bool isProxy) const; void clear(); void clearHttpLayerInformation(); - qint64 readReplyBodyRaw(QIODevice *in, QByteDataBuffer *out, qint64 size); - qint64 readReplyBodyChunked(QIODevice *in, QByteDataBuffer *out); - qint64 getChunkSize(QIODevice *in, qint64 *chunkSize); + qint64 readReplyBodyRaw(QAbstractSocket *in, QByteDataBuffer *out, qint64 size); + qint64 readReplyBodyChunked(QAbstractSocket *in, QByteDataBuffer *out); + qint64 getChunkSize(QAbstractSocket *in, qint64 *chunkSize); void appendUncompressedReplyData(QByteArray &qba); void appendUncompressedReplyData(QByteDataBuffer &data); @@ -211,6 +217,7 @@ public: } state; QHttpNetworkRequest request; + bool ssl; int statusCode; int majorVersion; int minorVersion; @@ -240,6 +247,8 @@ public: bool pipeliningUsed; bool downstreamLimited; + + char* userProvidedDownloadBuffer; }; diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp index 639025e..d2f3212 100644 --- a/src/network/access/qhttpnetworkrequest.cpp +++ b/src/network/access/qhttpnetworkrequest.cpp @@ -63,6 +63,7 @@ QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequest pipeliningAllowed = other.pipeliningAllowed; customVerb = other.customVerb; withCredentials = other.withCredentials; + ssl = other.ssl; } QHttpNetworkRequestPrivate::~QHttpNetworkRequestPrivate() @@ -73,6 +74,7 @@ bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &ot { return QHttpNetworkHeaderPrivate::operator==(other) && (operation == other.operation) + && (ssl == other.ssl) && (uploadByteDevice == other.uploadByteDevice); } @@ -199,6 +201,15 @@ void QHttpNetworkRequest::setUrl(const QUrl &url) d->url = url; } +bool QHttpNetworkRequest::isSsl() const +{ + return d->ssl; +} +void QHttpNetworkRequest::setSsl(bool s) +{ + d->ssl = s; +} + qint64 QHttpNetworkRequest::contentLength() const { return d->contentLength(); diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h index 15cab73..123babc 100644 --- a/src/network/access/qhttpnetworkrequest_p.h +++ b/src/network/access/qhttpnetworkrequest_p.h @@ -116,6 +116,9 @@ public: bool withCredentials() const; void setWithCredentials(bool b); + bool isSsl() const; + void setSsl(bool); + void setUploadByteDevice(QNonContiguousByteDevice *bd); QNonContiguousByteDevice* uploadByteDevice() const; @@ -146,6 +149,7 @@ public: bool autoDecompress; bool pipeliningAllowed; bool withCredentials; + bool ssl; }; diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp index 0a0987a..86dd59b 100644 --- a/src/network/access/qnetworkaccessbackend.cpp +++ b/src/network/access/qnetworkaccessbackend.cpp @@ -146,7 +146,7 @@ QNonContiguousByteDevice* QNetworkAccessBackend::createUploadByteDevice() // and the special backends need to access this. void QNetworkAccessBackend::emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal) { - if (reply->isFinished()) + if (reply->isFinished) return; reply->emitUploadProgress(bytesSent, bytesTotal); } @@ -252,6 +252,17 @@ void QNetworkAccessBackend::writeDownstreamData(QIODevice *data) reply->appendDownstreamData(data); } +// not actually appending data, it was already written to the user buffer +void QNetworkAccessBackend::writeDownstreamDataDownloadBuffer(qint64 bytesReceived, qint64 bytesTotal) +{ + reply->appendDownstreamDataDownloadBuffer(bytesReceived, bytesTotal); +} + +char* QNetworkAccessBackend::getDownloadBuffer(qint64 size) +{ + return reply->getDownloadBuffer(size); +} + QVariant QNetworkAccessBackend::header(QNetworkRequest::KnownHeaders header) const { return reply->q_func()->header(header); diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h index 4fe6de6..9f8a01f 100644 --- a/src/network/access/qnetworkaccessbackend_p.h +++ b/src/network/access/qnetworkaccessbackend_p.h @@ -177,6 +177,10 @@ protected: qint64 nextDownstreamBlockSize() const; void writeDownstreamData(QByteDataBuffer &list); + // not actually appending data, it was already written to the user buffer + void writeDownstreamDataDownloadBuffer(qint64, qint64); + char* getDownloadBuffer(qint64); + public slots: // for task 251801, needs to be a slot to be called asynchronously void writeDownstreamData(QIODevice *data); diff --git a/src/network/access/qnetworkaccessdatabackend.cpp b/src/network/access/qnetworkaccessdatabackend.cpp deleted file mode 100644 index efb6e3e..0000000 --- a/src/network/access/qnetworkaccessdatabackend.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/**************************************************************************** -** -** 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 QtNetwork 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 "qnetworkaccessdatabackend_p.h" -#include "qnetworkrequest.h" -#include "qnetworkreply.h" -#include "qurlinfo.h" -#include "private/qdataurl_p.h" -#include <qcoreapplication.h> - -QT_BEGIN_NAMESPACE - -QNetworkAccessBackend * -QNetworkAccessDataBackendFactory::create(QNetworkAccessManager::Operation, - const QNetworkRequest &request) const -{ - if (request.url().scheme() == QLatin1String("data")) - return new QNetworkAccessDataBackend; - - return 0; -} - -QNetworkAccessDataBackend::QNetworkAccessDataBackend() -{ -} - -QNetworkAccessDataBackend::~QNetworkAccessDataBackend() -{ -} - -void QNetworkAccessDataBackend::open() -{ - QUrl uri = request().url(); - - if (operation() != QNetworkAccessManager::GetOperation && - operation() != QNetworkAccessManager::HeadOperation) { - // data: doesn't support anything but GET - const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend", - "Operation not supported on %1") - .arg(uri.toString()); - error(QNetworkReply::ContentOperationNotPermittedError, msg); - finished(); - return; - } - - QPair<QString, QByteArray> decoded = qDecodeDataUrl(uri); - - if (! decoded.first.isNull()) { - setHeader(QNetworkRequest::ContentTypeHeader, decoded.first); - setHeader(QNetworkRequest::ContentLengthHeader, decoded.second.size()); - emit metaDataChanged(); - - QByteDataBuffer list; - list.append(decoded.second); - decoded.second.clear(); // important because of implicit sharing! - writeDownstreamData(list); - - finished(); - return; - } - - // something wrong with this URI - const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend", - "Invalid URI: %1").arg(uri.toString()); - error(QNetworkReply::ProtocolFailure, msg); - finished(); -} - -void QNetworkAccessDataBackend::closeDownstreamChannel() -{ -} - -void QNetworkAccessDataBackend::closeUpstreamChannel() -{ -} - -bool QNetworkAccessDataBackend::waitForDownstreamReadyRead(int) -{ - return false; -} - -bool QNetworkAccessDataBackend::waitForUpstreamBytesWritten(int) -{ - return false; -} - -QT_END_NAMESPACE diff --git a/src/network/access/qnetworkaccessfilebackend.cpp b/src/network/access/qnetworkaccessfilebackend.cpp index 4560153..710c258 100644 --- a/src/network/access/qnetworkaccessfilebackend.cpp +++ b/src/network/access/qnetworkaccessfilebackend.cpp @@ -65,10 +65,15 @@ QNetworkAccessFileBackendFactory::create(QNetworkAccessManager::Operation op, } QUrl url = request.url(); - if (url.scheme() == QLatin1String("qrc") || !url.toLocalFile().isEmpty()) + if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0 || url.isLocalFile()) { return new QNetworkAccessFileBackend; - else if (!url.isEmpty() && url.authority().isEmpty()) { - // check if QFile could, in theory, open this URL + } else if (!url.scheme().isEmpty() && url.authority().isEmpty()) { + // check if QFile could, in theory, open this URL via the file engines + // it has to be in the format: + // prefix:path/to/file + // or prefix:/path/to/file + // + // this construct here must match the one below in open() QFileInfo fi(url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery)); if (fi.exists() || (op == QNetworkAccessManager::PutOperation && fi.dir().exists())) return new QNetworkAccessFileBackend; diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp index 1a59011..da336d0 100644 --- a/src/network/access/qnetworkaccessftpbackend.cpp +++ b/src/network/access/qnetworkaccessftpbackend.cpp @@ -77,7 +77,7 @@ QNetworkAccessFtpBackendFactory::create(QNetworkAccessManager::Operation op, } QUrl url = request.url(); - if (url.scheme() == QLatin1String("ftp")) + if (url.scheme().compare(QLatin1String("ftp"), Qt::CaseInsensitive) == 0) return new QNetworkAccessFtpBackend; return 0; } diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index 2a0daf8..afbb706 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -524,6 +524,9 @@ void QNetworkAccessHttpBackend::postRequest() break; // can't happen } + bool encrypt = (url().scheme().toLower() == QLatin1String("https")); + httpRequest.setSsl(encrypt); + httpRequest.setUrl(url()); QList<QByteArray> headers = request().rawHeaderList(); @@ -579,7 +582,6 @@ void QNetworkAccessHttpBackend::postRequest() SLOT(sslErrors(QList<QSslError>))); #endif - connect(httpReply, SIGNAL(readyRead()), SLOT(replyReadyRead())); connect(httpReply, SIGNAL(finished()), SLOT(replyFinished())); connect(httpReply, SIGNAL(finishedWithError(QNetworkReply::NetworkError,QString)), SLOT(httpError(QNetworkReply::NetworkError,QString))); @@ -850,9 +852,33 @@ void QNetworkAccessHttpBackend::replyHeaderChanged() if (!isCachingEnabled()) setCachingEnabled(true); } + + // Check if a download buffer is supported from the HTTP reply + char *buf = 0; + if (httpReply->supportsUserProvidedDownloadBuffer()) { + // Check if a download buffer is supported by the user + buf = getDownloadBuffer(httpReply->contentLength()); + if (buf) { + httpReply->setUserProvidedDownloadBuffer(buf); + // If there is a download buffer we react on the progress signal + connect(httpReply, SIGNAL(dataReadProgress(int,int)), SLOT(replyDownloadProgressSlot(int,int))); + } + } + + // If there is no buffer, we react on the readyRead signal + if (!buf) { + connect(httpReply, SIGNAL(readyRead()), SLOT(replyReadyRead())); + } + metaDataChanged(); } +void QNetworkAccessHttpBackend::replyDownloadProgressSlot(int received, int total) +{ + // we can be sure here that there is a download buffer + writeDownstreamDataDownloadBuffer(received, total); +} + void QNetworkAccessHttpBackend::httpAuthenticationRequired(const QHttpNetworkRequest &, QAuthenticator *auth) { @@ -1137,6 +1163,11 @@ bool QNetworkAccessHttpBackend::canResume() const return false; } + // If we're using a download buffer then we don't support resuming/migration + // right now. Too much trouble. + if (httpReply->userProvidedDownloadBuffer()) + return false; + return true; } diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h index 568b2ee..ad0a7ba 100644 --- a/src/network/access/qnetworkaccesshttpbackend_p.h +++ b/src/network/access/qnetworkaccesshttpbackend_p.h @@ -104,6 +104,7 @@ private slots: void replyReadyRead(); void replyFinished(); void replyHeaderChanged(); + void replyDownloadProgressSlot(int,int); void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth); void httpCacheCredentials(const QHttpNetworkRequest &request, QAuthenticator *auth); void httpError(QNetworkReply::NetworkError error, const QString &errorString); diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index e5f4d5a..5ae1078 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -52,9 +52,9 @@ #include "qnetworkaccesshttpbackend_p.h" #include "qnetworkaccessftpbackend_p.h" #include "qnetworkaccessfilebackend_p.h" -#include "qnetworkaccessdatabackend_p.h" #include "qnetworkaccessdebugpipebackend_p.h" -#include "qfilenetworkreply_p.h" +#include "qnetworkreplydataimpl_p.h" +#include "qnetworkreplyfileimpl_p.h" #include "QtCore/qbuffer.h" #include "QtCore/qurl.h" @@ -69,7 +69,6 @@ QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QNetworkAccessHttpBackendFactory, httpBackend) #endif // QT_NO_HTTP Q_GLOBAL_STATIC(QNetworkAccessFileBackendFactory, fileBackend) -Q_GLOBAL_STATIC(QNetworkAccessDataBackendFactory, dataBackend) #ifndef QT_NO_FTP Q_GLOBAL_STATIC(QNetworkAccessFtpBackendFactory, ftpBackend) #endif // QT_NO_FTP @@ -83,7 +82,7 @@ static void ensureInitialized() #ifndef QT_NO_HTTP (void) httpBackend(); #endif // QT_NO_HTTP - (void) dataBackend(); + #ifndef QT_NO_FTP (void) ftpBackend(); #endif @@ -450,6 +449,8 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent) : QObject(*new QNetworkAccessManagerPrivate, parent) { ensureInitialized(); + + qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError"); } /*! @@ -944,37 +945,25 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera { Q_D(QNetworkAccessManager); - // 4.7 only hotfix fast path for data:// URLs - // In 4.8 this is solved with QNetworkReplyDataImpl and will work there - // This hotfix is done for not needing a QNetworkSession for data:// - if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation) - && (req.url().scheme() == QLatin1String("data"))) { - QNetworkReplyImpl *reply = new QNetworkReplyImpl(this); - QNetworkReplyImplPrivate *priv = reply->d_func(); - priv->manager = this; - priv->backend = new QNetworkAccessDataBackend(); - priv->backend->manager = this->d_func(); - priv->backend->setParent(reply); - priv->backend->reply = priv; - priv->setup(op, req, outgoingData); - return reply; - } + bool isLocalFile = req.url().isLocalFile(); + QString scheme = req.url().scheme().toLower(); // fast path for GET on file:// URLs - // Also if the scheme is empty we consider it a file. // The QNetworkAccessFileBackend will right now only be used for PUT if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation) - && (req.url().scheme() == QLatin1String("file") - || req.url().scheme() == QLatin1String("qrc") - || req.url().scheme().isEmpty())) { - return new QFileNetworkReply(this, req, op); + && (isLocalFile || scheme == QLatin1String("qrc"))) { + return new QNetworkReplyFileImpl(this, req, op); + } + + if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation) + && scheme == QLatin1String("data")) { + return new QNetworkReplyDataImpl(this, req, op); } #ifndef QT_NO_BEARERMANAGEMENT // Return a disabled network reply if network access is disabled. // Except if the scheme is empty or file://. - if (!d->networkAccessible && !(req.url().scheme() == QLatin1String("file") || - req.url().scheme().isEmpty())) { + if (!d->networkAccessible && !isLocalFile) { return new QDisabledNetworkReply(this, req, op); } @@ -1008,7 +997,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera if (d->cookieJar) { QList<QNetworkCookie> cookies = d->cookieJar->cookiesForUrl(request.url()); if (!cookies.isEmpty()) - request.setHeader(QNetworkRequest::CookieHeader, qVariantFromValue(cookies)); + request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies)); } } @@ -1016,7 +1005,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera QUrl url = request.url(); QNetworkReplyImpl *reply = new QNetworkReplyImpl(this); #ifndef QT_NO_BEARERMANAGEMENT - if (req.url().scheme() != QLatin1String("file") && !req.url().scheme().isEmpty()) { + if (!isLocalFile) { connect(this, SIGNAL(networkSessionConnected()), reply, SLOT(_q_networkSessionConnected())); } diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index 261ed20..f55f67d 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -49,6 +49,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate() : readBufferMaxSize(0), operation(QNetworkAccessManager::UnknownOperation), errorCode(QNetworkReply::NoError) + , isFinished(false) { // set the default attribute values attributes.insert(QNetworkRequest::ConnectionEncryptedAttribute, false); @@ -462,7 +463,7 @@ QNetworkReply::NetworkError QNetworkReply::error() const */ bool QNetworkReply::isFinished() const { - return d_func()->isFinished(); + return d_func()->isFinished; } /*! @@ -718,6 +719,21 @@ void QNetworkReply::setError(NetworkError errorCode, const QString &errorString) } /*! + \since 4.8 + Sets the reply as \a finished. + + After having this set the replies data must not change. + + \sa isFinished() +*/ +void QNetworkReply::setFinished(bool finished) +{ + Q_D(QNetworkReply); + d->isFinished = finished; +} + + +/*! Sets the URL being processed to be \a url. Normally, the URL matches that of the request that was posted, but for a variety of reasons it can be different (for example, a file path being made diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h index acb7379..b39fd32 100644 --- a/src/network/access/qnetworkreply.h +++ b/src/network/access/qnetworkreply.h @@ -163,6 +163,7 @@ protected: void setOperation(QNetworkAccessManager::Operation operation); void setRequest(const QNetworkRequest &request); void setError(NetworkError errorCode, const QString &errorString); + void setFinished(bool); void setUrl(const QUrl &url); void setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value); void setRawHeader(const QByteArray &headerName, const QByteArray &value); diff --git a/src/network/access/qnetworkreply_p.h b/src/network/access/qnetworkreply_p.h index d7b8ab0..2e2e0bc 100644 --- a/src/network/access/qnetworkreply_p.h +++ b/src/network/access/qnetworkreply_p.h @@ -71,12 +71,11 @@ public: qint64 readBufferMaxSize; QNetworkAccessManager::Operation operation; QNetworkReply::NetworkError errorCode; + bool isFinished; static inline void setManager(QNetworkReply *reply, QNetworkAccessManager *manager) { reply->d_func()->manager = manager; } - virtual bool isFinished() const { return false; } - Q_DECLARE_PUBLIC(QNetworkReply) }; diff --git a/src/network/access/qnetworkreplydataimpl.cpp b/src/network/access/qnetworkreplydataimpl.cpp new file mode 100644 index 0000000..52cfe95 --- /dev/null +++ b/src/network/access/qnetworkreplydataimpl.cpp @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** 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 QtNetwork 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 "qnetworkreplydataimpl_p.h" +#include "private/qdataurl_p.h" +#include <QtCore/QCoreApplication> +#include <QtCore/QMetaObject> + +QT_BEGIN_NAMESPACE + +QNetworkReplyDataImplPrivate::QNetworkReplyDataImplPrivate() + : QNetworkReplyPrivate() +{ +} + +QNetworkReplyDataImplPrivate::~QNetworkReplyDataImplPrivate() +{ +} + +QNetworkReplyDataImpl::~QNetworkReplyDataImpl() +{ +} + +QNetworkReplyDataImpl::QNetworkReplyDataImpl(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op) + : QNetworkReply(*new QNetworkReplyDataImplPrivate(), parent) +{ + Q_D(QNetworkReplyDataImpl); + setRequest(req); + setUrl(req.url()); + setOperation(op); + setFinished(true); + QNetworkReply::open(QIODevice::ReadOnly); + + QUrl url = req.url(); + + // FIXME qDecodeDataUrl should instead be rewritten to have the QByteArray + // and the mime type as an output parameter and return a bool instead + d->decodeDataUrlResult = qDecodeDataUrl(url); + + if (! d->decodeDataUrlResult.first.isNull()) { + QString &mimeType = d->decodeDataUrlResult.first; + qint64 size = d->decodeDataUrlResult.second.size(); + setHeader(QNetworkRequest::ContentTypeHeader, mimeType); + setHeader(QNetworkRequest::ContentLengthHeader, size); + QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection); + + d->decodedData.setBuffer(&d->decodeDataUrlResult.second); + d->decodedData.open(QIODevice::ReadOnly); + + QMetaObject::invokeMethod(this, "downloadProgress", Qt::QueuedConnection, + Q_ARG(qint64,size), Q_ARG(qint64, size)); + QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection); + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); + } else { + // something wrong with this URI + const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend", + "Invalid URI: %1").arg(QString::fromLatin1(url.toEncoded())); + setError(QNetworkReply::ProtocolFailure, msg); + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolFailure)); + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); + } +} + +void QNetworkReplyDataImpl::close() +{ + QNetworkReply::close(); +} + +void QNetworkReplyDataImpl::abort() +{ + QNetworkReply::close(); +} + +qint64 QNetworkReplyDataImpl::bytesAvailable() const +{ + Q_D(const QNetworkReplyDataImpl); + return QNetworkReply::bytesAvailable() + d->decodedData.bytesAvailable(); +} + +bool QNetworkReplyDataImpl::isSequential () const +{ + return true; +} + +qint64 QNetworkReplyDataImpl::size() const +{ + Q_D(const QNetworkReplyDataImpl); + return d->decodedData.size(); +} + +/*! + \internal +*/ +qint64 QNetworkReplyDataImpl::readData(char *data, qint64 maxlen) +{ + Q_D(QNetworkReplyDataImpl); + + // TODO idea: + // Instead of decoding the whole data into new memory, we could decode on demand. + // Note that this might be tricky to do. + + return d->decodedData.read(data, maxlen); +} + + +QT_END_NAMESPACE + +#include "moc_qnetworkreplydataimpl_p.cpp" + diff --git a/src/network/access/qnetworkreplydataimpl_p.h b/src/network/access/qnetworkreplydataimpl_p.h new file mode 100644 index 0000000..6c62d28 --- /dev/null +++ b/src/network/access/qnetworkreplydataimpl_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 QtNetwork 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$ +** +****************************************************************************/ + +#ifndef QNETWORKREPLYDATAIMPL_H +#define QNETWORKREPLYDATAIMPL_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the Network Access API. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qnetworkreply.h" +#include "qnetworkreply_p.h" +#include "qnetworkaccessmanager.h" +#include <QBuffer> + +QT_BEGIN_NAMESPACE + + +class QNetworkReplyDataImplPrivate; +class QNetworkReplyDataImpl: public QNetworkReply +{ + Q_OBJECT +public: + QNetworkReplyDataImpl(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op); + ~QNetworkReplyDataImpl(); + virtual void abort(); + + // reimplemented from QNetworkReply + virtual void close(); + virtual qint64 bytesAvailable() const; + virtual bool isSequential () const; + qint64 size() const; + + virtual qint64 readData(char *data, qint64 maxlen); + + Q_DECLARE_PRIVATE(QNetworkReplyDataImpl) +}; + +class QNetworkReplyDataImplPrivate: public QNetworkReplyPrivate +{ +public: + QNetworkReplyDataImplPrivate(); + ~QNetworkReplyDataImplPrivate(); + + QPair<QString, QByteArray> decodeDataUrlResult; + QBuffer decodedData; + + Q_DECLARE_PUBLIC(QNetworkReplyDataImpl) +}; + +QT_END_NAMESPACE + +#endif // QNETWORKREPLYDATAIMPL_H diff --git a/src/network/access/qfilenetworkreply.cpp b/src/network/access/qnetworkreplyfileimpl.cpp index 00bd29e..10fa97e 100644 --- a/src/network/access/qfilenetworkreply.cpp +++ b/src/network/access/qnetworkreplyfileimpl.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qfilenetworkreply_p.h" +#include "qnetworkreplyfileimpl_p.h" #include "QtCore/qdatetime.h" #include <QtCore/QCoreApplication> @@ -48,31 +48,30 @@ QT_BEGIN_NAMESPACE -QFileNetworkReplyPrivate::QFileNetworkReplyPrivate() +QNetworkReplyFileImplPrivate::QNetworkReplyFileImplPrivate() : QNetworkReplyPrivate(), fileEngine(0), fileSize(0), filePos(0) { } -QFileNetworkReplyPrivate::~QFileNetworkReplyPrivate() +QNetworkReplyFileImplPrivate::~QNetworkReplyFileImplPrivate() { delete fileEngine; } -QFileNetworkReply::~QFileNetworkReply() +QNetworkReplyFileImpl::~QNetworkReplyFileImpl() { } -QFileNetworkReply::QFileNetworkReply(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op) - : QNetworkReply(*new QFileNetworkReplyPrivate(), parent) +QNetworkReplyFileImpl::QNetworkReplyFileImpl(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op) + : QNetworkReply(*new QNetworkReplyFileImplPrivate(), parent) { setRequest(req); setUrl(req.url()); setOperation(op); + setFinished(true); QNetworkReply::open(QIODevice::ReadOnly); - qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError"); - - QFileNetworkReplyPrivate *d = (QFileNetworkReplyPrivate*) d_func(); + QNetworkReplyFileImplPrivate *d = (QNetworkReplyFileImplPrivate*) d_func(); QUrl url = req.url(); if (url.host() == QLatin1String("localhost")) @@ -144,54 +143,48 @@ QFileNetworkReply::QFileNetworkReply(QObject *parent, const QNetworkRequest &req QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); } - -bool QFileNetworkReplyPrivate::isFinished() const -{ - return true; -} - -void QFileNetworkReply::close() +void QNetworkReplyFileImpl::close() { - Q_D(QFileNetworkReply); + Q_D(QNetworkReplyFileImpl); QNetworkReply::close(); if (d->fileEngine) d->fileEngine->close(); } -void QFileNetworkReply::abort() +void QNetworkReplyFileImpl::abort() { - Q_D(QFileNetworkReply); + Q_D(QNetworkReplyFileImpl); QNetworkReply::close(); if (d->fileEngine) d->fileEngine->close(); } -qint64 QFileNetworkReply::bytesAvailable() const +qint64 QNetworkReplyFileImpl::bytesAvailable() const { - Q_D(const QFileNetworkReply); + Q_D(const QNetworkReplyFileImpl); if (!d->fileEngine) return 0; return QNetworkReply::bytesAvailable() + d->fileSize - d->filePos; } -bool QFileNetworkReply::isSequential () const +bool QNetworkReplyFileImpl::isSequential () const { return true; } -qint64 QFileNetworkReply::size() const +qint64 QNetworkReplyFileImpl::size() const { - Q_D(const QFileNetworkReply); + Q_D(const QNetworkReplyFileImpl); return d->fileSize; } /*! \internal */ -qint64 QFileNetworkReply::readData(char *data, qint64 maxlen) +qint64 QNetworkReplyFileImpl::readData(char *data, qint64 maxlen) { - Q_D(QFileNetworkReply); + Q_D(QNetworkReplyFileImpl); if (!d->fileEngine) return -1; @@ -208,5 +201,5 @@ qint64 QFileNetworkReply::readData(char *data, qint64 maxlen) QT_END_NAMESPACE -#include "moc_qfilenetworkreply_p.cpp" +#include "moc_qnetworkreplyfileimpl_p.cpp" diff --git a/src/network/access/qfilenetworkreply_p.h b/src/network/access/qnetworkreplyfileimpl_p.h index 710ec9f..627363f 100644 --- a/src/network/access/qfilenetworkreply_p.h +++ b/src/network/access/qnetworkreplyfileimpl_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QFILENETWORKREPLY_P_H -#define QFILENETWORKREPLY_P_H +#ifndef QNETWORKREPLYFILEIMPL_H +#define QNETWORKREPLYFILEIMPL_H // // W A R N I N G @@ -62,13 +62,13 @@ QT_BEGIN_NAMESPACE -class QFileNetworkReplyPrivate; -class QFileNetworkReply: public QNetworkReply +class QNetworkReplyFileImplPrivate; +class QNetworkReplyFileImpl: public QNetworkReply { Q_OBJECT public: - QFileNetworkReply(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op); - ~QFileNetworkReply(); + QNetworkReplyFileImpl(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op); + ~QNetworkReplyFileImpl(); virtual void abort(); // reimplemented from QNetworkReply @@ -79,24 +79,22 @@ public: virtual qint64 readData(char *data, qint64 maxlen); - Q_DECLARE_PRIVATE(QFileNetworkReply) + Q_DECLARE_PRIVATE(QNetworkReplyFileImpl) }; -class QFileNetworkReplyPrivate: public QNetworkReplyPrivate +class QNetworkReplyFileImplPrivate: public QNetworkReplyPrivate { public: - QFileNetworkReplyPrivate(); - ~QFileNetworkReplyPrivate(); + QNetworkReplyFileImplPrivate(); + ~QNetworkReplyFileImplPrivate(); QAbstractFileEngine *fileEngine; qint64 fileSize; qint64 filePos; - virtual bool isFinished() const; - - Q_DECLARE_PUBLIC(QFileNetworkReply) + Q_DECLARE_PUBLIC(QNetworkReplyFileImpl) }; QT_END_NAMESPACE -#endif // QFILENETWORKREPLY_P_H +#endif // QNETWORKREPLYFILEIMPL_H diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 5850494..010e904 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -52,6 +52,8 @@ #include <QtCore/QCoreApplication> +Q_DECLARE_METATYPE(QSharedPointer<char>) + QT_BEGIN_NAMESPACE inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate() @@ -62,6 +64,10 @@ inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate() bytesDownloaded(0), lastBytesDownloaded(-1), bytesUploaded(-1), preMigrationDownloaded(-1), httpStatusCode(0), state(Idle) + , downloadBufferReadPosition(0) + , downloadBufferCurrentSize(0) + , downloadBufferMaximumSize(0) + , downloadBuffer(0) { } @@ -125,6 +131,10 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead() if (!copyDevice || !q->isOpen()) return; + // FIXME Optimize to use download buffer if it is a QBuffer. + // Needs to be done where sendCacheContents() (?) of HTTP is emitting + // metaDataChanged ? + forever { qint64 bytesToRead = nextDownstreamBlockSize(); if (bytesToRead == 0) @@ -543,8 +553,6 @@ void QNetworkReplyImplPrivate::appendDownstreamDataSignalEmissions() { Q_Q(QNetworkReplyImpl); - QPointer<QNetworkReplyImpl> qq = q; - QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader); if (preMigrationDownloaded != Q_INT64_C(-1)) totalSize = totalSize.toLongLong() + preMigrationDownloaded; @@ -555,13 +563,10 @@ void QNetworkReplyImplPrivate::appendDownstreamDataSignalEmissions() // else implicit sharing will trigger memcpy when the user is reading data! emit q->readyRead(); - // hopefully we haven't been deleted here - if (!qq.isNull()) { - resumeNotificationHandling(); - // do we still have room in the buffer? - if (nextDownstreamBlockSize() > 0) - backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); - } + resumeNotificationHandling(); + // do we still have room in the buffer? + if (nextDownstreamBlockSize() > 0) + backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); } // this is used when it was fetched from the cache, right? @@ -596,6 +601,60 @@ void QNetworkReplyImplPrivate::appendDownstreamData(const QByteArray &data) qFatal("QNetworkReplyImplPrivate::appendDownstreamData not implemented"); } +static void downloadBufferDeleter(char *ptr) +{ + delete[] ptr; +} + +char* QNetworkReplyImplPrivate::getDownloadBuffer(qint64 size) +{ + Q_Q(QNetworkReplyImpl); + + // Check attribute() if allocating a buffer of that size can be allowed + if (!downloadBuffer) { + QVariant bufferAllocationPolicy = request.attribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute); + if (bufferAllocationPolicy.isValid() && bufferAllocationPolicy.toLongLong() >= size) { + downloadBufferCurrentSize = 0; + downloadBufferMaximumSize = size; + downloadBuffer = new char[downloadBufferMaximumSize]; // throws if allocation fails + downloadBufferPointer = QSharedPointer<char>(downloadBuffer, downloadBufferDeleter); + + q->setAttribute(QNetworkRequest::DownloadBufferAttribute, qVariantFromValue<QSharedPointer<char> > (downloadBufferPointer)); + } + } + + return downloadBuffer; +} + +void QNetworkReplyImplPrivate::appendDownstreamDataDownloadBuffer(qint64 bytesReceived, qint64 bytesTotal) +{ + Q_Q(QNetworkReplyImpl); + if (!q->isOpen()) + return; + + if (cacheEnabled && !cacheSaveDevice) + initCacheSaveDevice(); + + if (cacheSaveDevice && bytesReceived == bytesTotal) { +// if (lastBytesDownloaded == -1) +// lastBytesDownloaded = 0; +// cacheSaveDevice->write(downloadBuffer + lastBytesDownloaded, bytesReceived - lastBytesDownloaded); + + // Write everything in one go if we use a download buffer. might be more performant. + cacheSaveDevice->write(downloadBuffer, bytesTotal); + } + + bytesDownloaded = bytesReceived; + lastBytesDownloaded = bytesReceived; + + downloadBufferCurrentSize = bytesReceived; + + emit q->downloadProgress(bytesDownloaded, bytesTotal); + // Only emit readyRead when actual data is there + if (bytesDownloaded > 0) + emit q->readyRead(); +} + void QNetworkReplyImplPrivate::finished() { Q_Q(QNetworkReplyImpl); @@ -634,6 +693,8 @@ void QNetworkReplyImplPrivate::finished() resumeNotificationHandling(); state = Finished; + q->setFinished(true); + pendingNotifications.clear(); pauseNotificationHandling(); @@ -704,11 +765,6 @@ void QNetworkReplyImplPrivate::sslErrors(const QList<QSslError> &errors) #endif } -bool QNetworkReplyImplPrivate::isFinished() const -{ - return (state == Finished || state == Aborted); -} - QNetworkReplyImpl::QNetworkReplyImpl(QObject *parent) : QNetworkReply(*new QNetworkReplyImplPrivate, parent) { @@ -743,7 +799,7 @@ void QNetworkReplyImpl::abort() QNetworkReply::close(); if (d->state != QNetworkReplyImplPrivate::Finished) { - // emit signals + // call finished which will emit signals d->error(OperationCanceledError, tr("Operation canceled")); d->finished(); } @@ -771,7 +827,7 @@ void QNetworkReplyImpl::close() QNetworkReply::close(); - // emit signals + // call finished which will emit signals d->error(OperationCanceledError, tr("Operation canceled")); d->finished(); } @@ -790,6 +846,13 @@ bool QNetworkReplyImpl::canReadLine () const */ qint64 QNetworkReplyImpl::bytesAvailable() const { + // Special case for the "zero copy" download buffer + Q_D(const QNetworkReplyImpl); + if (d->downloadBuffer) { + qint64 maxAvail = d->downloadBufferCurrentSize - d->downloadBufferReadPosition; + return QNetworkReply::bytesAvailable() + maxAvail; + } + return QNetworkReply::bytesAvailable() + d_func()->readBuffer.byteAmount(); } @@ -844,8 +907,22 @@ void QNetworkReplyImpl::ignoreSslErrorsImplementation(const QList<QSslError> &er qint64 QNetworkReplyImpl::readData(char *data, qint64 maxlen) { Q_D(QNetworkReplyImpl); + + // Special case code if we have the "zero copy" download buffer + if (d->downloadBuffer) { + qint64 maxAvail = qMin<qint64>(d->downloadBufferCurrentSize - d->downloadBufferReadPosition, maxlen); + if (maxAvail == 0) + return d->state == QNetworkReplyImplPrivate::Finished ? -1 : 0; + // FIXME what about "Aborted" state? + qMemCopy(data, d->downloadBuffer + d->downloadBufferReadPosition, maxAvail); + d->downloadBufferReadPosition += maxAvail; + return maxAvail; + } + + if (d->readBuffer.isEmpty()) return d->state == QNetworkReplyImplPrivate::Finished ? -1 : 0; + // FIXME what about "Aborted" state? d->backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); if (maxlen == 1) { diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index 38084bd..e944601 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -62,6 +62,7 @@ #include "QtCore/qbuffer.h" #include "private/qringbuffer_p.h" #include "private/qbytedata_p.h" +#include <QSharedPointer> QT_BEGIN_NAMESPACE @@ -163,14 +164,15 @@ public: void appendDownstreamData(QIODevice *data); void appendDownstreamData(const QByteArray &data); + char* getDownloadBuffer(qint64 size); + void appendDownstreamDataDownloadBuffer(qint64, qint64); + void finished(); void error(QNetworkReply::NetworkError code, const QString &errorString); void metaDataChanged(); void redirectionRequested(const QUrl &target); void sslErrors(const QList<QSslError> &errors); - bool isFinished() const; - QNetworkAccessBackend *backend; QIODevice *outgoingData; QRingBuffer *outgoingDataBuffer; @@ -191,6 +193,7 @@ public: QList<QNetworkProxy> proxyList; #endif + // Used for normal downloading. For "zero copy" the downloadBuffer is used QByteDataBuffer readBuffer; qint64 bytesDownloaded; qint64 lastBytesDownloaded; @@ -202,6 +205,14 @@ public: State state; + // only used when the "zero copy" style is used. Else readBuffer is used. + // Please note that the whole "zero copy" download buffer API is private right now. Do not use it. + qint64 downloadBufferReadPosition; + qint64 downloadBufferCurrentSize; + qint64 downloadBufferMaximumSize; + QSharedPointer<char> downloadBufferPointer; + char* downloadBuffer; + Q_DECLARE_PUBLIC(QNetworkReplyImpl) }; diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index b761af5..deb678a 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -756,7 +756,7 @@ static QVariant parseCookieHeader(const QByteArray &raw) result += parsed; } - return qVariantFromValue(result); + return QVariant::fromValue(result); } static QVariant parseHeaderValue(QNetworkRequest::KnownHeaders header, const QByteArray &value) @@ -789,7 +789,7 @@ static QVariant parseHeaderValue(QNetworkRequest::KnownHeaders header, const QBy return parseCookieHeader(value); case QNetworkRequest::SetCookieHeader: - return qVariantFromValue(QNetworkCookie::parseCookies(value)); + return QVariant::fromValue(QNetworkCookie::parseCookies(value)); default: Q_ASSERT(0); diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index f984cf8..c8fc45e 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -56,9 +56,7 @@ QT_BEGIN_NAMESPACE -#ifndef QT_NO_THREAD Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager) -#endif //#define QHOSTINFO_DEBUG @@ -87,10 +85,8 @@ Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager) \snippet doc/src/snippets/code/src_network_kernel_qhostinfo.cpp 0 - The slot is invoked when the results are ready. (If you use - Qt for Embedded Linux and disabled multithreading support by defining - \c QT_NO_THREAD, lookupHost() will block until the lookup has - finished.) The results are stored in a QHostInfo object. Call + The slot is invoked when the results are ready. The results are + stored in a QHostInfo object. Call addresses() to get the list of IP addresses for the host, and hostName() to get the host name that was looked up. @@ -176,14 +172,6 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, return id; } -#ifdef QT_NO_THREAD - QHostInfo hostInfo = QHostInfoAgent::fromName(name); - hostInfo.setLookupId(id); - QScopedPointer<QHostInfoResult> result(new QHostInfoResult); - QObject::connect(result.data(), SIGNAL(resultsReady(QHostInfo)), - receiver, member, Qt::QueuedConnection); - result.data()->emitResultsReady(hostInfo); -#else QHostInfoLookupManager *manager = theHostInfoLookupManager(); if (manager) { // the application is still alive @@ -204,8 +192,6 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, QObject::connect(&runnable->resultEmitter, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); manager->scheduleLookup(runnable); } -#endif - return id; } @@ -216,12 +202,7 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, */ void QHostInfo::abortHostLookup(int id) { -#ifndef QT_NO_THREAD theHostInfoLookupManager()->abortLookup(id); -#else - // we cannot abort if it was non threaded.. the result signal has already been posted - Q_UNUSED(id); -#endif } /*! @@ -425,7 +406,6 @@ void QHostInfo::setErrorString(const QString &str) \sa hostName() */ -#ifndef QT_NO_THREAD QHostInfoRunnable::QHostInfoRunnable(QString hn, int i) : toBeLookedUp(hn), id(i) { setAutoDelete(true); @@ -753,6 +733,4 @@ void QHostInfoCache::clear() cache.clear(); } -#endif // QT_NO_THREAD - QT_END_NAMESPACE diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index 85d14c2..134335f 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -60,8 +60,6 @@ #include "QtCore/qwaitcondition.h" #include "QtCore/qobject.h" #include "QtCore/qpointer.h" - -#ifndef QT_NO_THREAD #include "QtCore/qthread.h" #include "QtCore/qthreadpool.h" #include "QtCore/qmutex.h" @@ -70,7 +68,7 @@ #include "QtCore/qqueue.h" #include <QTime> #include <QCache> -#endif + QT_BEGIN_NAMESPACE @@ -112,7 +110,6 @@ public: int lookupId; }; -#ifndef QT_NO_THREAD // These functions are outside of the QHostInfo class and strictly internal. // Do NOT use them outside of QAbstractSocket. QHostInfo Q_NETWORK_EXPORT qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *member, bool *valid, int *id); @@ -192,8 +189,6 @@ private slots: void waitForThreadPoolDone() { threadPool.waitForDone(); } }; -#endif - QT_END_NAMESPACE #endif // QHOSTINFO_P_H diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp index 9e3da61..5ca15a3 100644 --- a/src/network/kernel/qhostinfo_unix.cpp +++ b/src/network/kernel/qhostinfo_unix.cpp @@ -132,9 +132,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) // Load res_init on demand. static volatile bool triedResolve = false; if (!triedResolve) { -#ifndef QT_NO_THREAD QMutexLocker locker(QMutexPool::globalInstanceGet(&local_res_init)); -#endif if (!triedResolve) { resolveLibrary(); triedResolve = true; diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp index 8241c84..8e28fb3 100644 --- a/src/network/kernel/qhostinfo_win.cpp +++ b/src/network/kernel/qhostinfo_win.cpp @@ -39,11 +39,6 @@ ** ****************************************************************************/ -#if defined Q_CC_MSVC && _MSC_VER <=1300 -//VC.net 2002 support for templates doesn't match some PSDK requirements -#define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0])) -#endif - #include <winsock2.h> #include "qhostinfo_p.h" @@ -115,9 +110,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) // Load res_init on demand. static volatile bool triedResolve = false; if (!triedResolve) { -#ifndef QT_NO_THREAD QMutexLocker locker(QMutexPool::globalInstanceGet(&local_getaddrinfo)); -#endif if (!triedResolve) { resolveLibrary(); triedResolve = true; diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index f03d102..c638e2a 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -356,6 +356,10 @@ to enable. \value KeepAliveOption Set this to 1 to enable the SO_KEEPALIVE socket option + \value MulticastTtlOption Set this to an integer value to set IP_MULTICAST_TTL (TTL for multicast datagrams) socket option. + + \value MulticastLoopbackOption Set this to 1 to enable the IP_MULTICAST_LOOP (multicast loopback) socket option. + \sa QAbstractSocket::setSocketOption(), QAbstractSocket::socketOption() */ @@ -466,9 +470,6 @@ QAbstractSocketPrivate::QAbstractSocketPrivate() peerPort(0), socketEngine(0), cachedSocketDescriptor(-1), -#ifdef Q_OS_LINUX - addToBytesAvailable(0), -#endif readBufferMaxSize(0), readBuffer(QABSTRACTSOCKET_BUFFERSIZE), writeBuffer(QABSTRACTSOCKET_BUFFERSIZE), @@ -630,8 +631,9 @@ bool QAbstractSocketPrivate::canReadNotification() // only emit readyRead() when not recursing, and only if there is data available bool hasData = newBytes > 0 #ifndef QT_NO_UDPSOCKET - || (!isBuffered && socketEngine && socketEngine->hasPendingDatagrams()) + || (!isBuffered && socketType != QAbstractSocket::TcpSocket && socketEngine && socketEngine->hasPendingDatagrams()) #endif + || (!isBuffered && socketType == QAbstractSocket::TcpSocket && socketEngine) ; if (!emittedReadyRead && hasData) { @@ -1132,10 +1134,6 @@ bool QAbstractSocketPrivate::readFromSocket() Q_Q(QAbstractSocket); // Find how many bytes we can read from the socket layer. qint64 bytesToRead = socketEngine->bytesAvailable(); -#ifdef Q_OS_LINUX - if (bytesToRead > 0) // ### See setSocketDescriptor() - bytesToRead += addToBytesAvailable; -#endif if (bytesToRead == 0) { // Under heavy load, certain conditions can trigger read notifications // for socket notifiers on which there is no activity. If we continue @@ -1370,10 +1368,6 @@ void QAbstractSocket::connectToHostImplementation(const QString &hostName, quint d->localAddress.clear(); d->peerAddress.clear(); d->peerName = hostName; -#ifdef Q_OS_LINUX - // ### See setSocketDescriptor(). - d->addToBytesAvailable = 0; -#endif if (d->hostLookupId != -1) { QHostInfo::abortHostLookup(d->hostLookupId); d->hostLookupId = -1; @@ -1391,8 +1385,11 @@ void QAbstractSocket::connectToHostImplementation(const QString &hostName, quint } #endif - if (!d_func()->isBuffered) - openMode |= QAbstractSocket::Unbuffered; + if (openMode & QIODevice::Unbuffered) + d->isBuffered = false; // Unbuffered QTcpSocket + else if (!d_func()->isBuffered) + openMode |= QAbstractSocket::Unbuffered; // QUdpSocket + QIODevice::open(openMode); d->state = HostLookupState; emit stateChanged(d->state); @@ -1472,10 +1469,12 @@ qint64 QAbstractSocket::bytesAvailable() const { Q_D(const QAbstractSocket); qint64 available = QIODevice::bytesAvailable(); - if (d->isBuffered) - available += (qint64) d->readBuffer.size(); - else if (d->socketEngine && d->socketEngine->isValid()) + + available += (qint64) d->readBuffer.size(); + + if (!d->isBuffered && d->socketEngine && d->socketEngine->isValid()) available += d->socketEngine->bytesAvailable(); + #if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocket::bytesAvailable() == %llu", available); #endif @@ -1633,17 +1632,6 @@ bool QAbstractSocket::setSocketDescriptor(int socketDescriptor, SocketState sock d->peerAddress = d->socketEngine->peerAddress(); d->cachedSocketDescriptor = socketDescriptor; -#ifdef Q_OS_LINUX - // ### This is a workaround for certain broken Linux kernels, when using - // QTcpSocket with a Unix domain socket. It was introduced around 2.6.9, - // and fixed at some point after that. - // http://archive.linux-usenet.com/index-t-73300.html - // We can provide a better workaround for this: readFromSocket() can loop - // while reading, but this must happen without triggering an implicit - // close because of reading after the socket has closed. - d->addToBytesAvailable = 4096; -#endif - return true; } @@ -1673,6 +1661,14 @@ void QAbstractSocket::setSocketOption(QAbstractSocket::SocketOption option, cons case KeepAliveOption: d_func()->socketEngine->setOption(QAbstractSocketEngine::KeepAliveOption, value.toInt()); break; + + case MulticastTtlOption: + d_func()->socketEngine->setOption(QAbstractSocketEngine::MulticastTtlOption, value.toInt()); + break; + + case MulticastLoopbackOption: + d_func()->socketEngine->setOption(QAbstractSocketEngine::MulticastLoopbackOption, value.toInt()); + break; } } @@ -1702,6 +1698,13 @@ QVariant QAbstractSocket::socketOption(QAbstractSocket::SocketOption option) case KeepAliveOption: ret = d_func()->socketEngine->option(QAbstractSocketEngine::KeepAliveOption); break; + + case MulticastTtlOption: + ret = d_func()->socketEngine->option(QAbstractSocketEngine::MulticastTtlOption); + break; + case MulticastLoopbackOption: + ret = d_func()->socketEngine->option(QAbstractSocketEngine::MulticastLoopbackOption); + break; } if (ret == -1) return QVariant(); @@ -2119,42 +2122,50 @@ bool QAbstractSocket::flush() qint64 QAbstractSocket::readData(char *data, qint64 maxSize) { Q_D(QAbstractSocket); - if (d->socketEngine && !d->socketEngine->isReadNotificationEnabled() && d->socketEngine->isValid()) - d->socketEngine->setReadNotificationEnabled(true); - if (!d->isBuffered) { - if (!d->socketEngine) - return -1; // no socket engine is probably EOF - qint64 readBytes = d->socketEngine->read(data, maxSize); - if (readBytes < 0) { - d->socketError = d->socketEngine->error(); - setErrorString(d->socketEngine->errorString()); - } - if (!d->socketEngine->isReadNotificationEnabled()) - d->socketEngine->setReadNotificationEnabled(true); -#if defined (QABSTRACTSOCKET_DEBUG) - qDebug("QAbstractSocket::readData(%p \"%s\", %lli) == %lld", - data, qt_prettyDebug(data, 32, readBytes).data(), maxSize, - readBytes); -#endif - return readBytes; - } - - if (d->readBuffer.isEmpty()) + // This is for a buffered QTcpSocket + if (d->isBuffered && d->readBuffer.isEmpty()) // if we're still connected, return 0 indicating there may be more data in the future // if we're not connected, return -1 indicating EOF return d->state == QAbstractSocket::ConnectedState ? qint64(0) : qint64(-1); - // If readFromSocket() read data, copy it to its destination. - if (maxSize == 1) { + // short cut for a char read if we have something in the buffer + if (maxSize == 1 && !d->readBuffer.isEmpty()) { *data = d->readBuffer.getChar(); #if defined (QABSTRACTSOCKET_DEBUG) - qDebug("QAbstractSocket::readData(%p '%c (0x%.2x)', 1) == 1", + qDebug("QAbstractSocket::readData(%p '%c (0x%.2x)', 1) == 1 [char buffer]", data, isprint(int(uchar(*data))) ? *data : '?', *data); #endif + if (d->readBuffer.isEmpty() && d->socketEngine) + d->socketEngine->setReadNotificationEnabled(true); return 1; } + // Special case for an Unbuffered QTcpSocket + // Re-filling the buffer. + if (d->socketType == TcpSocket + && !d->isBuffered + && d->readBuffer.size() < maxSize + && d->readBufferMaxSize > 0 + && maxSize < d->readBufferMaxSize + && d->socketEngine) { + // Our buffer is empty and a read() was requested for a byte amount that is smaller + // than the readBufferMaxSize. This means that we should fill our buffer since we want + // such small reads come from the buffer and not always go to the costly socket engine read() + qint64 bytesToRead = d->socketEngine->bytesAvailable(); + if (bytesToRead > 0) { + char *ptr = d->readBuffer.reserve(bytesToRead); + qint64 readBytes = d->socketEngine->read(ptr, bytesToRead); + if (readBytes == -2) { + // No bytes currently available for reading. + d->readBuffer.chop(bytesToRead); + } else { + d->readBuffer.chop(int(bytesToRead - (readBytes < 0 ? qint64(0) : readBytes))); + } + } + } + + // First try to satisfy the read from the buffer qint64 bytesToRead = qMin(qint64(d->readBuffer.size()), maxSize); qint64 readSoFar = 0; while (readSoFar < bytesToRead) { @@ -2166,8 +2177,50 @@ qint64 QAbstractSocket::readData(char *data, qint64 maxSize) d->readBuffer.free(bytesToReadFromThisBlock); } + if (d->socketEngine && !d->socketEngine->isReadNotificationEnabled() && d->socketEngine->isValid()) + d->socketEngine->setReadNotificationEnabled(true); + + if (readSoFar > 0) { + // we read some data from buffer. + // Just return, readyRead will be emitted again #if defined (QABSTRACTSOCKET_DEBUG) - qDebug("QAbstractSocket::readData(%p \"%s\", %lli) == %lld", + qDebug("QAbstractSocket::readData(%p '%c (0x%.2x)', %lli) == %lli [buffer]", + data, isprint(int(uchar(*data))) ? *data : '?', *data, maxSize, readSoFar); +#endif + + if (d->readBuffer.isEmpty() && d->socketEngine) + d->socketEngine->setReadNotificationEnabled(true); + return readSoFar; + } + + // This code path is for Unbuffered QTcpSocket or for connected UDP + + if (!d->isBuffered) { + if (!d->socketEngine) + return -1; // no socket engine is probably EOF + qint64 readBytes = d->socketEngine->read(data, maxSize); + if (readBytes == -2) { + // -2 from the engine means no bytes available (EAGAIN) so read more later + return 0; + } else if (readBytes < 0) { + d->socketError = d->socketEngine->error(); + setErrorString(d->socketEngine->errorString()); + } else if (!d->socketEngine->isReadNotificationEnabled()) { + // Only do this when there was no error + d->socketEngine->setReadNotificationEnabled(true); + } + +#if defined (QABSTRACTSOCKET_DEBUG) + qDebug("QAbstractSocket::readData(%p \"%s\", %lli) == %lld [engine]", + data, qt_prettyDebug(data, 32, readBytes).data(), maxSize, + readBytes); +#endif + return readBytes; + } + + +#if defined (QABSTRACTSOCKET_DEBUG) + qDebug("QAbstractSocket::readData(%p \"%s\", %lli) == %lld [unreachable]", data, qt_prettyDebug(data, qMin<qint64>(32, readSoFar), readSoFar).data(), maxSize, readSoFar); #endif @@ -2192,7 +2245,23 @@ qint64 QAbstractSocket::writeData(const char *data, qint64 size) return -1; } - if (!d->isBuffered) { + if (!d->isBuffered && d->socketType == TcpSocket && d->writeBuffer.isEmpty()) { + // This code is for the new Unbuffered QTcpSocket use case + qint64 written = d->socketEngine->write(data, size); + if (written < 0) { + d->socketError = d->socketEngine->error(); + setErrorString(d->socketEngine->errorString()); + return written; + } else if (written < size) { + // Buffer what was not written yet + char *ptr = d->writeBuffer.reserve(size - written); + memcpy(ptr, data + written, size - written); + if (d->socketEngine) + d->socketEngine->setWriteNotificationEnabled(true); + } + return size; // size=actually written + what has been buffered + } else if (!d->isBuffered && d->socketType != TcpSocket) { + // This is for a QUdpSocket that was connect()ed qint64 written = d->socketEngine->write(data, size); if (written < 0) { d->socketError = d->socketEngine->error(); @@ -2211,6 +2280,12 @@ qint64 QAbstractSocket::writeData(const char *data, qint64 size) return written; } + // This is the code path for normal buffered QTcpSocket or + // unbuffered QTcpSocket when there was already something in the + // write buffer and therefore we could not do a direct engine write. + // We just write to our write buffer and enable the write notifier + // The write notifier then flush()es the buffer. + char *ptr = d->writeBuffer.reserve(size); if (size == 1) *ptr = *data; diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h index 9e487d2..f610db3 100644 --- a/src/network/socket/qabstractsocket.h +++ b/src/network/socket/qabstractsocket.h @@ -118,7 +118,9 @@ public: }; enum SocketOption { LowDelayOption, // TCP_NODELAY - KeepAliveOption // SO_KEEPALIVE + KeepAliveOption, // SO_KEEPALIVE + MulticastTtlOption, // IP_MULTICAST_TTL + MulticastLoopbackOption // IP_MULTICAST_LOOPBACK }; QAbstractSocket(SocketType socketType, QObject *parent); diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h index 7fba0fe..8ca83fc 100644 --- a/src/network/socket/qabstractsocket_p.h +++ b/src/network/socket/qabstractsocket_p.h @@ -138,9 +138,6 @@ public: void setupSocketNotifiers(); bool readFromSocket(); -#ifdef Q_OS_LINUX - qint64 addToBytesAvailable; -#endif qint64 readBufferMaxSize; QRingBuffer readBuffer; QRingBuffer writeBuffer; diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h index 3669852..ec5fbd3 100644 --- a/src/network/socket/qabstractsocketengine_p.h +++ b/src/network/socket/qabstractsocketengine_p.h @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE class QAuthenticator; class QAbstractSocketEnginePrivate; +class QNetworkInterface; class QNetworkProxy; class QAbstractSocketEngineReceiver { @@ -94,7 +95,9 @@ public: BindExclusively, ReceiveOutOfBandData, LowDelayOption, - KeepAliveOption + KeepAliveOption, + MulticastTtlOption, + MulticastLoopbackOption }; virtual bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) = 0; @@ -118,6 +121,13 @@ public: virtual qint64 write(const char *data, qint64 len) = 0; #ifndef QT_NO_UDPSOCKET + virtual bool joinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) = 0; + virtual bool leaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) = 0; + virtual QNetworkInterface multicastInterface() const = 0; + virtual bool setMulticastInterface(const QNetworkInterface &iface) = 0; + virtual qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, quint16 *port = 0) = 0; virtual qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp index dfda257..cb0e296 100644 --- a/src/network/socket/qhttpsocketengine.cpp +++ b/src/network/socket/qhttpsocketengine.cpp @@ -45,6 +45,7 @@ #include "qurl.h" #include "qhttp.h" #include "qelapsedtimer.h" +#include "qnetworkinterface.h" #if !defined(QT_NO_NETWORKPROXY) && !defined(QT_NO_HTTP) #include <qdebug.h> @@ -239,6 +240,34 @@ qint64 QHttpSocketEngine::write(const char *data, qint64 len) } #ifndef QT_NO_UDPSOCKET +bool QHttpSocketEngine::joinMulticastGroup(const QHostAddress &, + const QNetworkInterface &) +{ + setError(QAbstractSocket::UnsupportedSocketOperationError, + QLatin1String("Operation on socket is not supported")); + return false; +} + +bool QHttpSocketEngine::leaveMulticastGroup(const QHostAddress &, + const QNetworkInterface &) +{ + setError(QAbstractSocket::UnsupportedSocketOperationError, + QLatin1String("Operation on socket is not supported")); + return false; +} + +QNetworkInterface QHttpSocketEngine::multicastInterface() const +{ + return QNetworkInterface(); +} + +bool QHttpSocketEngine::setMulticastInterface(const QNetworkInterface &) +{ + setError(QAbstractSocket::UnsupportedSocketOperationError, + QLatin1String("Operation on socket is not supported")); + return false; +} + qint64 QHttpSocketEngine::readDatagram(char *, qint64, QHostAddress *, quint16 *) { diff --git a/src/network/socket/qhttpsocketengine_p.h b/src/network/socket/qhttpsocketengine_p.h index 5051def..b68b7117 100644 --- a/src/network/socket/qhttpsocketengine_p.h +++ b/src/network/socket/qhttpsocketengine_p.h @@ -102,6 +102,13 @@ public: qint64 write(const char *data, qint64 len); #ifndef QT_NO_UDPSOCKET + bool joinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &interface); + bool leaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &interface); + QNetworkInterface multicastInterface() const; + bool setMulticastInterface(const QNetworkInterface &iface); + qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, quint16 *port = 0); qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index a169ca0..df73b9c 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -98,6 +98,7 @@ #include <qabstracteventdispatcher.h> #include <qsocketnotifier.h> +#include <qnetworkinterface.h> #include "qnativesocketengine_p.h" #include <private/qthread_p.h> @@ -647,6 +648,51 @@ int QNativeSocketEngine::accept() } /*! + \since 4.8 +*/ +bool QNativeSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) +{ + Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::joinMulticastGroup(), false); + Q_CHECK_STATE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::BoundState, false); + Q_CHECK_TYPE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::UdpSocket, false); + return d->nativeJoinMulticastGroup(groupAddress, iface); +} + +/*! + \since 4.8 +*/ +bool QNativeSocketEngine::leaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) +{ + Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::leaveMulticastGroup(), false); + Q_CHECK_STATE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::BoundState, false); + Q_CHECK_TYPE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::UdpSocket, false); + return d->nativeLeaveMulticastGroup(groupAddress, iface); +} + +/*! \since 4.8 */ +QNetworkInterface QNativeSocketEngine::multicastInterface() const +{ + Q_D(const QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::multicastInterface(), QNetworkInterface()); + Q_CHECK_TYPE(QNativeSocketEngine::multicastInterface(), QAbstractSocket::UdpSocket, QNetworkInterface()); + return d->nativeMulticastInterface(); +} + + +/*! \since 4.8 */ +bool QNativeSocketEngine::setMulticastInterface(const QNetworkInterface &iface) +{ + Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setMulticastInterface(), false); + Q_CHECK_TYPE(QNativeSocketEngine::setMulticastInterface(), QAbstractSocket::UdpSocket, false); + return d->nativeSetMulticastInterface(iface); +} + +/*! Returns the number of bytes that are currently available for reading. On error, -1 is returned. diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index eca16f6..9baacf0 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -101,6 +101,7 @@ union qt_sockaddr { }; class QNativeSocketEnginePrivate; +class QNetworkInterface; class Q_AUTOTEST_EXPORT QNativeSocketEngine : public QAbstractSocketEngine { @@ -123,6 +124,13 @@ public: int accept(); void close(); + bool joinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface); + bool leaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface); + QNetworkInterface multicastInterface() const; + bool setMulticastInterface(const QNetworkInterface &iface); + qint64 bytesAvailable() const; qint64 read(char *data, qint64 maxlen); @@ -237,6 +245,12 @@ public: bool nativeBind(const QHostAddress &address, quint16 port); bool nativeListen(int backlog); int nativeAccept(); + bool nativeJoinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface); + bool nativeLeaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface); + QNetworkInterface nativeMulticastInterface() const; + bool nativeSetMulticastInterface(const QNetworkInterface &iface); qint64 nativeBytesAvailable() const; bool nativeHasPendingDatagrams() const; diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index f6bfbac..aa55009 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -46,6 +46,7 @@ #include "qhostaddress.h" #include "qelapsedtimer.h" #include "qvarlengtharray.h" +#include "qnetworkinterface.h" #include <time.h> #include <errno.h> #include <fcntl.h> @@ -247,6 +248,30 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co case QNativeSocketEngine::KeepAliveOption: n = SO_KEEPALIVE; break; + case QNativeSocketEngine::MulticastTtlOption: +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + n = IPV6_MULTICAST_HOPS; + } else +#endif + { + level = IPPROTO_IP; + n = IP_MULTICAST_TTL; + } + break; + case QNativeSocketEngine::MulticastLoopbackOption: +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + n = IPV6_MULTICAST_LOOP; + } else +#endif + { + level = IPPROTO_IP; + n = IP_MULTICAST_LOOP; + } + break; } int v = -1; @@ -330,6 +355,30 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt case QNativeSocketEngine::KeepAliveOption: n = SO_KEEPALIVE; break; + case QNativeSocketEngine::MulticastTtlOption: +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + n = IPV6_MULTICAST_HOPS; + } else +#endif + { + level = IPPROTO_IP; + n = IP_MULTICAST_TTL; + } + break; + case QNativeSocketEngine::MulticastLoopbackOption: +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + n = IPV6_MULTICAST_LOOP; + } else +#endif + { + level = IPPROTO_IP; + n = IP_MULTICAST_LOOP; + } + break; } return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0; @@ -579,6 +628,171 @@ int QNativeSocketEnginePrivate::nativeAccept() return acceptedDescriptor; } + +static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d, + int how6, + int how4, + const QHostAddress &groupAddress, + const QNetworkInterface &interface) +{ + int level = 0; + int sockOpt = 0; + void *sockArg; + int sockArgSize; + + ip_mreq mreq4; +#ifndef QT_NO_IPV6 + ipv6_mreq mreq6; + + if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + sockOpt = how6; + sockArg = &mreq6; + sockArgSize = sizeof(mreq6); + memset(&mreq6, 0, sizeof(mreq6)); + Q_IPV6ADDR ip6 = groupAddress.toIPv6Address(); + memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6)); + mreq6.ipv6mr_interface = interface.index(); + } else +#endif + if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) { + level = IPPROTO_IP; + sockOpt = how4; + sockArg = &mreq4; + sockArgSize = sizeof(mreq4); + memset(&mreq4, 0, sizeof(mreq4)); + mreq4.imr_multiaddr.s_addr = htonl(groupAddress.toIPv4Address()); + + if (interface.isValid()) { + QList<QNetworkAddressEntry> addressEntries = interface.addressEntries(); + if (!addressEntries.isEmpty()) { + QHostAddress firstIP = addressEntries.first().ip(); + mreq4.imr_interface.s_addr = htonl(firstIP.toIPv4Address()); + } else { + d->setError(QAbstractSocket::NetworkError, + QNativeSocketEnginePrivate::NetworkUnreachableErrorString); + return false; + } + } else { + mreq4.imr_interface.s_addr = INADDR_ANY; + } + } else { + // unreachable + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + QNativeSocketEnginePrivate::ProtocolUnsupportedErrorString); + return false; + } + + int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize); + if (res == -1) { + switch (errno) { + case ENOPROTOOPT: + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + QNativeSocketEnginePrivate::OperationUnsupportedErrorString); + break; + case EADDRNOTAVAIL: + d->setError(QAbstractSocket::SocketAddressNotAvailableError, + QNativeSocketEnginePrivate::AddressNotAvailableErrorString); + break; + default: + d->setError(QAbstractSocket::UnknownSocketError, + QNativeSocketEnginePrivate::UnknownSocketErrorString); + break; + } + return false; + } + return true; +} + +bool QNativeSocketEnginePrivate::nativeJoinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &interface) +{ + return multicastMembershipHelper(this, +#ifndef QT_NO_IPV6 + IPV6_JOIN_GROUP, +#else + 0, +#endif + IP_ADD_MEMBERSHIP, + groupAddress, + interface); +} + +bool QNativeSocketEnginePrivate::nativeLeaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &interface) +{ + return multicastMembershipHelper(this, +#ifndef QT_NO_IPV6 + IPV6_LEAVE_GROUP, +#else + 0, +#endif + IP_DROP_MEMBERSHIP, + groupAddress, + interface); +} + +QNetworkInterface QNativeSocketEnginePrivate::nativeMulticastInterface() const +{ +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + uint v; + QT_SOCKOPTLEN_T sizeofv = sizeof(v); + if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v, &sizeofv) == -1) + return QNetworkInterface(); + return QNetworkInterface::interfaceFromIndex(v); + } +#endif + + struct in_addr v = { 0 }; + QT_SOCKOPTLEN_T sizeofv = sizeof(v); + if (::getsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, &sizeofv) == -1) + return QNetworkInterface(); + if (v.s_addr != 0 && sizeofv >= sizeof(v)) { + QHostAddress ipv4(ntohl(v.s_addr)); + QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces(); + for (int i = 0; i < ifaces.count(); ++i) { + const QNetworkInterface &iface = ifaces.at(i); + QList<QNetworkAddressEntry> entries = iface.addressEntries(); + for (int j = 0; j < entries.count(); ++j) { + const QNetworkAddressEntry &entry = entries.at(j); + if (entry.ip() == ipv4) + return iface; + } + } + } + return QNetworkInterface(); +} + +bool QNativeSocketEnginePrivate::nativeSetMulticastInterface(const QNetworkInterface &iface) +{ +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + uint v = iface.index(); + return (::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v, sizeof(v)) != -1); + } +#endif + + struct in_addr v; + if (iface.isValid()) { + QList<QNetworkAddressEntry> entries = iface.addressEntries(); + for (int i = 0; i < entries.count(); ++i) { + const QNetworkAddressEntry &entry = entries.at(i); + const QHostAddress &ip = entry.ip(); + if (ip.protocol() == QAbstractSocket::IPv4Protocol) { + v.s_addr = htonl(ip.toIPv4Address()); + int r = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, sizeof(v)); + if (r != -1) + return true; + } + } + return false; + } + + v.s_addr = INADDR_ANY; + return (::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, sizeof(v)) != -1); +} + qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const { int nbytes = 0; @@ -890,7 +1104,7 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) { Q_Q(QNativeSocketEngine); if (!q->isValid()) { - qWarning("QNativeSocketEngine::unbufferedRead: Invalid socket"); + qWarning("QNativeSocketEngine::nativeRead: Invalid socket"); return -1; } diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index c1a4cfc..dbf443e 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include <winsock2.h> +#include <ws2tcpip.h> #include "qnativesocketengine_p.h" @@ -47,6 +48,7 @@ #include <qsocketnotifier.h> #include <qdebug.h> #include <qdatetime.h> +#include <qnetworkinterface.h> //#define QNATIVESOCKETENGINE_DEBUG #if defined(QNATIVESOCKETENGINE_DEBUG) @@ -399,6 +401,30 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co case QNativeSocketEngine::KeepAliveOption: n = SO_KEEPALIVE; break; + case QNativeSocketEngine::MulticastTtlOption: +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + n = IPV6_MULTICAST_HOPS; + } else +#endif + { + level = IPPROTO_IP; + n = IP_MULTICAST_TTL; + } + break; + case QNativeSocketEngine::MulticastLoopbackOption: +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + n = IPV6_MULTICAST_LOOP; + } else +#endif + { + level = IPPROTO_IP; + n = IP_MULTICAST_LOOP; + } + break; } int v = -1; @@ -459,6 +485,30 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt case QNativeSocketEngine::KeepAliveOption: n = SO_KEEPALIVE; break; + case QNativeSocketEngine::MulticastTtlOption: +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + n = IPV6_MULTICAST_HOPS; + } else +#endif + { + level = IPPROTO_IP; + n = IP_MULTICAST_TTL; + } + break; + case QNativeSocketEngine::MulticastLoopbackOption: +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + n = IPV6_MULTICAST_LOOP; + } else +#endif + { + level = IPPROTO_IP; + n = IP_MULTICAST_LOOP; + } + break; } if (::setsockopt(socketDescriptor, level, n, (char*)&v, sizeof(v)) != 0) { @@ -648,8 +698,26 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin } -bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port) +bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &a, quint16 port) { + QHostAddress address = a; + switch (address.protocol()) { + case QAbstractSocket::IPv6Protocol: + if (address.toIPv6Address()[0] == 0xff) { + // binding to a multicast address + address = QHostAddress(QHostAddress::AnyIPv6); + } + break; + case QAbstractSocket::IPv4Protocol: + if ((address.toIPv4Address() & 0xffff0000) == 0xefff0000) { + // binding to a multicast address + address = QHostAddress(QHostAddress::Any); + } + break; + default: + break; + } + struct sockaddr_in sockAddrIPv4; qt_sockaddr_in6 sockAddrIPv6; struct sockaddr *sockAddrPtr = 0; @@ -747,6 +815,159 @@ int QNativeSocketEnginePrivate::nativeAccept() return acceptedDescriptor; } +static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d, + int how6, + int how4, + const QHostAddress &groupAddress, + const QNetworkInterface &iface) +{ + int level = 0; + int sockOpt = 0; + char *sockArg; + int sockArgSize; + + struct ip_mreq mreq4; +#ifndef QT_NO_IPV6 + struct ipv6_mreq mreq6; + + if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) { + level = IPPROTO_IPV6; + sockOpt = how6; + sockArg = reinterpret_cast<char *>(&mreq6); + sockArgSize = sizeof(mreq6); + memset(&mreq6, 0, sizeof(mreq6)); + Q_IPV6ADDR ip6 = groupAddress.toIPv6Address(); + memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6)); + mreq6.ipv6mr_interface = iface.index(); + } else +#endif + if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) { + level = IPPROTO_IP; + sockOpt = how4; + sockArg = reinterpret_cast<char *>(&mreq4); + sockArgSize = sizeof(mreq4); + memset(&mreq4, 0, sizeof(mreq4)); + mreq4.imr_multiaddr.s_addr = htonl(groupAddress.toIPv4Address()); + + if (iface.isValid()) { + QList<QNetworkAddressEntry> addressEntries = iface.addressEntries(); + if (!addressEntries.isEmpty()) { + QHostAddress firstIP = addressEntries.first().ip(); + mreq4.imr_interface.s_addr = htonl(firstIP.toIPv4Address()); + } else { + d->setError(QAbstractSocket::NetworkError, + QNativeSocketEnginePrivate::NetworkUnreachableErrorString); + return false; + } + } else { + mreq4.imr_interface.s_addr = INADDR_ANY; + } + } else { + // unreachable + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + QNativeSocketEnginePrivate::ProtocolUnsupportedErrorString); + return false; + } + + int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize); + if (res == -1) { + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + QNativeSocketEnginePrivate::OperationUnsupportedErrorString); + return false; + } + return true; +} + +bool QNativeSocketEnginePrivate::nativeJoinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) +{ + return multicastMembershipHelper(this, +#ifndef QT_NO_IPV6 + IPV6_JOIN_GROUP, +#else + 0, +#endif + IP_ADD_MEMBERSHIP, + groupAddress, + iface); +} + +bool QNativeSocketEnginePrivate::nativeLeaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) +{ + return multicastMembershipHelper(this, +#ifndef QT_NO_IPV6 + IPV6_LEAVE_GROUP, +#else + 0, +#endif + IP_DROP_MEMBERSHIP, + groupAddress, + iface); +} + +QNetworkInterface QNativeSocketEnginePrivate::nativeMulticastInterface() const +{ +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + uint v; + QT_SOCKOPTLEN_T sizeofv = sizeof(v); + if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &v, &sizeofv) == -1) + return QNetworkInterface(); + return QNetworkInterface::interfaceFromIndex(v); + } +#endif + + struct in_addr v = { 0 }; + QT_SOCKOPTLEN_T sizeofv = sizeof(v); + if (::getsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, (char *) &v, &sizeofv) == -1) + return QNetworkInterface(); + if (v.s_addr != 0 && sizeofv >= sizeof(v)) { + QHostAddress ipv4(ntohl(v.s_addr)); + QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces(); + for (int i = 0; i < ifaces.count(); ++i) { + const QNetworkInterface &iface = ifaces.at(i); + if (!(iface.flags() & QNetworkInterface::CanMulticast)) + continue; + QList<QNetworkAddressEntry> entries = iface.addressEntries(); + for (int j = 0; j < entries.count(); ++j) { + const QNetworkAddressEntry &entry = entries.at(j); + if (entry.ip() == ipv4) + return iface; + } + } + } + return QNetworkInterface(); +} + +bool QNativeSocketEnginePrivate::nativeSetMulticastInterface(const QNetworkInterface &iface) +{ +#ifndef QT_NO_IPV6 + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + uint v = iface.isValid() ? iface.index() : 0; + return (::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &v, sizeof(v)) != -1); + } +#endif + + struct in_addr v; + if (iface.isValid()) { + QList<QNetworkAddressEntry> entries = iface.addressEntries(); + for (int i = 0; i < entries.count(); ++i) { + const QNetworkAddressEntry &entry = entries.at(i); + const QHostAddress &ip = entry.ip(); + if (ip.protocol() == QAbstractSocket::IPv4Protocol) { + v.s_addr = htonl(ip.toIPv4Address()); + int r = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, (char *) &v, sizeof(v)); + if (r != -1) + return true; + } + } + return false; + } + + v.s_addr = INADDR_ANY; + return (::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, (char *) &v, sizeof(v)) != -1); +} qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const { diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp index f68edfe..17cf5b1 100644 --- a/src/network/socket/qsocks5socketengine.cpp +++ b/src/network/socket/qsocks5socketengine.cpp @@ -56,6 +56,7 @@ #include "qurl.h" #include "qauthenticator.h" #include <qendian.h> +#include <qnetworkinterface.h> QT_BEGIN_NAMESPACE @@ -1544,6 +1545,35 @@ qint64 QSocks5SocketEngine::write(const char *data, qint64 len) } #ifndef QT_NO_UDPSOCKET +bool QSocks5SocketEngine::joinMulticastGroup(const QHostAddress &, + const QNetworkInterface &) +{ + setError(QAbstractSocket::UnsupportedSocketOperationError, + QLatin1String("Operation on socket is not supported")); + return false; +} + +bool QSocks5SocketEngine::leaveMulticastGroup(const QHostAddress &, + const QNetworkInterface &) +{ + setError(QAbstractSocket::UnsupportedSocketOperationError, + QLatin1String("Operation on socket is not supported")); + return false; +} + + +QNetworkInterface QSocks5SocketEngine::multicastInterface() const +{ + return QNetworkInterface(); +} + +bool QSocks5SocketEngine::setMulticastInterface(const QNetworkInterface &) +{ + setError(QAbstractSocket::UnsupportedSocketOperationError, + QLatin1String("Operation on socket is not supported")); + return false; +} + qint64 QSocks5SocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress *addr, quint16 *port) { diff --git a/src/network/socket/qsocks5socketengine_p.h b/src/network/socket/qsocks5socketengine_p.h index 3d35b57..06fcad2 100644 --- a/src/network/socket/qsocks5socketengine_p.h +++ b/src/network/socket/qsocks5socketengine_p.h @@ -92,6 +92,13 @@ public: qint64 write(const char *data, qint64 len); #ifndef QT_NO_UDPSOCKET + bool joinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &interface); + bool leaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &interface); + QNetworkInterface multicastInterface() const; + bool setMulticastInterface(const QNetworkInterface &iface); + qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, quint16 *port = 0); qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp index d5366d3..5d8f4c0 100644 --- a/src/network/socket/qudpsocket.cpp +++ b/src/network/socket/qudpsocket.cpp @@ -77,14 +77,23 @@ \snippet doc/src/snippets/code/src_network_socket_qudpsocket.cpp 0 + QUdpSocket also supports UDP multicast. Use joinMulticastGroup() and + leaveMulticastGroup() to control group membership, and + QAbstractSocket::MulticastTtlOption and + QAbstractSocket::MulticastLoopbackOption to set the TTL and loopback socket + options. Use setMulticastInterface() to control the outgoing interface for + multicast datagrams, and multicastInterface() to query it. + With QUdpSocket, you can also establish a virtual connection to a UDP server using connectToHost() and then use read() and write() to exchange datagrams without specifying the receiver for each datagram. - The \l{network/broadcastsender}{Broadcast Sender} and - \l{network/broadcastreceiver}{Broadcast Receiver} examples - illustrate how to use QUdpSocket in applications. + The \l{network/broadcastsender}{Broadcast Sender}, + \l{network/broadcastreceiver}{Broadcast Receiver}, + \l{network/multicastsender}{Multicast Sender}, and + \l{network/multicastreceiver}{Multicast Receiver} examples illustrate how + to use QUdpSocket in applications. \section1 Symbian Platform Security Requirements @@ -145,6 +154,7 @@ */ #include "qhostaddress.h" +#include "qnetworkinterface.h" #include "qabstractsocket_p.h" #include "qudpsocket.h" @@ -329,6 +339,112 @@ bool QUdpSocket::bind(quint16 port, BindMode mode) } /*! + \since 4.8 + + Joins the the multicast group specified by \a groupAddress on the default + interface chosen by the operating system. The socket must be in BoundState, + otherwise an error occurs. + + This function returns true if successful; otherwise it returns false + and sets the socket error accordingly. + + \sa leaveMulticastGroup() +*/ +bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress) +{ + return joinMulticastGroup(groupAddress, QNetworkInterface()); +} + +/*! + \since 4.8 + \overload + + Joins the multicast group address \a groupAddress on the interface \a + iface. + + \sa leaveMulticastGroup() +*/ +bool QUdpSocket::joinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) +{ + Q_D(QUdpSocket); + QT_CHECK_BOUND("QUdpSocket::joinMulticastGroup()", false); + return d->socketEngine->joinMulticastGroup(groupAddress, iface); +} + +/*! + \since 4.8 + + Leaves the multicast group specified by \a groupAddress on the default + interface chosen by the operating system. The socket must be in BoundState, + otherwise an error occurs. + + This function returns true if successful; otherwise it returns false and + sets the socket error accordingly. + + \sa joinMulticastGroup() +*/ +bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress) +{ + return leaveMulticastGroup(groupAddress, QNetworkInterface()); +} + +/*! + \since 4.8 + \overload + + Leaves the multicast group specified by \a groupAddress on the interface \a + iface. + + \sa joinMulticastGroup() +*/ +bool QUdpSocket::leaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface) +{ + QT_CHECK_BOUND("QUdpSocket::leaveMulticastGroup()", false); + return d_func()->socketEngine->leaveMulticastGroup(groupAddress, iface); +} + +/*! + \since 4.8 + + Returns the interface for the outgoing interface for multicast datagrams. + This corresponds to the IP_MULTICAST_IF socket option for IPv4 sockets and + the IPV6_MULTICAST_IF socket option for IPv6 sockets. If no interface has + been previously set, this function returns an invalid QNetworkInterface. + The socket must be in BoundState, otherwise an invalid QNetworkInterface is + returned. + + \sa setMulticastInterface() +*/ +QNetworkInterface QUdpSocket::multicastInterface() const +{ + Q_D(const QUdpSocket); + QT_CHECK_BOUND("QUdpSocket::multicastInterface()", QNetworkInterface()); + return d->socketEngine->multicastInterface(); +} + +/*! + \since 4.8 + + Sets the outgoing interface for multicast datagrams to the interface \a + iface. This corresponds to the IP_MULTICAST_IF socket option for IPv4 + sockets and the IPV6_MULTICAST_IF socket option for IPv6 sockets. The + socket must be in BoundState, otherwise this function does nothing. + + \sa multicastInterface(), joinMulticastGroup(), leaveMulticastGroup() +*/ +void QUdpSocket::setMulticastInterface(const QNetworkInterface &iface) +{ + Q_D(QUdpSocket); + if (!isValid()) { + qWarning("QUdpSocket::setMulticastInterface() called on a QUdpSocket when not in QUdpSocket::BoundState"); + return; + } + d->socketEngine->setMulticastInterface(iface); +} + +/*! Returns true if at least one datagram is waiting to be read; otherwise returns false. diff --git a/src/network/socket/qudpsocket.h b/src/network/socket/qudpsocket.h index f477306..b277d3f 100644 --- a/src/network/socket/qudpsocket.h +++ b/src/network/socket/qudpsocket.h @@ -53,6 +53,7 @@ QT_MODULE(Network) #ifndef QT_NO_UDPSOCKET +class QNetworkInterface; class QUdpSocketPrivate; class Q_NETWORK_EXPORT QUdpSocket : public QAbstractSocket @@ -76,6 +77,16 @@ public: bool bind(quint16 port, BindMode mode); // ### Qt 5: Merge the bind functions + bool joinMulticastGroup(const QHostAddress &groupAddress); + bool joinMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface); + bool leaveMulticastGroup(const QHostAddress &groupAddress); + bool leaveMulticastGroup(const QHostAddress &groupAddress, + const QNetworkInterface &iface); + + QNetworkInterface multicastInterface() const; + void setMulticastInterface(const QNetworkInterface &iface); + bool hasPendingDatagrams() const; qint64 pendingDatagramSize() const; qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *host = 0, quint16 *port = 0); diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index ac87784..93ff3f4 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -47,24 +47,29 @@ #include <QMetaEnum> #endif +// #define QT_GL_SHARED_SHADER_DEBUG QT_BEGIN_NAMESPACE -static void qt_shared_shaders_free(void *data) +class QGLShaderStorage { - delete reinterpret_cast<QGLEngineSharedShaders *>(data); -} +public: + QGLEngineSharedShaders *shadersForThread(const QGLContext *context) { + QGLContextGroupResource<QGLEngineSharedShaders> *&shaders = m_storage.localData(); + if (!shaders) + shaders = new QGLContextGroupResource<QGLEngineSharedShaders>(); + return shaders->value(context); + } + +private: + QThreadStorage<QGLContextGroupResource<QGLEngineSharedShaders> *> m_storage; +}; -Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_shared_shaders, (qt_shared_shaders_free)) +Q_GLOBAL_STATIC(QGLShaderStorage, qt_shader_storage); QGLEngineSharedShaders *QGLEngineSharedShaders::shadersForContext(const QGLContext *context) { - QGLEngineSharedShaders *p = reinterpret_cast<QGLEngineSharedShaders *>(qt_shared_shaders()->value(context)); - if (!p) { - QGLShareContextScope scope(context); - qt_shared_shaders()->insert(context, p = new QGLEngineSharedShaders(context)); - } - return p; + return qt_shader_storage()->shadersForThread(context); } const char* QGLEngineSharedShaders::qShaderSnippets[] = { @@ -171,18 +176,20 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) source.clear(); source.append(qShaderSnippets[MainVertexShader]); source.append(qShaderSnippets[PositionOnlyVertexShader]); - vertexShader = new QGLShader(QGLShader::Vertex, context, this); + vertexShader = new QGLShader(QGLShader::Vertex, context, 0); + shaders.append(vertexShader); 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); + fragShader = new QGLShader(QGLShader::Fragment, context, 0); + shaders.append(fragShader); if (!fragShader->compileSourceCode(source)) qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile"); - simpleShaderProg = new QGLShaderProgram(context, this); + simpleShaderProg = new QGLShaderProgram(context, 0); simpleShaderProg->addShader(vertexShader); simpleShaderProg->addShader(fragShader); simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); @@ -199,18 +206,20 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) source.clear(); source.append(qShaderSnippets[MainWithTexCoordsVertexShader]); source.append(qShaderSnippets[UntransformedPositionVertexShader]); - vertexShader = new QGLShader(QGLShader::Vertex, context, this); + vertexShader = new QGLShader(QGLShader::Vertex, context, 0); + shaders.append(vertexShader); 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); + fragShader = new QGLShader(QGLShader::Fragment, context, 0); + shaders.append(fragShader); if (!fragShader->compileSourceCode(source)) qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile"); - blitShaderProg = new QGLShaderProgram(context, this); + blitShaderProg = new QGLShaderProgram(context, 0); blitShaderProg->addShader(vertexShader); blitShaderProg->addShader(fragShader); blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); @@ -221,13 +230,21 @@ QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context) << simpleShaderProg->log(); } +#ifdef QT_GL_SHARED_SHADER_DEBUG + qDebug(" -> QGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread()); +#endif } QGLEngineSharedShaders::~QGLEngineSharedShaders() { - QList<QGLEngineShaderProg*>::iterator itr; - for (itr = cachedPrograms.begin(); itr != cachedPrograms.end(); ++itr) - delete *itr; +#ifdef QT_GL_SHARED_SHADER_DEBUG + qDebug(" -> ~QGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread()); +#endif + qDeleteAll(shaders); + shaders.clear(); + + qDeleteAll(cachedPrograms); + cachedPrograms.clear(); if (blitShaderProg) { delete blitShaderProg; @@ -279,7 +296,8 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS source.append(qShaderSnippets[prog.compositionFragShader]); if (prog.maskFragShader) source.append(qShaderSnippets[prog.maskFragShader]); - fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this); + fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), 0); + shaders.append(fragShader); QByteArray description; #if defined(QT_DEBUG) // Name the shader for easier debugging @@ -305,7 +323,8 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS source.clear(); source.append(qShaderSnippets[prog.mainVertexShader]); source.append(qShaderSnippets[prog.positionVertexShader]); - vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this); + vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), 0); + shaders.append(vertexShader); #if defined(QT_DEBUG) // Name the shader for easier debugging description.clear(); @@ -323,7 +342,7 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS newProg = new QGLEngineShaderProg(prog); // If the shader program's not found in the cache, create it now. - newProg->program = new QGLShaderProgram(ctxGuard.context(), this); + newProg->program = new QGLShaderProgram(ctxGuard.context(), 0); newProg->program->addShader(vertexShader); newProg->program->addShader(fragShader); @@ -424,7 +443,6 @@ QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context) currentShaderProg(0) { sharedShaders = QGLEngineSharedShaders::shadersForContext(context); - connect(sharedShaders, SIGNAL(shaderProgNeedsChanging()), this, SLOT(shaderProgNeedsChangingSlot())); } QGLEngineShaderManager::~QGLEngineShaderManager() diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 92cf108..d24f302 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -259,9 +259,9 @@ static const GLuint QT_PMV_MATRIX_3_ATTR = 5; class QGLEngineShaderProg; -class QGLEngineSharedShaders : public QObject +class QGLEngineSharedShaders { - Q_OBJECT + Q_GADGET public: enum SnippetName { @@ -364,14 +364,12 @@ public: // full. void cleanupCustomStage(QGLCustomShaderStage* stage); -signals: - void shaderProgNeedsChanging(); - private: QGLSharedResourceGuard ctxGuard; QGLShaderProgram *blitShaderProg; QGLShaderProgram *simpleShaderProg; QList<QGLEngineShaderProg*> cachedPrograms; + QList<QGLShader *> shaders; static const char* qShaderSnippets[TotalSnippetCount]; }; @@ -492,9 +490,6 @@ public: QGLEngineSharedShaders* sharedShaders; -private slots: - void shaderProgNeedsChangingSlot() { shaderProgNeedsChanging = true; } - private: QGLContext* ctx; bool shaderProgNeedsChanging; diff --git a/src/opengl/gl2paintengineex/qglgradientcache.cpp b/src/opengl/gl2paintengineex/qglgradientcache.cpp index a1495dd..cbd5eb8 100644 --- a/src/opengl/gl2paintengineex/qglgradientcache.cpp +++ b/src/opengl/gl2paintengineex/qglgradientcache.cpp @@ -42,29 +42,33 @@ #include "qglgradientcache_p.h" #include <private/qdrawhelper_p.h> #include <private/qgl_p.h> - +#include <QtCore/qmutex.h> QT_BEGIN_NAMESPACE -static void QGL2GradientCache_free(void *ptr) +class QGL2GradientCacheWrapper { - delete reinterpret_cast<QGL2GradientCache *>(ptr); -} +public: + QGL2GradientCache *cacheForContext(const QGLContext *context) { + QMutexLocker lock(&m_mutex); + return m_resource.value(context); + } -Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_gradient_caches, (QGL2GradientCache_free)) +private: + QGLContextGroupResource<QGL2GradientCache> m_resource; + QMutex m_mutex; +}; + +Q_GLOBAL_STATIC(QGL2GradientCacheWrapper, qt_gradient_caches) QGL2GradientCache *QGL2GradientCache::cacheForContext(const QGLContext *context) { - QGL2GradientCache *p = reinterpret_cast<QGL2GradientCache *>(qt_gradient_caches()->value(context)); - if (!p) { - QGLShareContextScope scope(context); - p = new QGL2GradientCache; - qt_gradient_caches()->insert(context, p); - } - return p; + return qt_gradient_caches()->cacheForContext(context); } -void QGL2GradientCache::cleanCache() { +void QGL2GradientCache::cleanCache() +{ + QMutexLocker lock(&m_mutex); QGLGradientColorTableHash::const_iterator it = cache.constBegin(); for (; it != cache.constEnd(); ++it) { const CacheInfo &cache_info = it.value(); @@ -75,6 +79,7 @@ void QGL2GradientCache::cleanCache() { GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity) { + QMutexLocker lock(&m_mutex); quint64 hash_val = 0; QGradientStops stops = gradient.stops(); @@ -88,7 +93,9 @@ GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity) else { do { const CacheInfo &cache_info = it.value(); - if (cache_info.stops == stops && cache_info.opacity == opacity && cache_info.interpolationMode == gradient.interpolationMode()) { + if (cache_info.stops == stops && cache_info.opacity == opacity + && cache_info.interpolationMode == gradient.interpolationMode()) + { return cache_info.texId; } ++it; diff --git a/src/opengl/gl2paintengineex/qglgradientcache_p.h b/src/opengl/gl2paintengineex/qglgradientcache_p.h index 0a5f846..7e93d87 100644 --- a/src/opengl/gl2paintengineex/qglgradientcache_p.h +++ b/src/opengl/gl2paintengineex/qglgradientcache_p.h @@ -54,6 +54,7 @@ #include <QObject> #include <QtOpenGL/QtOpenGL> #include <private/qgl_p.h> +#include <QtCore/qmutex.h> QT_BEGIN_NAMESPACE @@ -75,22 +76,22 @@ class QGL2GradientCache public: static QGL2GradientCache *cacheForContext(const QGLContext *context); - QGL2GradientCache() { } - ~QGL2GradientCache() {cleanCache();} + QGL2GradientCache(const QGLContext *) {} + ~QGL2GradientCache() { cleanCache(); } GLuint getBuffer(const QGradient &gradient, qreal opacity); inline int paletteSize() const { return 1024; } -protected: +private: inline int maxCacheSize() const { return 60; } inline void generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const; GLuint addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity); - void cleanCache(); QGLGradientColorTableHash cache; + QMutex m_mutex; }; QT_END_NAMESPACE diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 84c7fed..66895dd 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -872,6 +872,35 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) // Tag it for later so that if the same path is drawn twice, it is assumed to be static and thus cachable path.makeCacheable(); + if (!device->format().stencil()) { + // If there is no stencil buffer, triangulate the path instead. + + QRectF bbox = path.controlPointRect(); + // If the path doesn't fit within these limits, it is possible that the triangulation will fail. + bool withinLimits = (bbox.left() > -0x8000 * inverseScale) + && (bbox.right() < 0x8000 * inverseScale) + && (bbox.top() > -0x8000 * inverseScale) + && (bbox.bottom() < 0x8000 * inverseScale); + if (withinLimits) { + QTriangleSet polys = qTriangulate(path, QTransform().scale(1 / inverseScale, 1 / inverseScale)); + + QVarLengthArray<float> vertices(polys.vertices.size()); + for (int i = 0; i < polys.vertices.size(); ++i) + vertices[i] = float(inverseScale * polys.vertices.at(i)); + + prepareForDraw(currentBrush.isOpaque()); + setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, vertices.constData()); + if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) + glDrawElements(GL_TRIANGLES, polys.indices.size(), GL_UNSIGNED_INT, polys.indices.data()); + else + glDrawElements(GL_TRIANGLES, polys.indices.size(), GL_UNSIGNED_SHORT, polys.indices.data()); + } else { + // We can't handle big, concave painter paths with OpenGL without stencil buffer. + qWarning("Painter path exceeds +/-32767 pixels."); + } + return; + } + // The path is too complicated & needs the stencil technique vertexCoordinateArray.clear(); vertexCoordinateArray.addPath(path, inverseScale, false); @@ -1474,11 +1503,13 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp QOpenGL2PaintEngineState *s = q->state(); + void *cacheKey = const_cast<QGLContext *>(QGLContextPrivate::contextGroup(ctx)->context()); QGLTextureGlyphCache *cache = - (QGLTextureGlyphCache *) staticTextItem->fontEngine->glyphCache(ctx, glyphType, QTransform()); - if (!cache || cache->cacheType() != glyphType) { + (QGLTextureGlyphCache *) staticTextItem->fontEngine->glyphCache(cacheKey, glyphType, QTransform()); + if (!cache || cache->cacheType() != glyphType || cache->context() == 0) { cache = new QGLTextureGlyphCache(ctx, glyphType, QTransform()); - staticTextItem->fontEngine->setGlyphCache(ctx, cache); + staticTextItem->fontEngine->setGlyphCache(cacheKey, cache); + cache->insert(ctx, cache); } bool recreateVertexArrays = false; @@ -1496,6 +1527,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp cache->setPaintEnginePrivate(this); cache->populate(staticTextItem->fontEngine, staticTextItem->numGlyphs, staticTextItem->glyphs, staticTextItem->glyphPositions); + cache->fillInPendingGlyphs(); } if (cache->width() == 0 || cache->height() == 0) @@ -1541,8 +1573,15 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp vertexCoordinates->clear(); textureCoordinates->clear(); + bool supportsSubPixelPositions = staticTextItem->fontEngine->supportsSubPixelPositions(); for (int i=0; i<staticTextItem->numGlyphs; ++i) { - const QTextureGlyphCache::Coord &c = cache->coords.value(staticTextItem->glyphs[i]); + QFixed subPixelPosition; + if (supportsSubPixelPositions) + subPixelPosition = cache->subPixelPositionForX(staticTextItem->glyphPositions[i].x); + + QTextureGlyphCache::GlyphAndSubPixelPosition glyph(staticTextItem->glyphs[i], subPixelPosition); + + const QTextureGlyphCache::Coord &c = cache->coords.value(glyph); int x = staticTextItem->glyphPositions[i].x.toInt() + c.baseLineX - margin; int y = staticTextItem->glyphPositions[i].y.toInt() - c.baseLineY - margin; diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index 919c542..7954d77 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -41,6 +41,7 @@ #include "qtextureglyphcache_gl_p.h" #include "qpaintengineex_opengl2_p.h" +#include "private/qglengineshadersource_p.h" #if defined QT_OPENGL_ES_2 && !defined(QT_NO_EGL) #include "private/qeglcontext_p.h" @@ -52,40 +53,59 @@ QT_BEGIN_NAMESPACE extern Q_GUI_EXPORT bool qt_cleartype_enabled; #endif -QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix) - : QImageTextureGlyphCache(type, matrix) +QGLTextureGlyphCache::QGLTextureGlyphCache(const QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix) + : QImageTextureGlyphCache(type, matrix), QGLContextGroupResourceBase() , ctx(context) - , m_width(0) - , m_height(0) + , pex(0) + , m_blitProgram(0) , m_filterMode(Nearest) { - // broken FBO readback is a bug in the SGX 1.3 and 1.4 drivers for the N900 where - // copying between FBO's is broken if the texture is either GL_ALPHA or POT. The - // workaround is to use a system-memory copy of the glyph cache for this device. - // Switching to NPOT and GL_RGBA would both cost a lot more graphics memory and - // be slower, so that is not desireable. - if (!ctx->d_ptr->workaround_brokenFBOReadBack) - glGenFramebuffers(1, &m_fbo); - - connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)), - SLOT(contextDestroyed(const QGLContext*))); +#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG + qDebug(" -> QGLTextureGlyphCache() %p for context %p.", this, ctx); +#endif + setContext(context); + + m_vertexCoordinateArray[0] = -1.0f; + m_vertexCoordinateArray[1] = -1.0f; + m_vertexCoordinateArray[2] = 1.0f; + m_vertexCoordinateArray[3] = -1.0f; + m_vertexCoordinateArray[4] = 1.0f; + m_vertexCoordinateArray[5] = 1.0f; + m_vertexCoordinateArray[6] = -1.0f; + m_vertexCoordinateArray[7] = 1.0f; + + m_textureCoordinateArray[0] = 0.0f; + m_textureCoordinateArray[1] = 0.0f; + m_textureCoordinateArray[2] = 1.0f; + m_textureCoordinateArray[3] = 0.0f; + m_textureCoordinateArray[4] = 1.0f; + m_textureCoordinateArray[5] = 1.0f; + m_textureCoordinateArray[6] = 0.0f; + m_textureCoordinateArray[7] = 1.0f; } QGLTextureGlyphCache::~QGLTextureGlyphCache() { - if (ctx) { - QGLShareContextScope scope(ctx); +#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG + qDebug(" -> ~QGLTextureGlyphCache() %p.", this); +#endif - if (!ctx->d_ptr->workaround_brokenFBOReadBack) - glDeleteFramebuffers(1, &m_fbo); + delete m_blitProgram; +} - if (m_width || m_height) - glDeleteTextures(1, &m_texture); - } +void QGLTextureGlyphCache::setContext(const QGLContext *context) +{ + ctx = context; + m_h = 0; } void QGLTextureGlyphCache::createTextureData(int width, int height) { + if (ctx == 0) { + qWarning("QGLTextureGlyphCache::createTextureData: Called with no context"); + return; + } + // create in QImageTextureGlyphCache baseclass is meant to be called // only to create the initial image and does not preserve the content, // so we don't call when this function is called from resize. @@ -98,11 +118,12 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) if (height < 16) height = 16; - glGenTextures(1, &m_texture); - glBindTexture(GL_TEXTURE_2D, m_texture); + QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx); + glGenTextures(1, &glyphTexture->m_texture); + glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); - m_width = width; - m_height = height; + glyphTexture->m_width = width; + glyphTexture->m_height = height; QVarLengthArray<uchar> data(width * height); for (int i = 0; i < data.size(); ++i) @@ -122,8 +143,14 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) void QGLTextureGlyphCache::resizeTextureData(int width, int height) { - int oldWidth = m_width; - int oldHeight = m_height; + if (ctx == 0) { + qWarning("QGLTextureGlyphCache::resizeTextureData: Called with no context"); + return; + } + QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx); + + int oldWidth = glyphTexture->m_width; + int oldHeight = glyphTexture->m_height; // Make the lower glyph texture size 16 x 16. if (width < 16) @@ -131,7 +158,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) if (height < 16) height = 16; - GLuint oldTexture = m_texture; + GLuint oldTexture = glyphTexture->m_texture; createTextureData(width, height); if (ctx->d_ptr->workaround_brokenFBOReadBack) { @@ -145,7 +172,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) // ### the QTextureGlyphCache API needs to be reworked to allow // ### resizeTextureData to fail - glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo); + glBindFramebuffer(GL_FRAMEBUFFER_EXT, glyphTexture->m_fbo); GLuint tmp_texture; glGenTextures(1, &tmp_texture); @@ -164,7 +191,8 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); glBindTexture(GL_TEXTURE_2D, oldTexture); - pex->transferMode(BrushDrawingMode); + if (pex != 0) + pex->transferMode(BrushDrawingMode); glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); @@ -173,35 +201,62 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) glViewport(0, 0, oldWidth, oldHeight); - GLfloat* vertexCoordinateArray = pex->staticVertexCoordinateArray; - vertexCoordinateArray[0] = -1.0f; - vertexCoordinateArray[1] = -1.0f; - vertexCoordinateArray[2] = 1.0f; - vertexCoordinateArray[3] = -1.0f; - vertexCoordinateArray[4] = 1.0f; - vertexCoordinateArray[5] = 1.0f; - vertexCoordinateArray[6] = -1.0f; - vertexCoordinateArray[7] = 1.0f; - - GLfloat* textureCoordinateArray = pex->staticTextureCoordinateArray; - textureCoordinateArray[0] = 0.0f; - textureCoordinateArray[1] = 0.0f; - textureCoordinateArray[2] = 1.0f; - textureCoordinateArray[3] = 0.0f; - textureCoordinateArray[4] = 1.0f; - textureCoordinateArray[5] = 1.0f; - textureCoordinateArray[6] = 0.0f; - textureCoordinateArray[7] = 1.0f; - - pex->setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, vertexCoordinateArray); - pex->setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, textureCoordinateArray); - - pex->shaderManager->useBlitProgram(); - pex->shaderManager->blitProgram()->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT); + QGLShaderProgram *blitProgram = 0; + if (pex == 0) { + if (m_blitProgram == 0) { + m_blitProgram = new QGLShaderProgram(ctx); + + { + QString source; + source.append(QLatin1String(qglslMainWithTexCoordsVertexShader)); + source.append(QLatin1String(qglslUntransformedPositionVertexShader)); + + QGLShader *vertexShader = new QGLShader(QGLShader::Vertex, m_blitProgram); + vertexShader->compileSourceCode(source); + + m_blitProgram->addShader(vertexShader); + } + + { + QString source; + source.append(QLatin1String(qglslMainFragmentShader)); + source.append(QLatin1String(qglslImageSrcFragmentShader)); + + QGLShader *fragmentShader = new QGLShader(QGLShader::Fragment, m_blitProgram); + fragmentShader->compileSourceCode(source); + + m_blitProgram->addShader(fragmentShader); + } + + m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); + m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); + + m_blitProgram->link(); + } + + glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_vertexCoordinateArray); + glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_textureCoordinateArray); + + m_blitProgram->bind(); + m_blitProgram->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR)); + m_blitProgram->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR)); + m_blitProgram->disableAttributeArray(int(QT_OPACITY_ATTR)); + + blitProgram = m_blitProgram; + + } else { + pex->setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, m_vertexCoordinateArray); + pex->setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, m_textureCoordinateArray); + + pex->shaderManager->useBlitProgram(); + blitProgram = pex->shaderManager->blitProgram(); + } + + blitProgram->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glBindTexture(GL_TEXTURE_2D, m_texture); + glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight); @@ -212,16 +267,24 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); - glViewport(0, 0, pex->width, pex->height); - pex->updateClipScissorTest(); + if (pex != 0) { + glViewport(0, 0, pex->width, pex->height); + pex->updateClipScissorTest(); + } } -void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph) +void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition) { + if (ctx == 0) { + qWarning("QGLTextureGlyphCache::fillTexture: Called with no context"); + return; + } + + QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx); if (ctx->d_ptr->workaround_brokenFBOReadBack) { - QImageTextureGlyphCache::fillTexture(c, glyph); + QImageTextureGlyphCache::fillTexture(c, glyph, subPixelPosition); - glBindTexture(GL_TEXTURE_2D, m_texture); + glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); const QImage &texture = image(); const uchar *bits = texture.constBits(); bits += c.y * texture.bytesPerLine() + c.x; @@ -229,11 +292,10 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph) glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, c.w, 1, GL_ALPHA, GL_UNSIGNED_BYTE, bits); bits += texture.bytesPerLine(); } - return; } - QImage mask = textureMapForGlyph(glyph); + QImage mask = textureMapForGlyph(glyph, subPixelPosition); const int maskWidth = mask.width(); const int maskHeight = mask.height(); @@ -259,7 +321,7 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph) } } - glBindTexture(GL_TEXTURE_2D, m_texture); + glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture); if (mask.format() == QImage::Format_RGB32) { glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits()); } else { @@ -288,11 +350,17 @@ int QGLTextureGlyphCache::glyphPadding() const int QGLTextureGlyphCache::maxTextureWidth() const { - return ctx->d_ptr->maxTextureSize(); + if (ctx == 0) + return QImageTextureGlyphCache::maxTextureWidth(); + else + return ctx->d_ptr->maxTextureSize(); } int QGLTextureGlyphCache::maxTextureHeight() const { - return ctx->d_ptr->maxTextureSize(); + if (ctx == 0) + return QImageTextureGlyphCache::maxTextureHeight(); + else + return ctx->d_ptr->maxTextureSize(); } QT_END_NAMESPACE diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h index e22146d..572da82 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h @@ -57,32 +57,82 @@ #include <private/qgl_p.h> #include <qglshaderprogram.h> +// #define QT_GL_TEXTURE_GLYPH_CACHE_DEBUG QT_BEGIN_NAMESPACE class QGL2PaintEngineExPrivate; -class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QObject, public QImageTextureGlyphCache +struct QGLGlyphTexture +{ + QGLGlyphTexture(const QGLContext *ctx) + : m_width(0) + , m_height(0) + { + if (ctx && !ctx->d_ptr->workaround_brokenFBOReadBack) + glGenFramebuffers(1, &m_fbo); + +#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG + qDebug(" -> QGLGlyphTexture() %p for context %p.", this, ctx); +#endif + } + + ~QGLGlyphTexture() { + const QGLContext *ctx = QGLContext::currentContext(); +#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG + qDebug("~QGLGlyphTexture() %p for context %p.", this, ctx); +#endif + // At this point, the context group is made current, so it's safe to + // release resources without a makeCurrent() call + if (ctx) { + if (!ctx->d_ptr->workaround_brokenFBOReadBack) + glDeleteFramebuffers(1, &m_fbo); + if (m_width || m_height) + glDeleteTextures(1, &m_texture); + } + } + + GLuint m_texture; + GLuint m_fbo; + int m_width; + int m_height; +}; + +class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QImageTextureGlyphCache, public QGLContextGroupResourceBase { - Q_OBJECT public: - QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix); + QGLTextureGlyphCache(const QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix); ~QGLTextureGlyphCache(); virtual void createTextureData(int width, int height); virtual void resizeTextureData(int width, int height); - virtual void fillTexture(const Coord &c, glyph_t glyph); + virtual void fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition); virtual int glyphPadding() const; virtual int maxTextureWidth() const; virtual int maxTextureHeight() const; - inline GLuint texture() const { return m_texture; } + inline GLuint texture() const { + QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this); + QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx); + return glyphTexture ? glyphTexture->m_texture : 0; + } - inline int width() const { return m_width; } - inline int height() const { return m_height; } + inline int width() const { + QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this); + QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx); + return glyphTexture ? glyphTexture->m_width : 0; + } + inline int height() const { + QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this); + QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx); + return glyphTexture ? glyphTexture->m_height : 0; + } inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; } + void setContext(const QGLContext *context); + inline const QGLContext *context() const { return ctx; } + enum FilterMode { Nearest, Linear @@ -90,41 +140,18 @@ public: FilterMode filterMode() const { return m_filterMode; } void setFilterMode(FilterMode m) { m_filterMode = m; } -public Q_SLOTS: - void contextDestroyed(const QGLContext *context) { - if (context == ctx) { - const QGLContext *nextCtx = qt_gl_transfer_context(ctx); - if (!nextCtx) { - // the context may not be current, so we cannot directly - // destroy the fbo and texture here, but since the context - // is about to be destroyed, the GL server will do the - // clean up for us anyway - m_fbo = 0; - m_texture = 0; - ctx = 0; - } else { - // since the context holding the texture is shared, and - // about to be destroyed, we have to transfer ownership - // of the texture to one of the share contexts - ctx = const_cast<QGLContext *>(nextCtx); - } - } - } + void freeResource(void *) { ctx = 0; } private: - QGLContext *ctx; + QGLContextGroupResource<QGLGlyphTexture> m_textureResource; + const QGLContext *ctx; QGL2PaintEngineExPrivate *pex; - - GLuint m_texture; - GLuint m_fbo; - - int m_width; - int m_height; - - QGLShaderProgram *m_program; - + QGLShaderProgram *m_blitProgram; FilterMode m_filterMode; + + GLfloat m_vertexCoordinateArray[8]; + GLfloat m_textureCoordinateArray[8]; }; QT_END_NAMESPACE diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index 0e82467..682e620 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -11,7 +11,7 @@ unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui include(../qbase.pri) -!win32:!embedded:!mac:!symbian:CONFIG += x11 +!win32:!embedded:!mac:!symbian:!qpa:CONFIG += x11 contains(QT_CONFIG, opengl):CONFIG += opengl contains(QT_CONFIG, opengles1):CONFIG += opengles1 contains(QT_CONFIG, opengles2):CONFIG += opengles2 @@ -20,6 +20,7 @@ contains(QT_CONFIG, egl):CONFIG += egl HEADERS += qgl.h \ qgl_p.h \ qglcolormap.h \ + qglfunctions.h \ qglpixelbuffer.h \ qglpixelbuffer_p.h \ qglframebufferobject.h \ @@ -29,8 +30,9 @@ HEADERS += qgl.h \ qglbuffer.h \ -SOURCES += qgl.cpp \ +SOURCES += qgl.cpp \ qglcolormap.cpp \ + qglfunctions.cpp \ qglpixelbuffer.cpp \ qglframebufferobject.cpp \ qglextensions.cpp \ @@ -77,6 +79,11 @@ SOURCES += qgl.cpp \ } +qpa { + SOURCES += qgl_qpa.cpp \ + qglpixelbuffer_stub.cpp +} + x11 { contains(QT_CONFIG, egl) { SOURCES += qgl_x11egl.cpp \ diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index dbd295f..f316db6 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -93,10 +93,15 @@ #include "qlibrary.h" #include <qmutex.h> +#ifdef QT_OPENGL_ES +#include <EGL/egl.h> +#endif + +// #define QT_GL_CONTEXT_RESOURCE_DEBUG QT_BEGIN_NAMESPACE -#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs; #endif @@ -105,6 +110,10 @@ extern const QX11Info *qt_x11Info(const QPaintDevice *pd); #endif struct QGLThreadContext { + ~QGLThreadContext() { + if (context) + context->doneCurrent(); + } QGLContext *context; }; @@ -1400,6 +1409,10 @@ QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags() } } +#ifdef Q_WS_QPA + hasOpenGL(); // ### I have no idea why this is needed here, but it makes things work for testlite +#endif + QString versionString(QLatin1String(reinterpret_cast<const char*>(glGetString(GL_VERSION)))); OpenGLVersionFlags versionFlags = qOpenGLVersionFlagsFromString(versionString); if (currentCtx) { @@ -1660,6 +1673,7 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format) #if defined(Q_WS_WIN) dc = 0; win = 0; + threadId = 0; pixelFormatId = 0; cmap = 0; hbitmap = 0; @@ -1671,7 +1685,10 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format) # endif vi = 0; #endif -#ifndef QT_NO_EGL +#if defined(Q_WS_QPA) + platformContext = 0; +#endif +#if !defined(QT_NO_EGL) ownsEglContext = false; eglContext = 0; eglSurface = EGL_NO_SURFACE; @@ -2065,6 +2082,9 @@ QGLContext::~QGLContext() // remove any textures cached in this context QGLTextureCache::instance()->removeContextTextures(this); + // clean up resources specific to this context + d_ptr->cleanup(); + // clean up resources belonging to this context's group d_ptr->group->cleanupResources(this); QGLSignalProxy::instance()->emitAboutToDestroyContext(this); @@ -2073,6 +2093,10 @@ QGLContext::~QGLContext() void QGLContextPrivate::cleanup() { + QHash<QGLContextResourceBase *, void *>::ConstIterator it; + for (it = m_resources.begin(); it != m_resources.end(); ++it) + it.key()->freeResource(it.value()); + m_resources.clear(); } #define ctx q_ptr @@ -2132,20 +2156,10 @@ void QGLContextPrivate::swapRegion(const QRegion &) GLuint QGLContext::bindTexture(const QString &fileName) { - Q_D(QGLContext); - QGLDDSCache *dds_cache = &(d->group->m_dds_cache); - QGLDDSCache::const_iterator it = dds_cache->constFind(fileName); - if (it != dds_cache->constEnd()) { - glBindTexture(GL_TEXTURE_2D, it.value()); - return it.value(); - } - QGLTexture texture(this); QSize size = texture.bindCompressedTexture(fileName); if (!size.isValid()) return 0; - - dds_cache->insert(fileName, texture.id); return texture.id; } @@ -2264,7 +2278,7 @@ static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum textu } } -#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) QGLExtensionFuncs& QGLContextPrivate::extensionFuncs(const QGLContext *) { return qt_extensionFuncs; @@ -2585,7 +2599,8 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, const QX11Info *xinfo = qt_x11Info(paintDevice); if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType && xinfo && xinfo->screen() == pixmap.x11Info().screen() - && target == GL_TEXTURE_2D) + && target == GL_TEXTURE_2D + && QApplication::instance()->thread() == QThread::currentThread()) { if (!workaround_brokenTextureFromPixmap_init) { workaround_brokenTextureFromPixmap_init = true; @@ -2806,24 +2821,8 @@ GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, Q */ void QGLContext::deleteTexture(GLuint id) { - Q_D(QGLContext); - if (QGLTextureCache::instance()->remove(this, id)) return; - - // check the DDS cache if the texture wasn't found in the pixmap/image - // cache - QGLDDSCache *dds_cache = &(d->group->m_dds_cache); - QList<QString> ddsKeys = dds_cache->keys(); - for (int i = 0; i < ddsKeys.size(); ++i) { - GLuint texture = dds_cache->value(ddsKeys.at(i)); - if (id == texture) { - dds_cache->remove(ddsKeys.at(i)); - break; - } - } - - // Finally, actually delete the texture ID glDeleteTextures(1, &id); } @@ -3620,12 +3619,90 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context) \section1 Threading - It is possible to render into a QGLWidget from another thread, but it - requires that all access to the GL context is safe guarded. The Qt GUI - thread will try to use the context in resizeEvent and paintEvent, so in - order for threaded rendering using a GL widget to work, these functions - need to be intercepted in the GUI thread and handled accordingly in the - application. + As of Qt version 4.8, support for doing threaded GL rendering has + been improved. There are three scenarios that we currently support: + \list + \o 1. Buffer swapping in a thread. + + Swapping buffers in a double buffered context may be a + synchronous, locking call that may be a costly operation in some + GL implementations. Especially so on embedded devices. It's not + optimal to have the CPU idling while the GPU is doing a buffer + swap. In those cases it is possible to do the rendering in the + main thread and do the actual buffer swap in a separate + thread. This can be done with the following steps: + + 1. Call doneCurrent() in the main thread when the rendering is + finished. + + 2. Notify the swapping thread that it can grab the context. + + 3. Make the rendering context current in the swapping thread with + makeCurrent() and then call swapBuffers(). + + 4. Call doneCurrent() in the swapping thread and notify the main + thread that swapping is done. + + Doing this will free up the main thread so that it can continue + with, for example, handling UI events or network requests. Even if + there is a context swap involved, it may be preferable compared to + having the main thread wait while the GPU finishes the swap + operation. Note that this is highly implementation dependent. + + \o 2. Texture uploading in a thread. + + Doing texture uploads in a thread may be very useful for + applications handling large amounts of images that needs to be + displayed, like for instance a photo gallery application. This is + supported in Qt through the existing bindTexture() API. A simple + way of doing this is to create two sharing QGLWidgets. One is made + current in the main GUI thread, while the other is made current in + the texture upload thread. The widget in the uploading thread is + never shown, it is only used for sharing textures with the main + thread. For each texture that is bound via bindTexture(), notify + the main thread so that it can start using the texture. + + \o 3. Using QPainter to draw into a QGLWidget in a thread. + + In Qt 4.8, it is possible to draw into a QGLWidget using a + QPainter in a separate thread. Note that this is also possible for + QGLPixelBuffers and QGLFramebufferObjects. Since this is only + supported in the GL 2 paint engine, OpenGL 2.0 or OpenGL ES 2.0 is + required. + + QGLWidgets can only be created in the main GUI thread. This means + a call to doneCurrent() is necessary to release the GL context + from the main thread, before the widget can be drawn into by + another thread. Also, the main GUI thread will dispatch resize and + paint events to a QGLWidget when the widget is resized, or parts + of it becomes exposed or needs redrawing. It is therefore + necessary to handle those events because the default + implementations inside QGLWidget will try to make the QGLWidget's + context current, which again will interfere with any threads + rendering into the widget. Reimplement QGLWidget::paintEvent() and + QGLWidget::resizeEvent() to notify the rendering thread that a + resize or update is necessary, and be careful not to call the base + class implementation. If you are rendering an animation, it might + not be necessary to handle the paint event at all since the + rendering thread is doing regular updates. Then it would be enough + to reimplement QGLWidget::paintEvent() to do nothing. + + \endlist + + As a general rule when doing threaded rendering: be aware that + binding and releasing contexts in different threads have to be + synchronized by the user. A GL rendering context can only be + current in one thread at any time. If you try to open a QPainter + on a QGLWidget and the widget's rendering context is current in + another thread, it will fail. + + Note that under X11 it is necessary to set the + Qt::AA_X11InitThreads application attribute to make the X11 + library and GLX calls thread safe, otherwise the above scenarios + will fail. + + In addition to this, rendering using raw GL calls in a separate + thread is supported. \e{OpenGL is a trademark of Silicon Graphics, Inc. in the United States and other countries.} @@ -4122,7 +4199,7 @@ void QGLWidget::resizeOverlayGL(int, int) /*! \fn bool QGLWidget::event(QEvent *e) \reimp */ -#if !defined(Q_OS_WINCE) && !defined(Q_WS_QWS) +#if !defined(Q_OS_WINCE) && !defined(Q_WS_QWS) && !defined(Q_WS_QPA) bool QGLWidget::event(QEvent *e) { Q_D(QGLWidget); @@ -4141,13 +4218,7 @@ bool QGLWidget::event(QEvent *e) } #if defined(Q_WS_X11) - // prevents X errors on some systems, where we get a flush to a - // hidden widget - if (e->type() == QEvent::Hide) { - makeCurrent(); - glFinish(); - doneCurrent(); - } else if (e->type() == QEvent::ParentChange) { + if (e->type() == QEvent::ParentChange) { // if we've reparented a window that has the current context // bound, we need to rebind that context to the new window id if (d->glcx == QGLContext::currentContext()) @@ -5149,24 +5220,24 @@ void QGLWidget::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QM #endif #ifndef QT_OPENGL_ES_1 -Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_2_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_gl_2_engine) #endif #ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QOpenGLPaintEngine>, qt_gl_engine) #endif Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine() { #if defined(QT_OPENGL_ES_1) - return qt_gl_engine(); + return qt_gl_engine()->engine(); #elif defined(QT_OPENGL_ES_2) - return qt_gl_2_engine(); + return qt_gl_2_engine()->engine(); #else if (qt_gl_preferGL2Engine()) - return qt_gl_2_engine(); + return qt_gl_2_engine()->engine(); else - return qt_gl_engine(); + return qt_gl_engine()->engine(); #endif } @@ -5374,7 +5445,7 @@ void QGLWidgetPrivate::initContext(QGLContext *context, const QGLWidget* shareWi glcx = new QGLContext(QGLFormat::defaultFormat(), q); } -#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) +#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_WS_QPA) Q_GLOBAL_STATIC(QString, qt_gl_lib_name) Q_OPENGL_EXPORT void qt_set_gl_library_name(const QString& name) @@ -5439,13 +5510,23 @@ void QGLContextGroup::removeShare(const QGLContext *context) { group->m_shares.clear(); } -QGLContextResource::QGLContextResource(FreeFunc f) - : free(f), active(0) +QGLContextGroupResourceBase::QGLContextGroupResourceBase() + : active(0) { +#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG + qDebug("Creating context group resource object %p.", this); +#endif } -QGLContextResource::~QGLContextResource() +QGLContextGroupResourceBase::~QGLContextGroupResourceBase() { +#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG + qDebug("Deleting context group resource %p. Group size: %d.", this, m_groups.size()); +#endif + for (int i = 0; i < m_groups.size(); ++i) { + m_groups.at(i)->m_resources.remove(this); + active.deref(); + } #ifndef QT_NO_DEBUG if (active != 0) { qWarning("QtOpenGL: Resources are still available at program shutdown.\n" @@ -5455,37 +5536,47 @@ QGLContextResource::~QGLContextResource() #endif } -void QGLContextResource::insert(const QGLContext *key, void *value) +void QGLContextGroupResourceBase::insert(const QGLContext *context, void *value) { - QGLContextGroup *group = QGLContextPrivate::contextGroup(key); +#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG + qDebug("Inserting context group resource %p for context %p, managed by %p.", value, context, this); +#endif + QGLContextGroup *group = QGLContextPrivate::contextGroup(context); Q_ASSERT(!group->m_resources.contains(this)); group->m_resources.insert(this, value); + m_groups.append(group); active.ref(); } -void *QGLContextResource::value(const QGLContext *key) +void *QGLContextGroupResourceBase::value(const QGLContext *context) { - QGLContextGroup *group = QGLContextPrivate::contextGroup(key); + QGLContextGroup *group = QGLContextPrivate::contextGroup(context); return group->m_resources.value(this, 0); } -void QGLContextResource::cleanup(const QGLContext *ctx, void *value) +void QGLContextGroupResourceBase::cleanup(const QGLContext *ctx, void *value) { +#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG + qDebug("Cleaning up context group resource %p, for context %p in thread %p.", this, ctx, QThread::currentThread()); +#endif QGLShareContextScope scope(ctx); - free(value); + freeResource(value); active.deref(); + + QGLContextGroup *group = QGLContextPrivate::contextGroup(ctx); + m_groups.removeOne(group); } -void QGLContextGroup::cleanupResources(const QGLContext *ctx) +void QGLContextGroup::cleanupResources(const QGLContext *context) { // If there are still shares, then no cleanup to be done yet. if (m_shares.size() > 1) return; // Iterate over all resources and free each in turn. - QHash<QGLContextResource *, void *>::ConstIterator it; + QHash<QGLContextGroupResourceBase *, void *>::ConstIterator it; for (it = m_resources.begin(); it != m_resources.end(); ++it) - it.key()->cleanup(ctx, it.value()); + it.key()->cleanup(context, it.value()); } QGLSharedResourceGuard::~QGLSharedResourceGuard() diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index f85cad5..2ac4cb6 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -56,7 +56,6 @@ QT_BEGIN_HEADER #if defined(Q_WS_MAC) # include <OpenGL/gl.h> -# include <OpenGL/glu.h> #elif defined(QT_OPENGL_ES_1) # include <GLES/gl.h> #ifndef GL_DOUBLE @@ -75,9 +74,6 @@ typedef GLfloat GLdouble; #endif #else # include <GL/gl.h> -# ifndef QT_LINUXBASE -# include <GL/glu.h> -# endif #endif QT_BEGIN_NAMESPACE @@ -424,6 +420,7 @@ private: friend class QGLPixmapData; friend class QGLPixmapFilterBase; friend class QGLTextureGlyphCache; + friend struct QGLGlyphTexture; friend class QGLContextGroup; friend class QGLSharedResourceGuard; friend class QGLPixmapBlurFilter; @@ -443,6 +440,7 @@ private: friend class QGLWidgetGLPaintDevice; friend class QX11GLPixmapData; friend class QX11GLSharedContexts; + friend class QGLContextResourceBase; private: Q_DISABLE_COPY(QGLContext) }; diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index f86c77f..8c7f15c 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -68,6 +68,10 @@ #include <QtGui/private/qegl_p.h> #endif +#if defined(Q_WS_QPA) +#include <QtGui/QPlatformGLContext> +#endif + QT_BEGIN_NAMESPACE class QGLContext; @@ -161,7 +165,7 @@ class QGLWidgetPrivate : public QWidgetPrivate public: QGLWidgetPrivate() : QWidgetPrivate() , disable_clear_on_painter_begin(false) -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) , wsurf(0) #endif #if defined(Q_WS_X11) && !defined(QT_NO_EGL) @@ -217,11 +221,9 @@ public: #endif }; -class QGLContextResource; +class QGLContextGroupResourceBase; class QGLSharedResourceGuard; -typedef QHash<QString, GLuint> QGLDDSCache; - // QGLContextPrivate has the responsibility of creating context groups. // QGLContextPrivate maintains the reference counter and destroys // context groups when needed. @@ -240,22 +242,22 @@ public: static void addShare(const QGLContext *context, const QGLContext *share); static void removeShare(const QGLContext *context); + private: QGLContextGroup(const QGLContext *context); QGLExtensionFuncs m_extensionFuncs; const QGLContext *m_context; // context group's representative QList<const QGLContext *> m_shares; - QHash<QGLContextResource *, void *> m_resources; + QHash<QGLContextGroupResourceBase *, void *> m_resources; QGLSharedResourceGuard *m_guards; // double-linked list of active guards. QAtomicInt m_refs; - QGLDDSCache m_dds_cache; void cleanupResources(const QGLContext *ctx); friend class QGLContext; friend class QGLContextPrivate; - friend class QGLContextResource; + friend class QGLContextGroupResourceBase; }; // Get the context that resources for "ctx" will transfer to once @@ -322,6 +324,8 @@ class QGLTexture; // all the GL2 engine uses: #define QT_GL_VERTEX_ARRAY_TRACKED_COUNT 3 +class QGLContextResourceBase; + class QGLContextPrivate { Q_DECLARE_PUBLIC(QGLContext) @@ -357,13 +361,17 @@ public: QGLCmap* cmap; HBITMAP hbitmap; HDC hbitmap_hdc; + Qt::HANDLE threadId; #endif #ifndef QT_NO_EGL - uint ownsEglContext : 1; QEglContext *eglContext; EGLSurface eglSurface; void destroyEglSurfaceForDevice(); EGLSurface eglSurfaceForDevice() const; +#endif + +#if defined(Q_WS_QPA) + QPlatformGLContext *platformContext; #elif defined(Q_WS_X11) || defined(Q_WS_MAC) void* cx; #endif @@ -405,6 +413,10 @@ public: uint workaround_brokenTextureFromPixmap : 1; uint workaround_brokenTextureFromPixmap_init : 1; +#ifndef QT_NO_EGL + uint ownsEglContext : 1; +#endif + QPaintDevice *paintDevice; QColor transpColor; QGLContext *q_ptr; @@ -417,6 +429,7 @@ public: GLuint current_fbo; GLuint default_fbo; QPaintEngine *active_engine; + QHash<QGLContextResourceBase *, void *> m_resources; bool vertexAttributeArraysEnabledState[QT_GL_VERTEX_ARRAY_TRACKED_COUNT]; @@ -426,8 +439,8 @@ public: static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *ctx) { return ctx->d_ptr->group->extensionFuncs(); } #endif -#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) - static QGLExtensionFuncs qt_extensionFuncs; +#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) + static Q_OPENGL_EXPORT QGLExtensionFuncs qt_extensionFuncs; static Q_OPENGL_EXPORT QGLExtensionFuncs& extensionFuncs(const QGLContext *); #endif @@ -625,24 +638,130 @@ inline GLenum qt_gl_preferredTextureTarget() #endif } -// One resource per group of shared contexts. -class Q_OPENGL_EXPORT QGLContextResource +/* + Base for resources that are shared in a context group. +*/ +class Q_OPENGL_EXPORT QGLContextGroupResourceBase { public: - typedef void (*FreeFunc)(void *); - QGLContextResource(FreeFunc f); - ~QGLContextResource(); - // Set resource 'value' for 'key' and all its shared contexts. - void insert(const QGLContext *key, void *value); - // Return resource for 'key' or a shared context. - void *value(const QGLContext *key); - // Cleanup 'value' in response to a context group being destroyed. - void cleanup(const QGLContext *ctx, void *value); + QGLContextGroupResourceBase(); + virtual ~QGLContextGroupResourceBase(); + void insert(const QGLContext *context, void *value); + void *value(const QGLContext *context); + void cleanup(const QGLContext *context, void *value); + virtual void freeResource(void *value) = 0; + +protected: + QList<QGLContextGroup *> m_groups; + private: - FreeFunc free; QAtomicInt active; }; +/* + The QGLContextGroupResource template is used to manage a resource + for a group of sharing GL contexts. When the last context in the + group is destroyed, or when the QGLContextGroupResource object + itself is destroyed (implies potential context switches), the + resource will be freed. + + The class used as the template class type needs to have a + constructor with the following signature: + T(const QGLContext *); +*/ +template <class T> +class QGLContextGroupResource : public QGLContextGroupResourceBase +{ +public: + ~QGLContextGroupResource() { + for (int i = 0; i < m_groups.size(); ++i) { + const QGLContext *context = m_groups.at(i)->context(); + T *resource = reinterpret_cast<T *>(QGLContextGroupResourceBase::value(context)); + if (resource) { + QGLShareContextScope scope(context); + delete resource; + } + } + } + + T *value(const QGLContext *context) { + T *resource = reinterpret_cast<T *>(QGLContextGroupResourceBase::value(context)); + if (!resource) { + resource = new T(context); + insert(context, resource); + } + return resource; + } + +protected: + void freeResource(void *resource) { + delete reinterpret_cast<T *>(resource); + } +}; + +/* + Base for resources that are context specific. +*/ +class Q_OPENGL_EXPORT QGLContextResourceBase +{ +public: + virtual ~QGLContextResourceBase() { + for (int i = 0; i < m_contexts.size(); ++i) + m_contexts.at(i)->d_ptr->m_resources.remove(this); + } + + void insert(const QGLContext *context, void *value) { + context->d_ptr->m_resources.insert(this, value); + } + + void *value(const QGLContext *context) { + return context->d_ptr->m_resources.value(this, 0); + } + virtual void freeResource(void *value) = 0; + +protected: + QList<const QGLContext *> m_contexts; +}; + +/* + The QGLContextResource template is used to manage a resource for a + single GL context. Just before the context is destroyed (while it's + still the current context), or when the QGLContextResource object + itself is destroyed (implies potential context switches), the + resource will be freed. The class used as the template class type + needs to have a constructor with the following signature: T(const + QGLContext *); +*/ +template <class T> +class QGLContextResource : public QGLContextResourceBase +{ +public: + ~QGLContextResource() { + for (int i = 0; i < m_contexts.size(); ++i) { + const QGLContext *context = m_contexts.at(i); + T *resource = reinterpret_cast<T *>(QGLContextResourceBase::value(context)); + if (resource) { + QGLShareContextScope scope(context); + delete resource; + } + } + } + + T *value(const QGLContext *context) { + T *resource = reinterpret_cast<T *>(QGLContextResourceBase::value(context)); + if (!resource) { + resource = new T(context); + insert(context, resource); + } + return resource; + } + +protected: + void freeResource(void *resource) { + delete reinterpret_cast<T *>(resource); + } +}; + // Put a guard around a GL object identifier and its context. // When the context goes away, a shared context will be used // in its place. If there are no more shared contexts, then @@ -732,6 +851,24 @@ private: int gl_extensions_length; }; + +// this is a class that wraps a QThreadStorage object for storing +// thread local instances of the GL 1 and GL 2 paint engines + +template <class T> +class QGLEngineThreadStorage +{ +public: + QPaintEngine *engine() { + QPaintEngine *&localEngine = storage.localData(); + if (!localEngine) + localEngine = new T; + return localEngine; + } + +private: + QThreadStorage<QPaintEngine *> storage; +}; QT_END_NAMESPACE #endif // QGL_P_H diff --git a/src/opengl/qgl_qpa.cpp b/src/opengl/qgl_qpa.cpp new file mode 100644 index 0000000..49c0860 --- /dev/null +++ b/src/opengl/qgl_qpa.cpp @@ -0,0 +1,345 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include <QApplication> +#include <QtGui/private/qapplication_p.h> +#include <QPixmap> +#include <QDebug> + +#include <QtGui/private/qapplication_p.h> +#include <QtGui/QPlatformWindow> + +#include "qgl.h" +#include "qgl_p.h" + +QT_BEGIN_NAMESPACE + +static QGLFormat qt_platformwindowformat_to_glformat(const QPlatformWindowFormat &format) +{ + QGLFormat retFormat; + retFormat.setAccum(format.accum()); + if (format.accumBufferSize() >= 0) + retFormat.setAccumBufferSize(format.accumBufferSize()); + retFormat.setAlpha(format.alpha()); + if (format.alphaBufferSize() >= 0) + retFormat.setAlphaBufferSize(format.alphaBufferSize()); + if (format.blueBufferSize() >= 0) + retFormat.setBlueBufferSize(format.blueBufferSize()); + retFormat.setDepth(format.depth()); + if (format.depthBufferSize() >= 0) + retFormat.setDepthBufferSize(format.depthBufferSize()); + retFormat.setDirectRendering(format.directRendering()); + retFormat.setDoubleBuffer(format.doubleBuffer()); + if (format.greenBufferSize() >= 0) + retFormat.setGreenBufferSize(format.greenBufferSize()); + if (format.redBufferSize() >= 0) + retFormat.setRedBufferSize(format.redBufferSize()); + retFormat.setRgba(format.rgba()); + retFormat.setSampleBuffers(format.sampleBuffers()); + retFormat.setSamples(format.sampleBuffers()); + retFormat.setStencil(format.stencil()); + if (format.stencilBufferSize() >= 0) + retFormat.setStencilBufferSize(format.stencilBufferSize()); + retFormat.setStereo(format.stereo()); + retFormat.setSwapInterval(format.swapInterval()); + return retFormat; +} + +static QPlatformWindowFormat qt_glformat_to_platformwindowformat(const QGLFormat &format) +{ + QPlatformWindowFormat retFormat; + retFormat.setAccum(format.accum()); + if (format.accumBufferSize() >= 0) + retFormat.setAccumBufferSize(format.accumBufferSize()); + retFormat.setAlpha(format.alpha()); + if (format.alphaBufferSize() >= 0) + retFormat.setAlphaBufferSize(format.alphaBufferSize()); + if (format.blueBufferSize() >= 0) + retFormat.setBlueBufferSize(format.blueBufferSize()); + retFormat.setDepth(format.depth()); + if (format.depthBufferSize() >= 0) + retFormat.setDepthBufferSize(format.depthBufferSize()); + retFormat.setDirectRendering(format.directRendering()); + retFormat.setDoubleBuffer(format.doubleBuffer()); + if (format.greenBufferSize() >= 0) + retFormat.setGreenBufferSize(format.greenBufferSize()); + if (format.redBufferSize() >= 0) + retFormat.setRedBufferSize(format.redBufferSize()); + retFormat.setRgba(format.rgba()); + retFormat.setSampleBuffers(format.sampleBuffers()); + if (format.samples() >= 0) + retFormat.setSamples(format.samples()); + retFormat.setStencil(format.stencil()); + if (format.stencilBufferSize() >= 0) + retFormat.setStencilBufferSize(format.stencilBufferSize()); + retFormat.setStereo(format.stereo()); + retFormat.setSwapInterval(format.swapInterval()); + return retFormat; +} + +bool QGLFormat::hasOpenGL() +{ + return QApplicationPrivate::platformIntegration()->hasOpenGL(); +} + +bool QGLContext::chooseContext(const QGLContext* shareContext) +{ + Q_D(QGLContext); + if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) { + d->valid = false; + }else { + QWidget *widget = static_cast<QWidget *>(d->paintDevice); + if (!widget->platformWindow()){ + QGLFormat glformat = format(); + QPlatformWindowFormat winFormat = qt_glformat_to_platformwindowformat(glformat); + if (shareContext) { + winFormat.setSharedContext(shareContext->d_func()->platformContext); + } + winFormat.setWindowApi(QPlatformWindowFormat::OpenGL); + widget->setPlatformWindowFormat(winFormat); + widget->winId();//make window + } + d->platformContext = widget->platformWindow()->glContext(); + Q_ASSERT(d->platformContext); + d->glFormat = qt_platformwindowformat_to_glformat(d->platformContext->platformWindowFormat()); + d->valid =(bool) d->platformContext; + } + + return d->valid; +} + +void QGLContext::reset() +{ + Q_D(QGLContext); + if (!d->valid) + return; + d->cleanup(); + + d->crWin = false; + d->sharing = false; + d->valid = false; + d->transpColor = QColor(); + d->initDone = false; + QGLContextGroup::removeShare(this); +} + +void QGLContext::makeCurrent() +{ + Q_D(QGLContext); + d->platformContext->makeCurrent(); + QGLContextPrivate::setCurrentContext(this); +} + +void QGLContext::doneCurrent() +{ + Q_D(QGLContext); + d->platformContext->doneCurrent(); + QGLContextPrivate::setCurrentContext(0); +} + +void QGLContext::swapBuffers() const +{ + Q_D(const QGLContext); + d->platformContext->swapBuffers(); +} + +void *QGLContext::getProcAddress(const QString &procName) const +{ + Q_D(const QGLContext); + return d->platformContext->getProcAddress(procName); +} + +void QGLWidget::setContext(QGLContext *context, + const QGLContext* shareContext, + bool deleteOldContext) +{ + Q_D(QGLWidget); + if (context == 0) { + qWarning("QGLWidget::setContext: Cannot set null context"); + return; + } + if (!context->deviceIsPixmap() && context->device() != this) { + qWarning("QGLWidget::setContext: Context must refer to this widget"); + return; + } + + QGLContext* oldcx = d->glcx; + d->glcx = context; + + if (!d->glcx->isValid()) + d->glcx->create(shareContext ? shareContext : oldcx); + + if (deleteOldContext) + delete oldcx; +} + +void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget) +{ + initContext(context, shareWidget); +} + +bool QGLFormat::hasOpenGLOverlays() +{ + return false; +} + +QColor QGLContext::overlayTransparentColor() const +{ + return QColor(); // Invalid color +} + +uint QGLContext::colorIndex(const QColor&) const +{ + return 0; +} + +void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase) +{ + Q_UNUSED(fnt); + Q_UNUSED(listBase); +} + +/* + QGLTemporaryContext implementation +*/ +class QGLTemporaryContextPrivate +{ +public: + QWidget *widget; + QGLContext *context; +}; + +QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) + : d(new QGLTemporaryContextPrivate) +{ + d->context = const_cast<QGLContext *>(QGLContext::currentContext()); + if (d->context) + d->context->doneCurrent(); + d->widget = new QWidget; + d->widget->setGeometry(0,0,3,3); + QPlatformWindowFormat format = d->widget->platformWindowFormat(); + format.setWindowApi(QPlatformWindowFormat::OpenGL); + d->widget->winId(); + + + d->widget->platformWindow()->glContext()->makeCurrent(); +} + +QGLTemporaryContext::~QGLTemporaryContext() +{ + d->widget->platformWindow()->glContext()->doneCurrent(); + if (d->context) + d->context->makeCurrent(); + delete d->widget; +} + + +bool QGLWidgetPrivate::renderCxPm(QPixmap*) +{ + return false; +} + +/*! \internal + Free up any allocated colormaps. This fn is only called for + top-level widgets. +*/ +void QGLWidgetPrivate::cleanupColormaps() +{ +} + +void QGLWidget::setMouseTracking(bool enable) +{ + Q_UNUSED(enable); +} + +bool QGLWidget::event(QEvent *e) +{ + Q_D(QGLWidget); + if (e->type() == QEvent::WinIdChange) { + if (d->glcx->isValid()) { + if (QGLContext::currentContext() == d->glcx) + QGLContextPrivate::setCurrentContext(0); //Its not valid anymore + setContext(new QGLContext(d->glcx->requestedFormat(), this)); + + } + } + return QWidget::event(e); +} + +void QGLWidget::resizeEvent(QResizeEvent *e) +{ + Q_D(QGLWidget); + if (!isValid()) + return; + makeCurrent(); + if (!d->glcx->initialized()) + glInit(); + resizeGL(width(), height()); + return QWidget::resizeEvent(e); +} + + +const QGLContext* QGLWidget::overlayContext() const +{ + return 0; +} + +void QGLWidget::makeOverlayCurrent() +{ +} + + +void QGLWidget::updateOverlayGL() +{ +} + +const QGLColormap & QGLWidget::colormap() const +{ + Q_D(const QGLWidget); + return d->cmap; +} + +void QGLWidget::setColormap(const QGLColormap & c) +{ + Q_UNUSED(c); +} + +QT_END_NAMESPACE diff --git a/src/opengl/qgl_win.cpp b/src/opengl/qgl_win.cpp index 8eb6177..5f7d4e2 100644 --- a/src/opengl/qgl_win.cpp +++ b/src/opengl/qgl_win.cpp @@ -1261,6 +1261,7 @@ void QGLContext::reset() } d->dc = 0; d->win = 0; + d->threadId = 0; d->pixelFormatId = 0; d->sharing = false; d->valid = false; @@ -1283,8 +1284,9 @@ void QGLContext::makeCurrent() if (d->rc == wglGetCurrentContext() || !d->valid) // already current return; - if (d->win) { + if (d->win && (!d->dc || d->threadId != QThread::currentThreadId())) { d->dc = GetDC(d->win); + d->threadId = QThread::currentThreadId(); if (!d->dc) { qwglError("QGLContext::makeCurrent()", "GetDC()"); return; @@ -1322,6 +1324,7 @@ void QGLContext::doneCurrent() if (d->win && d->dc) { ReleaseDC(d->win, d->dc); d->dc = 0; + d->threadId = 0; } } diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp index 9d28de0..1f7e60a 100644 --- a/src/opengl/qgl_x11egl.cpp +++ b/src/opengl/qgl_x11egl.cpp @@ -97,7 +97,6 @@ QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) XVisualInfo visualInfo; XVisualInfo *vi; int numVisuals; - EGLint id = 0; visualInfo.visualid = QEgl::getCompatibleVisualId(config); vi = XGetVisualInfo(X11->display, VisualIDMask, &visualInfo, &numVisuals); @@ -346,7 +345,7 @@ void QGLWidgetPrivate::recreateEglSurface() // old surface before re-creating a new one. Note: This should not be the case as the // surface should be deleted before the old window id. if (glcx->d_func()->eglSurface != EGL_NO_SURFACE && (currentId != eglSurfaceWindowId)) { - qWarning("EGL surface for deleted window %x was not destroyed", eglSurfaceWindowId); + qWarning("EGL surface for deleted window %lx was not destroyed", eglSurfaceWindowId); glcx->d_func()->destroyEglSurfaceForDevice(); } diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h index a35ad87..ffbc472 100644 --- a/src/opengl/qglextensions_p.h +++ b/src/opengl/qglextensions_p.h @@ -879,10 +879,10 @@ struct QGLExtensionFuncs #endif extern bool qt_resolve_framebufferobject_extensions(QGLContext *ctx); -bool qt_resolve_buffer_extensions(QGLContext *ctx); +bool Q_OPENGL_EXPORT qt_resolve_buffer_extensions(QGLContext *ctx); bool qt_resolve_version_1_3_functions(QGLContext *ctx); -bool qt_resolve_version_2_0_functions(QGLContext *ctx); +bool Q_OPENGL_EXPORT qt_resolve_version_2_0_functions(QGLContext *ctx); bool qt_resolve_stencil_face_extension(QGLContext *ctx); bool qt_resolve_frag_program_extensions(QGLContext *ctx); diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index 3ccefbf..8915b5e 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -324,6 +324,10 @@ void QGLFBOGLPaintDevice::setFBO(QGLFramebufferObject* f, fboFormat.setStencil(true); } else if (attachment == QGLFramebufferObject::Depth) { fboFormat.setDepth(true); + fboFormat.setStencil(false); + } else { + fboFormat.setDepth(false); + fboFormat.setStencil(false); } GLenum format = f->format().internalTextureFormat(); @@ -674,6 +678,13 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, as a texture, you first need to copy from it to a regular framebuffer object using QGLContext::blitFramebuffer(). + \section Threading + + As of Qt 4.8, it's possible to draw into a QGLFramebufferObject + using a QPainter in a separate thread. Note that OpenGL 2.0 or + OpenGL ES 2.0 is required for this to work. Also, under X11, it's + necessary to set the Qt::AA_X11InitThreads application attribute. + \sa {Framebuffer Object Example} */ @@ -1044,11 +1055,11 @@ QImage QGLFramebufferObject::toImage() const } #if !defined(QT_OPENGL_ES_1) -Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_buffer_2_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_buffer_2_engine) #endif #ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QOpenGLPaintEngine>, qt_buffer_engine) #endif /*! \reimp */ @@ -1062,7 +1073,7 @@ QPaintEngine *QGLFramebufferObject::paintEngine() const #if !defined (QT_OPENGL_ES_2) if (qt_gl_preferGL2Engine()) { #endif - QPaintEngine *engine = qt_buffer_2_engine(); + QPaintEngine *engine = qt_buffer_2_engine()->engine(); if (engine->isActive() && engine->paintDevice() != this) { d->engine = new QGL2PaintEngineEx; return d->engine; @@ -1074,7 +1085,7 @@ QPaintEngine *QGLFramebufferObject::paintEngine() const #endif #if !defined(QT_OPENGL_ES_2) - QPaintEngine *engine = qt_buffer_engine(); + QPaintEngine *engine = qt_buffer_engine()->engine(); if (engine->isActive() && engine->paintDevice() != this) { d->engine = new QOpenGLPaintEngine; return d->engine; diff --git a/src/opengl/qglfunctions.cpp b/src/opengl/qglfunctions.cpp new file mode 100644 index 0000000..8a544c1 --- /dev/null +++ b/src/opengl/qglfunctions.cpp @@ -0,0 +1,3705 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qglfunctions.h" +#include "qgl_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QGLFunctions + \brief The QGLFunctions class provides cross-platform access to the OpenGL/ES 2.0 API. + \since 4.8 + \ingroup painting-3D + + OpenGL/ES 2.0 defines a subset of the OpenGL specification that is + common across many desktop and embedded OpenGL implementations. + However, it can be difficult to use the functions from that subset + because they need to be resolved manually on desktop systems. + + QGLFunctions provides a guaranteed API that is available on all + OpenGL systems and takes care of function resolution on systems + that need it. The recommended way to use QGLFunctions is by + direct inheritance: + + \code + class MyGLWidget : public QGLWidget, protected QGLFunctions + { + Q_OBJECT + public: + MyGLWidget(QWidget *parent = 0) : QGLWidget(parent) {} + + protected: + void initializeGL(); + void paintGL(); + }; + + void MyGLWidget::initializeGL() + { + initializeGLFunctions(); + } + \endcode + + The \c{paintGL()} function can then use any of the OpenGL/ES 2.0 + functions without explicit resolution, such as glActiveTexture() + in the following example: + + \code + void MyGLWidget::paintGL() + { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, textureId); + ... + } + \endcode + + QGLFunctions can also be used directly for ad-hoc invocation + of OpenGL/ES 2.0 functions on all platforms: + + \code + QGLFunctions glFuncs(QGLContext::currentContext()); + glFuncs.glActiveTexture(GL_TEXTURE1); + \endcode + + QGLFunctions provides wrappers for all OpenGL/ES 2.0 functions, + except those like \c{glDrawArrays()}, \c{glViewport()}, and + \c{glBindTexture()} that don't have portability issues. + + Including the header for QGLFunctions will also define all of + the OpenGL/ES 2.0 macro constants that are not already defined by + the system's OpenGL headers, such as \c{GL_TEXTURE1} above. + + The hasOpenGLFeature() and openGLFeatures() functions can be used + to determine if the OpenGL implementation has a major OpenGL/ES 2.0 + feature. For example, the following checks if non power of two + textures are available: + + \code + QGLFunctions funcs(QGLContext::currentContext()); + bool npot = funcs.hasOpenGLFeature(QGLFunctions::NPOTTextures); + \endcode +*/ + +/*! + \enum QGLFunctions::OpenGLFeature + This enum defines OpenGL/ES 2.0 features that may be optional + on other platforms. + + \value Multitexture glActiveTexture() function is available. + \value Shaders Shader functions are available. + \value Buffers Vertex and index buffer functions are available. + \value Framebuffers Framebuffer object functions are available. + \value BlendColor glBlendColor() is available. + \value BlendEquation glBlendEquation() is available. + \value BlendEquationSeparate glBlendEquationSeparate() is available. + \value BlendFuncSeparate glBlendFuncSeparate() is available. + \value BlendSubtract Blend subtract mode is available. + \value CompressedTextures Compressed texture functions are available. + \value Multisample glSampleCoverage() function is available. + \value StencilSeparate Separate stencil functions are available. + \value NPOTTextures Non power of two textures are available. +*/ + +// Hidden private fields for additional extension data. +struct QGLFunctionsPrivateEx : public QGLFunctionsPrivate +{ + QGLFunctionsPrivateEx(const QGLContext *context = 0) + : QGLFunctionsPrivate(context) + , m_features(-1) {} + + int m_features; +}; + +#if QT_VERSION >= 0x040800 +Q_GLOBAL_STATIC(QGLContextGroupResource<QGLFunctionsPrivateEx>, qt_gl_functions_resource) +#else +static void qt_gl_functions_free(void *data) +{ + delete reinterpret_cast<QGLFunctionsPrivateEx *>(data); +} + +Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_gl_functions_resource, (qt_gl_functions_free)) +#endif +static QGLFunctionsPrivateEx *qt_gl_functions(const QGLContext *context = 0) +{ + if (!context) + context = QGLContext::currentContext(); + Q_ASSERT(context); + QGLFunctionsPrivateEx *funcs = + reinterpret_cast<QGLFunctionsPrivateEx *> + (qt_gl_functions_resource()->value(context)); +#if QT_VERSION < 0x040800 + if (!funcs) { + funcs = new QGLFunctionsPrivateEx(); + qt_gl_functions_resource()->insert(context, funcs); + } +#endif + return funcs; +} + +/*! + Constructs a default function resolver. The resolver cannot + be used until initializeGLFunctions() is called to specify + the context. + + \sa initializeGLFunctions() +*/ +QGLFunctions::QGLFunctions() + : d_ptr(0) +{ +} + +/*! + Constructs a function resolver for \a context. If \a context + is null, then the resolver will be created for the current QGLContext. + + An object constructed in this way can only be used with \a context + and other contexts that share with it. Use initializeGLFunctions() + to change the object's context association. + + \sa initializeGLFunctions() +*/ +QGLFunctions::QGLFunctions(const QGLContext *context) + : d_ptr(qt_gl_functions(context)) +{ +} + +/*! + \fn QGLFunctions::~QGLFunctions() + + Destroys this function resolver. +*/ + +static int qt_gl_resolve_features() +{ +#if defined(QT_OPENGL_ES_2) + return QGLFunctions::Multitexture | + QGLFunctions::Shaders | + QGLFunctions::Buffers | + QGLFunctions::Framebuffers | + QGLFunctions::BlendColor | + QGLFunctions::BlendEquation | + QGLFunctions::BlendEquationSeparate | + QGLFunctions::BlendFuncSeparate | + QGLFunctions::BlendSubtract | + QGLFunctions::CompressedTextures | + QGLFunctions::Multisample | + QGLFunctions::StencilSeparate | + QGLFunctions::NPOTTextures; +#elif defined(QT_OPENGL_ES) + int features = QGLFunctions::Multitexture | + QGLFunctions::Buffers | + QGLFunctions::CompressedTextures | + QGLFunctions::Multisample; + QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))); + if (extensions.match("GL_OES_framebuffer_object")) + features |= QGLFunctions::Framebuffers; + if (extensions.match("GL_OES_blend_equation_separate")) + features |= QGLFunctions::BlendEquationSeparate; + if (extensions.match("GL_OES_blend_func_separate")) + features |= QGLFunctions::BlendFuncSeparate; + if (extensions.match("GL_OES_blend_subtract")) + features |= QGLFunctions::BlendSubtract; + if (extensions.match("GL_OES_texture_npot")) + features |= QGLFunctions::NPOTTextures; + return features; +#else + int features = 0; + QGLFormat::OpenGLVersionFlags versions = QGLFormat::openGLVersionFlags(); + QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))); + + // Recognize features by extension name. + if (extensions.match("GL_ARB_multitexture")) + features |= QGLFunctions::Multitexture; + if (extensions.match("GL_ARB_shader_objects")) + features |= QGLFunctions::Shaders; + if (extensions.match("GL_EXT_framebuffer_object") || + extensions.match("GL_ARB_framebuffer_object")) + features |= QGLFunctions::Framebuffers; + if (extensions.match("GL_EXT_blend_color")) + features |= QGLFunctions::BlendColor; + if (extensions.match("GL_EXT_blend_equation_separate")) + features |= QGLFunctions::BlendEquationSeparate; + if (extensions.match("GL_EXT_blend_func_separate")) + features |= QGLFunctions::BlendFuncSeparate; + if (extensions.match("GL_EXT_blend_subtract")) + features |= QGLFunctions::BlendSubtract; + if (extensions.match("GL_ARB_texture_compression")) + features |= QGLFunctions::CompressedTextures; + if (extensions.match("GL_ARB_multisample")) + features |= QGLFunctions::Multisample; + if (extensions.match("GL_ARB_texture_non_power_of_two")) + features |= QGLFunctions::NPOTTextures; + + // Recognize features by minimum OpenGL version. + if (versions & QGLFormat::OpenGL_Version_1_2) { + features |= QGLFunctions::BlendColor | + QGLFunctions::BlendEquation; + } + if (versions & QGLFormat::OpenGL_Version_1_3) { + features |= QGLFunctions::Multitexture | + QGLFunctions::CompressedTextures | + QGLFunctions::Multisample; + } + if (versions & QGLFormat::OpenGL_Version_1_4) + features |= QGLFunctions::BlendFuncSeparate; + if (versions & QGLFormat::OpenGL_Version_1_5) + features |= QGLFunctions::Buffers; + if (versions & QGLFormat::OpenGL_Version_2_0) { + features |= QGLFunctions::Shaders | + QGLFunctions::StencilSeparate | + QGLFunctions::BlendEquationSeparate | + QGLFunctions::NPOTTextures; + } + return features; +#endif +} + +/*! + Returns the set of features that are present on this system's + OpenGL implementation. + + It is assumed that the QGLContext associated with this function + resolver is current. + + \sa hasOpenGLFeature() +*/ +QGLFunctions::OpenGLFeatures QGLFunctions::openGLFeatures() const +{ + QGLFunctionsPrivateEx *d = static_cast<QGLFunctionsPrivateEx *>(d_ptr); + if (!d) + return 0; + if (d->m_features == -1) + d->m_features = qt_gl_resolve_features(); + return QGLFunctions::OpenGLFeatures(d->m_features); +} + +/*! + Returns true if \a feature is present on this system's OpenGL + implementation; false otherwise. + + It is assumed that the QGLContext associated with this function + resolver is current. + + \sa openGLFeatures() +*/ +bool QGLFunctions::hasOpenGLFeature(QGLFunctions::OpenGLFeature feature) const +{ + QGLFunctionsPrivateEx *d = static_cast<QGLFunctionsPrivateEx *>(d_ptr); + if (!d) + return false; + if (d->m_features == -1) + d->m_features = qt_gl_resolve_features(); + return (d->m_features & int(feature)) != 0; +} + +/*! + Initializes GL function resolution for \a context. If \a context + is null, then the current QGLContext will be used. + + After calling this function, the QGLFunctions object can only be + used with \a context and other contexts that share with it. + Call initializeGLFunctions() again to change the object's context + association. +*/ +void QGLFunctions::initializeGLFunctions(const QGLContext *context) +{ + d_ptr = qt_gl_functions(context); +} + +/*! + \fn void QGLFunctions::glActiveTexture(GLenum texture) + + Convenience function that calls glActiveTexture(\a texture). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glActiveTexture.xml}{glActiveTexture()}. +*/ + +/*! + \fn void QGLFunctions::glAttachShader(GLuint program, GLuint shader) + + Convenience function that calls glAttachShader(\a program, \a shader). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glAttachShader.xml}{glAttachShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glBindAttribLocation(GLuint program, GLuint index, const char* name) + + Convenience function that calls glBindAttribLocation(\a program, \a index, \a name). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBindAttribLocation.xml}{glBindAttribLocation()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glBindBuffer(GLenum target, GLuint buffer) + + Convenience function that calls glBindBuffer(\a target, \a buffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBindBuffer.xml}{glBindBuffer()}. +*/ + +/*! + \fn void QGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer) + + Convenience function that calls glBindFramebuffer(\a target, \a framebuffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBindFramebuffer.xml}{glBindFramebuffer()}. +*/ + +/*! + \fn void QGLFunctions::glBindRenderbuffer(GLenum target, GLuint renderbuffer) + + Convenience function that calls glBindRenderbuffer(\a target, \a renderbuffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBindRenderbuffer.xml}{glBindRenderbuffer()}. +*/ + +/*! + \fn void QGLFunctions::glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) + + Convenience function that calls glBlendColor(\a red, \a green, \a blue, \a alpha). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendColor.xml}{glBlendColor()}. +*/ + +/*! + \fn void QGLFunctions::glBlendEquation(GLenum mode) + + Convenience function that calls glBlendEquation(\a mode). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendEquation.xml}{glBlendEquation()}. +*/ + +/*! + \fn void QGLFunctions::glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) + + Convenience function that calls glBlendEquationSeparate(\a modeRGB, \a modeAlpha). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendEquationSeparate.xml}{glBlendEquationSeparate()}. +*/ + +/*! + \fn void QGLFunctions::glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) + + Convenience function that calls glBlendFuncSeparate(\a srcRGB, \a dstRGB, \a srcAlpha, \a dstAlpha). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendFuncSeparate.xml}{glBlendFuncSeparate()}. +*/ + +/*! + \fn void QGLFunctions::glBufferData(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage) + + Convenience function that calls glBufferData(\a target, \a size, \a data, \a usage). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBufferData.xml}{glBufferData()}. +*/ + +/*! + \fn void QGLFunctions::glBufferSubData(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data) + + Convenience function that calls glBufferSubData(\a target, \a offset, \a size, \a data). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glBufferSubData.xml}{glBufferSubData()}. +*/ + +/*! + \fn GLenum QGLFunctions::glCheckFramebufferStatus(GLenum target) + + Convenience function that calls glCheckFramebufferStatus(\a target). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCheckFramebufferStatus.xml}{glCheckFramebufferStatus()}. +*/ + +/*! + \fn void QGLFunctions::glClearDepthf(GLclampf depth) + + Convenience function that calls glClearDepth(\a depth) on + desktop OpenGL systems and glClearDepthf(\a depth) on + embedded OpenGL/ES systems. + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glClearDepthf.xml}{glClearDepthf()}. +*/ + +/*! + \fn void QGLFunctions::glCompileShader(GLuint shader) + + Convenience function that calls glCompileShader(\a shader). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCompileShader.xml}{glCompileShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) + + Convenience function that calls glCompressedTexImage2D(\a target, \a level, \a internalformat, \a width, \a height, \a border, \a imageSize, \a data). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCompressedTexImage2D.xml}{glCompressedTexImage2D()}. +*/ + +/*! + \fn void QGLFunctions::glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) + + Convenience function that calls glCompressedTexSubImage2D(\a target, \a level, \a xoffset, \a yoffset, \a width, \a height, \a format, \a imageSize, \a data). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCompressedTexSubImage2D.xml}{glCompressedTexSubImage2D()}. +*/ + +/*! + \fn GLuint QGLFunctions::glCreateProgram() + + Convenience function that calls glCreateProgram(). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCreateProgram.xml}{glCreateProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn GLuint QGLFunctions::glCreateShader(GLenum type) + + Convenience function that calls glCreateShader(\a type). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glCreateShader.xml}{glCreateShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glDeleteBuffers(GLsizei n, const GLuint* buffers) + + Convenience function that calls glDeleteBuffers(\a n, \a buffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteBuffers.xml}{glDeleteBuffers()}. +*/ + +/*! + \fn void QGLFunctions::glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) + + Convenience function that calls glDeleteFramebuffers(\a n, \a framebuffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteFramebuffers.xml}{glDeleteFramebuffers()}. +*/ + +/*! + \fn void QGLFunctions::glDeleteProgram(GLuint program) + + Convenience function that calls glDeleteProgram(\a program). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteProgram.xml}{glDeleteProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) + + Convenience function that calls glDeleteRenderbuffers(\a n, \a renderbuffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteRenderbuffers.xml}{glDeleteRenderbuffers()}. +*/ + +/*! + \fn void QGLFunctions::glDeleteShader(GLuint shader) + + Convenience function that calls glDeleteShader(\a shader). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteShader.xml}{glDeleteShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glDepthRangef(GLclampf zNear, GLclampf zFar) + + Convenience function that calls glDepthRange(\a zNear, \a zFar) on + desktop OpenGL systems and glDepthRangef(\a zNear, \a zFar) on + embedded OpenGL/ES systems. + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDepthRangef.xml}{glDepthRangef()}. +*/ + +/*! + \fn void QGLFunctions::glDetachShader(GLuint program, GLuint shader) + + Convenience function that calls glDetachShader(\a program, \a shader). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDetachShader.xml}{glDetachShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glDisableVertexAttribArray(GLuint index) + + Convenience function that calls glDisableVertexAttribArray(\a index). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glDisableVertexAttribArray.xml}{glDisableVertexAttribArray()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glEnableVertexAttribArray(GLuint index) + + Convenience function that calls glEnableVertexAttribArray(\a index). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glEnableVertexAttribArray.xml}{glEnableVertexAttribArray()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) + + Convenience function that calls glFramebufferRenderbuffer(\a target, \a attachment, \a renderbuffertarget, \a renderbuffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glFramebufferRenderbuffer.xml}{glFramebufferRenderbuffer()}. +*/ + +/*! + \fn void QGLFunctions::glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) + + Convenience function that calls glFramebufferTexture2D(\a target, \a attachment, \a textarget, \a texture, \a level). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glFramebufferTexture2D.xml}{glFramebufferTexture2D()}. +*/ + +/*! + \fn void QGLFunctions::glGenBuffers(GLsizei n, GLuint* buffers) + + Convenience function that calls glGenBuffers(\a n, \a buffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGenBuffers.xml}{glGenBuffers()}. +*/ + +/*! + \fn void QGLFunctions::glGenerateMipmap(GLenum target) + + Convenience function that calls glGenerateMipmap(\a target). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGenerateMipmap.xml}{glGenerateMipmap()}. +*/ + +/*! + \fn void QGLFunctions::glGenFramebuffers(GLsizei n, GLuint* framebuffers) + + Convenience function that calls glGenFramebuffers(\a n, \a framebuffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGenFramebuffers.xml}{glGenFramebuffers()}. +*/ + +/*! + \fn void QGLFunctions::glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) + + Convenience function that calls glGenRenderbuffers(\a n, \a renderbuffers). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGenRenderbuffers.xml}{glGenRenderbuffers()}. +*/ + +/*! + \fn void QGLFunctions::glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) + + Convenience function that calls glGetActiveAttrib(\a program, \a index, \a bufsize, \a length, \a size, \a type, \a name). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetActiveAttrib.xml}{glGetActiveAttrib()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) + + Convenience function that calls glGetActiveUniform(\a program, \a index, \a bufsize, \a length, \a size, \a type, \a name). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetActiveUniform.xml}{glGetActiveUniform()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) + + Convenience function that calls glGetAttachedShaders(\a program, \a maxcount, \a count, \a shaders). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetAttachedShaders.xml}{glGetAttachedShaders()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn int QGLFunctions::glGetAttribLocation(GLuint program, const char* name) + + Convenience function that calls glGetAttribLocation(\a program, \a name). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetAttribLocation.xml}{glGetAttribLocation()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) + + Convenience function that calls glGetBufferParameteriv(\a target, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetBufferParameteriv.xml}{glGetBufferParameteriv()}. +*/ + +/*! + \fn void QGLFunctions::glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) + + Convenience function that calls glGetFramebufferAttachmentParameteriv(\a target, \a attachment, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetFramebufferAttachmentParameteriv.xml}{glGetFramebufferAttachmentParameteriv()}. +*/ + +/*! + \fn void QGLFunctions::glGetProgramiv(GLuint program, GLenum pname, GLint* params) + + Convenience function that calls glGetProgramiv(\a program, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetProgramiv.xml}{glGetProgramiv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) + + Convenience function that calls glGetProgramInfoLog(\a program, \a bufsize, \a length, \a infolog). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetProgramInfoLog.xml}{glGetProgramInfoLog()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) + + Convenience function that calls glGetRenderbufferParameteriv(\a target, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetRenderbufferParameteriv.xml}{glGetRenderbufferParameteriv()}. +*/ + +/*! + \fn void QGLFunctions::glGetShaderiv(GLuint shader, GLenum pname, GLint* params) + + Convenience function that calls glGetShaderiv(\a shader, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderiv.xml}{glGetShaderiv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) + + Convenience function that calls glGetShaderInfoLog(\a shader, \a bufsize, \a length, \a infolog). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderInfoLog.xml}{glGetShaderInfoLog()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) + + Convenience function that calls glGetShaderPrecisionFormat(\a shadertype, \a precisiontype, \a range, \a precision). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderPrecisionFormat.xml}{glGetShaderPrecisionFormat()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source) + + Convenience function that calls glGetShaderSource(\a shader, \a bufsize, \a length, \a source). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderSource.xml}{glGetShaderSource()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetUniformfv(GLuint program, GLint location, GLfloat* params) + + Convenience function that calls glGetUniformfv(\a program, \a location, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformfv.xml}{glGetUniformfv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetUniformiv(GLuint program, GLint location, GLint* params) + + Convenience function that calls glGetUniformiv(\a program, \a location, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformiv.xml}{glGetUniformiv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn int QGLFunctions::glGetUniformLocation(GLuint program, const char* name) + + Convenience function that calls glGetUniformLocation(\a program, \a name). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformLocation.xml}{glGetUniformLocation()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) + + Convenience function that calls glGetVertexAttribfv(\a index, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribfv.xml}{glGetVertexAttribfv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) + + Convenience function that calls glGetVertexAttribiv(\a index, \a pname, \a params). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribiv.xml}{glGetVertexAttribiv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer) + + Convenience function that calls glGetVertexAttribPointerv(\a index, \a pname, \a pointer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribPointerv.xml}{glGetVertexAttribPointerv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn GLboolean QGLFunctions::glIsBuffer(GLuint buffer) + + Convenience function that calls glIsBuffer(\a buffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glIsBuffer.xml}{glIsBuffer()}. +*/ + +/*! + \fn GLboolean QGLFunctions::glIsFramebuffer(GLuint framebuffer) + + Convenience function that calls glIsFramebuffer(\a framebuffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glIsFramebuffer.xml}{glIsFramebuffer()}. +*/ + +/*! + \fn GLboolean QGLFunctions::glIsProgram(GLuint program) + + Convenience function that calls glIsProgram(\a program). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glIsProgram.xml}{glIsProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn GLboolean QGLFunctions::glIsRenderbuffer(GLuint renderbuffer) + + Convenience function that calls glIsRenderbuffer(\a renderbuffer). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glIsRenderbuffer.xml}{glIsRenderbuffer()}. +*/ + +/*! + \fn GLboolean QGLFunctions::glIsShader(GLuint shader) + + Convenience function that calls glIsShader(\a shader). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glIsShader.xml}{glIsShader()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glLinkProgram(GLuint program) + + Convenience function that calls glLinkProgram(\a program). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glLinkProgram.xml}{glLinkProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glReleaseShaderCompiler() + + Convenience function that calls glReleaseShaderCompiler(). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glReleaseShaderCompiler.xml}{glReleaseShaderCompiler()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) + + Convenience function that calls glRenderbufferStorage(\a target, \a internalformat, \a width, \a height). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glRenderbufferStorage.xml}{glRenderbufferStorage()}. +*/ + +/*! + \fn void QGLFunctions::glSampleCoverage(GLclampf value, GLboolean invert) + + Convenience function that calls glSampleCoverage(\a value, \a invert). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glSampleCoverage.xml}{glSampleCoverage()}. +*/ + +/*! + \fn void QGLFunctions::glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length) + + Convenience function that calls glShaderBinary(\a n, \a shaders, \a binaryformat, \a binary, \a length). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glShaderBinary.xml}{glShaderBinary()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length) + + Convenience function that calls glShaderSource(\a shader, \a count, \a string, \a length). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glShaderSource.xml}{glShaderSource()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) + + Convenience function that calls glStencilFuncSeparate(\a face, \a func, \a ref, \a mask). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilFuncSeparate.xml}{glStencilFuncSeparate()}. +*/ + +/*! + \fn void QGLFunctions::glStencilMaskSeparate(GLenum face, GLuint mask) + + Convenience function that calls glStencilMaskSeparate(\a face, \a mask). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilMaskSeparate.xml}{glStencilMaskSeparate()}. +*/ + +/*! + \fn void QGLFunctions::glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) + + Convenience function that calls glStencilOpSeparate(\a face, \a fail, \a zfail, \a zpass). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilOpSeparate.xml}{glStencilOpSeparate()}. +*/ + +/*! + \fn void QGLFunctions::glUniform1f(GLint location, GLfloat x) + + Convenience function that calls glUniform1f(\a location, \a x). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1f.xml}{glUniform1f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform1fv(GLint location, GLsizei count, const GLfloat* v) + + Convenience function that calls glUniform1fv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1fv.xml}{glUniform1fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform1i(GLint location, GLint x) + + Convenience function that calls glUniform1i(\a location, \a x). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1i.xml}{glUniform1i()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform1iv(GLint location, GLsizei count, const GLint* v) + + Convenience function that calls glUniform1iv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1iv.xml}{glUniform1iv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform2f(GLint location, GLfloat x, GLfloat y) + + Convenience function that calls glUniform2f(\a location, \a x, \a y). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2f.xml}{glUniform2f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform2fv(GLint location, GLsizei count, const GLfloat* v) + + Convenience function that calls glUniform2fv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2fv.xml}{glUniform2fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform2i(GLint location, GLint x, GLint y) + + Convenience function that calls glUniform2i(\a location, \a x, \a y). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2i.xml}{glUniform2i()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform2iv(GLint location, GLsizei count, const GLint* v) + + Convenience function that calls glUniform2iv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2iv.xml}{glUniform2iv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) + + Convenience function that calls glUniform3f(\a location, \a x, \a y, \a z). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3f.xml}{glUniform3f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform3fv(GLint location, GLsizei count, const GLfloat* v) + + Convenience function that calls glUniform3fv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3fv.xml}{glUniform3fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform3i(GLint location, GLint x, GLint y, GLint z) + + Convenience function that calls glUniform3i(\a location, \a x, \a y, \a z). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3i.xml}{glUniform3i()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform3iv(GLint location, GLsizei count, const GLint* v) + + Convenience function that calls glUniform3iv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3iv.xml}{glUniform3iv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) + + Convenience function that calls glUniform4f(\a location, \a x, \a y, \a z, \a w). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4f.xml}{glUniform4f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform4fv(GLint location, GLsizei count, const GLfloat* v) + + Convenience function that calls glUniform4fv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4fv.xml}{glUniform4fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) + + Convenience function that calls glUniform4i(\a location, \a x, \a y, \a z, \a w). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4i.xml}{glUniform4i()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniform4iv(GLint location, GLsizei count, const GLint* v) + + Convenience function that calls glUniform4iv(\a location, \a count, \a v). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4iv.xml}{glUniform4iv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + + Convenience function that calls glUniformMatrix2fv(\a location, \a count, \a transpose, \a value). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix2fv.xml}{glUniformMatrix2fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + + Convenience function that calls glUniformMatrix3fv(\a location, \a count, \a transpose, \a value). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix3fv.xml}{glUniformMatrix3fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + + Convenience function that calls glUniformMatrix4fv(\a location, \a count, \a transpose, \a value). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix4fv.xml}{glUniformMatrix4fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glUseProgram(GLuint program) + + Convenience function that calls glUseProgram(\a program). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glUseProgram.xml}{glUseProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glValidateProgram(GLuint program) + + Convenience function that calls glValidateProgram(\a program). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glValidateProgram.xml}{glValidateProgram()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib1f(GLuint indx, GLfloat x) + + Convenience function that calls glVertexAttrib1f(\a indx, \a x). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib1f.xml}{glVertexAttrib1f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib1fv(GLuint indx, const GLfloat* values) + + Convenience function that calls glVertexAttrib1fv(\a indx, \a values). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib1fv.xml}{glVertexAttrib1fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) + + Convenience function that calls glVertexAttrib2f(\a indx, \a x, \a y). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib2f.xml}{glVertexAttrib2f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib2fv(GLuint indx, const GLfloat* values) + + Convenience function that calls glVertexAttrib2fv(\a indx, \a values). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib2fv.xml}{glVertexAttrib2fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) + + Convenience function that calls glVertexAttrib3f(\a indx, \a x, \a y, \a z). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib3f.xml}{glVertexAttrib3f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib3fv(GLuint indx, const GLfloat* values) + + Convenience function that calls glVertexAttrib3fv(\a indx, \a values). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib3fv.xml}{glVertexAttrib3fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) + + Convenience function that calls glVertexAttrib4f(\a indx, \a x, \a y, \a z, \a w). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib4f.xml}{glVertexAttrib4f()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttrib4fv(GLuint indx, const GLfloat* values) + + Convenience function that calls glVertexAttrib4fv(\a indx, \a values). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib4fv.xml}{glVertexAttrib4fv()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +/*! + \fn void QGLFunctions::glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) + + Convenience function that calls glVertexAttribPointer(\a indx, \a size, \a type, \a normalized, \a stride, \a ptr). + + For more information, see the OpenGL/ES 2.0 documentation for + \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttribPointer.xml}{glVertexAttribPointer()}. + + This convenience function will do nothing on OpenGL/ES 1.x systems. +*/ + +#ifndef QT_OPENGL_ES_2 + +static void qglfResolveActiveTexture(GLenum texture) +{ + typedef void (QGLF_APIENTRYP type_glActiveTexture)(GLenum texture); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->activeTexture = (type_glActiveTexture) + context->getProcAddress(QLatin1String("glActiveTexture")); + if (!funcs->activeTexture) { + funcs->activeTexture = (type_glActiveTexture) + context->getProcAddress(QLatin1String("glActiveTextureARB")); + } + + if (funcs->activeTexture) + funcs->activeTexture(texture); + else + funcs->activeTexture = qglfResolveActiveTexture; +} + +static void qglfResolveAttachShader(GLuint program, GLuint shader) +{ + typedef void (QGLF_APIENTRYP type_glAttachShader)(GLuint program, GLuint shader); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->attachShader = (type_glAttachShader) + context->getProcAddress(QLatin1String("glAttachShader")); + if (!funcs->attachShader) { + funcs->attachShader = (type_glAttachShader) + context->getProcAddress(QLatin1String("glAttachObjectARB")); + } + + if (funcs->attachShader) + funcs->attachShader(program, shader); + else + funcs->attachShader = qglfResolveAttachShader; +} + +static void qglfResolveBindAttribLocation(GLuint program, GLuint index, const char* name) +{ + typedef void (QGLF_APIENTRYP type_glBindAttribLocation)(GLuint program, GLuint index, const char* name); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bindAttribLocation = (type_glBindAttribLocation) + context->getProcAddress(QLatin1String("glBindAttribLocation")); + if (!funcs->bindAttribLocation) { + funcs->bindAttribLocation = (type_glBindAttribLocation) + context->getProcAddress(QLatin1String("glBindAttribLocationARB")); + } + + if (funcs->bindAttribLocation) + funcs->bindAttribLocation(program, index, name); + else + funcs->bindAttribLocation = qglfResolveBindAttribLocation; +} + +static void qglfResolveBindBuffer(GLenum target, GLuint buffer) +{ + typedef void (QGLF_APIENTRYP type_glBindBuffer)(GLenum target, GLuint buffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bindBuffer = (type_glBindBuffer) + context->getProcAddress(QLatin1String("glBindBuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->bindBuffer) { + funcs->bindBuffer = (type_glBindBuffer) + context->getProcAddress(QLatin1String("glBindBufferOES")); + } +#endif + if (!funcs->bindBuffer) { + funcs->bindBuffer = (type_glBindBuffer) + context->getProcAddress(QLatin1String("glBindBufferEXT")); + } + if (!funcs->bindBuffer) { + funcs->bindBuffer = (type_glBindBuffer) + context->getProcAddress(QLatin1String("glBindBufferARB")); + } + + if (funcs->bindBuffer) + funcs->bindBuffer(target, buffer); + else + funcs->bindBuffer = qglfResolveBindBuffer; +} + +static void qglfResolveBindFramebuffer(GLenum target, GLuint framebuffer) +{ + typedef void (QGLF_APIENTRYP type_glBindFramebuffer)(GLenum target, GLuint framebuffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bindFramebuffer = (type_glBindFramebuffer) + context->getProcAddress(QLatin1String("glBindFramebuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->bindFramebuffer) { + funcs->bindFramebuffer = (type_glBindFramebuffer) + context->getProcAddress(QLatin1String("glBindFramebufferOES")); + } +#endif + if (!funcs->bindFramebuffer) { + funcs->bindFramebuffer = (type_glBindFramebuffer) + context->getProcAddress(QLatin1String("glBindFramebufferEXT")); + } + if (!funcs->bindFramebuffer) { + funcs->bindFramebuffer = (type_glBindFramebuffer) + context->getProcAddress(QLatin1String("glBindFramebufferARB")); + } + + if (funcs->bindFramebuffer) + funcs->bindFramebuffer(target, framebuffer); + else + funcs->bindFramebuffer = qglfResolveBindFramebuffer; +} + +static void qglfResolveBindRenderbuffer(GLenum target, GLuint renderbuffer) +{ + typedef void (QGLF_APIENTRYP type_glBindRenderbuffer)(GLenum target, GLuint renderbuffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bindRenderbuffer = (type_glBindRenderbuffer) + context->getProcAddress(QLatin1String("glBindRenderbuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->bindRenderbuffer) { + funcs->bindRenderbuffer = (type_glBindRenderbuffer) + context->getProcAddress(QLatin1String("glBindRenderbufferOES")); + } +#endif + if (!funcs->bindRenderbuffer) { + funcs->bindRenderbuffer = (type_glBindRenderbuffer) + context->getProcAddress(QLatin1String("glBindRenderbufferEXT")); + } + if (!funcs->bindRenderbuffer) { + funcs->bindRenderbuffer = (type_glBindRenderbuffer) + context->getProcAddress(QLatin1String("glBindRenderbufferARB")); + } + + if (funcs->bindRenderbuffer) + funcs->bindRenderbuffer(target, renderbuffer); + else + funcs->bindRenderbuffer = qglfResolveBindRenderbuffer; +} + +static void qglfResolveBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + typedef void (QGLF_APIENTRYP type_glBlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->blendColor = (type_glBlendColor) + context->getProcAddress(QLatin1String("glBlendColor")); +#ifdef QT_OPENGL_ES + if (!funcs->blendColor) { + funcs->blendColor = (type_glBlendColor) + context->getProcAddress(QLatin1String("glBlendColorOES")); + } +#endif + if (!funcs->blendColor) { + funcs->blendColor = (type_glBlendColor) + context->getProcAddress(QLatin1String("glBlendColorEXT")); + } + if (!funcs->blendColor) { + funcs->blendColor = (type_glBlendColor) + context->getProcAddress(QLatin1String("glBlendColorARB")); + } + + if (funcs->blendColor) + funcs->blendColor(red, green, blue, alpha); + else + funcs->blendColor = qglfResolveBlendColor; +} + +static void qglfResolveBlendEquation(GLenum mode) +{ + typedef void (QGLF_APIENTRYP type_glBlendEquation)(GLenum mode); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->blendEquation = (type_glBlendEquation) + context->getProcAddress(QLatin1String("glBlendEquation")); +#ifdef QT_OPENGL_ES + if (!funcs->blendEquation) { + funcs->blendEquation = (type_glBlendEquation) + context->getProcAddress(QLatin1String("glBlendEquationOES")); + } +#endif + if (!funcs->blendEquation) { + funcs->blendEquation = (type_glBlendEquation) + context->getProcAddress(QLatin1String("glBlendEquationEXT")); + } + if (!funcs->blendEquation) { + funcs->blendEquation = (type_glBlendEquation) + context->getProcAddress(QLatin1String("glBlendEquationARB")); + } + + if (funcs->blendEquation) + funcs->blendEquation(mode); + else + funcs->blendEquation = qglfResolveBlendEquation; +} + +static void qglfResolveBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) +{ + typedef void (QGLF_APIENTRYP type_glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->blendEquationSeparate = (type_glBlendEquationSeparate) + context->getProcAddress(QLatin1String("glBlendEquationSeparate")); +#ifdef QT_OPENGL_ES + if (!funcs->blendEquationSeparate) { + funcs->blendEquationSeparate = (type_glBlendEquationSeparate) + context->getProcAddress(QLatin1String("glBlendEquationSeparateOES")); + } +#endif + if (!funcs->blendEquationSeparate) { + funcs->blendEquationSeparate = (type_glBlendEquationSeparate) + context->getProcAddress(QLatin1String("glBlendEquationSeparateEXT")); + } + if (!funcs->blendEquationSeparate) { + funcs->blendEquationSeparate = (type_glBlendEquationSeparate) + context->getProcAddress(QLatin1String("glBlendEquationSeparateARB")); + } + + if (funcs->blendEquationSeparate) + funcs->blendEquationSeparate(modeRGB, modeAlpha); + else + funcs->blendEquationSeparate = qglfResolveBlendEquationSeparate; +} + +static void qglfResolveBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +{ + typedef void (QGLF_APIENTRYP type_glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->blendFuncSeparate = (type_glBlendFuncSeparate) + context->getProcAddress(QLatin1String("glBlendFuncSeparate")); +#ifdef QT_OPENGL_ES + if (!funcs->blendFuncSeparate) { + funcs->blendFuncSeparate = (type_glBlendFuncSeparate) + context->getProcAddress(QLatin1String("glBlendFuncSeparateOES")); + } +#endif + if (!funcs->blendFuncSeparate) { + funcs->blendFuncSeparate = (type_glBlendFuncSeparate) + context->getProcAddress(QLatin1String("glBlendFuncSeparateEXT")); + } + if (!funcs->blendFuncSeparate) { + funcs->blendFuncSeparate = (type_glBlendFuncSeparate) + context->getProcAddress(QLatin1String("glBlendFuncSeparateARB")); + } + + if (funcs->blendFuncSeparate) + funcs->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); + else + funcs->blendFuncSeparate = qglfResolveBlendFuncSeparate; +} + +static void qglfResolveBufferData(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage) +{ + typedef void (QGLF_APIENTRYP type_glBufferData)(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bufferData = (type_glBufferData) + context->getProcAddress(QLatin1String("glBufferData")); +#ifdef QT_OPENGL_ES + if (!funcs->bufferData) { + funcs->bufferData = (type_glBufferData) + context->getProcAddress(QLatin1String("glBufferDataOES")); + } +#endif + if (!funcs->bufferData) { + funcs->bufferData = (type_glBufferData) + context->getProcAddress(QLatin1String("glBufferDataEXT")); + } + if (!funcs->bufferData) { + funcs->bufferData = (type_glBufferData) + context->getProcAddress(QLatin1String("glBufferDataARB")); + } + + if (funcs->bufferData) + funcs->bufferData(target, size, data, usage); + else + funcs->bufferData = qglfResolveBufferData; +} + +static void qglfResolveBufferSubData(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data) +{ + typedef void (QGLF_APIENTRYP type_glBufferSubData)(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->bufferSubData = (type_glBufferSubData) + context->getProcAddress(QLatin1String("glBufferSubData")); +#ifdef QT_OPENGL_ES + if (!funcs->bufferSubData) { + funcs->bufferSubData = (type_glBufferSubData) + context->getProcAddress(QLatin1String("glBufferSubDataOES")); + } +#endif + if (!funcs->bufferSubData) { + funcs->bufferSubData = (type_glBufferSubData) + context->getProcAddress(QLatin1String("glBufferSubDataEXT")); + } + if (!funcs->bufferSubData) { + funcs->bufferSubData = (type_glBufferSubData) + context->getProcAddress(QLatin1String("glBufferSubDataARB")); + } + + if (funcs->bufferSubData) + funcs->bufferSubData(target, offset, size, data); + else + funcs->bufferSubData = qglfResolveBufferSubData; +} + +static GLenum qglfResolveCheckFramebufferStatus(GLenum target) +{ + typedef GLenum (QGLF_APIENTRYP type_glCheckFramebufferStatus)(GLenum target); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->checkFramebufferStatus = (type_glCheckFramebufferStatus) + context->getProcAddress(QLatin1String("glCheckFramebufferStatus")); +#ifdef QT_OPENGL_ES + if (!funcs->checkFramebufferStatus) { + funcs->checkFramebufferStatus = (type_glCheckFramebufferStatus) + context->getProcAddress(QLatin1String("glCheckFramebufferStatusOES")); + } +#endif + if (!funcs->checkFramebufferStatus) { + funcs->checkFramebufferStatus = (type_glCheckFramebufferStatus) + context->getProcAddress(QLatin1String("glCheckFramebufferStatusEXT")); + } + if (!funcs->checkFramebufferStatus) { + funcs->checkFramebufferStatus = (type_glCheckFramebufferStatus) + context->getProcAddress(QLatin1String("glCheckFramebufferStatusARB")); + } + + if (funcs->checkFramebufferStatus) + return funcs->checkFramebufferStatus(target); + funcs->checkFramebufferStatus = qglfResolveCheckFramebufferStatus; + return GLenum(0); +} + +static void qglfResolveCompileShader(GLuint shader) +{ + typedef void (QGLF_APIENTRYP type_glCompileShader)(GLuint shader); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->compileShader = (type_glCompileShader) + context->getProcAddress(QLatin1String("glCompileShader")); + if (!funcs->compileShader) { + funcs->compileShader = (type_glCompileShader) + context->getProcAddress(QLatin1String("glCompileShader")); + } + + if (funcs->compileShader) + funcs->compileShader(shader); + else + funcs->compileShader = qglfResolveCompileShader; +} + +static void qglfResolveCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) +{ + typedef void (QGLF_APIENTRYP type_glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->compressedTexImage2D = (type_glCompressedTexImage2D) + context->getProcAddress(QLatin1String("glCompressedTexImage2D")); +#ifdef QT_OPENGL_ES + if (!funcs->compressedTexImage2D) { + funcs->compressedTexImage2D = (type_glCompressedTexImage2D) + context->getProcAddress(QLatin1String("glCompressedTexImage2DOES")); + } +#endif + if (!funcs->compressedTexImage2D) { + funcs->compressedTexImage2D = (type_glCompressedTexImage2D) + context->getProcAddress(QLatin1String("glCompressedTexImage2DEXT")); + } + if (!funcs->compressedTexImage2D) { + funcs->compressedTexImage2D = (type_glCompressedTexImage2D) + context->getProcAddress(QLatin1String("glCompressedTexImage2DARB")); + } + + if (funcs->compressedTexImage2D) + funcs->compressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); + else + funcs->compressedTexImage2D = qglfResolveCompressedTexImage2D; +} + +static void qglfResolveCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) +{ + typedef void (QGLF_APIENTRYP type_glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->compressedTexSubImage2D = (type_glCompressedTexSubImage2D) + context->getProcAddress(QLatin1String("glCompressedTexSubImage2D")); +#ifdef QT_OPENGL_ES + if (!funcs->compressedTexSubImage2D) { + funcs->compressedTexSubImage2D = (type_glCompressedTexSubImage2D) + context->getProcAddress(QLatin1String("glCompressedTexSubImage2DOES")); + } +#endif + if (!funcs->compressedTexSubImage2D) { + funcs->compressedTexSubImage2D = (type_glCompressedTexSubImage2D) + context->getProcAddress(QLatin1String("glCompressedTexSubImage2DEXT")); + } + if (!funcs->compressedTexSubImage2D) { + funcs->compressedTexSubImage2D = (type_glCompressedTexSubImage2D) + context->getProcAddress(QLatin1String("glCompressedTexSubImage2DARB")); + } + + if (funcs->compressedTexSubImage2D) + funcs->compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); + else + funcs->compressedTexSubImage2D = qglfResolveCompressedTexSubImage2D; +} + +static GLuint qglfResolveCreateProgram() +{ + typedef GLuint (QGLF_APIENTRYP type_glCreateProgram)(); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->createProgram = (type_glCreateProgram) + context->getProcAddress(QLatin1String("glCreateProgram")); + if (!funcs->createProgram) { + funcs->createProgram = (type_glCreateProgram) + context->getProcAddress(QLatin1String("glCreateProgramObjectARB")); + } + + if (funcs->createProgram) + return funcs->createProgram(); + funcs->createProgram = qglfResolveCreateProgram; + return GLuint(0); +} + +static GLuint qglfResolveCreateShader(GLenum type) +{ + typedef GLuint (QGLF_APIENTRYP type_glCreateShader)(GLenum type); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->createShader = (type_glCreateShader) + context->getProcAddress(QLatin1String("glCreateShader")); + if (!funcs->createShader) { + funcs->createShader = (type_glCreateShader) + context->getProcAddress(QLatin1String("glCreateShaderObjectARB")); + } + + if (funcs->createShader) + return funcs->createShader(type); + funcs->createShader = qglfResolveCreateShader; + return GLuint(0); +} + +static void qglfResolveDeleteBuffers(GLsizei n, const GLuint* buffers) +{ + typedef void (QGLF_APIENTRYP type_glDeleteBuffers)(GLsizei n, const GLuint* buffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->deleteBuffers = (type_glDeleteBuffers) + context->getProcAddress(QLatin1String("glDeleteBuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->deleteBuffers) { + funcs->deleteBuffers = (type_glDeleteBuffers) + context->getProcAddress(QLatin1String("glDeleteBuffersOES")); + } +#endif + if (!funcs->deleteBuffers) { + funcs->deleteBuffers = (type_glDeleteBuffers) + context->getProcAddress(QLatin1String("glDeleteBuffersEXT")); + } + if (!funcs->deleteBuffers) { + funcs->deleteBuffers = (type_glDeleteBuffers) + context->getProcAddress(QLatin1String("glDeleteBuffersARB")); + } + + if (funcs->deleteBuffers) + funcs->deleteBuffers(n, buffers); + else + funcs->deleteBuffers = qglfResolveDeleteBuffers; +} + +static void qglfResolveDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) +{ + typedef void (QGLF_APIENTRYP type_glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->deleteFramebuffers = (type_glDeleteFramebuffers) + context->getProcAddress(QLatin1String("glDeleteFramebuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->deleteFramebuffers) { + funcs->deleteFramebuffers = (type_glDeleteFramebuffers) + context->getProcAddress(QLatin1String("glDeleteFramebuffersOES")); + } +#endif + if (!funcs->deleteFramebuffers) { + funcs->deleteFramebuffers = (type_glDeleteFramebuffers) + context->getProcAddress(QLatin1String("glDeleteFramebuffersEXT")); + } + if (!funcs->deleteFramebuffers) { + funcs->deleteFramebuffers = (type_glDeleteFramebuffers) + context->getProcAddress(QLatin1String("glDeleteFramebuffersARB")); + } + + if (funcs->deleteFramebuffers) + funcs->deleteFramebuffers(n, framebuffers); + else + funcs->deleteFramebuffers = qglfResolveDeleteFramebuffers; +} + +static void qglfResolveDeleteProgram(GLuint program) +{ + typedef void (QGLF_APIENTRYP type_glDeleteProgram)(GLuint program); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->deleteProgram = (type_glDeleteProgram) + context->getProcAddress(QLatin1String("glDeleteProgram")); + if (!funcs->deleteProgram) { + funcs->deleteProgram = (type_glDeleteProgram) + context->getProcAddress(QLatin1String("glDeleteObjectARB")); + } + + if (funcs->deleteProgram) + funcs->deleteProgram(program); + else + funcs->deleteProgram = qglfResolveDeleteProgram; +} + +static void qglfResolveDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) +{ + typedef void (QGLF_APIENTRYP type_glDeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->deleteRenderbuffers = (type_glDeleteRenderbuffers) + context->getProcAddress(QLatin1String("glDeleteRenderbuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->deleteRenderbuffers) { + funcs->deleteRenderbuffers = (type_glDeleteRenderbuffers) + context->getProcAddress(QLatin1String("glDeleteRenderbuffersOES")); + } +#endif + if (!funcs->deleteRenderbuffers) { + funcs->deleteRenderbuffers = (type_glDeleteRenderbuffers) + context->getProcAddress(QLatin1String("glDeleteRenderbuffersEXT")); + } + if (!funcs->deleteRenderbuffers) { + funcs->deleteRenderbuffers = (type_glDeleteRenderbuffers) + context->getProcAddress(QLatin1String("glDeleteRenderbuffersARB")); + } + + if (funcs->deleteRenderbuffers) + funcs->deleteRenderbuffers(n, renderbuffers); + else + funcs->deleteRenderbuffers = qglfResolveDeleteRenderbuffers; +} + +static void qglfResolveDeleteShader(GLuint shader) +{ + typedef void (QGLF_APIENTRYP type_glDeleteShader)(GLuint shader); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->deleteShader = (type_glDeleteShader) + context->getProcAddress(QLatin1String("glDeleteShader")); + if (!funcs->deleteShader) { + funcs->deleteShader = (type_glDeleteShader) + context->getProcAddress(QLatin1String("glDeleteObjectARB")); + } + + if (funcs->deleteShader) + funcs->deleteShader(shader); + else + funcs->deleteShader = qglfResolveDeleteShader; +} + +static void qglfResolveDetachShader(GLuint program, GLuint shader) +{ + typedef void (QGLF_APIENTRYP type_glDetachShader)(GLuint program, GLuint shader); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->detachShader = (type_glDetachShader) + context->getProcAddress(QLatin1String("glDetachShader")); + if (!funcs->detachShader) { + funcs->detachShader = (type_glDetachShader) + context->getProcAddress(QLatin1String("glDetachObjectARB")); + } + + if (funcs->detachShader) + funcs->detachShader(program, shader); + else + funcs->detachShader = qglfResolveDetachShader; +} + +static void qglfResolveDisableVertexAttribArray(GLuint index) +{ + typedef void (QGLF_APIENTRYP type_glDisableVertexAttribArray)(GLuint index); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->disableVertexAttribArray = (type_glDisableVertexAttribArray) + context->getProcAddress(QLatin1String("glDisableVertexAttribArray")); + if (!funcs->disableVertexAttribArray) { + funcs->disableVertexAttribArray = (type_glDisableVertexAttribArray) + context->getProcAddress(QLatin1String("glDisableVertexAttribArrayARB")); + } + + if (funcs->disableVertexAttribArray) + funcs->disableVertexAttribArray(index); + else + funcs->disableVertexAttribArray = qglfResolveDisableVertexAttribArray; +} + +static void qglfResolveEnableVertexAttribArray(GLuint index) +{ + typedef void (QGLF_APIENTRYP type_glEnableVertexAttribArray)(GLuint index); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->enableVertexAttribArray = (type_glEnableVertexAttribArray) + context->getProcAddress(QLatin1String("glEnableVertexAttribArray")); + if (!funcs->enableVertexAttribArray) { + funcs->enableVertexAttribArray = (type_glEnableVertexAttribArray) + context->getProcAddress(QLatin1String("glEnableVertexAttribArrayARB")); + } + + if (funcs->enableVertexAttribArray) + funcs->enableVertexAttribArray(index); + else + funcs->enableVertexAttribArray = qglfResolveEnableVertexAttribArray; +} + +static void qglfResolveFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ + typedef void (QGLF_APIENTRYP type_glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->framebufferRenderbuffer = (type_glFramebufferRenderbuffer) + context->getProcAddress(QLatin1String("glFramebufferRenderbuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->framebufferRenderbuffer) { + funcs->framebufferRenderbuffer = (type_glFramebufferRenderbuffer) + context->getProcAddress(QLatin1String("glFramebufferRenderbufferOES")); + } +#endif + if (!funcs->framebufferRenderbuffer) { + funcs->framebufferRenderbuffer = (type_glFramebufferRenderbuffer) + context->getProcAddress(QLatin1String("glFramebufferRenderbufferEXT")); + } + if (!funcs->framebufferRenderbuffer) { + funcs->framebufferRenderbuffer = (type_glFramebufferRenderbuffer) + context->getProcAddress(QLatin1String("glFramebufferRenderbufferARB")); + } + + if (funcs->framebufferRenderbuffer) + funcs->framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); + else + funcs->framebufferRenderbuffer = qglfResolveFramebufferRenderbuffer; +} + +static void qglfResolveFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ + typedef void (QGLF_APIENTRYP type_glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->framebufferTexture2D = (type_glFramebufferTexture2D) + context->getProcAddress(QLatin1String("glFramebufferTexture2D")); +#ifdef QT_OPENGL_ES + if (!funcs->framebufferTexture2D) { + funcs->framebufferTexture2D = (type_glFramebufferTexture2D) + context->getProcAddress(QLatin1String("glFramebufferTexture2DOES")); + } +#endif + if (!funcs->framebufferTexture2D) { + funcs->framebufferTexture2D = (type_glFramebufferTexture2D) + context->getProcAddress(QLatin1String("glFramebufferTexture2DEXT")); + } + if (!funcs->framebufferTexture2D) { + funcs->framebufferTexture2D = (type_glFramebufferTexture2D) + context->getProcAddress(QLatin1String("glFramebufferTexture2DARB")); + } + + if (funcs->framebufferTexture2D) + funcs->framebufferTexture2D(target, attachment, textarget, texture, level); + else + funcs->framebufferTexture2D = qglfResolveFramebufferTexture2D; +} + +static void qglfResolveGenBuffers(GLsizei n, GLuint* buffers) +{ + typedef void (QGLF_APIENTRYP type_glGenBuffers)(GLsizei n, GLuint* buffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->genBuffers = (type_glGenBuffers) + context->getProcAddress(QLatin1String("glGenBuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->genBuffers) { + funcs->genBuffers = (type_glGenBuffers) + context->getProcAddress(QLatin1String("glGenBuffersOES")); + } +#endif + if (!funcs->genBuffers) { + funcs->genBuffers = (type_glGenBuffers) + context->getProcAddress(QLatin1String("glGenBuffersEXT")); + } + if (!funcs->genBuffers) { + funcs->genBuffers = (type_glGenBuffers) + context->getProcAddress(QLatin1String("glGenBuffersARB")); + } + + if (funcs->genBuffers) + funcs->genBuffers(n, buffers); + else + funcs->genBuffers = qglfResolveGenBuffers; +} + +static void qglfResolveGenerateMipmap(GLenum target) +{ + typedef void (QGLF_APIENTRYP type_glGenerateMipmap)(GLenum target); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->generateMipmap = (type_glGenerateMipmap) + context->getProcAddress(QLatin1String("glGenerateMipmap")); +#ifdef QT_OPENGL_ES + if (!funcs->generateMipmap) { + funcs->generateMipmap = (type_glGenerateMipmap) + context->getProcAddress(QLatin1String("glGenerateMipmapOES")); + } +#endif + if (!funcs->generateMipmap) { + funcs->generateMipmap = (type_glGenerateMipmap) + context->getProcAddress(QLatin1String("glGenerateMipmapEXT")); + } + if (!funcs->generateMipmap) { + funcs->generateMipmap = (type_glGenerateMipmap) + context->getProcAddress(QLatin1String("glGenerateMipmapARB")); + } + + if (funcs->generateMipmap) + funcs->generateMipmap(target); + else + funcs->generateMipmap = qglfResolveGenerateMipmap; +} + +static void qglfResolveGenFramebuffers(GLsizei n, GLuint* framebuffers) +{ + typedef void (QGLF_APIENTRYP type_glGenFramebuffers)(GLsizei n, GLuint* framebuffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->genFramebuffers = (type_glGenFramebuffers) + context->getProcAddress(QLatin1String("glGenFramebuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->genFramebuffers) { + funcs->genFramebuffers = (type_glGenFramebuffers) + context->getProcAddress(QLatin1String("glGenFramebuffersOES")); + } +#endif + if (!funcs->genFramebuffers) { + funcs->genFramebuffers = (type_glGenFramebuffers) + context->getProcAddress(QLatin1String("glGenFramebuffersEXT")); + } + if (!funcs->genFramebuffers) { + funcs->genFramebuffers = (type_glGenFramebuffers) + context->getProcAddress(QLatin1String("glGenFramebuffersARB")); + } + + if (funcs->genFramebuffers) + funcs->genFramebuffers(n, framebuffers); + else + funcs->genFramebuffers = qglfResolveGenFramebuffers; +} + +static void qglfResolveGenRenderbuffers(GLsizei n, GLuint* renderbuffers) +{ + typedef void (QGLF_APIENTRYP type_glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->genRenderbuffers = (type_glGenRenderbuffers) + context->getProcAddress(QLatin1String("glGenRenderbuffers")); +#ifdef QT_OPENGL_ES + if (!funcs->genRenderbuffers) { + funcs->genRenderbuffers = (type_glGenRenderbuffers) + context->getProcAddress(QLatin1String("glGenRenderbuffersOES")); + } +#endif + if (!funcs->genRenderbuffers) { + funcs->genRenderbuffers = (type_glGenRenderbuffers) + context->getProcAddress(QLatin1String("glGenRenderbuffersEXT")); + } + if (!funcs->genRenderbuffers) { + funcs->genRenderbuffers = (type_glGenRenderbuffers) + context->getProcAddress(QLatin1String("glGenRenderbuffersARB")); + } + + if (funcs->genRenderbuffers) + funcs->genRenderbuffers(n, renderbuffers); + else + funcs->genRenderbuffers = qglfResolveGenRenderbuffers; +} + +static void qglfResolveGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) +{ + typedef void (QGLF_APIENTRYP type_glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getActiveAttrib = (type_glGetActiveAttrib) + context->getProcAddress(QLatin1String("glGetActiveAttrib")); + if (!funcs->getActiveAttrib) { + funcs->getActiveAttrib = (type_glGetActiveAttrib) + context->getProcAddress(QLatin1String("glGetActiveAttribARB")); + } + + if (funcs->getActiveAttrib) + funcs->getActiveAttrib(program, index, bufsize, length, size, type, name); + else + funcs->getActiveAttrib = qglfResolveGetActiveAttrib; +} + +static void qglfResolveGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) +{ + typedef void (QGLF_APIENTRYP type_glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getActiveUniform = (type_glGetActiveUniform) + context->getProcAddress(QLatin1String("glGetActiveUniform")); + if (!funcs->getActiveUniform) { + funcs->getActiveUniform = (type_glGetActiveUniform) + context->getProcAddress(QLatin1String("glGetActiveUniformARB")); + } + + if (funcs->getActiveUniform) + funcs->getActiveUniform(program, index, bufsize, length, size, type, name); + else + funcs->getActiveUniform = qglfResolveGetActiveUniform; +} + +static void qglfResolveGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) +{ + typedef void (QGLF_APIENTRYP type_glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getAttachedShaders = (type_glGetAttachedShaders) + context->getProcAddress(QLatin1String("glGetAttachedShaders")); + if (!funcs->getAttachedShaders) { + funcs->getAttachedShaders = (type_glGetAttachedShaders) + context->getProcAddress(QLatin1String("glGetAttachedObjectsARB")); + } + + if (funcs->getAttachedShaders) + funcs->getAttachedShaders(program, maxcount, count, shaders); + else + funcs->getAttachedShaders = qglfResolveGetAttachedShaders; +} + +static int qglfResolveGetAttribLocation(GLuint program, const char* name) +{ + typedef int (QGLF_APIENTRYP type_glGetAttribLocation)(GLuint program, const char* name); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getAttribLocation = (type_glGetAttribLocation) + context->getProcAddress(QLatin1String("glGetAttribLocation")); + if (!funcs->getAttribLocation) { + funcs->getAttribLocation = (type_glGetAttribLocation) + context->getProcAddress(QLatin1String("glGetAttribLocationARB")); + } + + if (funcs->getAttribLocation) + return funcs->getAttribLocation(program, name); + funcs->getAttribLocation = qglfResolveGetAttribLocation; + return int(0); +} + +static void qglfResolveGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getBufferParameteriv = (type_glGetBufferParameteriv) + context->getProcAddress(QLatin1String("glGetBufferParameteriv")); +#ifdef QT_OPENGL_ES + if (!funcs->getBufferParameteriv) { + funcs->getBufferParameteriv = (type_glGetBufferParameteriv) + context->getProcAddress(QLatin1String("glGetBufferParameterivOES")); + } +#endif + if (!funcs->getBufferParameteriv) { + funcs->getBufferParameteriv = (type_glGetBufferParameteriv) + context->getProcAddress(QLatin1String("glGetBufferParameterivEXT")); + } + if (!funcs->getBufferParameteriv) { + funcs->getBufferParameteriv = (type_glGetBufferParameteriv) + context->getProcAddress(QLatin1String("glGetBufferParameterivARB")); + } + + if (funcs->getBufferParameteriv) + funcs->getBufferParameteriv(target, pname, params); + else + funcs->getBufferParameteriv = qglfResolveGetBufferParameteriv; +} + +static void qglfResolveGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getFramebufferAttachmentParameteriv = (type_glGetFramebufferAttachmentParameteriv) + context->getProcAddress(QLatin1String("glGetFramebufferAttachmentParameteriv")); +#ifdef QT_OPENGL_ES + if (!funcs->getFramebufferAttachmentParameteriv) { + funcs->getFramebufferAttachmentParameteriv = (type_glGetFramebufferAttachmentParameteriv) + context->getProcAddress(QLatin1String("glGetFramebufferAttachmentParameterivOES")); + } +#endif + if (!funcs->getFramebufferAttachmentParameteriv) { + funcs->getFramebufferAttachmentParameteriv = (type_glGetFramebufferAttachmentParameteriv) + context->getProcAddress(QLatin1String("glGetFramebufferAttachmentParameterivEXT")); + } + if (!funcs->getFramebufferAttachmentParameteriv) { + funcs->getFramebufferAttachmentParameteriv = (type_glGetFramebufferAttachmentParameteriv) + context->getProcAddress(QLatin1String("glGetFramebufferAttachmentParameterivARB")); + } + + if (funcs->getFramebufferAttachmentParameteriv) + funcs->getFramebufferAttachmentParameteriv(target, attachment, pname, params); + else + funcs->getFramebufferAttachmentParameteriv = qglfResolveGetFramebufferAttachmentParameteriv; +} + +static void qglfResolveGetProgramiv(GLuint program, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetProgramiv)(GLuint program, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getProgramiv = (type_glGetProgramiv) + context->getProcAddress(QLatin1String("glGetProgramiv")); + if (!funcs->getProgramiv) { + funcs->getProgramiv = (type_glGetProgramiv) + context->getProcAddress(QLatin1String("glGetObjectParameterivARB")); + } + + if (funcs->getProgramiv) + funcs->getProgramiv(program, pname, params); + else + funcs->getProgramiv = qglfResolveGetProgramiv; +} + +static void qglfResolveGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) +{ + typedef void (QGLF_APIENTRYP type_glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getProgramInfoLog = (type_glGetProgramInfoLog) + context->getProcAddress(QLatin1String("glGetProgramInfoLog")); + if (!funcs->getProgramInfoLog) { + funcs->getProgramInfoLog = (type_glGetProgramInfoLog) + context->getProcAddress(QLatin1String("glGetInfoLogARB")); + } + + if (funcs->getProgramInfoLog) + funcs->getProgramInfoLog(program, bufsize, length, infolog); + else + funcs->getProgramInfoLog = qglfResolveGetProgramInfoLog; +} + +static void qglfResolveGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getRenderbufferParameteriv = (type_glGetRenderbufferParameteriv) + context->getProcAddress(QLatin1String("glGetRenderbufferParameteriv")); +#ifdef QT_OPENGL_ES + if (!funcs->getRenderbufferParameteriv) { + funcs->getRenderbufferParameteriv = (type_glGetRenderbufferParameteriv) + context->getProcAddress(QLatin1String("glGetRenderbufferParameterivOES")); + } +#endif + if (!funcs->getRenderbufferParameteriv) { + funcs->getRenderbufferParameteriv = (type_glGetRenderbufferParameteriv) + context->getProcAddress(QLatin1String("glGetRenderbufferParameterivEXT")); + } + if (!funcs->getRenderbufferParameteriv) { + funcs->getRenderbufferParameteriv = (type_glGetRenderbufferParameteriv) + context->getProcAddress(QLatin1String("glGetRenderbufferParameterivARB")); + } + + if (funcs->getRenderbufferParameteriv) + funcs->getRenderbufferParameteriv(target, pname, params); + else + funcs->getRenderbufferParameteriv = qglfResolveGetRenderbufferParameteriv; +} + +static void qglfResolveGetShaderiv(GLuint shader, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetShaderiv)(GLuint shader, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getShaderiv = (type_glGetShaderiv) + context->getProcAddress(QLatin1String("glGetShaderiv")); + if (!funcs->getShaderiv) { + funcs->getShaderiv = (type_glGetShaderiv) + context->getProcAddress(QLatin1String("glGetObjectParameterivARB")); + } + + if (funcs->getShaderiv) + funcs->getShaderiv(shader, pname, params); + else + funcs->getShaderiv = qglfResolveGetShaderiv; +} + +static void qglfResolveGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) +{ + typedef void (QGLF_APIENTRYP type_glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getShaderInfoLog = (type_glGetShaderInfoLog) + context->getProcAddress(QLatin1String("glGetShaderInfoLog")); + if (!funcs->getShaderInfoLog) { + funcs->getShaderInfoLog = (type_glGetShaderInfoLog) + context->getProcAddress(QLatin1String("glGetInfoLogARB")); + } + + if (funcs->getShaderInfoLog) + funcs->getShaderInfoLog(shader, bufsize, length, infolog); + else + funcs->getShaderInfoLog = qglfResolveGetShaderInfoLog; +} + +static void qglfSpecialGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) +{ + Q_UNUSED(shadertype); + Q_UNUSED(precisiontype); + range[0] = range[1] = precision[0] = 0; +} + +static void qglfResolveGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) +{ + typedef void (QGLF_APIENTRYP type_glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getShaderPrecisionFormat = (type_glGetShaderPrecisionFormat) + context->getProcAddress(QLatin1String("glGetShaderPrecisionFormat")); +#ifdef QT_OPENGL_ES + if (!funcs->getShaderPrecisionFormat) { + funcs->getShaderPrecisionFormat = (type_glGetShaderPrecisionFormat) + context->getProcAddress(QLatin1String("glGetShaderPrecisionFormatOES")); + } +#endif + if (!funcs->getShaderPrecisionFormat) { + funcs->getShaderPrecisionFormat = (type_glGetShaderPrecisionFormat) + context->getProcAddress(QLatin1String("glGetShaderPrecisionFormatEXT")); + } + if (!funcs->getShaderPrecisionFormat) { + funcs->getShaderPrecisionFormat = (type_glGetShaderPrecisionFormat) + context->getProcAddress(QLatin1String("glGetShaderPrecisionFormatARB")); + } + + if (!funcs->getShaderPrecisionFormat) + funcs->getShaderPrecisionFormat = qglfSpecialGetShaderPrecisionFormat; + + funcs->getShaderPrecisionFormat(shadertype, precisiontype, range, precision); +} + +static void qglfResolveGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source) +{ + typedef void (QGLF_APIENTRYP type_glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, char* source); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getShaderSource = (type_glGetShaderSource) + context->getProcAddress(QLatin1String("glGetShaderSource")); + if (!funcs->getShaderSource) { + funcs->getShaderSource = (type_glGetShaderSource) + context->getProcAddress(QLatin1String("glGetShaderSourceARB")); + } + + if (funcs->getShaderSource) + funcs->getShaderSource(shader, bufsize, length, source); + else + funcs->getShaderSource = qglfResolveGetShaderSource; +} + +static void qglfResolveGetUniformfv(GLuint program, GLint location, GLfloat* params) +{ + typedef void (QGLF_APIENTRYP type_glGetUniformfv)(GLuint program, GLint location, GLfloat* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getUniformfv = (type_glGetUniformfv) + context->getProcAddress(QLatin1String("glGetUniformfv")); + if (!funcs->getUniformfv) { + funcs->getUniformfv = (type_glGetUniformfv) + context->getProcAddress(QLatin1String("glGetUniformfvARB")); + } + + if (funcs->getUniformfv) + funcs->getUniformfv(program, location, params); + else + funcs->getUniformfv = qglfResolveGetUniformfv; +} + +static void qglfResolveGetUniformiv(GLuint program, GLint location, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetUniformiv)(GLuint program, GLint location, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getUniformiv = (type_glGetUniformiv) + context->getProcAddress(QLatin1String("glGetUniformiv")); + if (!funcs->getUniformiv) { + funcs->getUniformiv = (type_glGetUniformiv) + context->getProcAddress(QLatin1String("glGetUniformivARB")); + } + + if (funcs->getUniformiv) + funcs->getUniformiv(program, location, params); + else + funcs->getUniformiv = qglfResolveGetUniformiv; +} + +static int qglfResolveGetUniformLocation(GLuint program, const char* name) +{ + typedef int (QGLF_APIENTRYP type_glGetUniformLocation)(GLuint program, const char* name); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getUniformLocation = (type_glGetUniformLocation) + context->getProcAddress(QLatin1String("glGetUniformLocation")); + if (!funcs->getUniformLocation) { + funcs->getUniformLocation = (type_glGetUniformLocation) + context->getProcAddress(QLatin1String("glGetUniformLocationARB")); + } + + if (funcs->getUniformLocation) + return funcs->getUniformLocation(program, name); + funcs->getUniformLocation = qglfResolveGetUniformLocation; + return int(0); +} + +static void qglfResolveGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) +{ + typedef void (QGLF_APIENTRYP type_glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getVertexAttribfv = (type_glGetVertexAttribfv) + context->getProcAddress(QLatin1String("glGetVertexAttribfv")); + if (!funcs->getVertexAttribfv) { + funcs->getVertexAttribfv = (type_glGetVertexAttribfv) + context->getProcAddress(QLatin1String("glGetVertexAttribfvARB")); + } + + if (funcs->getVertexAttribfv) + funcs->getVertexAttribfv(index, pname, params); + else + funcs->getVertexAttribfv = qglfResolveGetVertexAttribfv; +} + +static void qglfResolveGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) +{ + typedef void (QGLF_APIENTRYP type_glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getVertexAttribiv = (type_glGetVertexAttribiv) + context->getProcAddress(QLatin1String("glGetVertexAttribiv")); + if (!funcs->getVertexAttribiv) { + funcs->getVertexAttribiv = (type_glGetVertexAttribiv) + context->getProcAddress(QLatin1String("glGetVertexAttribivARB")); + } + + if (funcs->getVertexAttribiv) + funcs->getVertexAttribiv(index, pname, params); + else + funcs->getVertexAttribiv = qglfResolveGetVertexAttribiv; +} + +static void qglfResolveGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer) +{ + typedef void (QGLF_APIENTRYP type_glGetVertexAttribPointerv)(GLuint index, GLenum pname, void** pointer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->getVertexAttribPointerv = (type_glGetVertexAttribPointerv) + context->getProcAddress(QLatin1String("glGetVertexAttribPointerv")); + if (!funcs->getVertexAttribPointerv) { + funcs->getVertexAttribPointerv = (type_glGetVertexAttribPointerv) + context->getProcAddress(QLatin1String("glGetVertexAttribPointervARB")); + } + + if (funcs->getVertexAttribPointerv) + funcs->getVertexAttribPointerv(index, pname, pointer); + else + funcs->getVertexAttribPointerv = qglfResolveGetVertexAttribPointerv; +} + +static GLboolean qglfResolveIsBuffer(GLuint buffer) +{ + typedef GLboolean (QGLF_APIENTRYP type_glIsBuffer)(GLuint buffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->isBuffer = (type_glIsBuffer) + context->getProcAddress(QLatin1String("glIsBuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->isBuffer) { + funcs->isBuffer = (type_glIsBuffer) + context->getProcAddress(QLatin1String("glIsBufferOES")); + } +#endif + if (!funcs->isBuffer) { + funcs->isBuffer = (type_glIsBuffer) + context->getProcAddress(QLatin1String("glIsBufferEXT")); + } + if (!funcs->isBuffer) { + funcs->isBuffer = (type_glIsBuffer) + context->getProcAddress(QLatin1String("glIsBufferARB")); + } + + if (funcs->isBuffer) + return funcs->isBuffer(buffer); + funcs->isBuffer = qglfResolveIsBuffer; + return GLboolean(0); +} + +static GLboolean qglfResolveIsFramebuffer(GLuint framebuffer) +{ + typedef GLboolean (QGLF_APIENTRYP type_glIsFramebuffer)(GLuint framebuffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->isFramebuffer = (type_glIsFramebuffer) + context->getProcAddress(QLatin1String("glIsFramebuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->isFramebuffer) { + funcs->isFramebuffer = (type_glIsFramebuffer) + context->getProcAddress(QLatin1String("glIsFramebufferOES")); + } +#endif + if (!funcs->isFramebuffer) { + funcs->isFramebuffer = (type_glIsFramebuffer) + context->getProcAddress(QLatin1String("glIsFramebufferEXT")); + } + if (!funcs->isFramebuffer) { + funcs->isFramebuffer = (type_glIsFramebuffer) + context->getProcAddress(QLatin1String("glIsFramebufferARB")); + } + + if (funcs->isFramebuffer) + return funcs->isFramebuffer(framebuffer); + funcs->isFramebuffer = qglfResolveIsFramebuffer; + return GLboolean(0); +} + +static GLboolean qglfSpecialIsProgram(GLuint program) +{ + return program != 0; +} + +static GLboolean qglfResolveIsProgram(GLuint program) +{ + typedef GLboolean (QGLF_APIENTRYP type_glIsProgram)(GLuint program); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->isProgram = (type_glIsProgram) + context->getProcAddress(QLatin1String("glIsProgram")); + if (!funcs->isProgram) { + funcs->isProgram = (type_glIsProgram) + context->getProcAddress(QLatin1String("glIsProgramARB")); + } + + if (!funcs->isProgram) + funcs->isProgram = qglfSpecialIsProgram; + + return funcs->isProgram(program); +} + +static GLboolean qglfResolveIsRenderbuffer(GLuint renderbuffer) +{ + typedef GLboolean (QGLF_APIENTRYP type_glIsRenderbuffer)(GLuint renderbuffer); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->isRenderbuffer = (type_glIsRenderbuffer) + context->getProcAddress(QLatin1String("glIsRenderbuffer")); +#ifdef QT_OPENGL_ES + if (!funcs->isRenderbuffer) { + funcs->isRenderbuffer = (type_glIsRenderbuffer) + context->getProcAddress(QLatin1String("glIsRenderbufferOES")); + } +#endif + if (!funcs->isRenderbuffer) { + funcs->isRenderbuffer = (type_glIsRenderbuffer) + context->getProcAddress(QLatin1String("glIsRenderbufferEXT")); + } + if (!funcs->isRenderbuffer) { + funcs->isRenderbuffer = (type_glIsRenderbuffer) + context->getProcAddress(QLatin1String("glIsRenderbufferARB")); + } + + if (funcs->isRenderbuffer) + return funcs->isRenderbuffer(renderbuffer); + funcs->isRenderbuffer = qglfResolveIsRenderbuffer; + return GLboolean(0); +} + +static GLboolean qglfSpecialIsShader(GLuint shader) +{ + return shader != 0; +} + +static GLboolean qglfResolveIsShader(GLuint shader) +{ + typedef GLboolean (QGLF_APIENTRYP type_glIsShader)(GLuint shader); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->isShader = (type_glIsShader) + context->getProcAddress(QLatin1String("glIsShader")); + if (!funcs->isShader) { + funcs->isShader = (type_glIsShader) + context->getProcAddress(QLatin1String("glIsShaderARB")); + } + + if (!funcs->isShader) + funcs->isShader = qglfSpecialIsShader; + + return funcs->isShader(shader); +} + +static void qglfResolveLinkProgram(GLuint program) +{ + typedef void (QGLF_APIENTRYP type_glLinkProgram)(GLuint program); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->linkProgram = (type_glLinkProgram) + context->getProcAddress(QLatin1String("glLinkProgram")); + if (!funcs->linkProgram) { + funcs->linkProgram = (type_glLinkProgram) + context->getProcAddress(QLatin1String("glLinkProgramARB")); + } + + if (funcs->linkProgram) + funcs->linkProgram(program); + else + funcs->linkProgram = qglfResolveLinkProgram; +} + +static void qglfSpecialReleaseShaderCompiler() +{ +} + +static void qglfResolveReleaseShaderCompiler() +{ + typedef void (QGLF_APIENTRYP type_glReleaseShaderCompiler)(); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->releaseShaderCompiler = (type_glReleaseShaderCompiler) + context->getProcAddress(QLatin1String("glReleaseShaderCompiler")); + if (!funcs->releaseShaderCompiler) { + funcs->releaseShaderCompiler = (type_glReleaseShaderCompiler) + context->getProcAddress(QLatin1String("glReleaseShaderCompilerARB")); + } + + if (!funcs->releaseShaderCompiler) + funcs->releaseShaderCompiler = qglfSpecialReleaseShaderCompiler; + + funcs->releaseShaderCompiler(); +} + +static void qglfResolveRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ + typedef void (QGLF_APIENTRYP type_glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->renderbufferStorage = (type_glRenderbufferStorage) + context->getProcAddress(QLatin1String("glRenderbufferStorage")); +#ifdef QT_OPENGL_ES + if (!funcs->renderbufferStorage) { + funcs->renderbufferStorage = (type_glRenderbufferStorage) + context->getProcAddress(QLatin1String("glRenderbufferStorageOES")); + } +#endif + if (!funcs->renderbufferStorage) { + funcs->renderbufferStorage = (type_glRenderbufferStorage) + context->getProcAddress(QLatin1String("glRenderbufferStorageEXT")); + } + if (!funcs->renderbufferStorage) { + funcs->renderbufferStorage = (type_glRenderbufferStorage) + context->getProcAddress(QLatin1String("glRenderbufferStorageARB")); + } + + if (funcs->renderbufferStorage) + funcs->renderbufferStorage(target, internalformat, width, height); + else + funcs->renderbufferStorage = qglfResolveRenderbufferStorage; +} + +static void qglfResolveSampleCoverage(GLclampf value, GLboolean invert) +{ + typedef void (QGLF_APIENTRYP type_glSampleCoverage)(GLclampf value, GLboolean invert); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->sampleCoverage = (type_glSampleCoverage) + context->getProcAddress(QLatin1String("glSampleCoverage")); +#ifdef QT_OPENGL_ES + if (!funcs->sampleCoverage) { + funcs->sampleCoverage = (type_glSampleCoverage) + context->getProcAddress(QLatin1String("glSampleCoverageOES")); + } +#endif + if (!funcs->sampleCoverage) { + funcs->sampleCoverage = (type_glSampleCoverage) + context->getProcAddress(QLatin1String("glSampleCoverageEXT")); + } + if (!funcs->sampleCoverage) { + funcs->sampleCoverage = (type_glSampleCoverage) + context->getProcAddress(QLatin1String("glSampleCoverageARB")); + } + + if (funcs->sampleCoverage) + funcs->sampleCoverage(value, invert); + else + funcs->sampleCoverage = qglfResolveSampleCoverage; +} + +static void qglfResolveShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length) +{ + typedef void (QGLF_APIENTRYP type_glShaderBinary)(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->shaderBinary = (type_glShaderBinary) + context->getProcAddress(QLatin1String("glShaderBinary")); + if (!funcs->shaderBinary) { + funcs->shaderBinary = (type_glShaderBinary) + context->getProcAddress(QLatin1String("glShaderBinaryARB")); + } + + if (funcs->shaderBinary) + funcs->shaderBinary(n, shaders, binaryformat, binary, length); + else + funcs->shaderBinary = qglfResolveShaderBinary; +} + +static void qglfResolveShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length) +{ + typedef void (QGLF_APIENTRYP type_glShaderSource)(GLuint shader, GLsizei count, const char** string, const GLint* length); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->shaderSource = (type_glShaderSource) + context->getProcAddress(QLatin1String("glShaderSource")); + if (!funcs->shaderSource) { + funcs->shaderSource = (type_glShaderSource) + context->getProcAddress(QLatin1String("glShaderSourceARB")); + } + + if (funcs->shaderSource) + funcs->shaderSource(shader, count, string, length); + else + funcs->shaderSource = qglfResolveShaderSource; +} + +static void qglfResolveStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +{ + typedef void (QGLF_APIENTRYP type_glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->stencilFuncSeparate = (type_glStencilFuncSeparate) + context->getProcAddress(QLatin1String("glStencilFuncSeparate")); +#ifdef QT_OPENGL_ES + if (!funcs->stencilFuncSeparate) { + funcs->stencilFuncSeparate = (type_glStencilFuncSeparate) + context->getProcAddress(QLatin1String("glStencilFuncSeparateOES")); + } +#endif + if (!funcs->stencilFuncSeparate) { + funcs->stencilFuncSeparate = (type_glStencilFuncSeparate) + context->getProcAddress(QLatin1String("glStencilFuncSeparateEXT")); + } + if (!funcs->stencilFuncSeparate) { + funcs->stencilFuncSeparate = (type_glStencilFuncSeparate) + context->getProcAddress(QLatin1String("glStencilFuncSeparateARB")); + } + + if (funcs->stencilFuncSeparate) + funcs->stencilFuncSeparate(face, func, ref, mask); + else + funcs->stencilFuncSeparate = qglfResolveStencilFuncSeparate; +} + +static void qglfResolveStencilMaskSeparate(GLenum face, GLuint mask) +{ + typedef void (QGLF_APIENTRYP type_glStencilMaskSeparate)(GLenum face, GLuint mask); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->stencilMaskSeparate = (type_glStencilMaskSeparate) + context->getProcAddress(QLatin1String("glStencilMaskSeparate")); +#ifdef QT_OPENGL_ES + if (!funcs->stencilMaskSeparate) { + funcs->stencilMaskSeparate = (type_glStencilMaskSeparate) + context->getProcAddress(QLatin1String("glStencilMaskSeparateOES")); + } +#endif + if (!funcs->stencilMaskSeparate) { + funcs->stencilMaskSeparate = (type_glStencilMaskSeparate) + context->getProcAddress(QLatin1String("glStencilMaskSeparateEXT")); + } + if (!funcs->stencilMaskSeparate) { + funcs->stencilMaskSeparate = (type_glStencilMaskSeparate) + context->getProcAddress(QLatin1String("glStencilMaskSeparateARB")); + } + + if (funcs->stencilMaskSeparate) + funcs->stencilMaskSeparate(face, mask); + else + funcs->stencilMaskSeparate = qglfResolveStencilMaskSeparate; +} + +static void qglfResolveStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ + typedef void (QGLF_APIENTRYP type_glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->stencilOpSeparate = (type_glStencilOpSeparate) + context->getProcAddress(QLatin1String("glStencilOpSeparate")); +#ifdef QT_OPENGL_ES + if (!funcs->stencilOpSeparate) { + funcs->stencilOpSeparate = (type_glStencilOpSeparate) + context->getProcAddress(QLatin1String("glStencilOpSeparateOES")); + } +#endif + if (!funcs->stencilOpSeparate) { + funcs->stencilOpSeparate = (type_glStencilOpSeparate) + context->getProcAddress(QLatin1String("glStencilOpSeparateEXT")); + } + if (!funcs->stencilOpSeparate) { + funcs->stencilOpSeparate = (type_glStencilOpSeparate) + context->getProcAddress(QLatin1String("glStencilOpSeparateARB")); + } + + if (funcs->stencilOpSeparate) + funcs->stencilOpSeparate(face, fail, zfail, zpass); + else + funcs->stencilOpSeparate = qglfResolveStencilOpSeparate; +} + +static void qglfResolveUniform1f(GLint location, GLfloat x) +{ + typedef void (QGLF_APIENTRYP type_glUniform1f)(GLint location, GLfloat x); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform1f = (type_glUniform1f) + context->getProcAddress(QLatin1String("glUniform1f")); + if (!funcs->uniform1f) { + funcs->uniform1f = (type_glUniform1f) + context->getProcAddress(QLatin1String("glUniform1fARB")); + } + + if (funcs->uniform1f) + funcs->uniform1f(location, x); + else + funcs->uniform1f = qglfResolveUniform1f; +} + +static void qglfResolveUniform1fv(GLint location, GLsizei count, const GLfloat* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform1fv)(GLint location, GLsizei count, const GLfloat* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform1fv = (type_glUniform1fv) + context->getProcAddress(QLatin1String("glUniform1fv")); + if (!funcs->uniform1fv) { + funcs->uniform1fv = (type_glUniform1fv) + context->getProcAddress(QLatin1String("glUniform1fvARB")); + } + + if (funcs->uniform1fv) + funcs->uniform1fv(location, count, v); + else + funcs->uniform1fv = qglfResolveUniform1fv; +} + +static void qglfResolveUniform1i(GLint location, GLint x) +{ + typedef void (QGLF_APIENTRYP type_glUniform1i)(GLint location, GLint x); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform1i = (type_glUniform1i) + context->getProcAddress(QLatin1String("glUniform1i")); + if (!funcs->uniform1i) { + funcs->uniform1i = (type_glUniform1i) + context->getProcAddress(QLatin1String("glUniform1iARB")); + } + + if (funcs->uniform1i) + funcs->uniform1i(location, x); + else + funcs->uniform1i = qglfResolveUniform1i; +} + +static void qglfResolveUniform1iv(GLint location, GLsizei count, const GLint* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform1iv)(GLint location, GLsizei count, const GLint* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform1iv = (type_glUniform1iv) + context->getProcAddress(QLatin1String("glUniform1iv")); + if (!funcs->uniform1iv) { + funcs->uniform1iv = (type_glUniform1iv) + context->getProcAddress(QLatin1String("glUniform1ivARB")); + } + + if (funcs->uniform1iv) + funcs->uniform1iv(location, count, v); + else + funcs->uniform1iv = qglfResolveUniform1iv; +} + +static void qglfResolveUniform2f(GLint location, GLfloat x, GLfloat y) +{ + typedef void (QGLF_APIENTRYP type_glUniform2f)(GLint location, GLfloat x, GLfloat y); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform2f = (type_glUniform2f) + context->getProcAddress(QLatin1String("glUniform2f")); + if (!funcs->uniform2f) { + funcs->uniform2f = (type_glUniform2f) + context->getProcAddress(QLatin1String("glUniform2fARB")); + } + + if (funcs->uniform2f) + funcs->uniform2f(location, x, y); + else + funcs->uniform2f = qglfResolveUniform2f; +} + +static void qglfResolveUniform2fv(GLint location, GLsizei count, const GLfloat* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform2fv)(GLint location, GLsizei count, const GLfloat* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform2fv = (type_glUniform2fv) + context->getProcAddress(QLatin1String("glUniform2fv")); + if (!funcs->uniform2fv) { + funcs->uniform2fv = (type_glUniform2fv) + context->getProcAddress(QLatin1String("glUniform2fvARB")); + } + + if (funcs->uniform2fv) + funcs->uniform2fv(location, count, v); + else + funcs->uniform2fv = qglfResolveUniform2fv; +} + +static void qglfResolveUniform2i(GLint location, GLint x, GLint y) +{ + typedef void (QGLF_APIENTRYP type_glUniform2i)(GLint location, GLint x, GLint y); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform2i = (type_glUniform2i) + context->getProcAddress(QLatin1String("glUniform2i")); + if (!funcs->uniform2i) { + funcs->uniform2i = (type_glUniform2i) + context->getProcAddress(QLatin1String("glUniform2iARB")); + } + + if (funcs->uniform2i) + funcs->uniform2i(location, x, y); + else + funcs->uniform2i = qglfResolveUniform2i; +} + +static void qglfResolveUniform2iv(GLint location, GLsizei count, const GLint* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform2iv)(GLint location, GLsizei count, const GLint* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform2iv = (type_glUniform2iv) + context->getProcAddress(QLatin1String("glUniform2iv")); + if (!funcs->uniform2iv) { + funcs->uniform2iv = (type_glUniform2iv) + context->getProcAddress(QLatin1String("glUniform2ivARB")); + } + + if (funcs->uniform2iv) + funcs->uniform2iv(location, count, v); + else + funcs->uniform2iv = qglfResolveUniform2iv; +} + +static void qglfResolveUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) +{ + typedef void (QGLF_APIENTRYP type_glUniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform3f = (type_glUniform3f) + context->getProcAddress(QLatin1String("glUniform3f")); + if (!funcs->uniform3f) { + funcs->uniform3f = (type_glUniform3f) + context->getProcAddress(QLatin1String("glUniform3fARB")); + } + + if (funcs->uniform3f) + funcs->uniform3f(location, x, y, z); + else + funcs->uniform3f = qglfResolveUniform3f; +} + +static void qglfResolveUniform3fv(GLint location, GLsizei count, const GLfloat* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform3fv)(GLint location, GLsizei count, const GLfloat* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform3fv = (type_glUniform3fv) + context->getProcAddress(QLatin1String("glUniform3fv")); + if (!funcs->uniform3fv) { + funcs->uniform3fv = (type_glUniform3fv) + context->getProcAddress(QLatin1String("glUniform3fvARB")); + } + + if (funcs->uniform3fv) + funcs->uniform3fv(location, count, v); + else + funcs->uniform3fv = qglfResolveUniform3fv; +} + +static void qglfResolveUniform3i(GLint location, GLint x, GLint y, GLint z) +{ + typedef void (QGLF_APIENTRYP type_glUniform3i)(GLint location, GLint x, GLint y, GLint z); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform3i = (type_glUniform3i) + context->getProcAddress(QLatin1String("glUniform3i")); + if (!funcs->uniform3i) { + funcs->uniform3i = (type_glUniform3i) + context->getProcAddress(QLatin1String("glUniform3iARB")); + } + + if (funcs->uniform3i) + funcs->uniform3i(location, x, y, z); + else + funcs->uniform3i = qglfResolveUniform3i; +} + +static void qglfResolveUniform3iv(GLint location, GLsizei count, const GLint* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform3iv)(GLint location, GLsizei count, const GLint* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform3iv = (type_glUniform3iv) + context->getProcAddress(QLatin1String("glUniform3iv")); + if (!funcs->uniform3iv) { + funcs->uniform3iv = (type_glUniform3iv) + context->getProcAddress(QLatin1String("glUniform3ivARB")); + } + + if (funcs->uniform3iv) + funcs->uniform3iv(location, count, v); + else + funcs->uniform3iv = qglfResolveUniform3iv; +} + +static void qglfResolveUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + typedef void (QGLF_APIENTRYP type_glUniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform4f = (type_glUniform4f) + context->getProcAddress(QLatin1String("glUniform4f")); + if (!funcs->uniform4f) { + funcs->uniform4f = (type_glUniform4f) + context->getProcAddress(QLatin1String("glUniform4fARB")); + } + + if (funcs->uniform4f) + funcs->uniform4f(location, x, y, z, w); + else + funcs->uniform4f = qglfResolveUniform4f; +} + +static void qglfResolveUniform4fv(GLint location, GLsizei count, const GLfloat* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform4fv)(GLint location, GLsizei count, const GLfloat* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform4fv = (type_glUniform4fv) + context->getProcAddress(QLatin1String("glUniform4fv")); + if (!funcs->uniform4fv) { + funcs->uniform4fv = (type_glUniform4fv) + context->getProcAddress(QLatin1String("glUniform4fvARB")); + } + + if (funcs->uniform4fv) + funcs->uniform4fv(location, count, v); + else + funcs->uniform4fv = qglfResolveUniform4fv; +} + +static void qglfResolveUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) +{ + typedef void (QGLF_APIENTRYP type_glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform4i = (type_glUniform4i) + context->getProcAddress(QLatin1String("glUniform4i")); + if (!funcs->uniform4i) { + funcs->uniform4i = (type_glUniform4i) + context->getProcAddress(QLatin1String("glUniform4iARB")); + } + + if (funcs->uniform4i) + funcs->uniform4i(location, x, y, z, w); + else + funcs->uniform4i = qglfResolveUniform4i; +} + +static void qglfResolveUniform4iv(GLint location, GLsizei count, const GLint* v) +{ + typedef void (QGLF_APIENTRYP type_glUniform4iv)(GLint location, GLsizei count, const GLint* v); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniform4iv = (type_glUniform4iv) + context->getProcAddress(QLatin1String("glUniform4iv")); + if (!funcs->uniform4iv) { + funcs->uniform4iv = (type_glUniform4iv) + context->getProcAddress(QLatin1String("glUniform4ivARB")); + } + + if (funcs->uniform4iv) + funcs->uniform4iv(location, count, v); + else + funcs->uniform4iv = qglfResolveUniform4iv; +} + +static void qglfResolveUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + typedef void (QGLF_APIENTRYP type_glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniformMatrix2fv = (type_glUniformMatrix2fv) + context->getProcAddress(QLatin1String("glUniformMatrix2fv")); + if (!funcs->uniformMatrix2fv) { + funcs->uniformMatrix2fv = (type_glUniformMatrix2fv) + context->getProcAddress(QLatin1String("glUniformMatrix2fvARB")); + } + + if (funcs->uniformMatrix2fv) + funcs->uniformMatrix2fv(location, count, transpose, value); + else + funcs->uniformMatrix2fv = qglfResolveUniformMatrix2fv; +} + +static void qglfResolveUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + typedef void (QGLF_APIENTRYP type_glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniformMatrix3fv = (type_glUniformMatrix3fv) + context->getProcAddress(QLatin1String("glUniformMatrix3fv")); + if (!funcs->uniformMatrix3fv) { + funcs->uniformMatrix3fv = (type_glUniformMatrix3fv) + context->getProcAddress(QLatin1String("glUniformMatrix3fvARB")); + } + + if (funcs->uniformMatrix3fv) + funcs->uniformMatrix3fv(location, count, transpose, value); + else + funcs->uniformMatrix3fv = qglfResolveUniformMatrix3fv; +} + +static void qglfResolveUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + typedef void (QGLF_APIENTRYP type_glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->uniformMatrix4fv = (type_glUniformMatrix4fv) + context->getProcAddress(QLatin1String("glUniformMatrix4fv")); + if (!funcs->uniformMatrix4fv) { + funcs->uniformMatrix4fv = (type_glUniformMatrix4fv) + context->getProcAddress(QLatin1String("glUniformMatrix4fvARB")); + } + + if (funcs->uniformMatrix4fv) + funcs->uniformMatrix4fv(location, count, transpose, value); + else + funcs->uniformMatrix4fv = qglfResolveUniformMatrix4fv; +} + +static void qglfResolveUseProgram(GLuint program) +{ + typedef void (QGLF_APIENTRYP type_glUseProgram)(GLuint program); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->useProgram = (type_glUseProgram) + context->getProcAddress(QLatin1String("glUseProgram")); + if (!funcs->useProgram) { + funcs->useProgram = (type_glUseProgram) + context->getProcAddress(QLatin1String("glUseProgramObjectARB")); + } + + if (funcs->useProgram) + funcs->useProgram(program); + else + funcs->useProgram = qglfResolveUseProgram; +} + +static void qglfResolveValidateProgram(GLuint program) +{ + typedef void (QGLF_APIENTRYP type_glValidateProgram)(GLuint program); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->validateProgram = (type_glValidateProgram) + context->getProcAddress(QLatin1String("glValidateProgram")); + if (!funcs->validateProgram) { + funcs->validateProgram = (type_glValidateProgram) + context->getProcAddress(QLatin1String("glValidateProgramARB")); + } + + if (funcs->validateProgram) + funcs->validateProgram(program); + else + funcs->validateProgram = qglfResolveValidateProgram; +} + +static void qglfResolveVertexAttrib1f(GLuint indx, GLfloat x) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib1f)(GLuint indx, GLfloat x); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib1f = (type_glVertexAttrib1f) + context->getProcAddress(QLatin1String("glVertexAttrib1f")); + if (!funcs->vertexAttrib1f) { + funcs->vertexAttrib1f = (type_glVertexAttrib1f) + context->getProcAddress(QLatin1String("glVertexAttrib1fARB")); + } + + if (funcs->vertexAttrib1f) + funcs->vertexAttrib1f(indx, x); + else + funcs->vertexAttrib1f = qglfResolveVertexAttrib1f; +} + +static void qglfResolveVertexAttrib1fv(GLuint indx, const GLfloat* values) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib1fv)(GLuint indx, const GLfloat* values); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib1fv = (type_glVertexAttrib1fv) + context->getProcAddress(QLatin1String("glVertexAttrib1fv")); + if (!funcs->vertexAttrib1fv) { + funcs->vertexAttrib1fv = (type_glVertexAttrib1fv) + context->getProcAddress(QLatin1String("glVertexAttrib1fvARB")); + } + + if (funcs->vertexAttrib1fv) + funcs->vertexAttrib1fv(indx, values); + else + funcs->vertexAttrib1fv = qglfResolveVertexAttrib1fv; +} + +static void qglfResolveVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib2f = (type_glVertexAttrib2f) + context->getProcAddress(QLatin1String("glVertexAttrib2f")); + if (!funcs->vertexAttrib2f) { + funcs->vertexAttrib2f = (type_glVertexAttrib2f) + context->getProcAddress(QLatin1String("glVertexAttrib2fARB")); + } + + if (funcs->vertexAttrib2f) + funcs->vertexAttrib2f(indx, x, y); + else + funcs->vertexAttrib2f = qglfResolveVertexAttrib2f; +} + +static void qglfResolveVertexAttrib2fv(GLuint indx, const GLfloat* values) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib2fv)(GLuint indx, const GLfloat* values); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib2fv = (type_glVertexAttrib2fv) + context->getProcAddress(QLatin1String("glVertexAttrib2fv")); + if (!funcs->vertexAttrib2fv) { + funcs->vertexAttrib2fv = (type_glVertexAttrib2fv) + context->getProcAddress(QLatin1String("glVertexAttrib2fvARB")); + } + + if (funcs->vertexAttrib2fv) + funcs->vertexAttrib2fv(indx, values); + else + funcs->vertexAttrib2fv = qglfResolveVertexAttrib2fv; +} + +static void qglfResolveVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib3f = (type_glVertexAttrib3f) + context->getProcAddress(QLatin1String("glVertexAttrib3f")); + if (!funcs->vertexAttrib3f) { + funcs->vertexAttrib3f = (type_glVertexAttrib3f) + context->getProcAddress(QLatin1String("glVertexAttrib3fARB")); + } + + if (funcs->vertexAttrib3f) + funcs->vertexAttrib3f(indx, x, y, z); + else + funcs->vertexAttrib3f = qglfResolveVertexAttrib3f; +} + +static void qglfResolveVertexAttrib3fv(GLuint indx, const GLfloat* values) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib3fv)(GLuint indx, const GLfloat* values); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib3fv = (type_glVertexAttrib3fv) + context->getProcAddress(QLatin1String("glVertexAttrib3fv")); + if (!funcs->vertexAttrib3fv) { + funcs->vertexAttrib3fv = (type_glVertexAttrib3fv) + context->getProcAddress(QLatin1String("glVertexAttrib3fvARB")); + } + + if (funcs->vertexAttrib3fv) + funcs->vertexAttrib3fv(indx, values); + else + funcs->vertexAttrib3fv = qglfResolveVertexAttrib3fv; +} + +static void qglfResolveVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib4f = (type_glVertexAttrib4f) + context->getProcAddress(QLatin1String("glVertexAttrib4f")); + if (!funcs->vertexAttrib4f) { + funcs->vertexAttrib4f = (type_glVertexAttrib4f) + context->getProcAddress(QLatin1String("glVertexAttrib4fARB")); + } + + if (funcs->vertexAttrib4f) + funcs->vertexAttrib4f(indx, x, y, z, w); + else + funcs->vertexAttrib4f = qglfResolveVertexAttrib4f; +} + +static void qglfResolveVertexAttrib4fv(GLuint indx, const GLfloat* values) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttrib4fv)(GLuint indx, const GLfloat* values); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttrib4fv = (type_glVertexAttrib4fv) + context->getProcAddress(QLatin1String("glVertexAttrib4fv")); + if (!funcs->vertexAttrib4fv) { + funcs->vertexAttrib4fv = (type_glVertexAttrib4fv) + context->getProcAddress(QLatin1String("glVertexAttrib4fvARB")); + } + + if (funcs->vertexAttrib4fv) + funcs->vertexAttrib4fv(indx, values); + else + funcs->vertexAttrib4fv = qglfResolveVertexAttrib4fv; +} + +static void qglfResolveVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) +{ + typedef void (QGLF_APIENTRYP type_glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr); + + const QGLContext *context = QGLContext::currentContext(); + QGLFunctionsPrivate *funcs = qt_gl_functions(context); + + funcs->vertexAttribPointer = (type_glVertexAttribPointer) + context->getProcAddress(QLatin1String("glVertexAttribPointer")); + if (!funcs->vertexAttribPointer) { + funcs->vertexAttribPointer = (type_glVertexAttribPointer) + context->getProcAddress(QLatin1String("glVertexAttribPointerARB")); + } + + if (funcs->vertexAttribPointer) + funcs->vertexAttribPointer(indx, size, type, normalized, stride, ptr); + else + funcs->vertexAttribPointer = qglfResolveVertexAttribPointer; +} + +#endif // !QT_OPENGL_ES_2 + +QGLFunctionsPrivate::QGLFunctionsPrivate(const QGLContext *) +{ +#ifndef QT_OPENGL_ES_2 + activeTexture = qglfResolveActiveTexture; + attachShader = qglfResolveAttachShader; + bindAttribLocation = qglfResolveBindAttribLocation; + bindBuffer = qglfResolveBindBuffer; + bindFramebuffer = qglfResolveBindFramebuffer; + bindRenderbuffer = qglfResolveBindRenderbuffer; + blendColor = qglfResolveBlendColor; + blendEquation = qglfResolveBlendEquation; + blendEquationSeparate = qglfResolveBlendEquationSeparate; + blendFuncSeparate = qglfResolveBlendFuncSeparate; + bufferData = qglfResolveBufferData; + bufferSubData = qglfResolveBufferSubData; + checkFramebufferStatus = qglfResolveCheckFramebufferStatus; + compileShader = qglfResolveCompileShader; + compressedTexImage2D = qglfResolveCompressedTexImage2D; + compressedTexSubImage2D = qglfResolveCompressedTexSubImage2D; + createProgram = qglfResolveCreateProgram; + createShader = qglfResolveCreateShader; + deleteBuffers = qglfResolveDeleteBuffers; + deleteFramebuffers = qglfResolveDeleteFramebuffers; + deleteProgram = qglfResolveDeleteProgram; + deleteRenderbuffers = qglfResolveDeleteRenderbuffers; + deleteShader = qglfResolveDeleteShader; + detachShader = qglfResolveDetachShader; + disableVertexAttribArray = qglfResolveDisableVertexAttribArray; + enableVertexAttribArray = qglfResolveEnableVertexAttribArray; + framebufferRenderbuffer = qglfResolveFramebufferRenderbuffer; + framebufferTexture2D = qglfResolveFramebufferTexture2D; + genBuffers = qglfResolveGenBuffers; + generateMipmap = qglfResolveGenerateMipmap; + genFramebuffers = qglfResolveGenFramebuffers; + genRenderbuffers = qglfResolveGenRenderbuffers; + getActiveAttrib = qglfResolveGetActiveAttrib; + getActiveUniform = qglfResolveGetActiveUniform; + getAttachedShaders = qglfResolveGetAttachedShaders; + getAttribLocation = qglfResolveGetAttribLocation; + getBufferParameteriv = qglfResolveGetBufferParameteriv; + getFramebufferAttachmentParameteriv = qglfResolveGetFramebufferAttachmentParameteriv; + getProgramiv = qglfResolveGetProgramiv; + getProgramInfoLog = qglfResolveGetProgramInfoLog; + getRenderbufferParameteriv = qglfResolveGetRenderbufferParameteriv; + getShaderiv = qglfResolveGetShaderiv; + getShaderInfoLog = qglfResolveGetShaderInfoLog; + getShaderPrecisionFormat = qglfResolveGetShaderPrecisionFormat; + getShaderSource = qglfResolveGetShaderSource; + getUniformfv = qglfResolveGetUniformfv; + getUniformiv = qglfResolveGetUniformiv; + getUniformLocation = qglfResolveGetUniformLocation; + getVertexAttribfv = qglfResolveGetVertexAttribfv; + getVertexAttribiv = qglfResolveGetVertexAttribiv; + getVertexAttribPointerv = qglfResolveGetVertexAttribPointerv; + isBuffer = qglfResolveIsBuffer; + isFramebuffer = qglfResolveIsFramebuffer; + isProgram = qglfResolveIsProgram; + isRenderbuffer = qglfResolveIsRenderbuffer; + isShader = qglfResolveIsShader; + linkProgram = qglfResolveLinkProgram; + releaseShaderCompiler = qglfResolveReleaseShaderCompiler; + renderbufferStorage = qglfResolveRenderbufferStorage; + sampleCoverage = qglfResolveSampleCoverage; + shaderBinary = qglfResolveShaderBinary; + shaderSource = qglfResolveShaderSource; + stencilFuncSeparate = qglfResolveStencilFuncSeparate; + stencilMaskSeparate = qglfResolveStencilMaskSeparate; + stencilOpSeparate = qglfResolveStencilOpSeparate; + uniform1f = qglfResolveUniform1f; + uniform1fv = qglfResolveUniform1fv; + uniform1i = qglfResolveUniform1i; + uniform1iv = qglfResolveUniform1iv; + uniform2f = qglfResolveUniform2f; + uniform2fv = qglfResolveUniform2fv; + uniform2i = qglfResolveUniform2i; + uniform2iv = qglfResolveUniform2iv; + uniform3f = qglfResolveUniform3f; + uniform3fv = qglfResolveUniform3fv; + uniform3i = qglfResolveUniform3i; + uniform3iv = qglfResolveUniform3iv; + uniform4f = qglfResolveUniform4f; + uniform4fv = qglfResolveUniform4fv; + uniform4i = qglfResolveUniform4i; + uniform4iv = qglfResolveUniform4iv; + uniformMatrix2fv = qglfResolveUniformMatrix2fv; + uniformMatrix3fv = qglfResolveUniformMatrix3fv; + uniformMatrix4fv = qglfResolveUniformMatrix4fv; + useProgram = qglfResolveUseProgram; + validateProgram = qglfResolveValidateProgram; + vertexAttrib1f = qglfResolveVertexAttrib1f; + vertexAttrib1fv = qglfResolveVertexAttrib1fv; + vertexAttrib2f = qglfResolveVertexAttrib2f; + vertexAttrib2fv = qglfResolveVertexAttrib2fv; + vertexAttrib3f = qglfResolveVertexAttrib3f; + vertexAttrib3fv = qglfResolveVertexAttrib3fv; + vertexAttrib4f = qglfResolveVertexAttrib4f; + vertexAttrib4fv = qglfResolveVertexAttrib4fv; + vertexAttribPointer = qglfResolveVertexAttribPointer; +#endif // !QT_OPENGL_ES_2 +} + +QT_END_NAMESPACE diff --git a/src/opengl/qglfunctions.h b/src/opengl/qglfunctions.h new file mode 100644 index 0000000..e06de7f --- /dev/null +++ b/src/opengl/qglfunctions.h @@ -0,0 +1,2290 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QGLFUNCTIONS_H +#define QGLFUNCTIONS_H + +#include <QtOpenGL/qgl.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(OpenGL) + +// Types that aren't defined in all system's gl.h files. +typedef ptrdiff_t qgl_GLintptr; +typedef ptrdiff_t qgl_GLsizeiptr; + +#ifndef Q_WS_MAC +# ifndef QGLF_APIENTRYP +# ifdef QGLF_APIENTRY +# define QGLF_APIENTRYP QGLF_APIENTRY * +# else +# define QGLF_APIENTRY +# define QGLF_APIENTRYP * +# endif +# endif +#else +# define QGLF_APIENTRY +# define QGLF_APIENTRYP * +#endif + +struct QGLFunctionsPrivate; + +// Undefine any macros from GLEW, qglextensions_p.h, etc that +// may interfere with the definition of QGLFunctions. +#undef glActiveTexture +#undef glAttachShader +#undef glBindAttribLocation +#undef glBindBuffer +#undef glBindFramebuffer +#undef glBindRenderbuffer +#undef glBlendColor +#undef glBlendEquation +#undef glBlendEquationSeparate +#undef glBlendFuncSeparate +#undef glBufferData +#undef glBufferSubData +#undef glCheckFramebufferStatus +#undef glClearDepthf +#undef glCompileShader +#undef glCompressedTexImage2D +#undef glCompressedTexSubImage2D +#undef glCreateProgram +#undef glCreateShader +#undef glDeleteBuffers +#undef glDeleteFramebuffers +#undef glDeleteProgram +#undef glDeleteRenderbuffers +#undef glDeleteShader +#undef glDepthRangef +#undef glDetachShader +#undef glDisableVertexAttribArray +#undef glEnableVertexAttribArray +#undef glFramebufferRenderbuffer +#undef glFramebufferTexture2D +#undef glGenBuffers +#undef glGenerateMipmap +#undef glGenFramebuffers +#undef glGenRenderbuffers +#undef glGetActiveAttrib +#undef glGetActiveUniform +#undef glGetAttachedShaders +#undef glGetAttribLocation +#undef glGetBufferParameteriv +#undef glGetFramebufferAttachmentParameteriv +#undef glGetProgramiv +#undef glGetProgramInfoLog +#undef glGetRenderbufferParameteriv +#undef glGetShaderiv +#undef glGetShaderInfoLog +#undef glGetShaderPrecisionFormat +#undef glGetShaderSource +#undef glGetUniformfv +#undef glGetUniformiv +#undef glGetUniformLocation +#undef glGetVertexAttribfv +#undef glGetVertexAttribiv +#undef glGetVertexAttribPointerv +#undef glIsBuffer +#undef glIsFramebuffer +#undef glIsProgram +#undef glIsRenderbuffer +#undef glIsShader +#undef glLinkProgram +#undef glReleaseShaderCompiler +#undef glRenderbufferStorage +#undef glSampleCoverage +#undef glShaderBinary +#undef glShaderSource +#undef glStencilFuncSeparate +#undef glStencilMaskSeparate +#undef glStencilOpSeparate +#undef glUniform1f +#undef glUniform1fv +#undef glUniform1i +#undef glUniform1iv +#undef glUniform2f +#undef glUniform2fv +#undef glUniform2i +#undef glUniform2iv +#undef glUniform3f +#undef glUniform3fv +#undef glUniform3i +#undef glUniform3iv +#undef glUniform4f +#undef glUniform4fv +#undef glUniform4i +#undef glUniform4iv +#undef glUniformMatrix2fv +#undef glUniformMatrix3fv +#undef glUniformMatrix4fv +#undef glUseProgram +#undef glValidateProgram +#undef glVertexAttrib1f +#undef glVertexAttrib1fv +#undef glVertexAttrib2f +#undef glVertexAttrib2fv +#undef glVertexAttrib3f +#undef glVertexAttrib3fv +#undef glVertexAttrib4f +#undef glVertexAttrib4fv +#undef glVertexAttribPointer + +class Q_OPENGL_EXPORT QGLFunctions +{ +public: + QGLFunctions(); + explicit QGLFunctions(const QGLContext *context); + ~QGLFunctions() {} + + enum OpenGLFeature + { + Multitexture = 0x0001, + Shaders = 0x0002, + Buffers = 0x0004, + Framebuffers = 0x0008, + BlendColor = 0x0010, + BlendEquation = 0x0020, + BlendEquationSeparate = 0x0040, + BlendFuncSeparate = 0x0080, + BlendSubtract = 0x0100, + CompressedTextures = 0x0200, + Multisample = 0x0400, + StencilSeparate = 0x0800, + NPOTTextures = 0x1000 + }; + Q_DECLARE_FLAGS(OpenGLFeatures, OpenGLFeature) + + QGLFunctions::OpenGLFeatures openGLFeatures() const; + bool hasOpenGLFeature(QGLFunctions::OpenGLFeature feature) const; + + void initializeGLFunctions(const QGLContext *context = 0); + + void glActiveTexture(GLenum texture); + void glAttachShader(GLuint program, GLuint shader); + void glBindAttribLocation(GLuint program, GLuint index, const char* name); + void glBindBuffer(GLenum target, GLuint buffer); + void glBindFramebuffer(GLenum target, GLuint framebuffer); + void glBindRenderbuffer(GLenum target, GLuint renderbuffer); + void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void glBlendEquation(GLenum mode); + void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); + void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + void glBufferData(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage); + void glBufferSubData(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data); + GLenum glCheckFramebufferStatus(GLenum target); + void glClearDepthf(GLclampf depth); + void glCompileShader(GLuint shader); + void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); + void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); + GLuint glCreateProgram(); + GLuint glCreateShader(GLenum type); + void glDeleteBuffers(GLsizei n, const GLuint* buffers); + void glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers); + void glDeleteProgram(GLuint program); + void glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers); + void glDeleteShader(GLuint shader); + void glDepthRangef(GLclampf zNear, GLclampf zFar); + void glDetachShader(GLuint program, GLuint shader); + void glDisableVertexAttribArray(GLuint index); + void glEnableVertexAttribArray(GLuint index); + void glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + void glGenBuffers(GLsizei n, GLuint* buffers); + void glGenerateMipmap(GLenum target); + void glGenFramebuffers(GLsizei n, GLuint* framebuffers); + void glGenRenderbuffers(GLsizei n, GLuint* renderbuffers); + void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + void glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); + int glGetAttribLocation(GLuint program, const char* name); + void glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params); + void glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params); + void glGetProgramiv(GLuint program, GLenum pname, GLint* params); + void glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog); + void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params); + void glGetShaderiv(GLuint shader, GLenum pname, GLint* params); + void glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog); + void glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); + void glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source); + void glGetUniformfv(GLuint program, GLint location, GLfloat* params); + void glGetUniformiv(GLuint program, GLint location, GLint* params); + int glGetUniformLocation(GLuint program, const char* name); + void glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params); + void glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params); + void glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer); + GLboolean glIsBuffer(GLuint buffer); + GLboolean glIsFramebuffer(GLuint framebuffer); + GLboolean glIsProgram(GLuint program); + GLboolean glIsRenderbuffer(GLuint renderbuffer); + GLboolean glIsShader(GLuint shader); + void glLinkProgram(GLuint program); + void glReleaseShaderCompiler(); + void glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + void glSampleCoverage(GLclampf value, GLboolean invert); + void glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length); + void glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length); + void glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); + void glStencilMaskSeparate(GLenum face, GLuint mask); + void glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); + void glUniform1f(GLint location, GLfloat x); + void glUniform1fv(GLint location, GLsizei count, const GLfloat* v); + void glUniform1i(GLint location, GLint x); + void glUniform1iv(GLint location, GLsizei count, const GLint* v); + void glUniform2f(GLint location, GLfloat x, GLfloat y); + void glUniform2fv(GLint location, GLsizei count, const GLfloat* v); + void glUniform2i(GLint location, GLint x, GLint y); + void glUniform2iv(GLint location, GLsizei count, const GLint* v); + void glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z); + void glUniform3fv(GLint location, GLsizei count, const GLfloat* v); + void glUniform3i(GLint location, GLint x, GLint y, GLint z); + void glUniform3iv(GLint location, GLsizei count, const GLint* v); + void glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void glUniform4fv(GLint location, GLsizei count, const GLfloat* v); + void glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w); + void glUniform4iv(GLint location, GLsizei count, const GLint* v); + void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void glUseProgram(GLuint program); + void glValidateProgram(GLuint program); + void glVertexAttrib1f(GLuint indx, GLfloat x); + void glVertexAttrib1fv(GLuint indx, const GLfloat* values); + void glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y); + void glVertexAttrib2fv(GLuint indx, const GLfloat* values); + void glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z); + void glVertexAttrib3fv(GLuint indx, const GLfloat* values); + void glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void glVertexAttrib4fv(GLuint indx, const GLfloat* values); + void glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr); + +private: + QGLFunctionsPrivate *d_ptr; + static bool isInitialized(const QGLFunctionsPrivate *d) { return d != 0; } +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QGLFunctions::OpenGLFeatures) + +struct QGLFunctionsPrivate +{ + QGLFunctionsPrivate(const QGLContext *context = 0); + +#ifndef QT_OPENGL_ES_2 + void (QGLF_APIENTRYP activeTexture)(GLenum texture); + void (QGLF_APIENTRYP attachShader)(GLuint program, GLuint shader); + void (QGLF_APIENTRYP bindAttribLocation)(GLuint program, GLuint index, const char* name); + void (QGLF_APIENTRYP bindBuffer)(GLenum target, GLuint buffer); + void (QGLF_APIENTRYP bindFramebuffer)(GLenum target, GLuint framebuffer); + void (QGLF_APIENTRYP bindRenderbuffer)(GLenum target, GLuint renderbuffer); + void (QGLF_APIENTRYP blendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void (QGLF_APIENTRYP blendEquation)(GLenum mode); + void (QGLF_APIENTRYP blendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha); + void (QGLF_APIENTRYP blendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + void (QGLF_APIENTRYP bufferData)(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage); + void (QGLF_APIENTRYP bufferSubData)(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data); + GLenum (QGLF_APIENTRYP checkFramebufferStatus)(GLenum target); + void (QGLF_APIENTRYP compileShader)(GLuint shader); + void (QGLF_APIENTRYP compressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); + void (QGLF_APIENTRYP compressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); + GLuint (QGLF_APIENTRYP createProgram)(); + GLuint (QGLF_APIENTRYP createShader)(GLenum type); + void (QGLF_APIENTRYP deleteBuffers)(GLsizei n, const GLuint* buffers); + void (QGLF_APIENTRYP deleteFramebuffers)(GLsizei n, const GLuint* framebuffers); + void (QGLF_APIENTRYP deleteProgram)(GLuint program); + void (QGLF_APIENTRYP deleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers); + void (QGLF_APIENTRYP deleteShader)(GLuint shader); + void (QGLF_APIENTRYP detachShader)(GLuint program, GLuint shader); + void (QGLF_APIENTRYP disableVertexAttribArray)(GLuint index); + void (QGLF_APIENTRYP enableVertexAttribArray)(GLuint index); + void (QGLF_APIENTRYP framebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + void (QGLF_APIENTRYP framebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + void (QGLF_APIENTRYP genBuffers)(GLsizei n, GLuint* buffers); + void (QGLF_APIENTRYP generateMipmap)(GLenum target); + void (QGLF_APIENTRYP genFramebuffers)(GLsizei n, GLuint* framebuffers); + void (QGLF_APIENTRYP genRenderbuffers)(GLsizei n, GLuint* renderbuffers); + void (QGLF_APIENTRYP getActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + void (QGLF_APIENTRYP getActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); + void (QGLF_APIENTRYP getAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); + int (QGLF_APIENTRYP getAttribLocation)(GLuint program, const char* name); + void (QGLF_APIENTRYP getBufferParameteriv)(GLenum target, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getProgramiv)(GLuint program, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog); + void (QGLF_APIENTRYP getRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getShaderiv)(GLuint shader, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog); + void (QGLF_APIENTRYP getShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); + void (QGLF_APIENTRYP getShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, char* source); + void (QGLF_APIENTRYP getUniformfv)(GLuint program, GLint location, GLfloat* params); + void (QGLF_APIENTRYP getUniformiv)(GLuint program, GLint location, GLint* params); + int (QGLF_APIENTRYP getUniformLocation)(GLuint program, const char* name); + void (QGLF_APIENTRYP getVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params); + void (QGLF_APIENTRYP getVertexAttribiv)(GLuint index, GLenum pname, GLint* params); + void (QGLF_APIENTRYP getVertexAttribPointerv)(GLuint index, GLenum pname, void** pointer); + GLboolean (QGLF_APIENTRYP isBuffer)(GLuint buffer); + GLboolean (QGLF_APIENTRYP isFramebuffer)(GLuint framebuffer); + GLboolean (QGLF_APIENTRYP isProgram)(GLuint program); + GLboolean (QGLF_APIENTRYP isRenderbuffer)(GLuint renderbuffer); + GLboolean (QGLF_APIENTRYP isShader)(GLuint shader); + void (QGLF_APIENTRYP linkProgram)(GLuint program); + void (QGLF_APIENTRYP releaseShaderCompiler)(); + void (QGLF_APIENTRYP renderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + void (QGLF_APIENTRYP sampleCoverage)(GLclampf value, GLboolean invert); + void (QGLF_APIENTRYP shaderBinary)(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length); + void (QGLF_APIENTRYP shaderSource)(GLuint shader, GLsizei count, const char** string, const GLint* length); + void (QGLF_APIENTRYP stencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask); + void (QGLF_APIENTRYP stencilMaskSeparate)(GLenum face, GLuint mask); + void (QGLF_APIENTRYP stencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); + void (QGLF_APIENTRYP uniform1f)(GLint location, GLfloat x); + void (QGLF_APIENTRYP uniform1fv)(GLint location, GLsizei count, const GLfloat* v); + void (QGLF_APIENTRYP uniform1i)(GLint location, GLint x); + void (QGLF_APIENTRYP uniform1iv)(GLint location, GLsizei count, const GLint* v); + void (QGLF_APIENTRYP uniform2f)(GLint location, GLfloat x, GLfloat y); + void (QGLF_APIENTRYP uniform2fv)(GLint location, GLsizei count, const GLfloat* v); + void (QGLF_APIENTRYP uniform2i)(GLint location, GLint x, GLint y); + void (QGLF_APIENTRYP uniform2iv)(GLint location, GLsizei count, const GLint* v); + void (QGLF_APIENTRYP uniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z); + void (QGLF_APIENTRYP uniform3fv)(GLint location, GLsizei count, const GLfloat* v); + void (QGLF_APIENTRYP uniform3i)(GLint location, GLint x, GLint y, GLint z); + void (QGLF_APIENTRYP uniform3iv)(GLint location, GLsizei count, const GLint* v); + void (QGLF_APIENTRYP uniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (QGLF_APIENTRYP uniform4fv)(GLint location, GLsizei count, const GLfloat* v); + void (QGLF_APIENTRYP uniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w); + void (QGLF_APIENTRYP uniform4iv)(GLint location, GLsizei count, const GLint* v); + void (QGLF_APIENTRYP uniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void (QGLF_APIENTRYP uniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void (QGLF_APIENTRYP uniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + void (QGLF_APIENTRYP useProgram)(GLuint program); + void (QGLF_APIENTRYP validateProgram)(GLuint program); + void (QGLF_APIENTRYP vertexAttrib1f)(GLuint indx, GLfloat x); + void (QGLF_APIENTRYP vertexAttrib1fv)(GLuint indx, const GLfloat* values); + void (QGLF_APIENTRYP vertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y); + void (QGLF_APIENTRYP vertexAttrib2fv)(GLuint indx, const GLfloat* values); + void (QGLF_APIENTRYP vertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z); + void (QGLF_APIENTRYP vertexAttrib3fv)(GLuint indx, const GLfloat* values); + void (QGLF_APIENTRYP vertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (QGLF_APIENTRYP vertexAttrib4fv)(GLuint indx, const GLfloat* values); + void (QGLF_APIENTRYP vertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr); +#endif +}; + +inline void QGLFunctions::glActiveTexture(GLenum texture) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glActiveTexture(texture); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->activeTexture(texture); +#endif +} + +inline void QGLFunctions::glAttachShader(GLuint program, GLuint shader) +{ +#if defined(QT_OPENGL_ES_2) + ::glAttachShader(program, shader); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->attachShader(program, shader); +#endif +} + +inline void QGLFunctions::glBindAttribLocation(GLuint program, GLuint index, const char* name) +{ +#if defined(QT_OPENGL_ES_2) + ::glBindAttribLocation(program, index, name); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bindAttribLocation(program, index, name); +#endif +} + +inline void QGLFunctions::glBindBuffer(GLenum target, GLuint buffer) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glBindBuffer(target, buffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bindBuffer(target, buffer); +#endif +} + +inline void QGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer) +{ +#if defined(QT_OPENGL_ES_2) + ::glBindFramebuffer(target, framebuffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bindFramebuffer(target, framebuffer); +#endif +} + +inline void QGLFunctions::glBindRenderbuffer(GLenum target, GLuint renderbuffer) +{ +#if defined(QT_OPENGL_ES_2) + ::glBindRenderbuffer(target, renderbuffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bindRenderbuffer(target, renderbuffer); +#endif +} + +inline void QGLFunctions::glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ +#if defined(QT_OPENGL_ES_2) + ::glBlendColor(red, green, blue, alpha); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->blendColor(red, green, blue, alpha); +#endif +} + +inline void QGLFunctions::glBlendEquation(GLenum mode) +{ +#if defined(QT_OPENGL_ES_2) + ::glBlendEquation(mode); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->blendEquation(mode); +#endif +} + +inline void QGLFunctions::glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) +{ +#if defined(QT_OPENGL_ES_2) + ::glBlendEquationSeparate(modeRGB, modeAlpha); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->blendEquationSeparate(modeRGB, modeAlpha); +#endif +} + +inline void QGLFunctions::glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +{ +#if defined(QT_OPENGL_ES_2) + ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); +#endif +} + +inline void QGLFunctions::glBufferData(GLenum target, qgl_GLsizeiptr size, const void* data, GLenum usage) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glBufferData(target, size, data, usage); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bufferData(target, size, data, usage); +#endif +} + +inline void QGLFunctions::glBufferSubData(GLenum target, qgl_GLintptr offset, qgl_GLsizeiptr size, const void* data) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glBufferSubData(target, offset, size, data); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->bufferSubData(target, offset, size, data); +#endif +} + +inline GLenum QGLFunctions::glCheckFramebufferStatus(GLenum target) +{ +#if defined(QT_OPENGL_ES_2) + return ::glCheckFramebufferStatus(target); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->checkFramebufferStatus(target); +#endif +} + +inline void QGLFunctions::glClearDepthf(GLclampf depth) +{ +#ifndef QT_OPENGL_ES + ::glClearDepth(depth); +#else + ::glClearDepthf(depth); +#endif +} + +inline void QGLFunctions::glCompileShader(GLuint shader) +{ +#if defined(QT_OPENGL_ES_2) + ::glCompileShader(shader); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->compileShader(shader); +#endif +} + +inline void QGLFunctions::glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->compressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); +#endif +} + +inline void QGLFunctions::glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); +#endif +} + +inline GLuint QGLFunctions::glCreateProgram() +{ +#if defined(QT_OPENGL_ES_2) + return ::glCreateProgram(); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->createProgram(); +#endif +} + +inline GLuint QGLFunctions::glCreateShader(GLenum type) +{ +#if defined(QT_OPENGL_ES_2) + return ::glCreateShader(type); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->createShader(type); +#endif +} + +inline void QGLFunctions::glDeleteBuffers(GLsizei n, const GLuint* buffers) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glDeleteBuffers(n, buffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->deleteBuffers(n, buffers); +#endif +} + +inline void QGLFunctions::glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) +{ +#if defined(QT_OPENGL_ES_2) + ::glDeleteFramebuffers(n, framebuffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->deleteFramebuffers(n, framebuffers); +#endif +} + +inline void QGLFunctions::glDeleteProgram(GLuint program) +{ +#if defined(QT_OPENGL_ES_2) + ::glDeleteProgram(program); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->deleteProgram(program); +#endif +} + +inline void QGLFunctions::glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) +{ +#if defined(QT_OPENGL_ES_2) + ::glDeleteRenderbuffers(n, renderbuffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->deleteRenderbuffers(n, renderbuffers); +#endif +} + +inline void QGLFunctions::glDeleteShader(GLuint shader) +{ +#if defined(QT_OPENGL_ES_2) + ::glDeleteShader(shader); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->deleteShader(shader); +#endif +} + +inline void QGLFunctions::glDepthRangef(GLclampf zNear, GLclampf zFar) +{ +#ifndef QT_OPENGL_ES + ::glDepthRange(zNear, zFar); +#else + ::glDepthRangef(zNear, zFar); +#endif +} + +inline void QGLFunctions::glDetachShader(GLuint program, GLuint shader) +{ +#if defined(QT_OPENGL_ES_2) + ::glDetachShader(program, shader); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->detachShader(program, shader); +#endif +} + +inline void QGLFunctions::glDisableVertexAttribArray(GLuint index) +{ +#if defined(QT_OPENGL_ES_2) + ::glDisableVertexAttribArray(index); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->disableVertexAttribArray(index); +#endif +} + +inline void QGLFunctions::glEnableVertexAttribArray(GLuint index) +{ +#if defined(QT_OPENGL_ES_2) + ::glEnableVertexAttribArray(index); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->enableVertexAttribArray(index); +#endif +} + +inline void QGLFunctions::glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ +#if defined(QT_OPENGL_ES_2) + ::glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); +#endif +} + +inline void QGLFunctions::glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ +#if defined(QT_OPENGL_ES_2) + ::glFramebufferTexture2D(target, attachment, textarget, texture, level); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->framebufferTexture2D(target, attachment, textarget, texture, level); +#endif +} + +inline void QGLFunctions::glGenBuffers(GLsizei n, GLuint* buffers) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glGenBuffers(n, buffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->genBuffers(n, buffers); +#endif +} + +inline void QGLFunctions::glGenerateMipmap(GLenum target) +{ +#if defined(QT_OPENGL_ES_2) + ::glGenerateMipmap(target); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->generateMipmap(target); +#endif +} + +inline void QGLFunctions::glGenFramebuffers(GLsizei n, GLuint* framebuffers) +{ +#if defined(QT_OPENGL_ES_2) + ::glGenFramebuffers(n, framebuffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->genFramebuffers(n, framebuffers); +#endif +} + +inline void QGLFunctions::glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) +{ +#if defined(QT_OPENGL_ES_2) + ::glGenRenderbuffers(n, renderbuffers); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->genRenderbuffers(n, renderbuffers); +#endif +} + +inline void QGLFunctions::glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetActiveAttrib(program, index, bufsize, length, size, type, name); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getActiveAttrib(program, index, bufsize, length, size, type, name); +#endif +} + +inline void QGLFunctions::glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetActiveUniform(program, index, bufsize, length, size, type, name); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getActiveUniform(program, index, bufsize, length, size, type, name); +#endif +} + +inline void QGLFunctions::glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetAttachedShaders(program, maxcount, count, shaders); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getAttachedShaders(program, maxcount, count, shaders); +#endif +} + +inline int QGLFunctions::glGetAttribLocation(GLuint program, const char* name) +{ +#if defined(QT_OPENGL_ES_2) + return ::glGetAttribLocation(program, name); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->getAttribLocation(program, name); +#endif +} + +inline void QGLFunctions::glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetBufferParameteriv(target, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getBufferParameteriv(target, pname, params); +#endif +} + +inline void QGLFunctions::glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetFramebufferAttachmentParameteriv(target, attachment, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getFramebufferAttachmentParameteriv(target, attachment, pname, params); +#endif +} + +inline void QGLFunctions::glGetProgramiv(GLuint program, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetProgramiv(program, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getProgramiv(program, pname, params); +#endif +} + +inline void QGLFunctions::glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetProgramInfoLog(program, bufsize, length, infolog); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getProgramInfoLog(program, bufsize, length, infolog); +#endif +} + +inline void QGLFunctions::glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetRenderbufferParameteriv(target, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getRenderbufferParameteriv(target, pname, params); +#endif +} + +inline void QGLFunctions::glGetShaderiv(GLuint shader, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetShaderiv(shader, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getShaderiv(shader, pname, params); +#endif +} + +inline void QGLFunctions::glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetShaderInfoLog(shader, bufsize, length, infolog); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getShaderInfoLog(shader, bufsize, length, infolog); +#endif +} + +inline void QGLFunctions::glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getShaderPrecisionFormat(shadertype, precisiontype, range, precision); +#endif +} + +inline void QGLFunctions::glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetShaderSource(shader, bufsize, length, source); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getShaderSource(shader, bufsize, length, source); +#endif +} + +inline void QGLFunctions::glGetUniformfv(GLuint program, GLint location, GLfloat* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetUniformfv(program, location, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getUniformfv(program, location, params); +#endif +} + +inline void QGLFunctions::glGetUniformiv(GLuint program, GLint location, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetUniformiv(program, location, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getUniformiv(program, location, params); +#endif +} + +inline int QGLFunctions::glGetUniformLocation(GLuint program, const char* name) +{ +#if defined(QT_OPENGL_ES_2) + return ::glGetUniformLocation(program, name); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->getUniformLocation(program, name); +#endif +} + +inline void QGLFunctions::glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetVertexAttribfv(index, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getVertexAttribfv(index, pname, params); +#endif +} + +inline void QGLFunctions::glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetVertexAttribiv(index, pname, params); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getVertexAttribiv(index, pname, params); +#endif +} + +inline void QGLFunctions::glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer) +{ +#if defined(QT_OPENGL_ES_2) + ::glGetVertexAttribPointerv(index, pname, pointer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->getVertexAttribPointerv(index, pname, pointer); +#endif +} + +inline GLboolean QGLFunctions::glIsBuffer(GLuint buffer) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + return ::glIsBuffer(buffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->isBuffer(buffer); +#endif +} + +inline GLboolean QGLFunctions::glIsFramebuffer(GLuint framebuffer) +{ +#if defined(QT_OPENGL_ES_2) + return ::glIsFramebuffer(framebuffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->isFramebuffer(framebuffer); +#endif +} + +inline GLboolean QGLFunctions::glIsProgram(GLuint program) +{ +#if defined(QT_OPENGL_ES_2) + return ::glIsProgram(program); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->isProgram(program); +#endif +} + +inline GLboolean QGLFunctions::glIsRenderbuffer(GLuint renderbuffer) +{ +#if defined(QT_OPENGL_ES_2) + return ::glIsRenderbuffer(renderbuffer); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->isRenderbuffer(renderbuffer); +#endif +} + +inline GLboolean QGLFunctions::glIsShader(GLuint shader) +{ +#if defined(QT_OPENGL_ES_2) + return ::glIsShader(shader); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + return d_ptr->isShader(shader); +#endif +} + +inline void QGLFunctions::glLinkProgram(GLuint program) +{ +#if defined(QT_OPENGL_ES_2) + ::glLinkProgram(program); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->linkProgram(program); +#endif +} + +inline void QGLFunctions::glReleaseShaderCompiler() +{ +#if defined(QT_OPENGL_ES_2) + ::glReleaseShaderCompiler(); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->releaseShaderCompiler(); +#endif +} + +inline void QGLFunctions::glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ +#if defined(QT_OPENGL_ES_2) + ::glRenderbufferStorage(target, internalformat, width, height); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->renderbufferStorage(target, internalformat, width, height); +#endif +} + +inline void QGLFunctions::glSampleCoverage(GLclampf value, GLboolean invert) +{ +#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) + ::glSampleCoverage(value, invert); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->sampleCoverage(value, invert); +#endif +} + +inline void QGLFunctions::glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length) +{ +#if defined(QT_OPENGL_ES_2) + ::glShaderBinary(n, shaders, binaryformat, binary, length); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->shaderBinary(n, shaders, binaryformat, binary, length); +#endif +} + +inline void QGLFunctions::glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length) +{ +#if defined(QT_OPENGL_ES_2) + ::glShaderSource(shader, count, string, length); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->shaderSource(shader, count, string, length); +#endif +} + +inline void QGLFunctions::glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +{ +#if defined(QT_OPENGL_ES_2) + ::glStencilFuncSeparate(face, func, ref, mask); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->stencilFuncSeparate(face, func, ref, mask); +#endif +} + +inline void QGLFunctions::glStencilMaskSeparate(GLenum face, GLuint mask) +{ +#if defined(QT_OPENGL_ES_2) + ::glStencilMaskSeparate(face, mask); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->stencilMaskSeparate(face, mask); +#endif +} + +inline void QGLFunctions::glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ +#if defined(QT_OPENGL_ES_2) + ::glStencilOpSeparate(face, fail, zfail, zpass); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->stencilOpSeparate(face, fail, zfail, zpass); +#endif +} + +inline void QGLFunctions::glUniform1f(GLint location, GLfloat x) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform1f(location, x); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform1f(location, x); +#endif +} + +inline void QGLFunctions::glUniform1fv(GLint location, GLsizei count, const GLfloat* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform1fv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform1fv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform1i(GLint location, GLint x) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform1i(location, x); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform1i(location, x); +#endif +} + +inline void QGLFunctions::glUniform1iv(GLint location, GLsizei count, const GLint* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform1iv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform1iv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform2f(GLint location, GLfloat x, GLfloat y) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform2f(location, x, y); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform2f(location, x, y); +#endif +} + +inline void QGLFunctions::glUniform2fv(GLint location, GLsizei count, const GLfloat* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform2fv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform2fv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform2i(GLint location, GLint x, GLint y) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform2i(location, x, y); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform2i(location, x, y); +#endif +} + +inline void QGLFunctions::glUniform2iv(GLint location, GLsizei count, const GLint* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform2iv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform2iv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform3f(location, x, y, z); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform3f(location, x, y, z); +#endif +} + +inline void QGLFunctions::glUniform3fv(GLint location, GLsizei count, const GLfloat* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform3fv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform3fv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform3i(GLint location, GLint x, GLint y, GLint z) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform3i(location, x, y, z); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform3i(location, x, y, z); +#endif +} + +inline void QGLFunctions::glUniform3iv(GLint location, GLsizei count, const GLint* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform3iv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform3iv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform4f(location, x, y, z, w); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform4f(location, x, y, z, w); +#endif +} + +inline void QGLFunctions::glUniform4fv(GLint location, GLsizei count, const GLfloat* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform4fv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform4fv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform4i(location, x, y, z, w); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform4i(location, x, y, z, w); +#endif +} + +inline void QGLFunctions::glUniform4iv(GLint location, GLsizei count, const GLint* v) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniform4iv(location, count, v); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniform4iv(location, count, v); +#endif +} + +inline void QGLFunctions::glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniformMatrix2fv(location, count, transpose, value); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniformMatrix2fv(location, count, transpose, value); +#endif +} + +inline void QGLFunctions::glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniformMatrix3fv(location, count, transpose, value); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniformMatrix3fv(location, count, transpose, value); +#endif +} + +inline void QGLFunctions::glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ +#if defined(QT_OPENGL_ES_2) + ::glUniformMatrix4fv(location, count, transpose, value); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->uniformMatrix4fv(location, count, transpose, value); +#endif +} + +inline void QGLFunctions::glUseProgram(GLuint program) +{ +#if defined(QT_OPENGL_ES_2) + ::glUseProgram(program); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->useProgram(program); +#endif +} + +inline void QGLFunctions::glValidateProgram(GLuint program) +{ +#if defined(QT_OPENGL_ES_2) + ::glValidateProgram(program); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->validateProgram(program); +#endif +} + +inline void QGLFunctions::glVertexAttrib1f(GLuint indx, GLfloat x) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib1f(indx, x); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib1f(indx, x); +#endif +} + +inline void QGLFunctions::glVertexAttrib1fv(GLuint indx, const GLfloat* values) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib1fv(indx, values); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib1fv(indx, values); +#endif +} + +inline void QGLFunctions::glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib2f(indx, x, y); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib2f(indx, x, y); +#endif +} + +inline void QGLFunctions::glVertexAttrib2fv(GLuint indx, const GLfloat* values) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib2fv(indx, values); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib2fv(indx, values); +#endif +} + +inline void QGLFunctions::glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib3f(indx, x, y, z); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib3f(indx, x, y, z); +#endif +} + +inline void QGLFunctions::glVertexAttrib3fv(GLuint indx, const GLfloat* values) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib3fv(indx, values); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib3fv(indx, values); +#endif +} + +inline void QGLFunctions::glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib4f(indx, x, y, z, w); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib4f(indx, x, y, z, w); +#endif +} + +inline void QGLFunctions::glVertexAttrib4fv(GLuint indx, const GLfloat* values) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttrib4fv(indx, values); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttrib4fv(indx, values); +#endif +} + +inline void QGLFunctions::glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) +{ +#if defined(QT_OPENGL_ES_2) + ::glVertexAttribPointer(indx, size, type, normalized, stride, ptr); +#else + Q_ASSERT(QGLFunctions::isInitialized(d_ptr)); + d_ptr->vertexAttribPointer(indx, size, type, normalized, stride, ptr); +#endif +} + +#ifndef GL_ACTIVE_ATTRIBUTE_MAX_LENGTH +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#endif +#ifndef GL_ACTIVE_ATTRIBUTES +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#endif +#ifndef GL_ACTIVE_TEXTURE +#define GL_ACTIVE_TEXTURE 0x84E0 +#endif +#ifndef GL_ACTIVE_UNIFORM_MAX_LENGTH +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#endif +#ifndef GL_ACTIVE_UNIFORMS +#define GL_ACTIVE_UNIFORMS 0x8B86 +#endif +#ifndef GL_ALIASED_LINE_WIDTH_RANGE +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#endif +#ifndef GL_ALIASED_POINT_SIZE_RANGE +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#endif +#ifndef GL_ALPHA +#define GL_ALPHA 0x1906 +#endif +#ifndef GL_ALPHA_BITS +#define GL_ALPHA_BITS 0x0D55 +#endif +#ifndef GL_ALWAYS +#define GL_ALWAYS 0x0207 +#endif +#ifndef GL_ARRAY_BUFFER +#define GL_ARRAY_BUFFER 0x8892 +#endif +#ifndef GL_ARRAY_BUFFER_BINDING +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#endif +#ifndef GL_ATTACHED_SHADERS +#define GL_ATTACHED_SHADERS 0x8B85 +#endif +#ifndef GL_BACK +#define GL_BACK 0x0405 +#endif +#ifndef GL_BLEND +#define GL_BLEND 0x0BE2 +#endif +#ifndef GL_BLEND_COLOR +#define GL_BLEND_COLOR 0x8005 +#endif +#ifndef GL_BLEND_DST_ALPHA +#define GL_BLEND_DST_ALPHA 0x80CA +#endif +#ifndef GL_BLEND_DST_RGB +#define GL_BLEND_DST_RGB 0x80C8 +#endif +#ifndef GL_BLEND_EQUATION +#define GL_BLEND_EQUATION 0x8009 +#endif +#ifndef GL_BLEND_EQUATION_ALPHA +#define GL_BLEND_EQUATION_ALPHA 0x883D +#endif +#ifndef GL_BLEND_EQUATION_RGB +#define GL_BLEND_EQUATION_RGB 0x8009 +#endif +#ifndef GL_BLEND_SRC_ALPHA +#define GL_BLEND_SRC_ALPHA 0x80CB +#endif +#ifndef GL_BLEND_SRC_RGB +#define GL_BLEND_SRC_RGB 0x80C9 +#endif +#ifndef GL_BLUE_BITS +#define GL_BLUE_BITS 0x0D54 +#endif +#ifndef GL_BOOL +#define GL_BOOL 0x8B56 +#endif +#ifndef GL_BOOL_VEC2 +#define GL_BOOL_VEC2 0x8B57 +#endif +#ifndef GL_BOOL_VEC3 +#define GL_BOOL_VEC3 0x8B58 +#endif +#ifndef GL_BOOL_VEC4 +#define GL_BOOL_VEC4 0x8B59 +#endif +#ifndef GL_BUFFER_SIZE +#define GL_BUFFER_SIZE 0x8764 +#endif +#ifndef GL_BUFFER_USAGE +#define GL_BUFFER_USAGE 0x8765 +#endif +#ifndef GL_BYTE +#define GL_BYTE 0x1400 +#endif +#ifndef GL_CCW +#define GL_CCW 0x0901 +#endif +#ifndef GL_CLAMP_TO_EDGE +#define GL_CLAMP_TO_EDGE 0x812F +#endif +#ifndef GL_COLOR_ATTACHMENT0 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#endif +#ifndef GL_COLOR_BUFFER_BIT +#define GL_COLOR_BUFFER_BIT 0x00004000 +#endif +#ifndef GL_COLOR_CLEAR_VALUE +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#endif +#ifndef GL_COLOR_WRITEMASK +#define GL_COLOR_WRITEMASK 0x0C23 +#endif +#ifndef GL_COMPILE_STATUS +#define GL_COMPILE_STATUS 0x8B81 +#endif +#ifndef GL_COMPRESSED_TEXTURE_FORMATS +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#endif +#ifndef GL_CONSTANT_ALPHA +#define GL_CONSTANT_ALPHA 0x8003 +#endif +#ifndef GL_CONSTANT_COLOR +#define GL_CONSTANT_COLOR 0x8001 +#endif +#ifndef GL_CULL_FACE +#define GL_CULL_FACE 0x0B44 +#endif +#ifndef GL_CULL_FACE_MODE +#define GL_CULL_FACE_MODE 0x0B45 +#endif +#ifndef GL_CURRENT_PROGRAM +#define GL_CURRENT_PROGRAM 0x8B8D +#endif +#ifndef GL_CURRENT_VERTEX_ATTRIB +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#endif +#ifndef GL_CW +#define GL_CW 0x0900 +#endif +#ifndef GL_DECR +#define GL_DECR 0x1E03 +#endif +#ifndef GL_DECR_WRAP +#define GL_DECR_WRAP 0x8508 +#endif +#ifndef GL_DELETE_STATUS +#define GL_DELETE_STATUS 0x8B80 +#endif +#ifndef GL_DEPTH_ATTACHMENT +#define GL_DEPTH_ATTACHMENT 0x8D00 +#endif +#ifndef GL_DEPTH_BITS +#define GL_DEPTH_BITS 0x0D56 +#endif +#ifndef GL_DEPTH_BUFFER_BIT +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#endif +#ifndef GL_DEPTH_CLEAR_VALUE +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#endif +#ifndef GL_DEPTH_COMPONENT +#define GL_DEPTH_COMPONENT 0x1902 +#endif +#ifndef GL_DEPTH_COMPONENT16 +#define GL_DEPTH_COMPONENT16 0x81A5 +#endif +#ifndef GL_DEPTH_FUNC +#define GL_DEPTH_FUNC 0x0B74 +#endif +#ifndef GL_DEPTH_RANGE +#define GL_DEPTH_RANGE 0x0B70 +#endif +#ifndef GL_DEPTH_TEST +#define GL_DEPTH_TEST 0x0B71 +#endif +#ifndef GL_DEPTH_WRITEMASK +#define GL_DEPTH_WRITEMASK 0x0B72 +#endif +#ifndef GL_DITHER +#define GL_DITHER 0x0BD0 +#endif +#ifndef GL_DONT_CARE +#define GL_DONT_CARE 0x1100 +#endif +#ifndef GL_DST_ALPHA +#define GL_DST_ALPHA 0x0304 +#endif +#ifndef GL_DST_COLOR +#define GL_DST_COLOR 0x0306 +#endif +#ifndef GL_DYNAMIC_DRAW +#define GL_DYNAMIC_DRAW 0x88E8 +#endif +#ifndef GL_ELEMENT_ARRAY_BUFFER +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#endif +#ifndef GL_ELEMENT_ARRAY_BUFFER_BINDING +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#endif +#ifndef GL_EQUAL +#define GL_EQUAL 0x0202 +#endif +#ifndef GL_EXTENSIONS +#define GL_EXTENSIONS 0x1F03 +#endif +#ifndef GL_FALSE +#define GL_FALSE 0 +#endif +#ifndef GL_FASTEST +#define GL_FASTEST 0x1101 +#endif +#ifndef GL_FIXED +#define GL_FIXED 0x140C +#endif +#ifndef GL_FLOAT +#define GL_FLOAT 0x1406 +#endif +#ifndef GL_FLOAT_MAT2 +#define GL_FLOAT_MAT2 0x8B5A +#endif +#ifndef GL_FLOAT_MAT3 +#define GL_FLOAT_MAT3 0x8B5B +#endif +#ifndef GL_FLOAT_MAT4 +#define GL_FLOAT_MAT4 0x8B5C +#endif +#ifndef GL_FLOAT_VEC2 +#define GL_FLOAT_VEC2 0x8B50 +#endif +#ifndef GL_FLOAT_VEC3 +#define GL_FLOAT_VEC3 0x8B51 +#endif +#ifndef GL_FLOAT_VEC4 +#define GL_FLOAT_VEC4 0x8B52 +#endif +#ifndef GL_FRAGMENT_SHADER +#define GL_FRAGMENT_SHADER 0x8B30 +#endif +#ifndef GL_FRAMEBUFFER +#define GL_FRAMEBUFFER 0x8D40 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#endif +#ifndef GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#endif +#ifndef GL_FRAMEBUFFER_BINDING +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#endif +#ifndef GL_FRAMEBUFFER_COMPLETE +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#endif +#ifndef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#endif +#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#endif +#ifndef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#endif +#ifndef GL_FRAMEBUFFER_UNSUPPORTED +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#endif +#ifndef GL_FRONT +#define GL_FRONT 0x0404 +#endif +#ifndef GL_FRONT_AND_BACK +#define GL_FRONT_AND_BACK 0x0408 +#endif +#ifndef GL_FRONT_FACE +#define GL_FRONT_FACE 0x0B46 +#endif +#ifndef GL_FUNC_ADD +#define GL_FUNC_ADD 0x8006 +#endif +#ifndef GL_FUNC_REVERSE_SUBTRACT +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#endif +#ifndef GL_FUNC_SUBTRACT +#define GL_FUNC_SUBTRACT 0x800A +#endif +#ifndef GL_GENERATE_MIPMAP_HINT +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#endif +#ifndef GL_GEQUAL +#define GL_GEQUAL 0x0206 +#endif +#ifndef GL_GREATER +#define GL_GREATER 0x0204 +#endif +#ifndef GL_GREEN_BITS +#define GL_GREEN_BITS 0x0D53 +#endif +#ifndef GL_HIGH_FLOAT +#define GL_HIGH_FLOAT 0x8DF2 +#endif +#ifndef GL_HIGH_INT +#define GL_HIGH_INT 0x8DF5 +#endif +#ifndef GL_IMPLEMENTATION_COLOR_READ_FORMAT +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#endif +#ifndef GL_IMPLEMENTATION_COLOR_READ_TYPE +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#endif +#ifndef GL_INCR +#define GL_INCR 0x1E02 +#endif +#ifndef GL_INCR_WRAP +#define GL_INCR_WRAP 0x8507 +#endif +#ifndef GL_INFO_LOG_LENGTH +#define GL_INFO_LOG_LENGTH 0x8B84 +#endif +#ifndef GL_INT +#define GL_INT 0x1404 +#endif +#ifndef GL_INT_VEC2 +#define GL_INT_VEC2 0x8B53 +#endif +#ifndef GL_INT_VEC3 +#define GL_INT_VEC3 0x8B54 +#endif +#ifndef GL_INT_VEC4 +#define GL_INT_VEC4 0x8B55 +#endif +#ifndef GL_INVALID_ENUM +#define GL_INVALID_ENUM 0x0500 +#endif +#ifndef GL_INVALID_FRAMEBUFFER_OPERATION +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#endif +#ifndef GL_INVALID_OPERATION +#define GL_INVALID_OPERATION 0x0502 +#endif +#ifndef GL_INVALID_VALUE +#define GL_INVALID_VALUE 0x0501 +#endif +#ifndef GL_INVERT +#define GL_INVERT 0x150A +#endif +#ifndef GL_KEEP +#define GL_KEEP 0x1E00 +#endif +#ifndef GL_LEQUAL +#define GL_LEQUAL 0x0203 +#endif +#ifndef GL_LESS +#define GL_LESS 0x0201 +#endif +#ifndef GL_LINEAR +#define GL_LINEAR 0x2601 +#endif +#ifndef GL_LINEAR_MIPMAP_LINEAR +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#endif +#ifndef GL_LINEAR_MIPMAP_NEAREST +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#endif +#ifndef GL_LINE_LOOP +#define GL_LINE_LOOP 0x0002 +#endif +#ifndef GL_LINES +#define GL_LINES 0x0001 +#endif +#ifndef GL_LINE_STRIP +#define GL_LINE_STRIP 0x0003 +#endif +#ifndef GL_LINE_WIDTH +#define GL_LINE_WIDTH 0x0B21 +#endif +#ifndef GL_LINK_STATUS +#define GL_LINK_STATUS 0x8B82 +#endif +#ifndef GL_LOW_FLOAT +#define GL_LOW_FLOAT 0x8DF0 +#endif +#ifndef GL_LOW_INT +#define GL_LOW_INT 0x8DF3 +#endif +#ifndef GL_LUMINANCE +#define GL_LUMINANCE 0x1909 +#endif +#ifndef GL_LUMINANCE_ALPHA +#define GL_LUMINANCE_ALPHA 0x190A +#endif +#ifndef GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#endif +#ifndef GL_MAX_CUBE_MAP_TEXTURE_SIZE +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#endif +#ifndef GL_MAX_FRAGMENT_UNIFORM_VECTORS +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#endif +#ifndef GL_MAX_RENDERBUFFER_SIZE +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#endif +#ifndef GL_MAX_TEXTURE_IMAGE_UNITS +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#endif +#ifndef GL_MAX_TEXTURE_SIZE +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#endif +#ifndef GL_MAX_VARYING_VECTORS +#define GL_MAX_VARYING_VECTORS 0x8DFC +#endif +#ifndef GL_MAX_VERTEX_ATTRIBS +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#endif +#ifndef GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#endif +#ifndef GL_MAX_VERTEX_UNIFORM_VECTORS +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#endif +#ifndef GL_MAX_VIEWPORT_DIMS +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#endif +#ifndef GL_MEDIUM_FLOAT +#define GL_MEDIUM_FLOAT 0x8DF1 +#endif +#ifndef GL_MEDIUM_INT +#define GL_MEDIUM_INT 0x8DF4 +#endif +#ifndef GL_MIRRORED_REPEAT +#define GL_MIRRORED_REPEAT 0x8370 +#endif +#ifndef GL_NEAREST +#define GL_NEAREST 0x2600 +#endif +#ifndef GL_NEAREST_MIPMAP_LINEAR +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#endif +#ifndef GL_NEAREST_MIPMAP_NEAREST +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#endif +#ifndef GL_NEVER +#define GL_NEVER 0x0200 +#endif +#ifndef GL_NICEST +#define GL_NICEST 0x1102 +#endif +#ifndef GL_NO_ERROR +#define GL_NO_ERROR 0 +#endif +#ifndef GL_NONE +#define GL_NONE 0 +#endif +#ifndef GL_NOTEQUAL +#define GL_NOTEQUAL 0x0205 +#endif +#ifndef GL_NUM_COMPRESSED_TEXTURE_FORMATS +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#endif +#ifndef GL_NUM_SHADER_BINARY_FORMATS +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#endif +#ifndef GL_ONE +#define GL_ONE 1 +#endif +#ifndef GL_ONE_MINUS_CONSTANT_ALPHA +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#endif +#ifndef GL_ONE_MINUS_CONSTANT_COLOR +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#endif +#ifndef GL_ONE_MINUS_DST_ALPHA +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#endif +#ifndef GL_ONE_MINUS_DST_COLOR +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#endif +#ifndef GL_ONE_MINUS_SRC_ALPHA +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#endif +#ifndef GL_ONE_MINUS_SRC_COLOR +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#endif +#ifndef GL_OUT_OF_MEMORY +#define GL_OUT_OF_MEMORY 0x0505 +#endif +#ifndef GL_PACK_ALIGNMENT +#define GL_PACK_ALIGNMENT 0x0D05 +#endif +#ifndef GL_POINTS +#define GL_POINTS 0x0000 +#endif +#ifndef GL_POLYGON_OFFSET_FACTOR +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#endif +#ifndef GL_POLYGON_OFFSET_FILL +#define GL_POLYGON_OFFSET_FILL 0x8037 +#endif +#ifndef GL_POLYGON_OFFSET_UNITS +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#endif +#ifndef GL_RED_BITS +#define GL_RED_BITS 0x0D52 +#endif +#ifndef GL_RENDERBUFFER +#define GL_RENDERBUFFER 0x8D41 +#endif +#ifndef GL_RENDERBUFFER_ALPHA_SIZE +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#endif +#ifndef GL_RENDERBUFFER_BINDING +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#endif +#ifndef GL_RENDERBUFFER_BLUE_SIZE +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#endif +#ifndef GL_RENDERBUFFER_DEPTH_SIZE +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#endif +#ifndef GL_RENDERBUFFER_GREEN_SIZE +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#endif +#ifndef GL_RENDERBUFFER_HEIGHT +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#endif +#ifndef GL_RENDERBUFFER_INTERNAL_FORMAT +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#endif +#ifndef GL_RENDERBUFFER_RED_SIZE +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#endif +#ifndef GL_RENDERBUFFER_STENCIL_SIZE +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#endif +#ifndef GL_RENDERBUFFER_WIDTH +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#endif +#ifndef GL_RENDERER +#define GL_RENDERER 0x1F01 +#endif +#ifndef GL_REPEAT +#define GL_REPEAT 0x2901 +#endif +#ifndef GL_REPLACE +#define GL_REPLACE 0x1E01 +#endif +#ifndef GL_RGB +#define GL_RGB 0x1907 +#endif +#ifndef GL_RGB565 +#define GL_RGB565 0x8D62 +#endif +#ifndef GL_RGB5_A1 +#define GL_RGB5_A1 0x8057 +#endif +#ifndef GL_RGBA +#define GL_RGBA 0x1908 +#endif +#ifndef GL_RGBA4 +#define GL_RGBA4 0x8056 +#endif +#ifndef GL_SAMPLE_ALPHA_TO_COVERAGE +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#endif +#ifndef GL_SAMPLE_BUFFERS +#define GL_SAMPLE_BUFFERS 0x80A8 +#endif +#ifndef GL_SAMPLE_COVERAGE +#define GL_SAMPLE_COVERAGE 0x80A0 +#endif +#ifndef GL_SAMPLE_COVERAGE_INVERT +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#endif +#ifndef GL_SAMPLE_COVERAGE_VALUE +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#endif +#ifndef GL_SAMPLER_2D +#define GL_SAMPLER_2D 0x8B5E +#endif +#ifndef GL_SAMPLER_CUBE +#define GL_SAMPLER_CUBE 0x8B60 +#endif +#ifndef GL_SAMPLES +#define GL_SAMPLES 0x80A9 +#endif +#ifndef GL_SCISSOR_BOX +#define GL_SCISSOR_BOX 0x0C10 +#endif +#ifndef GL_SCISSOR_TEST +#define GL_SCISSOR_TEST 0x0C11 +#endif +#ifndef GL_SHADER_BINARY_FORMATS +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#endif +#ifndef GL_SHADER_COMPILER +#define GL_SHADER_COMPILER 0x8DFA +#endif +#ifndef GL_SHADER_SOURCE_LENGTH +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#endif +#ifndef GL_SHADER_TYPE +#define GL_SHADER_TYPE 0x8B4F +#endif +#ifndef GL_SHADING_LANGUAGE_VERSION +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#endif +#ifndef GL_SHORT +#define GL_SHORT 0x1402 +#endif +#ifndef GL_SRC_ALPHA +#define GL_SRC_ALPHA 0x0302 +#endif +#ifndef GL_SRC_ALPHA_SATURATE +#define GL_SRC_ALPHA_SATURATE 0x0308 +#endif +#ifndef GL_SRC_COLOR +#define GL_SRC_COLOR 0x0300 +#endif +#ifndef GL_STATIC_DRAW +#define GL_STATIC_DRAW 0x88E4 +#endif +#ifndef GL_STENCIL_ATTACHMENT +#define GL_STENCIL_ATTACHMENT 0x8D20 +#endif +#ifndef GL_STENCIL_BACK_FAIL +#define GL_STENCIL_BACK_FAIL 0x8801 +#endif +#ifndef GL_STENCIL_BACK_FUNC +#define GL_STENCIL_BACK_FUNC 0x8800 +#endif +#ifndef GL_STENCIL_BACK_PASS_DEPTH_FAIL +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#endif +#ifndef GL_STENCIL_BACK_PASS_DEPTH_PASS +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#endif +#ifndef GL_STENCIL_BACK_REF +#define GL_STENCIL_BACK_REF 0x8CA3 +#endif +#ifndef GL_STENCIL_BACK_VALUE_MASK +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#endif +#ifndef GL_STENCIL_BACK_WRITEMASK +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#endif +#ifndef GL_STENCIL_BITS +#define GL_STENCIL_BITS 0x0D57 +#endif +#ifndef GL_STENCIL_BUFFER_BIT +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#endif +#ifndef GL_STENCIL_CLEAR_VALUE +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#endif +#ifndef GL_STENCIL_FAIL +#define GL_STENCIL_FAIL 0x0B94 +#endif +#ifndef GL_STENCIL_FUNC +#define GL_STENCIL_FUNC 0x0B92 +#endif +#ifndef GL_STENCIL_INDEX +#define GL_STENCIL_INDEX 0x1901 +#endif +#ifndef GL_STENCIL_INDEX8 +#define GL_STENCIL_INDEX8 0x8D48 +#endif +#ifndef GL_STENCIL_PASS_DEPTH_FAIL +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#endif +#ifndef GL_STENCIL_PASS_DEPTH_PASS +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#endif +#ifndef GL_STENCIL_REF +#define GL_STENCIL_REF 0x0B97 +#endif +#ifndef GL_STENCIL_TEST +#define GL_STENCIL_TEST 0x0B90 +#endif +#ifndef GL_STENCIL_VALUE_MASK +#define GL_STENCIL_VALUE_MASK 0x0B93 +#endif +#ifndef GL_STENCIL_WRITEMASK +#define GL_STENCIL_WRITEMASK 0x0B98 +#endif +#ifndef GL_STREAM_DRAW +#define GL_STREAM_DRAW 0x88E0 +#endif +#ifndef GL_SUBPIXEL_BITS +#define GL_SUBPIXEL_BITS 0x0D50 +#endif +#ifndef GL_TEXTURE0 +#define GL_TEXTURE0 0x84C0 +#endif +#ifndef GL_TEXTURE +#define GL_TEXTURE 0x1702 +#endif +#ifndef GL_TEXTURE10 +#define GL_TEXTURE10 0x84CA +#endif +#ifndef GL_TEXTURE1 +#define GL_TEXTURE1 0x84C1 +#endif +#ifndef GL_TEXTURE11 +#define GL_TEXTURE11 0x84CB +#endif +#ifndef GL_TEXTURE12 +#define GL_TEXTURE12 0x84CC +#endif +#ifndef GL_TEXTURE13 +#define GL_TEXTURE13 0x84CD +#endif +#ifndef GL_TEXTURE14 +#define GL_TEXTURE14 0x84CE +#endif +#ifndef GL_TEXTURE15 +#define GL_TEXTURE15 0x84CF +#endif +#ifndef GL_TEXTURE16 +#define GL_TEXTURE16 0x84D0 +#endif +#ifndef GL_TEXTURE17 +#define GL_TEXTURE17 0x84D1 +#endif +#ifndef GL_TEXTURE18 +#define GL_TEXTURE18 0x84D2 +#endif +#ifndef GL_TEXTURE19 +#define GL_TEXTURE19 0x84D3 +#endif +#ifndef GL_TEXTURE20 +#define GL_TEXTURE20 0x84D4 +#endif +#ifndef GL_TEXTURE2 +#define GL_TEXTURE2 0x84C2 +#endif +#ifndef GL_TEXTURE21 +#define GL_TEXTURE21 0x84D5 +#endif +#ifndef GL_TEXTURE22 +#define GL_TEXTURE22 0x84D6 +#endif +#ifndef GL_TEXTURE23 +#define GL_TEXTURE23 0x84D7 +#endif +#ifndef GL_TEXTURE24 +#define GL_TEXTURE24 0x84D8 +#endif +#ifndef GL_TEXTURE25 +#define GL_TEXTURE25 0x84D9 +#endif +#ifndef GL_TEXTURE26 +#define GL_TEXTURE26 0x84DA +#endif +#ifndef GL_TEXTURE27 +#define GL_TEXTURE27 0x84DB +#endif +#ifndef GL_TEXTURE28 +#define GL_TEXTURE28 0x84DC +#endif +#ifndef GL_TEXTURE29 +#define GL_TEXTURE29 0x84DD +#endif +#ifndef GL_TEXTURE_2D +#define GL_TEXTURE_2D 0x0DE1 +#endif +#ifndef GL_TEXTURE30 +#define GL_TEXTURE30 0x84DE +#endif +#ifndef GL_TEXTURE3 +#define GL_TEXTURE3 0x84C3 +#endif +#ifndef GL_TEXTURE31 +#define GL_TEXTURE31 0x84DF +#endif +#ifndef GL_TEXTURE4 +#define GL_TEXTURE4 0x84C4 +#endif +#ifndef GL_TEXTURE5 +#define GL_TEXTURE5 0x84C5 +#endif +#ifndef GL_TEXTURE6 +#define GL_TEXTURE6 0x84C6 +#endif +#ifndef GL_TEXTURE7 +#define GL_TEXTURE7 0x84C7 +#endif +#ifndef GL_TEXTURE8 +#define GL_TEXTURE8 0x84C8 +#endif +#ifndef GL_TEXTURE9 +#define GL_TEXTURE9 0x84C9 +#endif +#ifndef GL_TEXTURE_BINDING_2D +#define GL_TEXTURE_BINDING_2D 0x8069 +#endif +#ifndef GL_TEXTURE_BINDING_CUBE_MAP +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#endif +#ifndef GL_TEXTURE_CUBE_MAP +#define GL_TEXTURE_CUBE_MAP 0x8513 +#endif +#ifndef GL_TEXTURE_CUBE_MAP_NEGATIVE_X +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#endif +#ifndef GL_TEXTURE_CUBE_MAP_NEGATIVE_Y +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#endif +#ifndef GL_TEXTURE_CUBE_MAP_NEGATIVE_Z +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#endif +#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_X +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#endif +#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_Y +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#endif +#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_Z +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#endif +#ifndef GL_TEXTURE_MAG_FILTER +#define GL_TEXTURE_MAG_FILTER 0x2800 +#endif +#ifndef GL_TEXTURE_MIN_FILTER +#define GL_TEXTURE_MIN_FILTER 0x2801 +#endif +#ifndef GL_TEXTURE_WRAP_S +#define GL_TEXTURE_WRAP_S 0x2802 +#endif +#ifndef GL_TEXTURE_WRAP_T +#define GL_TEXTURE_WRAP_T 0x2803 +#endif +#ifndef GL_TRIANGLE_FAN +#define GL_TRIANGLE_FAN 0x0006 +#endif +#ifndef GL_TRIANGLES +#define GL_TRIANGLES 0x0004 +#endif +#ifndef GL_TRIANGLE_STRIP +#define GL_TRIANGLE_STRIP 0x0005 +#endif +#ifndef GL_TRUE +#define GL_TRUE 1 +#endif +#ifndef GL_UNPACK_ALIGNMENT +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#endif +#ifndef GL_UNSIGNED_BYTE +#define GL_UNSIGNED_BYTE 0x1401 +#endif +#ifndef GL_UNSIGNED_INT +#define GL_UNSIGNED_INT 0x1405 +#endif +#ifndef GL_UNSIGNED_SHORT +#define GL_UNSIGNED_SHORT 0x1403 +#endif +#ifndef GL_UNSIGNED_SHORT_4_4_4_4 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#endif +#ifndef GL_UNSIGNED_SHORT_5_5_5_1 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#endif +#ifndef GL_UNSIGNED_SHORT_5_6_5 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#endif +#ifndef GL_VALIDATE_STATUS +#define GL_VALIDATE_STATUS 0x8B83 +#endif +#ifndef GL_VENDOR +#define GL_VENDOR 0x1F00 +#endif +#ifndef GL_VERSION +#define GL_VERSION 0x1F02 +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_ENABLED +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_NORMALIZED +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_POINTER +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_SIZE +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_STRIDE +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#endif +#ifndef GL_VERTEX_ATTRIB_ARRAY_TYPE +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#endif +#ifndef GL_VERTEX_SHADER +#define GL_VERTEX_SHADER 0x8B31 +#endif +#ifndef GL_VIEWPORT +#define GL_VIEWPORT 0x0BA2 +#endif +#ifndef GL_ZERO +#define GL_ZERO 0 +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index 3992f34..261d567 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -76,6 +76,14 @@ \endlist + + \section Threading + + As of Qt 4.8, it's possible to render into a QGLPixelBuffer using + a QPainter in a separate thread. Note that OpenGL 2.0 or OpenGL ES + 2.0 is required for this to work. Also, under X11, it's necessary + to set the Qt::AA_X11InitThreads application attribute. + Pbuffers are provided by the OpenGL \c pbuffer extension; call hasOpenGLPbuffer() to find out if the system provides pbuffers. @@ -394,25 +402,25 @@ bool QGLPixelBuffer::isValid() const } #if !defined(QT_OPENGL_ES_1) -Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_buffer_2_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_buffer_2_engine) #endif #ifndef QT_OPENGL_ES_2 -Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_engine) +Q_GLOBAL_STATIC(QGLEngineThreadStorage<QOpenGLPaintEngine>, qt_buffer_engine) #endif /*! \reimp */ QPaintEngine *QGLPixelBuffer::paintEngine() const { #if defined(QT_OPENGL_ES_1) - return qt_buffer_engine(); + return qt_buffer_engine()->engine(); #elif defined(QT_OPENGL_ES_2) - return qt_buffer_2_engine(); + return qt_buffer_2_engine()->engine(); #else if (qt_gl_preferGL2Engine()) - return qt_buffer_2_engine(); + return qt_buffer_2_engine()->engine(); else - return qt_buffer_engine(); + return qt_buffer_engine()->engine(); #endif } diff --git a/src/opengl/qglpixelbuffer_p.h b/src/opengl/qglpixelbuffer_p.h index 2a1f671..69678d0 100644 --- a/src/opengl/qglpixelbuffer_p.h +++ b/src/opengl/qglpixelbuffer_p.h @@ -197,6 +197,10 @@ public: EGLSurface pbuf; QEglContext *ctx; int textureFormat; +#elif defined(Q_WS_QPA) + //stubs + void *pbuf; + void *ctx; #endif }; diff --git a/src/opengl/qglpixelbuffer_stub.cpp b/src/opengl/qglpixelbuffer_stub.cpp new file mode 100644 index 0000000..2caef6b --- /dev/null +++ b/src/opengl/qglpixelbuffer_stub.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include <qdebug.h> +#include "qglpixelbuffer.h" +#include "qglpixelbuffer_p.h" + +#include <qimage.h> +#include <private/qgl_p.h> + +QT_BEGIN_NAMESPACE + +bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget) +{ + Q_UNUSED(size); + Q_UNUSED(f); + Q_UNUSED(shareWidget); + return false; +} + +bool QGLPixelBufferPrivate::cleanup() +{ + return false; +} + +bool QGLPixelBuffer::bindToDynamicTexture(GLuint texture_id) +{ + Q_UNUSED(texture_id); + return false; +} + +void QGLPixelBuffer::releaseFromDynamicTexture() +{ +} + +GLuint QGLPixelBuffer::generateDynamicTexture() const +{ + return 0; +} + +bool QGLPixelBuffer::hasOpenGLPbuffers() +{ + return false; +} + +QT_END_NAMESPACE diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index 74018cd..73d698c 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -315,7 +315,7 @@ class QGLBlurTextureCache : public QObject public: static QGLBlurTextureCache *cacheForContext(const QGLContext *context); - QGLBlurTextureCache(); + QGLBlurTextureCache(const QGLContext *); ~QGLBlurTextureCache(); QGLBlurTextureInfo *takeBlurTextureInfo(const QPixmap &pixmap); @@ -336,15 +336,9 @@ private: }; QList<QGLBlurTextureCache *> QGLBlurTextureCache::blurTextureCaches; +Q_GLOBAL_STATIC(QGLContextGroupResource<QGLBlurTextureCache>, qt_blur_texture_caches) -static void QGLBlurTextureCache_free(void *ptr) -{ - delete reinterpret_cast<QGLBlurTextureCache *>(ptr); -} - -Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_blur_texture_caches, (QGLBlurTextureCache_free)) - -QGLBlurTextureCache::QGLBlurTextureCache() +QGLBlurTextureCache::QGLBlurTextureCache(const QGLContext *) : timerId(0) { cache.setMaxCost(4 * 1024 * 1024); @@ -366,12 +360,7 @@ void QGLBlurTextureCache::timerEvent(QTimerEvent *) QGLBlurTextureCache *QGLBlurTextureCache::cacheForContext(const QGLContext *context) { - QGLBlurTextureCache *p = reinterpret_cast<QGLBlurTextureCache *>(qt_blur_texture_caches()->value(context)); - if (!p) { - p = new QGLBlurTextureCache; - qt_blur_texture_caches()->insert(context, p); - } - return p; + return qt_blur_texture_caches()->value(context); } QGLBlurTextureInfo *QGLBlurTextureCache::takeBlurTextureInfo(const QPixmap &pixmap) diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index bbb98d0..47f36dd 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -314,7 +314,7 @@ QPaintEngine *QGLWindowSurfaceGLPaintDevice::paintEngine() const QGLWindowSurface::QGLWindowSurface(QWidget *window) : QWindowSurface(window), d_ptr(new QGLWindowSurfacePrivate) { - Q_ASSERT(window->isTopLevel()); +// Q_ASSERT(window->isTopLevel()); d_ptr->pb = 0; d_ptr->fbo = 0; d_ptr->ctx = 0; @@ -358,12 +358,12 @@ void QGLWindowSurface::deleted(QObject *object) QWidgetPrivate *widgetPrivate = widget->d_func(); if (widgetPrivate->extraData()) { - union { QGLContext **ctxPtr; void **voidPtr; }; - voidPtr = &widgetPrivate->extraData()->glContext; - int index = d_ptr->contexts.indexOf(ctxPtr); + union { QGLContext **ctxPtrPtr; void **voidPtrPtr; }; + voidPtrPtr = &widgetPrivate->extraData()->glContext; + int index = d_ptr->contexts.indexOf(ctxPtrPtr); if (index != -1) { - delete *ctxPtr; - *ctxPtr = 0; + delete *ctxPtrPtr; + *ctxPtrPtr = 0; d_ptr->contexts.removeAt(index); } } @@ -397,16 +397,18 @@ void QGLWindowSurface::hijackWindow(QWidget *widget) setPartialUpdateSupport(false); // Force full-screen updates else setPartialUpdateSupport(true); +#else + setPartialUpdateSupport(false); #endif widgetPrivate->extraData()->glContext = ctx; - union { QGLContext **ctxPtr; void **voidPtr; }; + union { QGLContext **ctxPtrPtr; void **voidPtrPtr; }; connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(deleted(QObject*))); - voidPtr = &widgetPrivate->extraData()->glContext; - d_ptr->contexts << ctxPtr; + voidPtrPtr = &widgetPrivate->extraData()->glContext; + d_ptr->contexts << ctxPtrPtr; qDebug() << "hijackWindow() context created for" << widget << d_ptr->contexts.size(); } @@ -505,8 +507,13 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint & QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget(); Q_ASSERT(parent); +#if !defined(Q_WS_QPA) if (!geometry().isValid()) return; +#else + if (!size().isValid()) + return; +#endif // Needed to support native child-widgets... hijackWindow(parent); @@ -728,19 +735,31 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint & } +#if !defined(Q_WS_QPA) void QGLWindowSurface::setGeometry(const QRect &rect) { QWindowSurface::setGeometry(rect); d_ptr->geometry_updated = true; } - +#else +void QGLWindowSurface::resize(const QSize &size) +{ + QWindowSurface::resize(size); + d_ptr->geometry_updated = true; +} +#endif void QGLWindowSurface::updateGeometry() { if (!d_ptr->geometry_updated) return; d_ptr->geometry_updated = false; - QRect rect = geometry(); +#ifdef Q_WS_QPA + QSize surfSize = size(); +#else + QSize surfSize = geometry().size(); +#endif + hijackWindow(window()); QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext); @@ -750,18 +769,18 @@ void QGLWindowSurface::updateGeometry() { const GLenum target = GL_TEXTURE_2D; - if (rect.width() <= 0 || rect.height() <= 0) + if (surfSize.width() <= 0 || surfSize.height() <= 0) return; - if (d_ptr->size == rect.size()) + if (d_ptr->size == surfSize) return; - d_ptr->size = rect.size(); + d_ptr->size = surfSize; if (d_ptr->ctx) { #ifndef QT_OPENGL_ES_2 if (d_ptr->destructive_swap_buffers) - initializeOffscreenTexture(rect.size()); + initializeOffscreenTexture(surfSize); #endif return; } @@ -784,10 +803,10 @@ void QGLWindowSurface::updateGeometry() { if (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit) format.setSamples(8); - d_ptr->fbo = new QGLFramebufferObject(rect.size(), format); + d_ptr->fbo = new QGLFramebufferObject(surfSize, format); if (d_ptr->fbo->isValid()) { - qDebug() << "Created Window Surface FBO" << rect.size() + qDebug() << "Created Window Surface FBO" << surfSize << "with samples" << d_ptr->fbo->format().samples(); return; } else { @@ -808,7 +827,7 @@ void QGLWindowSurface::updateGeometry() { delete d_ptr->pb; - d_ptr->pb = new QGLPixelBuffer(rect.width(), rect.height(), + d_ptr->pb = new QGLPixelBuffer(surfSize.width(), surfSize.height(), QGLFormat(QGL::SampleBuffers | QGL::StencilBuffer | QGL::DepthBuffer), qt_gl_share_widget()); @@ -818,7 +837,7 @@ void QGLWindowSurface::updateGeometry() { glGenTextures(1, &d_ptr->pb_tex_id); glBindTexture(target, d_ptr->pb_tex_id); - glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexImage2D(target, 0, GL_RGBA, surfSize.width(), surfSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -842,7 +861,7 @@ void QGLWindowSurface::updateGeometry() { #ifndef QT_OPENGL_ES_2 if (d_ptr->destructive_swap_buffers) - initializeOffscreenTexture(rect.size()); + initializeOffscreenTexture(surfSize); #endif qDebug() << "QGLWindowSurface: Using plain widget as window surface" << this;; diff --git a/src/opengl/qwindowsurface_gl_p.h b/src/opengl/qwindowsurface_gl_p.h index 6906f35..4f4ec92 100644 --- a/src/opengl/qwindowsurface_gl_p.h +++ b/src/opengl/qwindowsurface_gl_p.h @@ -89,7 +89,13 @@ public: QPaintDevice *paintDevice(); void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + +#if !defined(Q_WS_QPA) void setGeometry(const QRect &rect); +#else + virtual void resize(const QSize &size); +#endif + void updateGeometry(); bool scroll(const QRegion &area, int dx, int dy); diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp index c608c81..e4edfcb 100644 --- a/src/openvg/qvg_symbian.cpp +++ b/src/openvg/qvg_symbian.cpp @@ -77,7 +77,8 @@ extern int qt_vg_pixmap_serial; static CFbsBitmap* createBlitCopy(CFbsBitmap* bitmap) { - CFbsBitmap *copy = q_check_ptr(new CFbsBitmap); + CFbsBitmap *copy = new CFbsBitmap; + Q_CHECK_PTR(copy); if(!copy) return 0; @@ -271,7 +272,8 @@ void* QVGPixmapData::toNativeType(NativeType type) return reinterpret_cast<void*>(sgImage.take()); #endif } else if (type == QPixmapData::FbsBitmap) { - CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); + CFbsBitmap *bitmap = new CFbsBitmap; + Q_CHECK_PTR(bitmap); if (bitmap) { if (bitmap->Create(TSize(source.width(), source.height()), diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp index 662663d..6eb0617 100644 --- a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp +++ b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp @@ -348,7 +348,7 @@ QVariant QAccessibleTextEdit::invokeMethodEx(QAccessible::Method method, int chi case ListSupportedMethods: { QSet<QAccessible::Method> set; set << ListSupportedMethods << SetCursorPosition << GetCursorPosition; - return qVariantFromValue(set | qvariant_cast<QSet<QAccessible::Method> >( + return QVariant::fromValue(set | qvariant_cast<QSet<QAccessible::Method> >( QAccessibleWidgetEx::invokeMethodEx(method, child, params))); } case SetCursorPosition: diff --git a/src/plugins/accessible/widgets/rangecontrols.cpp b/src/plugins/accessible/widgets/rangecontrols.cpp index 4cd171b..bf7b561 100644 --- a/src/plugins/accessible/widgets/rangecontrols.cpp +++ b/src/plugins/accessible/widgets/rangecontrols.cpp @@ -233,7 +233,7 @@ QVariant QAccessibleAbstractSpinBox::invokeMethodEx(Method method, int child, co case ListSupportedMethods: { QSet<QAccessible::Method> set; set << ListSupportedMethods; - return qVariantFromValue(set | qvariant_cast<QSet<QAccessible::Method> >( + return QVariant::fromValue(set | qvariant_cast<QSet<QAccessible::Method> >( QAccessibleWidgetEx::invokeMethodEx(method, child, params))); } default: @@ -814,7 +814,7 @@ QVariant QAccessibleAbstractSlider::invokeMethodEx(Method method, int child, con case ListSupportedMethods: { QSet<QAccessible::Method> set; set << ListSupportedMethods; - return qVariantFromValue(set | qvariant_cast<QSet<QAccessible::Method> >( + return QVariant::fromValue(set | qvariant_cast<QSet<QAccessible::Method> >( QAccessibleWidgetEx::invokeMethodEx(method, child, params))); } default: diff --git a/src/plugins/accessible/widgets/simplewidgets.cpp b/src/plugins/accessible/widgets/simplewidgets.cpp index 4a3acbb..eb6a909 100644 --- a/src/plugins/accessible/widgets/simplewidgets.cpp +++ b/src/plugins/accessible/widgets/simplewidgets.cpp @@ -732,7 +732,7 @@ QVariant QAccessibleLineEdit::invokeMethodEx(QAccessible::Method method, int chi case ListSupportedMethods: { QSet<QAccessible::Method> set; set << ListSupportedMethods << SetCursorPosition << GetCursorPosition; - return qVariantFromValue(set | qvariant_cast<QSet<QAccessible::Method> >( + return QVariant::fromValue(set | qvariant_cast<QSet<QAccessible::Method> >( QAccessibleWidgetEx::invokeMethodEx(method, child, params))); } case SetCursorPosition: diff --git a/src/plugins/bearer/connman/qconnmanservice_linux.cpp b/src/plugins/bearer/connman/qconnmanservice_linux.cpp index 952a444..b66298e 100644 --- a/src/plugins/bearer/connman/qconnmanservice_linux.cpp +++ b/src/plugins/bearer/connman/qconnmanservice_linux.cpp @@ -1049,7 +1049,7 @@ QVariantMap QConnmanDeviceInterface::getProperties() bool QConnmanDeviceInterface::setProperty(const QString &name, const QDBusVariant &value) { - QDBusMessage reply = this->call(QLatin1String("SetProperty"),name, qVariantFromValue(value)); + QDBusMessage reply = this->call(QLatin1String("SetProperty"),name, QVariant::fromValue(value)); return true; } @@ -1111,7 +1111,7 @@ quint16 QConnmanDeviceInterface::getScanInterval() bool QConnmanDeviceInterface::setScanInterval(const QString & interval) { // QList<QVariant> args; -// args << qVariantFromValue(name) +// args << QVariant::fromValue(name) // << value.variant(); // QDBusMessage reply = this->callWithArgumentList(QDBus::AutoDetect,QLatin1String("SetProperty"),args); @@ -1134,8 +1134,8 @@ QStringList QConnmanDeviceInterface::getNetworks() bool QConnmanDeviceInterface::setEnabled(bool powered) { QList<QVariant> args; - args << qVariantFromValue(QString("Powered")) - << qVariantFromValue(QDBusVariant(powered)); + args << QVariant::fromValue(QString("Powered")) + << QVariant::fromValue(QDBusVariant(powered)); QDBusMessage reply = this->callWithArgumentList(QDBus::AutoDetect,QLatin1String("SetProperty"),args); return true; diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm index 844e38b..db577fd 100644 --- a/src/plugins/bearer/corewlan/qcorewlanengine.mm +++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm @@ -850,7 +850,7 @@ quint64 QCoreWlanEngine::bytesReceived(const QString &id) return getBytes(interfaceStr,true); } -quint64 QCoreWlanEngine::startTime(const QString &id) +quint64 QCoreWlanEngine::startTime(const QString &identifier) { QMutexLocker locker(&mutex); QMacCocoaAutoReleasePool pool; @@ -885,7 +885,7 @@ quint64 QCoreWlanEngine::startTime(const QString &id) for(int i = 0; i < dictSize; i++) { if([ssidStr isEqualToString:keys[i]]) { const QString ident = QString::number(qHash(QLatin1String("corewlan:") + qt_mac_NSStringToQString(objects[i]))); - if(ident == id) { + if(ident == identifier) { ok = true; } } diff --git a/src/plugins/bearer/platformdefs_win.h b/src/plugins/bearer/platformdefs_win.h index 1a10ba7..68343cf 100644 --- a/src/plugins/bearer/platformdefs_win.h +++ b/src/plugins/bearer/platformdefs_win.h @@ -53,6 +53,7 @@ QT_BEGIN_NAMESPACE #define NS_NLA 15 +#ifndef NLA_NAMESPACE_GUID enum NLA_BLOB_DATA_TYPE { NLA_RAW_DATA = 0, NLA_INTERFACE = 1, @@ -115,6 +116,8 @@ struct NLA_BLOB { } ICS; } data; }; +#endif // NLA_NAMESPACE_GUID + #endif enum NDIS_MEDIUM { diff --git a/src/plugins/generic/linuxinput/linuxinput.pro b/src/plugins/generic/linuxinput/linuxinput.pro new file mode 100644 index 0000000..ad9f6a9 --- /dev/null +++ b/src/plugins/generic/linuxinput/linuxinput.pro @@ -0,0 +1,18 @@ +TARGET = qlinuxinputplugin +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/generic +target.path = $$[QT_INSTALL_PLUGINS]/generic +INSTALLS += target + +DEFINES += QT_QWS_KBD_LINUXINPUT + +HEADERS = qlinuxinput.h + +SOURCES = main.cpp \ + qlinuxinput.cpp + +HEADERS += $$QT_SOURCE_TREE/src/gui/embedded/qkbd_qws.h \ + $$QT_SOURCE_TREE/src/gui/embedded/qkbd_qws_p.h + +SOURCES += $$QT_SOURCE_TREE/src/gui/embedded/qkbd_qws.cpp diff --git a/src/plugins/generic/linuxinput/main.cpp b/src/plugins/generic/linuxinput/main.cpp new file mode 100644 index 0000000..dc05254 --- /dev/null +++ b/src/plugins/generic/linuxinput/main.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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 plugins 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 <qgenericplugin_qpa.h> +#include "qlinuxinput.h" + +QT_BEGIN_NAMESPACE + +class QLinuxInputPlugin : public QGenericPlugin +{ +public: + QLinuxInputPlugin(); + + QStringList keys() const; + QObject* create(const QString &key, const QString &specification); +}; + +QLinuxInputPlugin::QLinuxInputPlugin() + : QGenericPlugin() +{ +} + +QStringList QLinuxInputPlugin::keys() const +{ + return (QStringList() + << QLatin1String("LinuxInputMouse") + << QLatin1String("LinuxInputKeyboard")); +} + +QObject* QLinuxInputPlugin::create(const QString &key, + const QString &specification) +{ + if (!key.compare(QLatin1String("LinuxInputMouse"), Qt::CaseInsensitive)) + return new QLinuxInputMouseHandler(key, specification); + if (!key.compare(QLatin1String("LinuxInputKeyboard"), Qt::CaseInsensitive)) + return new QLinuxInputKeyboardHandler(key, specification); + return 0; + } + +Q_EXPORT_PLUGIN2(qlinuxinputplugin, QLinuxInputPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/generic/linuxinput/qlinuxinput.cpp b/src/plugins/generic/linuxinput/qlinuxinput.cpp new file mode 100644 index 0000000..c5bfd33 --- /dev/null +++ b/src/plugins/generic/linuxinput/qlinuxinput.cpp @@ -0,0 +1,557 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qlinuxinput.h" + + +#include <QSocketNotifier> +#include <QStringList> +#include <QPoint> +#include <QWindowSystemInterface> + +#include <qkbd_qws.h> + + +#include <qplatformdefs.h> +#include <private/qcore_unix_p.h> // overrides QT_OPEN + +#include <errno.h> +#include <termios.h> + +#include <linux/kd.h> +#include <linux/input.h> + +#include <qdebug.h> + +QT_BEGIN_NAMESPACE + + +//#define QT_QPA_EXPERIMENTAL_TOUCHEVENT + +#ifdef QT_QPA_EXPERIMENTAL_TOUCHEVENT +class QLinuxInputMouseHandlerData +{ +public: + QLinuxInputMouseHandlerData() :seenMT(false), state(QEvent::TouchBegin), currentIdx(0) {} + + void ensureCurrentPoint() { + if (currentIdx >= touchPoints.size()) { + Q_ASSERT(currentIdx == touchPoints.size()); + QWindowSystemInterface::TouchPoint tp; + tp.id = currentIdx; + tp.isPrimary = (currentIdx == 0); + tp.pressure = 1; + tp.area = QRectF(0,0,1,1); + tp.state = Qt::TouchPointReleased; // init in neutral state + touchPoints.append(tp); + } + } + void setCurrentPoint(int i) { + currentIdx = i; + if (currentIdx < touchPoints.size()) { + currentX = int(touchPoints[currentIdx].area.left()); + currentY = int(touchPoints[currentIdx].area.top()); + } else { + currentY = currentX = -999; + } + } + void advanceCurrentPoint() { + setCurrentPoint(currentIdx + 1); + } + int currentPoint() { return currentIdx; } + void setCurrentX(int value) { + ensureCurrentPoint(); + touchPoints[currentIdx].area.moveLeft(value); + } + bool currentMoved() { + return currentX != touchPoints[currentIdx].area.left() || currentY != touchPoints[currentIdx].area.top(); + } + void updateCurrentPos() { + ensureCurrentPoint(); + touchPoints[currentIdx].area.moveTopLeft(QPointF(currentX, currentY)); + } + void setCurrentState(Qt::TouchPointState state) { + ensureCurrentPoint(); + touchPoints[currentIdx].state = state; + } + Qt::TouchPointState currentState() const { + if (currentIdx < touchPoints.size()) + return touchPoints[currentIdx].state; + return Qt::TouchPointReleased; + } + QList<QWindowSystemInterface::TouchPoint> touchPoints; + int currentX; + int currentY; + bool seenMT; + QEvent::Type state; +private: + int currentIdx; +}; +#endif + + +QLinuxInputMouseHandler::QLinuxInputMouseHandler(const QString &key, + const QString &specification) + : m_notify(0), m_x(0), m_y(0), m_prevx(0), m_prevy(0), m_xoffset(0), m_yoffset(0), m_buttons(0), d(0) +{ + qDebug() << "QLinuxInputMouseHandler" << key << specification; + + + setObjectName(QLatin1String("LinuxInputSubsystem Mouse Handler")); + + QString dev = QLatin1String("/dev/input/event0"); + m_compression = true; + m_smooth = false; + int jitterLimit = 0; + + QStringList args = specification.split(QLatin1Char(':')); + foreach (const QString &arg, args) { + if (arg == "nocompress") + m_compression = false; + else if (arg.startsWith("dejitter=")) + jitterLimit = arg.mid(9).toInt(); + else if (arg.startsWith("xoffset=")) + m_xoffset = arg.mid(8).toInt(); + else if (arg.startsWith("yoffset=")) + m_yoffset = arg.mid(8).toInt(); + else if (arg.startsWith(QLatin1String("/dev/"))) + dev = arg; + } + m_jitterLimitSquared = jitterLimit*jitterLimit; + + m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0); + if (m_fd >= 0) { + m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); + connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData())); + } else { + qWarning("Cannot open mouse input device '%s': %s", qPrintable(dev), strerror(errno)); + return; + } +#ifdef QT_QPA_EXPERIMENTAL_TOUCHEVENT + d = new QLinuxInputMouseHandlerData; +#endif +} + + +QLinuxInputMouseHandler::~QLinuxInputMouseHandler() +{ + if (m_fd >= 0) + QT_CLOSE(m_fd); +#ifdef QT_QPA_EXPERIMENTAL_TOUCHEVENT + delete d; +#endif +} + +void QLinuxInputMouseHandler::sendMouseEvent(int x, int y, Qt::MouseButtons buttons) +{ + QPoint pos(x+m_xoffset, y+m_yoffset); + QWindowSystemInterface::handleMouseEvent(0, pos, pos, m_buttons); + m_prevx = x; + m_prevy = y; +} + +void QLinuxInputMouseHandler::readMouseData() +{ + struct ::input_event buffer[32]; + int n = 0; + bool posChanged = false; + bool pendingMouseEvent = false; + int eventCompressCount = 0; + forever { + n = QT_READ(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n); + + if (n == 0) { + qWarning("Got EOF from the input device."); + return; + } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) { + qWarning("Could not read from input device: %s", strerror(errno)); + return; + } else if (n % sizeof(buffer[0]) == 0) { + break; + } + } + + n /= sizeof(buffer[0]); + + for (int i = 0; i < n; ++i) { + struct ::input_event *data = &buffer[i]; + //qDebug() << ">>" << hex << data->type << data->code << dec << data->value; + bool unknown = false; + if (data->type == EV_ABS) { + if (data->code == ABS_X && m_x != data->value) { + m_x = data->value; + posChanged = true; + } else if (data->code == ABS_Y && m_y != data->value) { + m_y = data->value; + posChanged = true; + } else if (data->code == ABS_PRESSURE) { + //ignore for now... + } else if (data->code == ABS_TOOL_WIDTH) { + //ignore for now... + } else if (data->code == ABS_HAT0X) { + //ignore for now... + } else if (data->code == ABS_HAT0Y) { + //ignore for now... +#ifdef QT_QPA_EXPERIMENTAL_TOUCHEVENT + } else if (data->code == ABS_MT_POSITION_X) { + d->currentX = data->value; + d->seenMT = true; + } else if (data->code == ABS_MT_POSITION_Y) { + d->currentY = data->value; + d->seenMT = true; + } else if (data->code == ABS_MT_TOUCH_MAJOR) { + if (data->value == 0) + d->setCurrentState(Qt::TouchPointReleased); + //otherwise, ignore for now... + } else if (data->code == ABS_MT_TOUCH_MINOR) { + //ignore for now... +#endif + } else { + unknown = true; + } + } else if (data->type == EV_REL) { + if (data->code == REL_X) { + m_x += data->value; + posChanged = true; + } else if (data->code == REL_Y) { + m_y += data->value; + posChanged = true; + } else if (data->code == ABS_WHEEL) { // vertical scroll + // data->value: 1 == up, -1 == down + int delta = 120 * data->value; + QWindowSystemInterface::handleWheelEvent(0, QPoint(m_x, m_y), + QPoint(m_x, m_y), + delta, Qt::Vertical); + } else if (data->code == ABS_THROTTLE) { // horizontal scroll + // data->value: 1 == right, -1 == left + int delta = 120 * -data->value; + QWindowSystemInterface::handleWheelEvent(0, QPoint(m_x, m_y), + QPoint(m_x, m_y), + delta, Qt::Horizontal); + } else { + unknown = true; + } + } else if (data->type == EV_KEY && data->code == BTN_TOUCH) { + m_buttons = data->value ? Qt::LeftButton : Qt::NoButton; + + sendMouseEvent(m_x, m_y, m_buttons); + pendingMouseEvent = false; + } else if (data->type == EV_KEY && data->code >= BTN_LEFT && data->code <= BTN_MIDDLE) { + Qt::MouseButton button = Qt::NoButton; + switch (data->code) { + case BTN_LEFT: button = Qt::LeftButton; break; + case BTN_MIDDLE: button = Qt::MidButton; break; + case BTN_RIGHT: button = Qt::RightButton; break; + } + if (data->value) + m_buttons |= button; + else + m_buttons &= ~button; + sendMouseEvent(m_x, m_y, m_buttons); + pendingMouseEvent = false; + } else if (data->type == EV_SYN && data->code == SYN_REPORT) { + if (posChanged) { + posChanged = false; + if (m_compression) { + pendingMouseEvent = true; + eventCompressCount++; + } else { + sendMouseEvent(m_x, m_y, m_buttons); + } + } +#ifdef QT_QPA_EXPERIMENTAL_TOUCHEVENT + if (d->state == QEvent::TouchBegin && !d->seenMT) { + //no multipoint-touch events to send + } else { + if (!d->seenMT) + d->state = QEvent::TouchEnd; + + for (int i = d->currentPoint(); i < d->touchPoints.size(); ++i) { + d->touchPoints[i].pressure = 0; + d->touchPoints[i].state = Qt::TouchPointReleased; + } + //qDebug() << "handleTouchEvent" << d->state << d->touchPoints.size() << d->touchPoints[0].state; + QWindowSystemInterface::handleTouchEvent(0, d->state, QTouchEvent::TouchScreen, d->touchPoints); + if (d->seenMT) { + d->state = QEvent::TouchUpdate; + } else { + d->state = QEvent::TouchBegin; + d->touchPoints.clear(); + } + d->setCurrentPoint(0); + d->seenMT = false; + } + } else if (data->type == EV_SYN && data->code == SYN_MT_REPORT) { + //store data for this touch point + + if (!d->seenMT) { + d->setCurrentState(Qt::TouchPointReleased); + } else if (d->currentState() == Qt::TouchPointReleased) { + d->updateCurrentPos(); + d->setCurrentState(Qt::TouchPointPressed); + } else if (d->currentMoved()) { + d->updateCurrentPos(); + d->setCurrentState(Qt::TouchPointMoved); + } else { + d->setCurrentState(Qt::TouchPointStationary); + } + //qDebug() << "end of point" << d->currentPoint() << d->currentX << d->currentY << d->currentState(); + + //advance to next tp: + d->advanceCurrentPoint(); +#endif + } else if (data->type == EV_MSC && data->code == MSC_SCAN) { + // kernel encountered an unmapped key - just ignore it + continue; + } else { + unknown = true; + } +#ifdef QLINUXINPUT_EXTRA_DEBUG + if (unknown) { + qWarning("unknown mouse event type=%x, code=%x, value=%x", data->type, data->code, data->value); + } +#endif + } + if (m_compression && pendingMouseEvent) { + int distanceSquared = (m_x - m_prevx)*(m_x - m_prevx) + (m_y - m_prevy)*(m_y - m_prevy); + if (distanceSquared > m_jitterLimitSquared) + sendMouseEvent(m_x, m_y, m_buttons); + } +} + + + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//Keyboard handler + + + + +class QWSLinuxInputKeyboardHandler : public QWSKeyboardHandler +{ +public: + QWSLinuxInputKeyboardHandler(const QString&); + ~QWSLinuxInputKeyboardHandler(); + + virtual bool filterInputEvent(quint16 &input_code, qint32 &input_value); + +//private: +// QWSLinuxInputKbPrivate *d; +}; + + +QWSLinuxInputKeyboardHandler::QWSLinuxInputKeyboardHandler(const QString &device) + : QWSKeyboardHandler(device) +{ +} + +QWSLinuxInputKeyboardHandler::~QWSLinuxInputKeyboardHandler() +{ +} + +bool QWSLinuxInputKeyboardHandler::filterInputEvent(quint16 &, qint32 &) +{ + return false; +} + + +QLinuxInputKeyboardHandler::QLinuxInputKeyboardHandler(const QString &key, const QString &specification) + : m_handler(0), m_fd(-1), m_tty_fd(-1), m_orig_kbmode(K_XLATE) +{ + setObjectName(QLatin1String("LinuxInputSubsystem Keyboard Handler")); + + QString dev = QLatin1String("/dev/input/event1"); + int repeat_delay = -1; + int repeat_rate = -1; + + bool ttymode = false; + + QStringList args = specification.split(QLatin1Char(':')); + foreach (const QString &arg, args) { + if (arg.startsWith(QLatin1String("repeat-delay="))) + repeat_delay = arg.mid(13).toInt(); + else if (arg.startsWith(QLatin1String("repeat-rate="))) + repeat_rate = arg.mid(12).toInt(); + else if (arg.startsWith(QLatin1String("ttymode"))) + ttymode = true; + else if (arg.startsWith(QLatin1String("/dev/"))) + dev = arg; + } + + m_handler = new QWSLinuxInputKeyboardHandler(dev); //This is a hack to avoid copying all the QWS code + + m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDWR, 0); + if (m_fd >= 0) { + if (repeat_delay > 0 && repeat_rate > 0) { + int kbdrep[2] = { repeat_delay, repeat_rate }; + ::ioctl(m_fd, EVIOCSREP, kbdrep); + } + + QSocketNotifier *notifier; + notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); + connect(notifier, SIGNAL(activated(int)), this, SLOT(readKeycode())); + + if (ttymode) { + // play nice in case we are started from a shell (e.g. for debugging) + m_tty_fd = isatty(0) ? 0 : -1; + + if (m_tty_fd >= 0) { + // save tty config for restore. + tcgetattr(m_tty_fd, &m_tty_attr); + + struct ::termios termdata; + tcgetattr(m_tty_fd, &termdata); + + // record the original mode so we can restore it again in the destructor. + ::ioctl(m_tty_fd, KDGKBMODE, &m_orig_kbmode); + + // setting this translation mode is even needed in INPUT mode to prevent + // the shell from also interpreting codes, if the process has a tty + // attached: e.g. Ctrl+C wouldn't copy, but kill the application. + ::ioctl(m_tty_fd, KDSKBMODE, K_MEDIUMRAW); + + // set the tty layer to pass-through + termdata.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); + termdata.c_oflag = 0; + termdata.c_cflag = CREAD | CS8; + termdata.c_lflag = 0; + termdata.c_cc[VTIME]=0; + termdata.c_cc[VMIN]=1; + cfsetispeed(&termdata, 9600); + cfsetospeed(&termdata, 9600); + tcsetattr(m_tty_fd, TCSANOW, &termdata); + } + } + } else { + qWarning("Cannot open keyboard input device '%s': %s", qPrintable(dev), strerror(errno)); + return; + } +} + +QLinuxInputKeyboardHandler::~QLinuxInputKeyboardHandler() +{ + if (m_tty_fd >= 0) { + ::ioctl(m_tty_fd, KDSKBMODE, m_orig_kbmode); + tcsetattr(m_tty_fd, TCSANOW, &m_tty_attr); + } + if (m_fd >= 0) + QT_CLOSE(m_fd); + delete m_handler; +} + +void QLinuxInputKeyboardHandler::switchLed(int led, bool state) +{ + struct ::input_event led_ie; + ::gettimeofday(&led_ie.time, 0); + led_ie.type = EV_LED; + led_ie.code = led; + led_ie.value = state; + + QT_WRITE(m_fd, &led_ie, sizeof(led_ie)); +} + + + +void QLinuxInputKeyboardHandler::readKeycode() +{ + struct ::input_event buffer[32]; + int n = 0; + + forever { + n = QT_READ(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n); + + if (n == 0) { + qWarning("Got EOF from the input device."); + return; + } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) { + qWarning("Could not read from input device: %s", strerror(errno)); + return; + } else if (n % sizeof(buffer[0]) == 0) { + break; + } + } + + n /= sizeof(buffer[0]); + + for (int i = 0; i < n; ++i) { + if (buffer[i].type != EV_KEY) + continue; + + quint16 code = buffer[i].code; + qint32 value = buffer[i].value; + + if (m_handler->filterInputEvent(code, value)) + continue; + + QWSKeyboardHandler::KeycodeAction ka; + ka = m_handler->processKeycode(code, value != 0, value == 2); + + switch (ka) { + case QWSKeyboardHandler::CapsLockOn: + case QWSKeyboardHandler::CapsLockOff: + switchLed(LED_CAPSL, ka == QWSKeyboardHandler::CapsLockOn); + break; + + case QWSKeyboardHandler::NumLockOn: + case QWSKeyboardHandler::NumLockOff: + switchLed(LED_NUML, ka == QWSKeyboardHandler::NumLockOn); + break; + + case QWSKeyboardHandler::ScrollLockOn: + case QWSKeyboardHandler::ScrollLockOff: + switchLed(LED_SCROLLL, ka == QWSKeyboardHandler::ScrollLockOn); + break; + + default: + // ignore console switching and reboot + break; + } + } +} + + + + + +QT_END_NAMESPACE + diff --git a/src/plugins/generic/linuxinput/qlinuxinput.h b/src/plugins/generic/linuxinput/qlinuxinput.h new file mode 100644 index 0000000..c94c0f4 --- /dev/null +++ b/src/plugins/generic/linuxinput/qlinuxinput.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QLINUXINPUT_H +#define QLINUXINPUT_H + +#include <qobject.h> +#include <Qt> +#include <termios.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QSocketNotifier; + +class QLinuxInputMouseHandlerData; + +class QLinuxInputMouseHandler : public QObject +{ + Q_OBJECT +public: + QLinuxInputMouseHandler(const QString &key, const QString &specification); + ~QLinuxInputMouseHandler(); + +private slots: + void readMouseData(); + +private: + void sendMouseEvent(int x, int y, Qt::MouseButtons buttons); + QSocketNotifier * m_notify; + int m_fd; + int m_x, m_y; + int m_prevx, m_prevy; + int m_xoffset, m_yoffset; + int m_smoothx, m_smoothy; + Qt::MouseButtons m_buttons; + bool m_compression; + bool m_smooth; + int m_jitterLimitSquared; + QLinuxInputMouseHandlerData *d; +}; + + +class QWSLinuxInputKeyboardHandler; + +class QLinuxInputKeyboardHandler : public QObject +{ + Q_OBJECT +public: + QLinuxInputKeyboardHandler(const QString &key, const QString &specification); + ~QLinuxInputKeyboardHandler(); + + +private: + void switchLed(int, bool); + +private slots: + void readKeycode(); + +private: + QWSLinuxInputKeyboardHandler *m_handler; + int m_fd; + int m_tty_fd; + struct termios m_tty_attr; + int m_orig_kbmode; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QLINUXINPUT_H diff --git a/src/plugins/generic/tslib/main.cpp b/src/plugins/generic/tslib/main.cpp new file mode 100644 index 0000000..502c6a0 --- /dev/null +++ b/src/plugins/generic/tslib/main.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** 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 plugins 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 <qgenericplugin_qpa.h> +#include "qtslib.h" + +QT_BEGIN_NAMESPACE + +class QTsLibPlugin : public QGenericPlugin +{ +public: + QTsLibPlugin(); + + QStringList keys() const; + QObject* create(const QString &key, const QString &specification); +}; + +QTsLibPlugin::QTsLibPlugin() + : QGenericPlugin() +{ +} + +QStringList QTsLibPlugin::keys() const +{ + return (QStringList() + << QLatin1String("Tslib") + << QLatin1String("TslibRaw")); +} + +QObject* QTsLibPlugin::create(const QString &key, + const QString &specification) +{ + if (!key.compare(QLatin1String("Tslib"), Qt::CaseInsensitive) || !key.compare(QLatin1String("TslibRaw"), Qt::CaseInsensitive)) + return new QTsLibMouseHandler(key, specification); + return 0; + } + +Q_EXPORT_PLUGIN2(qtslibplugin, QTsLibPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/generic/tslib/qtslib.cpp b/src/plugins/generic/tslib/qtslib.cpp new file mode 100644 index 0000000..12963a0 --- /dev/null +++ b/src/plugins/generic/tslib/qtslib.cpp @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qtslib.h" + + +#include <QSocketNotifier> +#include <QStringList> +#include <QPoint> +#include <QWindowSystemInterface> + +#include <Qt> + +#include <errno.h> +#include <tslib.h> + +#include <qdebug.h> + +QT_BEGIN_NAMESPACE + +QTsLibMouseHandler::QTsLibMouseHandler(const QString &key, + const QString &specification) + : m_notify(0), m_x(0), m_y(0), m_pressed(0), m_rawMode(false) +{ + qDebug() << "QTsLibMouseHandler" << key << specification; + setObjectName(QLatin1String("TSLib Mouse Handler")); + + QByteArray device = "/dev/input/event1"; + if (specification.startsWith("/dev/")) + device = specification.toLocal8Bit(); + + m_dev = ts_open(device.constData(), 1); + + if (ts_config(m_dev)) { + perror("Error configuring\n"); + } + + + m_rawMode = !key.compare(QLatin1String("TslibRaw"), Qt::CaseInsensitive); + + int fd = ts_fd(m_dev); + if (fd >= 0) { + m_notify = new QSocketNotifier(fd, QSocketNotifier::Read, this); + connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData())); + } else { + qWarning("Cannot open mouse input device '%s': %s", device.constData(), strerror(errno)); + return; + } +} + + +QTsLibMouseHandler::~QTsLibMouseHandler() +{ + if (m_dev) + ts_close(m_dev); +} + + +static bool get_sample(struct tsdev *dev, struct ts_sample *sample, bool rawMode) +{ + if (rawMode) { + return (ts_read_raw(dev, sample, 1) == 1); + } else { + int ret = ts_read(dev, sample, 1); + return ( ret == 1); + } +} + + +void QTsLibMouseHandler::readMouseData() +{ + ts_sample sample; + while (get_sample(m_dev, &sample, m_rawMode)) { + + bool pressed = sample.pressure; + int x = sample.x; + int y = sample.y; + + + if (!m_rawMode) { + //filtering: ignore movements of 2 pixels or less + int dx = x - m_x; + int dy = y - m_y; + if (dx*dx <= 4 && dy*dy <= 4 && pressed == m_pressed) + continue; + } else { + // work around missing coordinates on mouse release in raw mode + if (sample.pressure == 0 && sample.x == 0 && sample.y == 0) { + x = m_x; + y = m_y; + } + } + QPoint pos(x, y); + + //printf("handleMouseEvent %d %d %d %ld\n", m_x, m_y, pressed, sample.tv.tv_usec); + + QWindowSystemInterface::handleMouseEvent(0, pos, pos, pressed ? Qt::LeftButton : Qt::NoButton); + + m_x = x; + m_y = y; + m_pressed = pressed; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/generic/tslib/qtslib.h b/src/plugins/generic/tslib/qtslib.h new file mode 100644 index 0000000..5eab8b9 --- /dev/null +++ b/src/plugins/generic/tslib/qtslib.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QTSLIB_H +#define QTSLIB_H + +#include <qobject.h> +//#include <Qt> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QSocketNotifier; +struct tsdev; + +class QTsLibMouseHandler : public QObject +{ + Q_OBJECT +public: + QTsLibMouseHandler(const QString &key, const QString &specification); + ~QTsLibMouseHandler(); + +private slots: + void readMouseData(); + +private: + QSocketNotifier * m_notify; + tsdev *m_dev; + int m_x, m_y; + bool m_pressed; + bool m_rawMode; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QTSLIB_H diff --git a/src/plugins/generic/tslib/tslib.pro b/src/plugins/generic/tslib/tslib.pro new file mode 100644 index 0000000..74c7fd2 --- /dev/null +++ b/src/plugins/generic/tslib/tslib.pro @@ -0,0 +1,13 @@ +TARGET = qlinuxinputplugin +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/generic +target.path = $$[QT_INSTALL_PLUGINS]/generic +INSTALLS += target + +HEADERS = qtslib.h + +SOURCES = main.cpp \ + qtslib.cpp + +LIBS += -lts diff --git a/src/plugins/gfxdrivers/eglnullws/README b/src/plugins/gfxdrivers/eglnullws/README new file mode 100644 index 0000000..80b88c7 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/README @@ -0,0 +1,48 @@ +EGL NullWS QScreen Driver +========================= + +If your application draws everything within a single full-screen QGLWidget then +you may wish to use this QScreen plugin driver. This driver simply returns 0 +(as a EGLNativeWindowType value) when asked by the QtOpenGl module to create a +native window. Some OpenGL ES implementations (including PowerVR) interpret this +to mean that a full-screen OpenGL context is desired without any windowing +support (NullWS). + +To tell a Qt/Embedded application to use this driver use the -display command +line option or the QWS_DISPLAY environment variable. The following driver +options are supported: + +size=WIDTHxHEIGHT Screen size reported by the driver +format=FORMAT Screen format + +Run with '-display eglnullws:help' to get a full list of options (including a +list of supported format strings). + +If you choose a screen format that is not supported by the hardware then the +QtOpenGl module will write out a list of supported EGL configurations. Use +one of the supported screen formats from this list. + +Using this driver with PowerVR hardware +--------------------------------------- + +Using this plugin with PowerVR hardware should give a significant speedup +compared to running with the Qt powervr driver (with a full-screen QGLWidget). +This is because sacrificing the window system allows less work to be done in +order to get graphics on the screen. Using this driver also avoids the memory +fragmentation issues present in the powervr driver and avoids any direct +dependencies on the deprecated PVR2D API from Imagination Technologies. + +To use this driver ensure you have /etc/powervr.ini with contents similar to +this: + +[default] +WindowSystem=libpvrPVR2D_FLIPWSEGL.so + +This driver will also function with libpvrPVR2D_FRONTWSEGL.so, but that draws +straight into the framebuffer and will therefore cause flickering (it can be +useful for performance testing though). The flip plugin uses triple buffering, +so you will need to set the virtual vertical resolution of your framebuffer to +be three times the physical vertical resolution of your screen. This can be +done with 'fbset -vyres'. Failure to do this can cause system crashes. You +should also ensure that the plugin you choose in powervr.ini is in your library +path (it may just silently default to the flip plugin if not). diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullws.pro b/src/plugins/gfxdrivers/eglnullws/eglnullws.pro new file mode 100644 index 0000000..242ab07 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullws.pro @@ -0,0 +1,18 @@ +TARGET = qeglnullws +include(../../qpluginbase.pri) + +CONFIG += warn_on +QT += opengl + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/gfxdrivers + +target.path = $$[QT_INSTALL_PLUGINS]/gfxdrivers +INSTALLS += target + +HEADERS = eglnullwsscreen.h \ + eglnullwsscreenplugin.h \ + eglnullwswindowsurface.h + +SOURCES = eglnullwsscreen.cpp \ + eglnullwsscreenplugin.cpp \ + eglnullwswindowsurface.cpp diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.cpp b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.cpp new file mode 100644 index 0000000..b8ea5d5 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.cpp @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** 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 plugins 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 "eglnullwsscreen.h" +#include "eglnullwswindowsurface.h" +#include "eglnullwsscreenplugin.h" + +#include <QHash> +#include <QDebug> + +namespace +{ + class EGLNullWSScreenSurfaceFunctions : public QGLScreenSurfaceFunctions + { + public: + virtual bool createNativeWindow(QWidget *, EGLNativeWindowType *native) + { *native = 0; return true; } + }; +} + +EGLNullWSScreen::EGLNullWSScreen(int displayId) : QGLScreen(displayId) {} + +EGLNullWSScreen::~EGLNullWSScreen() {} + +bool EGLNullWSScreen::initDevice() +{ + setSurfaceFunctions(new EGLNullWSScreenSurfaceFunctions); + return true; +} + +static const QHash<QString, QImage::Format> formatDictionary() +{ + QHash<QString, QImage::Format> dictionary; + dictionary["rgb32"] = QImage::Format_RGB32; + dictionary["argb32"] = QImage::Format_ARGB32; + dictionary["rgb16"] = QImage::Format_RGB16; + dictionary["rgb666"] = QImage::Format_RGB666; + dictionary["rgb555"] = QImage::Format_RGB555; + dictionary["rgb888"] = QImage::Format_RGB888; + dictionary["rgb444"] = QImage::Format_RGB444; + return dictionary; +} + +static int depthForFormat(QImage::Format format) +{ + switch (format) { + case QImage::Format_RGB32: return 32; + case QImage::Format_ARGB32: return 32; + case QImage::Format_RGB16: return 16; + case QImage::Format_RGB666: return 24; + case QImage::Format_RGB555: return 16; + case QImage::Format_RGB888: return 24; + case QImage::Format_RGB444: return 16; + default: + Q_ASSERT_X(false, "EGLNullWSScreen", "Unknown format"); + return -1; + } +} + +static void printHelp(const QHash<QString, QImage::Format> &formatDictionary) +{ + QByteArray formatsBuf; + QTextStream(&formatsBuf) << QStringList(formatDictionary.keys()).join(", "); + qWarning( + "%s: Valid options are:\n" + "size=WIDTHxHEIGHT Screen size reported by this driver\n" + "format=FORMAT Screen format, where FORMAT is one of the following:\n" + " %s\n", + PluginName, + formatsBuf.constData()); +} + +bool EGLNullWSScreen::connect(const QString &displaySpec) +{ + const QStringList args = displaySpec.section(':', 1).split(':', QString::SkipEmptyParts); + const QHash<QString, QImage::Format> formatDict = formatDictionary(); + Q_FOREACH(const QString arg, args) { + const QString optionName = arg.section('=', 0, 0); + const QString optionArg = arg.section('=', 1); + if (optionName == QLatin1String("size")) { + w = optionArg.section('x', 0, 0).toInt(); + h = optionArg.section('x', 1, 1).toInt(); + } else if (optionName == QLatin1String("format")) { + if (formatDict.contains(optionArg)) + setPixelFormat(formatDict.value(optionArg)); + else + printHelp(formatDict); + } else { + printHelp(formatDict); + } + } + + if (w == 0 || h == 0) { + w = 640; + h = 480; + qWarning("%s: Using default screen size %dx%d", PluginName, w, h); + } + dw = w; + dh = h; + + if (pixelFormat() == QImage::Format_Invalid) { + qWarning("%s: Using default screen format argb32", PluginName); + setPixelFormat(QImage::Format_ARGB32); + } + d = depthForFormat(pixelFormat()); + + static const int Dpi = 120; + static const qreal ScalingFactor = static_cast<qreal>(25.4) / Dpi; + physWidth = qRound(dw * ScalingFactor); + physHeight = qRound(dh * ScalingFactor); + + return true; +} + +void EGLNullWSScreen::disconnect() {} + +void EGLNullWSScreen::shutdownDevice() {} + +void EGLNullWSScreen::setMode(int /*width*/, int /*height*/, int /*depth*/) {} + +void EGLNullWSScreen::blank(bool /*on*/) {} + +void EGLNullWSScreen::exposeRegion(QRegion /*r*/, int /*changing*/) {} + +QWSWindowSurface* EGLNullWSScreen::createSurface(QWidget *widget) const +{ + if (qobject_cast<QGLWidget*>(widget)) { + return new EGLNullWSWindowSurface(widget); + } else { + qWarning("%s: Creating non-GL surface", PluginName); + return QScreen::createSurface(widget); + } +} + +QWSWindowSurface* EGLNullWSScreen::createSurface(const QString &key) const +{ + if (key == QLatin1String("eglnullws")) { + return new EGLNullWSWindowSurface; + } else { + qWarning("%s: Creating non-GL surface", PluginName); + return QScreen::createSurface(key); + } +} diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.h b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.h new file mode 100644 index 0000000..7f794bc --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreen.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef EGLNULLWSSCREEN +#define EGLNULLWSSCREEN + +#include <QGLScreen> + +class EGLNullWSScreen : public QGLScreen +{ +public: + EGLNullWSScreen(int displayId); + ~EGLNullWSScreen(); + + bool initDevice(); + bool connect(const QString &displaySpec); + void disconnect(); + void shutdownDevice(); + + void setMode(int width, int height, int depth); + void blank(bool on); + + void exposeRegion(QRegion r, int changing); + + QWSWindowSurface* createSurface(QWidget *widget) const; + QWSWindowSurface* createSurface(const QString &key) const; + + bool hasOpenGL() { return true; } +}; + +#endif // EGLNULLWSSCREEN diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.cpp b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.cpp new file mode 100644 index 0000000..67b3f56 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** 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 plugins 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 "eglnullwsscreenplugin.h" +#include "eglnullwsscreen.h" + +#include <QScreenDriverPlugin> +#include <QStringList> + +class EGLNullWSScreenPlugin : public QScreenDriverPlugin +{ +public: + virtual QStringList keys() const; + virtual QScreen *create(const QString& driver, int displayId); +}; + +QStringList EGLNullWSScreenPlugin::keys() const +{ + return QStringList() << QLatin1String(PluginName); +} + +QScreen *EGLNullWSScreenPlugin::create(const QString& driver, int displayId) +{ + return (driver.toLower() == QLatin1String(PluginName) ? + new EGLNullWSScreen(displayId) : 0); +} + +Q_EXPORT_PLUGIN2(qeglnullws, EGLNullWSScreenPlugin) diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.h b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.h new file mode 100644 index 0000000..84f0699 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwsscreenplugin.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef EGLNULLWSSCREENPLUGIN_H +#define EGLNULLWSSCREENPLUGIN_H + +const char *const PluginName = "eglnullws"; + +#endif // EGLNULLWSSCREENPLUGIN_H diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.cpp b/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.cpp new file mode 100644 index 0000000..da4b728 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 plugins 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 "eglnullwswindowsurface.h" +#include "eglnullwsscreenplugin.h" + +#include <QGLWidget> + +static const QWSWindowSurface::SurfaceFlags Flags + = QWSWindowSurface::RegionReserved | QWSWindowSurface::RegionReserved; + +EGLNullWSWindowSurface::EGLNullWSWindowSurface(QWidget *w) + : + QWSGLWindowSurface(w), + widget(w) +{ + setSurfaceFlags(Flags); +} + +EGLNullWSWindowSurface::EGLNullWSWindowSurface() + : widget(0) +{ + setSurfaceFlags(Flags); +} + +EGLNullWSWindowSurface::~EGLNullWSWindowSurface() {} + +QString EGLNullWSWindowSurface::key() const +{ + return QLatin1String(PluginName); +} + +QPaintDevice *EGLNullWSWindowSurface::paintDevice() +{ + return widget; +} + +bool EGLNullWSWindowSurface::isValid() const +{ + return qobject_cast<QGLWidget *>(window()); +} + +QImage EGLNullWSWindowSurface::image() const +{ + return QImage(); +} diff --git a/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.h b/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.h new file mode 100644 index 0000000..b730415 --- /dev/null +++ b/src/plugins/gfxdrivers/eglnullws/eglnullwswindowsurface.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef EGLNULLWSWINDOWSURFACE_H +#define EGLNULLWSWINDOWSURFACE_H + +#include <private/qglwindowsurface_qws_p.h> + +class EGLNullWSWindowSurface : public QWSGLWindowSurface +{ +public: + EGLNullWSWindowSurface(QWidget *widget); + EGLNullWSWindowSurface(); + virtual ~EGLNullWSWindowSurface(); + + virtual QString key() const; + virtual QPaintDevice *paintDevice(); + virtual bool isValid() const; + virtual QImage image() const; + +private: + QWidget *widget; +}; + +#endif // EGLNULLWSWINDOWSURFACE_H diff --git a/src/plugins/gfxdrivers/gfxdrivers.pro b/src/plugins/gfxdrivers/gfxdrivers.pro index d1ee3f2..1f38942 100644 --- a/src/plugins/gfxdrivers/gfxdrivers.pro +++ b/src/plugins/gfxdrivers/gfxdrivers.pro @@ -7,3 +7,4 @@ contains(gfx-plugins, vnc) :SUBDIRS += vnc contains(gfx-plugins, transformed) :SUBDIRS += transformed contains(gfx-plugins, svgalib) :SUBDIRS += svgalib contains(gfx-plugins, powervr) :SUBDIRS += powervr +contains(gfx-plugins, eglnullws) :SUBDIRS += eglnullws diff --git a/src/plugins/graphicssystems/graphicssystems.pro b/src/plugins/graphicssystems/graphicssystems.pro index 29a1f34..5c99291 100644 --- a/src/plugins/graphicssystems/graphicssystems.pro +++ b/src/plugins/graphicssystems/graphicssystems.pro @@ -1,7 +1,9 @@ TEMPLATE = subdirs SUBDIRS += trace !wince*:contains(QT_CONFIG, opengl):SUBDIRS += opengl -contains(QT_CONFIG, openvg):contains(QT_CONFIG, egl):SUBDIRS += openvg +contains(QT_CONFIG, openvg):contains(QT_CONFIG, egl) { + SUBDIRS += openvg +} contains(QT_CONFIG, shivavg) { # Only works under X11 at present diff --git a/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp b/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp index 6bf9d6b..e2b9f99 100644 --- a/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp +++ b/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp @@ -98,7 +98,11 @@ QPaintDevice *QTraceWindowSurface::paintDevice() { if (!buffer) { buffer = new QPaintBuffer; +#ifdef Q_WS_QPA + buffer->setBoundingRect(QRect(QPoint(), size())); +#else buffer->setBoundingRect(geometry()); +#endif } return buffer; } diff --git a/src/plugins/phonon/gstreamer/gstreamer.pro b/src/plugins/phonon/gstreamer/gstreamer.pro index 1013205..02e0848 100644 --- a/src/plugins/phonon/gstreamer/gstreamer.pro +++ b/src/plugins/phonon/gstreamer/gstreamer.pro @@ -58,7 +58,7 @@ SOURCES += $$PHONON_GSTREAMER_DIR/abstractrenderer.cpp \ $$PHONON_GSTREAMER_DIR/volumefadereffect.cpp \ $$PHONON_GSTREAMER_DIR/widgetrenderer.cpp -!embedded { +x11 { HEADERS += $$PHONON_GSTREAMER_DIR/x11renderer.h SOURCES += $$PHONON_GSTREAMER_DIR/x11renderer.cpp } diff --git a/src/plugins/phonon/mmf/mmf.pro b/src/plugins/phonon/mmf/mmf.pro index ac11188..ade9023 100644 --- a/src/plugins/phonon/mmf/mmf.pro +++ b/src/plugins/phonon/mmf/mmf.pro @@ -18,7 +18,7 @@ symbian { # This is necessary because both epoc32/include and Phonon contain videoplayer.h. # By making /epoc32/include the first SYSTEMINCLUDE, we ensure that # '#include <videoplayer.h>' picks up the Symbian header, as intended. - PREPEND_INCLUDEPATH = /epoc32/include + PREPEND_INCLUDEPATH = $$EPOCROOT/epoc32/include PREPEND_INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty @@ -125,7 +125,11 @@ symbian { LIBS += -lmediaclientaudiostream # For CMdaAudioOutputStream # These are for effects. - LIBS += -lAudioEqualizerEffect -lBassBoostEffect -lDistanceAttenuationEffect -lDopplerBase -lEffectBase -lEnvironmentalReverbEffect -lListenerDopplerEffect -lListenerLocationEffect -lListenerOrientationEffect -lLocationBase -lLoudnessEffect -lOrientationBase -lSourceDopplerEffect -lSourceLocationEffect -lSourceOrientationEffect -lStereoWideningEffect + is_using_gnupoc { + LIBS += -laudioequalizereffect -lbassboosteffect -ldistanceattenuationeffect -ldopplerbase -leffectbase -lenvironmentalreverbeffect -llistenerdopplereffect -llistenerlocationeffect -llistenerorientationeffect -llocationbase -lloudnesseffect -lorientationbase -lsourcedopplereffect -lsourcelocationeffect -lsourceorientationeffect -lstereowideningeffect + } else { + LIBS += -lAudioEqualizerEffect -lBassBoostEffect -lDistanceAttenuationEffect -lDopplerBase -lEffectBase -lEnvironmentalReverbEffect -lListenerDopplerEffect -lListenerLocationEffect -lListenerOrientationEffect -lLocationBase -lLoudnessEffect -lOrientationBase -lSourceDopplerEffect -lSourceLocationEffect -lSourceOrientationEffect -lStereoWideningEffect + } # This is needed for having the .qtplugin file properly created on Symbian. QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro new file mode 100644 index 0000000..1633ee4 --- /dev/null +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -0,0 +1,29 @@ +TARGET = qcocoa +include(../../qpluginbase.pri) +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +OBJECTIVE_SOURCES = main.mm \ + qcocoaintegration.mm \ + qcocoawindowsurface.mm \ + qcocoawindow.mm \ + qnsview.mm \ + qcocoaeventloopintegration.mm \ + qcocoaautoreleasepool.mm \ + qnswindowdelegate.mm + +OBJECTIVE_HEADERS = qcocoaintegration.h \ + qcocoawindowsurface.h \ + qcocoawindow.h \ + qnsview.h \ + qcocoaeventloopintegration.h \ + qcocoaautoreleasepool.h \ + qnswindowdelegate.h + +#add libz for freetype. +LIBS += -lz +LIBS += -framework cocoa + +include(../fontdatabases/coretext/coretext.pri) +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target + diff --git a/src/plugins/platforms/cocoa/main.mm b/src/plugins/platforms/cocoa/main.mm new file mode 100644 index 0000000..8be8883 --- /dev/null +++ b/src/plugins/platforms/cocoa/main.mm @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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 plugins 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 <Cocoa/Cocoa.h> + +#include <QtGui/QPlatformIntegrationPlugin> +#include "qcocoaintegration.h" + +QT_BEGIN_NAMESPACE + +class QCocoaIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QCocoaIntegrationPlugin::keys() const +{ + QStringList list; + list << "Cocoa"; + return list; +} + +QPlatformIntegration * QCocoaIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "cocoa") + return new QCocoaIntegration; + + return 0; +} + +Q_EXPORT_PLUGIN2(Cocoa, QCocoaIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h new file mode 100644 index 0000000..47b94d1 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QCOCOAAUTORELEASEPOOL_H +#define QCOCOAAUTORELEASEPOOL_H + +#include <Cocoa/Cocoa.h> + +class QCocoaAutoReleasePool +{ +public: + QCocoaAutoReleasePool(); + ~QCocoaAutoReleasePool(); + +private: + NSAutoreleasePool *pool; +}; + +#endif // QCOCOAAUTORELEASEPOOL_H diff --git a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm new file mode 100644 index 0000000..9a18fe2 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** 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 plugins 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 "qcocoaautoreleasepool.h" + +QCocoaAutoReleasePool::QCocoaAutoReleasePool() +{ + pool = [[NSAutoreleasePool alloc] init]; +} + +QCocoaAutoReleasePool::~QCocoaAutoReleasePool() +{ + [pool release]; +} diff --git a/src/plugins/platforms/cocoa/qcocoaeventloopintegration.h b/src/plugins/platforms/cocoa/qcocoaeventloopintegration.h new file mode 100644 index 0000000..8c21944 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaeventloopintegration.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QCOCAEVENTLOOPINTEGRATION_H +#define QCOCAEVENTLOOPINTEGRATION_H + +#include <Cocoa/Cocoa.h> + +#include <QPlatformEventLoopIntegration> + +@interface OurApplication: NSApplication +{ + bool shouldKeepRunning; +} + +- (void) run; +- (void) processEvents: (int) msec; + +@end + +class QCocoaEventLoopIntegration : public QPlatformEventLoopIntegration +{ +public: + QCocoaEventLoopIntegration(); + void processEvents( qint64 msec ); + void wakeup(); + + static int wakeupEventId; +private: + OurApplication *app; +}; + + + +#endif // QCOCAEVENTLOOPINTEGRATION_H + diff --git a/src/plugins/platforms/cocoa/qcocoaeventloopintegration.mm b/src/plugins/platforms/cocoa/qcocoaeventloopintegration.mm new file mode 100644 index 0000000..b184f90 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaeventloopintegration.mm @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** 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 plugins 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 "qcocoaeventloopintegration.h" + +#import <Cocoa/Cocoa.h> + +#include "qcocoaautoreleasepool.h" + +#include <QtCore/QElapsedTimer> + +#include <QDebug> + +@implementation OurApplication + +- (void) run +{ + QCocoaAutoReleasePool pool; + [self finishLaunching]; + + shouldKeepRunning = YES; +} + +- (void) processEvents : (int) msec +{ + QCocoaAutoReleasePool pool; + Q_UNUSED(pool); + + QElapsedTimer timer; + timer.start(); + + NSTimeInterval seconds = NSTimeInterval(msec)/1000; + id untilDate = [NSDate dateWithTimeIntervalSinceNow:seconds]; + bool continueLooping = true; + while ((timer.elapsed() < (msec-1)) && continueLooping) { + NSEvent *event = + [self nextEventMatchingMask:NSAnyEventMask + untilDate:untilDate + inMode:NSDefaultRunLoopMode + dequeue:YES]; + if ([event type] == NSApplicationDefined + && [event subtype] == QCocoaEventLoopIntegration::wakeupEventId) { + continueLooping = false; + } else { + [self sendEvent:event]; + } + + } + [self updateWindows]; +} + +@end + +int QCocoaEventLoopIntegration::wakeupEventId = SHRT_MAX; + +QCocoaEventLoopIntegration::QCocoaEventLoopIntegration() : + QPlatformEventLoopIntegration() +{ + app = (OurApplication *)[OurApplication sharedApplication]; + [app run]; +} + +void QCocoaEventLoopIntegration::processEvents(qint64 msec) +{ + [app processEvents:msec]; +} + +void QCocoaEventLoopIntegration::wakeup() +{ + QCocoaAutoReleasePool pool; + Q_UNUSED(pool); + + NSPoint p = NSMakePoint(0,0); + NSWindow *nswin = [app keyWindow]; + double timestamp = (double)(AbsoluteToDuration(UpTime())) / 1000.0; + NSEvent *event = [NSEvent + otherEventWithType:NSApplicationDefined + location:NSZeroPoint + modifierFlags:0 + timestamp: timestamp + windowNumber:[nswin windowNumber] + context:0 + subtype:QCocoaEventLoopIntegration::wakeupEventId + data1:0 + data2:0 + ]; + [app postEvent:event atStart:NO]; + +} + diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h new file mode 100644 index 0000000..e7ecf2a --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QPLATFORMINTEGRATION_COCOA_H +#define QPLATFORMINTEGRATION_COCOA_H + +#include <Cocoa/Cocoa.h> + +#include "qcocoaautoreleasepool.h" + +#include <QtGui/QPlatformIntegration> + +QT_BEGIN_NAMESPACE + +class QCocoaScreen : public QPlatformScreen +{ +public: + QCocoaScreen(int screenIndex); + ~QCocoaScreen(); + + QRect geometry() const { return m_geometry; } + int depth() const { return m_depth; } + QImage::Format format() const { return m_format; } + QSize physicalSize() const { return m_physicalSize; } + +public: + NSScreen *m_screen; + QRect m_geometry; + int m_depth; + QImage::Format m_format; + QSize m_physicalSize; +}; + +class QCocoaIntegration : public QPlatformIntegration +{ +public: + QCocoaIntegration(); + ~QCocoaIntegration(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId = 0) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QList<QPlatformScreen *> screens() const { return mScreens; } + + QPlatformFontDatabase *fontDatabase() const; + + QPlatformEventLoopIntegration *createEventLoopIntegration() const; + +private: + QList<QPlatformScreen *> mScreens; + QPlatformFontDatabase *mFontDb; + + QCocoaAutoReleasePool *mPool; +}; + +QT_END_NAMESPACE + +#endif + diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm new file mode 100644 index 0000000..79d5f51 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** 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 plugins 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 "qcocoaintegration.h" + +#include "qcocoawindow.h" +#include "qcocoawindowsurface.h" +#include "qcocoaeventloopintegration.h" + +#include "qcoretextfontdatabase.h" + +#include <QtGui/QApplication> + +#include <private/qpixmap_raster_p.h> + +QT_BEGIN_NAMESPACE + +QCocoaScreen::QCocoaScreen(int screenIndex) + :QPlatformScreen() +{ + m_screen = [[NSScreen screens] objectAtIndex:screenIndex]; + NSRect rect = [m_screen frame]; + m_geometry = QRect(rect.origin.x,rect.origin.y,rect.size.width,rect.size.height); + + m_format = QImage::Format_ARGB32; + + m_depth = NSBitsPerPixelFromDepth([m_screen depth]); + + const int dpi = 72; + const qreal inch = 25.4; + m_physicalSize = QSize(qRound(m_geometry.width() * inch / dpi), qRound(m_geometry.height() *inch / dpi)); +} + +QCocoaScreen::~QCocoaScreen() +{ +} + +QCocoaIntegration::QCocoaIntegration() + : mFontDb(new QCoreTextFontDatabase()) +{ + mPool = new QCocoaAutoReleasePool; + + //Make sure we have a nsapplication :) + [OurApplication sharedApplication]; +// [[OurApplication alloc] init]; + + NSArray *screens = [NSScreen screens]; + for (uint i = 0; i < [screens count]; i++) { + QCocoaScreen *screen = new QCocoaScreen(i); + mScreens.append(screen); + } +} + +QCocoaIntegration::~QCocoaIntegration() +{ + delete mPool; +} + +QPixmapData *QCocoaIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QPlatformWindow *QCocoaIntegration::createPlatformWindow(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + return new QCocoaWindow(widget); +} + +QWindowSurface *QCocoaIntegration::createWindowSurface(QWidget *widget, WId winId) const +{ + return new QCocoaWindowSurface(widget,winId); +} + +QPlatformFontDatabase *QCocoaIntegration::fontDatabase() const +{ + return mFontDb; +} + +QPlatformEventLoopIntegration *QCocoaIntegration::createEventLoopIntegration() const +{ + return new QCocoaEventLoopIntegration(); +} +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h new file mode 100644 index 0000000..660e9f8 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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$ +** +****************************************************************************/ + +#ifndef QCOCOAWINDOW_H +#define QCOCOAWINDOW_H + +#include <Cocoa/Cocoa.h> + +#include <QPlatformWindow> + +QT_BEGIN_NAMESPACE + +class QCocoaWindow : public QPlatformWindow +{ +public: + QCocoaWindow(QWidget *tlw); + ~QCocoaWindow(); + + void setGeometry(const QRect &rect); + + void setVisible(bool visible); + + WId winId() const; + + NSView *contentView() const; + void setContentView(NSView *contentView); + + void windowDidResize(); + +private: + NSWindow *m_nsWindow; +}; + +QT_END_NAMESPACE + +#endif // QCOCOAWINDOW_H + diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm new file mode 100644 index 0000000..f004cb8 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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 "qcocoawindow.h" +#include "qnswindowdelegate.h" +#include "qcocoaautoreleasepool.h" + +#include <QWidget> + +#include <QtGui/QApplication> + +#include <QWindowSystemInterface> + +#include <QDebug> + +QCocoaWindow::QCocoaWindow(QWidget *tlw) + : QPlatformWindow(tlw) +{ + QCocoaAutoReleasePool pool; + const QRect geo = tlw->geometry(); + NSRect frame = NSMakeRect(geo.x(), geo.y(), geo.width(), geo.height()); + + m_nsWindow = [[NSWindow alloc] initWithContentRect:frame + styleMask:NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask + backing:NSBackingStoreBuffered + defer:YES]; + + QNSWindowDelegate *delegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:this]; + [m_nsWindow setDelegate:delegate]; + + [m_nsWindow makeKeyAndOrderFront:nil]; + [m_nsWindow setAcceptsMouseMovedEvents:YES]; +} + +QCocoaWindow::~QCocoaWindow() +{ +} + +void QCocoaWindow::setGeometry(const QRect &rect) +{ + QPlatformWindow::setGeometry(rect); + + NSRect bounds = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()); + [[m_nsWindow contentView]setFrameSize:bounds.size]; +} + +void QCocoaWindow::setVisible(bool visible) +{ + Q_UNUSED(visible); +} + +WId QCocoaWindow::winId() const +{ + return WId([m_nsWindow windowNumber]); +} + +NSView *QCocoaWindow::contentView() const +{ + return [m_nsWindow contentView]; +} + +void QCocoaWindow::setContentView(NSView *contentView) +{ + [m_nsWindow setContentView:contentView]; +} + +void QCocoaWindow::windowDidResize() +{ + //jlind: XXX This isn't ideal. Eventdispatcher does not run when resizing... + NSRect rect = [[m_nsWindow contentView]frame]; + QRect geo(rect.origin.x,rect.origin.y,rect.size.width,rect.size.height); + if (geometry() != geo) { + widget()->setGeometry(geo); + QResizeEvent e(geo.size(), geometry().size()); + setGeometry(geo); + QApplication::sendEvent(widget(), &e); + widget()->repaint(); + } +} diff --git a/src/plugins/platforms/cocoa/qcocoawindowsurface.h b/src/plugins/platforms/cocoa/qcocoawindowsurface.h new file mode 100644 index 0000000..35f4064 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoawindowsurface.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_COCOA_H +#define QWINDOWSURFACE_COCOA_H + +#include <Cocoa/Cocoa.h> + +#include "qcocoawindow.h" +#include "qnsview.h" + +#include <QtGui/private/qwindowsurface_p.h> + +QT_BEGIN_NAMESPACE + +class QCocoaWindowSurface : public QWindowSurface +{ +public: + QCocoaWindowSurface(QWidget *window, WId wid); + ~QCocoaWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize (const QSize &size); + +private: + + QCocoaWindow *m_cocoaWindow; + QImage *m_image; + QNSView *m_contentView; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/cocoa/qcocoawindowsurface.mm b/src/plugins/platforms/cocoa/qcocoawindowsurface.mm new file mode 100644 index 0000000..443a486 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoawindowsurface.mm @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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 "qcocoawindowsurface.h" + +#include <QtCore/qdebug.h> + +#include <QtGui/QPainter> + +QT_BEGIN_NAMESPACE + +QRect flipedRect(const QRect &sourceRect,int height) +{ + if (!sourceRect.isValid()) + return QRect(); + QRect flippedRect = sourceRect; + flippedRect.moveTop(height - sourceRect.y()); + return flippedRect; +} + +QCocoaWindowSurface::QCocoaWindowSurface(QWidget *window, WId wId) + : QWindowSurface(window) +{ + m_cocoaWindow = static_cast<QCocoaWindow *>(window->platformWindow()); + + const QRect geo = window->geometry(); + NSRect rect = NSMakeRect(geo.x(),geo.y(),geo.width(),geo.height()); + m_contentView = [[QNSView alloc] initWithWidget:window]; + m_cocoaWindow->setContentView(m_contentView); + + m_image = new QImage(window->size(),QImage::Format_ARGB32); +} + +QCocoaWindowSurface::~QCocoaWindowSurface() +{ + delete m_image; +} + +QPaintDevice *QCocoaWindowSurface::paintDevice() +{ + return m_image; +} + +void QCocoaWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(offset); + + QRect geo = region.boundingRect(); + + NSRect rect = NSMakeRect(geo.x(), geo.y(), geo.width(), geo.height()); + [m_contentView displayRect:rect]; +} + +void QCocoaWindowSurface::resize(const QSize &size) +{ + QWindowSurface::resize(size); + delete m_image; + m_image = new QImage(size,QImage::Format_ARGB32_Premultiplied); + NSSize newSize = NSMakeSize(size.width(),size.height()); + [m_contentView setImage:m_image]; + +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h new file mode 100644 index 0000000..0523725 --- /dev/null +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QNSVIEW_H +#define QNSVIEW_H + +#include <Cocoa/Cocoa.h> + +#include <QtGui/QImage> + +@interface QNSView : NSView { + CGImageRef m_cgImage; + QWidget *m_widget; + Qt::MouseButtons m_buttons; +} + +- (id)init; +- (id)initWithWidget:(QWidget *)widget; + +- (void)setImage:(QImage *)image; +- (void)drawRect:(NSRect)dirtyRect; + +- (BOOL)isFlipped; + +- (void)handleMouseEvent:(NSEvent *)theEvent; +- (void)mouseDown:(NSEvent *)theEvent; +- (void)mouseDragged:(NSEvent *)theEvent; +- (void)mouseUp:(NSEvent *)theEvent; +- (void)mouseMoved:(NSEvent *)theEvent; +- (void)mouseEntered:(NSEvent *)theEvent; +- (void)mouseExited:(NSEvent *)theEvent; +- (void)rightMouseDown:(NSEvent *)theEvent; +- (void)rightMouseDragged:(NSEvent *)theEvent; +- (void)rightMouseUp:(NSEvent *)theEvent; +- (void)otherMouseDown:(NSEvent *)theEvent; +- (void)otherMouseDragged:(NSEvent *)theEvent; +- (void)otherMouseUp:(NSEvent *)theEvent; + +@end + +#endif //QNSVIEW_H diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm new file mode 100644 index 0000000..60de6ba --- /dev/null +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -0,0 +1,211 @@ +/**************************************************************************** +** +** 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 plugins 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 "qnsview.h" + +#include <QtGui/QWindowSystemInterface> + +#include <QtCore/QDebug> + +@implementation QNSView + +- (id) init +{ + self = [super init]; + if (self) { + m_cgImage = 0; + m_widget = 0; + m_buttons = Qt::NoButton; + } + return self; +} + +- (id)initWithWidget:(QWidget *)widget { + self = [self init]; + if (self) { + m_widget = widget; + } + return self; +} + +- (void) setImage:(QImage *)image +{ + CGImageRelease(m_cgImage); + + const uchar *imageData = image->bits(); + int bitDepth = image->depth(); + int colorBufferSize = 8; + int bytesPrLine = image->bytesPerLine(); + int width = image->width(); + int height = image->height(); + + CGColorSpaceRef cgColourSpaceRef = CGColorSpaceCreateDeviceRGB(); + + CGDataProviderRef cgDataProviderRef = CGDataProviderCreateWithData( + NULL, + imageData, + image->byteCount(), + NULL); + + m_cgImage = CGImageCreate(width, + height, + colorBufferSize, + bitDepth, + bytesPrLine, + cgColourSpaceRef, + kCGImageAlphaNone, + cgDataProviderRef, + NULL, + false, + kCGRenderingIntentDefault); + + CGColorSpaceRelease(cgColourSpaceRef); + +} + +- (void) drawRect:(NSRect)dirtyRect +{ + if (!m_cgImage) + return; + + CGRect dirtyCGRect = NSRectToCGRect(dirtyRect); + + NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext]; + CGContextRef cgContext = (CGContextRef) [nsGraphicsContext graphicsPort]; + + CGContextSaveGState( cgContext ); + int dy = dirtyCGRect.origin.y + CGRectGetMaxY(dirtyCGRect); + CGContextTranslateCTM(cgContext, 0, dy); + CGContextScaleCTM(cgContext, 1, -1); + + CGImageRef subImage = CGImageCreateWithImageInRect(m_cgImage, dirtyCGRect); + CGContextDrawImage(cgContext,dirtyCGRect,subImage); + + CGContextRestoreGState(cgContext); + + CGImageRelease(subImage); + +} + +- (BOOL) isFlipped +{ + return YES; +} + +- (void)handleMouseEvent:(NSEvent *)theEvent; +{ + NSPoint point = [self convertPoint: [theEvent locationInWindow] fromView: nil]; + QPoint qt_localPoint(point.x,point.y); + + NSTimeInterval timestamp = [theEvent timestamp]; + ulong qt_timestamp = timestamp * 1000; + + QWindowSystemInterface::handleMouseEvent(m_widget,qt_timestamp,qt_localPoint,QPoint(),m_buttons); + +} + - (void)mouseDown:(NSEvent *)theEvent + { + m_buttons |= Qt::LeftButton; + [self handleMouseEvent:theEvent]; + } + - (void)mouseDragged:(NSEvent *)theEvent + { + if (!(m_buttons & Qt::LeftButton)) + qWarning("Internal Mousebutton tracking invalid(missing Qt::LeftButton"); + [self handleMouseEvent:theEvent]; + } + - (void)mouseUp:(NSEvent *)theEvent + { + m_buttons &= QFlag(~int(Qt::LeftButton)); + [self handleMouseEvent:theEvent]; + } + +- (void)mouseMoved:(NSEvent *)theEvent +{ + qDebug() << "mouseMove"; + [self handleMouseEvent:theEvent]; +} +- (void)mouseEntered:(NSEvent *)theEvent +{ + Q_UNUSED(theEvent); + QWindowSystemInterface::handleEnterEvent(m_widget); +} +- (void)mouseExited:(NSEvent *)theEvent +{ + Q_UNUSED(theEvent); + QWindowSystemInterface::handleLeaveEvent(m_widget); +} +- (void)rightMouseDown:(NSEvent *)theEvent +{ + m_buttons |= Qt::RightButton; + [self handleMouseEvent:theEvent]; +} +- (void)rightMouseDragged:(NSEvent *)theEvent +{ + if (!(m_buttons & Qt::LeftButton)) + qWarning("Internal Mousebutton tracking invalid(missing Qt::LeftButton"); + [self handleMouseEvent:theEvent]; +} +- (void)rightMouseUp:(NSEvent *)theEvent +{ + m_buttons &= QFlag(~int(Qt::RightButton)); + [self handleMouseEvent:theEvent]; +} +- (void)otherMouseDown:(NSEvent *)theEvent +{ + m_buttons |= Qt::RightButton; + [self handleMouseEvent:theEvent]; +} +- (void)otherMouseDragged:(NSEvent *)theEvent +{ + if (!(m_buttons & Qt::LeftButton)) + qWarning("Internal Mousebutton tracking invalid(missing Qt::LeftButton"); + [self handleMouseEvent:theEvent]; +} +- (void)otherMouseUp:(NSEvent *)theEvent +{ + m_buttons &= QFlag(~int(Qt::MiddleButton)); + [self handleMouseEvent:theEvent]; +} + + + +@end diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.h b/src/plugins/platforms/cocoa/qnswindowdelegate.h new file mode 100644 index 0000000..9fc1d63 --- /dev/null +++ b/src/plugins/platforms/cocoa/qnswindowdelegate.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QNSWINDOWDELEGATE_H +#define QNSWINDOWDELEGATE_H + +#include <Cocoa/Cocoa.h> + +#include "qcocoawindow.h" + +@interface QNSWindowDelegate : NSObject <NSWindowDelegate> +{ + QCocoaWindow *m_cocoaWindow; +} + +- (id)initWithQCocoaWindow: (QCocoaWindow *) cocoaWindow; + +- (void)windowDidResize:(NSNotification *)notification; +- (void)windowWillClose:(NSNotification *)notification; + +@end + +#endif // QNSWINDOWDELEGATE_H diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.mm b/src/plugins/platforms/cocoa/qnswindowdelegate.mm new file mode 100644 index 0000000..c04602b --- /dev/null +++ b/src/plugins/platforms/cocoa/qnswindowdelegate.mm @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 plugins 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 "qnswindowdelegate.h" + +#include <QDebug> +#include <QWindowSystemInterface> + +@implementation QNSWindowDelegate + +- (id) initWithQCocoaWindow: (QCocoaWindow *) cocoaWindow +{ + self = [super init]; + + if (self) { + m_cocoaWindow = cocoaWindow; + } + return self; +} + +- (void)windowDidResize:(NSNotification *)notification +{ + Q_UNUSED(notification); + if (m_cocoaWindow) { + m_cocoaWindow->windowDidResize(); + } +} + +- (void)windowWillClose:(NSNotification *)notification +{ + Q_UNUSED(notification); + QWindowSystemInterface::handleCloseEvent(m_cocoaWindow->widget()); +} + +@end diff --git a/src/plugins/platforms/directfb/directfb.pro b/src/plugins/platforms/directfb/directfb.pro new file mode 100644 index 0000000..65c49e3 --- /dev/null +++ b/src/plugins/platforms/directfb/directfb.pro @@ -0,0 +1,35 @@ +TARGET = qdirectfb +include(../../qpluginbase.pri) +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +isEmpty(DIRECTFB_LIBS) { + DIRECTFB_LIBS = -ldirectfb -lfusion -ldirect -lpthread +} +isEmpty(DIRECTFB_INCLUDEPATH) { + DIRECTFB_INCLUDEPATH = /usr/include/directfb +} + +INCLUDEPATH += $$DIRECTFB_INCLUDEPATH +LIBS += $$DIRECTFB_LIBS + +SOURCES = main.cpp \ + qdirectfbintegration.cpp \ + qdirectfbwindowsurface.cpp \ + qdirectfbblitter.cpp \ + qdirectfbconvenience.cpp \ + qdirectfbinput.cpp \ + qdirectfbcursor.cpp \ + qdirectfbwindow.cpp \ + qdirectfbglcontext.cpp +HEADERS = qdirectfbintegration.h \ + qdirectfbwindowsurface.h \ + qdirectfbblitter.h \ + qdirectfbconvenience.h \ + qdirectfbinput.h \ + qdirectfbcursor.h \ + qdirectfbwindow.h \ + qdirectfbglcontext.h + +include(../fontdatabases/genericunix/genericunix.pri) +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target diff --git a/src/plugins/platforms/directfb/main.cpp b/src/plugins/platforms/directfb/main.cpp new file mode 100644 index 0000000..f4ece32 --- /dev/null +++ b/src/plugins/platforms/directfb/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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 plugins 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 <QtGui/QPlatformIntegrationPlugin> +#include "qdirectfbintegration.h" + +QT_BEGIN_NAMESPACE + +class QDirectFbIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QDirectFbIntegrationPlugin::keys() const +{ + QStringList list; + list << "directfb"; + return list; +} + +QPlatformIntegration * QDirectFbIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "directfb") + return new QDirectFbIntegration; + + return 0; +} + +Q_EXPORT_PLUGIN2(directfb, QDirectFbIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/directfb/qdirectfbblitter.cpp b/src/plugins/platforms/directfb/qdirectfbblitter.cpp new file mode 100644 index 0000000..d379b65 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbblitter.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** 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 plugins 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 "qdirectfbblitter.h" +#include "qdirectfbconvenience.h" + +#include <QtGui/private/qpixmap_blitter_p.h> + +#include <QDebug> + +#include <directfb.h> + +QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, IDirectFBSurface *surface) + : QBlittable(rect, QBlittable::Capabilities(QBlittable::SolidRectCapability + |QBlittable::SourcePixmapCapability + |QBlittable::SourceOverPixmapCapability + |QBlittable::SourceOverScaledPixmapCapability)) +{ + if (surface) { + m_surface = surface; + } else { + DFBSurfaceDescription surfaceDesc; + memset(&surfaceDesc,0,sizeof(DFBSurfaceDescription)); + surfaceDesc.width = rect.width(); + surfaceDesc.height = rect.height(); + surfaceDesc.caps = DSCAPS_PREMULTIPLIED; + surfaceDesc.pixelformat = DSPF_ARGB; + surfaceDesc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_CAPS | DSDESC_PIXELFORMAT); + + IDirectFB *dfb = QDirectFbConvenience::dfbInterface(); + dfb->CreateSurface(dfb,&surfaceDesc, &m_surface); + m_surface->Clear(m_surface,0,0,0,0); + } + +} + +QDirectFbBlitter::~QDirectFbBlitter() +{ + unlock(); + m_surface->Release(m_surface); +} + +void QDirectFbBlitter::fillRect(const QRectF &rect, const QColor &color) +{ + m_surface->SetColor(m_surface, color.red(), color.green(), color.blue(), color.alpha()); +// When the blitter api supports non opaque blits, also remember to change +// qpixmap_blitter.cpp::fill +// DFBSurfaceDrawingFlags drawingFlags = color.alpha() ? DSDRAW_BLEND : DSDRAW_NOFX; +// m_surface->SetDrawingFlags(m_surface, drawingFlags); + m_surface->SetDrawingFlags(m_surface, DSDRAW_NOFX); + m_surface->FillRectangle(m_surface, rect.x(), rect.y(), + rect.width(), rect.height()); +} + +void QDirectFbBlitter::drawPixmap(const QRectF &rect, const QPixmap &pixmap, const QRectF &srcRect) +{ + QPixmapData *data = pixmap.pixmapData(); + Q_ASSERT(data->width() && data->height()); + Q_ASSERT(data->classId() == QPixmapData::BlitterClass); + QBlittablePixmapData *blitPm = static_cast<QBlittablePixmapData*>(data); + QDirectFbBlitter *dfbBlitter = static_cast<QDirectFbBlitter *>(blitPm->blittable()); + dfbBlitter->unlock(); + + IDirectFBSurface *s = dfbBlitter->m_surface; + + DFBSurfaceBlittingFlags blittingFlags = DSBLIT_NOFX; + DFBSurfacePorterDuffRule porterDuff = DSPD_SRC; + if (pixmap.hasAlpha()) { + blittingFlags = DSBLIT_BLEND_ALPHACHANNEL; + porterDuff = DSPD_SRC_OVER; + } + + m_surface->SetBlittingFlags(m_surface, DFBSurfaceBlittingFlags(blittingFlags)); + m_surface->SetPorterDuff(m_surface,porterDuff); + m_surface->SetDstBlendFunction(m_surface,DSBF_INVSRCALPHA); + + const DFBRectangle sRect = { srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height() }; + + DFBResult result; + if (rect.width() == srcRect.width() && rect.height() == srcRect.height()) + result = m_surface->Blit(m_surface, s, &sRect, rect.x(), rect.y()); + else { + const DFBRectangle dRect = { rect.x(), rect.y(), rect.width(), rect.height() }; + result = m_surface->StretchBlit(m_surface, s, &sRect, &dRect); + } + if (result != DFB_OK) + DirectFBError("QDirectFBBlitter::drawPixmap()", result); +} + +QImage *QDirectFbBlitter::doLock() +{ + Q_ASSERT(m_surface); + Q_ASSERT(size().isValid()); + + void *mem; + int bpl; + const DFBResult result = m_surface->Lock(m_surface, DFBSurfaceLockFlags(DSLF_WRITE|DSLF_READ), static_cast<void**>(&mem), &bpl); + if (result == DFB_OK) { + DFBSurfacePixelFormat dfbFormat; + DFBSurfaceCapabilities dfbCaps; + m_surface->GetPixelFormat(m_surface,&dfbFormat); + m_surface->GetCapabilities(m_surface,&dfbCaps); + QImage::Format format = QDirectFbConvenience::imageFormatFromSurfaceFormat(dfbFormat, dfbCaps); + int w, h; + m_surface->GetSize(m_surface,&w,&h); + m_image = QImage(static_cast<uchar *>(mem),w,h,bpl,format); + } else { + DirectFBError("Failed to lock image", result); + } + + return &m_image; +} + +void QDirectFbBlitter::doUnlock() +{ + m_surface->Unlock(m_surface); +} diff --git a/src/plugins/platforms/directfb/qdirectfbblitter.h b/src/plugins/platforms/directfb/qdirectfbblitter.h new file mode 100644 index 0000000..1e874ba --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbblitter.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QDIRECTFBBLITTER_H +#define QDIRECTFBBLITTER_H + +#include "qdirectfbconvenience.h" + +#include <private/qblittable_p.h> + +#include <directfb.h> + +class QDirectFbBlitter : public QBlittable +{ +public: + QDirectFbBlitter(const QSize &size, IDirectFBSurface *surface = 0); + virtual ~QDirectFbBlitter(); + + virtual void fillRect(const QRectF &rect, const QColor &color); + virtual void drawPixmap(const QRectF &rect, const QPixmap &pixmap, const QRectF &subrect); + +protected: + virtual QImage *doLock(); + virtual void doUnlock(); + + IDirectFBSurface *m_surface; + QImage m_image; + + friend class QDirectFbConvenience; +}; + +class QDirectFbBlitterPixmapData : public QBlittablePixmapData +{ +public: + QBlittable *createBlittable(const QSize &size) const { return new QDirectFbBlitter(size); } +}; + +#endif // QDIRECTFBBLITTER_H diff --git a/src/plugins/platforms/directfb/qdirectfbconvenience.cpp b/src/plugins/platforms/directfb/qdirectfbconvenience.cpp new file mode 100644 index 0000000..91a1b3a --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbconvenience.cpp @@ -0,0 +1,376 @@ +/**************************************************************************** +** +** 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 plugins 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 "qdirectfbconvenience.h" +#include "qdirectfbblitter.h" + +#include <private/qpixmap_blitter_p.h> + +IDirectFB *QDirectFbConvenience::dfbInterface() +{ + static IDirectFB *dfb = 0; + if (!dfb) { + DFBResult result = DirectFBCreate(&dfb); + if (result != DFB_OK) { + DirectFBError("QDirectFBConvenience: error creating DirectFB interface",result); + return 0; + } + } + return dfb; +} + +IDirectFBDisplayLayer *QDirectFbConvenience::dfbDisplayLayer(int display) +{ + IDirectFBDisplayLayer *layer; + DFBResult result = QDirectFbConvenience::dfbInterface()->GetDisplayLayer(QDirectFbConvenience::dfbInterface(),display,&layer); + if (result != DFB_OK) { + DirectFBError("QDirectFbConvenience: " + "Unable to get primary display layer!", result); + } + return layer; +} + +QImage::Format QDirectFbConvenience::imageFormatFromSurfaceFormat(const DFBSurfacePixelFormat format, const DFBSurfaceCapabilities caps) +{ + switch (format) { + case DSPF_LUT8: + return QImage::Format_Indexed8; + case DSPF_RGB24: + return QImage::Format_RGB888; + case DSPF_ARGB4444: + return QImage::Format_ARGB4444_Premultiplied; + case DSPF_RGB444: + return QImage::Format_RGB444; + case DSPF_RGB555: + case DSPF_ARGB1555: + return QImage::Format_RGB555; + case DSPF_RGB16: + return QImage::Format_RGB16; + case DSPF_ARGB6666: + return QImage::Format_ARGB6666_Premultiplied; + case DSPF_RGB18: + return QImage::Format_RGB666; + case DSPF_RGB32: + return QImage::Format_RGB32; + case DSPF_ARGB: { + if (caps & DSCAPS_PREMULTIPLIED) + return QImage::Format_ARGB32_Premultiplied; + else return QImage::Format_ARGB32; } + default: + break; + } + return QImage::Format_Invalid; + +} + +int QDirectFbConvenience::colorDepthForSurface(const DFBSurfacePixelFormat format) +{ + return ((0x1f << 7) & format) >> 7; +} + +IDirectFBSurface *QDirectFbConvenience::dfbSurfaceForPixmapData(QPixmapData *pixmapData) +{ + QBlittablePixmapData *blittablePmData = static_cast<QBlittablePixmapData *>(pixmapData); + if (blittablePmData) { + QBlittable *blittable = blittablePmData->blittable(); + QDirectFbBlitter *dfbBlitter = static_cast<QDirectFbBlitter *>(blittable); + return dfbBlitter->m_surface; + } + return 0; +} + +Qt::MouseButton QDirectFbConvenience::mouseButton(DFBInputDeviceButtonIdentifier identifier) +{ + switch (identifier){ + case DIBI_LEFT: + return Qt::LeftButton; + case DIBI_MIDDLE: + return Qt::MidButton; + case DIBI_RIGHT: + return Qt::RightButton; + default: + return Qt::NoButton; + } +} + +Qt::MouseButtons QDirectFbConvenience::mouseButtons(DFBInputDeviceButtonMask mask) +{ + Qt::MouseButtons buttons = Qt::NoButton; + + if (mask & DIBM_LEFT) { + buttons |= Qt::LeftButton; + } + if (mask & DIBM_MIDDLE) { + buttons |= Qt::MidButton; + } + if (mask & DIBM_RIGHT) { + buttons |= Qt::RightButton; + } + return buttons; +} + +Qt::KeyboardModifiers QDirectFbConvenience::keyboardModifiers(DFBInputDeviceModifierMask mask) +{ + Qt::KeyboardModifiers modifiers = Qt::NoModifier; + + if (mask & DIMM_SHIFT) { + modifiers |= Qt::ShiftModifier; + } + if (mask & DIMM_ALT) { + modifiers |= Qt::AltModifier; + } + if (mask & DIMM_ALTGR) { + modifiers |= Qt::MetaModifier; + } + if (mask & DIMM_CONTROL) { + modifiers |= Qt::ControlModifier; + } + if (mask & DIMM_META) { + modifiers | Qt::MetaModifier; + } + return modifiers; +} + +QEvent::Type QDirectFbConvenience::eventType(DFBWindowEventType type) +{ + switch(type) { + case DWET_BUTTONDOWN: + return QEvent::MouseButtonPress; + case DWET_BUTTONUP: + return QEvent::MouseButtonRelease; + case DWET_MOTION: + return QEvent::MouseMove; + case DWET_WHEEL: + return QEvent::Wheel; + case DWET_KEYDOWN: + return QEvent::KeyPress; + case DWET_KEYUP: + return QEvent::KeyRelease; + default: + return QEvent::None; + } +} +QDirectFbKeyMap *QDirectFbConvenience::dfbKeymap = 0; +QDirectFbKeyMap *QDirectFbConvenience::keyMap() +{ + if (!dfbKeymap) + dfbKeymap = new QDirectFbKeyMap(); + return dfbKeymap; +} + +QDirectFbKeyMap::QDirectFbKeyMap() +{ + insert(DIKS_BACKSPACE , Qt::Key_Backspace); + insert(DIKS_TAB , Qt::Key_Tab); + insert(DIKS_RETURN , Qt::Key_Return); + insert(DIKS_ESCAPE , Qt::Key_Escape); + insert(DIKS_DELETE , Qt::Key_Delete); + + insert(DIKS_CURSOR_LEFT , Qt::Key_Left); + insert(DIKS_CURSOR_RIGHT , Qt::Key_Right); + insert(DIKS_CURSOR_UP , Qt::Key_Up); + insert(DIKS_CURSOR_DOWN , Qt::Key_Down); + insert(DIKS_INSERT , Qt::Key_Insert); + insert(DIKS_HOME , Qt::Key_Home); + insert(DIKS_END , Qt::Key_End); + insert(DIKS_PAGE_UP , Qt::Key_PageUp); + insert(DIKS_PAGE_DOWN , Qt::Key_PageDown); + insert(DIKS_PRINT , Qt::Key_Print); + insert(DIKS_PAUSE , Qt::Key_Pause); + insert(DIKS_SELECT , Qt::Key_Select); + insert(DIKS_GOTO , Qt::Key_OpenUrl); + insert(DIKS_CLEAR , Qt::Key_Clear); + insert(DIKS_MENU , Qt::Key_Menu); + insert(DIKS_HELP , Qt::Key_Help); + + insert(DIKS_INTERNET , Qt::Key_HomePage); + insert(DIKS_MAIL , Qt::Key_LaunchMail); + insert(DIKS_FAVORITES , Qt::Key_Favorites); + + insert(DIKS_BACK , Qt::Key_Back); + insert(DIKS_FORWARD , Qt::Key_Forward); + insert(DIKS_VOLUME_UP , Qt::Key_VolumeUp); + insert(DIKS_VOLUME_DOWN , Qt::Key_VolumeDown); + insert(DIKS_MUTE , Qt::Key_VolumeMute); + insert(DIKS_PLAYPAUSE , Qt::Key_Pause); + insert(DIKS_PLAY , Qt::Key_MediaPlay); + insert(DIKS_STOP , Qt::Key_MediaStop); + insert(DIKS_RECORD , Qt::Key_MediaRecord); + insert(DIKS_PREVIOUS , Qt::Key_MediaPrevious); + insert(DIKS_NEXT , Qt::Key_MediaNext); + + insert(DIKS_F1 , Qt::Key_F1); + insert(DIKS_F2 , Qt::Key_F2); + insert(DIKS_F3 , Qt::Key_F3); + insert(DIKS_F4 , Qt::Key_F4); + insert(DIKS_F5 , Qt::Key_F5); + insert(DIKS_F6 , Qt::Key_F6); + insert(DIKS_F7 , Qt::Key_F7); + insert(DIKS_F8 , Qt::Key_F8); + insert(DIKS_F9 , Qt::Key_F9); + insert(DIKS_F10 , Qt::Key_F10); + insert(DIKS_F11 , Qt::Key_F11); + insert(DIKS_F12 , Qt::Key_F12); + + insert(DIKS_SHIFT , Qt::Key_Shift); + insert(DIKS_CONTROL , Qt::Key_Control); + insert(DIKS_ALT , Qt::Key_Alt); + insert(DIKS_ALTGR , Qt::Key_AltGr); + + insert(DIKS_META , Qt::Key_Meta); + insert(DIKS_SUPER , Qt::Key_Super_L); // ??? + insert(DIKS_HYPER , Qt::Key_Hyper_L); // ??? + + insert(DIKS_CAPS_LOCK , Qt::Key_CapsLock); + insert(DIKS_NUM_LOCK , Qt::Key_NumLock); + insert(DIKS_SCROLL_LOCK , Qt::Key_ScrollLock); + + insert(DIKS_DEAD_ABOVEDOT , Qt::Key_Dead_Abovedot); + insert(DIKS_DEAD_ABOVERING , Qt::Key_Dead_Abovering); + insert(DIKS_DEAD_ACUTE , Qt::Key_Dead_Acute); + insert(DIKS_DEAD_BREVE , Qt::Key_Dead_Breve); + insert(DIKS_DEAD_CARON , Qt::Key_Dead_Caron); + insert(DIKS_DEAD_CEDILLA , Qt::Key_Dead_Cedilla); + insert(DIKS_DEAD_CIRCUMFLEX , Qt::Key_Dead_Circumflex); + insert(DIKS_DEAD_DIAERESIS , Qt::Key_Dead_Diaeresis); + insert(DIKS_DEAD_DOUBLEACUTE , Qt::Key_Dead_Doubleacute); + insert(DIKS_DEAD_GRAVE , Qt::Key_Dead_Grave); + insert(DIKS_DEAD_IOTA , Qt::Key_Dead_Iota); + insert(DIKS_DEAD_MACRON , Qt::Key_Dead_Macron); + insert(DIKS_DEAD_OGONEK , Qt::Key_Dead_Ogonek); + insert(DIKS_DEAD_SEMIVOICED_SOUND , Qt::Key_Dead_Semivoiced_Sound); + insert(DIKS_DEAD_TILDE , Qt::Key_Dead_Tilde); + insert(DIKS_DEAD_VOICED_SOUND , Qt::Key_Dead_Voiced_Sound); + insert(DIKS_SPACE , Qt::Key_Space); + insert(DIKS_EXCLAMATION_MARK , Qt::Key_Exclam); + insert(DIKS_QUOTATION , Qt::Key_QuoteDbl); + insert(DIKS_NUMBER_SIGN , Qt::Key_NumberSign); + insert(DIKS_DOLLAR_SIGN , Qt::Key_Dollar); + insert(DIKS_PERCENT_SIGN , Qt::Key_Percent); + insert(DIKS_AMPERSAND , Qt::Key_Ampersand); + insert(DIKS_APOSTROPHE , Qt::Key_Apostrophe); + insert(DIKS_PARENTHESIS_LEFT , Qt::Key_ParenLeft); + insert(DIKS_PARENTHESIS_RIGHT , Qt::Key_ParenRight); + insert(DIKS_ASTERISK , Qt::Key_Asterisk); + insert(DIKS_PLUS_SIGN , Qt::Key_Plus); + insert(DIKS_COMMA , Qt::Key_Comma); + insert(DIKS_MINUS_SIGN , Qt::Key_Minus); + insert(DIKS_PERIOD , Qt::Key_Period); + insert(DIKS_SLASH , Qt::Key_Slash); + insert(DIKS_0 , Qt::Key_0); + insert(DIKS_1 , Qt::Key_1); + insert(DIKS_2 , Qt::Key_2); + insert(DIKS_3 , Qt::Key_3); + insert(DIKS_4 , Qt::Key_4); + insert(DIKS_5 , Qt::Key_5); + insert(DIKS_6 , Qt::Key_6); + insert(DIKS_7 , Qt::Key_7); + insert(DIKS_8 , Qt::Key_8); + insert(DIKS_9 , Qt::Key_9); + insert(DIKS_COLON , Qt::Key_Colon); + insert(DIKS_SEMICOLON , Qt::Key_Semicolon); + insert(DIKS_LESS_THAN_SIGN , Qt::Key_Less); + insert(DIKS_EQUALS_SIGN , Qt::Key_Equal); + insert(DIKS_GREATER_THAN_SIGN , Qt::Key_Greater); + insert(DIKS_QUESTION_MARK , Qt::Key_Question); + insert(DIKS_AT , Qt::Key_At); + insert(DIKS_CAPITAL_A , Qt::Key_A); + insert(DIKS_CAPITAL_B , Qt::Key_B); + insert(DIKS_CAPITAL_C , Qt::Key_C); + insert(DIKS_CAPITAL_D , Qt::Key_D); + insert(DIKS_CAPITAL_E , Qt::Key_E); + insert(DIKS_CAPITAL_F , Qt::Key_F); + insert(DIKS_CAPITAL_G , Qt::Key_G); + insert(DIKS_CAPITAL_H , Qt::Key_H); + insert(DIKS_CAPITAL_I , Qt::Key_I); + insert(DIKS_CAPITAL_J , Qt::Key_J); + insert(DIKS_CAPITAL_K , Qt::Key_K); + insert(DIKS_CAPITAL_L , Qt::Key_L); + insert(DIKS_CAPITAL_M , Qt::Key_M); + insert(DIKS_CAPITAL_N , Qt::Key_N); + insert(DIKS_CAPITAL_O , Qt::Key_O); + insert(DIKS_CAPITAL_P , Qt::Key_P); + insert(DIKS_CAPITAL_Q , Qt::Key_Q); + insert(DIKS_CAPITAL_R , Qt::Key_R); + insert(DIKS_CAPITAL_S , Qt::Key_S); + insert(DIKS_CAPITAL_T , Qt::Key_T); + insert(DIKS_CAPITAL_U , Qt::Key_U); + insert(DIKS_CAPITAL_V , Qt::Key_V); + insert(DIKS_CAPITAL_W , Qt::Key_W); + insert(DIKS_CAPITAL_X , Qt::Key_X); + insert(DIKS_CAPITAL_Y , Qt::Key_Y); + insert(DIKS_CAPITAL_Z , Qt::Key_Z); + insert(DIKS_SQUARE_BRACKET_LEFT , Qt::Key_BracketLeft); + insert(DIKS_BACKSLASH , Qt::Key_Backslash); + insert(DIKS_SQUARE_BRACKET_RIGHT , Qt::Key_BracketRight); + insert(DIKS_CIRCUMFLEX_ACCENT , Qt::Key_AsciiCircum); + insert(DIKS_UNDERSCORE , Qt::Key_Underscore); + insert(DIKS_SMALL_A , Qt::Key_A); + insert(DIKS_SMALL_B , Qt::Key_B); + insert(DIKS_SMALL_C , Qt::Key_C); + insert(DIKS_SMALL_D , Qt::Key_D); + insert(DIKS_SMALL_E , Qt::Key_E); + insert(DIKS_SMALL_F , Qt::Key_F); + insert(DIKS_SMALL_G , Qt::Key_G); + insert(DIKS_SMALL_H , Qt::Key_H); + insert(DIKS_SMALL_I , Qt::Key_I); + insert(DIKS_SMALL_J , Qt::Key_J); + insert(DIKS_SMALL_K , Qt::Key_K); + insert(DIKS_SMALL_L , Qt::Key_L); + insert(DIKS_SMALL_M , Qt::Key_M); + insert(DIKS_SMALL_N , Qt::Key_N); + insert(DIKS_SMALL_O , Qt::Key_O); + insert(DIKS_SMALL_P , Qt::Key_P); + insert(DIKS_SMALL_Q , Qt::Key_Q); + insert(DIKS_SMALL_R , Qt::Key_R); + insert(DIKS_SMALL_S , Qt::Key_S); + insert(DIKS_SMALL_T , Qt::Key_T); + insert(DIKS_SMALL_U , Qt::Key_U); + insert(DIKS_SMALL_V , Qt::Key_V); + insert(DIKS_SMALL_W , Qt::Key_W); + insert(DIKS_SMALL_X , Qt::Key_X); + insert(DIKS_SMALL_Y , Qt::Key_Y); + insert(DIKS_SMALL_Z , Qt::Key_Z); + insert(DIKS_CURLY_BRACKET_LEFT , Qt::Key_BraceLeft); + insert(DIKS_VERTICAL_BAR , Qt::Key_Bar); + insert(DIKS_CURLY_BRACKET_RIGHT , Qt::Key_BraceRight); + insert(DIKS_TILDE , Qt::Key_AsciiTilde); +} diff --git a/src/plugins/platforms/directfb/qdirectfbconvenience.h b/src/plugins/platforms/directfb/qdirectfbconvenience.h new file mode 100644 index 0000000..3669159 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbconvenience.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QDIRECTFBCONVENIENCE_H +#define QDIRECTFBCONVENIENCE_H + +#include <QtGui/qimage.h> +#include <QtCore/QHash> +#include <QtCore/QEvent> +#include <QtGui/QPixmap> + +#include <directfb.h> + +class QDirectFbKeyMap: public QHash<DFBInputDeviceKeySymbol, Qt::Key> +{ +public: + QDirectFbKeyMap(); +}; + + +class QDirectFbConvenience +{ +public: + static QImage::Format imageFormatFromSurfaceFormat(const DFBSurfacePixelFormat format, const DFBSurfaceCapabilities caps); + static bool pixelFomatHasAlpha(const DFBSurfacePixelFormat format) { return (1 << 16) & format; } + static int colorDepthForSurface(const DFBSurfacePixelFormat format); + + //This is set by the graphicssystem constructor + static IDirectFB *dfbInterface(); + static IDirectFBDisplayLayer *dfbDisplayLayer(int display = DLID_PRIMARY); + + static IDirectFBSurface *dfbSurfaceForPixmapData(QPixmapData *); + + static Qt::MouseButton mouseButton(DFBInputDeviceButtonIdentifier identifier); + static Qt::MouseButtons mouseButtons(DFBInputDeviceButtonMask mask); + static Qt::KeyboardModifiers keyboardModifiers(DFBInputDeviceModifierMask mask); + static QEvent::Type eventType(DFBWindowEventType type); + + static QDirectFbKeyMap *keyMap(); + +private: + static QDirectFbKeyMap *dfbKeymap; + friend class QDirectFbIntegration; +}; + +#endif // QDIRECTFBCONVENIENCE_H diff --git a/src/plugins/platforms/directfb/qdirectfbcursor.cpp b/src/plugins/platforms/directfb/qdirectfbcursor.cpp new file mode 100644 index 0000000..51502f8 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbcursor.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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 plugins 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 "qdirectfbcursor.h" +#include "qdirectfbconvenience.h" + + +QDirectFBCursor::QDirectFBCursor(QPlatformScreen* screen) : + QPlatformCursor(screen), surface(0) +{ + QDirectFbConvenience::dfbInterface()->GetDisplayLayer(QDirectFbConvenience::dfbInterface(),DLID_PRIMARY, &m_layer); + image = new QPlatformCursorImage(0, 0, 0, 0, 0, 0); +} + +void QDirectFBCursor::changeCursor(QCursor * cursor, QWidget * widget) +{ + Q_UNUSED(widget); + int xSpot; + int ySpot; + QPixmap map; + + if (cursor->shape() != Qt::BitmapCursor) { + image->set(cursor->shape()); + xSpot = image->hotspot().x(); + ySpot = image->hotspot().y(); + QImage *i = image->image(); + map = QPixmap::fromImage(*i); + } else { + QPoint point = cursor->hotSpot(); + xSpot = point.x(); + ySpot = point.y(); + map = cursor->pixmap(); + } + + IDirectFBSurface *surface = QDirectFbConvenience::dfbSurfaceForPixmapData(map.pixmapData()); + + if (m_layer->SetCooperativeLevel(m_layer, DLSCL_ADMINISTRATIVE) != DFB_OK) { + return; + } + m_layer->SetCursorShape( m_layer, surface, xSpot, ySpot); + m_layer->SetCooperativeLevel(m_layer, DLSCL_SHARED); +} diff --git a/src/plugins/platforms/directfb/qdirectfbcursor.h b/src/plugins/platforms/directfb/qdirectfbcursor.h new file mode 100644 index 0000000..ea8b7b0 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbcursor.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QDIRECTFBCURSOR_H +#define QDIRECTFBCURSOR_H + +#include <QPlatformCursor> +#include <directfb.h> +class QDirectFbScreen; +class QDirectFbBlitter; + +class QDirectFBCursor : public QPlatformCursor +{ +public: + QDirectFBCursor(QPlatformScreen *screem); + void changeCursor(QCursor * cursor, QWidget * widget); + +private: + IDirectFBDisplayLayer * m_layer; + IDirectFBSurface * surface; + QPlatformCursorImage * image; + QDirectFbBlitter *blitter; +}; + +#endif // QDIRECTFBCURSOR_H diff --git a/src/plugins/platforms/directfb/qdirectfbglcontext.cpp b/src/plugins/platforms/directfb/qdirectfbglcontext.cpp new file mode 100644 index 0000000..033ff1e --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbglcontext.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** 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 plugins 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 "qdirectfbglcontext.h" + +#include <directfb/directfbgl.h> + +#include <QDebug> + +QDirectFbGLContext::QDirectFbGLContext(IDirectFBGL *glContext) + : m_dfbGlContext(glContext) +{ + DFBResult result; + DFBGLAttributes glAttribs; + result = m_dfbGlContext->GetAttributes(glContext, &glAttribs); + if (result == DFB_OK) { + m_windowFormat.setDepthBufferSize(glAttribs.depth_size); + m_windowFormat.setStencilBufferSize(glAttribs.stencil_size); + + m_windowFormat.setRedBufferSize(glAttribs.red_size); + m_windowFormat.setGreenBufferSize(glAttribs.green_size); + m_windowFormat.setBlueBufferSize(glAttribs.blue_size); + m_windowFormat.setAlphaBufferSize(glAttribs.alpha_size); + + m_windowFormat.setAccumBufferSize(glAttribs.accum_red_size); + m_windowFormat.setAlpha(glAttribs.accum_alpha_size); + + m_windowFormat.setDoubleBuffer(glAttribs.double_buffer); + m_windowFormat.setStereo(glAttribs.stereo); + } +} + +void QDirectFbGLContext::makeCurrent() +{ + m_dfbGlContext->Lock(m_dfbGlContext); +} + +void QDirectFbGLContext::doneCurrent() +{ + m_dfbGlContext->Unlock(m_dfbGlContext); +} + +void *QDirectFbGLContext::getProcAddress(const QString &procName) +{ + void *proc; + DFBResult result = m_dfbGlContext->GetProcAddress(m_dfbGlContext,qPrintable(procName),&proc); + if (result == DFB_OK) + return proc; + return 0; +} + +void QDirectFbGLContext::swapBuffers() +{ +// m_dfbGlContext->Unlock(m_dfbGlContext); //maybe not in doneCurrent() + qDebug() << "Swap buffers"; +} + +QPlatformWindowFormat QDirectFbGLContext::platformWindowFormat() const +{ + return m_windowFormat; +} diff --git a/src/plugins/platforms/directfb/qdirectfbglcontext.h b/src/plugins/platforms/directfb/qdirectfbglcontext.h new file mode 100644 index 0000000..1785666 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbglcontext.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QDIRECTFBGLCONTEXT_H +#define QDIRECTFBGLCONTEXT_H + +#include <QPlatformGLContext> + +#include "qdirectfbconvenience.h" + +class QDirectFbGLContext : public QPlatformGLContext +{ +public: + explicit QDirectFbGLContext(IDirectFBGL *glContext); + + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void *getProcAddress(const QString &procName); + + QPlatformWindowFormat platformWindowFormat() const; + + +private: + IDirectFBGL *m_dfbGlContext; + + QPlatformWindowFormat m_windowFormat; + +}; + +#endif // QDIRECTFBGLCONTEXT_H diff --git a/src/plugins/platforms/directfb/qdirectfbinput.cpp b/src/plugins/platforms/directfb/qdirectfbinput.cpp new file mode 100644 index 0000000..9d2a8a8 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbinput.cpp @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** 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 plugins 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 "qdirectfbinput.h" +#include "qdirectfbconvenience.h" + +#include <QThread> +#include <QDebug> +#include <QWindowSystemInterface> +#include <QMouseEvent> +#include <QEvent> +#include <QApplication> + +#include <directfb.h> + +QDirectFbInput::QDirectFbInput(QObject *parent) + : QObject(parent), m_shouldStop(false) +{ + m_dfbInterface = QDirectFbConvenience::dfbInterface(); + + DFBResult ok = m_dfbInterface->CreateEventBuffer(m_dfbInterface,&m_eventBuffer); + if (ok != DFB_OK) + DirectFBError("Failed to initialise eventbuffer", ok); + + m_dfbInterface->GetDisplayLayer(m_dfbInterface,DLID_PRIMARY, &m_dfbDisplayLayer); + +} + +void QDirectFbInput::runInputEventLoop() +{ + while (true) { + m_eventBuffer->WaitForEvent(m_eventBuffer); + if (m_shouldStop) { + m_waitStop.release(); + break; + } + handleEvents(); + } +} + +void QDirectFbInput::stopInputEventLoop() +{ + m_shouldStop = true; + m_waitStop.acquire(); +} + +void QDirectFbInput::addWindow(DFBWindowID id, QWidget *tlw) +{ + m_tlwMap.insert(id,tlw); + IDirectFBWindow *window; + m_dfbDisplayLayer->GetWindow(m_dfbDisplayLayer,id,&window); + + window->AttachEventBuffer(window,m_eventBuffer); +} + +void QDirectFbInput::removeWindow(WId wId) +{ + IDirectFBWindow *window; + m_dfbDisplayLayer->GetWindow(m_dfbDisplayLayer,wId, &window); + + window->DetachEventBuffer(window,m_eventBuffer); + m_tlwMap.remove(wId); +} + +void QDirectFbInput::handleEvents() +{ + DFBResult hasEvent = m_eventBuffer->HasEvent(m_eventBuffer); + while(hasEvent == DFB_OK){ + DFBEvent event; + DFBResult ok = m_eventBuffer->GetEvent(m_eventBuffer,&event); + if (ok != DFB_OK) + DirectFBError("Failed to get event",ok); + if (event.clazz == DFEC_WINDOW) { + switch (event.window.type) { + case DWET_BUTTONDOWN: + case DWET_BUTTONUP: + case DWET_MOTION: + handleMouseEvents(event); + break; + case DWET_WHEEL: + handleWheelEvent(event); + break; + case DWET_KEYDOWN: + case DWET_KEYUP: + handleKeyEvents(event); + break; + case DWET_ENTER: + case DWET_LEAVE: + handleEnterLeaveEvents(event); + default: + break; + } + + } + + hasEvent = m_eventBuffer->HasEvent(m_eventBuffer); + } +} + +void QDirectFbInput::handleMouseEvents(const DFBEvent &event) +{ + QPoint p(event.window.x, event.window.y); + QPoint globalPos = globalPoint(event); + Qt::MouseButtons buttons = QDirectFbConvenience::mouseButtons(event.window.buttons); + + IDirectFBDisplayLayer *layer = QDirectFbConvenience::dfbDisplayLayer(); + IDirectFBWindow *window; + layer->GetWindow(layer,event.window.window_id,&window); + + long timestamp = (event.window.timestamp.tv_sec*1000) + (event.window.timestamp.tv_usec/1000); + + if (event.window.type == DWET_BUTTONDOWN) { + window->GrabPointer(window); + } else if (event.window.type == DWET_BUTTONUP) { + window->UngrabPointer(window); + } + QWidget *tlw = m_tlwMap.value(event.window.window_id); + QWindowSystemInterface::handleMouseEvent(tlw, timestamp, p, globalPos, buttons); +} + +void QDirectFbInput::handleWheelEvent(const DFBEvent &event) +{ + QPoint p(event.window.cx, event.window.cy); + QPoint globalPos = globalPoint(event); + long timestamp = (event.window.timestamp.tv_sec*1000) + (event.window.timestamp.tv_usec/1000); + QWidget *tlw = m_tlwMap.value(event.window.window_id); + QWindowSystemInterface::handleWheelEvent(tlw, timestamp, p, globalPos, + event.window.step*120, + Qt::Vertical); +} + +void QDirectFbInput::handleKeyEvents(const DFBEvent &event) +{ + QEvent::Type type = QDirectFbConvenience::eventType(event.window.type); + Qt::Key key = QDirectFbConvenience::keyMap()->value(event.window.key_symbol); + Qt::KeyboardModifiers modifiers = QDirectFbConvenience::keyboardModifiers(event.window.modifiers); + + long timestamp = (event.window.timestamp.tv_sec*1000) + (event.window.timestamp.tv_usec/1000); + + QChar character; + if (DFB_KEY_TYPE(event.window.key_symbol) == DIKT_UNICODE) + character = QChar(event.window.key_symbol); + QWidget *tlw = m_tlwMap.value(event.window.window_id); + QWindowSystemInterface::handleKeyEvent(tlw, timestamp, type, key, modifiers, character); +} + +void QDirectFbInput::handleEnterLeaveEvents(const DFBEvent &event) +{ + QWidget *tlw = m_tlwMap.value(event.window.window_id); + switch (event.window.type) { + case DWET_ENTER: + QWindowSystemInterface::handleEnterEvent(tlw); + break; + case DWET_LEAVE: + QWindowSystemInterface::handleLeaveEvent(tlw); + break; + default: + break; + } +} + +inline QPoint QDirectFbInput::globalPoint(const DFBEvent &event) const +{ + IDirectFBWindow *window; + m_dfbDisplayLayer->GetWindow(m_dfbDisplayLayer,event.window.window_id,&window); + int x,y; + window->GetPosition(window,&x,&y); + return QPoint(event.window.cx +x, event.window.cy + y); +} + diff --git a/src/plugins/platforms/directfb/qdirectfbinput.h b/src/plugins/platforms/directfb/qdirectfbinput.h new file mode 100644 index 0000000..bca155f --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbinput.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QDIRECTFBINPUT_H +#define QDIRECTFBINPUT_H + +#include <QSemaphore> +#include <QObject> +#include <QHash> +#include <QPoint> +#include <QEvent> + +#include <QtGui/qwindowdefs.h> + +#include <directfb.h> + +class QDirectFbInput : public QObject +{ + Q_OBJECT +public: + QDirectFbInput(QObject *parent); + void addWindow(DFBWindowID id, QWidget *tlw); + void removeWindow(WId wId); + +public slots: + void runInputEventLoop(); + void stopInputEventLoop(); + void handleEvents(); + +private: + void handleMouseEvents(const DFBEvent &event); + void handleWheelEvent(const DFBEvent &event); + void handleKeyEvents(const DFBEvent &event); + void handleEnterLeaveEvents(const DFBEvent &event); + inline QPoint globalPoint(const DFBEvent &event) const; + + + IDirectFB *m_dfbInterface; + IDirectFBDisplayLayer *m_dfbDisplayLayer; + IDirectFBEventBuffer *m_eventBuffer; + + bool m_shouldStop; + QSemaphore m_waitStop; + + QHash<DFBWindowID,QWidget *>m_tlwMap; +}; + +#endif // QDIRECTFBINPUT_H diff --git a/src/plugins/platforms/directfb/qdirectfbintegration.cpp b/src/plugins/platforms/directfb/qdirectfbintegration.cpp new file mode 100644 index 0000000..8639bdb --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbintegration.cpp @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** 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 plugins 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 "qdirectfbintegration.h" +#include "qdirectfbwindowsurface.h" +#include "qdirectfbblitter.h" +#include "qdirectfbconvenience.h" +#include "qdirectfbcursor.h" +#include "qdirectfbwindow.h" + +#include "qgenericunixfontdatabase.h" + +#include <private/qwindowsurface_raster_p.h> +#include <private/qpixmap_raster_p.h> + +#include <QtGui/private/qpixmap_blitter_p.h> +#include <QtGui/private/qpixmapdata_p.h> +#include <QtCore/QCoreApplication> +#include <QtCore/QThread> + +QT_BEGIN_NAMESPACE + +QDirectFbScreen::QDirectFbScreen(int display) + :QPlatformScreen() +{ + m_layer = QDirectFbConvenience::dfbDisplayLayer(display); + m_layer->SetCooperativeLevel(m_layer,DLSCL_SHARED); + + DFBDisplayLayerConfig config; + m_layer->GetConfiguration(m_layer, &config); + + m_format = QDirectFbConvenience::imageFormatFromSurfaceFormat(config.pixelformat, config.surface_caps); + m_geometry = QRect(0,0,config.width,config.height); + const int dpi = 72; + const qreal inch = 25.4; + m_depth = QDirectFbConvenience::colorDepthForSurface(config.pixelformat); + m_physicalSize = QSize(qRound(config.width * inch / dpi), qRound(config.height *inch / dpi)); + + cursor = new QDirectFBCursor(this); +} + +QDirectFbScreen::~QDirectFbScreen() +{ +} + +QDirectFbIntegration::QDirectFbIntegration() + : mFontDb(new QGenericUnixFontDatabase()) +{ + const QStringList args = QCoreApplication::arguments(); + int argc = args.size(); + char **argv = new char*[argc]; + + for (int i = 0; i < argc; ++i) + argv[i] = qstrdup(args.at(i).toLocal8Bit().constData()); + + DFBResult result = DirectFBInit(&argc, &argv); + if (result != DFB_OK) { + DirectFBError("QDirectFBScreen: error initializing DirectFB", + result); + } + delete[] argv; + + + QDirectFbScreen *primaryScreen = new QDirectFbScreen(0); + mScreens.append(primaryScreen); + + mInputRunner = new QThread; + mInput = new QDirectFbInput(0); + mInput->moveToThread(mInputRunner); + QObject::connect(mInputRunner,SIGNAL(started()),mInput,SLOT(runInputEventLoop())); + mInputRunner->start(); +} + +QDirectFbIntegration::~QDirectFbIntegration() +{ + mInput->stopInputEventLoop(); + delete mInputRunner; + delete mInput; +} + +QPixmapData *QDirectFbIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + if (type == QPixmapData::BitmapType) + return new QRasterPixmapData(type); + else + return new QDirectFbBlitterPixmapData; +} + +QPlatformWindow *QDirectFbIntegration::createPlatformWindow(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + QDirectFbInput *input = const_cast<QDirectFbInput *>(mInput);//gah + return new QDirectFbWindow(widget,input); +} + +QWindowSurface *QDirectFbIntegration::createWindowSurface(QWidget *widget, WId winId) const +{ + return new QDirectFbWindowSurface(widget,winId); +} + +QPlatformFontDatabase *QDirectFbIntegration::fontDatabase() const +{ + return mFontDb; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/directfb/qdirectfbintegration.h b/src/plugins/platforms/directfb/qdirectfbintegration.h new file mode 100644 index 0000000..965bdd2 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbintegration.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QPLATFORMINTEGRATION_DIRECTFB_H +#define QPLATFORMINTEGRATION_DIRECTFB_H + +#include "qdirectfbinput.h" + +#include <QtGui/QPlatformIntegration> +#include <directfb.h> +#include <directfb_version.h> + +QT_BEGIN_NAMESPACE + +class QThread; +class QDirectFBCursor; + +class QDirectFbScreen : public QPlatformScreen +{ +Q_OBJECT +public: + QDirectFbScreen(int display); + ~QDirectFbScreen(); + + QRect geometry() const { return m_geometry; } + int depth() const { return m_depth; } + QImage::Format format() const { return m_format; } + QSize physicalSize() const { return m_physicalSize; } + +public: + QRect m_geometry; + int m_depth; + QImage::Format m_format; + QSize m_physicalSize; + + IDirectFBDisplayLayer *m_layer; + +private: + QDirectFBCursor * cursor; + +}; + +class QDirectFbIntegration : public QPlatformIntegration +{ +public: + QDirectFbIntegration(); + ~QDirectFbIntegration(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId = 0) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QList<QPlatformScreen *> screens() const { return mScreens; } + + QPlatformFontDatabase *fontDatabase() const; + +private: + QList<QPlatformScreen *> mScreens; + QDirectFbInput *mInput; + QThread *mInputRunner; + QPlatformFontDatabase *mFontDb; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/directfb/qdirectfbwindow.cpp b/src/plugins/platforms/directfb/qdirectfbwindow.cpp new file mode 100644 index 0000000..1cd23ad --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbwindow.cpp @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** 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 plugins 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 "qdirectfbwindow.h" +#include "qdirectfbinput.h" +#include "qdirectfbglcontext.h" + +#include <QWidget> + +#include "qdirectfbwindowsurface.h" + +#include <directfb.h> + +QDirectFbWindow::QDirectFbWindow(QWidget *tlw, QDirectFbInput *inputhandler) + : QPlatformWindow(tlw), m_inputHandler(inputhandler), m_context(0) +{ + IDirectFBDisplayLayer *layer = QDirectFbConvenience::dfbDisplayLayer(); + DFBDisplayLayerConfig layerConfig; + layer->GetConfiguration(layer,&layerConfig); + + DFBWindowDescription description; + memset(&description,0,sizeof(DFBWindowDescription)); + description.flags = DFBWindowDescriptionFlags(DWDESC_WIDTH|DWDESC_HEIGHT|DWDESC_POSX|DWDESC_POSY|DWDESC_SURFACE_CAPS +#if DIRECTFB_MINOR_VERSION >= 1 + |DWDESC_OPTIONS +#endif + |DWDESC_CAPS); + description.width = tlw->rect().width(); + description.height = tlw->rect().height(); + description.posx = tlw->rect().x(); + description.posy = tlw->rect().y(); + + if (layerConfig.surface_caps & DSCAPS_PREMULTIPLIED) + description.surface_caps = DSCAPS_PREMULTIPLIED; + description.pixelformat = layerConfig.pixelformat; + +#if DIRECTFB_MINOR_VERSION >= 1 + description.options = DFBWindowOptions(DWOP_ALPHACHANNEL); +#endif + description.caps = DFBWindowCapabilities(DWCAPS_DOUBLEBUFFER|DWCAPS_ALPHACHANNEL); + description.surface_caps = DSCAPS_PREMULTIPLIED; + + DFBResult result = layer->CreateWindow(layer,&description,&m_dfbWindow); + if (result != DFB_OK) { + DirectFBError("QDirectFbGraphicsSystemScreen: failed to create window",result); + } + + m_dfbWindow->SetOpacity(m_dfbWindow,0xff); + + setVisible(widget()->isVisible()); + + DFBWindowID id; + m_dfbWindow->GetID(m_dfbWindow, &id); + m_inputHandler->addWindow(id,tlw); +} + +QDirectFbWindow::~QDirectFbWindow() +{ + m_inputHandler->removeWindow(winId()); + m_dfbWindow->Destroy(m_dfbWindow); +} + +void QDirectFbWindow::setGeometry(const QRect &rect) +{ + bool isMoveOnly = (rect.topLeft() != geometry().topLeft()) && (rect.size() == geometry().size()); + QPlatformWindow::setGeometry(rect); + if (widget()->isVisible() && !(widget()->testAttribute(Qt::WA_DontShowOnScreen))) { + m_dfbWindow->SetBounds(m_dfbWindow, rect.x(),rect.y(), + rect.width(), rect.height()); + + //Hack. When moving since the WindowSurface of a window becomes invalid when moved + if (isMoveOnly) { //if resize then windowsurface is updated. + widget()->windowSurface()->resize(rect.size()); + widget()->update(); + } + } +} + +void QDirectFbWindow::setOpacity(qreal level) +{ + const quint8 windowOpacity = quint8(level * 0xff); + m_dfbWindow->SetOpacity(m_dfbWindow,windowOpacity); +} + +void QDirectFbWindow::setVisible(bool visible) +{ + if (visible) { + int x = geometry().x(); + int y = geometry().y(); + m_dfbWindow->MoveTo(m_dfbWindow,x,y); + } else { + IDirectFBDisplayLayer *displayLayer; + QDirectFbConvenience::dfbInterface()->GetDisplayLayer(QDirectFbConvenience::dfbInterface(),DLID_PRIMARY,&displayLayer); + + DFBDisplayLayerConfig config; + displayLayer->GetConfiguration(displayLayer,&config); + m_dfbWindow->MoveTo(m_dfbWindow,config.width+1,config.height + 1); + } +} + +Qt::WindowFlags QDirectFbWindow::setWindowFlags(Qt::WindowFlags flags) +{ + switch (flags & Qt::WindowType_Mask) { + case Qt::ToolTip: { + DFBWindowOptions options; + m_dfbWindow->GetOptions(m_dfbWindow,&options); + options = DFBWindowOptions(options | DWOP_GHOST); + m_dfbWindow->SetOptions(m_dfbWindow,options); + break; } + default: + break; + } + + m_dfbWindow->SetStackingClass(m_dfbWindow, flags & Qt::WindowStaysOnTopHint ? DWSC_UPPER : DWSC_MIDDLE); + return flags; +} + +void QDirectFbWindow::raise() +{ + m_dfbWindow->RaiseToTop(m_dfbWindow); +} + +void QDirectFbWindow::lower() +{ + m_dfbWindow->LowerToBottom(m_dfbWindow); +} + +WId QDirectFbWindow::winId() const +{ + DFBWindowID id; + m_dfbWindow->GetID(m_dfbWindow, &id); + return WId(id); +} + +QPlatformGLContext *QDirectFbWindow::glContext() const +{ + if (!m_context) { + IDirectFBSurface *surface; + DFBResult result = m_dfbWindow->GetSurface(m_dfbWindow,&surface); + if (result != DFB_OK) { + qWarning("could not retrieve surface in QDirectFbWindow::glContext()"); + return 0; + } + IDirectFBGL *gl; + result = surface->GetGL(surface,&gl); + if (result != DFB_OK) { + qWarning("could not retrieve IDirectFBGL in QDirectFbWindow::glContext()"); + return 0; + } + const_cast<QDirectFbWindow *>(this)->m_context = new QDirectFbGLContext(gl); + } + return m_context; +} diff --git a/src/plugins/platforms/directfb/qdirectfbwindow.h b/src/plugins/platforms/directfb/qdirectfbwindow.h new file mode 100644 index 0000000..19491c5 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbwindow.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QDIRECTFBWINDOW_H +#define QDIRECTFBWINDOW_H + +#include <QPlatformWindow> + +#include "qdirectfbconvenience.h" +#include "qdirectfbinput.h" + +QT_BEGIN_NAMESPACE + +class QDirectFbWindow : public QPlatformWindow +{ +public: + QDirectFbWindow(QWidget *tlw, QDirectFbInput *inputhandler); + ~QDirectFbWindow(); + + void setGeometry(const QRect &rect); + void setOpacity(qreal level); + + void setVisible(bool visible); + + Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags); + void raise(); + void lower(); + WId winId() const; + + QPlatformGLContext *glContext() const; + +private: + IDirectFBWindow *m_dfbWindow; + QDirectFbInput *m_inputHandler; + + QPlatformGLContext *m_context; +}; + +QT_END_NAMESPACE + +#endif // QDIRECTFBWINDOW_H diff --git a/src/plugins/platforms/directfb/qdirectfbwindowsurface.cpp b/src/plugins/platforms/directfb/qdirectfbwindowsurface.cpp new file mode 100644 index 0000000..b1a8899 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbwindowsurface.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** 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 plugins 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 "qdirectfbwindowsurface.h" +#include "qdirectfbintegration.h" +#include "qdirectfbblitter.h" +#include "qdirectfbconvenience.h" +#include <private/qpixmap_blitter_p.h> + +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +QDirectFbWindowSurface::QDirectFbWindowSurface(QWidget *window, WId wId) + : QWindowSurface(window), m_pixmap(0), m_pmdata(0), m_dfbSurface(0) +{ + + IDirectFBDisplayLayer *layer = QDirectFbConvenience::dfbDisplayLayer(); + + DFBWindowID id(wId); + IDirectFBWindow *dfbWindow; + + layer->GetWindow(layer,id,&dfbWindow); + + dfbWindow->GetSurface(dfbWindow,&m_dfbSurface); +//WRONGSIZE + QDirectFbBlitter *blitter = new QDirectFbBlitter(window->rect().size(), m_dfbSurface); + m_pmdata = new QDirectFbBlitterPixmapData; + m_pmdata->setBlittable(blitter); + m_pixmap = new QPixmap(m_pmdata); +} + +QDirectFbWindowSurface::~QDirectFbWindowSurface() +{ + delete m_pixmap; +} + +QPaintDevice *QDirectFbWindowSurface::paintDevice() +{ + return m_pixmap; +} + +void QDirectFbWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + m_pmdata->blittable()->unlock(); + + QVector<QRect> rects = region.rects(); + for (int i = 0 ; i < rects.size(); i++) { + const QRect rect = rects.at(i); + DFBRegion dfbReg = { rect.x() + offset.x(),rect.y() + offset.y(),rect.right() + offset.x(),rect.bottom() + offset.y()}; + m_dfbSurface->Flip(m_dfbSurface, &dfbReg, DFBSurfaceFlipFlags(DSFLIP_BLIT|DSFLIP_ONSYNC)); + } +} + +void QDirectFbWindowSurface::resize(const QSize &size) +{ + QWindowSurface::resize(size); + + //Have to add 1 ref ass it will be removed by deleting the old blitter in setBlittable + m_dfbSurface->AddRef(m_dfbSurface); + QDirectFbBlitter *blitter = new QDirectFbBlitter(size,m_dfbSurface); + m_pmdata->setBlittable(blitter); +} + +static inline void scrollSurface(IDirectFBSurface *surface, const QRect &r, int dx, int dy) +{ + const DFBRectangle rect = { r.x(), r.y(), r.width(), r.height() }; + surface->Blit(surface, surface, &rect, r.x() + dx, r.y() + dy); + const DFBRegion region = { rect.x + dx, rect.y + dy, r.right() + dx, r.bottom() + dy }; + surface->Flip(surface, ®ion, DFBSurfaceFlipFlags(DSFLIP_BLIT)); +} + +bool QDirectFbWindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + m_pmdata->blittable()->unlock(); + + if (!m_dfbSurface || area.isEmpty()) + return false; + m_dfbSurface->SetBlittingFlags(m_dfbSurface, DSBLIT_NOFX); + if (area.rectCount() == 1) { + scrollSurface(m_dfbSurface, area.boundingRect(), dx, dy); + } else { + const QVector<QRect> rects = area.rects(); + const int n = rects.size(); + for (int i=0; i<n; ++i) { + scrollSurface(m_dfbSurface, rects.at(i), dx, dy); + } + } + return true; +} + +void QDirectFbWindowSurface::beginPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +void QDirectFbWindowSurface::endPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/directfb/qdirectfbwindowsurface.h b/src/plugins/platforms/directfb/qdirectfbwindowsurface.h new file mode 100644 index 0000000..aaa74d4 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbwindowsurface.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_DIRECTFB_H +#define QWINDOWSURFACE_DIRECTFB_H + +#include <QtGui/private/qwindowsurface_p.h> +#include <private/qpixmap_blitter_p.h> + +#include <directfb.h> + +QT_BEGIN_NAMESPACE + +class QDirectFbWindowSurface : public QWindowSurface +{ +public: + QDirectFbWindowSurface(QWidget *window, WId wid); + ~QDirectFbWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize (const QSize &size); + bool scroll(const QRegion &area, int dx, int dy); + + void beginPaint(const QRegion ®ion); + void endPaint(const QRegion ®ion); + +private: + void lockSurfaceToImage(); + + QPixmap *m_pixmap; + QBlittablePixmapData *m_pmdata; + + IDirectFBSurface *m_dfbSurface; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglconvenience/qeglconvenience.cpp b/src/plugins/platforms/eglconvenience/qeglconvenience.cpp new file mode 100644 index 0000000..b203fe8 --- /dev/null +++ b/src/plugins/platforms/eglconvenience/qeglconvenience.cpp @@ -0,0 +1,316 @@ +/**************************************************************************** +** +** 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 plugins 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 "qeglconvenience.h" + +QT_BEGIN_NAMESPACE + +QVector<EGLint> q_createConfigAttributesFromFormat(const QPlatformWindowFormat &format) +{ + int redSize = format.redBufferSize(); + int greenSize = format.greenBufferSize(); + int blueSize = format.blueBufferSize(); + int alphaSize = format.alphaBufferSize(); + int depthSize = format.depthBufferSize(); + int stencilSize = format.stencilBufferSize(); + int sampleCount = format.samples(); + + // QPlatformWindowFormat uses a magic value of -1 to indicate "don't care", even when a buffer of that + // type has been requested. So we must check QPlatformWindowFormat's booleans too if size is -1: + if (format.alpha() && alphaSize <= 0) + alphaSize = 1; + if (format.depth() && depthSize <= 0) + depthSize = 1; + if (format.stencil() && stencilSize <= 0) + stencilSize = 1; + if (format.sampleBuffers() && sampleCount <= 0) + sampleCount = 1; + + // We want to make sure 16-bit configs are chosen over 32-bit configs as they will provide + // the best performance. The EGL config selection algorithm is a bit stange in this regard: + // The selection criteria for EGL_BUFFER_SIZE is "AtLeast", so we can't use it to discard + // 32-bit configs completely from the selection. So it then comes to the sorting algorithm. + // The red/green/blue sizes have a sort priority of 3, so they are sorted by first. The sort + // order is special and described as "by larger _total_ number of color bits.". So EGL will + // put 32-bit configs in the list before the 16-bit configs. However, the spec also goes on + // to say "If the requested number of bits in attrib_list for a particular component is 0, + // then the number of bits for that component is not considered". This part of the spec also + // seems to imply that setting the red/green/blue bits to zero means none of the components + // are considered and EGL disregards the entire sorting rule. It then looks to the next + // highest priority rule, which is EGL_BUFFER_SIZE. Despite the selection criteria being + // "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are + // put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit, + // we must set the red/green/blue sizes to zero. This has an unfortunate consequence that + // if the application sets the red/green/blue size to 5/6/5 on the QPlatformWindowFormat, + // they will probably get a 32-bit config, even when there's an RGB565 config available. + + // Now normalize the values so -1 becomes 0 + redSize = redSize > 0 ? redSize : 0; + greenSize = greenSize > 0 ? greenSize : 0; + blueSize = blueSize > 0 ? blueSize : 0; + alphaSize = alphaSize > 0 ? alphaSize : 0; + depthSize = depthSize > 0 ? depthSize : 0; + stencilSize = stencilSize > 0 ? stencilSize : 0; + sampleCount = sampleCount > 0 ? sampleCount : 0; + + QVector<EGLint> configAttributes; + + configAttributes.append(EGL_RED_SIZE); + configAttributes.append(redSize); + + configAttributes.append(EGL_GREEN_SIZE); + configAttributes.append(greenSize); + + configAttributes.append(EGL_BLUE_SIZE); + configAttributes.append(blueSize); + + configAttributes.append(EGL_ALPHA_SIZE); + configAttributes.append(alphaSize); + + configAttributes.append(EGL_DEPTH_SIZE); + configAttributes.append(depthSize); + + configAttributes.append(EGL_STENCIL_SIZE); + configAttributes.append(stencilSize); + + configAttributes.append(EGL_SAMPLES); + configAttributes.append(sampleCount); + + configAttributes.append(EGL_SAMPLE_BUFFERS); + configAttributes.append(sampleCount? 1:0); + + return configAttributes; +} + +bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes) +{ + int i = -1; + // Reduce the complexity of a configuration request to ask for less + // because the previous request did not result in success. Returns + // true if the complexity was reduced, or false if no further + // reductions in complexity are possible. + + i = configAttributes->indexOf(EGL_SWAP_BEHAVIOR); + if (i >= 0) { + configAttributes->remove(i,2); + } + +#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT + // For OpenVG, we sometimes try to create a surface using a pre-multiplied format. If we can't + // find a config which supports pre-multiplied formats, remove the flag on the surface type: + + i = configAttributes->indexOf(EGL_SURFACE_TYPE); + if (i >= 0) { + EGLint surfaceType = configAttributes->at(i +1); + if (surfaceType & EGL_VG_ALPHA_FORMAT_PRE_BIT) { + surfaceType ^= EGL_VG_ALPHA_FORMAT_PRE_BIT; + configAttributes->replace(i+1,surfaceType); + return true; + } + } +#endif + + // EGL chooses configs with the highest color depth over + // those with smaller (but faster) lower color depths. One + // way around this is to set EGL_BUFFER_SIZE to 16, which + // trumps the others. Of course, there may not be a 16-bit + // config available, so it's the first restraint we remove. + i = configAttributes->indexOf(EGL_BUFFER_SIZE); + if (i >= 0) { + if (configAttributes->at(i+1) == 16) { + configAttributes->remove(i,2); + return true; + } + } + + i = configAttributes->indexOf(EGL_SAMPLE_BUFFERS); + if (i >= 0) { + configAttributes->remove(i,2); + i = configAttributes->indexOf(EGL_SAMPLES); + if (i >= 0) { + configAttributes->remove(i,2); + } + return true; + } + + i = configAttributes->indexOf(EGL_ALPHA_SIZE); + if (i >= 0) { + configAttributes->remove(i,2); +#if defined(EGL_BIND_TO_TEXTURE_RGBA) && defined(EGL_BIND_TO_TEXTURE_RGB) + i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGBA); + if (i >= 0) { + configAttributes->replace(i,EGL_BIND_TO_TEXTURE_RGB); + configAttributes->replace(i+1,TRUE); + + } +#endif + return true; + } + + i = configAttributes->indexOf(EGL_STENCIL_SIZE); + if (i >= 0) { + configAttributes->remove(i,2); + return true; + } + i = configAttributes->indexOf(EGL_DEPTH_SIZE); + if (i >= 0) { + configAttributes->remove(i,2); + return true; + } +#ifdef EGL_BIND_TO_TEXTURE_RGB + i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGB); + if (i >= 0) { + configAttributes->remove(i,2); + return true; + } +#endif + + return false; +} + +EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format) +{ + EGLConfig cfg = 0; + QVector<EGLint> configureAttributes = q_createConfigAttributesFromFormat(format); + configureAttributes.append(EGL_SURFACE_TYPE); //we only support eglconfigs for windows for now + configureAttributes.append(EGL_WINDOW_BIT); + + configureAttributes.append(EGL_RENDERABLE_TYPE); + if (format.windowApi() == QPlatformWindowFormat::OpenVG) { + configureAttributes.append(EGL_OPENVG_BIT); + } else { + configureAttributes.append(EGL_OPENGL_ES2_BIT); + } + configureAttributes.append(EGL_NONE); + + do { + // Get the number of matching configurations for this set of properties. + EGLint matching = 0; + if (!eglChooseConfig(display, configureAttributes.constData(), 0, 0, &matching) || !matching) + continue; + +// // If we want the best pixel format, then return the first +// // matching configuration. +// if (match == QEgl::BestPixelFormat) { +// eglChooseConfig(display, props.properties(), &cfg, 1, &matching); +// if (matching < 1) +// continue; +// return cfg; +// } + + // Fetch all of the matching configurations and find the + // first that matches the pixel format we wanted. + int i = configureAttributes.indexOf(EGL_RED_SIZE); + int confAttrRed = configureAttributes.at(i+1); + i = configureAttributes.indexOf(EGL_GREEN_SIZE); + int confAttrGreen = configureAttributes.at(i+1); + i = configureAttributes.indexOf(EGL_BLUE_SIZE); + int confAttrBlue = configureAttributes.at(i+1); + i = configureAttributes.indexOf(EGL_ALPHA_SIZE); + int confAttrAlpha = configureAttributes.at(i+1); + + EGLint size = matching; + EGLConfig *configs = new EGLConfig [size]; + eglChooseConfig(display, configureAttributes.constData(), configs, size, &matching); + for (EGLint index = 0; index < size; ++index) { + EGLint red, green, blue, alpha; + eglGetConfigAttrib(display, configs[index], EGL_RED_SIZE, &red); + eglGetConfigAttrib(display, configs[index], EGL_GREEN_SIZE, &green); + eglGetConfigAttrib(display, configs[index], EGL_BLUE_SIZE, &blue); + eglGetConfigAttrib(display, configs[index], EGL_ALPHA_SIZE, &alpha); + if (red == confAttrRed && + green == confAttrGreen && + blue == confAttrBlue && + (confAttrAlpha == 0 || + alpha == confAttrAlpha)) { + cfg = configs[index]; + delete [] configs; + return cfg; + } + } + delete [] configs; + } while (q_reduceConfigAttributes(&configureAttributes)); + qWarning("Cant find EGLConfig, returning null config"); + return 0; +} + +QPlatformWindowFormat qt_qPlatformWindowFormatFromConfig(EGLDisplay display, const EGLConfig config) +{ + QPlatformWindowFormat format; + EGLint redSize = 0; + EGLint greenSize = 0; + EGLint blueSize = 0; + EGLint alphaSize = 0; + EGLint depthSize = 0; + EGLint stencilSize = 0; + EGLint sampleCount = 0; + EGLint level = 0; + + eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize); + eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize); + eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize); + eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize); + eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depthSize); + eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize); + eglGetConfigAttrib(display, config, EGL_SAMPLES, &sampleCount); + eglGetConfigAttrib(display, config, EGL_LEVEL, &level); + + format.setRedBufferSize(redSize); + format.setGreenBufferSize(greenSize); + format.setBlueBufferSize(blueSize); + format.setAlphaBufferSize(alphaSize); + format.setDepthBufferSize(depthSize); + format.setStencilBufferSize(stencilSize); + format.setSamples(sampleCount); + format.setDirectRendering(true); // All EGL contexts are direct-rendered + format.setRgba(true); // EGL doesn't support colour index rendering + format.setStereo(false); // EGL doesn't support stereo buffers + format.setAccumBufferSize(0); // EGL doesn't support accululation buffers + + // Clear the EGL error state because some of the above may + // have errored out because the attribute is not applicable + // to the surface type. Such errors don't matter. + eglGetError(); + + return format; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglconvenience/qeglconvenience.h b/src/plugins/platforms/eglconvenience/qeglconvenience.h new file mode 100644 index 0000000..604262b --- /dev/null +++ b/src/plugins/platforms/eglconvenience/qeglconvenience.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QEGLCONVENIENCE_H +#define QEGLCONVENIENCE_H + + +#include <QtGui/QPlatformWindowFormat> +#include <QtCore/QVector> + +#include <EGL/egl.h> +QT_BEGIN_NAMESPACE + +QVector<EGLint> q_createConfigAttributesFromFormat(const QPlatformWindowFormat &format); +bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes); +EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format); +QPlatformWindowFormat qt_qPlatformWindowFormatFromConfig(EGLDisplay display, const EGLConfig config); + +QT_END_NAMESPACE + +#endif //QEGLCONVENIENCE_H diff --git a/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp b/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp new file mode 100644 index 0000000..ae3b539 --- /dev/null +++ b/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** 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 plugins 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 "qeglplatformcontext.h" + + +#include <QtGui/QPlatformWindow> + +#include "qeglconvenience.h" + +#include <EGL/egl.h> + +QEGLPlatformContext::QEGLPlatformContext(EGLDisplay display, EGLConfig config, EGLint contextAttrs[], EGLSurface surface, EGLenum eglApi) + : QPlatformGLContext() + , m_eglDisplay(display) + , m_eglSurface(surface) + , m_eglApi(eglApi) +{ + if (m_eglSurface == EGL_NO_SURFACE) { + qWarning("Createing QEGLPlatformContext with no surface"); + } + + eglBindAPI(m_eglApi); + m_eglContext = eglCreateContext(m_eglDisplay,config, 0,contextAttrs); + if (m_eglContext == EGL_NO_CONTEXT) { + qWarning("Could not create the egl context\n"); + eglTerminate(m_eglDisplay); + qFatal("EGL error"); + } + + m_windowFormat = qt_qPlatformWindowFormatFromConfig(display,config); +} + +QEGLPlatformContext::~QEGLPlatformContext() +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglContext::~QEglContext(): %p\n",this); +#endif + if (m_eglSurface != EGL_NO_SURFACE) { + doneCurrent(); + eglDestroySurface(m_eglDisplay, m_eglSurface); + m_eglSurface = EGL_NO_SURFACE; + } + + if (m_eglContext != EGL_NO_CONTEXT) { + eglDestroyContext(m_eglDisplay, m_eglContext); + m_eglContext = EGL_NO_CONTEXT; + } +} + +void QEGLPlatformContext::makeCurrent() +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglContext::makeCurrent: %p\n",this); +#endif + eglBindAPI(m_eglApi); + bool ok = eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); + if (!ok) + qWarning("QEGLPlatformContext::makeCurrent: eglError: %d, this: %p \n", eglGetError(), this); +#ifdef QEGL_EXTRA_DEBUG + static bool showDebug = true; + if (showDebug) { + showDebug = false; + const char *str = (const char*)glGetString(GL_VENDOR); + qWarning("Vendor %s\n", str); + str = (const char*)glGetString(GL_RENDERER); + qWarning("Renderer %s\n", str); + str = (const char*)glGetString(GL_VERSION); + qWarning("Version %s\n", str); + + str = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); + qWarning("Extensions %s\n",str); + + str = (const char*)glGetString(GL_EXTENSIONS); + qWarning("Extensions %s\n", str); + + } +#endif +} +void QEGLPlatformContext::doneCurrent() +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglContext::doneCurrent:%p\n",this); +#endif + eglBindAPI(m_eglApi); + bool ok = eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (!ok) + qWarning("QEGLPlatformContext::doneCurrent(): eglError: %d, this: %p \n", eglGetError(), this); +} +void QEGLPlatformContext::swapBuffers() +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglContext::swapBuffers:%p\n",this); +#endif + eglBindAPI(m_eglApi); + bool ok = eglSwapBuffers(m_eglDisplay, m_eglSurface); + if (!ok) + qWarning("QEGLPlatformContext::swapBuffers(): eglError: %d, this: %p \n", eglGetError(), this); +} +void* QEGLPlatformContext::getProcAddress(const QString& procName) +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglContext::getProcAddress%p\n",this); +#endif + eglBindAPI(m_eglApi); + return (void *)eglGetProcAddress(qPrintable(procName)); +} + +void QEGLPlatformContext::makeDefaultSaredContext() +{ + setDefaultSharedContext(this); +} + +QPlatformWindowFormat QEGLPlatformContext::platformWindowFormat() const +{ + return m_windowFormat; +} diff --git a/src/plugins/platforms/eglconvenience/qeglplatformcontext.h b/src/plugins/platforms/eglconvenience/qeglplatformcontext.h new file mode 100644 index 0000000..ae1a891 --- /dev/null +++ b/src/plugins/platforms/eglconvenience/qeglplatformcontext.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QOPENKODEGLINTEGRATION_H +#define QOPENKODEGLINTEGRATION_H + +#include <QtGui/QPlatformGLContext> +#include <EGL/egl.h> + +class QEGLPlatformContext : public QPlatformGLContext +{ +public: + QEGLPlatformContext(EGLDisplay display, EGLConfig config, EGLint contextAttrs[], EGLSurface surface, EGLenum eglApi); + ~QEGLPlatformContext(); + + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void* getProcAddress(const QString& procName); + + void makeDefaultSaredContext(); + + QPlatformWindowFormat platformWindowFormat() const; +private: + EGLContext m_eglContext; + EGLDisplay m_eglDisplay; + EGLSurface m_eglSurface; + EGLenum m_eglApi; + + QPlatformWindowFormat m_windowFormat; +}; + +#endif //QOPENKODEGLINTEGRATION_H diff --git a/src/plugins/platforms/eglfs/eglfs.pro b/src/plugins/platforms/eglfs/eglfs.pro new file mode 100644 index 0000000..7ad8fd9 --- /dev/null +++ b/src/plugins/platforms/eglfs/eglfs.pro @@ -0,0 +1,31 @@ +TARGET = qeglfs +TEMPLATE = lib +CONFIG += plugin + +QT += opengl + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +#DEFINES += QEGL_EXTRA_DEBUG + +#DEFINES += Q_OPENKODE + +SOURCES = main.cpp \ + qeglfsintegration.cpp \ + ../eglconvenience/qeglconvenience.cpp \ + ../eglconvenience/qeglplatformcontext.cpp \ + qeglfswindow.cpp \ + qeglfswindowsurface.cpp \ + qeglfsscreen.cpp + +HEADERS = qeglfsintegration.h \ + ../eglconvenience/qeglconvenience.h \ + ../eglconvenience/qeglplatformcontext.h \ + qeglfswindow.h \ + qeglfswindowsurface.h \ + qeglfsscreen.h + +include(../fontdatabases/genericunix/genericunix.pri) + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target diff --git a/src/plugins/platforms/eglfs/main.cpp b/src/plugins/platforms/eglfs/main.cpp new file mode 100644 index 0000000..d0a82b7 --- /dev/null +++ b/src/plugins/platforms/eglfs/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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 plugins 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 <QtGui/QPlatformIntegrationPlugin> +#include "qeglfsintegration.h" + +QT_BEGIN_NAMESPACE + +class QEglIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QEglIntegrationPlugin::keys() const +{ + QStringList list; + list << "EglFS"; + return list; +} + +QPlatformIntegration* QEglIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "eglfs") + return new QEglFSIntegration; + + return 0; +} + +Q_EXPORT_PLUGIN2(eglintegration, QEglIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp new file mode 100644 index 0000000..a48fde8 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** 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 plugins 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 "qeglfsintegration.h" + +#include "qeglfswindow.h" +#include "qeglfswindowsurface.h" + +#include <QtGui/QPlatformWindow> +#include <QtGui/QPlatformWindowFormat> +#include <QtOpenGL/private/qpixmapdata_gl_p.h> + +#include "qgenericunixfontdatabase.h" + +#include <EGL/egl.h> + +QT_BEGIN_NAMESPACE + +QEglFSIntegration::QEglFSIntegration() + : mFontDb(new QGenericUnixFontDatabase()) +{ + m_primaryScreen = new QEglFSScreen(EGL_DEFAULT_DISPLAY); + + mScreens.append(m_primaryScreen); +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglIntegration\n"); +#endif +} + +QPixmapData *QEglFSIntegration::createPixmapData(QPixmapData::PixelType type) const +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglIntegration::createPixmapData %d\n", type); +#endif + return new QGLPixmapData(type); +} + +QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglIntegration::createPlatformWindow %p\n",widget); +#endif + return new QEglFSWindow(widget, m_primaryScreen); +} + + +QWindowSurface *QEglFSIntegration::createWindowSurface(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglIntegration::createWindowSurface %p\n",widget); +#endif + return new QEglFSWindowSurface(m_primaryScreen,widget); +} + +QPlatformFontDatabase *QEglFSIntegration::fontDatabase() const +{ + return mFontDb; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.h b/src/plugins/platforms/eglfs/qeglfsintegration.h new file mode 100644 index 0000000..0342539 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfsintegration.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef EGLINTEGRATION_H +#define EGLINTEGRATION_H + +#include "qeglfsscreen.h" + +#include <QtGui/QPlatformIntegration> +#include <QtGui/QPlatformScreen> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QEglFSIntegration : public QPlatformIntegration +{ +public: + QEglFSIntegration(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QList<QPlatformScreen *> screens() const { return mScreens; } + + QPlatformFontDatabase *fontDatabase() const; + +private: + QPlatformFontDatabase *mFontDb; + QList<QPlatformScreen *> mScreens; + QEglFSScreen *m_primaryScreen; +}; + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp new file mode 100644 index 0000000..9a40b86 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** 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 plugins 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 "qeglfsscreen.h" + +#include "../eglconvenience/qeglconvenience.h" +#include "../eglconvenience/qeglplatformcontext.h" + +#ifdef Q_OPENKODE +#include <KD/kd.h> +#include <KD/NV_initialize.h> +#endif //Q_OPENKODE + +QT_BEGIN_NAMESPACE + +// #define QEGL_EXTRA_DEBUG + +#ifdef QEGL_EXTRA_DEBUG +struct AttrInfo { EGLint attr; const char *name; }; +static struct AttrInfo attrs[] = { + {EGL_BUFFER_SIZE, "EGL_BUFFER_SIZE"}, + {EGL_ALPHA_SIZE, "EGL_ALPHA_SIZE"}, + {EGL_BLUE_SIZE, "EGL_BLUE_SIZE"}, + {EGL_GREEN_SIZE, "EGL_GREEN_SIZE"}, + {EGL_RED_SIZE, "EGL_RED_SIZE"}, + {EGL_DEPTH_SIZE, "EGL_DEPTH_SIZE"}, + {EGL_STENCIL_SIZE, "EGL_STENCIL_SIZE"}, + {EGL_CONFIG_CAVEAT, "EGL_CONFIG_CAVEAT"}, + {EGL_CONFIG_ID, "EGL_CONFIG_ID"}, + {EGL_LEVEL, "EGL_LEVEL"}, + {EGL_MAX_PBUFFER_HEIGHT, "EGL_MAX_PBUFFER_HEIGHT"}, + {EGL_MAX_PBUFFER_PIXELS, "EGL_MAX_PBUFFER_PIXELS"}, + {EGL_MAX_PBUFFER_WIDTH, "EGL_MAX_PBUFFER_WIDTH"}, + {EGL_NATIVE_RENDERABLE, "EGL_NATIVE_RENDERABLE"}, + {EGL_NATIVE_VISUAL_ID, "EGL_NATIVE_VISUAL_ID"}, + {EGL_NATIVE_VISUAL_TYPE, "EGL_NATIVE_VISUAL_TYPE"}, + {EGL_SAMPLES, "EGL_SAMPLES"}, + {EGL_SAMPLE_BUFFERS, "EGL_SAMPLE_BUFFERS"}, + {EGL_SURFACE_TYPE, "EGL_SURFACE_TYPE"}, + {EGL_TRANSPARENT_TYPE, "EGL_TRANSPARENT_TYPE"}, + {EGL_TRANSPARENT_BLUE_VALUE, "EGL_TRANSPARENT_BLUE_VALUE"}, + {EGL_TRANSPARENT_GREEN_VALUE, "EGL_TRANSPARENT_GREEN_VALUE"}, + {EGL_TRANSPARENT_RED_VALUE, "EGL_TRANSPARENT_RED_VALUE"}, + {EGL_BIND_TO_TEXTURE_RGB, "EGL_BIND_TO_TEXTURE_RGB"}, + {EGL_BIND_TO_TEXTURE_RGBA, "EGL_BIND_TO_TEXTURE_RGBA"}, + {EGL_MIN_SWAP_INTERVAL, "EGL_MIN_SWAP_INTERVAL"}, + {EGL_MAX_SWAP_INTERVAL, "EGL_MAX_SWAP_INTERVAL"}, + {-1, 0}}; +#endif //QEGL_EXTRA_DEBUG + +QEglFSScreen::QEglFSScreen(EGLNativeDisplayType display) + : m_depth(32), m_format(QImage::Format_ARGB32_Premultiplied), m_platformContext(0) +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglScreen %p\n", this); +#endif + + EGLint major, minor; +#ifdef QEGL_EXTRA_DEBUG + EGLint index; +#endif + if (!eglBindAPI(EGL_OPENGL_ES_API)) { + qWarning("Could not bind GL_ES API\n"); + qFatal("EGL error"); + } + + m_dpy = eglGetDisplay(display); + if (m_dpy == EGL_NO_DISPLAY) { + qWarning("Could not open egl display\n"); + qFatal("EGL error"); + } + qWarning("Opened display %p\n", m_dpy); + + if (!eglInitialize(m_dpy, &major, &minor)) { + qWarning("Could not initialize egl display\n"); + qFatal("EGL error"); + } + + qWarning("Initialized display %d %d\n", major, minor); + + QPlatformWindowFormat platformFormat; + platformFormat.setWindowApi(QPlatformWindowFormat::OpenGL); + + QByteArray depthString = qgetenv("QT_QPA_EGLFS_DEPTH"); + if (depthString.toInt() == 16) { + platformFormat.setDepth(16); + platformFormat.setRedBufferSize(5); + platformFormat.setGreenBufferSize(6); + platformFormat.setBlueBufferSize(5); + m_depth = 16; + m_format = QImage::Format_RGB16; + } else { + platformFormat.setDepth(32); + platformFormat.setRedBufferSize(8); + platformFormat.setGreenBufferSize(8); + platformFormat.setBlueBufferSize(8); + } + + if (!qgetenv("QT_QPA_EGLFS_MULTISAMPLE").isEmpty()) { + platformFormat.setSampleBuffers(true); + } + + int swapInterval = 1; + QByteArray swapIntervalString = qgetenv("QT_QPA_EGLFS_SWAPINTERVAL"); + if (!swapIntervalString.isEmpty()) { + bool ok; + swapInterval = swapIntervalString.toInt(&ok); + if (!ok) + swapInterval = 1; + } + + EGLConfig config = q_configFromQPlatformWindowFormat(m_dpy, platformFormat); + eglSwapInterval(display, swapInterval); + + EGLNativeWindowType eglWindow = 0; +#ifdef Q_OPENKODE + if (kdInitializeNV() == KD_ENOTINITIALIZED) { + qFatal("Did not manage to initialize openkode"); + } + KDWindow *window = kdCreateWindow(m_dpy,config,0); + + kdRealizeWindow(window,&eglWindow); +#endif + + m_surface = eglCreateWindowSurface(m_dpy, config, eglWindow, NULL); + if (m_surface == EGL_NO_SURFACE) { + qWarning("Could not create the egl surface: error = 0x%x\n", eglGetError()); + eglTerminate(m_dpy); + qFatal("EGL error"); + } + // qWarning("Created surface %dx%d\n", w, h); + +#ifdef QEGL_EXTRA_DEBUG + qWarning("Configuration %d matches requirements\n", (int)config); + + for (index = 0; attrs[index].attr != -1; ++index) { + EGLint value; + if (eglGetConfigAttrib(m_dpy, config, attrs[index].attr, &value)) { + qWarning("\t%s: %d\n", attrs[index].name, (int)value); + } + } + qWarning("\n"); +#endif + + EGLint temp; + EGLint attribList[32]; + + temp = 0; + + attribList[temp++] = EGL_CONTEXT_CLIENT_VERSION; + attribList[temp++] = 2; // GLES version 2 + attribList[temp++] = EGL_NONE; + + m_platformContext = new QEGLPlatformContext(m_dpy,config,attribList,m_surface,EGL_OPENGL_ES_API); + +// qWarning("Created platformcontext"); + EGLint w,h; + + eglQuerySurface(m_dpy, m_surface, EGL_WIDTH, &w); + eglQuerySurface(m_dpy, m_surface, EGL_HEIGHT, &h); + + m_geometry = QRect(0,0,w,h); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.h b/src/plugins/platforms/eglfs/qeglfsscreen.h new file mode 100644 index 0000000..9ed1b04 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfsscreen.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QEGLSCREEN_H +#define QEGLSCREEN_H + +#include <QPlatformScreen> + + +#include <EGL/egl.h> + +QT_BEGIN_NAMESPACE + +class QPlatformGLContext; + +class QEglFSScreen : public QPlatformScreen //huh: FullScreenScreen ;) just to follow namespace +{ +public: + QEglFSScreen(EGLNativeDisplayType display); + ~QEglFSScreen() {} + + QRect geometry() const { return m_geometry; } + int depth() const { return m_depth; } + QImage::Format format() const { return m_format; } + + QPlatformGLContext *platformContext() const { return m_platformContext; } + +private: + QRect m_geometry; + int m_depth; + QImage::Format m_format; + QPlatformGLContext *m_platformContext; + EGLDisplay m_dpy; + EGLSurface m_surface; +}; + +QT_END_NAMESPACE +#endif // QEGLSCREEN_H diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp new file mode 100644 index 0000000..d0e15d3 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 plugins 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 "qeglfswindow.h" + +#include <QtGui/QWindowSystemInterface> + +QT_BEGIN_NAMESPACE + +QEglFSWindow::QEglFSWindow(QWidget *w, QEglFSScreen *screen) + : QPlatformWindow(w), m_screen(screen) +{ + static int serialNo = 0; + m_winid = ++serialNo; +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglWindow %p: %p %p 0x%x\n", this, w, screen, uint(m_winid)); +#endif +} + + +void QEglFSWindow::setGeometry(const QRect &) +{ + // We only support full-screen windows + QRect rect(m_screen->availableGeometry()); + QWindowSystemInterface::handleGeometryChange(this->widget(), rect); + + QPlatformWindow::setGeometry(rect); +} + +WId QEglFSWindow::winId() const +{ + return m_winid; +} + + + +QPlatformGLContext *QEglFSWindow::glContext() const +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglWindow::glContext %p\n", m_screen->platformContext()); +#endif + Q_ASSERT(m_screen); + return m_screen->platformContext(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h new file mode 100644 index 0000000..43f185b --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfswindow.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QEGLWINDOW_H +#define QEGLWINDOW_H + +#include "qeglfsintegration.h" +#include "qeglfsscreen.h" + + +#include <QPlatformWindow> +#include <QtGui/QWidget> + +#include <EGL/egl.h> + +QT_BEGIN_NAMESPACE + +class QEglFSWindow : public QPlatformWindow +{ +public: + QEglFSWindow(QWidget *w, QEglFSScreen *screen); + + void setGeometry(const QRect &); + WId winId() const; + + QPlatformGLContext *glContext() const; + +private: + QEglFSScreen *m_screen; + WId m_winid; +}; +QT_END_NAMESPACE +#endif // QEGLWINDOW_H diff --git a/src/plugins/platforms/eglfs/qeglfswindowsurface.cpp b/src/plugins/platforms/eglfs/qeglfswindowsurface.cpp new file mode 100644 index 0000000..fcea4d3 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfswindowsurface.cpp @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** 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 plugins 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 "qeglfswindowsurface.h" + +#include <QtGui/QPlatformGLContext> + +#include <QtOpenGL/private/qgl_p.h> +#include <QtOpenGL/private/qglpaintdevice_p.h> + +QT_BEGIN_NAMESPACE + +class QEglFSPaintDevice : public QGLPaintDevice +{ +public: + QEglFSPaintDevice(QEglFSScreen *screen, QWidget *widget) + :QGLPaintDevice(), m_screen(screen) + { + #ifdef QEGL_EXTRA_DEBUG + qWarning("QEglPaintDevice %p, %p, %p",this, screen, widget); + #endif + QGLFormat format; + m_context = new QGLContext(format, widget); + m_context->create(); + } + + QSize size() const { return m_screen->geometry().size(); } + QGLContext* context() const { return m_context;} + + QPaintEngine *paintEngine() const { return qt_qgl_paint_engine(); } + + void beginPaint(){ + QGLPaintDevice::beginPaint(); + } +private: + QEglFSScreen *m_screen; + QGLContext *m_context; +}; + + +QEglFSWindowSurface::QEglFSWindowSurface( QEglFSScreen *screen, QWidget *window ) + :QWindowSurface(window) +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglWindowSurface %p, %p", window, screen); +#endif + m_paintDevice = new QEglFSPaintDevice(screen,window); +} + +void QEglFSWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(region); + Q_UNUSED(offset); +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglWindowSurface::flush %p",widget); +#endif + widget->platformWindow()->glContext()->swapBuffers(); +} + +void QEglFSWindowSurface::resize(const QSize &size) +{ + Q_UNUSED(size); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfswindowsurface.h b/src/plugins/platforms/eglfs/qeglfswindowsurface.h new file mode 100644 index 0000000..f8aca40 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfswindowsurface.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QEGLWINDOWSURFACE_H +#define QEGLWINDOWSURFACE_H + +#include "qeglfsintegration.h" +#include "qeglfswindow.h" + +#include <QtGui/private/qwindowsurface_p.h> + +QT_BEGIN_NAMESPACE + +class QEglFSWindowSurface : public QWindowSurface +{ +public: + QEglFSWindowSurface(QEglFSScreen *screen, QWidget *window); + ~QEglFSWindowSurface() {} + + QPaintDevice *paintDevice() { return m_paintDevice; } + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); +private: + QPaintDevice *m_paintDevice; +}; + +QT_END_NAMESPACE + +#endif // QEGLWINDOWSURFACE_H diff --git a/src/plugins/platforms/fb_base/fb_base.cpp b/src/plugins/platforms/fb_base/fb_base.cpp new file mode 100644 index 0000000..b000a18 --- /dev/null +++ b/src/plugins/platforms/fb_base/fb_base.cpp @@ -0,0 +1,507 @@ +/**************************************************************************** +** +** 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 plugins 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 "fb_base.h" +#include <qpainter.h> +#include <qdebug.h> +#include <qbitmap.h> +#include <QPlatformCursor> +#include <QWindowSystemInterface> + +QPlatformSoftwareCursor::QPlatformSoftwareCursor(QPlatformScreen *scr) + : QPlatformCursor(scr), currentRect(QRect()), prevRect(QRect()) +{ + graphic = new QPlatformCursorImage(0, 0, 0, 0, 0, 0); + setCursor(Qt::ArrowCursor); +} + +QRect QPlatformSoftwareCursor::getCurrentRect() +{ + QRect rect = graphic->image()->rect().translated(-graphic->hotspot().x(), + -graphic->hotspot().y()); + rect.translate(QCursor::pos()); + QPoint screenOffset = screen->geometry().topLeft(); + rect.translate(-screenOffset); // global to local translation + return rect; +} + + +void QPlatformSoftwareCursor::pointerEvent(const QMouseEvent & e) +{ + Q_UNUSED(e); + QPoint screenOffset = screen->geometry().topLeft(); + currentRect = getCurrentRect(); + // global to local translation + if (onScreen || screen->geometry().intersects(currentRect.translated(screenOffset))) { + setDirty(); + } +} + +QRect QPlatformSoftwareCursor::drawCursor(QPainter & painter) +{ + dirty = false; + if (currentRect.isNull()) + return QRect(); + + // We need this because the cursor might be dirty due to moving off screen + QPoint screenOffset = screen->geometry().topLeft(); + // global to local translation + if (!currentRect.translated(screenOffset).intersects(screen->geometry())) + return QRect(); + + prevRect = currentRect; + painter.drawImage(prevRect, *graphic->image()); + onScreen = true; + return prevRect; +} + +QRect QPlatformSoftwareCursor::dirtyRect() +{ + if (onScreen) { + onScreen = false; + return prevRect; + } + return QRect(); +} + +void QPlatformSoftwareCursor::setCursor(Qt::CursorShape shape) +{ + graphic->set(shape); +} + +void QPlatformSoftwareCursor::setCursor(const QImage &image, int hotx, int hoty) +{ + graphic->set(image, hotx, hoty); +} + +void QPlatformSoftwareCursor::setCursor(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY) +{ + graphic->set(data, mask, width, height, hotX, hotY); +} + +void QPlatformSoftwareCursor::changeCursor(QCursor * widgetCursor, QWidget * widget) +{ + Q_UNUSED(widget); + Qt::CursorShape shape = widgetCursor->shape(); + + if (shape == Qt::BitmapCursor) { + // application supplied cursor + QPoint spot = widgetCursor->hotSpot(); + setCursor(widgetCursor->pixmap().toImage(), spot.x(), spot.y()); + } else { + // system cursor + setCursor(shape); + } + currentRect = getCurrentRect(); + QPoint screenOffset = screen->geometry().topLeft(); // global to local translation + if (onScreen || screen->geometry().intersects(currentRect.translated(screenOffset))) + setDirty(); +} + +QFbScreen::QFbScreen() : cursor(0), mGeometry(), mDepth(16), mFormat(QImage::Format_RGB16), mScreenImage(0), compositePainter(0), isUpToDate(false) +{ + mScreenImage = new QImage(mGeometry.size(), mFormat); + redrawTimer.setSingleShot(true); + redrawTimer.setInterval(0); + QObject::connect(&redrawTimer, SIGNAL(timeout()), this, SLOT(doRedraw())); +} + +void QFbScreen::setGeometry(QRect rect) +{ + delete mScreenImage; + mGeometry = rect; + mScreenImage = new QImage(mGeometry.size(), mFormat); + delete compositePainter; + compositePainter = 0; + invalidateRectCache(); +} + +void QFbScreen::setDepth(int depth) +{ + mDepth = depth; +} + +void QFbScreen::setPhysicalSize(QSize size) +{ + mPhysicalSize = size; +} + +void QFbScreen::setFormat(QImage::Format format) +{ + mFormat = format; + delete mScreenImage; + mScreenImage = new QImage(mGeometry.size(), mFormat); + delete compositePainter; + compositePainter = 0; +} + +QFbScreen::~QFbScreen() +{ + delete compositePainter; + delete mScreenImage; +} + +void QFbScreen::setDirty(const QRect &rect) +{ + QRect intersection = rect.intersected(mGeometry); + QPoint screenOffset = mGeometry.topLeft(); + repaintRegion += intersection.translated(-screenOffset); // global to local translation + if (!redrawTimer.isActive()) { + redrawTimer.start(); + } +} + +void QFbScreen::generateRects() +{ + cachedRects.clear(); + QPoint screenOffset = mGeometry.topLeft(); + QRegion remainingScreen(mGeometry.translated(-screenOffset)); // global to local translation + + for (int i = 0; i < windowStack.length(); i++) { + if (remainingScreen.isEmpty()) + break; + if (!windowStack[i]->visible()) + continue; + if (windowStack[i]->widget()->isMinimized()) + continue; + + if (!windowStack[i]->widget()->testAttribute(Qt::WA_TranslucentBackground)) { + QRect localGeometry = windowStack.at(i)->geometry().translated(-screenOffset); // global to local translation + remainingScreen -= localGeometry; + QRegion windowRegion(localGeometry); + windowRegion -= remainingScreen; + foreach(QRect rect, windowRegion.rects()) { + cachedRects += QPair<QRect, int>(rect, i); + } + } + } + foreach (QRect rect, remainingScreen.rects()) + cachedRects += QPair<QRect, int>(rect, -1); + isUpToDate = true; + return; +} + + + +QRegion QFbScreen::doRedraw() +{ + QPoint screenOffset = mGeometry.topLeft(); + + QRegion touchedRegion; + if (cursor && cursor->isDirty() && cursor->isOnScreen()) { + QRect lastCursor = cursor->dirtyRect(); + repaintRegion += lastCursor; + } + if (repaintRegion.isEmpty() && (!cursor || !cursor->isDirty())) { + return touchedRegion; + } + + QVector<QRect> rects = repaintRegion.rects(); + + if (!isUpToDate) + generateRects(); + + if (!compositePainter) + compositePainter = new QPainter(mScreenImage); + for (int rectIndex = 0; rectIndex < repaintRegion.numRects(); rectIndex++) { + QRegion rectRegion = rects[rectIndex]; + + for(int i = 0; i < cachedRects.length(); i++) { + QRect screenSubRect = cachedRects[i].first; + int layer = cachedRects[i].second; + QRegion intersect = rectRegion.intersected(screenSubRect); + + if (intersect.isEmpty()) + continue; + + rectRegion -= intersect; + + // we only expect one rectangle, but defensive coding... + foreach (QRect rect, intersect.rects()) { + bool firstLayer = true; + if (layer == -1) { + compositePainter->fillRect(rect, Qt::black); + firstLayer = false; + layer = windowStack.size() - 1; + } + + for (int layerIndex = layer; layerIndex != -1; layerIndex--) { + if (!windowStack[layerIndex]->visible()) + continue; + if (windowStack[layerIndex]->widget()->isMinimized()) + continue; + QRect windowRect = windowStack[layerIndex]->geometry().translated(-screenOffset); + QRect windowIntersect = rect.translated(-windowRect.left(), + -windowRect.top()); + compositePainter->drawImage(rect, windowStack[layerIndex]->surface->image(), + windowIntersect); + if (firstLayer) { + firstLayer = false; + } + } + } + } + } + + QRect cursorRect; + if (cursor && (cursor->isDirty() || repaintRegion.intersects(cursor->lastPainted()))) { + cursorRect = cursor->drawCursor(*compositePainter); + touchedRegion += cursorRect; + } + touchedRegion += repaintRegion; + repaintRegion = QRegion(); + + + +// qDebug() << "QFbScreen::doRedraw" << windowStack.size() << mScreenImage->size() << touchedRegion; + + + return touchedRegion; +} + +void QFbScreen::addWindow(QFbWindow *surface) +{ + windowStack.prepend(surface); + surface->mScreens.append(this); + invalidateRectCache(); + setDirty(surface->geometry()); +} + +void QFbScreen::removeWindow(QFbWindow * surface) +{ + windowStack.removeOne(surface); + surface->mScreens.removeOne(this); + invalidateRectCache(); + setDirty(surface->geometry()); +} + +void QFbWindow::raise() +{ + QList<QFbScreen *>::const_iterator i = mScreens.constBegin(); + QList<QFbScreen *>::const_iterator end = mScreens.constEnd(); + while (i != end) { + (*i)->raise(this); + ++i; + } +} + +void QFbScreen::raise(QPlatformWindow * surface) +{ + QFbWindow *s = static_cast<QFbWindow *>(surface); + int index = windowStack.indexOf(s); + if (index <= 0) + return; + windowStack.move(index, 0); + invalidateRectCache(); + setDirty(s->geometry()); +} + +void QFbWindow::lower() +{ + QList<QFbScreen *>::const_iterator i = mScreens.constBegin(); + QList<QFbScreen *>::const_iterator end = mScreens.constEnd(); + while (i != end) { + (*i)->lower(this); + ++i; + } +} + +void QFbScreen::lower(QPlatformWindow * surface) +{ + QFbWindow *s = static_cast<QFbWindow *>(surface); + int index = windowStack.indexOf(s); + if (index == -1 || index == (windowStack.size() - 1)) + return; + windowStack.move(index, windowStack.size() - 1); + invalidateRectCache(); + setDirty(s->geometry()); +} + +QWidget * QFbScreen::topLevelAt(const QPoint & p) const +{ + for(int i = 0; i < windowStack.size(); i++) { + if (windowStack[i]->geometry().contains(p, false) && + windowStack[i]->visible() && + !windowStack[i]->widget()->isMinimized()) { + return windowStack[i]->widget(); + } + } + return 0; +} + +QFbWindow::QFbWindow(QWidget *window) + :QPlatformWindow(window), + visibleFlag(false) +{ + static QAtomicInt winIdGenerator(1); + windowId = winIdGenerator.fetchAndAddRelaxed(1); +} + + +QFbWindow::~QFbWindow() +{ + QList<QFbScreen *>::const_iterator i = mScreens.constBegin(); + QList<QFbScreen *>::const_iterator end = mScreens.constEnd(); + while (i != end) { + (*i)->removeWindow(this); + ++i; + } +} + + +QFbWindowSurface::QFbWindowSurface(QFbScreen *screen, QWidget *window) + : QWindowSurface(window), + mScreen(screen) +{ + mImage = QImage(window->size(), mScreen->format()); + + platformWindow = static_cast<QFbWindow*>(window->platformWindow()); + platformWindow->surface = this; +} + +QFbWindowSurface::~QFbWindowSurface() +{ +} + +void QFbWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(offset); + + +// qDebug() << "QFbWindowSurface::flush" << region; + + + platformWindow->repaint(region); +} + + +void QFbWindow::repaint(const QRegion ®ion) +{ + QRect currentGeometry = geometry(); + + QRect dirtyClient = region.boundingRect(); + QRect dirtyRegion(currentGeometry.left() + dirtyClient.left(), + currentGeometry.top() + dirtyClient.top(), + dirtyClient.width(), + dirtyClient.height()); + QList<QFbScreen *>::const_iterator i = mScreens.constBegin(); + QList<QFbScreen *>::const_iterator end = mScreens.constEnd(); + QRect oldGeometryLocal = oldGeometry; + oldGeometry = currentGeometry; + while (i != end) { + // If this is a move, redraw the previous location + if (oldGeometryLocal != currentGeometry) { + (*i)->setDirty(oldGeometryLocal); + } + (*i)->setDirty(dirtyRegion); + ++i; + } +} + +void QFbWindowSurface::resize(const QSize &size) +{ + // change the widget's QImage if this is a resize + if (mImage.size() != size) + mImage = QImage(size, mScreen->format()); + QWindowSurface::resize(size); +} + +void QFbWindow::setGeometry(const QRect &rect) +{ +// store previous geometry for screen update + oldGeometry = geometry(); + + + QList<QFbScreen *>::const_iterator i = mScreens.constBegin(); + QList<QFbScreen *>::const_iterator end = mScreens.constEnd(); + while (i != end) { + (*i)->invalidateRectCache(); + ++i; + } +//### QWindowSystemInterface::handleGeometryChange(window(), rect); + + QPlatformWindow::setGeometry(rect); +} + +bool QFbWindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + return QWindowSurface::scroll(area, dx, dy); +} + +void QFbWindowSurface::beginPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +void QFbWindowSurface::endPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +void QFbWindow::setVisible(bool visible) +{ + visibleFlag = visible; + QList<QFbScreen *>::const_iterator i = mScreens.constBegin(); + QList<QFbScreen *>::const_iterator end = mScreens.constEnd(); + while (i != end) { + (*i)->invalidateRectCache(); + (*i)->setDirty(geometry()); + ++i; + } +} + +Qt::WindowFlags QFbWindow::setWindowFlags(Qt::WindowFlags type) +{ + flags = type; + QList<QFbScreen *>::const_iterator i = mScreens.constBegin(); + QList<QFbScreen *>::const_iterator end = mScreens.constEnd(); + while (i != end) { + (*i)->invalidateRectCache(); + ++i; + } + return flags; +} + +Qt::WindowFlags QFbWindow::windowFlags() const +{ + return flags; +} diff --git a/src/plugins/platforms/fb_base/fb_base.h b/src/plugins/platforms/fb_base/fb_base.h new file mode 100644 index 0000000..45a5663 --- /dev/null +++ b/src/plugins/platforms/fb_base/fb_base.h @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QLIGHTHOUSEGRAPHICSSCREEN_H +#define QLIGHTHOUSEGRAPHICSSCREEN_H + +#include <qrect.h> +#include <qimage.h> +#include <qtimer.h> +#include <qpainter.h> +#include <QPlatformCursor> +#include <QPlatformScreen> +#include <QPlatformWindow> +#include <QtGui/private/qwindowsurface_p.h> + +class QMouseEvent; +class QSize; +class QPainter; + +class QFbScreen; + +class QPlatformSoftwareCursor : public QPlatformCursor +{ +public: + QPlatformSoftwareCursor(QPlatformScreen * scr); + + // output methods + QRect dirtyRect(); + virtual QRect drawCursor(QPainter & painter); + + // input methods + virtual void pointerEvent(const QMouseEvent & event); + virtual void changeCursor(QCursor * widgetCursor, QWidget * widget); + + virtual void setDirty() { dirty = true; screen->setDirty(QRect()); } + virtual bool isDirty() { return dirty; } + virtual bool isOnScreen() { return onScreen; } + virtual QRect lastPainted() { return prevRect; } + +protected: + QPlatformCursorImage * graphic; + +private: + void setCursor(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY); + void setCursor(Qt::CursorShape shape); + void setCursor(const QImage &image, int hotx, int hoty); + QRect currentRect; // next place to draw the cursor + QRect prevRect; // last place the cursor was drawn + QRect getCurrentRect(); + bool dirty; + bool onScreen; +}; + +class QFbWindow; + +class QFbWindowSurface : public QWindowSurface +{ +public: + QFbWindowSurface(QFbScreen *screen, QWidget *window); + ~QFbWindowSurface(); + + virtual QPaintDevice *paintDevice() { return &mImage; } + virtual void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + virtual bool scroll(const QRegion &area, int dx, int dy); + + virtual void beginPaint(const QRegion ®ion); + virtual void endPaint(const QRegion ®ion); + + + const QImage image() { return mImage; } + void resize(const QSize &size); + +protected: + friend class QFbWindow; + QFbWindow *platformWindow; + + QFbScreen *mScreen; + QImage mImage; +}; + + +class QFbWindow : public QPlatformWindow +{ +public: + + QFbWindow(QWidget *window); + ~QFbWindow(); + + + virtual void setVisible(bool visible); + virtual bool visible() { return visibleFlag; } + + virtual void raise(); + virtual void lower(); + + void setGeometry(const QRect &rect); + + virtual Qt::WindowFlags setWindowFlags(Qt::WindowFlags type); + virtual Qt::WindowFlags windowFlags() const; + + WId winId() const { return windowId; } + + virtual void repaint(const QRegion&); + +protected: + friend class QFbWindowSurface; + friend class QFbScreen; + QFbWindowSurface *surface; + QList<QFbScreen *> mScreens; + QRect oldGeometry; + bool visibleFlag; + Qt::WindowFlags flags; + + WId windowId; +}; + +class QFbScreen : public QPlatformScreen +{ + Q_OBJECT +public: + QFbScreen(); + ~QFbScreen(); + + virtual QRect geometry() const { return mGeometry; } + virtual int depth() const { return mDepth; } + virtual QImage::Format format() const { return mFormat; } + virtual QSize physicalSize() const { return mPhysicalSize; } + + virtual void setGeometry(QRect rect); + virtual void setDepth(int depth); + virtual void setFormat(QImage::Format format); + virtual void setPhysicalSize(QSize size); + + virtual void setDirty(const QRect &rect); + + virtual void removeWindow(QFbWindow * surface); + virtual void addWindow(QFbWindow * surface); + virtual void raise(QPlatformWindow * surface); + virtual void lower(QPlatformWindow * surface); + virtual QWidget * topLevelAt(const QPoint & p) const; + + QImage * image() const { return mScreenImage; } + QPaintDevice * paintDevice() const { return mScreenImage; } + +protected: + QList<QFbWindow *> windowStack; + QRegion repaintRegion; + QPlatformSoftwareCursor * cursor; + QTimer redrawTimer; + +protected slots: + virtual QRegion doRedraw(); + +protected: + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + QSize mPhysicalSize; + QImage *mScreenImage; + +private: + QPainter * compositePainter; + void generateRects(); + QList<QPair<QRect, int> > cachedRects; + + void invalidateRectCache() { isUpToDate = false; } + friend class QFbWindowSurface; + friend class QFbWindow; + bool isUpToDate; +}; + +#endif // QLIGHTHOUSEGRAPHICSSCREEN_H diff --git a/src/plugins/platforms/fb_base/fb_base.pri b/src/plugins/platforms/fb_base/fb_base.pri new file mode 100644 index 0000000..41bd87f --- /dev/null +++ b/src/plugins/platforms/fb_base/fb_base.pri @@ -0,0 +1,2 @@ +SOURCES += ../fb_base/fb_base.cpp +HEADERS += ../fb_base/fb_base.h diff --git a/src/plugins/platforms/fb_base/fb_base.pro b/src/plugins/platforms/fb_base/fb_base.pro new file mode 100644 index 0000000..e08c0c5 --- /dev/null +++ b/src/plugins/platforms/fb_base/fb_base.pro @@ -0,0 +1,23 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2009-11-05T13:22:31 +# +#------------------------------------------------- + +#QT -= core gui +TARGET = fb_base +#include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems + +TEMPLATE = lib + +#DEFINES += STATIC_LIBRARY +CONFIG += staticlib + +SOURCES += fb_base.cpp + +HEADERS += fb_base.h + +target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems +INSTALLS += target diff --git a/src/plugins/platforms/fontdatabases/basicunix/basicunix.pri b/src/plugins/platforms/fontdatabases/basicunix/basicunix.pri new file mode 100644 index 0000000..21aedba --- /dev/null +++ b/src/plugins/platforms/fontdatabases/basicunix/basicunix.pri @@ -0,0 +1,82 @@ +DEFINES += QT_NO_FONTCONFIG +HEADERS += \ + $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.h \ + $$QT_SOURCE_TREE/src/gui/text/qfontengine_ft_p.h + +SOURCES += \ + $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.cpp \ + $$QT_SOURCE_TREE/src/gui/text/qfontengine_ft.cpp + +INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/harfbuzz/src + +INCLUDEPATH += $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/basicunix + +CONFIG += opentype + +contains(QT_CONFIG, freetype) { + SOURCES += \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftbase.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftbbox.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftdebug.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftglyph.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftinit.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftmm.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/fttype1.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftsynth.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftbitmap.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/bdf/bdf.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/cache/ftcache.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/cff/cff.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/cid/type1cid.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/gzip/ftgzip.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/pcf/pcf.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/pfr/pfr.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/psaux/psaux.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/pshinter/pshinter.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/psnames/psmodule.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/raster/raster.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/sfnt/sfnt.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/smooth/smooth.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/truetype/truetype.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/type1/type1.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/type42/type42.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/winfonts/winfnt.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/lzw/ftlzw.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvalid.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvbase.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvgdef.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvjstf.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvcommn.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvgpos.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvgsub.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvmod.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afangles.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afglobal.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/aflatin.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afmodule.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afdummy.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afhints.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afloader.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/autofit.c + + symbian { + SOURCES += \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftsystem.c + } else { + SOURCES += \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/builds/unix/ftsystem.c + INCLUDEPATH += \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/builds/unix + } + + INCLUDEPATH += \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/include + + DEFINES += FT2_BUILD_LIBRARY FT_CONFIG_OPTION_SYSTEM_ZLIB + } else:contains(QT_CONFIG, system-freetype) { + # pull in the proper freetype2 include directory + include($$QT_SOURCE_TREE/config.tests/unix/freetype/freetype.pri) + LIBS_PRIVATE += -lfreetype + } + diff --git a/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.cpp b/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.cpp new file mode 100644 index 0000000..4634477 --- /dev/null +++ b/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.cpp @@ -0,0 +1,326 @@ +/**************************************************************************** +** +** 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 plugins 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 "qbasicunixfontdatabase.h" + +#include <QtGui/private/qapplication_p.h> +#include <QtGui/QPlatformScreen> + +#include <QtCore/QFile> +#include <QtCore/QLibraryInfo> +#include <QtCore/QDir> + +#undef QT_NO_FREETYPE +#include <QtGui/private/qfontengine_ft_p.h> +#include <QtGui/private/qfontengine_p.h> + +#include <ft2build.h> +#include FT_TRUETYPE_TABLES_H + +#define SimplifiedChineseCsbBit 18 +#define TraditionalChineseCsbBit 20 +#define JapaneseCsbBit 17 +#define KoreanCsbBit 21 + +static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = { + // Any, + { 127, 127 }, + // Latin, + { 0, 127 }, + // Greek, + { 7, 127 }, + // Cyrillic, + { 9, 127 }, + // Armenian, + { 10, 127 }, + // Hebrew, + { 11, 127 }, + // Arabic, + { 13, 127 }, + // Syriac, + { 71, 127 }, + //Thaana, + { 72, 127 }, + //Devanagari, + { 15, 127 }, + //Bengali, + { 16, 127 }, + //Gurmukhi, + { 17, 127 }, + //Gujarati, + { 18, 127 }, + //Oriya, + { 19, 127 }, + //Tamil, + { 20, 127 }, + //Telugu, + { 21, 127 }, + //Kannada, + { 22, 127 }, + //Malayalam, + { 23, 127 }, + //Sinhala, + { 73, 127 }, + //Thai, + { 24, 127 }, + //Lao, + { 25, 127 }, + //Tibetan, + { 70, 127 }, + //Myanmar, + { 74, 127 }, + // Georgian, + { 26, 127 }, + // Khmer, + { 80, 127 }, + // SimplifiedChinese, + { 126, 127 }, + // TraditionalChinese, + { 126, 127 }, + // Japanese, + { 126, 127 }, + // Korean, + { 56, 127 }, + // Vietnamese, + { 0, 127 }, // same as latin1 + // Other, + { 126, 127 }, + // Ogham, + { 78, 127 }, + // Runic, + { 79, 127 }, + // Nko, + { 14, 127 }, +}; + +static QSupportedWritingSystems determineWritingSystemsFromTrueTypeBits(quint32 unicodeRange[4], quint32 codePageRange[2]) +{ + QSupportedWritingSystems writingSystems; + bool hasScript = false; + + int i; + for(i = 0; i < QFontDatabase::WritingSystemsCount; i++) { + int bit = requiredUnicodeBits[i][0]; + int index = bit/32; + int flag = 1 << (bit&31); + if (bit != 126 && unicodeRange[index] & flag) { + bit = requiredUnicodeBits[i][1]; + index = bit/32; + + flag = 1 << (bit&31); + if (bit == 127 || unicodeRange[index] & flag) { + writingSystems.setSupported(QFontDatabase::WritingSystem(i)); + hasScript = true; + // qDebug("font %s: index=%d, flag=%8x supports script %d", familyName.latin1(), index, flag, i); + } + } + } + if(codePageRange[0] & (1 << SimplifiedChineseCsbBit)) { + writingSystems.setSupported(QFontDatabase::SimplifiedChinese); + hasScript = true; + //qDebug("font %s supports Simplified Chinese", familyName.latin1()); + } + if(codePageRange[0] & (1 << TraditionalChineseCsbBit)) { + writingSystems.setSupported(QFontDatabase::TraditionalChinese); + hasScript = true; + //qDebug("font %s supports Traditional Chinese", familyName.latin1()); + } + if(codePageRange[0] & (1 << JapaneseCsbBit)) { + writingSystems.setSupported(QFontDatabase::Japanese); + hasScript = true; + //qDebug("font %s supports Japanese", familyName.latin1()); + } + if(codePageRange[0] & (1 << KoreanCsbBit)) { + writingSystems.setSupported(QFontDatabase::Korean); + hasScript = true; + //qDebug("font %s supports Korean", familyName.latin1()); + } + if (!hasScript) + writingSystems.setSupported(QFontDatabase::Symbol); + + return writingSystems; +} + +static inline bool scriptRequiresOpenType(int script) +{ + return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala) + || script == QUnicodeTables::Khmer || script == QUnicodeTables::Nko); +} + +void QBasicUnixFontDatabase::populateFontDatabase() +{ + QPlatformFontDatabase::populateFontDatabase(); + QString fontpath = fontDir(); + + if(!QFile::exists(fontpath)) { + qFatal("QFontDatabase: Cannot find font directory %s - is Qt installed correctly?", + qPrintable(fontpath)); + } + + QDir dir(fontpath); + dir.setNameFilters(QStringList() << QLatin1String("*.ttf") + << QLatin1String("*.ttc") << QLatin1String("*.pfa") + << QLatin1String("*.pfb")); + dir.refresh(); + for (int i = 0; i < int(dir.count()); ++i) { + const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i])); +// qDebug() << "looking at" << file; + addTTFile(QByteArray(), file); + } +} + +QFontEngine *QBasicUnixFontDatabase::fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *usrPtr) +{ + QFontEngineFT *engine; + FontFile *fontfile = static_cast<FontFile *> (usrPtr); + QFontEngine::FaceId fid; + fid.filename = fontfile->fileName.toLocal8Bit(); + fid.index = fontfile->indexValue; + engine = new QFontEngineFT(fontDef); + + bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); + QFontEngineFT::GlyphFormat format = antialias? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; + if (!engine->init(fid,antialias,format)) { + delete engine; + engine = 0; + return engine; + } + if (engine->invalid()) { + delete engine; + engine = 0; + } else if (scriptRequiresOpenType(script)) { + HB_Face hbFace = engine->harfbuzzFace(); + if (!hbFace || !hbFace->supported_scripts[script]) { + delete engine; + engine = 0; + } + } + + return engine; +} + +QStringList QBasicUnixFontDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const +{ + Q_UNUSED(family); + Q_UNUSED(style); + Q_UNUSED(script); + return QStringList(); +} + +QStringList QBasicUnixFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) +{ + return addTTFile(fontData,fileName.toLocal8Bit()); +} + +void QBasicUnixFontDatabase::releaseHandle(void *handle) +{ + FontFile *file = static_cast<FontFile *>(handle); + delete file; +} + +QStringList QBasicUnixFontDatabase::addTTFile(const QByteArray &fontData, const QByteArray &file) +{ + extern FT_Library qt_getFreetype(); + FT_Library library = qt_getFreetype(); + + int index = 0; + int numFaces = 0; + QStringList families; + do { + FT_Face face; + FT_Error error; + if (!fontData.isEmpty()) { + error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face); + } else { + error = FT_New_Face(library, file.constData(), index, &face); + } + if (error != FT_Err_Ok) { + qDebug() << "FT_New_Face failed with index" << index << ":" << hex << error; + break; + } + numFaces = face->num_faces; + + int weight = QFont::Normal; + + QFont::Style style = QFont::StyleNormal; + if (face->style_flags & FT_STYLE_FLAG_ITALIC) + style = QFont::StyleItalic; + + if (face->style_flags & FT_STYLE_FLAG_BOLD) + weight = QFont::Bold; + + QSupportedWritingSystems writingSystems; + // detect symbol fonts + for (int i = 0; i < face->num_charmaps; ++i) { + FT_CharMap cm = face->charmaps[i]; + if (cm->encoding == ft_encoding_adobe_custom + || cm->encoding == ft_encoding_symbol) { + writingSystems.setSupported(QFontDatabase::Symbol); + break; + } + } + + TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2); + if (os2) { + quint32 unicodeRange[4] = { + os2->ulUnicodeRange1, os2->ulUnicodeRange2, os2->ulUnicodeRange3, os2->ulUnicodeRange4 + }; + quint32 codePageRange[2] = { + os2->ulCodePageRange1, os2->ulCodePageRange2 + }; + + writingSystems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange); + } + + QString family = QString::fromAscii(face->family_name); + FontFile *fontFile = new FontFile; + fontFile->fileName = file; + fontFile->indexValue = index; + + registerFont(family,"",weight,style,100,true,true,0,writingSystems,fontFile); + + families.append(family); + + FT_Done_Face(face); + ++index; + } while (index < numFaces); + return families; +} diff --git a/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.h b/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.h new file mode 100644 index 0000000..0af118d --- /dev/null +++ b/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QBASICUNIXFONTDATABASE_H +#define QBASICUNIXFONTDATABASE_H + +#include <QPlatformFontDatabase> +#include <QtCore/QByteArray> +#include <QtCore/QString> + +struct FontFile +{ + QString fileName; + int indexValue; +}; + +class QBasicUnixFontDatabase : public QPlatformFontDatabase +{ +public: + void populateFontDatabase(); + QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle); + QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const; + QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); + void releaseHandle(void *handle); + + static QStringList addTTFile(const QByteArray &fontData, const QByteArray &file); +}; + +#endif // QBASICUNIXFONTDATABASE_H diff --git a/src/plugins/platforms/fontdatabases/fontconfig/fontconfig.pri b/src/plugins/platforms/fontdatabases/fontconfig/fontconfig.pri new file mode 100644 index 0000000..19c74ed --- /dev/null +++ b/src/plugins/platforms/fontdatabases/fontconfig/fontconfig.pri @@ -0,0 +1,12 @@ +include(../basicunix/basicunix.pri) + +HEADERS += \ + $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h + +SOURCES += \ + $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp + +INCLUDEPATH += $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/fontconfig +LIBS_PRIVATE += -lfontconfig + + diff --git a/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp new file mode 100644 index 0000000..c9d1b74 --- /dev/null +++ b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -0,0 +1,572 @@ +/**************************************************************************** +** +** 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 plugins 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 "qfontconfigdatabase.h" + +#include <QtCore/QList> +#include <QtGui/private/qfont_p.h> + +#include <QtCore/QElapsedTimer> + +#include <QtGui/private/qapplication_p.h> +#include <QtGui/QPlatformScreen> + +#include <QtGui/private/qfontengine_ft_p.h> +#include <QtGui/private/qfontengine_p.h> + + + +#include <ft2build.h> +#include FT_TRUETYPE_TABLES_H + +#include <fontconfig/fontconfig.h> + +#define SimplifiedChineseCsbBit 18 +#define TraditionalChineseCsbBit 20 +#define JapaneseCsbBit 17 +#define KoreanCsbBit 21 + +static inline bool requiresOpenType(int writingSystem) +{ + return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala) + || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko); +} +static inline bool scriptRequiresOpenType(int script) +{ + return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala) + || script == QUnicodeTables::Khmer || script == QUnicodeTables::Nko); +} + +static int getFCWeight(int fc_weight) +{ + int qtweight = QFont::Black; + if (fc_weight <= (FC_WEIGHT_LIGHT + FC_WEIGHT_MEDIUM) / 2) + qtweight = QFont::Light; + else if (fc_weight <= (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2) + qtweight = QFont::Normal; + else if (fc_weight <= (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2) + qtweight = QFont::DemiBold; + else if (fc_weight <= (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2) + qtweight = QFont::Bold; + + return qtweight; +} + +static const char *specialLanguages[] = { + "en", // Common + "el", // Greek + "ru", // Cyrillic + "hy", // Armenian + "he", // Hebrew + "ar", // Arabic + "syr", // Syriac + "div", // Thaana + "hi", // Devanagari + "bn", // Bengali + "pa", // Gurmukhi + "gu", // Gujarati + "or", // Oriya + "ta", // Tamil + "te", // Telugu + "kn", // Kannada + "ml", // Malayalam + "si", // Sinhala + "th", // Thai + "lo", // Lao + "bo", // Tibetan + "my", // Myanmar + "ka", // Georgian + "ko", // Hangul + "", // Ogham + "", // Runic + "km", // Khmer + "" // N'Ko +}; +enum { SpecialLanguageCount = sizeof(specialLanguages) / sizeof(const char *) }; + +static const ushort specialChars[] = { + 0, // English + 0, // Greek + 0, // Cyrillic + 0, // Armenian + 0, // Hebrew + 0, // Arabic + 0, // Syriac + 0, // Thaana + 0, // Devanagari + 0, // Bengali + 0, // Gurmukhi + 0, // Gujarati + 0, // Oriya + 0, // Tamil + 0xc15, // Telugu + 0xc95, // Kannada + 0xd15, // Malayalam + 0xd9a, // Sinhala + 0, // Thai + 0, // Lao + 0, // Tibetan + 0x1000, // Myanmar + 0, // Georgian + 0, // Hangul + 0x1681, // Ogham + 0x16a0, // Runic + 0, // Khmer + 0x7ca // N'Ko +}; +enum { SpecialCharCount = sizeof(specialChars) / sizeof(ushort) }; + +// this could become a list of all languages used for each writing +// system, instead of using the single most common language. +static const char *languageForWritingSystem[] = { + 0, // Any + "en", // Latin + "el", // Greek + "ru", // Cyrillic + "hy", // Armenian + "he", // Hebrew + "ar", // Arabic + "syr", // Syriac + "div", // Thaana + "hi", // Devanagari + "bn", // Bengali + "pa", // Gurmukhi + "gu", // Gujarati + "or", // Oriya + "ta", // Tamil + "te", // Telugu + "kn", // Kannada + "ml", // Malayalam + "si", // Sinhala + "th", // Thai + "lo", // Lao + "bo", // Tibetan + "my", // Myanmar + "ka", // Georgian + "km", // Khmer + "zh-cn", // SimplifiedChinese + "zh-tw", // TraditionalChinese + "ja", // Japanese + "ko", // Korean + "vi", // Vietnamese + 0, // Symbol + 0, // Ogham + 0, // Runic + 0 // N'Ko +}; +enum { LanguageCount = sizeof(languageForWritingSystem) / sizeof(const char *) }; + +// Unfortunately FontConfig doesn't know about some languages. We have to test these through the +// charset. The lists below contain the systems where we need to do this. +static const ushort sampleCharForWritingSystem[] = { + 0, // Any + 0, // Latin + 0, // Greek + 0, // Cyrillic + 0, // Armenian + 0, // Hebrew + 0, // Arabic + 0, // Syriac + 0, // Thaana + 0, // Devanagari + 0, // Bengali + 0, // Gurmukhi + 0, // Gujarati + 0, // Oriya + 0, // Tamil + 0xc15, // Telugu + 0xc95, // Kannada + 0xd15, // Malayalam + 0xd9a, // Sinhala + 0, // Thai + 0, // Lao + 0, // Tibetan + 0x1000, // Myanmar + 0, // Georgian + 0, // Khmer + 0, // SimplifiedChinese + 0, // TraditionalChinese + 0, // Japanese + 0, // Korean + 0, // Vietnamese + 0, // Symbol + 0x1681, // Ogham + 0x16a0, // Runic + 0x7ca // N'Ko +}; +enum { SampleCharCount = sizeof(sampleCharForWritingSystem) / sizeof(ushort) }; + +// Newer FontConfig let's us sort out fonts that contain certain glyphs, but no +// open type tables for is directly. Do this so we don't pick some strange +// pseudo unicode font +static const char *openType[] = { + 0, // Any + 0, // Latin + 0, // Greek + 0, // Cyrillic + 0, // Armenian + 0, // Hebrew + 0, // Arabic + "syrc", // Syriac + "thaa", // Thaana + "deva", // Devanagari + "beng", // Bengali + "guru", // Gurmukhi + "gurj", // Gujarati + "orya", // Oriya + "taml", // Tamil + "telu", // Telugu + "knda", // Kannada + "mlym", // Malayalam + "sinh", // Sinhala + 0, // Thai + 0, // Lao + "tibt", // Tibetan + "mymr", // Myanmar + 0, // Georgian + "khmr", // Khmer + 0, // SimplifiedChinese + 0, // TraditionalChinese + 0, // Japanese + 0, // Korean + 0, // Vietnamese + 0, // Symbol + 0, // Ogham + 0, // Runic + "nko " // N'Ko +}; + +void QFontconfigDatabase::populateFontDatabase() +{ + FcFontSet *fonts; + + QString familyName; + FcChar8 *value = 0; + int weight_value; + int slant_value; + int spacing_value; + FcChar8 *file_value; + int indexValue; + FcChar8 *foundry_value; + FcBool scalable; + FcBool antialias; + + { + FcObjectSet *os = FcObjectSetCreate(); + FcPattern *pattern = FcPatternCreate(); + const char *properties [] = { + FC_FAMILY, FC_WEIGHT, FC_SLANT, + FC_SPACING, FC_FILE, FC_INDEX, + FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, FC_WEIGHT, + FC_WIDTH, +#if FC_VERSION >= 20297 + FC_CAPABILITY, +#endif + (const char *)0 + }; + const char **p = properties; + while (*p) { + FcObjectSetAdd(os, *p); + ++p; + } + fonts = FcFontList(0, pattern, os); + FcObjectSetDestroy(os); + FcPatternDestroy(pattern); + } + + for (int i = 0; i < fonts->nfont; i++) { + if (FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) + continue; + // capitalize(value); + familyName = QString::fromUtf8((const char *)value); + slant_value = FC_SLANT_ROMAN; + weight_value = FC_WEIGHT_MEDIUM; + spacing_value = FC_PROPORTIONAL; + file_value = 0; + indexValue = 0; + scalable = FcTrue; + + + if (FcPatternGetInteger (fonts->fonts[i], FC_SLANT, 0, &slant_value) != FcResultMatch) + slant_value = FC_SLANT_ROMAN; + if (FcPatternGetInteger (fonts->fonts[i], FC_WEIGHT, 0, &weight_value) != FcResultMatch) + weight_value = FC_WEIGHT_MEDIUM; + if (FcPatternGetInteger (fonts->fonts[i], FC_SPACING, 0, &spacing_value) != FcResultMatch) + spacing_value = FC_PROPORTIONAL; + if (FcPatternGetString (fonts->fonts[i], FC_FILE, 0, &file_value) != FcResultMatch) + file_value = 0; + if (FcPatternGetInteger (fonts->fonts[i], FC_INDEX, 0, &indexValue) != FcResultMatch) + indexValue = 0; + if (FcPatternGetBool(fonts->fonts[i], FC_SCALABLE, 0, &scalable) != FcResultMatch) + scalable = FcTrue; + if (FcPatternGetString(fonts->fonts[i], FC_FOUNDRY, 0, &foundry_value) != FcResultMatch) + foundry_value = 0; + if(FcPatternGetBool(fonts->fonts[i],FC_ANTIALIAS,0,&antialias) != FcResultMatch) + antialias = true; + + QSupportedWritingSystems writingSystems; + FcLangSet *langset = 0; + FcResult res = FcPatternGetLangSet(fonts->fonts[i], FC_LANG, 0, &langset); + if (res == FcResultMatch) { + for (int i = 1; i < LanguageCount; ++i) { + const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[i]; + if (lang) { + FcLangResult langRes = FcLangSetHasLang(langset, lang); + if (langRes != FcLangDifferentLang) + writingSystems.setSupported(QFontDatabase::WritingSystem(i)); + } + } + } else { + // we set Other to supported for symbol fonts. It makes no + // sense to merge these with other ones, as they are + // special in a way. + writingSystems.setSupported(QFontDatabase::Other); + } + + FcCharSet *cs = 0; + res = FcPatternGetCharSet(fonts->fonts[i], FC_CHARSET, 0, &cs); + if (res == FcResultMatch) { + // some languages are not supported by FontConfig, we rather check the + // charset to detect these + for (int i = 1; i < SampleCharCount; ++i) { + if (!sampleCharForWritingSystem[i]) + continue; + if (FcCharSetHasChar(cs, sampleCharForWritingSystem[i])) + writingSystems.setSupported(QFontDatabase::WritingSystem(i)); + } + } + +#if FC_VERSION >= 20297 + for (int j = 1; j < LanguageCount; ++j) { + if (writingSystems.supported(QFontDatabase::WritingSystem(j)) + && requiresOpenType(j) && openType[j]) { + FcChar8 *cap; + res = FcPatternGetString (fonts->fonts[i], FC_CAPABILITY, 0, &cap); + if (res != FcResultMatch || !strstr((const char *)cap, openType[j])) + writingSystems.setSupported(QFontDatabase::WritingSystem(j),false); + } + } +#endif + + FontFile *fontFile = new FontFile; + fontFile->fileName = QLatin1String((const char *)file_value); + fontFile->indexValue = indexValue; + + QFont::Style style = (slant_value == FC_SLANT_ITALIC) + ? QFont::StyleItalic + : ((slant_value == FC_SLANT_OBLIQUE) + ? QFont::StyleOblique + : QFont::StyleNormal); + int weight = getFCWeight(weight_value); + + double pixel_size = 0; + if (!scalable) { + int width = 100; + FcPatternGetInteger (fonts->fonts[i], FC_WIDTH, 0, &width); + FcPatternGetDouble (fonts->fonts[i], FC_PIXEL_SIZE, 0, &pixel_size); + } + + QPlatformFontDatabase::registerFont(familyName,QLatin1String((const char *)foundry_value),weight,style,100,antialias,scalable,pixel_size,writingSystems,fontFile); +// qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size; + } + + FcFontSetDestroy (fonts); + + struct FcDefaultFont { + const char *qtname; + const char *rawname; + bool fixed; + }; + const FcDefaultFont defaults[] = { + { "Serif", "serif", false }, + { "Sans Serif", "sans-serif", false }, + { "Monospace", "monospace", true }, + { 0, 0, false } + }; + const FcDefaultFont *f = defaults; + // aliases only make sense for 'common', not for any of the specials + QSupportedWritingSystems ws; + ws.setSupported(QFontDatabase::Latin); + + while (f->qtname) { + registerFont(f->qtname,"",50,QFont::StyleNormal,100,true,true,0,ws,0); + registerFont(f->qtname,"",50,QFont::StyleItalic,100,true,true,0,ws,0); + registerFont(f->qtname,"",50,QFont::StyleOblique,100,true,true,0,ws,0); + ++f; + } + + //Lighthouse has very lazy population of the font db. We want it to be initialized when + //QApplication is constructed, so that the population procedure can do something like this to + //set the default font +// const FcDefaultFont *s = defaults; +// QFont font("Sans Serif"); +// font.setPointSize(9); +// QApplication::setFont(font); +} + +QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables::Script script, void *usrPtr) +{ + QFontDef fontDef = f; + + QFontEngineFT *engine; + FontFile *fontfile = static_cast<FontFile *> (usrPtr); + QFontEngine::FaceId fid; + fid.filename = fontfile->fileName.toLocal8Bit(); + fid.index = fontfile->indexValue; + + //try and get the pattern + FcPattern *pattern = FcPatternCreate(); + + bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); + QFontEngineFT::GlyphFormat format = antialias? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; + + engine = new QFontEngineFT(fontDef); + + FcValue value; + value.type = FcTypeString; + QByteArray cs = fontDef.family.toUtf8(); + value.u.s = (const FcChar8 *)cs.data(); + FcPatternAdd(pattern,FC_FAMILY,value,true); + + + value.u.s = (const FcChar8 *)fid.filename.data(); + FcPatternAdd(pattern,FC_FILE,value,true); + + value.type = FcTypeInteger; + value.u.i = fid.index; + FcPatternAdd(pattern,FC_INDEX,value,true); + + QFontEngineFT::HintStyle default_hint_style; + + if (FcConfigSubstitute(0,pattern,FcMatchPattern)) { + + //hinting + int hint_style = 0; + if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch) + hint_style = QFontEngineFT::HintFull; + switch (hint_style) { + case FC_HINT_NONE: + default_hint_style = QFontEngineFT::HintNone; + break; + case FC_HINT_SLIGHT: + default_hint_style = QFontEngineFT::HintLight; + break; + case FC_HINT_MEDIUM: + default_hint_style = QFontEngineFT::HintMedium; + break; + default: + default_hint_style = QFontEngineFT::HintFull; + break; + } + } + + engine->setDefaultHintStyle(default_hint_style); + if (!engine->init(fid,antialias,format)) { + delete engine; + engine = 0; + return engine; + } + if (engine->invalid()) { + delete engine; + engine = 0; + } else if (scriptRequiresOpenType(script)) { + HB_Face hbFace = engine->harfbuzzFace(); + if (!hbFace || !hbFace->supported_scripts[script]) { + delete engine; + engine = 0; + } + } + + return engine; +} + +QStringList QFontconfigDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const +{ + QStringList fallbackFamilies; + FcPattern *pattern = FcPatternCreate(); + if (!pattern) + return fallbackFamilies; + + FcValue value; + value.type = FcTypeString; + QByteArray cs = family.toUtf8(); + value.u.s = (const FcChar8 *)cs.data(); + FcPatternAdd(pattern,FC_FAMILY,value,true); + + int slant_value = FC_SLANT_ROMAN; + if (style == QFont::StyleItalic) + slant_value = FC_SLANT_ITALIC; + else if (style == QFont::StyleOblique) + slant_value = FC_SLANT_OBLIQUE; + FcPatternAddInteger(pattern, FC_SLANT, slant_value); + + if (script != QUnicodeTables::Common && *specialLanguages[script] != '\0') { + Q_ASSERT(script < QUnicodeTables::ScriptCount); + FcLangSet *ls = FcLangSetCreate(); + FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]); + FcPatternAddLangSet(pattern, FC_LANG, ls); + FcLangSetDestroy(ls); + } + + FcConfigSubstitute(0, pattern, FcMatchPattern); + FcConfigSubstitute(0, pattern, FcMatchFont); + + FcResult result = FcResultMatch; + FcFontSet *fontSet = FcFontSort(0,pattern,FcFalse,0,&result); + + if (fontSet && result == FcResultMatch) + { + for (int i = 0; i < fontSet->nfont; i++) { + FcChar8 *value = 0; + if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) + continue; + // capitalize(value); + QString familyName = QString::fromUtf8((const char *)value); + if (!fallbackFamilies.contains(familyName,Qt::CaseInsensitive)) { + fallbackFamilies << familyName; + } + + } + } +// qDebug() << "fallbackFamilies for:" << family << fallbackFamilies; + + return fallbackFamilies; +} diff --git a/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h new file mode 100644 index 0000000..33382dc --- /dev/null +++ b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QFONTCONFIGDATABASE_H +#define QFONTCONFIGDATABASE_H + +#include <QPlatformFontDatabase> +#include "qbasicunixfontdatabase.h" + +class QFontconfigDatabase : public QBasicUnixFontDatabase +{ +public: + void populateFontDatabase(); + QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle); + QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const; +}; + +#endif // QFONTCONFIGDATABASE_H diff --git a/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri b/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri new file mode 100644 index 0000000..dbcfbce --- /dev/null +++ b/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri @@ -0,0 +1,10 @@ +contains(QT_CONFIG, fontconfig) { + include(../fontconfig/fontconfig.pri) + DEFINES += Q_FONTCONFIGDATABASE +} else { + include(../basicunix/basicunix.pri) +} + +INCLUDEPATH += $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/genericunix +HEADERS += \ + $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/genericunix/qgenericunixfontdatabase.h diff --git a/src/plugins/platforms/fontdatabases/genericunix/qgenericunixfontdatabase.h b/src/plugins/platforms/fontdatabases/genericunix/qgenericunixfontdatabase.h new file mode 100644 index 0000000..327c8f5 --- /dev/null +++ b/src/plugins/platforms/fontdatabases/genericunix/qgenericunixfontdatabase.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QGENERICUNIXFONTDATABASE_H +#define QGENERICUNIXFONTDATABASE_H + +#ifdef Q_FONTCONFIGDATABASE +#include "qfontconfigdatabase.h" +typedef QFontconfigDatabase QGenericUnixFontDatabase; +#else +#include "qbasicunixfontdatabase.h" +typedef QBasicUnixFontDatabase QGenericUnixFontDatabase; +#endif //Q_FONTCONFIGDATABASE + +#endif // QGENERICUNIXFONTDATABASE_H diff --git a/src/plugins/platforms/linuxfb/linuxfb.pro b/src/plugins/platforms/linuxfb/linuxfb.pro new file mode 100644 index 0000000..216b899 --- /dev/null +++ b/src/plugins/platforms/linuxfb/linuxfb.pro @@ -0,0 +1,13 @@ +TARGET = qlinuxfbgraphicssystem +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +SOURCES = main.cpp qlinuxfbintegration.cpp +HEADERS = qlinuxfbintegration.h + +include(../fb_base/fb_base.pri) +include(../fontdatabases/genericunix/genericunix.pri) + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target diff --git a/src/plugins/platforms/linuxfb/main.cpp b/src/plugins/platforms/linuxfb/main.cpp new file mode 100644 index 0000000..c5f7fe0 --- /dev/null +++ b/src/plugins/platforms/linuxfb/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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 plugins 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 <QPlatformIntegrationPlugin> +#include "qlinuxfbintegration.h" + +QT_BEGIN_NAMESPACE + +class QLinuxFbIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QLinuxFbIntegrationPlugin::keys() const +{ + QStringList list; + list << "LinuxFb"; + return list; +} + +QPlatformIntegration* QLinuxFbIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "linuxfb") + return new QLinuxFbIntegration; + + return 0; +} + +Q_EXPORT_PLUGIN2(linuxfb, QLinuxFbIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp new file mode 100644 index 0000000..aa1d401 --- /dev/null +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp @@ -0,0 +1,866 @@ +/**************************************************************************** +** +** 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 plugins 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 "qlinuxfbintegration.h" +#include "../fb_base/fb_base.h" +#include "qgenericunixfontdatabase.h" +#include <QtGui/private/qpixmap_raster_p.h> +#include <private/qcore_unix_p.h> // overrides QT_OPEN +#include <qimage.h> +#include <qdebug.h> + +#include <unistd.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <sys/kd.h> +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <limits.h> +#include <signal.h> + +#if !defined(Q_OS_DARWIN) && !defined(Q_OS_FREEBSD) +#include <linux/fb.h> + +#ifdef __i386__ +#include <asm/mtrr.h> +#endif +#endif + +QT_BEGIN_NAMESPACE + +class QLinuxFbIntegrationPrivate +{ +public: + QLinuxFbIntegrationPrivate(); + ~QLinuxFbIntegrationPrivate(); + + void openTty(); + void closeTty(); + + int fd; + int startupw; + int startuph; + int startupd; + bool blank; + + bool doGraphicsMode; +#ifdef QT_QWS_DEPTH_GENERIC + bool doGenericColors; +#endif + int ttyfd; + long oldKdMode; + QString ttyDevice; + QString displaySpec; +}; + +QLinuxFbIntegrationPrivate::QLinuxFbIntegrationPrivate() + : fd(-1), blank(true), doGraphicsMode(true), +#ifdef QT_QWS_DEPTH_GENERIC + doGenericColors(false), +#endif + ttyfd(-1), oldKdMode(KD_TEXT) +{ +} + +QLinuxFbIntegrationPrivate::~QLinuxFbIntegrationPrivate() +{ + closeTty(); +} + +void QLinuxFbIntegrationPrivate::openTty() +{ + const char *const devs[] = {"/dev/tty0", "/dev/tty", "/dev/console", 0}; + + if (ttyDevice.isEmpty()) { + for (const char * const *dev = devs; *dev; ++dev) { + ttyfd = QT_OPEN(*dev, O_RDWR); + if (ttyfd != -1) + break; + } + } else { + ttyfd = QT_OPEN(ttyDevice.toAscii().constData(), O_RDWR); + } + + if (ttyfd == -1) + return; + + if (doGraphicsMode) { + ioctl(ttyfd, KDGETMODE, &oldKdMode); + if (oldKdMode != KD_GRAPHICS) { + int ret = ioctl(ttyfd, KDSETMODE, KD_GRAPHICS); + if (ret == -1) + doGraphicsMode = false; + } + } + + // No blankin' screen, no blinkin' cursor!, no cursor! + const char termctl[] = "\033[9;0]\033[?33l\033[?25l\033[?1c"; + QT_WRITE(ttyfd, termctl, sizeof(termctl)); +} + +void QLinuxFbIntegrationPrivate::closeTty() +{ + if (ttyfd == -1) + return; + + if (doGraphicsMode) + ioctl(ttyfd, KDSETMODE, oldKdMode); + + // Blankin' screen, blinkin' cursor! + const char termctl[] = "\033[9;15]\033[?33h\033[?25h\033[?0c"; + QT_WRITE(ttyfd, termctl, sizeof(termctl)); + + QT_CLOSE(ttyfd); + ttyfd = -1; +} + +QLinuxFbIntegration::QLinuxFbIntegration() + :fontDb(new QGenericUnixFontDatabase()) +{ + d_ptr = new QLinuxFbIntegrationPrivate(); + + // XXX + QString displaySpec = QString::fromLatin1(qgetenv("QWS_DISPLAY")); + + if (!connect(displaySpec)) + qFatal("QLinuxFbIntegration: could not initialize screen"); + initDevice(); + + // Create a QImage directly on the screen's framebuffer. + // This is the blit target for copying windows to the screen. + mPrimaryScreen = new QLinuxFbScreen(data, w, h, lstep, + screenFormat); + mPrimaryScreen->setPhysicalSize(QSize(physWidth, physHeight)); + mScreens.append(mPrimaryScreen); +} + +QLinuxFbIntegration::~QLinuxFbIntegration() +{ + delete mPrimaryScreen; + delete d_ptr; +} + +bool QLinuxFbIntegration::connect(const QString &displaySpec) +{ + const QStringList args = displaySpec.split(QLatin1Char(':')); + + if (args.contains(QLatin1String("nographicsmodeswitch"))) + d_ptr->doGraphicsMode = false; + +#ifdef QT_QWS_DEPTH_GENERIC + if (args.contains(QLatin1String("genericcolors"))) + d_ptr->doGenericColors = true; +#endif + + QRegExp ttyRegExp(QLatin1String("tty=(.*)")); + if (args.indexOf(ttyRegExp) != -1) + d_ptr->ttyDevice = ttyRegExp.cap(1); + +#if 0 +#if Q_BYTE_ORDER == Q_BIG_ENDIAN +#ifndef QT_QWS_FRAMEBUFFER_LITTLE_ENDIAN + if (args.contains(QLatin1String("littleendian"))) +#endif + QScreen::setFrameBufferLittleEndian(true); +#endif +#endif + + // Check for explicitly specified device + const int len = 8; // "/dev/fbx" + int m = displaySpec.indexOf(QLatin1String("/dev/fb")); + + QString dev; + if (m > 0) + dev = displaySpec.mid(m, len); + else + dev = QLatin1String("/dev/fb0"); + + if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0) + d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR); + if (d_ptr->fd == -1) { + if (access(dev.toLatin1().constData(), R_OK) == 0) + d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDONLY); + if (d_ptr->fd == 1) { + qWarning("Error opening framebuffer device %s", qPrintable(dev)); + return false; + } + } + + fb_fix_screeninfo finfo; + fb_var_screeninfo vinfo; + //####################### + // Shut up Valgrind + memset(&vinfo, 0, sizeof(vinfo)); + memset(&finfo, 0, sizeof(finfo)); + //####################### + + /* Get fixed screen information */ + if (d_ptr->fd != -1 && ioctl(d_ptr->fd, FBIOGET_FSCREENINFO, &finfo)) { + perror("QLinuxFbIntegration::connect"); + qWarning("Error reading fixed information"); + return false; + } + + if (finfo.type == FB_TYPE_VGA_PLANES) { + qWarning("VGA16 video mode not supported"); + return false; + } + + /* Get variable screen information */ + if (d_ptr->fd != -1 && ioctl(d_ptr->fd, FBIOGET_VSCREENINFO, &vinfo)) { + perror("QLinuxFbIntegration::connect"); + qWarning("Error reading variable information"); + return false; + } + + grayscale = vinfo.grayscale; + d = vinfo.bits_per_pixel; + if (d == 24) { + d = vinfo.red.length + vinfo.green.length + vinfo.blue.length; + if (d <= 0) + d = 24; // reset if color component lengths are not reported + } else if (d == 16) { + d = vinfo.red.length + vinfo.green.length + vinfo.blue.length; + if (d <= 0) + d = 16; + } + lstep = finfo.line_length; + + int xoff = vinfo.xoffset; + int yoff = vinfo.yoffset; + const char* qwssize; + if((qwssize=::getenv("QWS_SIZE")) && sscanf(qwssize,"%dx%d",&w,&h)==2) { + if (d_ptr->fd != -1) { + if ((uint)w > vinfo.xres) w = vinfo.xres; + if ((uint)h > vinfo.yres) h = vinfo.yres; + } + dw=w; + dh=h; + int xxoff, yyoff; + if (sscanf(qwssize, "%*dx%*d+%d+%d", &xxoff, &yyoff) == 2) { + if (xxoff < 0 || xxoff + w > (int)(vinfo.xres)) + xxoff = vinfo.xres - w; + if (yyoff < 0 || yyoff + h > (int)(vinfo.yres)) + yyoff = vinfo.yres - h; + xoff += xxoff; + yoff += yyoff; + } else { + xoff += (vinfo.xres - w)/2; + yoff += (vinfo.yres - h)/2; + } + } else { + dw=w=vinfo.xres; + dh=h=vinfo.yres; + } + + if (w == 0 || h == 0) { + qWarning("QLinuxFbIntegration::connect(): Unable to find screen geometry, " + "will use 320x240."); + dw = w = 320; + dh = h = 240; + } + + setPixelFormat(vinfo); + + // Handle display physical size spec. + QStringList displayArgs = displaySpec.split(QLatin1Char(':')); + QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)")); + int dimIdxW = displayArgs.indexOf(mmWidthRx); + QRegExp mmHeightRx(QLatin1String("mmHeight=?(\\d+)")); + int dimIdxH = displayArgs.indexOf(mmHeightRx); + if (dimIdxW >= 0) { + mmWidthRx.exactMatch(displayArgs.at(dimIdxW)); + physWidth = mmWidthRx.cap(1).toInt(); + if (dimIdxH < 0) + physHeight = dh*physWidth/dw; + } + if (dimIdxH >= 0) { + mmHeightRx.exactMatch(displayArgs.at(dimIdxH)); + physHeight = mmHeightRx.cap(1).toInt(); + if (dimIdxW < 0) + physWidth = dw*physHeight/dh; + } + if (dimIdxW < 0 && dimIdxH < 0) { + if (vinfo.width != 0 && vinfo.height != 0 + && vinfo.width != UINT_MAX && vinfo.height != UINT_MAX) { + physWidth = vinfo.width; + physHeight = vinfo.height; + } else { + const int dpi = 72; + physWidth = qRound(dw * 25.4 / dpi); + physHeight = qRound(dh * 25.4 / dpi); + } + } + + dataoffset = yoff * lstep + xoff * d / 8; + //qDebug("Using %dx%dx%d screen",w,h,d); + + /* Figure out the size of the screen in bytes */ + size = h * lstep; + + mapsize = finfo.smem_len; + + data = (unsigned char *)-1; + if (d_ptr->fd != -1) + data = (unsigned char *)mmap(0, mapsize, PROT_READ | PROT_WRITE, + MAP_SHARED, d_ptr->fd, 0); + + if ((long)data == -1) { + perror("QLinuxFbIntegration::connect"); + qWarning("Error: failed to map framebuffer device to memory."); + return false; + } else { + data += dataoffset; + } + +#if 0 + canaccel = useOffscreen(); + if(canaccel) + setupOffScreen(); +#endif + canaccel = false; + + // Now read in palette + if((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4)) { + screencols= (vinfo.bits_per_pixel==8) ? 256 : 16; + int loopc; + fb_cmap startcmap; + startcmap.start=0; + startcmap.len=screencols; + startcmap.red=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + startcmap.green=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + startcmap.blue=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + startcmap.transp=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + if (d_ptr->fd == -1 || ioctl(d_ptr->fd, FBIOGETCMAP, &startcmap)) { + perror("QLinuxFbIntegration::connect"); + qWarning("Error reading palette from framebuffer, using default palette"); + createPalette(startcmap, vinfo, finfo); + } + int bits_used = 0; + for(loopc=0;loopc<screencols;loopc++) { + screenclut[loopc]=qRgb(startcmap.red[loopc] >> 8, + startcmap.green[loopc] >> 8, + startcmap.blue[loopc] >> 8); + bits_used |= startcmap.red[loopc] + | startcmap.green[loopc] + | startcmap.blue[loopc]; + } + // WORKAROUND: Some framebuffer drivers only return 8 bit + // color values, so we need to not bit shift them.. + if ((bits_used & 0x00ff) && !(bits_used & 0xff00)) { + for(loopc=0;loopc<screencols;loopc++) { + screenclut[loopc] = qRgb(startcmap.red[loopc], + startcmap.green[loopc], + startcmap.blue[loopc]); + } + qWarning("8 bits cmap returned due to faulty FB driver, colors corrected"); + } + free(startcmap.red); + free(startcmap.green); + free(startcmap.blue); + free(startcmap.transp); + } else { + screencols=0; + } + + return true; +} + +bool QLinuxFbIntegration::initDevice() +{ + d_ptr->openTty(); + + // Grab current mode so we can reset it + fb_var_screeninfo vinfo; + fb_fix_screeninfo finfo; + //####################### + // Shut up Valgrind + memset(&vinfo, 0, sizeof(vinfo)); + memset(&finfo, 0, sizeof(finfo)); + //####################### + + if (ioctl(d_ptr->fd, FBIOGET_VSCREENINFO, &vinfo)) { + perror("QLinuxFbScreen::initDevice"); + qFatal("Error reading variable information in card init"); + return false; + } + +#ifdef DEBUG_VINFO + qDebug("Greyscale %d",vinfo.grayscale); + qDebug("Nonstd %d",vinfo.nonstd); + qDebug("Red %d %d %d",vinfo.red.offset,vinfo.red.length, + vinfo.red.msb_right); + qDebug("Green %d %d %d",vinfo.green.offset,vinfo.green.length, + vinfo.green.msb_right); + qDebug("Blue %d %d %d",vinfo.blue.offset,vinfo.blue.length, + vinfo.blue.msb_right); + qDebug("Transparent %d %d %d",vinfo.transp.offset,vinfo.transp.length, + vinfo.transp.msb_right); +#endif + + d_ptr->startupw=vinfo.xres; + d_ptr->startuph=vinfo.yres; + d_ptr->startupd=vinfo.bits_per_pixel; + grayscale = vinfo.grayscale; + + if (ioctl(d_ptr->fd, FBIOGET_FSCREENINFO, &finfo)) { + perror("QLinuxFbScreen::initDevice"); + qCritical("Error reading fixed information in card init"); + // It's not an /error/ as such, though definitely a bad sign + // so we return true + return true; + } + +#ifdef __i386__ + // Now init mtrr + if(!::getenv("QWS_NOMTRR")) { + int mfd=QT_OPEN("/proc/mtrr",O_WRONLY,0); + // MTRR entry goes away when file is closed - i.e. + // hopefully when QWS is killed + if(mfd != -1) { + mtrr_sentry sentry; + sentry.base=(unsigned long int)finfo.smem_start; + //qDebug("Physical framebuffer address %p",(void*)finfo.smem_start); + // Size needs to be in 4k chunks, but that's not always + // what we get thanks to graphics card registers. Write combining + // these is Not Good, so we write combine what we can + // (which is not much - 4 megs on an 8 meg card, it seems) + unsigned int size=finfo.smem_len; + size=size >> 22; + size=size << 22; + sentry.size=size; + sentry.type=MTRR_TYPE_WRCOMB; + if(ioctl(mfd,MTRRIOC_ADD_ENTRY,&sentry)==-1) { + //printf("Couldn't add mtrr entry for %lx %lx, %s\n", + //sentry.base,sentry.size,strerror(errno)); + } + } + + // Should we close mfd here? + //QT_CLOSE(mfd); + } +#endif + if ((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4) || (finfo.visual==FB_VISUAL_DIRECTCOLOR)) + { + fb_cmap cmap; + createPalette(cmap, vinfo, finfo); + if (ioctl(d_ptr->fd, FBIOPUTCMAP, &cmap)) { + perror("QLinuxFbScreen::initDevice"); + qWarning("Error writing palette to framebuffer"); + } + free(cmap.red); + free(cmap.green); + free(cmap.blue); + free(cmap.transp); + } + +#if 0 + if (canaccel) { + *entryp=0; + *lowest = mapsize; + insert_entry(*entryp, *lowest, *lowest); // dummy entry to mark start + } + + shared->fifocount = 0; + shared->buffer_offset = 0xffffffff; // 0 would be a sensible offset (screen) + shared->linestep = 0; + shared->cliptop = 0xffffffff; + shared->clipleft = 0xffffffff; + shared->clipright = 0xffffffff; + shared->clipbottom = 0xffffffff; + shared->rop = 0xffffffff; +#endif + +#ifdef QT_QWS_DEPTH_GENERIC + if (pixelFormat() == QImage::Format_Invalid && screencols == 0 + && d_ptr->doGenericColors) + { + qt_set_generic_blit(this, vinfo.bits_per_pixel, + vinfo.red.length, vinfo.green.length, + vinfo.blue.length, vinfo.transp.length, + vinfo.red.offset, vinfo.green.offset, + vinfo.blue.offset, vinfo.transp.offset); + } +#endif + +#if 0 +#ifndef QT_NO_QWS_CURSOR + QScreenCursor::initSoftwareCursor(); +#endif +#endif + blank(false); + + return true; +} + +void QLinuxFbIntegration::setPixelFormat(struct fb_var_screeninfo info) +{ + const fb_bitfield rgba[4] = { info.red, info.green, + info.blue, info.transp }; + + QImage::Format format = QImage::Format_Invalid; + + switch (d) { + case 32: { + const fb_bitfield argb8888[4] = {{16, 8, 0}, {8, 8, 0}, + {0, 8, 0}, {24, 8, 0}}; + const fb_bitfield abgr8888[4] = {{0, 8, 0}, {8, 8, 0}, + {16, 8, 0}, {24, 8, 0}}; + if (memcmp(rgba, argb8888, 4 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_ARGB32; + } else if (memcmp(rgba, argb8888, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB32; + } else if (memcmp(rgba, abgr8888, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB32; + pixeltype = BGRPixel; + } + break; + } + case 24: { + const fb_bitfield rgb888[4] = {{16, 8, 0}, {8, 8, 0}, + {0, 8, 0}, {0, 0, 0}}; + const fb_bitfield bgr888[4] = {{0, 8, 0}, {8, 8, 0}, + {16, 8, 0}, {0, 0, 0}}; + if (memcmp(rgba, rgb888, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB888; + } else if (memcmp(rgba, bgr888, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB888; + pixeltype = BGRPixel; + } + break; + } + case 18: { + const fb_bitfield rgb666[4] = {{12, 6, 0}, {6, 6, 0}, + {0, 6, 0}, {0, 0, 0}}; + if (memcmp(rgba, rgb666, 3 * sizeof(fb_bitfield)) == 0) + format = QImage::Format_RGB666; + break; + } + case 16: { + const fb_bitfield rgb565[4] = {{11, 5, 0}, {5, 6, 0}, + {0, 5, 0}, {0, 0, 0}}; + const fb_bitfield bgr565[4] = {{0, 5, 0}, {5, 6, 0}, + {11, 5, 0}, {0, 0, 0}}; + if (memcmp(rgba, rgb565, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB16; + } else if (memcmp(rgba, bgr565, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB16; + pixeltype = BGRPixel; + } + break; + } + case 15: { + const fb_bitfield rgb1555[4] = {{10, 5, 0}, {5, 5, 0}, + {0, 5, 0}, {15, 1, 0}}; + const fb_bitfield bgr1555[4] = {{0, 5, 0}, {5, 5, 0}, + {10, 5, 0}, {15, 1, 0}}; + if (memcmp(rgba, rgb1555, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB555; + } else if (memcmp(rgba, bgr1555, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB555; + pixeltype = BGRPixel; + } + break; + } + case 12: { + const fb_bitfield rgb444[4] = {{8, 4, 0}, {4, 4, 0}, + {0, 4, 0}, {0, 0, 0}}; + if (memcmp(rgba, rgb444, 3 * sizeof(fb_bitfield)) == 0) + format = QImage::Format_RGB444; + break; + } + case 8: + break; + case 1: + format = QImage::Format_Mono; //###: LSB??? + break; + default: + break; + } + + screenFormat = format; +} + +void QLinuxFbIntegration::createPalette(fb_cmap &cmap, fb_var_screeninfo &vinfo, fb_fix_screeninfo &finfo) +{ + if((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4)) { + screencols= (vinfo.bits_per_pixel==8) ? 256 : 16; + cmap.start=0; + cmap.len=screencols; + cmap.red=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + cmap.green=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + cmap.blue=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + cmap.transp=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + + if (screencols==16) { + if (finfo.type == FB_TYPE_PACKED_PIXELS) { + // We'll setup a grayscale cmap for 4bpp linear + int val = 0; + for (int idx = 0; idx < 16; ++idx, val += 17) { + cmap.red[idx] = (val<<8)|val; + cmap.green[idx] = (val<<8)|val; + cmap.blue[idx] = (val<<8)|val; + screenclut[idx]=qRgb(val, val, val); + } + } else { + // Default 16 colour palette + // Green is now trolltech green so certain images look nicer + // black d_gray l_gray white red green blue cyan magenta yellow + unsigned char reds[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0xFF, 0xA2, 0x00, 0xFF, 0xFF, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x82 }; + unsigned char greens[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0x00, 0xC5, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F }; + unsigned char blues[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0x00, 0x11, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x7F, 0x7F, 0x7F, 0x00, 0x00 }; + + for (int idx = 0; idx < 16; ++idx) { + cmap.red[idx] = ((reds[idx]) << 8)|reds[idx]; + cmap.green[idx] = ((greens[idx]) << 8)|greens[idx]; + cmap.blue[idx] = ((blues[idx]) << 8)|blues[idx]; + cmap.transp[idx] = 0; + screenclut[idx]=qRgb(reds[idx], greens[idx], blues[idx]); + } + } + } else { + if (grayscale) { + // Build grayscale palette + int i; + for(i=0;i<screencols;++i) { + int bval = screencols == 256 ? i : (i << 4); + ushort val = (bval << 8) | bval; + cmap.red[i] = val; + cmap.green[i] = val; + cmap.blue[i] = val; + cmap.transp[i] = 0; + screenclut[i] = qRgb(bval,bval,bval); + } + } else { + // 6x6x6 216 color cube + int idx = 0; + for(int ir = 0x0; ir <= 0xff; ir+=0x33) { + for(int ig = 0x0; ig <= 0xff; ig+=0x33) { + for(int ib = 0x0; ib <= 0xff; ib+=0x33) { + cmap.red[idx] = (ir << 8)|ir; + cmap.green[idx] = (ig << 8)|ig; + cmap.blue[idx] = (ib << 8)|ib; + cmap.transp[idx] = 0; + screenclut[idx]=qRgb(ir, ig, ib); + ++idx; + } + } + } + // Fill in rest with 0 + for (int loopc=0; loopc<40; ++loopc) { + screenclut[idx]=0; + ++idx; + } + screencols=idx; + } + } + } else if(finfo.visual==FB_VISUAL_DIRECTCOLOR) { + cmap.start=0; + int rbits=0,gbits=0,bbits=0; + switch (vinfo.bits_per_pixel) { + case 8: + rbits=vinfo.red.length; + gbits=vinfo.green.length; + bbits=vinfo.blue.length; + if(rbits==0 && gbits==0 && bbits==0) { + // cyber2000 driver bug hack + rbits=3; + gbits=3; + bbits=2; + } + break; + case 15: + rbits=5; + gbits=5; + bbits=5; + break; + case 16: + rbits=5; + gbits=6; + bbits=5; + break; + case 18: + case 19: + rbits=6; + gbits=6; + bbits=6; + break; + case 24: case 32: + rbits=gbits=bbits=8; + break; + } + screencols=cmap.len=1<<qMax(rbits,qMax(gbits,bbits)); + cmap.red=(unsigned short int *) + malloc(sizeof(unsigned short int)*256); + cmap.green=(unsigned short int *) + malloc(sizeof(unsigned short int)*256); + cmap.blue=(unsigned short int *) + malloc(sizeof(unsigned short int)*256); + cmap.transp=(unsigned short int *) + malloc(sizeof(unsigned short int)*256); + for(unsigned int i = 0x0; i < cmap.len; i++) { + cmap.red[i] = i*65535/((1<<rbits)-1); + cmap.green[i] = i*65535/((1<<gbits)-1); + cmap.blue[i] = i*65535/((1<<bbits)-1); + cmap.transp[i] = 0; + } + } +} + +void QLinuxFbIntegration::blank(bool on) +{ + if (d_ptr->blank == on) + return; + +#if defined(QT_QWS_IPAQ) + if (on) + system("apm -suspend"); +#else + if (d_ptr->fd == -1) + return; +// Some old kernel versions don't have this. These defines should go +// away eventually +#if defined(FBIOBLANK) +#if defined(VESA_POWERDOWN) && defined(VESA_NO_BLANKING) + ioctl(d_ptr->fd, FBIOBLANK, on ? VESA_POWERDOWN : VESA_NO_BLANKING); +#else + ioctl(d_ptr->fd, FBIOBLANK, on ? 1 : 0); +#endif +#endif +#endif + + d_ptr->blank = on; +} + +QPixmapData *QLinuxFbIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QWindowSurface *QLinuxFbIntegration::createWindowSurface(QWidget *widget, WId) const +{ + QFbWindowSurface * surface = + new QFbWindowSurface(mPrimaryScreen, widget); + return surface; +} + +QPlatformWindow *QLinuxFbIntegration::createPlatformWindow(QWidget *widget, WId /*winId*/) const +{ + QFbWindow *w = new QFbWindow(widget); + mPrimaryScreen->addWindow(w); + return w; +} + +QPlatformFontDatabase *QLinuxFbIntegration::fontDatabase() const +{ + return fontDb; +} + +QLinuxFbScreen::QLinuxFbScreen(uchar * d, int w, + int h, int lstep, QImage::Format screenFormat) : compositePainter(0) +{ + data = d; + mGeometry = QRect(0,0,w,h); + bytesPerLine = lstep; + mFormat = screenFormat; + mDepth = 16; + mScreenImage = new QImage(mGeometry.width(), mGeometry.height(), + mFormat); + mFbScreenImage = new QImage(data, mGeometry.width(), mGeometry.height(), + bytesPerLine, mFormat); + cursor = new QPlatformSoftwareCursor(this); +} + +void QLinuxFbScreen::setGeometry(QRect rect) +{ + mGeometry = rect; + delete mFbScreenImage; + mFbScreenImage = new QImage(data, mGeometry.width(), mGeometry.height(), + bytesPerLine, mFormat); + delete compositePainter; + compositePainter = 0; + + delete mScreenImage; + mScreenImage = new QImage(mGeometry.width(), mGeometry.height(), + mFormat); +} + +void QLinuxFbScreen::setFormat(QImage::Format format) +{ + mFormat = format; + delete mFbScreenImage; + mFbScreenImage = new QImage(data, mGeometry.width(), mGeometry.height(), + bytesPerLine, mFormat); + delete compositePainter; + compositePainter = 0; + + delete mScreenImage; + mScreenImage = new QImage(mGeometry.width(), mGeometry.height(), + mFormat); +} + +QRegion QLinuxFbScreen::doRedraw() +{ + QRegion touched; + touched = QFbScreen::doRedraw(); + + if (!compositePainter) { + compositePainter = new QPainter(mFbScreenImage); + } + + QVector<QRect> rects = touched.rects(); + for (int i = 0; i < rects.size(); i++) + compositePainter->drawImage(rects[i], *mScreenImage, rects[i]); + return touched; +} +QT_END_NAMESPACE diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h new file mode 100644 index 0000000..e93495c --- /dev/null +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSYSTEM_LINUXFB_H +#define QGRAPHICSSYSTEM_LINUXFB_H + +#include <QPlatformIntegration> +#include "../fb_base/fb_base.h" + +QT_BEGIN_NAMESPACE + +class QLinuxFbScreen : public QFbScreen +{ + Q_OBJECT +public: + QLinuxFbScreen(uchar * d, int w, int h, int lstep, QImage::Format screenFormat); + void setGeometry(QRect rect); + void setFormat(QImage::Format format); + +public slots: + QRegion doRedraw(); + +private: + QImage * mFbScreenImage; + uchar * data; + int bytesPerLine; + + QPainter *compositePainter; +}; + +class QLinuxFbIntegrationPrivate; +struct fb_cmap; +struct fb_var_screeninfo; +struct fb_fix_screeninfo; + +class QLinuxFbIntegration : public QPlatformIntegration +{ +public: + QLinuxFbIntegration(); + ~QLinuxFbIntegration(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId WinId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId WinId) const; + + QList<QPlatformScreen *> screens() const { return mScreens; } + + QPlatformFontDatabase *fontDatabase() const; + +private: + QLinuxFbScreen *mPrimaryScreen; + QList<QPlatformScreen *> mScreens; + QLinuxFbIntegrationPrivate *d_ptr; + + enum PixelType { NormalPixel, BGRPixel }; + + QRgb screenclut[256]; + int screencols; + + uchar * data; + + QImage::Format screenFormat; + int w; + int lstep; + int h; + int d; + PixelType pixeltype; + bool grayscale; + + int dw; + int dh; + + int size; // Screen size + int mapsize; // Total mapped memory + + int displayId; + + int physWidth; + int physHeight; + + bool canaccel; + int dataoffset; + int cacheStart; + + bool connect(const QString &displaySpec); + bool initDevice(); + void setPixelFormat(struct fb_var_screeninfo); + void createPalette(fb_cmap &cmap, fb_var_screeninfo &vinfo, fb_fix_screeninfo &finfo); + void blank(bool on); + QPlatformFontDatabase *fontDb; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/minimal/main.cpp b/src/plugins/platforms/minimal/main.cpp new file mode 100644 index 0000000..82c15c2 --- /dev/null +++ b/src/plugins/platforms/minimal/main.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 plugins 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 <QtGui/QPlatformIntegrationPlugin> +#include "qminimalintegration.h" + +QT_BEGIN_NAMESPACE + +class QMinimalIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QMinimalIntegrationPlugin::keys() const +{ + QStringList list; + list << "Minimal"; + return list; +} + +QPlatformIntegration *QMinimalIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "minimal") + return new QMinimalIntegration; + + return 0; +} + +Q_EXPORT_PLUGIN2(minimal, QMinimalIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/minimal/minimal.pro b/src/plugins/platforms/minimal/minimal.pro new file mode 100644 index 0000000..438a88e --- /dev/null +++ b/src/plugins/platforms/minimal/minimal.pro @@ -0,0 +1,13 @@ +TARGET = qminimal +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +SOURCES = main.cpp \ + qminimalintegration.cpp \ + qminimalwindowsurface.cpp +HEADERS = qminimalintegration.h \ + qminimalwindowsurface.h + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target diff --git a/src/plugins/platforms/minimal/qminimalintegration.cpp b/src/plugins/platforms/minimal/qminimalintegration.cpp new file mode 100644 index 0000000..c90e92e --- /dev/null +++ b/src/plugins/platforms/minimal/qminimalintegration.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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 plugins 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 "qminimalintegration.h" +#include "qminimalwindowsurface.h" + +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtGui/QPlatformWindow> + +QMinimalIntegration::QMinimalIntegration() +{ + QMinimalScreen *mPrimaryScreen = new QMinimalScreen(); + + mPrimaryScreen->mGeometry = QRect(0, 0, 240, 320); + mPrimaryScreen->mDepth = 16; + mPrimaryScreen->mFormat = QImage::Format_RGB16; + + mScreens.append(mPrimaryScreen); +} + +QPixmapData *QMinimalIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QPlatformWindow *QMinimalIntegration::createPlatformWindow(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + return new QPlatformWindow(widget); +} + +QWindowSurface *QMinimalIntegration::createWindowSurface(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + return new QMinimalWindowSurface(widget); +} diff --git a/src/plugins/platforms/minimal/qminimalintegration.h b/src/plugins/platforms/minimal/qminimalintegration.h new file mode 100644 index 0000000..95b952e --- /dev/null +++ b/src/plugins/platforms/minimal/qminimalintegration.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QPLATFORMINTEGRATION_MINIMAL_H +#define QPLATFORMINTEGRATION_MINIMAL_H + +#include <QtGui/QPlatformIntegration> +#include <QtGui/QPlatformScreen> + +QT_BEGIN_NAMESPACE + +class QMinimalScreen : public QPlatformScreen +{ +public: + QMinimalScreen() + : mDepth(16), mFormat(QImage::Format_RGB16) {} + + QRect geometry() const { return mGeometry; } + int depth() const { return mDepth; } + QImage::Format format() const { return mFormat; } + +public: + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + QSize mPhysicalSize; +}; + +class QMinimalIntegration : public QPlatformIntegration +{ +public: + QMinimalIntegration(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QList<QPlatformScreen *> screens() const { return mScreens; } + +private: + QList<QPlatformScreen *> mScreens; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/minimal/qminimalwindowsurface.cpp b/src/plugins/platforms/minimal/qminimalwindowsurface.cpp new file mode 100644 index 0000000..acf0e6e --- /dev/null +++ b/src/plugins/platforms/minimal/qminimalwindowsurface.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** 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 plugins 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 "qminimalwindowsurface.h" +#include <QtCore/qdebug.h> +#include <QtGui/private/qapplication_p.h> + +QT_BEGIN_NAMESPACE + +QMinimalWindowSurface::QMinimalWindowSurface(QWidget *window) + : QWindowSurface(window) +{ + //qDebug() << "QMinimalWindowSurface::QMinimalWindowSurface:" << (long)this; +} + +QMinimalWindowSurface::~QMinimalWindowSurface() +{ +} + +QPaintDevice *QMinimalWindowSurface::paintDevice() +{ + //qDebug() << "QMinimalWindowSurface::paintDevice"; + return &mImage; +} + +void QMinimalWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(region); + Q_UNUSED(offset); + + static int c = 0; + QString filename = QString("output%1.png").arg(c++, 4, 10, QLatin1Char('0')); + qDebug() << "QMinimalWindowSurface::flush() saving contents to" << filename.toLocal8Bit().constData(); + mImage.save(filename); +} + +void QMinimalWindowSurface::resize(const QSize &size) +{ + //qDebug() << "QMinimalWindowSurface::setGeometry:" << (long)this << rect; + QWindowSurface::resize(size); + QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); + if (mImage.size() != size) + mImage = QImage(size, format); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/minimal/qminimalwindowsurface.h b/src/plugins/platforms/minimal/qminimalwindowsurface.h new file mode 100644 index 0000000..98b26f6 --- /dev/null +++ b/src/plugins/platforms/minimal/qminimalwindowsurface.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_MINIMAL_H +#define QWINDOWSURFACE_MINIMAL_H + +#include <QtGui/private/qwindowsurface_p.h> + +#include <QtGui/QPlatformWindow> + +QT_BEGIN_NAMESPACE + +class QMinimalWindowSurface : public QWindowSurface +{ +public: + QMinimalWindowSurface(QWidget *window); + ~QMinimalWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); + +private: + QImage mImage; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/openkode/main.cpp b/src/plugins/platforms/openkode/main.cpp new file mode 100644 index 0000000..527747e --- /dev/null +++ b/src/plugins/platforms/openkode/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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 plugins 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 <QtGui/QPlatformIntegrationPlugin> +#include "qopenkodeintegration.h" + +QT_BEGIN_NAMESPACE + +class QOpenKODEPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QOpenKODEPlugin::keys() const +{ + QStringList list; + list << "OpenKODE"; + return list; +} + +QPlatformIntegration * QOpenKODEPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "openkode") + return new QOpenKODEIntegration; + + return 0; +} + +Q_EXPORT_PLUGIN2(openkode, QOpenKODEPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/openkode/openkode.pro b/src/plugins/platforms/openkode/openkode.pro new file mode 100644 index 0000000..c8ae415 --- /dev/null +++ b/src/plugins/platforms/openkode/openkode.pro @@ -0,0 +1,42 @@ +TARGET = qopenkodeintegration +include(../../qpluginbase.pri) + +QT += opengl + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +SOURCES = main.cpp \ + qopenkodeintegration.cpp \ + qopenkodewindow.cpp \ + ../eglconvenience/qeglplatformcontext.cpp \ + ../eglconvenience/qeglconvenience.cpp \ + qopenkodeeventloopintegration.cpp + +HEADERS = qopenkodeintegration.h \ + qopenkodewindow.h \ + ../eglconvenience/qeglplatformcontext.h \ + ../eglconvenience/qeglconvenience.h \ + qopenkodeeventloopintegration.h \ + openkodekeytranslator.h + +include (../fontdatabases/genericunix/genericunix.pri) + +RESOURCES = resources.qrc + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target + +LIBS += -lKD -lEGL +!isEmpty(QMAKE_INCDIR_OPENGL_ES2){ + INCLUDEPATH += $$QMAKE_INCDIR_OPENGL_ES2 +} +!isEmpty(QMAKE_LIBDIR_OPENGL_ES2){ + for(p, QMAKE_LIBDIR_OPENGL_ES2) { + exists($$p):LIBS += -L$$p + } +} +!isEmpty(QMAKE_LIBS_OPENGL_ES2){ + LIBS += $$QMAKE_LIBS_OPENGL_ES2 +} else { + LIBS += -lGLESv2 +} diff --git a/src/plugins/platforms/openkode/openkodekeytranslator.h b/src/plugins/platforms/openkode/openkodekeytranslator.h new file mode 100644 index 0000000..0070edc --- /dev/null +++ b/src/plugins/platforms/openkode/openkodekeytranslator.h @@ -0,0 +1,244 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef OPENKODEKEYTRANSLATOR_H +#define OPENKODEKEYTRANSLATOR_H + +#ifdef KD_ATX_keyboard + +#include <KD/ATX_keyboard.h> + +QT_BEGIN_NAMESPACE + +Qt::Key keyTranslator( int key ) +{ + switch (key) { +// KD_KEY_ACCEPT_ATX: +// KD_KEY_AGAIN_ATX: +// KD_KEY_ALLCANDIDATES_ATX +// KD_KEY_ALPHANUMERIC_ATX + case KD_KEY_ALT_ATX: + return Qt::Key_Alt; + case KD_KEY_ALTGRAPH_ATX: + return Qt::Key_AltGr; +// KD_KEY_APPS_ATX +// KD_KEY_ATTN_ATX +// KD_KEY_BROWSERBACK_ATX +// KD_KEY_BROWSERFAVORITES_ATX +// KD_KEY_BROWSERFORWARD_ATX +// KD_KEY_BROWSERHOME_ATX +// KD_KEY_BROWSERREFRESH_ATX +// KD_KEY_BROWSERSEARCH_ATX +// KD_KEY_BROWSERSTOP_ATX + case KD_KEY_CAPSLOCK_ATX: + return Qt::Key_CapsLock; + case KD_KEY_CLEAR_ATX: + return Qt::Key_Clear; + case KD_KEY_CODEINPUT_ATX: + return Qt::Key_Codeinput; +// KD_KEY_COMPOSE_ATX + case KD_KEY_CONTROL_ATX: + return Qt::Key_Control; +// KD_KEY_CRSEL_ATX +// KD_KEY_CONVERT_ATX + case KD_KEY_COPY_ATX: + return Qt::Key_Copy; + case KD_KEY_CUT_ATX: + return Qt::Key_Cut; + case KD_KEY_DOWN_ATX: + return Qt::Key_Down; + case KD_KEY_END_ATX: + return Qt::Key_End; + case KD_KEY_ENTER_ATX: + return Qt::Key_Enter; +// KD_KEY_ERASEEOF_ATX +// KD_KEY_EXECUTE_ATX +// KD_KEY_EXSEL_ATX + case KD_KEY_F1_ATX: + return Qt::Key_F1; + case KD_KEY_F2_ATX: + return Qt::Key_F2; + case KD_KEY_F3_ATX: + return Qt::Key_F3; + case KD_KEY_F4_ATX: + return Qt::Key_F4; + case KD_KEY_F5_ATX: + return Qt::Key_F5; + case KD_KEY_F6_ATX: + return Qt::Key_F6; + case KD_KEY_F7_ATX: + return Qt::Key_F7; + case KD_KEY_F8_ATX: + return Qt::Key_F8; + case KD_KEY_F9_ATX: + return Qt::Key_F9; + case KD_KEY_F10_ATX: + return Qt::Key_F10; + case KD_KEY_F11_ATX: + return Qt::Key_F11; + case KD_KEY_F12_ATX: + return Qt::Key_F12; + case KD_KEY_F13_ATX: + return Qt::Key_F13; + case KD_KEY_F14_ATX: + return Qt::Key_F14; + case KD_KEY_F15_ATX: + return Qt::Key_F15; + case KD_KEY_F16_ATX: + return Qt::Key_F16; + case KD_KEY_F17_ATX: + return Qt::Key_F17; + case KD_KEY_F18_ATX: + return Qt::Key_F18; + case KD_KEY_F19_ATX: + return Qt::Key_F19; + case KD_KEY_F20_ATX: + return Qt::Key_F20; + case KD_KEY_F21_ATX: + return Qt::Key_F21; + case KD_KEY_F22_ATX: + return Qt::Key_F22; + case KD_KEY_F23_ATX: + return Qt::Key_F23; + case KD_KEY_F24_ATX: + return Qt::Key_F24; +// KD_KEY_FINALMODE_ATX +// KD_KEY_FIND_ATX +// KD_KEY_FULLWIDTH_ATX +// KD_KEY_HALFWIDTH_ATX + case KD_KEY_HANGULMODE_ATX: + return Qt::Key_Hangul; +// KD_KEY_HANJAMODE_ATX + case KD_KEY_HELP_ATX: + return Qt::Key_Help; + case KD_KEY_HIRAGANA_ATX: + return Qt::Key_Hiragana; + case KD_KEY_HOME_ATX: + return Qt::Key_Home; + case KD_KEY_INSERT_ATX: + return Qt::Key_Insert; +// KD_KEY_JAPANESEHIRAGANA_ATX: +// KD_KEY_JAPANESEKATAKANA_ATX +// KD_KEY_JAPANESEROMAJI_ATX +// KD_KEY_JUNJAMODE_ATX + case KD_KEY_KANAMODE_ATX: + return Qt::Key_Kana_Lock; //? + case KD_KEY_KANJIMODE_ATX: + return Qt::Key_Kanji; +// KD_KEY_KATAKANA_ATX +// KD_KEY_LAUNCHAPPLICATION1_ATX +// KD_KEY_LAUNCHAPPLICATION2_ATX + case KD_KEY_LAUNCHMAIL_ATX: + return Qt::Key_MailForward; + case KD_KEY_LEFT_ATX: + return Qt::Key_Left; + case KD_KEY_META_ATX: + return Qt::Key_Meta; + case KD_KEY_MEDIANEXTTRACK_ATX: + return Qt::Key_MediaNext; + case KD_KEY_MEDIAPLAYPAUSE_ATX: + return Qt::Key_MediaPause; + case KD_KEY_MEDIAPREVIOUSTRACK_ATX: + return Qt::Key_MediaPrevious; + case KD_KEY_MEDIASTOP_ATX: + return Qt::Key_MediaStop; + case KD_KEY_MODECHANGE_ATX: + return Qt::Key_Mode_switch; +// KD_KEY_NONCONVERT_ATX + case KD_KEY_NUMLOCK_ATX: + return Qt::Key_NumLock; + case KD_KEY_PAGEDOWN_ATX: + return Qt::Key_PageDown; + case KD_KEY_PAGEUP_ATX: + return Qt::Key_PageUp; + case KD_KEY_PASTE_ATX: + return Qt::Key_Paste; + case KD_KEY_PAUSE_ATX: + return Qt::Key_Pause; + case KD_KEY_PLAY_ATX: + return Qt::Key_Play; +// KD_KEY_PREVIOUSCANDIDATE_ATX + case KD_KEY_PRINTSCREEN_ATX: + return Qt::Key_Print; +// case KD_KEY_PROCESS_ATX +// case KD_KEY_PROPS_ATX + case KD_KEY_RIGHT_ATX: + return Qt::Key_Right; +// KD_KEY_ROMANCHARACTERS_ATX + case KD_KEY_SCROLL_ATX: + return Qt::Key_ScrollLock; + case KD_KEY_SELECT_ATX: + return Qt::Key_Select; +// KD_KEY_SELECTMEDIA_ATX + case KD_KEY_SHIFT_ATX: + return Qt::Key_Shift; + case KD_KEY_STOP_ATX: + return Qt::Key_Stop; + case KD_KEY_UP_ATX: + return Qt::Key_Up; +// KD_KEY_UNDO_ATX + case KD_KEY_VOLUMEDOWN_ATX: + return Qt::Key_VolumeDown; + case KD_KEY_VOLUMEMUTE_ATX: + return Qt::Key_VolumeMute; + case KD_KEY_VOLUMEUP_ATX: + return Qt::Key_VolumeUp; + case KD_KEY_WIN_ATX: + return Qt::Key_Meta; + case KD_KEY_ZOOM_ATX: + return Qt::Key_Zoom; + case 0x8: + return Qt::Key_Backspace; + case 0x1b: + return Qt::Key_Escape; + case 0x9: + return Qt::Key_Tab; + + default: + break; + } + + return Qt::Key_Escape; +} + +QT_END_NAMESPACE +#endif //KD_ATX_keyboard +#endif // OPENKODEKEYTRANSLATOR_H diff --git a/src/plugins/platforms/openkode/qopenkodeeventloopintegration.cpp b/src/plugins/platforms/openkode/qopenkodeeventloopintegration.cpp new file mode 100644 index 0000000..73d874c --- /dev/null +++ b/src/plugins/platforms/openkode/qopenkodeeventloopintegration.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** 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 plugins 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 "qopenkodeeventloopintegration.h" + +#include <QDebug> + +#include <KD/kd.h> +#include <KD/ATX_keyboard.h> + +QT_BEGIN_NAMESPACE + +static const int QT_EVENT_WAKEUP_EVENTLOOP = KD_EVENT_USER + 1; + +void kdprocessevent( const KDEvent *event) +{ + switch (event->type) { + case KD_EVENT_INPUT: + qDebug() << "KD_EVENT_INPUT"; + break; + case KD_EVENT_INPUT_POINTER: + qDebug() << "KD_EVENT_INPUT_POINTER"; + break; + case KD_EVENT_WINDOW_CLOSE: + qDebug() << "KD_EVENT_WINDOW_CLOSE"; + break; + case KD_EVENT_WINDOWPROPERTY_CHANGE: + qDebug() << "KD_EVENT_WINDOWPROPERTY_CHANGE"; + qDebug() << event->data.windowproperty.pname; + break; + case KD_EVENT_WINDOW_FOCUS: + qDebug() << "KD_EVENT_WINDOW_FOCUS"; + break; + case KD_EVENT_WINDOW_REDRAW: + qDebug() << "KD_EVENT_WINDOW_REDRAW"; + break; + case KD_EVENT_USER: + qDebug() << "KD_EVENT_USER"; + break; + case KD_EVENT_INPUT_KEY_ATX: + qDebug() << "KD_EVENT_INPUT_KEY_ATX"; + break; + case QT_EVENT_WAKEUP_EVENTLOOP: +// qDebug() << "QT_EVENT_WAKEUP_EVENTLOOP"; + break; + default: + break; + } + + kdDefaultEvent(event); + +} + +QOpenKODEEventLoopIntegration::QOpenKODEEventLoopIntegration() +{ + m_kdThread = kdThreadSelf(); + kdInstallCallback(&kdprocessevent,QT_EVENT_WAKEUP_EVENTLOOP,this); +} + +void QOpenKODEEventLoopIntegration::processEvents(qint64 msec) +{ + if (msec == 0) + msec = -1; + const KDEvent *event = kdWaitEvent(msec*1000); + if (event) { + kdDefaultEvent(event); + while ((event = kdWaitEvent(0)) != 0) { + kdDefaultEvent(event); + } + } +} + +void QOpenKODEEventLoopIntegration::wakeup() +{ + KDEvent *event = kdCreateEvent(); + event->type = QT_EVENT_WAKEUP_EVENTLOOP; + event->userptr = this; + kdPostThreadEvent(event,m_kdThread); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/openkode/qopenkodeeventloopintegration.h b/src/plugins/platforms/openkode/qopenkodeeventloopintegration.h new file mode 100644 index 0000000..61bd444 --- /dev/null +++ b/src/plugins/platforms/openkode/qopenkodeeventloopintegration.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QOPENKODEEVENTLOOPINTEGRATION_H +#define QOPENKODEEVENTLOOPINTEGRATION_H + +#include <QtGui/QPlatformEventLoopIntegration> + +class KDThread; +class KDEvent; + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +class QOpenKODEEventLoopIntegration : public QPlatformEventLoopIntegration +{ +public: + QOpenKODEEventLoopIntegration(); + void processEvents(qint64 msec); + void wakeup(); + + void processInputEvent(const KDEvent *event); +private: + + KDThread *m_kdThread; +}; + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // QOPENKODEEVENTLOOPINTEGRATION_H diff --git a/src/plugins/platforms/openkode/qopenkodeintegration.cpp b/src/plugins/platforms/openkode/qopenkodeintegration.cpp new file mode 100644 index 0000000..60be897 --- /dev/null +++ b/src/plugins/platforms/openkode/qopenkodeintegration.cpp @@ -0,0 +1,240 @@ +/**************************************************************************** +** +** 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 plugins 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 "qopenkodeintegration.h" +#include "qopenkodewindow.h" +#include "qopenkodeeventloopintegration.h" + +#include <QtOpenGL/private/qpixmapdata_gl_p.h> +#include <QtOpenGL/private/qwindowsurface_gl_p.h> + +#include <QtGui/private/qpixmap_raster_p.h> + +#include <QtCore/qdebug.h> +#include <QtCore/qthread.h> +#include <QtCore/qfile.h> + +#include "qgenericunixfontdatabase.h" + +#include <KD/kd.h> +#include <KD/NV_display.h> +#include <KD/NV_initialize.h> + +#include <EGL/egl.h> + +#include "GLES2/gl2ext.h" + +QT_BEGIN_NAMESPACE + +QOpenKODEScreen::QOpenKODEScreen(KDDisplayNV *kdDisplay, KDDesktopNV *kdDesktop) + : mIsFullScreen(false) +{ + qDebug() << "QOpenKODEScreen::QOpenKODEIntegrationScreen()"; + + KDboolean enabled = KD_TRUE; + kdSetDisplayPropertybvNV(kdDisplay, + KD_DISPLAYPROPERTY_ENABLED_NV, + &enabled); + KDboolean power = KD_DISPLAY_POWER_ON; + kdSetDisplayPropertyivNV(kdDisplay, + KD_DISPLAYPROPERTY_POWER_NV, + &power); + + kdSetDisplayPropertycvNV(kdDisplay, + KD_DISPLAYPROPERTY_DESKTOP_NAME_NV, + KD_DEFAULT_DESKTOP_NV); + + KDDisplayModeNV mode; + if (kdGetDisplayModeNV(kdDisplay, &mode)) { + qErrnoWarning(kdGetError(), "Could not get display mode"); + return; + } + + qDebug() << " - display mode " << mode.width << "x" << mode.height << " refresh " << mode.refresh; + + KDint desktopSize[] = { mode.width, mode.height }; + + if (kdSetDesktopPropertyivNV(kdDesktop, KD_DESKTOPPROPERTY_SIZE_NV, desktopSize)) { + qErrnoWarning(kdGetError(), "Could not set desktop size"); + return; + } + + // Once we've set up the desktop and display we don't need them anymore + kdReleaseDisplayNV(kdDisplay); + kdReleaseDesktopNV(kdDesktop); + + mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (mEglDisplay == EGL_NO_DISPLAY) { + qErrnoWarning("EGL failed to obtain display"); + } + + /* Initialize EGL display */ + EGLBoolean rvbool = eglInitialize(mEglDisplay, 0, 0); + if (!rvbool) { + qErrnoWarning("EGL failed to initialize display"); + } + +// cursor = new QOpenKODECursor(this); + + mGeometry = QRect(0, 0, mode.width, mode.height); + mDepth = 24; + mFormat = QImage::Format_RGB32; + + +} + +QOpenKODEIntegration::QOpenKODEIntegration() + : mEventLoopIntegration(0), mFontDb(new QGenericUnixFontDatabase()) +{ + if (kdInitializeNV() == KD_ENOTINITIALIZED) { + qFatal("Did not manage to initialize openkode"); + } + + KDDisplaySystemNV *kdDisplaySystem = kdCreateDisplaySystemSnapshotNV(this); + KDint32 displayCount = 0; + kdGetDisplaySystemPropertyivNV(kdDisplaySystem, KD_DISPLAYPROPERTY_COUNT_NV, 0, &displayCount); + + for (int i = 0; i < displayCount; i++) { + KDchar *displayName = 0; + KDsize displayNameLength = 0; + kdGetDisplaySystemPropertycvNV(kdDisplaySystem,KD_DISPLAYPROPERTY_NAME_NV,i,0,&displayNameLength); + if (!displayNameLength) + continue; + displayName = new KDchar[displayNameLength]; + kdGetDisplaySystemPropertycvNV(kdDisplaySystem,KD_DISPLAYPROPERTY_NAME_NV,i,displayName,&displayNameLength); + + KDDisplayNV *display = kdGetDisplayNV(displayName,this); + if (!display || display == (void*)-1) { + qErrnoWarning(kdGetError(), "Could not obtain KDDisplayNV pointer"); + return; + } + if (displayNameLength) + delete displayName; + + KDchar *desktopName = 0; + KDsize desktopNameLength = 0; + bool openkodeImpDoesNotFail = false; + if (openkodeImpDoesNotFail) { + qDebug() << "printing desktopname"; + kdGetDisplayPropertycvNV(display,KD_DISPLAYPROPERTY_DESKTOP_NAME_NV,desktopName,&desktopNameLength); + if (desktopNameLength) { + desktopName = new KDchar[desktopNameLength]; + kdGetDisplayPropertycvNV(display,KD_DISPLAYPROPERTY_DESKTOP_NAME_NV,desktopName,&desktopNameLength); + } else { + desktopName = KD_DEFAULT_DESKTOP_NV; + } + } else { + desktopName = KD_DEFAULT_DESKTOP_NV; + } + + KDDesktopNV *desktop = kdGetDesktopNV(desktopName,this); + if (!desktop || desktop == (void*)-1) { + qErrnoWarning(kdGetError(), "Could not obtain KDDesktopNV pointer"); + kdReleaseDisplayNV(display); + return; + } + if (desktopNameLength) + delete desktopName; + + QOpenKODEScreen *screen = new QOpenKODEScreen(display,desktop); + mScreens.append(screen); + } +} + +QOpenKODEIntegration::~QOpenKODEIntegration() +{ + delete mEventLoopIntegration; + delete mFontDb; +} + +QPixmapData *QOpenKODEIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + return new QGLPixmapData(type); +} + +QPlatformWindow *QOpenKODEIntegration::createPlatformWindow(QWidget *tlw, WId ) const +{ + return new QOpenKODEWindow(tlw); +} + +QWindowSurface *QOpenKODEIntegration::createWindowSurface(QWidget *widget, WId) const +{ + QWindowSurface *returnSurface = 0; + switch (widget->platformWindowFormat().windowApi()) { + + case QPlatformWindowFormat::Raster: + case QPlatformWindowFormat::OpenGL: + returnSurface = new QGLWindowSurface(widget); + break; + + case QPlatformWindowFormat::OpenVG: +// returnSurface = new QVGWindowSurface(widget); + break; + + default: + returnSurface = new QGLWindowSurface(widget); + break; + } + + return returnSurface; +} + +bool QOpenKODEIntegration::hasOpenGL() const +{ + return true; +} + +QPlatformEventLoopIntegration *QOpenKODEIntegration::createEventLoopIntegration() const +{ + if (!mEventLoopIntegration) { + QOpenKODEIntegration *that = const_cast<QOpenKODEIntegration *>(this); + that->mEventLoopIntegration = new QOpenKODEEventLoopIntegration; + } + return mEventLoopIntegration; +} + +QPlatformFontDatabase *QOpenKODEIntegration::fontDatabase() const +{ + return mFontDb; +} + + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/openkode/qopenkodeintegration.h b/src/plugins/platforms/openkode/qopenkodeintegration.h new file mode 100644 index 0000000..a067491 --- /dev/null +++ b/src/plugins/platforms/openkode/qopenkodeintegration.h @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSYSTEM_OPENKODE_H +#define QGRAPHICSSYSTEM_OPENKODE_H + +#include "qopenkodeeventloopintegration.h" + +#include <QtCore/qsemaphore.h> + +#include <QtGui/QPlatformIntegration> +#include <QtGui/QPlatformScreen> +#include <QtGui/QPlatformGLContext> +#include <QtGui/QPlatformFontDatabase> + +#include <GLES2/gl2.h> +#include <EGL/egl.h> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +struct KDDesktopNV; +struct KDDisplayNV; +class QOpenKODECursor; + +class QOpenKODEScreen : public QPlatformScreen +{ + Q_OBJECT +public: + QOpenKODEScreen(KDDisplayNV *kdDisplay, KDDesktopNV *kdDesktop); + ~QOpenKODEScreen() {} + + QRect geometry() const { return mGeometry; } + int depth() const { return mDepth; } + QImage::Format format() const { return mFormat; } + + EGLDisplay eglDisplay() { return mEglDisplay; } + + bool isFullScreen() const {return mIsFullScreen;} + void setFullScreen(bool fullscreen) { mIsFullScreen = fullscreen; } +private: + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + EGLDisplay mEglDisplay; + bool mIsFullScreen; +}; + +class QOpenKODEIntegration : public QPlatformIntegration +{ +public: + QOpenKODEIntegration(); + ~QOpenKODEIntegration(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId = 0) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + bool hasOpenGL() const; + + QPlatformEventLoopIntegration *createEventLoopIntegration() const; + + QPlatformFontDatabase *fontDatabase() const; + + virtual QList<QPlatformScreen *> screens() const { return mScreens; } + + static GLuint blitterProgram(); + +private: + QList<QPlatformScreen *> mScreens; + QOpenKODEEventLoopIntegration *mEventLoopIntegration; + QPlatformFontDatabase *mFontDb; +}; + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/plugins/platforms/openkode/qopenkodewindow.cpp b/src/plugins/platforms/openkode/qopenkodewindow.cpp new file mode 100644 index 0000000..32517c6 --- /dev/null +++ b/src/plugins/platforms/openkode/qopenkodewindow.cpp @@ -0,0 +1,316 @@ +/**************************************************************************** +** +** 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 plugins 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 "qopenkodewindow.h" +#include "qopenkodeintegration.h" +#include "../eglconvenience/qeglplatformcontext.h" +#include "../eglconvenience/qeglconvenience.h" + +#include <KD/kd.h> +#include <KD/NV_display.h> +#include <KD/kdplatform.h> +#ifdef KD_ATX_keyboard +#include "openkodekeytranslator.h" +#endif + +#include <EGL/egl.h> + +#include <QtGui/qwidget.h> +#include <QtGui/private/qwidget_p.h> +#include <QtGui/private/qapplication_p.h> + +#include <QtCore/qvector.h> +#include <QtCore/QDebug> + +QT_BEGIN_NAMESPACE + +void kdProcessMouseEvents( const KDEvent *event ) +{ + QOpenKODEWindow *window = static_cast<QOpenKODEWindow *>(event->userptr); + window->processMouseEvents(event); +} + +#ifdef KD_ATX_keyboard +void kdProcessKeyEvents( const KDEvent *event ) +{ + QOpenKODEWindow *window = static_cast<QOpenKODEWindow *>(event->userptr); + window->processKeyEvents(event); +} +#endif //KD_ATX_keyboard + +QOpenKODEWindow::QOpenKODEWindow(QWidget *tlw) + : QPlatformWindow(tlw), isFullScreen(false) +{ + if (tlw->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenVG) { + m_eglApi = EGL_OPENVG_API; + } else { + m_eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); + m_eglContextAttrs.append(2); + + m_eglApi = EGL_OPENGL_ES_API; + } + eglBindAPI(m_eglApi); + + m_eglContextAttrs.append(EGL_NONE); + m_eglWindowAttrs.append(EGL_NONE); + + QList<QPlatformScreen *> screens = QApplicationPrivate::platformIntegration()->screens(); + //XXXX: jl figure out how to pick the correct screen. +// Q_ASSERT(screens.size() > tlw->d_func()->screenNumber); +// QOpenKODEScreen *screen = qobject_cast<QOpenKODEScreen *>(screens.at(tlw->d_func()->screenNumber)); + QOpenKODEScreen *screen = qobject_cast<QOpenKODEScreen *>(screens.at(0)); + if (!screen) { + qErrnoWarning("Could not make QOpenKODEWindow without a screen"); + } + + QPlatformWindowFormat format = tlw->platformWindowFormat(); + format.setRedBufferSize(5); + format.setGreenBufferSize(6); + format.setBlueBufferSize(5); + + m_eglConfig = q_configFromQPlatformWindowFormat(screen->eglDisplay(),format); + + m_kdWindow = kdCreateWindow(screen->eglDisplay(), + m_eglConfig, + this); + kdInstallCallback(kdProcessMouseEvents,KD_EVENT_INPUT_POINTER,this); +#ifdef KD_ATX_keyboard + kdInstallCallback(kdProcessKeyEvents, KD_EVENT_INPUT_KEY_ATX,this); +#endif //KD_ATX_keyboard + + if (!m_kdWindow) { + qErrnoWarning(kdGetError(), "Error creating native window"); + return; + } + + KDboolean exclusive(false); + if (kdSetWindowPropertybv(m_kdWindow,KD_WINDOWPROPERTY_DESKTOP_EXCLUSIVE_NV, &exclusive)) { + isFullScreen = true; + } + + if (isFullScreen) { + tlw->setGeometry(screen->geometry()); + screen->setFullScreen(isFullScreen); + }else { + const KDint windowSize[2] = { tlw->width(), tlw->height() }; + if (kdSetWindowPropertyiv(m_kdWindow, KD_WINDOWPROPERTY_SIZE, windowSize)) { + qErrnoWarning(kdGetError(), "Could not set native window size"); + } + KDboolean visibillity(false); + if (kdSetWindowPropertybv(m_kdWindow, KD_WINDOWPROPERTY_VISIBILITY, &visibillity)) { + qErrnoWarning(kdGetError(), "Could not set visibillity to false"); + } + + const KDint windowPos[2] = { tlw->x(), tlw->y() }; + if (kdSetWindowPropertyiv(m_kdWindow, KD_WINDOWPROPERTY_DESKTOP_OFFSET_NV, windowPos)) { + qErrnoWarning(kdGetError(), "Could not set native window position"); + return; + } + } + + + + + if (!isFullScreen || (isFullScreen && !QPlatformGLContext::defaultSharedContext())) { + if (kdRealizeWindow(m_kdWindow, &m_eglWindow)) { + qErrnoWarning(kdGetError(), "Could not realize native window"); + return; + } + + EGLSurface surface = eglCreateWindowSurface(screen->eglDisplay(),m_eglConfig,m_eglWindow,m_eglWindowAttrs.constData()); + m_platformGlContext = new QEGLPlatformContext(screen->eglDisplay(), m_eglConfig, + m_eglContextAttrs.data(), surface, m_eglApi); + m_platformGlContext->makeDefaultSaredContext(); + } else { + m_platformGlContext = static_cast<QEGLPlatformContext *>(QPlatformGLContext::defaultSharedContext()); + kdDestroyWindow(m_kdWindow); + m_kdWindow = 0; + } +} + + +QOpenKODEWindow::~QOpenKODEWindow() +{ + if (m_platformGlContext != QPlatformGLContext::defaultSharedContext()) { + delete m_platformGlContext; + } + if (m_kdWindow) + kdDestroyWindow(m_kdWindow); +} +void QOpenKODEWindow::setGeometry(const QRect &rect) +{ + if (isFullScreen) { + QList<QPlatformScreen *> screens = QApplicationPrivate::platformIntegration()->screens(); + QOpenKODEScreen *screen = qobject_cast<QOpenKODEScreen *>(screens.at(0)); + widget()->setGeometry(screen->geometry()); + return; + } + bool needToDeleteContext = false; + if (!isFullScreen) { + const QRect geo = geometry(); + if (geo.size() != rect.size()) { + const KDint windowSize[2] = { rect.width(), rect.height() }; + if (kdSetWindowPropertyiv(m_kdWindow, KD_WINDOWPROPERTY_SIZE, windowSize)) { + qErrnoWarning(kdGetError(), "Could not set native window size"); + //return; + } else { + needToDeleteContext = true; + } + } + + if (geo.topLeft() != rect.topLeft()) { + const KDint windowPos[2] = { rect.x(), rect.y() }; + if (kdSetWindowPropertyiv(m_kdWindow, KD_WINDOWPROPERTY_DESKTOP_OFFSET_NV, windowPos)) { + qErrnoWarning(kdGetError(), "Could not set native window position"); + //return; + } else { + needToDeleteContext = true; + } + } + } + + //need to recreate context + if (needToDeleteContext) { + qDebug() << "deleting context"; + delete m_platformGlContext; + + QList<QPlatformScreen *> screens = QApplicationPrivate::platformIntegration()->screens(); + QOpenKODEScreen *screen = qobject_cast<QOpenKODEScreen *>(screens.at(0)); + EGLSurface surface = eglCreateWindowSurface(screen->eglDisplay(),m_eglConfig,m_eglWindow,m_eglWindowAttrs.constData()); + m_platformGlContext = new QEGLPlatformContext(screen->eglDisplay(),m_eglConfig, + m_eglContextAttrs.data(),surface,m_eglApi); + } +} + +void QOpenKODEWindow::setVisible(bool visible) +{ + if (!m_kdWindow) + return; + KDboolean visibillity(visible); + if (kdSetWindowPropertybv(m_kdWindow, KD_WINDOWPROPERTY_VISIBILITY, &visibillity)) { + qErrnoWarning(kdGetError(), "Could not set visibillity property"); + } +} + +WId QOpenKODEWindow::winId() const +{ + static int i = 0; + return i++; +} + +QPlatformGLContext *QOpenKODEWindow::glContext() const +{ + return m_platformGlContext; +} + +void QOpenKODEWindow::raise() +{ + if (!m_kdWindow) + return; + KDboolean focus(true); + if (kdSetWindowPropertybv(m_kdWindow, KD_WINDOWPROPERTY_FOCUS, &focus)) { + qErrnoWarning(kdGetError(), "Could not set focus"); + } +} + +void QOpenKODEWindow::lower() +{ + if (!m_kdWindow) + return; + KDboolean focus(false); + if (kdSetWindowPropertybv(m_kdWindow, KD_WINDOWPROPERTY_FOCUS, &focus)) { + qErrnoWarning(kdGetError(), "Could not set focus"); + } +} + +void QOpenKODEWindow::processMouseEvents(const KDEvent *event) +{ + int x = event->data.inputpointer.x; + int y = event->data.inputpointer.y; + Qt::MouseButtons buttons; + switch(event->data.inputpointer.select) { + case 1: + buttons = Qt::LeftButton; + break; + default: + buttons = Qt::NoButton; + } + QPoint pos(x,y); + QWindowSystemInterface::handleMouseEvent(0,event->timestamp,pos,pos,buttons); +} + +void QOpenKODEWindow::processKeyEvents(const KDEvent *event) +{ +#ifdef KD_ATX_keyboard + //KD_KEY_PRESS_ATX 1 + QEvent::Type keyPressed = QEvent::KeyRelease; + if (event->data.keyboardInputKey.flags) + keyPressed = QEvent::KeyPress; +//KD_KEY_LOCATION_LEFT_ATX // dont care for now +//KD_KEY_LOCATION_RIGHT_ATX +//KD_KEY_LOCATION_NUMPAD_ATX + Qt::KeyboardModifiers mod = Qt::NoModifier; + int openkodeMods = event->data.keyboardInputKey.flags; + if (openkodeMods & KD_KEY_MODIFIER_SHIFT_ATX) + mod |= Qt::ShiftModifier; + if (openkodeMods & KD_KEY_MODIFIER_CTRL_ATX) + mod |= Qt::ControlModifier; + if (openkodeMods & KD_KEY_MODIFIER_ALT_ATX) + mod |= Qt::AltModifier; + if (openkodeMods & KD_KEY_MODIFIER_META_ATX) + mod |= Qt::MetaModifier; + + Qt::Key qtKey; + QChar keyText; + int key = event->data.keyboardInputKey.keycode; + if (key >= 0x20 && key <= 0x0ff){ // 8 bit printable Latin1 + qtKey = Qt::Key(key); + keyText = QChar(event->data.keyboardInputKeyChar.character); + if (!(mod & Qt::ShiftModifier)) + keyText = keyText.toLower(); + } else { + qtKey = keyTranslator(key); + } + QWindowSystemInterface::handleKeyEvent(0,event->timestamp,keyPressed,qtKey,mod,keyText); +#endif +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/openkode/qopenkodewindow.h b/src/plugins/platforms/openkode/qopenkodewindow.h new file mode 100644 index 0000000..4992807 --- /dev/null +++ b/src/plugins/platforms/openkode/qopenkodewindow.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QOPENKODEWINDOW_H +#define QOPENKODEWINDOW_H + +#include <QtGui/QPlatformWindow> +#include <QtCore/QVector> + +#include <KD/kd.h> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +class QEGLPlatformContext; +class QPlatformEventLoopIntegration; + +class QOpenKODEWindow : public QPlatformWindow +{ +public: + QOpenKODEWindow(QWidget *tlw); + ~QOpenKODEWindow(); + + void setGeometry(const QRect &rect); + void setVisible(bool visible); + WId winId() const; + + QPlatformGLContext *glContext() const; + + void raise(); + void lower(); + + void processKeyEvents( const KDEvent *event ); + void processMouseEvents( const KDEvent *event ); + +private: + struct KDWindow *m_kdWindow; + EGLNativeWindowType m_eglWindow; + EGLConfig m_eglConfig; + QVector<EGLint> m_eglWindowAttrs; + QVector<EGLint> m_eglContextAttrs; + EGLenum m_eglApi; + QEGLPlatformContext *m_platformGlContext; + + bool isFullScreen; +}; + +QT_END_NAMESPACE +QT_END_HEADER + +#endif //QOPENKODEWINDOW_H diff --git a/src/plugins/platforms/openkode/resources.qrc b/src/plugins/platforms/openkode/resources.qrc new file mode 100644 index 0000000..dbb3419 --- /dev/null +++ b/src/plugins/platforms/openkode/resources.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>shaders/vert.glslv</file> + <file>shaders/frag.glslf</file> +</qresource> +</RCC> diff --git a/src/plugins/platforms/openkode/shaders/frag.glslf b/src/plugins/platforms/openkode/shaders/frag.glslf new file mode 100644 index 0000000..c768437 --- /dev/null +++ b/src/plugins/platforms/openkode/shaders/frag.glslf @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +uniform sampler2D tex_samp; + +varying vec2 texcoord_var; + +void main(void) +{ + gl_FragColor = texture2D(tex_samp, texcoord_var); +} diff --git a/src/plugins/platforms/openkode/shaders/vert.glslv b/src/plugins/platforms/openkode/shaders/vert.glslv new file mode 100644 index 0000000..8a64f4d --- /dev/null +++ b/src/plugins/platforms/openkode/shaders/vert.glslv @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +uniform vec2 window; // window size + +// Per-vertex attributes] +attribute vec2 pos_attr; +attribute vec2 texcoord_attr; + +// Output vertex color +varying vec2 texcoord_var; + +void main() +{ + gl_Position = vec4( (2.0 * pos_attr / window -1.0) * vec2(1.0, -1.0), 0.0, 1.0); + texcoord_var = texcoord_attr; +} diff --git a/src/plugins/platforms/openvglite/main.cpp b/src/plugins/platforms/openvglite/main.cpp new file mode 100644 index 0000000..dc0b4a8 --- /dev/null +++ b/src/plugins/platforms/openvglite/main.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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 plugins 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 <private/qgraphicssystemplugin_p.h> +#include "qgraphicssystem_vglite.h" + +QT_BEGIN_NAMESPACE + +class QVGGraphicsSystemPlugin : public QGraphicsSystemPlugin +{ +public: + QStringList keys() const; + QGraphicsSystem *create(const QString&); +}; + +QStringList QVGGraphicsSystemPlugin::keys() const +{ + QStringList list; + list << "OpenVG"; + return list; +} + +QGraphicsSystem* QVGGraphicsSystemPlugin::create(const QString& system) +{ + if (system.toLower() == "openvg") + return new QVGLiteGraphicsSystem; + + return 0; +} + +Q_EXPORT_PLUGIN2(openvg, QVGGraphicsSystemPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/openvglite/openvglite.pro b/src/plugins/platforms/openvglite/openvglite.pro new file mode 100644 index 0000000..9d7860a --- /dev/null +++ b/src/plugins/platforms/openvglite/openvglite.pro @@ -0,0 +1,12 @@ +TARGET = qvglitegraphicssystem +include(../../qpluginbase.pri) + +QT += openvg + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems + +SOURCES = main.cpp qgraphicssystem_vglite.cpp qwindowsurface_vglite.cpp +HEADERS = qgraphicssystem_vglite.h qwindowsurface_vglite.h + +target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems +INSTALLS += target diff --git a/src/plugins/platforms/openvglite/qgraphicssystem_vglite.cpp b/src/plugins/platforms/openvglite/qgraphicssystem_vglite.cpp new file mode 100644 index 0000000..41b2303 --- /dev/null +++ b/src/plugins/platforms/openvglite/qgraphicssystem_vglite.cpp @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** 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 plugins 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 "qgraphicssystem_vglite.h" +#include "qwindowsurface_vglite.h" +#include <QtOpenVG/private/qpixmapdata_vg_p.h> +#include <QtGui/private/qegl_p.h> +#include <QtCore/qdebug.h> +#ifdef OPENVG_USBHP_INIT +extern "C" { +#include <linuxusbhp.h> +}; +#endif + +QT_BEGIN_NAMESPACE + +QVGLiteGraphicsSystem::QVGLiteGraphicsSystem() + : w(0), h(0), d(0), dw(0), dh(0), physWidth(0), physHeight(0), + surface(0), context(0), rootWindow(0), + screenFormat(QImage::Format_RGB16), preservedSwap(false) +{ +#ifdef OPENVG_USBHP_INIT + initLibrary(); +#endif + + // The graphics system is also the screen definition. + mScreens.append(this); + + QString displaySpec = QString::fromLatin1(qgetenv("QWS_DISPLAY")); + QStringList displayArgs = displaySpec.split(QLatin1Char(':')); + + // Initialize EGL and create the global EGL context. + context = qt_vg_create_context(0); + if (!context) { + qFatal("QVGLiteGraphicsSystem: could not initialize EGL"); + return; + } + + // Get the root window handle to use. Default to zero. + QRegExp winidRx(QLatin1String("winid=?(\\d+)")); + int winidIdx = displayArgs.indexOf(winidRx); + int handle = 0; + if (winidIdx >= 0) { + winidRx.exactMatch(displayArgs.at(winidIdx)); + handle = winidRx.cap(1).toInt(); + } + + // Create a full-screen window based on the native handle. + // If the context is premultiplied, the window should be too. + QEglProperties props; +#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT + EGLint surfaceType = 0; + if (context->configAttrib(EGL_SURFACE_TYPE, &surfaceType) && + (surfaceType & EGL_VG_ALPHA_FORMAT_PRE_BIT) != 0) + props.setValue(EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE); +#endif + rootWindow = eglCreateWindowSurface + (context->display(), context->config(), + (EGLNativeWindowType)handle, props.properties()); + if (rootWindow == EGL_NO_SURFACE) { + delete context; + context = 0; + qFatal("QVGLiteGraphicsSystem: could not create full-screen window"); + return; + } + + // Try to turn on preserved swap behaviour on the root window. + // This will allow us to optimize compositing to focus on just + // the screen region that has changed. Otherwise we must + // re-composite the entire screen every frame. +#if !defined(QVG_NO_PRESERVED_SWAP) + eglGetError(); // Clear error state first. + eglSurfaceAttrib(context->display(), rootWindow, + EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); + preservedSwap = (eglGetError() == EGL_SUCCESS); +#else + preservedSwap = false; +#endif + + // Fetch the root window properties. + eglQuerySurface(context->display(), rootWindow, EGL_WIDTH, &w); + eglQuerySurface(context->display(), rootWindow, EGL_HEIGHT, &h); + screenFormat = qt_vg_config_to_image_format(context); + switch (screenFormat) { + case QImage::Format_ARGB32_Premultiplied: + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + default: + d = 32; + break; + case QImage::Format_RGB16: + case QImage::Format_ARGB4444_Premultiplied: + d = 16; + break; + } + dw = w; + dh = h; + qDebug("screen size: %dx%dx%d", w, h, d); + + // Handle display physical size spec. From qscreenlinuxfb_qws.cpp. + QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)")); + int dimIdxW = displayArgs.indexOf(mmWidthRx); + QRegExp mmHeightRx(QLatin1String("mmHeight=?(\\d+)")); + int dimIdxH = displayArgs.indexOf(mmHeightRx); + if (dimIdxW >= 0) { + mmWidthRx.exactMatch(displayArgs.at(dimIdxW)); + physWidth = mmWidthRx.cap(1).toInt(); + if (dimIdxH < 0) + physHeight = dh*physWidth/dw; + } + if (dimIdxH >= 0) { + mmHeightRx.exactMatch(displayArgs.at(dimIdxH)); + physHeight = mmHeightRx.cap(1).toInt(); + if (dimIdxW < 0) + physWidth = dw*physHeight/dh; + } + if (dimIdxW < 0 && dimIdxH < 0) { + const int dpi = 72; + physWidth = qRound(dw * 25.4 / dpi); + physHeight = qRound(dh * 25.4 / dpi); + } +} + +QVGLiteGraphicsSystem::~QVGLiteGraphicsSystem() +{ +} + +QPixmapData *QVGLiteGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const +{ +#if !defined(QVGLite_NO_SINGLE_CONTEXT) && !defined(QVGLite_NO_PIXMAP_DATA) + // Pixmaps can use QVGLitePixmapData; bitmaps must use raster. + if (type == QPixmapData::PixmapType) + return new QVGPixmapData(type); + else + return new QRasterPixmapData(type); +#else + return new QRasterPixmapData(type); +#endif +} + +QWindowSurface *QVGLiteGraphicsSystem::createWindowSurface(QWidget *widget) const +{ + if (widget->windowType() == Qt::Desktop) + return 0; // Don't create an explicit window surface for the destkop. + if (surface) { + qWarning() << "QVGLiteGraphicsSystem: only one window surface " + "is supported at a time"; + return 0; + } + surface = new QVGLiteWindowSurface + (const_cast<QVGLiteGraphicsSystem *>(this), widget); + return surface; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/openvglite/qgraphicssystem_vglite.h b/src/plugins/platforms/openvglite/qgraphicssystem_vglite.h new file mode 100644 index 0000000..512793d --- /dev/null +++ b/src/plugins/platforms/openvglite/qgraphicssystem_vglite.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSYSTEM_VGLITE_H +#define QGRAPHICSSYSTEM_VGLITE_H + +#include <QtGui/private/qgraphicssystem_p.h> +#include <QtGui/private/qegl_p.h> +#include <QtGui/qimage.h> + +QT_BEGIN_NAMESPACE + +class QVGLiteWindowSurface; + +class QVGLiteGraphicsSystem : public QGraphicsSystem, + public QGraphicsSystemScreen +{ +public: + QVGLiteGraphicsSystem(); + ~QVGLiteGraphicsSystem(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QWindowSurface *createWindowSurface(QWidget *widget) const; + QList<QGraphicsSystemScreen *> screens() const { return mScreens; } + + QRect geometry() const { return QRect(0, 0, w, h); } + int depth() const { return d; } + QImage::Format format() const { return screenFormat; } + QSize physicalSize() const { return QSize(physWidth, physHeight); } + +private: + friend class QVGLiteWindowSurface; + + int w; + int h; + int d; + + int dw; + int dh; + + int physWidth; + int physHeight; + + mutable QVGLiteWindowSurface *surface; + QEglContext *context; + EGLSurface rootWindow; + QImage::Format screenFormat; + bool preservedSwap; + + QList<QGraphicsSystemScreen *> mScreens; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/openvglite/qwindowsurface_vglite.cpp b/src/plugins/platforms/openvglite/qwindowsurface_vglite.cpp new file mode 100644 index 0000000..c73e35a --- /dev/null +++ b/src/plugins/platforms/openvglite/qwindowsurface_vglite.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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 "qwindowsurface_vglite.h" +#include "qgraphicssystem_vglite.h" +#include <QtOpenVG/qvg.h> +#include <QtOpenVG/private/qvg_p.h> +#include <QtOpenVG/private/qpaintengine_vg_p.h> + +QT_BEGIN_NAMESPACE + +QVGLiteWindowSurface::QVGLiteWindowSurface + (QVGLiteGraphicsSystem *gs, QWidget *window) + : QWindowSurface(window), graphicsSystem(gs), + isPaintingActive(false), engine(0) +{ +} + +QVGLiteWindowSurface::~QVGLiteWindowSurface() +{ + graphicsSystem->surface = 0; + if (engine) + qt_vg_destroy_paint_engine(engine); +} + +QPaintDevice *QVGLiteWindowSurface::paintDevice() +{ + qt_vg_make_current(graphicsSystem->context, graphicsSystem->rootWindow); + isPaintingActive = true; + // TODO: clear the parts of the back buffer that are not + // covered by the window surface to black. + return this; +} + +void QVGLiteWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(region); + Q_UNUSED(offset); + QEglContext *context = graphicsSystem->context; + if (context) { + if (!isPaintingActive) + qt_vg_make_current(context, graphicsSystem->rootWindow); + context->swapBuffers(); + qt_vg_done_current(context); + context->setSurface(EGL_NO_SURFACE); + isPaintingActive = false; + } +} + +void QVGLiteWindowSurface::setGeometry(const QRect &rect) +{ + QWindowSurface::setGeometry(rect); +} + +bool QVGLiteWindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + return QWindowSurface::scroll(area, dx, dy); +} + +void QVGLiteWindowSurface::beginPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +void QVGLiteWindowSurface::endPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +QPaintEngine *QVGLiteWindowSurface::paintEngine() const +{ + if (!engine) + engine = qt_vg_create_paint_engine(); + return engine; +} + +// We need to get access to QWidget::metric() from QVGLiteWindowSurface::metric, +// but it is not a friend of QWidget. To get around this, we create a +// fake QX11PaintEngine class, which is a friend. +class QX11PaintEngine +{ +public: + static int metric(const QWidget *widget, QPaintDevice::PaintDeviceMetric met) + { + return widget->metric(met); + } +}; + +int QVGLiteWindowSurface::metric(PaintDeviceMetric met) const +{ + return QX11PaintEngine::metric(window(), met); +} diff --git a/src/plugins/platforms/openvglite/qwindowsurface_vglite.h b/src/plugins/platforms/openvglite/qwindowsurface_vglite.h new file mode 100644 index 0000000..59faba8 --- /dev/null +++ b/src/plugins/platforms/openvglite/qwindowsurface_vglite.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_VGLITE_H +#define QWINDOWSURFACE_VGLITE_H + +// +// 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. +// + +#include <QtGui/private/qwindowsurface_p.h> +#include <QtGui/private/qegl_p.h> + +QT_BEGIN_NAMESPACE + +class QVGLiteGraphicsSystem; +class QVGPaintEngine; + +class Q_OPENVG_EXPORT QVGLiteWindowSurface : public QWindowSurface, public QPaintDevice +{ +public: + QVGLiteWindowSurface(QVGLiteGraphicsSystem *gs, QWidget *window); + ~QVGLiteWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void setGeometry(const QRect &rect); + bool scroll(const QRegion &area, int dx, int dy); + + void beginPaint(const QRegion ®ion); + void endPaint(const QRegion ®ion); + + QPaintEngine *paintEngine() const; + +protected: + int metric(PaintDeviceMetric metric) const; + +private: + QVGLiteGraphicsSystem *graphicsSystem; + bool isPaintingActive; + mutable QVGPaintEngine *engine; +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSURFACE_VGLITE_H diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro new file mode 100644 index 0000000..26ccd44 --- /dev/null +++ b/src/plugins/platforms/platforms.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs + +SUBDIRS += minimal + diff --git a/src/plugins/platforms/qvfb/main.cpp b/src/plugins/platforms/qvfb/main.cpp new file mode 100644 index 0000000..997e544 --- /dev/null +++ b/src/plugins/platforms/qvfb/main.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 plugins 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 <QPlatformIntegrationPlugin> +#include "qvfbintegration.h" +#include <qstringlist.h> + +QT_BEGIN_NAMESPACE + +class QVFbIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QVFbIntegrationPlugin::keys() const +{ + QStringList list; + list << "QVFb"; + return list; +} + +QPlatformIntegration* QVFbIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "qvfb") + return new QVFbIntegration(paramList); + + return 0; +} + +Q_EXPORT_PLUGIN2(qvfb, QVFbIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/qvfb/qvfb.pro b/src/plugins/platforms/qvfb/qvfb.pro new file mode 100644 index 0000000..d2b332a --- /dev/null +++ b/src/plugins/platforms/qvfb/qvfb.pro @@ -0,0 +1,13 @@ +TARGET = qvfbintegration +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + + +SOURCES = main.cpp qvfbintegration.cpp qvfbwindowsurface.cpp +HEADERS = qvfbintegration.h qvfbwindowsurface.h + +include(../fontdatabases/genericunix/genericunix.pri) + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target diff --git a/src/plugins/platforms/qvfb/qvfbintegration.cpp b/src/plugins/platforms/qvfb/qvfbintegration.cpp new file mode 100644 index 0000000..0cc3938 --- /dev/null +++ b/src/plugins/platforms/qvfb/qvfbintegration.cpp @@ -0,0 +1,448 @@ +/**************************************************************************** +** +** 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 plugins 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 <stdlib.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <private/qcore_unix_p.h> // overrides QT_OPEN + +#include <qvfbhdr.h> +#include <qsocketnotifier.h> + +#include "qvfbintegration.h" +#include "qvfbwindowsurface.h" +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtCore/qdebug.h> +#include <QMouseEvent> + +#include <qsocketnotifier.h> +#include <QApplication> +#include <QWindowSystemInterface> + +#include "qgenericunixfontdatabase.h" + +QT_BEGIN_NAMESPACE + + +class QVFbScreenKeyboardHandler : public QObject +{ + Q_OBJECT +public: + QVFbScreenKeyboardHandler(int displayId); + ~QVFbScreenKeyboardHandler(); + +private slots: + void readKeyboardData(); + +private: + int kbdFD; + int kbdIdx; + int kbdBufferLen; + unsigned char *kbdBuffer; + QSocketNotifier *keyNotifier; +}; + +QVFbScreenKeyboardHandler::QVFbScreenKeyboardHandler(int displayId) +{ + const QString keyboardDev = QT_VFB_KEYBOARD_PIPE(displayId); + + + kbdFD = -1; + kbdIdx = 0; + kbdBufferLen = sizeof(QVFbKeyData) * 5; + kbdBuffer = new unsigned char [kbdBufferLen]; + + kbdFD = QT_OPEN(keyboardDev.toLatin1().constData(), O_RDWR | O_NDELAY); + + if (kbdFD == -1) { + perror("QVFbScreenKeyboardHandler"); + qWarning("QVFbScreenKeyboardHandler: Unable to open device %s", + qPrintable(keyboardDev)); + return; + } + + // Clear pending input + char buf[2]; + while (QT_READ(kbdFD, buf, 1) > 0) { } + + keyNotifier = new QSocketNotifier(kbdFD, QSocketNotifier::Read, this); + connect(keyNotifier, SIGNAL(activated(int)),this, SLOT(readKeyboardData())); + +} + +QVFbScreenKeyboardHandler::~QVFbScreenKeyboardHandler() +{ + if (kbdFD >= 0) + QT_CLOSE(kbdFD); + delete [] kbdBuffer; +} + + +void QVFbScreenKeyboardHandler::readKeyboardData() +{ + int n; + do { + n = QT_READ(kbdFD, kbdBuffer+kbdIdx, kbdBufferLen - kbdIdx); + if (n > 0) + kbdIdx += n; + } while (n > 0); + + int idx = 0; + while (kbdIdx - idx >= (int)sizeof(QVFbKeyData)) { + QVFbKeyData *kd = (QVFbKeyData *)(kbdBuffer + idx); + if (kd->unicode == 0 && kd->keycode == 0 && kd->modifiers == 0 && kd->press) { + // magic exit key + qWarning("Instructed to quit by Virtual Keyboard"); + qApp->quit(); + } + + //QWSServer::processKeyEvent(kd->unicode ? kd->unicode : 0xffff, kd->keycode, kd->modifiers, kd->press, kd->repeat); + + QEvent::Type type = kd->press ? QEvent::KeyPress : QEvent::KeyRelease; + + QString text; + if (kd->unicode && kd->unicode != 0xffff) + text += QChar(kd->unicode); + +// qDebug() << "readKeyboardData" << type << hex << kd->keycode << kd->modifiers << text; + + QWindowSystemInterface::handleKeyEvent(0, type, kd->keycode, kd->modifiers, text, kd->repeat, int(text.length())); + idx += sizeof(QVFbKeyData); + } + + int surplus = kbdIdx - idx; + for (int i = 0; i < surplus; i++) + kbdBuffer[i] = kbdBuffer[idx+i]; + kbdIdx = surplus; +} + + + + +class QVFbScreenMouseHandler : public QObject +{ + Q_OBJECT +public: + QVFbScreenMouseHandler(int displayId); + ~QVFbScreenMouseHandler(); + +private slots: + void readMouseData(); + +private: + int mouseFD; + int mouseIdx; + enum {mouseBufSize = 128}; + uchar mouseBuf[mouseBufSize]; + QSocketNotifier *mouseNotifier; + + int oldButtonState; +}; + +QVFbScreenMouseHandler::QVFbScreenMouseHandler(int displayId) +{ + QString mouseDev = QT_VFB_MOUSE_PIPE(displayId); + + mouseFD = QT_OPEN(mouseDev.toLatin1().constData(), O_RDWR | O_NDELAY); + + if (mouseFD == -1) { + perror("QVFbMouseHandler::QVFbMouseHandler"); + qWarning("QVFbMouseHander: Unable to open device %s", + qPrintable(mouseDev)); + return; + } + + // Clear pending input + char buf[2]; + while (QT_READ(mouseFD, buf, 1) > 0) { } + + mouseIdx = 0; + oldButtonState = 0; + mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read, this); + connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData())); +} + + +QVFbScreenMouseHandler::~QVFbScreenMouseHandler() +{ + if (mouseFD >= 0) + QT_CLOSE(mouseFD); +} + +void QVFbScreenMouseHandler::readMouseData() +{ + int n; + do { + n = QT_READ(mouseFD, mouseBuf+mouseIdx, mouseBufSize-mouseIdx); + if (n > 0) + mouseIdx += n; + } while (n > 0); + + int idx = 0; + static const int packetsize = sizeof(QPoint) + 2*sizeof(int); + while (mouseIdx-idx >= packetsize) { + uchar *mb = mouseBuf+idx; + QPoint mousePos = *reinterpret_cast<QPoint *>(mb); + mb += sizeof(QPoint); + int bstate = *reinterpret_cast<int *>(mb); + mb += sizeof(int); + //int wheel = *reinterpret_cast<int *>(mb); + + int button = bstate ^ oldButtonState; + QEvent::Type type = QEvent::MouseMove; + + if (button) { + type = (button & bstate) ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease; + } + QWindowSystemInterface::handleMouseEvent(0, mousePos, mousePos, Qt::MouseButtons(bstate)); + +// qDebug() << "readMouseData" << mousePos << button << bstate << oldButtonState << type; + + oldButtonState = bstate; + + idx += packetsize; + } + + int surplus = mouseIdx - idx; + for (int i = 0; i < surplus; i++) + mouseBuf[i] = mouseBuf[idx+i]; + mouseIdx = surplus; + +} + + +class QVFbScreenPrivate +{ +public: + QVFbScreenPrivate(int id) + : shmrgn(0), hdr(0), data(0), mouseHandler(0), keyboardHandler(0) + { + displayId = id; + connect(displayId); + } + + ~QVFbScreenPrivate() { disconnect(); } + void setDirty(const QRect &r); + + bool connect(int displayId); + void disconnect(); + + QImage *screenImage() { return &img; } + QSize screenSize() { return img.size(); } + + int depth() const { return img.depth(); } + QImage::Format format() const { return img.format(); } + +private: + unsigned char *shmrgn; + QVFbHeader *hdr; + uchar *data; + QVFbScreenMouseHandler *mouseHandler; + QVFbScreenKeyboardHandler *keyboardHandler; + int displayId; + + QImage img; +}; + + +void QVFbScreenPrivate::setDirty(const QRect &r) +{ + hdr->dirty = true; + hdr->update = hdr->update.united(r); +} + + +bool QVFbScreenPrivate::connect(int displayId) +{ + qDebug() << "QVFbScreenPrivate::connect" << displayId; + key_t key = ftok(QT_VFB_MOUSE_PIPE(displayId).toLatin1(), 'b'); + + if (key == -1) + return false; + + + int shmId = shmget(key, 0, 0); + if (shmId != -1) + shmrgn = (unsigned char *)shmat(shmId, 0, 0); + else + return false; + + if ((long)shmrgn == -1 || shmrgn == 0) { + qDebug("No shmrgn %ld", (long)shmrgn); + return false; + } + + hdr = (QVFbHeader *)shmrgn; + data = shmrgn + hdr->dataoffset; + + int w = hdr->width; + int h = hdr->height; + int d = hdr->depth; + int lstep = hdr->linestep; + + QImage::Format format = QImage::Format_Invalid; + if (d == 32) + format = QImage::Format_ARGB32_Premultiplied; + else if (d == 16) + format = QImage::Format_RGB16; + + + if (format == QImage::Format_Invalid) { + img = QImage(); + return false; + } + + img = QImage(data, w, h, lstep, format); + + qDebug("connected %dx%d %d bpp", w, h, d); + + + mouseHandler = new QVFbScreenMouseHandler(displayId); + keyboardHandler = new QVFbScreenKeyboardHandler(displayId); + return true; +} + +void QVFbScreenPrivate::disconnect() +{ + if ((long)shmrgn != -1 && shmrgn) { + shmdt((char*)shmrgn); + shmrgn = 0; + } + delete mouseHandler; + mouseHandler = 0; + delete keyboardHandler; + keyboardHandler = 0; +} + + +QVFbScreen::QVFbScreen(int id) +{ + d_ptr = new QVFbScreenPrivate(id); +} + + +QVFbScreen::~QVFbScreen() +{ + delete d_ptr; +} + +void QVFbScreen::setDirty(const QRect &rect) +{ + d_ptr->setDirty(rect); +} + + + +QRect QVFbScreen::geometry() const { + return QRect(QPoint(), d_ptr->screenSize()); +} + + +int QVFbScreen::depth() const +{ + return d_ptr->depth(); +} + +QImage::Format QVFbScreen::format() const +{ + return d_ptr->format(); +} + +QSize QVFbScreen::physicalSize() const { + return (d_ptr->screenSize()*254)/720; +} + +#if 0 +int QVFbScreen::linestep() const { + return d_ptr->screenImage() ? d_ptr->screenImage()->bytesPerLine() : 0; +} + +uchar *QVFbScreen::base() const { + return d_ptr->screenImage() ? d_ptr->screenImage()->bits() : 0; +} +#endif + +QImage *QVFbScreen::screenImage() +{ + return d_ptr->screenImage(); +} + +QVFbIntegration::QVFbIntegration(const QStringList ¶mList) + : mFontDb(new QGenericUnixFontDatabase()) +{ + int displayId = 0; + if (paramList.length() > 0) + displayId = paramList.at(0).toInt(); + + mPrimaryScreen = new QVFbScreen(displayId); + + mScreens.append(mPrimaryScreen); +} + +QPixmapData *QVFbIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QWindowSurface *QVFbIntegration::createWindowSurface(QWidget *widget, WId) const +{ + return new QVFbWindowSurface(mPrimaryScreen, widget); +} + + +QPlatformWindow *QVFbIntegration::createPlatformWindow(QWidget *widget, WId) const +{ + return new QVFbWindow(mPrimaryScreen, widget); +} + +QPlatformFontDatabase *QVFbIntegration::fontDatabase() const +{ + return mFontDb; +} + +QT_END_NAMESPACE + +#include "qvfbintegration.moc" diff --git a/src/plugins/platforms/qvfb/qvfbintegration.h b/src/plugins/platforms/qvfb/qvfbintegration.h new file mode 100644 index 0000000..198a45c --- /dev/null +++ b/src/plugins/platforms/qvfb/qvfbintegration.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSYSTEM_QVFB_H +#define QGRAPHICSSYSTEM_QVFB_H + +#include <QPlatformScreen> +#include <QPlatformIntegration> + +QT_BEGIN_NAMESPACE + + +class QVFbScreenPrivate; + +class QVFbScreen : public QPlatformScreen +{ +public: + QVFbScreen(int id); + ~QVFbScreen(); + + QRect geometry() const; + int depth() const; + QImage::Format format() const; + QSize physicalSize() const; + + QImage *screenImage(); + + void setDirty(const QRect &rect); + +public: + + QVFbScreenPrivate *d_ptr; +}; + +class QVFbIntegrationPrivate; + + +class QVFbIntegration : public QPlatformIntegration +{ +public: + QVFbIntegration(const QStringList ¶mList); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QList<QPlatformScreen *> screens() const { return mScreens; } + + QPlatformFontDatabase *fontDatabase() const; + +private: + QVFbScreen *mPrimaryScreen; + QList<QPlatformScreen *> mScreens; + QPlatformFontDatabase *mFontDb; +}; + + + +QT_END_NAMESPACE + + +#endif diff --git a/src/plugins/platforms/qvfb/qvfbwindowsurface.cpp b/src/plugins/platforms/qvfb/qvfbwindowsurface.cpp new file mode 100644 index 0000000..6699072 --- /dev/null +++ b/src/plugins/platforms/qvfb/qvfbwindowsurface.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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 "qvfbwindowsurface.h" +#include "qvfbintegration.h" +#include <QtCore/qdebug.h> +#include <QtGui/qpainter.h> +#include <private/qapplication_p.h> + +QT_BEGIN_NAMESPACE + +QVFbWindowSurface::QVFbWindowSurface(//QVFbIntegration *graphicsSystem, + QVFbScreen *screen, QWidget *window) + : QWindowSurface(window), + mScreen(screen) +{ +} + +QVFbWindowSurface::~QVFbWindowSurface() +{ +} + +QPaintDevice *QVFbWindowSurface::paintDevice() +{ + return mScreen->screenImage(); +} + +void QVFbWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(offset); + +// QRect rect = geometry(); +// QPoint topLeft = rect.topLeft(); + + mScreen->setDirty(region.boundingRect()); +} + +void QVFbWindowSurface::resize(const QSize&) +{ + +// any size you like as long as it's full-screen... + + QRect rect(mScreen->availableGeometry()); + QWindowSurface::resize(rect.size()); +} + + +QVFbWindow::QVFbWindow(QVFbScreen *screen, QWidget *window) + : QPlatformWindow(window), + mScreen(screen) +{ +} + + +void QVFbWindow::setGeometry(const QRect &) +{ + +// any size you like as long as it's full-screen... + + QRect rect(mScreen->availableGeometry()); + QWindowSystemInterface::handleGeometryChange(this->widget(), rect); + + QPlatformWindow::setGeometry(rect); +} + + + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/qvfb/qvfbwindowsurface.h b/src/plugins/platforms/qvfb/qvfbwindowsurface.h new file mode 100644 index 0000000..9228189 --- /dev/null +++ b/src/plugins/platforms/qvfb/qvfbwindowsurface.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_QVFB_H +#define QWINDOWSURFACE_QVFB_H + +#include <QtGui/private/qwindowsurface_p.h> +#include <QPlatformWindow> + +QT_BEGIN_NAMESPACE + +class QVFbIntegration; +class QVFbScreen; + +class QVFbWindowSurface : public QWindowSurface +{ +public: + QVFbWindowSurface(QVFbScreen *screen, QWidget *window); + ~QVFbWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); + +private: + QVFbScreen *mScreen; +}; + +class QVFbWindow : public QPlatformWindow +{ +public: + QVFbWindow(QVFbScreen *screen, QWidget *window); + void setGeometry(const QRect &rect); + +private: + QVFbScreen *mScreen; +}; + + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/testlite/main.cpp b/src/plugins/platforms/testlite/main.cpp new file mode 100644 index 0000000..2f6aa8b --- /dev/null +++ b/src/plugins/platforms/testlite/main.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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 plugins 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 <QtGui/QPlatformIntegrationPlugin> +#include "qtestliteintegration.h" + +QT_BEGIN_NAMESPACE + +class QTestLiteIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QTestLiteIntegrationPlugin::keys() const +{ + QStringList list; + list << "TestLite"; +#ifndef QT_NO_OPENGL + list << "TestLiteGL"; +#endif + return list; +} + +QPlatformIntegration* QTestLiteIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "testlite") + return new QTestLiteIntegration; +#ifndef QT_NO_OPENGL + if (system.toLower() == "testlitegl") + return new QTestLiteIntegration(true); +#endif + + return 0; +} + +Q_EXPORT_PLUGIN2(testlite, QTestLiteIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qglxintegration.cpp b/src/plugins/platforms/testlite/qglxintegration.cpp new file mode 100644 index 0000000..e262d5b --- /dev/null +++ b/src/plugins/platforms/testlite/qglxintegration.cpp @@ -0,0 +1,370 @@ +/**************************************************************************** +** +** 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 plugins 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 <QDebug> +#include <QLibrary> +#include <QGLFormat> + +#include "qtestlitewindow.h" + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <GL/glx.h> + +#include "qglxintegration.h" + +#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) +#include <dlfcn.h> +#endif + +QT_BEGIN_NAMESPACE + +QMutex QGLXGLContext::m_defaultSharedContextMutex(QMutex::Recursive); + +QVector<int> QGLXGLContext::buildSpec(const QPlatformWindowFormat &format) +{ + QVector<int> spec(48); + int i = 0; + + spec[i++] = GLX_LEVEL; + spec[i++] = 0; + spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = GLX_WINDOW_BIT; + + if (format.rgba()) { + spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_RGBA_BIT; + spec[i++] = GLX_RED_SIZE; spec[i++] = (format.redBufferSize() == -1) ? 1 : format.redBufferSize(); + spec[i++] = GLX_GREEN_SIZE; spec[i++] = (format.greenBufferSize() == -1) ? 1 : format.greenBufferSize(); + spec[i++] = GLX_BLUE_SIZE; spec[i++] = (format.blueBufferSize() == -1) ? 1 : format.blueBufferSize(); + if (format.alpha()) { + spec[i++] = GLX_ALPHA_SIZE; spec[i++] = (format.alphaBufferSize() == -1) ? 1 : format.alphaBufferSize(); + } + + spec[i++] = GLX_ACCUM_RED_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); + spec[i++] = GLX_ACCUM_GREEN_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); + spec[i++] = GLX_ACCUM_BLUE_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); + + if (format.alpha()) { + spec[i++] = GLX_ACCUM_ALPHA_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); + } + + } else { + spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_COLOR_INDEX_BIT; //I'm really not sure if this works.... + spec[i++] = GLX_BUFFER_SIZE; spec[i++] = 8; + } + + spec[i++] = GLX_DOUBLEBUFFER; spec[i++] = format.doubleBuffer() ? True : False; + spec[i++] = GLX_STEREO; spec[i++] = format.stereo() ? True : False; + + if (format.depth()) { + spec[i++] = GLX_DEPTH_SIZE; spec[i++] = (format.depthBufferSize() == -1) ? 1 : format.depthBufferSize(); + } + + if (format.stencil()) { + spec[i++] = GLX_STENCIL_SIZE; spec[i++] = (format.stencilBufferSize() == -1) ? 1 : format.stencilBufferSize(); + } + if (format.sampleBuffers()) { + spec[i++] = GLX_SAMPLE_BUFFERS_ARB; + spec[i++] = 1; + spec[i++] = GLX_SAMPLES_ARB; + spec[i++] = format.samples() == -1 ? 4 : format.samples(); + } + + spec[i++] = XNone; + return spec; +} + +GLXFBConfig QGLXGLContext::findConfig(const MyDisplay *xd, const QPlatformWindowFormat &format) +{ + bool reduced = true; + GLXFBConfig chosenConfig = 0; + QPlatformWindowFormat reducedFormat = format; + while (!chosenConfig && reduced) { + QVector<int> spec = buildSpec(reducedFormat); + int confcount = 0; + GLXFBConfig *configs; + configs = glXChooseFBConfig(xd->display,xd->screen,spec.constData(),&confcount); + if (confcount) + { + for (int i = 0; i < confcount; i++) { + chosenConfig = configs[i]; + // Make sure we try to get an ARGB visual if the format asked for an alpha: + if (reducedFormat.alpha()) { + int alphaSize; + glXGetFBConfigAttrib(xd->display,configs[i],GLX_ALPHA_SIZE,&alphaSize); + if (alphaSize > 0) + break; + } else { + break; // Just choose the first in the list if there's no alpha requested + } + } + + XFree(configs); + } + reducedFormat = reducePlatformWindowFormat(reducedFormat,&reduced); + } + + if (!chosenConfig) + qWarning("Warning no context created"); + + return chosenConfig; +} + +XVisualInfo *QGLXGLContext::findVisualInfo(const MyDisplay *xd, const QPlatformWindowFormat &format) +{ + GLXFBConfig config = QGLXGLContext::findConfig(xd,format); + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(xd->display,config); + return visualInfo; +} + +QPlatformWindowFormat QGLXGLContext::platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext ctx) +{ + QPlatformWindowFormat format; + int redSize = 0; + int greenSize = 0; + int blueSize = 0; + int alphaSize = 0; + int depthSize = 0; + int stencilSize = 0; + int sampleBuffers = 0; + int sampleCount = 0; + int level = 0; + int rgba = 0; + int stereo = 0; + int accumSizeA = 0; + int accumSizeR = 0; + int accumSizeG = 0; + int accumSizeB = 0; + + XVisualInfo *vi = glXGetVisualFromFBConfig(display,config); + glXGetConfig(display,vi,GLX_RGBA,&rgba); + XFree(vi); + glXGetFBConfigAttrib(display, config, GLX_RED_SIZE, &redSize); + glXGetFBConfigAttrib(display, config, GLX_GREEN_SIZE, &greenSize); + glXGetFBConfigAttrib(display, config, GLX_BLUE_SIZE, &blueSize); + glXGetFBConfigAttrib(display, config, GLX_ALPHA_SIZE, &alphaSize); + glXGetFBConfigAttrib(display, config, GLX_DEPTH_SIZE, &depthSize); + glXGetFBConfigAttrib(display, config, GLX_STENCIL_SIZE, &stencilSize); + glXGetFBConfigAttrib(display, config, GLX_SAMPLES, &sampleBuffers); + glXGetFBConfigAttrib(display, config, GLX_LEVEL, &level); + glXGetFBConfigAttrib(display, config, GLX_STEREO, &stereo); + glXGetFBConfigAttrib(display, config, GLX_ACCUM_ALPHA_SIZE, &accumSizeA); + glXGetFBConfigAttrib(display, config, GLX_ACCUM_RED_SIZE, &accumSizeR); + glXGetFBConfigAttrib(display, config, GLX_ACCUM_GREEN_SIZE, &accumSizeG); + glXGetFBConfigAttrib(display, config, GLX_ACCUM_BLUE_SIZE, &accumSizeB); + + format.setRedBufferSize(redSize); + format.setGreenBufferSize(greenSize); + format.setBlueBufferSize(blueSize); + format.setAlphaBufferSize(alphaSize); + format.setDepthBufferSize(depthSize); + format.setStencilBufferSize(stencilSize); + format.setSampleBuffers(sampleBuffers); + if (format.sampleBuffers()) { + glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleCount); + format.setSamples(sampleCount); + } + + format.setDirectRendering(glXIsDirect(display, ctx)); + format.setRgba(rgba); + format.setStereo(stereo); + format.setAccumBufferSize(accumSizeB); + + return format; +} + +QPlatformWindowFormat QGLXGLContext::reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced) +{ + QPlatformWindowFormat retFormat = format; + *reduced = true; + + if (retFormat.sampleBuffers()) { + retFormat.setSampleBuffers(false); + } else if (retFormat.stereo()) { + retFormat.setStereo(false); + } else if (retFormat.accum()) { + retFormat.setAccum(false); + }else if (retFormat.stencil()) { + retFormat.setStencil(false); + }else if (retFormat.alpha()) { + retFormat.setAlpha(false); + }else if (retFormat.depth()) { + retFormat.setDepth(false); + }else if (retFormat.doubleBuffer()) { + retFormat.setDoubleBuffer(false); + }else{ + *reduced = false; + } + return retFormat; +} + +QGLXGLContext::QGLXGLContext(Window window, MyDisplay *xd, const QPlatformWindowFormat &format) + : QPlatformGLContext() + , m_xd(xd) + , m_drawable((Drawable)window) + , m_context(0) +{ + + QPlatformGLContext *sharePlatformContext; + if (format.useDefaultSharedContext()) { + if (!QPlatformGLContext::defaultSharedContext()) { + if (m_defaultSharedContextMutex.tryLock()){ + createDefaultSharedContex(xd); + m_defaultSharedContextMutex.unlock(); + } else { + m_defaultSharedContextMutex.lock(); //wait to the the shared context is created + m_defaultSharedContextMutex.unlock(); + } + } + sharePlatformContext = QPlatformGLContext::defaultSharedContext(); + } else { + sharePlatformContext = format.sharedGLContext(); + } + GLXContext shareGlxContext = 0; + if (sharePlatformContext) + shareGlxContext = static_cast<QGLXGLContext*>(sharePlatformContext)->glxContext(); + + GLXFBConfig config = findConfig(xd,format); + m_context = glXCreateNewContext(xd->display,config,GLX_RGBA_TYPE,shareGlxContext,TRUE); + m_windowFormat = QGLXGLContext::platformWindowFromGLXFBConfig(xd->display,config,m_context); + +#ifdef MYX11_DEBUG + qDebug() << "QGLXGLContext::create context" << m_context; +#endif +} + +QGLXGLContext::QGLXGLContext(MyDisplay *display, Drawable drawable, GLXContext context) + : QPlatformGLContext(), m_xd(display), m_drawable(drawable), m_context(context) +{ + +} + +QGLXGLContext::~QGLXGLContext() +{ + if (m_context) { + qDebug("Destroying GLX context 0x%p", m_context); + glXDestroyContext(m_xd->display, m_context); + } +} + +void QGLXGLContext::createDefaultSharedContex(MyDisplay *xd) +{ + int x = 0; + int y = 0; + int w = 3; + int h = 3; + + QPlatformWindowFormat format = QPlatformWindowFormat::defaultFormat(); + GLXContext context; + GLXFBConfig config = findConfig(xd,format); + if (config) { + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(xd->display,config); + Colormap cmap = XCreateColormap(xd->display,xd->rootWindow(),visualInfo->visual,AllocNone); + XSetWindowAttributes a; + a.colormap = cmap; + Window sharedWindow = XCreateWindow(xd->display, xd->rootWindow(),x, y, w, h, + 0, visualInfo->depth, InputOutput, visualInfo->visual, + CWColormap, &a); + + context = glXCreateNewContext(xd->display,config,GLX_RGBA_TYPE,0,TRUE); + QPlatformGLContext *sharedContext = new QGLXGLContext(xd,sharedWindow,context); + QPlatformGLContext::setDefaultSharedContext(sharedContext); + } else { + qWarning("Warning no shared context created"); + } +} + +void QGLXGLContext::makeCurrent() +{ +#ifdef MYX11_DEBUG + qDebug("QGLXGLContext::makeCurrent(window=0x%x, ctx=0x%x)", m_drawable, m_context); +#endif + glXMakeCurrent(m_xd->display, m_drawable, m_context); +} + +void QGLXGLContext::doneCurrent() +{ + glXMakeCurrent(m_xd->display, 0, 0); +} + +void QGLXGLContext::swapBuffers() +{ + glXSwapBuffers(m_xd->display, m_drawable); +} + +void* QGLXGLContext::getProcAddress(const QString& procName) +{ + typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *); + static qt_glXGetProcAddressARB glXGetProcAddressARB = 0; + static bool resolved = false; + + if (resolved && !glXGetProcAddressARB) + return 0; + if (!glXGetProcAddressARB) { + QList<QByteArray> glxExt = QByteArray(glXGetClientString(m_xd->display, GLX_EXTENSIONS)).split(' '); + if (glxExt.contains("GLX_ARB_get_proc_address")) { +#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) + void *handle = dlopen(NULL, RTLD_LAZY); + if (handle) { + glXGetProcAddressARB = (qt_glXGetProcAddressARB) dlsym(handle, "glXGetProcAddressARB"); + dlclose(handle); + } + if (!glXGetProcAddressARB) +#endif + { + extern const QString qt_gl_library_name(); +// QLibrary lib(qt_gl_library_name()); + QLibrary lib(QLatin1String("GL")); + glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB"); + } + } + resolved = true; + } + if (!glXGetProcAddressARB) + return 0; + return glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(procName.toLatin1().data())); +} + +QPlatformWindowFormat QGLXGLContext::platformWindowFormat() const +{ + return m_windowFormat; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qglxintegration.h b/src/plugins/platforms/testlite/qglxintegration.h new file mode 100644 index 0000000..479be4b --- /dev/null +++ b/src/plugins/platforms/testlite/qglxintegration.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef Q_GLX_CONTEXT_H +#define Q_GLX_CONTEXT_H + +#include "qtestlitewindow.h" + +#include <QtGui/QPlatformGLContext> +#include <QtGui/QPlatformWindowFormat> + +#include <QtCore/QMutex> + +#include <GL/glx.h> + +QT_BEGIN_NAMESPACE + +class MyDisplay; + +class QGLXGLContext : public QPlatformGLContext +{ +public: + QGLXGLContext(Window window, MyDisplay *xd, const QPlatformWindowFormat &format); + ~QGLXGLContext(); + + virtual void makeCurrent(); + virtual void doneCurrent(); + virtual void swapBuffers(); + virtual void* getProcAddress(const QString& procName); + + GLXContext glxContext() {return m_context;} + + QPlatformWindowFormat platformWindowFormat() const; + + static XVisualInfo *findVisualInfo(const MyDisplay *xd, const QPlatformWindowFormat &format); +private: + static GLXFBConfig findConfig(const MyDisplay *xd,const QPlatformWindowFormat &format); + static QVector<int> buildSpec(const QPlatformWindowFormat &format); + static QPlatformWindowFormat platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext context); + static QPlatformWindowFormat reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced); + + + MyDisplay *m_xd; + Drawable m_drawable; + GLXContext m_context; + QPlatformWindowFormat m_windowFormat; + + QGLXGLContext (MyDisplay *display, Drawable drawable, GLXContext context); + static QMutex m_defaultSharedContextMutex; + static void createDefaultSharedContex(MyDisplay *xd); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/testlite/qtestliteintegration.cpp b/src/plugins/platforms/testlite/qtestliteintegration.cpp new file mode 100644 index 0000000..68e9051 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestliteintegration.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** 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 plugins 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 "qtestliteintegration.h" +#include "qtestlitewindowsurface.h" +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtCore/qdebug.h> + +#include <QPlatformCursor> + +#include "qtestlitewindow.h" +#include "qgenericunixfontdatabase.h" + +#ifndef QT_NO_OPENGL +#include <GL/glx.h> +#include <private/qwindowsurface_gl_p.h> +#include <private/qpixmapdata_gl_p.h> +#endif //QT_NO_OPENGL + +QT_BEGIN_NAMESPACE + +class MyCursor : QPlatformCursor +{ +public: + MyCursor(QPlatformScreen *screen) : QPlatformCursor(screen) {} + + void changeCursor(QCursor * cursor, QWidget * widget) { + QTestLiteWindow *w = 0; + if (widget) { + QWidget *window = widget->window(); + w = static_cast<QTestLiteWindow*>(window->platformWindow()); + } else { + // No X11 cursor control when there is no widget under the cursor + return; + } + + //qDebug() << "changeCursor" << widget << ws; + if (!w) + return; + + w->setCursor(cursor); + } +}; + + +QTestLiteIntegration::QTestLiteIntegration(bool useOpenGL) + : mUseOpenGL(useOpenGL) + , mFontDb(new QGenericUnixFontDatabase()) +{ + xd = new MyDisplay; + + mPrimaryScreen = new QTestLiteScreen(); + + mPrimaryScreen->mGeometry = QRect + (0, 0, xd->width, xd->height); + mPrimaryScreen->mDepth = 32; + mPrimaryScreen->mFormat = QImage::Format_RGB32; + mPrimaryScreen->mPhysicalSize = + QSize(xd->physicalWidth, xd->physicalHeight); + + mScreens.append(mPrimaryScreen); + + + (void)new MyCursor(mPrimaryScreen); + +} + +QPixmapData *QTestLiteIntegration::createPixmapData(QPixmapData::PixelType type) const +{ +#ifndef QT_NO_OPENGL + if (mUseOpenGL) + return new QGLPixmapData(type); +#endif + return new QRasterPixmapData(type); +} + +QWindowSurface *QTestLiteIntegration::createWindowSurface(QWidget *widget, WId) const +{ +#ifndef QT_NO_OPENGL + if (mUseOpenGL) + return new QGLWindowSurface(widget); +#endif + return new QTestLiteWindowSurface(mPrimaryScreen, widget); +} + + +QPlatformWindow *QTestLiteIntegration::createPlatformWindow(QWidget *widget, WId /*winId*/) const +{ + return new QTestLiteWindow(this, mPrimaryScreen, widget); +} + + + +QPixmap QTestLiteIntegration::grabWindow(WId window, int x, int y, int width, int height) const +{ + QImage img = xd->grabWindow(window, x, y, width, height); + return QPixmap::fromImage(img); +} + +QPlatformFontDatabase *QTestLiteIntegration::fontDatabase() const +{ + return mFontDb; +} + +bool QTestLiteIntegration::hasOpenGL() const +{ +#ifndef QT_NO_OPENGL + return glXQueryExtension(xd->display, 0, 0) != 0; +#endif + return false; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestliteintegration.h b/src/plugins/platforms/testlite/qtestliteintegration.h new file mode 100644 index 0000000..8286ef0 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestliteintegration.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSYSTEM_TESTLITE_H +#define QGRAPHICSSYSTEM_TESTLITE_H + +#include <QtGui/QPlatformIntegration> +#include <QtGui/QPlatformScreen> + +//make sure textstream is included before any X11 headers +#include <QtCore/QTextStream> + +QT_BEGIN_NAMESPACE + +class MyDisplay; + +class QTestLiteScreen : public QPlatformScreen +{ +public: + QTestLiteScreen() + : mDepth(16), mFormat(QImage::Format_RGB16) {} + ~QTestLiteScreen() {} + + QRect geometry() const { return mGeometry; } + int depth() const { return mDepth; } + QImage::Format format() const { return mFormat; } + QSize physicalSize() const { return mPhysicalSize; } + +public: + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + QSize mPhysicalSize; +}; + +class QTestLiteIntegration : public QPlatformIntegration +{ +public: + QTestLiteIntegration(bool useOpenGL = false); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QPixmap grabWindow(WId window, int x, int y, int width, int height) const; + + QList<QPlatformScreen *> screens() const { return mScreens; } + + QPlatformFontDatabase *fontDatabase() const; + + bool hasOpenGL() const; + + MyDisplay *xd; + +private: + bool mUseOpenGL; + QTestLiteScreen *mPrimaryScreen; + QList<QPlatformScreen *> mScreens; + QPlatformFontDatabase *mFontDb; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/testlite/qtestlitewindow.cpp b/src/plugins/platforms/testlite/qtestlitewindow.cpp new file mode 100644 index 0000000..1de4b9d --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitewindow.cpp @@ -0,0 +1,1587 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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 "qtestliteintegration.h" +#include <QWindowSystemInterface> +#include <private/qwindowsurface_p.h> +#include <QtGui/private/qapplication_p.h> + +#include "qtestlitewindow.h" + +#include <QBitmap> +#include <QCursor> +#include <QDateTime> +#include <QPixmap> +#include <QImage> +#include <QSocketNotifier> + +#include <qdebug.h> +#include <QTimer> +#include <QApplication> + +#ifndef QT_NO_OPENGL +#include "qglxintegration.h" +#endif + +#include <stdio.h> +#include <stdlib.h> + + +#include <X11/Xatom.h> + +#include <X11/cursorfont.h> + + + +//### remove stuff we don't want from qt_x11_p.h +#undef ATOM +#undef X11 + +//#define MYX11_DEBUG + +QT_BEGIN_NAMESPACE + +static int (*original_x_errhandler)(Display *dpy, XErrorEvent *); +static bool seen_badwindow; + + +static Atom wmProtocolsAtom; +static Atom wmDeleteWindowAtom; + +class MyX11CursorNode +{ +public: + MyX11CursorNode(int id, Cursor c) { idValue = id; cursorValue = c; refCount = 1; } + QDateTime expiration() { return t; } + void setExpiration(QDateTime val) { t = val; } + MyX11CursorNode * ante() { return before; } + void setAnte(MyX11CursorNode *node) { before = node; } + MyX11CursorNode * post() { return after; } + void setPost(MyX11CursorNode *node) { after = node; } + Cursor cursor() { return cursorValue; } + int id() { return idValue; } + unsigned int refCount; + +private: + MyX11CursorNode *before; + MyX11CursorNode *after; + QDateTime t; + Cursor cursorValue; + int idValue; + + Display * display; +}; + + + + + +class MyX11Cursors : public QObject +{ + Q_OBJECT +public: + MyX11Cursors(Display * d); + ~MyX11Cursors() { timer.stop(); } + void incrementUseCount(int id); + void decrementUseCount(int id); + void createNode(int id, Cursor c); + bool exists(int id) { return lookupMap.contains(id); } + Cursor cursor(int id); +public slots: + void timeout(); + +private: + void removeNode(MyX11CursorNode *node); + void insertNode(MyX11CursorNode *node); + + // linked list of cursors currently not assigned to any window + MyX11CursorNode *firstExpired; + MyX11CursorNode *lastExpired; + + QHash<int, MyX11CursorNode *> lookupMap; + QTimer timer; + + Display *display; + + int removalDelay; +}; + + + + + +QTestLiteWindow::QTestLiteWindow(const QTestLiteIntegration *platformIntegration, + QTestLiteScreen */*screen*/, QWidget *window) + :QPlatformWindow(window), mGLContext(0) +{ + xd = platformIntegration->xd; + xd->windowList.append(this); + { + int x = window->x(); + int y = window->y(); + int w = window->width(); + int h = window->height(); + + if(window->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL + && QApplicationPrivate::platformIntegration()->hasOpenGL() ) { +#ifndef QT_NO_OPENGL + XVisualInfo *visualInfo = QGLXGLContext::findVisualInfo(xd,window->platformWindowFormat()); + Colormap cmap = XCreateColormap(xd->display,xd->rootWindow(),visualInfo->visual,AllocNone); + + XSetWindowAttributes a; + a.colormap = cmap; + x_window = XCreateWindow(xd->display, xd->rootWindow(),x, y, w, h, + 0, visualInfo->depth, InputOutput, visualInfo->visual, + CWColormap, &a); +#endif //QT_NO_OPENGL + } else { + x_window = XCreateSimpleWindow(xd->display, xd->rootWindow(), + x, y, w, h, 0 /*border_width*/, + xd->blackPixel(), xd->whitePixel()); + } + +#ifdef MYX11_DEBUG + qDebug() << "QTestLiteWindow::QTestLiteWindow creating" << hex << x_window << window; +#endif + } + + width = -1; + height = -1; + xpos = -1; + ypos = -1; + + XSetWindowBackgroundPixmap(xd->display, x_window, XNone); + + XSelectInput(xd->display, x_window, ExposureMask | KeyPressMask | KeyReleaseMask | + EnterWindowMask | LeaveWindowMask | FocusChangeMask | + PointerMotionMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | + StructureNotifyMask); + + gc = createGC(); + + XChangeProperty (xd->display, x_window, + wmProtocolsAtom, + XA_ATOM, 32, PropModeAppend, + (unsigned char *) &wmDeleteWindowAtom, 1); + currentCursor = -1; +} + + +QTestLiteWindow::~QTestLiteWindow() +{ +#ifdef MYX11_DEBUG + qDebug() << "~QTestLiteWindow" << hex << x_window; +#endif + delete mGLContext; + XFreeGC(xd->display, gc); + XDestroyWindow(xd->display, x_window); + + xd->windowList.removeAll(this); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Mouse event stuff + + + + +static Qt::MouseButtons translateMouseButtons(int s) +{ + Qt::MouseButtons ret = 0; + if (s & Button1Mask) + ret |= Qt::LeftButton; + if (s & Button2Mask) + ret |= Qt::MidButton; + if (s & Button3Mask) + ret |= Qt::RightButton; + return ret; +} + + +static Qt::KeyboardModifiers translateModifiers(int s) +{ + const uchar qt_alt_mask = Mod1Mask; + const uchar qt_meta_mask = Mod4Mask; + + + Qt::KeyboardModifiers ret = 0; + if (s & ShiftMask) + ret |= Qt::ShiftModifier; + if (s & ControlMask) + ret |= Qt::ControlModifier; + if (s & qt_alt_mask) + ret |= Qt::AltModifier; + if (s & qt_meta_mask) + ret |= Qt::MetaModifier; +#if 0 + if (s & qt_mode_switch_mask) + ret |= Qt::GroupSwitchModifier; +#endif + return ret; +} + +void QTestLiteWindow::handleMouseEvent(QEvent::Type type, XButtonEvent *e) +{ + static QPoint mousePoint; + + Qt::MouseButton button = Qt::NoButton; + Qt::MouseButtons buttons = translateMouseButtons(e->state); + Qt::KeyboardModifiers modifiers = translateModifiers(e->state); + if (type != QEvent::MouseMove) { + switch (e->button) { + case Button1: button = Qt::LeftButton; break; + case Button2: button = Qt::MidButton; break; + case Button3: button = Qt::RightButton; break; + case Button4: + case Button5: + case 6: + case 7: { + //mouse wheel + if (type == QEvent::MouseButtonPress) { + //logic borrowed from qapplication_x11.cpp + int delta = 120 * ((e->button == Button4 || e->button == 6) ? 1 : -1); + bool hor = (((e->button == Button4 || e->button == Button5) + && (modifiers & Qt::AltModifier)) + || (e->button == 6 || e->button == 7)); + QWindowSystemInterface::handleWheelEvent(widget(), e->time, + QPoint(e->x, e->y), + QPoint(e->x_root, e->y_root), + delta, hor ? Qt::Horizontal : Qt::Vertical); + } + return; + } + default: break; + } + } + + buttons ^= button; // X event uses state *before*, Qt uses state *after* + + QWindowSystemInterface::handleMouseEvent(widget(), e->time, QPoint(e->x, e->y), + QPoint(e->x_root, e->y_root), + buttons); + + mousePoint = QPoint(e->x_root, e->y_root); +} + +void QTestLiteWindow::handleCloseEvent() +{ + QWindowSystemInterface::handleCloseEvent(widget()); +} + + +void QTestLiteWindow::handleEnterEvent() +{ + QWindowSystemInterface::handleEnterEvent(widget()); +} + +void QTestLiteWindow::handleLeaveEvent() +{ + QWindowSystemInterface::handleLeaveEvent(widget()); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Key event stuff -- not pretty either +// +// What we want to do is to port Robert's keytable code properly + +// keyboard mapping table +static const unsigned int keyTbl[] = { + + // misc keys + + XK_Escape, Qt::Key_Escape, + XK_Tab, Qt::Key_Tab, + XK_ISO_Left_Tab, Qt::Key_Backtab, + XK_BackSpace, Qt::Key_Backspace, + XK_Return, Qt::Key_Return, + XK_Insert, Qt::Key_Insert, + XK_Delete, Qt::Key_Delete, + XK_Clear, Qt::Key_Delete, + XK_Pause, Qt::Key_Pause, + XK_Print, Qt::Key_Print, + 0x1005FF60, Qt::Key_SysReq, // hardcoded Sun SysReq + 0x1007ff00, Qt::Key_SysReq, // hardcoded X386 SysReq + + // cursor movement + + XK_Home, Qt::Key_Home, + XK_End, Qt::Key_End, + XK_Left, Qt::Key_Left, + XK_Up, Qt::Key_Up, + XK_Right, Qt::Key_Right, + XK_Down, Qt::Key_Down, + XK_Prior, Qt::Key_PageUp, + XK_Next, Qt::Key_PageDown, + + // modifiers + + XK_Shift_L, Qt::Key_Shift, + XK_Shift_R, Qt::Key_Shift, + XK_Shift_Lock, Qt::Key_Shift, + XK_Control_L, Qt::Key_Control, + XK_Control_R, Qt::Key_Control, + XK_Meta_L, Qt::Key_Meta, + XK_Meta_R, Qt::Key_Meta, + XK_Alt_L, Qt::Key_Alt, + XK_Alt_R, Qt::Key_Alt, + XK_Caps_Lock, Qt::Key_CapsLock, + XK_Num_Lock, Qt::Key_NumLock, + XK_Scroll_Lock, Qt::Key_ScrollLock, + XK_Super_L, Qt::Key_Super_L, + XK_Super_R, Qt::Key_Super_R, + XK_Menu, Qt::Key_Menu, + XK_Hyper_L, Qt::Key_Hyper_L, + XK_Hyper_R, Qt::Key_Hyper_R, + XK_Help, Qt::Key_Help, + 0x1000FF74, Qt::Key_Backtab, // hardcoded HP backtab + 0x1005FF10, Qt::Key_F11, // hardcoded Sun F36 (labeled F11) + 0x1005FF11, Qt::Key_F12, // hardcoded Sun F37 (labeled F12) + + // numeric and function keypad keys + + XK_KP_Space, Qt::Key_Space, + XK_KP_Tab, Qt::Key_Tab, + XK_KP_Enter, Qt::Key_Enter, + //XK_KP_F1, Qt::Key_F1, + //XK_KP_F2, Qt::Key_F2, + //XK_KP_F3, Qt::Key_F3, + //XK_KP_F4, Qt::Key_F4, + XK_KP_Home, Qt::Key_Home, + XK_KP_Left, Qt::Key_Left, + XK_KP_Up, Qt::Key_Up, + XK_KP_Right, Qt::Key_Right, + XK_KP_Down, Qt::Key_Down, + XK_KP_Prior, Qt::Key_PageUp, + XK_KP_Next, Qt::Key_PageDown, + XK_KP_End, Qt::Key_End, + XK_KP_Begin, Qt::Key_Clear, + XK_KP_Insert, Qt::Key_Insert, + XK_KP_Delete, Qt::Key_Delete, + XK_KP_Equal, Qt::Key_Equal, + XK_KP_Multiply, Qt::Key_Asterisk, + XK_KP_Add, Qt::Key_Plus, + XK_KP_Separator, Qt::Key_Comma, + XK_KP_Subtract, Qt::Key_Minus, + XK_KP_Decimal, Qt::Key_Period, + XK_KP_Divide, Qt::Key_Slash, + + // International input method support keys + + // International & multi-key character composition + XK_ISO_Level3_Shift, Qt::Key_AltGr, + XK_Multi_key, Qt::Key_Multi_key, + XK_Codeinput, Qt::Key_Codeinput, + XK_SingleCandidate, Qt::Key_SingleCandidate, + XK_MultipleCandidate, Qt::Key_MultipleCandidate, + XK_PreviousCandidate, Qt::Key_PreviousCandidate, + + // Misc Functions + XK_Mode_switch, Qt::Key_Mode_switch, + XK_script_switch, Qt::Key_Mode_switch, + + // Japanese keyboard support + XK_Kanji, Qt::Key_Kanji, + XK_Muhenkan, Qt::Key_Muhenkan, + //XK_Henkan_Mode, Qt::Key_Henkan_Mode, + XK_Henkan_Mode, Qt::Key_Henkan, + XK_Henkan, Qt::Key_Henkan, + XK_Romaji, Qt::Key_Romaji, + XK_Hiragana, Qt::Key_Hiragana, + XK_Katakana, Qt::Key_Katakana, + XK_Hiragana_Katakana, Qt::Key_Hiragana_Katakana, + XK_Zenkaku, Qt::Key_Zenkaku, + XK_Hankaku, Qt::Key_Hankaku, + XK_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku, + XK_Touroku, Qt::Key_Touroku, + XK_Massyo, Qt::Key_Massyo, + XK_Kana_Lock, Qt::Key_Kana_Lock, + XK_Kana_Shift, Qt::Key_Kana_Shift, + XK_Eisu_Shift, Qt::Key_Eisu_Shift, + XK_Eisu_toggle, Qt::Key_Eisu_toggle, + //XK_Kanji_Bangou, Qt::Key_Kanji_Bangou, + //XK_Zen_Koho, Qt::Key_Zen_Koho, + //XK_Mae_Koho, Qt::Key_Mae_Koho, + XK_Kanji_Bangou, Qt::Key_Codeinput, + XK_Zen_Koho, Qt::Key_MultipleCandidate, + XK_Mae_Koho, Qt::Key_PreviousCandidate, + +#ifdef XK_KOREAN + // Korean keyboard support + XK_Hangul, Qt::Key_Hangul, + XK_Hangul_Start, Qt::Key_Hangul_Start, + XK_Hangul_End, Qt::Key_Hangul_End, + XK_Hangul_Hanja, Qt::Key_Hangul_Hanja, + XK_Hangul_Jamo, Qt::Key_Hangul_Jamo, + XK_Hangul_Romaja, Qt::Key_Hangul_Romaja, + //XK_Hangul_Codeinput, Qt::Key_Hangul_Codeinput, + XK_Hangul_Codeinput, Qt::Key_Codeinput, + XK_Hangul_Jeonja, Qt::Key_Hangul_Jeonja, + XK_Hangul_Banja, Qt::Key_Hangul_Banja, + XK_Hangul_PreHanja, Qt::Key_Hangul_PreHanja, + XK_Hangul_PostHanja, Qt::Key_Hangul_PostHanja, + //XK_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate, + //XK_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate, + //XK_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate, + XK_Hangul_SingleCandidate, Qt::Key_SingleCandidate, + XK_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate, + XK_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate, + XK_Hangul_Special, Qt::Key_Hangul_Special, + //XK_Hangul_switch, Qt::Key_Hangul_switch, + XK_Hangul_switch, Qt::Key_Mode_switch, +#endif // XK_KOREAN + + // dead keys + XK_dead_grave, Qt::Key_Dead_Grave, + XK_dead_acute, Qt::Key_Dead_Acute, + XK_dead_circumflex, Qt::Key_Dead_Circumflex, + XK_dead_tilde, Qt::Key_Dead_Tilde, + XK_dead_macron, Qt::Key_Dead_Macron, + XK_dead_breve, Qt::Key_Dead_Breve, + XK_dead_abovedot, Qt::Key_Dead_Abovedot, + XK_dead_diaeresis, Qt::Key_Dead_Diaeresis, + XK_dead_abovering, Qt::Key_Dead_Abovering, + XK_dead_doubleacute, Qt::Key_Dead_Doubleacute, + XK_dead_caron, Qt::Key_Dead_Caron, + XK_dead_cedilla, Qt::Key_Dead_Cedilla, + XK_dead_ogonek, Qt::Key_Dead_Ogonek, + XK_dead_iota, Qt::Key_Dead_Iota, + XK_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound, + XK_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound, + XK_dead_belowdot, Qt::Key_Dead_Belowdot, + XK_dead_hook, Qt::Key_Dead_Hook, + XK_dead_horn, Qt::Key_Dead_Horn, + +#if 0 + // Special multimedia keys + // currently only tested with MS internet keyboard + + // browsing keys + XF86XK_Back, Qt::Key_Back, + XF86XK_Forward, Qt::Key_Forward, + XF86XK_Stop, Qt::Key_Stop, + XF86XK_Refresh, Qt::Key_Refresh, + XF86XK_Favorites, Qt::Key_Favorites, + XF86XK_AudioMedia, Qt::Key_LaunchMedia, + XF86XK_OpenURL, Qt::Key_OpenUrl, + XF86XK_HomePage, Qt::Key_HomePage, + XF86XK_Search, Qt::Key_Search, + + // media keys + XF86XK_AudioLowerVolume, Qt::Key_VolumeDown, + XF86XK_AudioMute, Qt::Key_VolumeMute, + XF86XK_AudioRaiseVolume, Qt::Key_VolumeUp, + XF86XK_AudioPlay, Qt::Key_MediaPlay, + XF86XK_AudioStop, Qt::Key_MediaStop, + XF86XK_AudioPrev, Qt::Key_MediaPrevious, + XF86XK_AudioNext, Qt::Key_MediaNext, + XF86XK_AudioRecord, Qt::Key_MediaRecord, + + // launch keys + XF86XK_Mail, Qt::Key_LaunchMail, + XF86XK_MyComputer, Qt::Key_Launch0, + XF86XK_Calculator, Qt::Key_Launch1, + XF86XK_Standby, Qt::Key_Standby, + + XF86XK_Launch0, Qt::Key_Launch2, + XF86XK_Launch1, Qt::Key_Launch3, + XF86XK_Launch2, Qt::Key_Launch4, + XF86XK_Launch3, Qt::Key_Launch5, + XF86XK_Launch4, Qt::Key_Launch6, + XF86XK_Launch5, Qt::Key_Launch7, + XF86XK_Launch6, Qt::Key_Launch8, + XF86XK_Launch7, Qt::Key_Launch9, + XF86XK_Launch8, Qt::Key_LaunchA, + XF86XK_Launch9, Qt::Key_LaunchB, + XF86XK_LaunchA, Qt::Key_LaunchC, + XF86XK_LaunchB, Qt::Key_LaunchD, + XF86XK_LaunchC, Qt::Key_LaunchE, + XF86XK_LaunchD, Qt::Key_LaunchF, +#endif + +#if 0 + // Qtopia keys + QTOPIAXK_Select, Qt::Key_Select, + QTOPIAXK_Yes, Qt::Key_Yes, + QTOPIAXK_No, Qt::Key_No, + QTOPIAXK_Cancel, Qt::Key_Cancel, + QTOPIAXK_Printer, Qt::Key_Printer, + QTOPIAXK_Execute, Qt::Key_Execute, + QTOPIAXK_Sleep, Qt::Key_Sleep, + QTOPIAXK_Play, Qt::Key_Play, + QTOPIAXK_Zoom, Qt::Key_Zoom, + QTOPIAXK_Context1, Qt::Key_Context1, + QTOPIAXK_Context2, Qt::Key_Context2, + QTOPIAXK_Context3, Qt::Key_Context3, + QTOPIAXK_Context4, Qt::Key_Context4, + QTOPIAXK_Call, Qt::Key_Call, + QTOPIAXK_Hangup, Qt::Key_Hangup, + QTOPIAXK_Flip, Qt::Key_Flip, +#endif + 0, 0 +}; + + +static int lookupCode(unsigned int xkeycode) +{ + if (xkeycode >= XK_F1 && xkeycode <= XK_F35) + return Qt::Key_F1 + (int(xkeycode) - XK_F1); + + const unsigned int *p = keyTbl; + while (*p) { + if (*p == xkeycode) + return *++p; + p += 2; + } + + return 0; +} + + +static Qt::KeyboardModifiers modifierFromKeyCode(int qtcode) +{ + switch (qtcode) { + case Qt::Key_Control: + return Qt::ControlModifier; + case Qt::Key_Alt: + return Qt::AltModifier; + case Qt::Key_Shift: + return Qt::ShiftModifier; + case Qt::Key_Meta: + return Qt::MetaModifier; + default: + return Qt::NoModifier; + } +} + +void QTestLiteWindow::handleKeyEvent(QEvent::Type type, void *ev) +{ + XKeyEvent *e = static_cast<XKeyEvent*>(ev); + + KeySym keySym; + QByteArray chars; + chars.resize(513); + + int count = XLookupString(e, chars.data(), chars.size(), &keySym, 0); + Q_UNUSED(count); +// qDebug() << "QTLWS::handleKeyEvent" << count << hex << "XKeysym:" << keySym; +// if (count) +// qDebug() << hex << int(chars[0]) << "String:" << chars; + + Qt::KeyboardModifiers modifiers = translateModifiers(e->state); + + int qtcode = lookupCode(keySym); +// qDebug() << "lookup: " << hex << keySym << qtcode << "mod" << modifiers; + + //X11 specifies state *before*, Qt expects state *after* the event + + modifiers ^= modifierFromKeyCode(qtcode); + + if (qtcode) { + QWindowSystemInterface::handleKeyEvent(widget(), e->time, type, qtcode, modifiers); + } else if (chars[0]) { + int qtcode = chars.toUpper()[0]; //Not exactly right... + if (modifiers & Qt::ControlModifier && qtcode < ' ') + qtcode = chars[0] + '@'; + QWindowSystemInterface::handleKeyEvent(0, e->time, type, qtcode, modifiers, QString::fromLatin1(chars)); + } else { + qWarning() << "unknown X keycode" << hex << e->keycode << keySym; + } +} + +void QTestLiteWindow::setGeometry(const QRect &rect) +{ + XMoveResizeWindow(xd->display, x_window, rect.x(), rect.y(), rect.width(), rect.height()); + QPlatformWindow::setGeometry(rect); +} + + +Qt::WindowFlags QTestLiteWindow::windowFlags() const +{ + return window_flags; +} + +WId QTestLiteWindow::winId() const +{ + return x_window; +} + +void QTestLiteWindow::setParent(const QPlatformWindow *window) +{ + QPoint point = widget()->mapTo(widget()->nativeParentWidget(),QPoint()); + XReparentWindow(xd->display,x_window,window->winId(),point.x(),point.y()); + XMapWindow(xd->display, x_window); +} + +void QTestLiteWindow::raise() +{ + XRaiseWindow(xd->display, x_window); +} + +void QTestLiteWindow::lower() +{ + XLowerWindow(xd->display, x_window); +} + +void QTestLiteWindow::setWindowTitle(const QString &title) +{ + QByteArray ba = title.toLatin1(); //We're not making a general solution here... + XTextProperty windowName; + windowName.value = (unsigned char *)ba.constData(); + windowName.encoding = XA_STRING; + windowName.format = 8; + windowName.nitems = ba.length(); + + XSetWMName(xd->display, x_window, &windowName); +} + +GC QTestLiteWindow::createGC() +{ + GC gc; + + gc = XCreateGC(xd->display, x_window, 0, 0); + if (gc < 0) { + qWarning("QTestLiteWindow::createGC() could not create GC"); + } + return gc; +} + +void QTestLiteWindow::paintEvent() +{ +#ifdef MYX11_DEBUG +// qDebug() << "QTestLiteWindow::paintEvent" << shm_img.size() << painted; +#endif + + if (QWindowSurface *surface = widget()->windowSurface()) + surface->flush(widget(), QRect(xpos,ypos,width, height), QPoint()); +} + + +void QTestLiteWindow::resizeEvent(XConfigureEvent *e) +{ + if ((e->width != width || e->height != height) && e->x == 0 && e->y == 0) { + //qDebug() << "resize with bogus pos" << e->x << e->y << e->width << e->height << "window"<< hex << window; + } else { + //qDebug() << "geometry change" << e->x << e->y << e->width << e->height << "window"<< hex << window; + xpos = e->x; + ypos = e->y; + } + width = e->width; + height = e->height; + +#ifdef MYX11_DEBUG + qDebug() << hex << x_window << dec << "ConfigureNotify" << e->x << e->y << e->width << e->height << "geometry" << xpos << ypos << width << height; +#endif + + QWindowSystemInterface::handleGeometryChange(widget(), QRect(xpos, ypos, width, height)); +} + + +void QTestLiteWindow::mousePressEvent(XButtonEvent *e) +{ + static long prevTime = 0; + static Window prevWindow; + static int prevX = -999; + static int prevY = -999; + + QEvent::Type type = QEvent::MouseButtonPress; + + if (e->window == prevWindow && long(e->time) - prevTime < QApplication::doubleClickInterval() + && qAbs(e->x - prevX) < 5 && qAbs(e->y - prevY) < 5) { + type = QEvent::MouseButtonDblClick; + prevTime = e->time - QApplication::doubleClickInterval(); //no double click next time + } else { + prevTime = e->time; + } + prevWindow = e->window; + prevX = e->x; + prevY = e->y; + + handleMouseEvent(type, e); +} + + + +// WindowFlag stuff, lots of copied code from qwidget_x11.cpp... + +//We're hacking here... + + +// MWM support +struct QtMWMHints { + ulong flags, functions, decorations; + long input_mode; + ulong status; +}; + +enum { + MWM_HINTS_FUNCTIONS = (1L << 0), + + MWM_FUNC_ALL = (1L << 0), + MWM_FUNC_RESIZE = (1L << 1), + MWM_FUNC_MOVE = (1L << 2), + MWM_FUNC_MINIMIZE = (1L << 3), + MWM_FUNC_MAXIMIZE = (1L << 4), + MWM_FUNC_CLOSE = (1L << 5), + + MWM_HINTS_DECORATIONS = (1L << 1), + + MWM_DECOR_ALL = (1L << 0), + MWM_DECOR_BORDER = (1L << 1), + MWM_DECOR_RESIZEH = (1L << 2), + MWM_DECOR_TITLE = (1L << 3), + MWM_DECOR_MENU = (1L << 4), + MWM_DECOR_MINIMIZE = (1L << 5), + MWM_DECOR_MAXIMIZE = (1L << 6), + + MWM_HINTS_INPUT_MODE = (1L << 2), + + MWM_INPUT_MODELESS = 0L, + MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L, + MWM_INPUT_FULL_APPLICATION_MODAL = 3L +}; + +static Atom mwm_hint_atom = XNone; + +#if 0 +static QtMWMHints GetMWMHints(Display *display, Window window) +{ + QtMWMHints mwmhints; + + Atom type; + int format; + ulong nitems, bytesLeft; + uchar *data = 0; + if ((XGetWindowProperty(display, window, mwm_hint_atom, 0, 5, false, + mwm_hint_atom, &type, &format, &nitems, &bytesLeft, + &data) == Success) + && (type == mwm_hint_atom + && format == 32 + && nitems >= 5)) { + mwmhints = *(reinterpret_cast<QtMWMHints *>(data)); + } else { + mwmhints.flags = 0L; + mwmhints.functions = MWM_FUNC_ALL; + mwmhints.decorations = MWM_DECOR_ALL; + mwmhints.input_mode = 0L; + mwmhints.status = 0L; + } + + if (data) + XFree(data); + + return mwmhints; +} +#endif + +static void SetMWMHints(Display *display, Window window, const QtMWMHints &mwmhints) +{ + if (mwmhints.flags != 0l) { + XChangeProperty(display, window, mwm_hint_atom, mwm_hint_atom, 32, + PropModeReplace, (unsigned char *) &mwmhints, 5); + } else { + XDeleteProperty(display, window, mwm_hint_atom); + } +} + +// Returns true if we should set WM_TRANSIENT_FOR on \a w +static inline bool isTransient(const QWidget *w) +{ + return ((w->windowType() == Qt::Dialog + || w->windowType() == Qt::Sheet + || w->windowType() == Qt::Tool + || w->windowType() == Qt::SplashScreen + || w->windowType() == Qt::ToolTip + || w->windowType() == Qt::Drawer + || w->windowType() == Qt::Popup) + && !w->testAttribute(Qt::WA_X11BypassTransientForHint)); +} + + + +Qt::WindowFlags QTestLiteWindow::setWindowFlags(Qt::WindowFlags flags) +{ +// Q_ASSERT(flags & Qt::Window); + window_flags = flags; + + if (mwm_hint_atom == XNone) { + mwm_hint_atom = XInternAtom(xd->display, "_MOTIF_WM_HINTS\0", False); + } + +#ifdef MYX11_DEBUG + qDebug() << "QTestLiteWindow::setWindowFlags" << hex << x_window << "flags" << flags; +#endif + Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask)); + + if (type == Qt::ToolTip) + flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint; + if (type == Qt::Popup) + flags |= Qt::X11BypassWindowManagerHint; + + bool topLevel = (flags & Qt::Window); + bool popup = (type == Qt::Popup); + bool dialog = (type == Qt::Dialog + || type == Qt::Sheet); + bool desktop = (type == Qt::Desktop); + bool tool = (type == Qt::Tool || type == Qt::SplashScreen + || type == Qt::ToolTip || type == Qt::Drawer); + + + Q_UNUSED(topLevel); + Q_UNUSED(dialog); + Q_UNUSED(desktop); + + + bool tooltip = (type == Qt::ToolTip); + + XSetWindowAttributes wsa; + + QtMWMHints mwmhints; + mwmhints.flags = 0L; + mwmhints.functions = 0L; + mwmhints.decorations = 0; + mwmhints.input_mode = 0L; + mwmhints.status = 0L; + + + ulong wsa_mask = 0; + if (type != Qt::SplashScreen) { // && customize) { + mwmhints.flags |= MWM_HINTS_DECORATIONS; + + bool customize = flags & Qt::CustomizeWindowHint; + if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) { + mwmhints.decorations |= MWM_DECOR_BORDER; + mwmhints.decorations |= MWM_DECOR_RESIZEH; + + if (flags & Qt::WindowTitleHint) + mwmhints.decorations |= MWM_DECOR_TITLE; + + if (flags & Qt::WindowSystemMenuHint) + mwmhints.decorations |= MWM_DECOR_MENU; + + if (flags & Qt::WindowMinimizeButtonHint) { + mwmhints.decorations |= MWM_DECOR_MINIMIZE; + mwmhints.functions |= MWM_FUNC_MINIMIZE; + } + + if (flags & Qt::WindowMaximizeButtonHint) { + mwmhints.decorations |= MWM_DECOR_MAXIMIZE; + mwmhints.functions |= MWM_FUNC_MAXIMIZE; + } + + if (flags & Qt::WindowCloseButtonHint) + mwmhints.functions |= MWM_FUNC_CLOSE; + } + } else { + // if type == Qt::SplashScreen + mwmhints.decorations = MWM_DECOR_ALL; + } + + if (tool) { + wsa.save_under = True; + wsa_mask |= CWSaveUnder; + } + + if (flags & Qt::X11BypassWindowManagerHint) { + wsa.override_redirect = True; + wsa_mask |= CWOverrideRedirect; + } +#if 0 + if (wsa_mask && initializeWindow) { + Q_ASSERT(id); + XChangeWindowAttributes(dpy, id, wsa_mask, &wsa); + } +#endif + if (mwmhints.functions != 0) { + mwmhints.flags |= MWM_HINTS_FUNCTIONS; + mwmhints.functions |= MWM_FUNC_MOVE | MWM_FUNC_RESIZE; + } else { + mwmhints.functions = MWM_FUNC_ALL; + } + + if (!(flags & Qt::FramelessWindowHint) + && flags & Qt::CustomizeWindowHint + && flags & Qt::WindowTitleHint + && !(flags & + (Qt::WindowMinimizeButtonHint + | Qt::WindowMaximizeButtonHint + | Qt::WindowCloseButtonHint))) { + // a special case - only the titlebar without any button + mwmhints.flags = MWM_HINTS_FUNCTIONS; + mwmhints.functions = MWM_FUNC_MOVE | MWM_FUNC_RESIZE; + mwmhints.decorations = 0; + } + + SetMWMHints(xd->display, x_window, mwmhints); + +//##### only if initializeWindow??? + + if (popup || tooltip) { // popup widget +#ifdef MYX11_DEBUG + qDebug() << "Doing XChangeWindowAttributes for popup" << wsa.override_redirect; +#endif + // set EWMH window types + // setNetWmWindowTypes(); + + wsa.override_redirect = True; + wsa.save_under = True; + XChangeWindowAttributes(xd->display, x_window, CWOverrideRedirect | CWSaveUnder, + &wsa); + } else { +#ifdef MYX11_DEBUG + qDebug() << "Doing XChangeWindowAttributes for non-popup"; +#endif + } + + return flags; +} + +void QTestLiteWindow::setVisible(bool visible) +{ +#ifdef MYX11_DEBUG + qDebug() << "QTestLiteWindow::setVisible" << visible << hex << x_window; +#endif + if (visible) + XMapWindow(xd->display, x_window); + else + XUnmapWindow(xd->display, x_window); +} + + +void QTestLiteWindow::setCursor(QCursor * cursor) +{ + int id = cursor->handle(); + if (id == currentCursor) + return; + Cursor c; + if (!xd->cursors->exists(id)) { + if (cursor->shape() == Qt::BitmapCursor) + c = createCursorBitmap(cursor); + else + c = createCursorShape(cursor->shape()); + if (!c) { + return; + } + xd->cursors->createNode(id, c); + } else { + xd->cursors->incrementUseCount(id); + c = xd->cursors->cursor(id); + } + + if (currentCursor != -1) + xd->cursors->decrementUseCount(currentCursor); + currentCursor = id; + + XDefineCursor(xd->display, x_window, c); + XFlush(xd->display); +} + +QPlatformGLContext *QTestLiteWindow::glContext() const +{ + if (!QApplicationPrivate::platformIntegration()->hasOpenGL()) + return 0; + if (!mGLContext) { + QTestLiteWindow *that = const_cast<QTestLiteWindow *>(this); +#ifndef QT_NO_OPENGL + that->mGLContext = new QGLXGLContext(x_window, xd, widget()->platformWindowFormat()); +#endif + } + return mGLContext; +} + +Cursor QTestLiteWindow::createCursorBitmap(QCursor * cursor) +{ + XColor bg, fg; + bg.red = 255 << 8; + bg.green = 255 << 8; + bg.blue = 255 << 8; + fg.red = 0; + fg.green = 0; + fg.blue = 0; + QPoint spot = cursor->hotSpot(); + Window rootwin = x_window; + + QImage mapImage = cursor->bitmap()->toImage().convertToFormat(QImage::Format_MonoLSB); + QImage maskImage = cursor->mask()->toImage().convertToFormat(QImage::Format_MonoLSB); + + int width = cursor->bitmap()->width(); + int height = cursor->bitmap()->height(); + int bytesPerLine = mapImage.bytesPerLine(); + int destLineSize = width / 8; + if (width % 8) + destLineSize++; + + const uchar * map = mapImage.bits(); + const uchar * mask = maskImage.bits(); + + char * mapBits = new char[height * destLineSize]; + char * maskBits = new char[height * destLineSize]; + for (int i = 0; i < height; i++) { + memcpy(mapBits + (destLineSize * i),map + (bytesPerLine * i), destLineSize); + memcpy(maskBits + (destLineSize * i),mask + (bytesPerLine * i), destLineSize); + } + + Pixmap cp = XCreateBitmapFromData(xd->display, rootwin, mapBits, width, height); + Pixmap mp = XCreateBitmapFromData(xd->display, rootwin, maskBits, width, height); + Cursor c = XCreatePixmapCursor(xd->display, cp, mp, &fg, &bg, spot.x(), spot.y()); + XFreePixmap(xd->display, cp); + XFreePixmap(xd->display, mp); + delete[] mapBits; + delete[] maskBits; + + return c; +} + +Cursor QTestLiteWindow::createCursorShape(int cshape) +{ + Cursor cursor = 0; + + if (cshape < 0 || cshape > Qt::LastCursor) + return 0; + + switch (cshape) { + case Qt::ArrowCursor: + cursor = XCreateFontCursor(xd->display, XC_left_ptr); + break; + case Qt::UpArrowCursor: + cursor = XCreateFontCursor(xd->display, XC_center_ptr); + break; + case Qt::CrossCursor: + cursor = XCreateFontCursor(xd->display, XC_crosshair); + break; + case Qt::WaitCursor: + cursor = XCreateFontCursor(xd->display, XC_watch); + break; + case Qt::IBeamCursor: + cursor = XCreateFontCursor(xd->display, XC_xterm); + break; + case Qt::SizeAllCursor: + cursor = XCreateFontCursor(xd->display, XC_fleur); + break; + case Qt::PointingHandCursor: + cursor = XCreateFontCursor(xd->display, XC_hand2); + break; + case Qt::SizeBDiagCursor: + cursor = XCreateFontCursor(xd->display, XC_top_right_corner); + break; + case Qt::SizeFDiagCursor: + cursor = XCreateFontCursor(xd->display, XC_bottom_right_corner); + break; + case Qt::SizeVerCursor: + case Qt::SplitVCursor: + cursor = XCreateFontCursor(xd->display, XC_sb_v_double_arrow); + break; + case Qt::SizeHorCursor: + case Qt::SplitHCursor: + cursor = XCreateFontCursor(xd->display, XC_sb_h_double_arrow); + break; + case Qt::WhatsThisCursor: + cursor = XCreateFontCursor(xd->display, XC_question_arrow); + break; + case Qt::ForbiddenCursor: + cursor = XCreateFontCursor(xd->display, XC_circle); + break; + case Qt::BusyCursor: + cursor = XCreateFontCursor(xd->display, XC_watch); + break; + + default: //default cursor for all the rest + break; + } + return cursor; +} + + +MyX11Cursors::MyX11Cursors(Display * d) : firstExpired(0), lastExpired(0), display(d), removalDelay(3) +{ + connect(&timer, SIGNAL(timeout()), this, SLOT(timeout())); +} + +void MyX11Cursors::insertNode(MyX11CursorNode * node) +{ + QDateTime now = QDateTime::currentDateTime(); + QDateTime timeout = now.addSecs(removalDelay); + node->setExpiration(timeout); + node->setPost(0); + if (lastExpired) { + lastExpired->setPost(node); + node->setAnte(lastExpired); + } + lastExpired = node; + if (!firstExpired) { + firstExpired = node; + node->setAnte(0); + int interval = removalDelay * 1000; + timer.setInterval(interval); + timer.start(); + } +} + +void MyX11Cursors::removeNode(MyX11CursorNode * node) +{ + MyX11CursorNode *pre = node->ante(); + MyX11CursorNode *post = node->post(); + if (pre) + pre->setPost(post); + if (post) + post->setAnte(pre); + if (node == lastExpired) + lastExpired = pre; + if (node == firstExpired) { + firstExpired = post; + if (!firstExpired) { + timer.stop(); + return; + } + int interval = QDateTime::currentDateTime().secsTo(firstExpired->expiration()) * 1000; + timer.stop(); + timer.setInterval(interval); + timer.start(); + } +} + +void MyX11Cursors::incrementUseCount(int id) +{ + MyX11CursorNode * node = lookupMap.value(id); + Q_ASSERT(node); + if (!node->refCount) + removeNode(node); + node->refCount++; +} + +void MyX11Cursors::decrementUseCount(int id) +{ + MyX11CursorNode * node = lookupMap.value(id); + Q_ASSERT(node); + node->refCount--; + if (!node->refCount) + insertNode(node); +} + +void MyX11Cursors::createNode(int id, Cursor c) +{ + MyX11CursorNode * node = new MyX11CursorNode(id, c); + lookupMap.insert(id, node); +} + +void MyX11Cursors::timeout() +{ + MyX11CursorNode * node; + node = firstExpired; + QDateTime now = QDateTime::currentDateTime(); + while (node && now.secsTo(node->expiration()) < 1) { + Cursor c = node->cursor(); + int id = node->id(); + lookupMap.take(id); + MyX11CursorNode * tmp = node; + node = node->post(); + if (node) + node->setAnte(0); + delete tmp; + XFreeCursor(display, c); + } + firstExpired = node; + if (node == 0) { + timer.stop(); + lastExpired = 0; + } + else { + int interval = QDateTime::currentDateTime().secsTo(firstExpired->expiration()) * 1000; + timer.setInterval(interval); + timer.start(); + } +} + +Cursor MyX11Cursors::cursor(int id) +{ + MyX11CursorNode * node = lookupMap.value(id); + Q_ASSERT(node); + return node->cursor(); +} + + + +/******************************************************************** + +MyDisplay class - perhaps better placed in qplatformintegration_testlite? + +*********************************************************************/ + +//### copied from qapplication_x11.cpp + +static int qt_x_errhandler(Display *dpy, XErrorEvent *err) +{ + +qDebug() << "qt_x_errhandler" << err->error_code; + + switch (err->error_code) { + case BadAtom: +#if 0 + if (err->request_code == 20 /* X_GetProperty */ + && (err->resourceid == XA_RESOURCE_MANAGER + || err->resourceid == XA_RGB_DEFAULT_MAP + || err->resourceid == ATOM(_NET_SUPPORTED) + || err->resourceid == ATOM(_NET_SUPPORTING_WM_CHECK) + || err->resourceid == ATOM(KDE_FULL_SESSION) + || err->resourceid == ATOM(KWIN_RUNNING) + || err->resourceid == ATOM(XdndProxy) + || err->resourceid == ATOM(XdndAware)) + + + ) { + // Perhaps we're running under SECURITY reduction? :/ + return 0; + } +#endif + qDebug() << "BadAtom"; + break; + + case BadWindow: + if (err->request_code == 2 /* X_ChangeWindowAttributes */ + || err->request_code == 38 /* X_QueryPointer */) { + for (int i = 0; i < ScreenCount(dpy); ++i) { + if (err->resourceid == RootWindow(dpy, i)) { + // Perhaps we're running under SECURITY reduction? :/ + return 0; + } + } + } + seen_badwindow = true; + if (err->request_code == 25 /* X_SendEvent */) { + for (int i = 0; i < ScreenCount(dpy); ++i) { + if (err->resourceid == RootWindow(dpy, i)) { + // Perhaps we're running under SECURITY reduction? :/ + return 0; + } + } +#if 0 + if (X11->xdndHandleBadwindow()) { + qDebug("xdndHandleBadwindow returned true"); + return 0; + } +#endif + } +#if 0 + if (X11->ignore_badwindow) + return 0; +#endif + break; + + case BadMatch: + if (err->request_code == 42 /* X_SetInputFocus */) + return 0; + break; + + default: +#if 0 //!defined(QT_NO_XINPUT) + if (err->request_code == X11->xinput_major + && err->error_code == (X11->xinput_errorbase + XI_BadDevice) + && err->minor_code == 3 /* X_OpenDevice */) { + return 0; + } +#endif + break; + } + + char errstr[256]; + XGetErrorText( dpy, err->error_code, errstr, 256 ); + char buffer[256]; + char request_str[256]; + qsnprintf(buffer, 256, "%d", err->request_code); + XGetErrorDatabaseText(dpy, "XRequest", buffer, "", request_str, 256); + if (err->request_code < 128) { + // X error for a normal protocol request + qWarning( "X Error: %s %d\n" + " Major opcode: %d (%s)\n" + " Resource id: 0x%lx", + errstr, err->error_code, + err->request_code, + request_str, + err->resourceid ); + } else { + // X error for an extension request + const char *extensionName = 0; +#if 0 + if (err->request_code == X11->xrender_major) + extensionName = "RENDER"; + else if (err->request_code == X11->xrandr_major) + extensionName = "RANDR"; + else if (err->request_code == X11->xinput_major) + extensionName = "XInputExtension"; + else if (err->request_code == X11->mitshm_major) + extensionName = "MIT-SHM"; +#endif + char minor_str[256]; + if (extensionName) { + qsnprintf(buffer, 256, "%s.%d", extensionName, err->minor_code); + XGetErrorDatabaseText(dpy, "XRequest", buffer, "", minor_str, 256); + } else { + extensionName = "Uknown extension"; + qsnprintf(minor_str, 256, "Unknown request"); + } + qWarning( "X Error: %s %d\n" + " Extension: %d (%s)\n" + " Minor opcode: %d (%s)\n" + " Resource id: 0x%lx", + errstr, err->error_code, + err->request_code, + extensionName, + err->minor_code, + minor_str, + err->resourceid ); + } + + // ### we really should distinguish between severe, non-severe and + // ### application specific errors + + return 0; +} + + +#ifdef KeyPress +#undef KeyPress +#endif +#ifdef KeyRelease +#undef KeyRelease +#endif + +bool MyDisplay::handleEvent(XEvent *xe) +{ + //qDebug() << "handleEvent" << xe->xany.type << xe->xany.window; + int quit = false; + QTestLiteWindow *xw = 0; + foreach (QTestLiteWindow *w, windowList) { + if (w->winId() == xe->xany.window) { + xw = w; + break; + } + } + if (!xw) { +#ifdef MYX11_DEBUG + qWarning() << "Unknown window" << hex << xe->xany.window << "received event" << xe->type; +#endif + return quit; + } + + switch (xe->type) { + + case ClientMessage: + if (xe->xclient.format == 32 && xe->xclient.message_type == wmProtocolsAtom) { + Atom a = xe->xclient.data.l[0]; + if (a == wmDeleteWindowAtom) + xw->handleCloseEvent(); +#ifdef MYX11_DEBUG + qDebug() << "ClientMessage WM_PROTOCOLS" << a; +#endif + } +#ifdef MYX11_DEBUG + else + qDebug() << "ClientMessage" << xe->xclient.format << xe->xclient.message_type; +#endif + break; + + case Expose: + if (xw) + if (xe->xexpose.count == 0) + xw->paintEvent(); + break; + case ConfigureNotify: + if (xw) + xw->resizeEvent(&xe->xconfigure); + break; + + case ButtonPress: + xw->mousePressEvent(&xe->xbutton); + break; + + case ButtonRelease: + xw->handleMouseEvent(QEvent::MouseButtonRelease, &xe->xbutton); + break; + + case MotionNotify: + xw->handleMouseEvent(QEvent::MouseMove, &xe->xbutton); + break; + + case XKeyPress: + xw->handleKeyEvent(QEvent::KeyPress, &xe->xkey); + break; + + case XKeyRelease: + xw->handleKeyEvent(QEvent::KeyRelease, &xe->xkey); + break; + + case EnterNotify: + xw->handleEnterEvent(); + break; + + case LeaveNotify: + xw->handleLeaveEvent(); + break; + + default: +#ifdef MYX11_DEBUG + qDebug() << hex << xe->xany.window << "Other X event" << xe->type; +#endif + break; + } + return quit; +}; + + + +MyDisplay::MyDisplay() +{ + char *display_name = getenv("DISPLAY"); + display = XOpenDisplay(display_name); + if (!display) { + fprintf(stderr, "Cannot connect to X server: %s\n", + display_name); + exit(1); + } + +#ifndef DONT_USE_MIT_SHM + Status MIT_SHM_extension_supported = XShmQueryExtension (display); + Q_ASSERT(MIT_SHM_extension_supported == True); +#endif + original_x_errhandler = XSetErrorHandler(qt_x_errhandler); + + if (qgetenv("DO_X_SYNCHRONIZE").toInt()) + XSynchronize(display, true); + + screen = DefaultScreen(display); + width = DisplayWidth(display, screen); + height = DisplayHeight(display, screen); + physicalWidth = DisplayWidthMM(display, screen); + physicalHeight = DisplayHeightMM(display, screen); + + int xSocketNumber = XConnectionNumber(display); +#ifdef MYX11_DEBUG + qDebug() << "X socket:"<< xSocketNumber; +#endif + QSocketNotifier *sock = new QSocketNotifier(xSocketNumber, QSocketNotifier::Read, this); + connect(sock, SIGNAL(activated(int)), this, SLOT(eventDispatcher())); + + wmProtocolsAtom = XInternAtom (display, "WM_PROTOCOLS", False); + wmDeleteWindowAtom = XInternAtom (display, "WM_DELETE_WINDOW", False); + + cursors = new MyX11Cursors(display); +} + + +MyDisplay::~MyDisplay() +{ + XCloseDisplay(display); +} + + +void MyDisplay::eventDispatcher() +{ +// qDebug() << "eventDispatcher"; + + + ulong marker = XNextRequest(display); +// int i = 0; + while (XPending(display)) { + XEvent event; + XNextEvent(display, &event); + /* done = */ + handleEvent(&event); + + if (event.xany.serial >= marker) { +#ifdef MYX11_DEBUG + qDebug() << "potential livelock averted"; +#endif +#if 0 + if (XEventsQueued(display, QueuedAfterFlush)) { + qDebug() << " with events queued"; + QTimer::singleShot(0, this, SLOT(eventDispatcher())); + } +#endif + break; + } + } +} + + +QImage MyDisplay::grabWindow(Window window, int x, int y, int w, int h) +{ + if (w == 0 || h ==0) + return QImage(); + + //WinId 0 means the desktop widget + if (!window) + window = rootWindow(); + + XWindowAttributes window_attr; + if (!XGetWindowAttributes(display, window, &window_attr)) + return QImage(); + + if (w < 0) + w = window_attr.width - x; + if (h < 0) + h = window_attr.height - y; + + // Ideally, we should also limit ourselves to the screen area, but the Qt docs say + // that it's "unsafe" to go outside the screen, so we can ignore that problem. + + //We're definitely not optimizing for speed... + XImage *xi = XGetImage(display, window, x, y, w, h, AllPlanes, ZPixmap); + + if (!xi) + return QImage(); + + //taking a copy to make sure we have ownership -- not fast + QImage result = QImage( (uchar*) xi->data, xi->width, xi->height, xi->bytes_per_line, QImage::Format_RGB32 ).copy(); + + XDestroyImage(xi); + + return result; +} + + + + + + + +QT_END_NAMESPACE +#include "qtestlitewindow.moc" diff --git a/src/plugins/platforms/testlite/qtestlitewindow.h b/src/plugins/platforms/testlite/qtestlitewindow.h new file mode 100644 index 0000000..dc628f1 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitewindow.h @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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$ +** +****************************************************************************/ + +#ifndef QTESTLITEWINDOW_H +#define QTESTLITEWINDOW_H + +#include <QPlatformWindow> +#include <qevent.h> + +#include <QObject> +#include <QImage> +#include <qtimer.h> +#include <QDateTime> + +#include <private/qt_x11_p.h> + +#include <X11/Xlib.h> +#include <X11/Xutil.h> + + + +class QTestLiteIntegration; +class QTestLiteScreen; +class QTestLiteWindowSurface; +class MyX11Cursors; +class QTestLiteWindow; + +class MyDisplay : public QObject +{ + Q_OBJECT; +public: + MyDisplay(); + ~MyDisplay(); + + Window rootWindow() { return RootWindow(display, screen); } + unsigned long blackPixel() { return BlackPixel(display, screen); } + unsigned long whitePixel() { return WhitePixel(display, screen); } + + bool handleEvent(XEvent *xe); + QImage grabWindow(Window window, int x, int y, int w, int h); + +public slots: + void eventDispatcher(); + +public: //### + Display * display; + int screen; + int width, height; + int physicalWidth; + int physicalHeight; + + QList<QTestLiteWindow*> windowList; + + MyX11Cursors * cursors; +}; + +struct MyShmImageInfo; + +class QTestLiteWindow : public QPlatformWindow +{ +public: + QTestLiteWindow(const QTestLiteIntegration *platformIntegration, + QTestLiteScreen *screen, QWidget *window); + ~QTestLiteWindow(); + + + void mousePressEvent(XButtonEvent*); + void handleMouseEvent(QEvent::Type, XButtonEvent *ev); + + void handleKeyEvent(QEvent::Type, void *); + void handleCloseEvent(); + void handleEnterEvent(); + void handleLeaveEvent(); + + void resizeEvent(XConfigureEvent *configure_event); + void paintEvent(); + + + void setGeometry(const QRect &rect); + + Qt::WindowFlags setWindowFlags(Qt::WindowFlags type); + Qt::WindowFlags windowFlags() const; + void setVisible(bool visible); + WId winId() const; + void setParent(const QPlatformWindow *window); + void raise(); + void lower(); + void setWindowTitle(const QString &title); + + void setCursor(QCursor * cursor); + + QPlatformGLContext *glContext() const; + +private: + int xpos, ypos; + int width, height; + Window x_window; + GC gc; + + GC createGC(); + Cursor createCursorShape(int cshape); + Cursor createCursorBitmap(QCursor * cursor); + + int currentCursor; + + MyDisplay *xd; + + QTestLiteScreen *mScreen; + Qt::WindowFlags window_flags; + QPlatformGLContext *mGLContext; + + friend class QTestLiteWindowSurface; // x_window, gc and windowSurface +}; + + + + + +#endif diff --git a/src/plugins/platforms/testlite/qtestlitewindowsurface.cpp b/src/plugins/platforms/testlite/qtestlitewindowsurface.cpp new file mode 100644 index 0000000..b3232c8 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitewindowsurface.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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 "qtestlitewindowsurface.h" +#include "qtestliteintegration.h" + +#include <QtCore/qdebug.h> +#include <QWindowSystemInterface> + +#include "qtestlitewindow.h" + +# include <sys/ipc.h> +# include <sys/shm.h> +# include <X11/extensions/XShm.h> + +QT_BEGIN_NAMESPACE + + +struct MyShmImageInfo { + MyShmImageInfo(Display *xdisplay) : image(0), display(xdisplay) {} + ~MyShmImageInfo() { destroy(); } + + void destroy(); + + XShmSegmentInfo shminfo; + XImage *image; + Display *display; +}; + +//void QTestLiteWindowSurface::flush() + + +#ifndef DONT_USE_MIT_SHM +void MyShmImageInfo::destroy() +{ + XShmDetach (display, &shminfo); + XDestroyImage (image); + shmdt (shminfo.shmaddr); + shmctl (shminfo.shmid, IPC_RMID, 0); +} +#endif + +void QTestLiteWindowSurface::resizeShmImage(int width, int height) +{ + MyDisplay *xd = xw->xd; + +#ifdef DONT_USE_MIT_SHM + shm_img = QImage(width, height, QImage::Format_RGB32); +#else + if (image_info) + image_info->destroy(); + else + image_info = new MyShmImageInfo(xd->display); + + Visual *visual = DefaultVisual(xd->display, xd->screen); + + + XImage *image = XShmCreateImage (xd->display, visual, 24, ZPixmap, 0, + &image_info->shminfo, width, height); + + + image_info->shminfo.shmid = shmget (IPC_PRIVATE, + image->bytes_per_line * image->height, IPC_CREAT|0777); + + image_info->shminfo.shmaddr = image->data = (char*)shmat (image_info->shminfo.shmid, 0, 0); + image_info->shminfo.readOnly = False; + + image_info->image = image; + + Status shm_attach_status = XShmAttach(xd->display, &image_info->shminfo); + + Q_ASSERT(shm_attach_status == True); + + shm_img = QImage( (uchar*) image->data, image->width, image->height, image->bytes_per_line, QImage::Format_RGB32 ); +#endif + painted = false; +} + + +void QTestLiteWindowSurface::resizeBuffer(QSize s) +{ + if (shm_img.size() != s) + resizeShmImage(s.width(), s.height()); +} + +QSize QTestLiteWindowSurface::bufferSize() const +{ + return shm_img.size(); +} + +QTestLiteWindowSurface::QTestLiteWindowSurface (QTestLiteScreen */*screen*/, QWidget *window) + : QWindowSurface(window), + painted(false), image_info(0) +{ + xw = static_cast<QTestLiteWindow*>(window->platformWindow()); +// qDebug() << "QTestLiteWindowSurface::QTestLiteWindowSurface:" << xw->window; +} + +QTestLiteWindowSurface::~QTestLiteWindowSurface() +{ + delete image_info; +} + +QPaintDevice *QTestLiteWindowSurface::paintDevice() +{ + return &shm_img; +} + + +void QTestLiteWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(region); + Q_UNUSED(offset); + + // qDebug() << "QTestLiteWindowSurface::flush:" << (long)this; + + if (!painted) + return; + + MyDisplay *xd = xw->xd; + GC gc = xw->gc; + Window window = xw->x_window; +#ifdef DONT_USE_MIT_SHM + // just convert the image every time... + if (!shm_img.isNull()) { + Visual *visual = DefaultVisual(xd->display, xd->screen); + + QImage image = shm_img; + //img.convertToFormat( + XImage *xi = XCreateImage(xd->display, visual, 24, ZPixmap, + 0, (char *) image.scanLine(0), image.width(), image.height(), + 32, image.bytesPerLine()); + + int x = 0; + int y = 0; + + /*int r =*/ XPutImage(xd->display, window, gc, xi, 0, 0, x, y, image.width(), image.height()); + + xi->data = 0; // QImage owns these bits + XDestroyImage(xi); + } +#else + // Use MIT_SHM + if (image_info && image_info->image) { + //qDebug() << "Here we go" << image_info->image->width << image_info->image->height; + int x = 0; + int y = 0; + + // We could set send_event to true, and then use the ShmCompletion to synchronize, + // but let's do like Qt/11 and just use XSync + XShmPutImage (xd->display, window, gc, image_info->image, 0, 0, + x, y, image_info->image->width, image_info->image->height, + /*send_event*/ False); + + XSync(xd->display, False); + } +#endif +} + +// from qwindowsurface.cpp +extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); + +bool QTestLiteWindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + if (shm_img.isNull()) + return false; + + const QVector<QRect> rects = area.rects(); + for (int i = 0; i < rects.size(); ++i) + qt_scrollRectInImage(shm_img, rects.at(i), QPoint(dx, dy)); + + return true; +} + + +void QTestLiteWindowSurface::beginPaint(const QRegion ®ion) +{ + Q_UNUSED(region); + resizeBuffer(size()); +} + +void QTestLiteWindowSurface::endPaint(const QRegion ®ion) +{ + Q_UNUSED(region); + painted = true; //there is content in the buffer +} +QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestlitewindowsurface.h b/src/plugins/platforms/testlite/qtestlitewindowsurface.h new file mode 100644 index 0000000..915e7fe --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitewindowsurface.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_TESTLITE_H +#define QWINDOWSURFACE_TESTLITE_H + +#include <QtGui/private/qwindowsurface_p.h> + + +QT_BEGIN_NAMESPACE + +class QTestLiteWindow; +class QTestLiteIntegration; +class QTestLiteScreen; +class MyShmImageInfo; + +class QTestLiteWindowSurface : public QWindowSurface +{ +public: + QTestLiteWindowSurface (QTestLiteScreen *screen, QWidget *window); + ~QTestLiteWindowSurface(); + + QPaintDevice *paintDevice(); +// void flush(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); +// void resize(const QSize &size); + bool scroll(const QRegion &area, int dx, int dy); + + void beginPaint(const QRegion ®ion); + void endPaint(const QRegion ®ion); + +private: + bool painted; + void resizeBuffer(QSize); + QSize bufferSize() const; + + + void resizeShmImage(int width, int height); + + QImage shm_img; + MyShmImageInfo *image_info; + + QTestLiteWindow *xw; + +}; + + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/testlite/testlite.pro b/src/plugins/platforms/testlite/testlite.pro new file mode 100644 index 0000000..05bd384 --- /dev/null +++ b/src/plugins/platforms/testlite/testlite.pro @@ -0,0 +1,29 @@ +TARGET = qtestlite + +include(../../qpluginbase.pri) +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +SOURCES = \ + main.cpp \ + qtestliteintegration.cpp \ + qtestlitewindowsurface.cpp \ + qtestlitewindow.cpp + +HEADERS = \ + qtestliteintegration.h \ + qtestlitewindowsurface.h \ + qtestlitewindow.h + + +LIBS += -lX11 -lXext + +include (../fontdatabases/genericunix/genericunix.pri) + +contains(QT_CONFIG, opengl) { + QT += opengl + HEADERS += qglxintegration.h + SOURCES += qglxintegration.cpp +} + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target diff --git a/src/plugins/platforms/vnc/main.cpp b/src/plugins/platforms/vnc/main.cpp new file mode 100644 index 0000000..e051e2d --- /dev/null +++ b/src/plugins/platforms/vnc/main.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 plugins 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 "qvncintegration.h" +#include <qstringlist.h> +#include <QtGui/QPlatformIntegrationPlugin> + +QT_BEGIN_NAMESPACE + +class QVNCIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList &); +}; + +QStringList QVNCIntegrationPlugin::keys() const +{ + QStringList list; + list << "VNC"; + return list; +} + +QPlatformIntegration* QVNCIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "vnc") + return new QVNCIntegration(paramList); + + return 0; +} + +Q_EXPORT_PLUGIN2(vnc, QVNCIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/vnc/qvnccursor.cpp b/src/plugins/platforms/vnc/qvnccursor.cpp new file mode 100644 index 0000000..e83696d --- /dev/null +++ b/src/plugins/platforms/vnc/qvnccursor.cpp @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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 <QPainter> +#include <QTcpSocket> +#include <arpa/inet.h> +#include <QBitmap> +#include <QApplication> + +#include <QDebug> + +#include "qvnccursor.h" +#include "qvncserver.h" +#include "qvncintegration.h" + +QT_BEGIN_NAMESPACE + +QVNCCursor::QVNCCursor(QVNCServer * srvr, QVNCScreen *scr ) + :QPlatformSoftwareCursor(scr), useVncCursor(false), server(srvr) +{ +} + +void QVNCCursor::changeCursor(QCursor * widgetCursor, QWidget * widget) +{ + QPlatformSoftwareCursor::changeCursor(widgetCursor, widget); + if (useVncCursor) { + server->setDirtyCursor(); + } else { + setDirty(); + } +} + +void QVNCCursor::setCursorMode(bool vnc) +{ + if (vnc) { + setDirty(); + server->setDirtyCursor(); + } else { + server->setDirtyCursor(); + } + useVncCursor = vnc; +} + +QRect QVNCCursor::drawCursor(QPainter & painter) +{ + if (useVncCursor) + return QRect(); + + return QPlatformSoftwareCursor::drawCursor(painter); +} + +void QVNCCursor::clearClientCursor() +{ + QTcpSocket *socket = server->clientSocket(); + if (!socket) { + return; + } + // FramebufferUpdate header + { + const quint16 tmp[6] = { htons(0), + htons(1), + htons(0), htons(0), + htons(0), + htons(0) }; + socket->write((char*)tmp, sizeof(tmp)); + + const quint32 encoding = htonl(-239); + socket->write((char*)(&encoding), sizeof(encoding)); + } +} + +void QVNCCursor::sendClientCursor() +{ + if (useVncCursor == false) { + clearClientCursor(); + return; + } + QImage *image = graphic->image(); + if (image->isNull()) + return; + QTcpSocket *socket = server->clientSocket(); + if (!socket) { + return; + } + // FramebufferUpdate header + { + const quint16 tmp[6] = { htons(0), + htons(1), + htons(graphic->hotspot().x()), htons(graphic->hotspot().y()), + htons(image->width()), + htons(image->height()) }; + socket->write((char*)tmp, sizeof(tmp)); + + const quint32 encoding = htonl(-239); + socket->write((char*)(&encoding), sizeof(encoding)); + } + + // write pixels + //Q_ASSERT(cursor->hasAlphaChannel()); + const QImage img = image->convertToFormat(QImage::Format_RGB32); + const int n = server->clientBytesPerPixel() * img.width(); + char *buffer = new char[n]; + for (int i = 0; i < img.height(); ++i) { + server->convertPixels(buffer, (const char*)img.scanLine(i), img.width()); + socket->write(buffer, n); + } + delete[] buffer; + + // write mask + const QImage bitmap = image->createAlphaMask().convertToFormat(QImage::Format_Mono); + Q_ASSERT(bitmap.depth() == 1); + Q_ASSERT(bitmap.size() == img.size()); + const int width = (bitmap.width() + 7) / 8; + for (int i = 0; i < bitmap.height(); ++i) + socket->write((const char*)bitmap.scanLine(i), width); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/vnc/qvnccursor.h b/src/plugins/platforms/vnc/qvnccursor.h new file mode 100644 index 0000000..eeb3686 --- /dev/null +++ b/src/plugins/platforms/vnc/qvnccursor.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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 QtOpenVG 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$ +** +****************************************************************************/ +#ifndef QVNCCURSOR_H +#define QVNCCURSOR_H + +#include "../fb_base/fb_base.h" +#include <QList> +#include <QImage> +#include <QMouseEvent> + +QT_BEGIN_NAMESPACE + +class QVNCScreen; +class QVNCServer; + +class QVNCCursor : public QPlatformSoftwareCursor { +public: + QVNCCursor(QVNCServer *, QVNCScreen *); + + // input methods + void setCursorMode(bool vnc); + void changeCursor(QCursor * widgetCursor, QWidget * widget); + + // output methods + QRect drawCursor(QPainter &); + + // VNC client communication + void sendClientCursor(); + void clearClientCursor(); +private: + bool useVncCursor; // VNC or local + + QVNCServer * server; // VNC server to get events from +}; + +QT_END_NAMESPACE + +#endif // QVNCCURSOR_H diff --git a/src/plugins/platforms/vnc/qvncintegration.cpp b/src/plugins/platforms/vnc/qvncintegration.cpp new file mode 100644 index 0000000..b36ff33 --- /dev/null +++ b/src/plugins/platforms/vnc/qvncintegration.cpp @@ -0,0 +1,242 @@ +/**************************************************************************** +** +** 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 plugins 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 "qvncintegration.h" +#include "../fb_base/fb_base.h" +#include <private/qapplication_p.h> +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtCore/qdebug.h> + +#include <qvncserver.h> +#include <QtGui/QPainter> + +#include <QtCore/QTimer> +#include "qgenericunixfontdatabase.h" + +QVNCScreen::QVNCScreen(QRect screenSize, int screenId) + : QFbScreen::QFbScreen() +{ + setGeometry(screenSize); + setDepth(32); + setFormat(QImage::Format_RGB32); + setPhysicalSize((geometry().size()*254)/720); + + + d_ptr = new QVNCScreenPrivate(this, screenId); + + cursor = new QVNCCursor(d_ptr->vncServer, this); + d_ptr->vncServer->setCursor(static_cast<QVNCCursor *>(cursor)); +} + +QVNCDirtyMap *QVNCScreen::dirtyMap() +{ + return d_ptr->dirty; +} + +QRegion QVNCScreen::doRedraw() +{ + QRegion touched; + touched = QFbScreen::doRedraw(); + + QVector<QRect> rects = touched.rects(); + for (int i = 0; i < rects.size(); i++) + d_ptr->setDirty(rects[i]); + return touched; +} + +static inline int defaultWidth() { return 800; } +static inline int defaultHeight() { return 600; } +static inline int defaultDisplay() { return 0; } + +static void usage() +{ + qWarning() << "VNC Platform Integration options:"; + qWarning() << " size=<Width>x<Height> - set the display width and height"; + qWarning() << " defaults to" << defaultWidth() << "x" << defaultHeight(); + qWarning() << " display=<ID> - set the VNC display port to ID + 5900"; + qWarning() << " defaults to" << defaultDisplay(); + qWarning() << " offset=<X>x<Y> - set the current screens offset"; + qWarning() << " vnc - start configuration of a new screen"; + qWarning() << " size and offset are inherited from the previous screen if not set"; + qWarning() << " display id is incremented from the previous screen if not set"; + qWarning() << " virtual - manage the set of screens as a virtual desktop"; +} + +QVNCIntegration::QVNCIntegration(const QStringList& paramList) + : virtualDesktop(false), fontDb(new QGenericUnixFontDatabase()) +{ + int sizeX = defaultWidth(); + int sizeY = defaultHeight(); + int offsetX = 0; + int offsetY = 0; + int display = defaultDisplay(); + bool showUsage = false; + + foreach(QString confString, paramList) { + if (confString.startsWith(QLatin1String("size="))) { + QString val = confString.section(QLatin1Char('='), 1, 1); + sizeX = val.section(QLatin1Char('x'), 0, 0).toInt(); + sizeY = val.section(QLatin1Char('x'), 1, 1).toInt(); + } + else if (confString.startsWith(QLatin1String("display="))) { + display = confString.section(QLatin1Char('='), 1, 1).toInt(); + } + else if (confString.startsWith(QLatin1String("offset="))) { + QString val = confString.section(QLatin1Char('='), 1, 1); + offsetX = val.section(QLatin1Char('x'), 0, 0).toInt(); + offsetY = val.section(QLatin1Char('x'), 1, 1).toInt(); + } + else if (confString == QLatin1String("vnc")) { + QRect screenRect(offsetX, offsetY, sizeX, sizeY); + QVNCScreen *screen = new QVNCScreen(screenRect, display); + mScreens.append(screen); + screen->setObjectName(QString("screen %1").arg(display)); + screen->setDirty(screenRect); + ++display; + } + else if (confString == QLatin1String("virtual")) { + virtualDesktop = true; + } + else { + qWarning() << "Unknown VNC option:" << confString; + showUsage = true; + } + } + + if (showUsage) + usage(); + + QRect screenRect(offsetX, offsetY, sizeX, sizeY); + QVNCScreen *screen = new QVNCScreen(screenRect, display); + mScreens.append(screen); + mPrimaryScreen = qobject_cast<QVNCScreen *>(mScreens.first()); + screen->setObjectName(QString("screen %1").arg(display)); + screen->setDirty(screenRect); +} + +QPixmapData *QVNCIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QWindowSurface *QVNCIntegration::createWindowSurface(QWidget *widget, WId) const +{ + QFbWindowSurface * surface; + surface = new QFbWindowSurface(mPrimaryScreen, widget); + return surface; +} + + +QPlatformWindow *QVNCIntegration::createPlatformWindow(QWidget *widget, WId /*winId*/) const +{ + QFbWindow *w = new QFbWindow(widget); + if (virtualDesktop) { + QList<QPlatformScreen *>::const_iterator i = mScreens.constBegin(); + QList<QPlatformScreen *>::const_iterator end = mScreens.constEnd(); + QFbScreen *screen; + while (i != end) { + screen = static_cast<QFbScreen *>(*i); + screen->addWindow(w); + ++i; + } + } + else + mPrimaryScreen->addWindow(w); + return w; +} + +QPixmap QVNCIntegration::grabWindow(WId window, int x, int y, int width, int height) const +{ +// qDebug() << "QVNCIntegration::grabWindow" << window << x << y << width << height; + + if (window == 0) { //desktop + QImage *desktopImage = mPrimaryScreen->image(); + if (x==0 && y == 0 && width < 0 && height < 0) { + return QPixmap::fromImage(*desktopImage); + } + if (width < 0) + width = desktopImage->width() - x; + if (height < 0) + height = desktopImage->height() - y; + int bytesPerPixel = desktopImage->depth()/8; //We don't support 1, 2, or 4 bpp + QImage img(desktopImage->scanLine(y) + bytesPerPixel*x, width, height, desktopImage->bytesPerLine(), desktopImage->format()); + return QPixmap::fromImage(img); + } + QWidget *win = QWidget::find(window); + if (win) { + QRect r = win->geometry(); + if (width < 0) + width = r.width() - x; + if (height < 0) + height = r.height() - y; + QImage *desktopImage = mPrimaryScreen->image(); + int bytesPerPixel = desktopImage->depth()/8; //We don't support 1, 2, or 4 bpp + + QImage img(desktopImage->scanLine(r.top() + y) + bytesPerPixel*(r.left()+x), width, height, desktopImage->bytesPerLine(), desktopImage->format()); + return QPixmap::fromImage(img); + } + return QPixmap(); +} + + +void QVNCIntegration::moveToScreen(QWidget *window, int screen) +{ + if (virtualDesktop) { // all windows exist on all screens in virtual desktop mode + return; + } + if (screen < 0 || screen > mScreens.size()) + return; + QVNCScreen * newScreen = qobject_cast<QVNCScreen *>(mScreens.at(screen)); + for(int i = 0; i < mScreens.size(); i++) { + QVNCScreen *oldScreen = qobject_cast<QVNCScreen *>(mScreens.at(i)); + if (oldScreen->windowStack.contains(static_cast<QFbWindow *>(window->platformWindow()))) { + oldScreen->removeWindow(static_cast<QFbWindow *>(window->platformWindow())); + break; + } + } + window->platformWindow()->setGeometry(window->geometry()); // this should be unified elsewhere + newScreen->addWindow(static_cast<QFbWindow *>(window->platformWindow())); +} + +QPlatformFontDatabase *QVNCIntegration::fontDatabase() const +{ + return fontDb; +} diff --git a/src/plugins/platforms/vnc/qvncintegration.h b/src/plugins/platforms/vnc/qvncintegration.h new file mode 100644 index 0000000..dfc0e6b --- /dev/null +++ b/src/plugins/platforms/vnc/qvncintegration.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSYSTEM_VNC_H +#define QGRAPHICSSYSTEM_VNC_H + +#include "qvnccursor.h" +#include "../fb_base/fb_base.h" +#include <QPlatformIntegration> +#include "qgenericunixfontdatabase.h" + +QT_BEGIN_NAMESPACE + +class QVNCServer; +class QVNCDirtyMap; + +class QVNCScreenPrivate; + +class QVNCScreen : public QFbScreen +{ + Q_OBJECT +public: + QVNCScreen(QRect screenSize, int screenId); + + int linestep() const { return image() ? image()->bytesPerLine() : 0; } + uchar *base() const { return image() ? image()->bits() : 0; } + QVNCDirtyMap *dirtyMap(); + +public: + QVNCScreenPrivate *d_ptr; + +private: + QVNCServer *server; + QRegion doRedraw(); + friend class QVNCIntegration; +}; + +class QVNCIntegrationPrivate; + + +class QVNCIntegration : public QPlatformIntegration +{ +public: + QVNCIntegration(const QStringList& paramList); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QPixmap grabWindow(WId window, int x, int y, int width, int height) const; + + QList<QPlatformScreen *> screens() const { return mScreens; } + + bool isVirtualDesktop() { return virtualDesktop; } + void moveToScreen(QWidget *window, int screen); + + QPlatformFontDatabase *fontDatabase() const; + +private: + QVNCScreen *mPrimaryScreen; + QList<QPlatformScreen *> mScreens; + bool virtualDesktop; + QPlatformFontDatabase *fontDb; +}; + + + +QT_END_NAMESPACE + +#endif //QGRAPHICSSYSTEM_VNC_H + diff --git a/src/plugins/platforms/vnc/qvncserver.cpp b/src/plugins/platforms/vnc/qvncserver.cpp new file mode 100644 index 0000000..288d1bc --- /dev/null +++ b/src/plugins/platforms/vnc/qvncserver.cpp @@ -0,0 +1,1935 @@ +/**************************************************************************** +** +** 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 plugins 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 "qvncserver.h" + +#include <QtCore/qtimer.h> +#include <QtCore/qregexp.h> +#include <QtGui/qwidget.h> +#include <QtGui/qpolygon.h> +#include <QtGui/qpainter.h> + +#include <QtGui/qevent.h> +#include <QWindowSystemInterface> + +#include <qplatformdefs.h> + +#include <qdebug.h> + +#include <stdlib.h> + + +#define QT_QWS_VNC_DEBUG +#define QT_NO_QWS_CURSOR //### + + +QT_BEGIN_NAMESPACE + + + +//copied from qscreen_qws.h +#ifndef QT_QWS_DEPTH16_RGB +#define QT_QWS_DEPTH16_RGB 565 +#endif +static const int qt_rbits = (QT_QWS_DEPTH16_RGB/100); +static const int qt_gbits = (QT_QWS_DEPTH16_RGB/10%10); +static const int qt_bbits = (QT_QWS_DEPTH16_RGB%10); +static const int qt_red_shift = qt_bbits+qt_gbits-(8-qt_rbits); +static const int qt_green_shift = qt_bbits-(8-qt_gbits); +static const int qt_neg_blue_shift = 8-qt_bbits; +static const int qt_blue_mask = (1<<qt_bbits)-1; +static const int qt_green_mask = (1<<(qt_gbits+qt_bbits))-(1<<qt_bbits); +static const int qt_red_mask = (1<<(qt_rbits+qt_gbits+qt_bbits))-(1<<(qt_gbits+qt_bbits)); + +static const int qt_red_rounding_shift = qt_red_shift + qt_rbits; +static const int qt_green_rounding_shift = qt_green_shift + qt_gbits; +static const int qt_blue_rounding_shift = qt_bbits - qt_neg_blue_shift; + + +inline QRgb qt_conv16ToRgb(ushort c) +{ + const int r=(c & qt_red_mask); + const int g=(c & qt_green_mask); + const int b=(c & qt_blue_mask); + const int tr = r >> qt_red_shift | r >> qt_red_rounding_shift; + const int tg = g >> qt_green_shift | g >> qt_green_rounding_shift; + const int tb = b << qt_neg_blue_shift | b >> qt_blue_rounding_shift; + + return qRgb(tr,tg,tb); +} + + + +//=========================================================================== + +static const struct { + int keysym; + int keycode; +} keyMap[] = { + { 0xff08, Qt::Key_Backspace }, + { 0xff09, Qt::Key_Tab }, + { 0xff0d, Qt::Key_Return }, + { 0xff1b, Qt::Key_Escape }, + { 0xff63, Qt::Key_Insert }, + { 0xffff, Qt::Key_Delete }, + { 0xff50, Qt::Key_Home }, + { 0xff57, Qt::Key_End }, + { 0xff55, Qt::Key_PageUp }, + { 0xff56, Qt::Key_PageDown }, + { 0xff51, Qt::Key_Left }, + { 0xff52, Qt::Key_Up }, + { 0xff53, Qt::Key_Right }, + { 0xff54, Qt::Key_Down }, + { 0xffbe, Qt::Key_F1 }, + { 0xffbf, Qt::Key_F2 }, + { 0xffc0, Qt::Key_F3 }, + { 0xffc1, Qt::Key_F4 }, + { 0xffc2, Qt::Key_F5 }, + { 0xffc3, Qt::Key_F6 }, + { 0xffc4, Qt::Key_F7 }, + { 0xffc5, Qt::Key_F8 }, + { 0xffc6, Qt::Key_F9 }, + { 0xffc7, Qt::Key_F10 }, + { 0xffc8, Qt::Key_F11 }, + { 0xffc9, Qt::Key_F12 }, + { 0xffe1, Qt::Key_Shift }, + { 0xffe2, Qt::Key_Shift }, + { 0xffe3, Qt::Key_Control }, + { 0xffe4, Qt::Key_Control }, + { 0xffe7, Qt::Key_Meta }, + { 0xffe8, Qt::Key_Meta }, + { 0xffe9, Qt::Key_Alt }, + { 0xffea, Qt::Key_Alt }, + { 0, 0 } +}; + +void QRfbRect::read(QTcpSocket *s) +{ + quint16 buf[4]; + s->read((char*)buf, 8); + x = ntohs(buf[0]); + y = ntohs(buf[1]); + w = ntohs(buf[2]); + h = ntohs(buf[3]); +} + +void QRfbRect::write(QTcpSocket *s) const +{ + quint16 buf[4]; + buf[0] = htons(x); + buf[1] = htons(y); + buf[2] = htons(w); + buf[3] = htons(h); + s->write((char*)buf, 8); +} + +void QRfbPixelFormat::read(QTcpSocket *s) +{ + char buf[16]; + s->read(buf, 16); + bitsPerPixel = buf[0]; + depth = buf[1]; + bigEndian = buf[2]; + trueColor = buf[3]; + + quint16 a = ntohs(*(quint16 *)(buf + 4)); + redBits = 0; + while (a) { a >>= 1; redBits++; } + + a = ntohs(*(quint16 *)(buf + 6)); + greenBits = 0; + while (a) { a >>= 1; greenBits++; } + + a = ntohs(*(quint16 *)(buf + 8)); + blueBits = 0; + while (a) { a >>= 1; blueBits++; } + + redShift = buf[10]; + greenShift = buf[11]; + blueShift = buf[12]; +} + +void QRfbPixelFormat::write(QTcpSocket *s) +{ + char buf[16]; + buf[0] = bitsPerPixel; + buf[1] = depth; + buf[2] = bigEndian; + buf[3] = trueColor; + + quint16 a = 0; + for (int i = 0; i < redBits; i++) a = (a << 1) | 1; + *(quint16 *)(buf + 4) = htons(a); + + a = 0; + for (int i = 0; i < greenBits; i++) a = (a << 1) | 1; + *(quint16 *)(buf + 6) = htons(a); + + a = 0; + for (int i = 0; i < blueBits; i++) a = (a << 1) | 1; + *(quint16 *)(buf + 8) = htons(a); + + buf[10] = redShift; + buf[11] = greenShift; + buf[12] = blueShift; + s->write(buf, 16); +} + + +void QRfbServerInit::setName(const char *n) +{ + delete[] name; + name = new char [strlen(n) + 1]; + strcpy(name, n); +} + +void QRfbServerInit::read(QTcpSocket *s) +{ + s->read((char *)&width, 2); + width = ntohs(width); + s->read((char *)&height, 2); + height = ntohs(height); + format.read(s); + + quint32 len; + s->read((char *)&len, 4); + len = ntohl(len); + + name = new char [len + 1]; + s->read(name, len); + name[len] = '\0'; +} + +void QRfbServerInit::write(QTcpSocket *s) +{ + quint16 t = htons(width); + s->write((char *)&t, 2); + t = htons(height); + s->write((char *)&t, 2); + format.write(s); + quint32 len = strlen(name); + len = htonl(len); + s->write((char *)&len, 4); + s->write(name, strlen(name)); +} + +bool QRfbSetEncodings::read(QTcpSocket *s) +{ + if (s->bytesAvailable() < 3) + return false; + + char tmp; + s->read(&tmp, 1); // padding + s->read((char *)&count, 2); + count = ntohs(count); + + return true; +} + +bool QRfbFrameBufferUpdateRequest::read(QTcpSocket *s) +{ + if (s->bytesAvailable() < 9) + return false; + + s->read(&incremental, 1); + rect.read(s); + + return true; +} + +bool QRfbKeyEvent::read(QTcpSocket *s) +{ + if (s->bytesAvailable() < 7) + return false; + + s->read(&down, 1); + quint16 tmp; + s->read((char *)&tmp, 2); // padding + + quint32 key; + s->read((char *)&key, 4); + key = ntohl(key); + + unicode = 0; + keycode = 0; + int i = 0; + while (keyMap[i].keysym && !keycode) { + if (keyMap[i].keysym == (int)key) + keycode = keyMap[i].keycode; + i++; + } + if (!keycode) { + if (key <= 0xff) { + unicode = key; + if (key >= 'a' && key <= 'z') + keycode = Qt::Key_A + key - 'a'; + else if (key >= ' ' && key <= '~') + keycode = Qt::Key_Space + key - ' '; + } + } + + return true; +} + +bool QRfbPointerEvent::read(QTcpSocket *s) +{ + if (s->bytesAvailable() < 5) + return false; + + char buttonMask; + s->read(&buttonMask, 1); + + buttons = Qt::NoButton; + wheelDirection = WheelNone; + if (buttonMask & 1) + buttons |= Qt::LeftButton; + if (buttonMask & 2) + buttons |= Qt::MidButton; + if (buttonMask & 4) + buttons |= Qt::RightButton; + if (buttonMask & 8) + wheelDirection = WheelUp; + if (buttonMask & 16) + wheelDirection = WheelDown; + if (buttonMask & 32) + wheelDirection = WheelLeft; + if (buttonMask & 64) + wheelDirection = WheelRight; + + quint16 tmp; + s->read((char *)&tmp, 2); + x = ntohs(tmp); + s->read((char *)&tmp, 2); + y = ntohs(tmp); + + return true; +} + +bool QRfbClientCutText::read(QTcpSocket *s) +{ + if (s->bytesAvailable() < 7) + return false; + + char tmp[3]; + s->read(tmp, 3); // padding + s->read((char *)&length, 4); + length = ntohl(length); + + return true; +} + +//=========================================================================== + +QVNCServer::QVNCServer(QVNCScreen *screen) + : qvnc_screen(screen), cursor(0) +{ + init(5900); +} + +QVNCServer::QVNCServer(QVNCScreen *screen, int id) + : qvnc_screen(screen), cursor(0) +{ + init(5900 + id); +} + +void QVNCServer::init(uint port) +{ + qDebug() << "QVNCServer::init" << port; + + handleMsg = false; + client = 0; + encodingsPending = 0; + cutTextPending = 0; + keymod = 0; + state = Unconnected; + dirtyCursor = false; + + refreshRate = 25; + timer = new QTimer(this); + timer->setSingleShot(true); + connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); + + serverSocket = new QTcpServer(this); + if (!serverSocket->listen(QHostAddress::Any, port)) + qDebug() << "QVNCServer could not connect:" << serverSocket->errorString(); + else + qDebug("QVNCServer created on port %d", port); + + connect(serverSocket, SIGNAL(newConnection()), this, SLOT(newConnection())); + +#ifndef QT_NO_QWS_CURSOR + qvnc_cursor = 0; +#endif + encoder = 0; +} + +QVNCServer::~QVNCServer() +{ + delete encoder; + encoder = 0; + delete client; + client = 0; +#ifndef QT_NO_QWS_CURSOR + delete qvnc_cursor; + qvnc_cursor = 0; +#endif +} + +void QVNCServer::setDirty() +{ + if (state == Connected && !timer->isActive() && + ((dirtyMap()->numDirty > 0) || dirtyCursor)) { + timer->start(); + } +} + +void QVNCServer::newConnection() +{ + if (client) + delete client; + + client = serverSocket->nextPendingConnection(); + connect(client,SIGNAL(readyRead()),this,SLOT(readClient())); + connect(client,SIGNAL(disconnected()),this,SLOT(discardClient())); + handleMsg = false; + encodingsPending = 0; + cutTextPending = 0; + supportHextile = false; + wantUpdate = false; + + timer->start(1000 / refreshRate); + dirtyMap()->reset(); + + // send protocol version + const char *proto = "RFB 003.003\n"; + client->write(proto, 12); + state = Protocol; + +// if (!qvnc_screen->screen()) +// QWSServer::instance()->enablePainting(true); +} + +void QVNCServer::readClient() +{ + switch (state) { + case Protocol: + if (client->bytesAvailable() >= 12) { + char proto[13]; + client->read(proto, 12); + proto[12] = '\0'; + qDebug("Client protocol version %s", proto); + // No authentication + quint32 auth = htonl(1); + client->write((char *) &auth, sizeof(auth)); + state = Init; + } + break; + + case Init: + if (client->bytesAvailable() >= 1) { + quint8 shared; + client->read((char *) &shared, 1); + + // Server Init msg + QRfbServerInit sim; + QRfbPixelFormat &format = sim.format; + switch (qvnc_screen->depth()) { + case 32: + format.bitsPerPixel = 32; + format.depth = 32; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 8; + format.greenBits = 8; + format.blueBits = 8; + format.redShift = 16; + format.greenShift = 8; + format.blueShift = 0; + break; + + case 24: + format.bitsPerPixel = 24; + format.depth = 24; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 8; + format.greenBits = 8; + format.blueBits = 8; + format.redShift = 16; + format.greenShift = 8; + format.blueShift = 0; + break; + + case 18: + format.bitsPerPixel = 24; + format.depth = 18; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 6; + format.greenBits = 6; + format.blueBits = 6; + format.redShift = 12; + format.greenShift = 6; + format.blueShift = 0; + break; + + case 16: + format.bitsPerPixel = 16; + format.depth = 16; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 5; + format.greenBits = 6; + format.blueBits = 5; + format.redShift = 11; + format.greenShift = 5; + format.blueShift = 0; + break; + + case 15: + format.bitsPerPixel = 16; + format.depth = 15; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 5; + format.greenBits = 5; + format.blueBits = 5; + format.redShift = 10; + format.greenShift = 5; + format.blueShift = 0; + break; + + case 12: + format.bitsPerPixel = 16; + format.depth = 12; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 4; + format.greenBits = 4; + format.blueBits = 4; + format.redShift = 8; + format.greenShift = 4; + format.blueShift = 0; + break; + + case 8: + case 4: + format.bitsPerPixel = 8; + format.depth = 8; + format.bigEndian = 0; + format.trueColor = false; + format.redBits = 0; + format.greenBits = 0; + format.blueBits = 0; + format.redShift = 0; + format.greenShift = 0; + format.blueShift = 0; + break; + + default: + qDebug("QVNC cannot drive depth %d", qvnc_screen->depth()); + discardClient(); + return; + } + sim.width = qvnc_screen->geometry().width(); + sim.height = qvnc_screen->geometry().height(); + sim.setName("Qt for Embedded Linux VNC Server"); + sim.write(client); + state = Connected; + } + break; + + case Connected: + do { + if (!handleMsg) { + client->read((char *)&msgType, 1); + handleMsg = true; + } + if (handleMsg) { + switch (msgType ) { + case SetPixelFormat: + setPixelFormat(); + break; + case FixColourMapEntries: + qDebug("Not supported: FixColourMapEntries"); + handleMsg = false; + break; + case SetEncodings: + setEncodings(); + break; + case FramebufferUpdateRequest: + frameBufferUpdateRequest(); + break; + case KeyEvent: + keyEvent(); + break; + case PointerEvent: + pointerEvent(); + break; + case ClientCutText: + clientCutText(); + break; + default: + qDebug("Unknown message type: %d", (int)msgType); + handleMsg = false; + } + } + } while (!handleMsg && client->bytesAvailable()); + break; + default: + break; + } +} + +#if 0//Q_BYTE_ORDER == Q_BIG_ENDIAN +bool QVNCScreen::swapBytes() const +{ + if (depth() != 16) + return false; + + if (screen()) + return screen()->frameBufferLittleEndian(); + return frameBufferLittleEndian(); +} +#endif + +void QVNCServer::setPixelFormat() +{ + if (client->bytesAvailable() >= 19) { + char buf[3]; + client->read(buf, 3); // just padding + pixelFormat.read(client); +#ifdef QT_QWS_VNC_DEBUG + qDebug("Want format: %d %d %d %d %d %d %d %d %d %d", + int(pixelFormat.bitsPerPixel), + int(pixelFormat.depth), + int(pixelFormat.bigEndian), + int(pixelFormat.trueColor), + int(pixelFormat.redBits), + int(pixelFormat.greenBits), + int(pixelFormat.blueBits), + int(pixelFormat.redShift), + int(pixelFormat.greenShift), + int(pixelFormat.blueShift)); +#endif + if (!pixelFormat.trueColor) { + qDebug("Can only handle true color clients"); + discardClient(); + } + handleMsg = false; + sameEndian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) == !!pixelFormat.bigEndian; + needConversion = pixelConversionNeeded(); +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + swapBytes = qvnc_screen->swapBytes(); +#endif + } +} + +void QVNCServer::setEncodings() +{ + QRfbSetEncodings enc; + + if (!encodingsPending && enc.read(client)) { + encodingsPending = enc.count; + if (!encodingsPending) + handleMsg = false; + } + + if (encoder) { + delete encoder; + encoder = 0; + } + + enum Encodings { + Raw = 0, + CopyRect = 1, + RRE = 2, + CoRRE = 4, + Hextile = 5, + ZRLE = 16, + Cursor = -239, + DesktopSize = -223 + }; + + supportCursor = false; + + if (encodingsPending && (unsigned)client->bytesAvailable() >= + encodingsPending * sizeof(quint32)) { + for (int i = 0; i < encodingsPending; ++i) { + qint32 enc; + client->read((char *)&enc, sizeof(qint32)); + enc = ntohl(enc); +#ifdef QT_QWS_VNC_DEBUG + qDebug("QVNCServer::setEncodings: %d", enc); +#endif + switch (enc) { + case Raw: + if (!encoder) { + encoder = new QRfbRawEncoder(this); +#ifdef QT_QWS_VNC_DEBUG + qDebug("QVNCServer::setEncodings: using raw"); +#endif + } + break; + case CopyRect: + supportCopyRect = true; + break; + case RRE: + supportRRE = true; + break; + case CoRRE: + supportCoRRE = true; + break; + case Hextile: + supportHextile = true; + if (encoder) + break; + switch (qvnc_screen->depth()) { +#ifdef QT_QWS_DEPTH_8 + case 8: + encoder = new QRfbHextileEncoder<quint8>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_12 + case 12: + encoder = new QRfbHextileEncoder<qrgb444>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_15 + case 15: + encoder = new QRfbHextileEncoder<qrgb555>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_16 + case 16: + encoder = new QRfbHextileEncoder<quint16>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_18 + case 18: + encoder = new QRfbHextileEncoder<qrgb666>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_24 + case 24: + encoder = new QRfbHextileEncoder<qrgb888>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_32 + case 32: + encoder = new QRfbHextileEncoder<quint32>(this); + break; +#endif + default: + break; + } +#ifdef QT_QWS_VNC_DEBUG + qDebug("QVNCServer::setEncodings: using hextile"); +#endif + break; + case ZRLE: + supportZRLE = true; + break; + case Cursor: + supportCursor = true; +#ifndef QT_NO_QWS_CURSOR + if (!qvnc_screen->screen() || qt_screencursor->isAccelerated()) { + delete qvnc_cursor; + qvnc_cursor = new QVNCClientCursor(this); + } +#endif + break; + case DesktopSize: + supportDesktopSize = true; + break; + default: + break; + } + } + handleMsg = false; + encodingsPending = 0; + } + + if (!encoder) { + encoder = new QRfbRawEncoder(this); +#ifdef QT_QWS_VNC_DEBUG + qDebug("QVNCServer::setEncodings: fallback using raw"); +#endif + } + + if (cursor) + cursor->setCursorMode(supportCursor); +} + +void QVNCServer::frameBufferUpdateRequest() +{ + QRfbFrameBufferUpdateRequest ev; + + if (ev.read(client)) { + if (!ev.incremental) { + QRect r(ev.rect.x, ev.rect.y, ev.rect.w, ev.rect.h); +////### r.translate(qvnc_screen->offset()); + qvnc_screen->d_ptr->setDirty(r, true); + } + wantUpdate = true; + checkUpdate(); + handleMsg = false; + } +} + +static bool buttonChange(Qt::MouseButtons before, Qt::MouseButtons after, Qt::MouseButton *button, bool *isPress) +{ + if (before == after) + return false; + for (int b = Qt::LeftButton; b <= Qt::MidButton; b<<=1) { + if ((before & b) != (after & b)) { + *button = static_cast<Qt::MouseButton>(b); + *isPress = (after & b); + return true; + } + } + return false; +} + +void QVNCServer::pointerEvent() +{ + QPoint screenOffset = this->screen()->geometry().topLeft(); + + QRfbPointerEvent ev; + if (ev.read(client)) { + QPoint eventPoint(ev.x, ev.y); + eventPoint += screenOffset; // local to global translation + + if (ev.wheelDirection == ev.WheelNone) { + QEvent::Type type = QEvent::MouseMove; + Qt::MouseButton button = Qt::NoButton; + bool isPress; + if (buttonChange(buttons, ev.buttons, &button, &isPress)) + type = isPress ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease; + QWindowSystemInterface::handleMouseEvent(0, eventPoint, eventPoint, ev.buttons); + } else { + // No buttons or motion reported at the same time as wheel events + Qt::Orientation orientation; + if (ev.wheelDirection == ev.WheelLeft || ev.wheelDirection == ev.WheelRight) + orientation = Qt::Horizontal; + else + orientation = Qt::Vertical; + int delta = 120 * ((ev.wheelDirection == ev.WheelLeft || ev.wheelDirection == ev.WheelUp) ? 1 : -1); + QWindowSystemInterface::handleWheelEvent(0, eventPoint, eventPoint, delta, orientation); + } + handleMsg = false; + } +} + +void QVNCServer::keyEvent() +{ + QRfbKeyEvent ev; + + if (ev.read(client)) { + if (ev.keycode == Qt::Key_Shift) + keymod = ev.down ? keymod | Qt::ShiftModifier : + keymod & ~Qt::ShiftModifier; + else if (ev.keycode == Qt::Key_Control) + keymod = ev.down ? keymod | Qt::ControlModifier : + keymod & ~Qt::ControlModifier; + else if (ev.keycode == Qt::Key_Alt) + keymod = ev.down ? keymod | Qt::AltModifier : + keymod & ~Qt::AltModifier; + if (ev.unicode || ev.keycode) { +// qDebug() << "keyEvent" << hex << ev.unicode << ev.keycode << keymod << ev.down; + QEvent::Type type = ev.down ? QEvent::KeyPress : QEvent::KeyRelease; + QString str; + if (ev.unicode && ev.unicode != 0xffff) + str = QString(ev.unicode); + QWindowSystemInterface::handleKeyEvent(0, type, ev.keycode, keymod, str); + } + handleMsg = false; + } +} + +void QVNCServer::clientCutText() +{ + QRfbClientCutText ev; + + if (cutTextPending == 0 && ev.read(client)) { + cutTextPending = ev.length; + if (!cutTextPending) + handleMsg = false; + } + + if (cutTextPending && client->bytesAvailable() >= cutTextPending) { + char *text = new char [cutTextPending+1]; + client->read(text, cutTextPending); + delete [] text; + cutTextPending = 0; + handleMsg = false; + } +} + +// stride in bytes +template <class SRC> +bool QRfbSingleColorHextile<SRC>::read(const uchar *data, + int width, int height, int stride) +{ + const int depth = encoder->server->screen()->depth(); + if (width % (depth / 8)) // hw: should rather fallback to simple loop + return false; + + static int alwaysFalse = qgetenv("QT_VNC_NOCHECKFILL").toInt(); + if (alwaysFalse) + return false; + + switch (depth) { + case 4: { + const quint8 *data8 = reinterpret_cast<const quint8*>(data); + if ((data8[0] & 0xf) != (data8[0] >> 4)) + return false; + width /= 2; + } // fallthrough + case 8: { + const quint8 *data8 = reinterpret_cast<const quint8*>(data); + if (data8[0] != data8[1]) + return false; + width /= 2; + } // fallthrough + case 12: + case 15: + case 16: { + const quint16 *data16 = reinterpret_cast<const quint16*>(data); + if (data16[0] != data16[1]) + return false; + width /= 2; + } // fallthrough + case 18: + case 24: + case 32: { + const quint32 *data32 = reinterpret_cast<const quint32*>(data); + const quint32 first = data32[0]; + const int linestep = (stride / sizeof(quint32)) - width; + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + if (*(data32++) != first) + return false; + } + data32 += linestep; + } + break; + } + default: + return false; + } + + SRC color = reinterpret_cast<const SRC*>(data)[0]; + encoder->newBg |= (color != encoder->bg); + encoder->bg = color; + return true; +} + +template <class SRC> +void QRfbSingleColorHextile<SRC>::write(QTcpSocket *socket) const +{ + if (true || encoder->newBg) { + const int bpp = encoder->server->clientBytesPerPixel(); + const int padding = 3; + QVarLengthArray<char> buffer(padding + 1 + bpp); + buffer[padding] = 2; // BackgroundSpecified + encoder->server->convertPixels(buffer.data() + padding + 1, + reinterpret_cast<char*>(&encoder->bg), + 1); + socket->write(buffer.data() + padding, bpp + 1); +// encoder->newBg = false; + } else { + char subenc = 0; + socket->write(&subenc, 1); + } +} + +template <class SRC> +bool QRfbDualColorHextile<SRC>::read(const uchar *data, + int width, int height, int stride) +{ + const SRC *ptr = reinterpret_cast<const SRC*>(data); + const int linestep = (stride / sizeof(SRC)) - width; + + SRC c1; + SRC c2 = 0; + int n1 = 0; + int n2 = 0; + int x = 0; + int y = 0; + + c1 = *ptr; + + // find second color + while (y < height) { + while (x < width) { + if (*ptr == c1) { + ++n1; + } else { + c2 = *ptr; + goto found_second_color; + } + ++ptr; + ++x; + } + x = 0; + ptr += linestep; + ++y; + } + +found_second_color: + // finish counting + while (y < height) { + while (x < width) { + if (*ptr == c1) { + ++n1; + } else if (*ptr == c2) { + ++n2; + } else { + return false; + } + ++ptr; + ++x; + } + x = 0; + ptr += linestep; + ++y; + } + + if (n2 > n1) { + const quint32 tmpC = c1; + c1 = c2; + c2 = tmpC; + } + + encoder->newBg |= (c1 != encoder->bg); + encoder->newFg |= (c2 != encoder->fg); + + encoder->bg = c1; + encoder->fg = c2; + + // create map + bool inRect = false; + numRects = 0; + ptr = reinterpret_cast<const SRC*>(data); + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + if (inRect && *ptr == encoder->bg) { + // rect finished + setWidth(x - lastx()); + next(); + inRect = false; + } else if (!inRect && *ptr == encoder->fg) { + // rect start + setX(x); + setY(y); + setHeight(1); + inRect = true; + } + ++ptr; + } + if (inRect) { + // finish rect + setWidth(width - lastx()); + next(); + inRect = false; + } + ptr += linestep; + } + + return true; +} + +template <class SRC> +void QRfbDualColorHextile<SRC>::write(QTcpSocket *socket) const +{ + const int bpp = encoder->server->clientBytesPerPixel(); + const int padding = 3; + QVarLengthArray<char> buffer(padding + 2 * bpp + sizeof(char) + sizeof(numRects)); + char &subenc = buffer[padding]; + int n = padding + sizeof(subenc); + + subenc = 0x8; // AnySubrects + + if (encoder->newBg) { + subenc |= 0x2; // Background + encoder->server->convertPixels(buffer.data() + n, (char*)&encoder->bg, 1); + n += bpp; +// encoder->newBg = false; + } + + if (encoder->newFg) { + subenc |= 0x4; // Foreground + encoder->server->convertPixels(buffer.data() + n, (char*)&encoder->fg, 1); + n += bpp; +// encoder->newFg = false; + } + buffer[n] = numRects; + n += sizeof(numRects); + + socket->write(buffer.data() + padding, n - padding); + socket->write((char*)rects, numRects * sizeof(Rect)); +} + +template <class SRC> +void QRfbDualColorHextile<SRC>::next() +{ + for (int r = numRects - 1; r >= 0; --r) { + if (recty(r) == lasty()) + continue; + if (recty(r) < lasty() - 1) // only search previous scanline + break; + if (rectx(r) == lastx() && width(r) == width(numRects)) { + ++rects[r].wh; + return; + } + } + ++numRects; +} + +template <class SRC> +inline void QRfbMultiColorHextile<SRC>::setColor(SRC color) +{ + encoder->server->convertPixels(reinterpret_cast<char*>(rect(numRects)), + (const char*)&color, 1); +} + +template <class SRC> +inline bool QRfbMultiColorHextile<SRC>::beginRect() +{ + if ((rects.size() + bpp + 2) > maxRectsSize) + return false; + rects.resize(rects.size() + bpp + 2); + return true; +} + +template <class SRC> +inline void QRfbMultiColorHextile<SRC>::endRect() +{ + setHeight(numRects, 1); + ++numRects; +} + +template <class SRC> +bool QRfbMultiColorHextile<SRC>::read(const uchar *data, + int width, int height, int stride) +{ + const SRC *ptr = reinterpret_cast<const SRC*>(data); + const int linestep = (stride / sizeof(SRC)) - width; + + bpp = encoder->server->clientBytesPerPixel(); + + if (encoder->newBg) + encoder->bg = ptr[0]; + + const SRC bg = encoder->bg; + SRC color = bg; + bool inRect = false; + + numRects = 0; + rects.clear(); + + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + if (inRect && *ptr != color) { // end rect + setWidth(numRects, x - rectx(numRects)); + endRect(); + inRect = false; + } + + if (!inRect && *ptr != bg) { // begin rect + if (!beginRect()) + return false; + inRect = true; + color = *ptr; + setColor(color); + setX(numRects, x); + setY(numRects, y); + } + ++ptr; + } + if (inRect) { // end rect + setWidth(numRects, width - rectx(numRects)); + endRect(); + inRect = false; + } + ptr += linestep; + } + + return true; +} + +template <class SRC> +void QRfbMultiColorHextile<SRC>::write(QTcpSocket *socket) const +{ + const int padding = 3; + QVarLengthArray<quint8> buffer(bpp + padding + sizeof(quint8) + sizeof(numRects)); + + quint8 &subenc = buffer[padding]; + int n = padding + sizeof(quint8); + + subenc = 8 | 16; // AnySubrects | SubrectsColoured + + if (encoder->newBg) { + subenc |= 0x2; // Background + encoder->server->convertPixels(reinterpret_cast<char*>(buffer.data() + n), + reinterpret_cast<const char*>(&encoder->bg), + 1); + n += bpp; +// encoder->newBg = false; + } + + buffer[n] = numRects; + n += sizeof(numRects); + + socket->write(reinterpret_cast<const char*>(buffer.data() + padding), + n - padding); + socket->write(reinterpret_cast<const char*>(rects.constData()), + rects.size()); +} + +bool QVNCServer::pixelConversionNeeded() const +{ + if (!sameEndian) + return true; + +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + if (qvnc_screen->swapBytes()) + return true; +#endif + + const int screendepth = qvnc_screen->depth(); + if (screendepth != pixelFormat.bitsPerPixel) + return true; + + switch (screendepth) { + case 32: + case 24: + return false; + case 18: + return (pixelFormat.redBits == 6 + && pixelFormat.greenBits == 6 + && pixelFormat.blueBits == 6); + case 16: + return (pixelFormat.redBits == 5 + && pixelFormat.greenBits == 6 + && pixelFormat.blueBits == 5); + case 15: + return (pixelFormat.redBits == 5 + && pixelFormat.greenBits == 5 + && pixelFormat.blueBits == 5); + case 12: + return (pixelFormat.redBits == 4 + && pixelFormat.greenBits == 4 + && pixelFormat.blueBits == 4); + } + return true; +} + +// count: number of pixels +void QVNCServer::convertPixels(char *dst, const char *src, int count) const +{ + const int screendepth = qvnc_screen->depth(); + const bool isBgr = false; //### qvnc_screen->pixelType() == QScreen::BGRPixel; + + // cutoffs +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + if (!swapBytes) +#endif + if (sameEndian) { + if (screendepth == pixelFormat.bitsPerPixel) { // memcpy cutoffs + + switch (screendepth) { + case 32: + memcpy(dst, src, count * sizeof(quint32)); + return; + case 16: + if (pixelFormat.redBits == 5 + && pixelFormat.greenBits == 6 + && pixelFormat.blueBits == 5) + { + memcpy(dst, src, count * sizeof(quint16)); + return; + } + } + } else if (screendepth == 16 && pixelFormat.bitsPerPixel == 32) { +#if defined(__i386__) // Currently fails on ARM if dst is not 4 byte aligned + const quint32 *src32 = reinterpret_cast<const quint32*>(src); + quint32 *dst32 = reinterpret_cast<quint32*>(dst); + int count32 = count * sizeof(quint16) / sizeof(quint32); + while (count32--) { + const quint32 s = *src32++; + quint32 result1; + quint32 result2; + + // red + result1 = ((s & 0xf8000000) | ((s & 0xe0000000) >> 5)) >> 8; + result2 = ((s & 0x0000f800) | ((s & 0x0000e000) >> 5)) << 8; + + // green + result1 |= ((s & 0x07e00000) | ((s & 0x06000000) >> 6)) >> 11; + result2 |= ((s & 0x000007e0) | ((s & 0x00000600) >> 6)) << 5; + + // blue + result1 |= ((s & 0x001f0000) | ((s & 0x001c0000) >> 5)) >> 13; + result2 |= ((s & 0x0000001f) | ((s & 0x0000001c) >> 5)) << 3; + + *dst32++ = result2; + *dst32++ = result1; + } + if (count & 0x1) { + const quint16 *src16 = reinterpret_cast<const quint16*>(src); + *dst32 = qt_conv16ToRgb(src16[count - 1]); + } + return; +#endif + } + } + + const int bytesPerPixel = (pixelFormat.bitsPerPixel + 7) / 8; + +// nibble = 0; + + for (int i = 0; i < count; ++i) { + int r, g, b; + + switch (screendepth) { +#if 0 + case 4: { + if (!nibble) { + r = ((*src) & 0x0f) << 4; + } else { + r = (*src) & 0xf0; + src++; + } + nibble = !nibble; + g = b = r; + break; + } +#endif +#if 0 + case 8: { + QRgb rgb = qvnc_screen->clut()[int(*src)]; + r = qRed(rgb); + g = qGreen(rgb); + b = qBlue(rgb); + src++; + break; + } +#endif +#ifdef QT_QWS_DEPTH_12 + case 12: { + quint32 p = quint32(*reinterpret_cast<const qrgb444*>(src)); + r = qRed(p); + g = qGreen(p); + b = qBlue(p); + src += sizeof(qrgb444); + break; + } +#endif +#ifdef QT_QWS_DEPTH_15 + case 15: { + quint32 p = quint32(*reinterpret_cast<const qrgb555*>(src)); + r = qRed(p); + g = qGreen(p); + b = qBlue(p); + src += sizeof(qrgb555); + break; + } +#endif + case 16: { + quint16 p = *reinterpret_cast<const quint16*>(src); +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + if (swapBytes) + p = ((p & 0xff) << 8) | ((p & 0xff00) >> 8); +#endif + r = (p >> 11) & 0x1f; + g = (p >> 5) & 0x3f; + b = p & 0x1f; + r <<= 3; + g <<= 2; + b <<= 3; + src += sizeof(quint16); + break; + } +#ifdef QT_QWS_DEPTH_18 + case 18: { + quint32 p = quint32(*reinterpret_cast<const qrgb666*>(src)); + r = qRed(p); + g = qGreen(p); + b = qBlue(p); + src += sizeof(qrgb666); + break; + } +#endif +#ifdef QT_QWS_DEPTH_24 + case 24: { + quint32 p = quint32(*reinterpret_cast<const qrgb888*>(src)); + r = qRed(p); + g = qGreen(p); + b = qBlue(p); + src += sizeof(qrgb888); + break; + } +#endif + case 32: { + quint32 p = *reinterpret_cast<const quint32*>(src); + r = (p >> 16) & 0xff; + g = (p >> 8) & 0xff; + b = p & 0xff; + src += sizeof(quint32); + break; + } + default: { + r = g = b = 0; + qDebug("QVNCServer: don't support %dbpp display", screendepth); + return; + } + } + +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + if (swapBytes ^ isBgr) +#else + if (isBgr) +#endif + qSwap(r, b); + + r >>= (8 - pixelFormat.redBits); + g >>= (8 - pixelFormat.greenBits); + b >>= (8 - pixelFormat.blueBits); + + int pixel = (r << pixelFormat.redShift) | + (g << pixelFormat.greenShift) | + (b << pixelFormat.blueShift); + + if (sameEndian || pixelFormat.bitsPerPixel == 8) { + memcpy(dst, &pixel, bytesPerPixel); // XXX: do a simple for-loop instead? + dst += bytesPerPixel; + continue; + } + + + if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { + switch (pixelFormat.bitsPerPixel) { + case 16: + pixel = (((pixel & 0x0000ff00) << 8) | + ((pixel & 0x000000ff) << 24)); + break; + case 32: + pixel = (((pixel & 0xff000000) >> 24) | + ((pixel & 0x00ff0000) >> 8) | + ((pixel & 0x0000ff00) << 8) | + ((pixel & 0x000000ff) << 24)); + break; + default: + qDebug("Cannot handle %d bpp client", pixelFormat.bitsPerPixel); + } + } else { // QSysInfo::ByteOrder == QSysInfo::LittleEndian + switch (pixelFormat.bitsPerPixel) { + case 16: + pixel = (((pixel & 0xff000000) >> 8) | + ((pixel & 0x00ff0000) << 8)); + break; + case 32: + pixel = (((pixel & 0xff000000) >> 24) | + ((pixel & 0x00ff0000) >> 8) | + ((pixel & 0x0000ff00) << 8) | + ((pixel & 0x000000ff) << 24)); + break; + default: + qDebug("Cannot handle %d bpp client", + pixelFormat.bitsPerPixel); + break; + } + } + memcpy(dst, &pixel, bytesPerPixel); // XXX: simple for-loop instead? + dst += bytesPerPixel; + } +} + +#ifndef QT_NO_QWS_CURSOR +static void blendCursor(QImage &image, const QRect &imageRect) +{ + const QRect cursorRect = qt_screencursor->boundingRect(); + const QRect intersection = (cursorRect & imageRect); + const QRect destRect = intersection.translated(-imageRect.topLeft()); + const QRect srcRect = intersection.translated(-cursorRect.topLeft()); + + QPainter painter(&image); + painter.drawImage(destRect, qt_screencursor->image(), srcRect); + painter.end(); +} +#endif // QT_NO_QWS_CURSOR + +QVNCDirtyMap::QVNCDirtyMap(QVNCScreen *s) + : bytesPerPixel(0), numDirty(0), screen(s) +{ + bytesPerPixel = (screen->depth() + 7) / 8; + QSize screenSize = screen->geometry().size(); + bufferWidth = screenSize.width(); + bufferHeight = screenSize.height(); + bufferStride = bufferWidth * bytesPerPixel; + buffer = new uchar[bufferHeight * bufferStride]; + + mapWidth = (bufferWidth + MAP_TILE_SIZE - 1) / MAP_TILE_SIZE; + mapHeight = (bufferHeight + MAP_TILE_SIZE - 1) / MAP_TILE_SIZE; + numTiles = mapWidth * mapHeight; + map = new uchar[numTiles]; +} + +QVNCDirtyMap::~QVNCDirtyMap() +{ + delete[] map; + delete[] buffer; +} + +void QVNCDirtyMap::reset() +{ + memset(map, 1, numTiles); + memset(buffer, 0, bufferHeight * bufferStride); + numDirty = numTiles; +} + +inline bool QVNCDirtyMap::dirty(int x, int y) const +{ + return map[y * mapWidth + x]; +} + +inline void QVNCDirtyMap::setClean(int x, int y) +{ + map[y * mapWidth + x] = 0; + --numDirty; +} + +template <class T> +void QVNCDirtyMapOptimized<T>::setDirty(int tileX, int tileY, bool force) +{ + static bool alwaysForce = qgetenv("QT_VNC_NO_COMPAREBUFFER").toInt(); + if (alwaysForce) + force = true; + + bool changed = false; + + if (!force) { + const int lstep = screen->linestep(); + const int startX = tileX * MAP_TILE_SIZE; + const int startY = tileY * MAP_TILE_SIZE; + const uchar *scrn = screen->base() + + startY * lstep + startX * bytesPerPixel; + uchar *old = buffer + startY * bufferStride + startX * sizeof(T); + + const int tileHeight = (startY + MAP_TILE_SIZE > bufferHeight ? + bufferHeight - startY : MAP_TILE_SIZE); + const int tileWidth = (startX + MAP_TILE_SIZE > bufferWidth ? + bufferWidth - startX : MAP_TILE_SIZE); + const bool doInlines = (tileWidth == MAP_TILE_SIZE); + + int y = tileHeight; + + if (doInlines) { // hw: memcmp/memcpy is inlined when using constants + while (y) { + if (memcmp(old, scrn, sizeof(T) * MAP_TILE_SIZE)) { + changed = true; + break; + } + scrn += lstep; + old += bufferStride; + --y; + } + + while (y) { + memcpy(old, scrn, sizeof(T) * MAP_TILE_SIZE); + scrn += lstep; + old += bufferStride; + --y; + } + } else { + while (y) { + if (memcmp(old, scrn, sizeof(T) * tileWidth)) { + changed = true; + break; + } + scrn += lstep; + old += bufferStride; + --y; + } + + while (y) { + memcpy(old, scrn, sizeof(T) * tileWidth); + scrn += lstep; + old += bufferStride; + --y; + } + } + } + + const int mapIndex = tileY * mapWidth + tileX; + if ((force || changed) && !map[mapIndex]) { + map[mapIndex] = 1; + ++numDirty; + } +} + +template <class SRC> +QRfbHextileEncoder<SRC>::QRfbHextileEncoder(QVNCServer *s) + : QRfbEncoder(s), + singleColorHextile(this), dualColorHextile(this), multiColorHextile(this) +{ +} + +/* + \internal + Send dirty rects using hextile encoding. +*/ +template <class SRC> +void QRfbHextileEncoder<SRC>::write() +{ +// QWSDisplay::grab(true); + + QVNCDirtyMap *map = server->dirtyMap(); + QTcpSocket *socket = server->clientSocket(); + + const quint32 encoding = htonl(5); // hextile encoding + const int bytesPerPixel = server->clientBytesPerPixel(); + + { + const char tmp[2] = { 0, 0 }; // msg type, padding + socket->write(tmp, sizeof(tmp)); + } + { + const quint16 count = htons(map->numDirty); + socket->write((char *)&count, sizeof(count)); + } + + if (map->numDirty <= 0) { +// QWSDisplay::ungrab(); + return; + } + + newBg = true; + newFg = true; + + const QImage screenImage = server->screenImage(); + QRfbRect rect(0, 0, MAP_TILE_SIZE, MAP_TILE_SIZE); + + QSize screenSize = server->screen()->geometry().size(); + + for (int y = 0; y < map->mapHeight; ++y) { + if (rect.y + MAP_TILE_SIZE > screenSize.height()) + rect.h = screenSize.height() - rect.y; + rect.w = MAP_TILE_SIZE; + for (int x = 0; x < map->mapWidth; ++x) { + if (!map->dirty(x, y)) + continue; + map->setClean(x, y); + + rect.x = x * MAP_TILE_SIZE; + if (rect.x + MAP_TILE_SIZE > screenSize.width()) //###deviceWidth ??? + rect.w = screenSize.width() - rect.x; + rect.write(socket); + + socket->write((char *)&encoding, sizeof(encoding)); + + const uchar *screendata = screenImage.scanLine(rect.y) + + rect.x * screenImage.depth() / 8; + int linestep = screenImage.bytesPerLine(); + +#ifndef QT_NO_QWS_CURSOR + // hardware cursors must be blended with the screen memory + const bool doBlendCursor = qt_screencursor + && !server->hasClientCursor() + && qt_screencursor->isAccelerated(); + QImage tileImage; + if (doBlendCursor) { + const QRect tileRect(rect.x, rect.y, rect.w, rect.h); + const QRect cursorRect = qt_screencursor->boundingRect() + .translated(-server->screen()->offset()); + if (tileRect.intersects(cursorRect)) { + tileImage = screenImage.copy(tileRect); + blendCursor(tileImage, + tileRect.translated(server->screen()->offset())); + screendata = tileImage.bits(); + linestep = tileImage.bytesPerLine(); + } + } +#endif // QT_NO_QWS_CURSOR + + if (singleColorHextile.read(screendata, rect.w, rect.h, linestep)) { + singleColorHextile.write(socket); + } else if (dualColorHextile.read(screendata, rect.w, rect.h, linestep)) { + dualColorHextile.write(socket); + } else if (multiColorHextile.read(screendata, rect.w, rect.h, linestep)) { + multiColorHextile.write(socket); + } else if (server->doPixelConversion()) { + const int bufferSize = rect.w * rect.h * bytesPerPixel + 1; + const int padding = sizeof(quint32) - sizeof(char); + buffer.resize(bufferSize + padding); + + buffer[padding] = 1; // Raw subencoding + + // convert pixels + char *b = buffer.data() + padding + 1; + const int bstep = rect.w * bytesPerPixel; + for (int i = 0; i < rect.h; ++i) { + server->convertPixels(b, (const char*)screendata, rect.w); + screendata += linestep; + b += bstep; + } + socket->write(buffer.constData() + padding, bufferSize); + } else { + quint8 subenc = 1; // Raw subencoding + socket->write((char *)&subenc, 1); + + // send pixels + for (int i = 0; i < rect.h; ++i) { + socket->write((const char*)screendata, + rect.w * bytesPerPixel); + screendata += linestep; + } + } + } + if (socket->state() == QAbstractSocket::UnconnectedState) + break; + rect.y += MAP_TILE_SIZE; + } + socket->flush(); + Q_ASSERT(map->numDirty == 0); + +// QWSDisplay::ungrab(); +} + +void QRfbRawEncoder::write() +{ +// QWSDisplay::grab(false); + + QVNCDirtyMap *map = server->dirtyMap(); + QTcpSocket *socket = server->clientSocket(); + + const int bytesPerPixel = server->clientBytesPerPixel(); + QSize screenSize = server->screen()->geometry().size(); + + // create a region from the dirty rects and send the region's merged rects. + QRegion rgn; + if (map) { + for (int y = 0; y < map->mapHeight; ++y) { + for (int x = 0; x < map->mapWidth; ++x) { + if (!map->dirty(x, y)) + continue; + rgn += QRect(x * MAP_TILE_SIZE, y * MAP_TILE_SIZE, + MAP_TILE_SIZE, MAP_TILE_SIZE); + map->setClean(x, y); + } + } + + rgn &= QRect(0, 0, screenSize.width(), + screenSize.height()); + } + const QVector<QRect> rects = rgn.rects(); + + { + const char tmp[2] = { 0, 0 }; // msg type, padding + socket->write(tmp, sizeof(tmp)); + } + + { + const quint16 count = htons(rects.size()); + socket->write((char *)&count, sizeof(count)); + } + + if (rects.size() <= 0) { +// QWSDisplay::ungrab(); + return; + } + + const QImage *screenImage = server->screenImage(); + + for (int i = 0; i < rects.size(); ++i) { + const QRect tileRect = rects.at(i); + const QRfbRect rect(tileRect.x(), tileRect.y(), + tileRect.width(), tileRect.height()); + rect.write(socket); + + const quint32 encoding = htonl(0); // raw encoding + socket->write((char *)&encoding, sizeof(encoding)); + + int linestep = screenImage->bytesPerLine(); + const uchar *screendata = screenImage->scanLine(rect.y) + + rect.x * screenImage->depth() / 8; + +#ifndef QT_NO_QWS_CURSOR + // hardware cursors must be blended with the screen memory + const bool doBlendCursor = qt_screencursor + && !server->hasClientCursor() + && qt_screencursor->isAccelerated(); + QImage tileImage; + if (doBlendCursor) { + const QRect cursorRect = qt_screencursor->boundingRect() + .translated(-server->screen()->offset()); + if (tileRect.intersects(cursorRect)) { + tileImage = screenImage->copy(tileRect); + blendCursor(tileImage, + tileRect.translated(server->screen()->offset())); + screendata = tileImage.bits(); + linestep = tileImage.bytesPerLine(); + } + } +#endif // QT_NO_QWS_CURSOR + + if (server->doPixelConversion()) { + const int bufferSize = rect.w * rect.h * bytesPerPixel; + if (bufferSize > buffer.size()) + buffer.resize(bufferSize); + + // convert pixels + char *b = buffer.data(); + const int bstep = rect.w * bytesPerPixel; + for (int i = 0; i < rect.h; ++i) { + server->convertPixels(b, (const char*)screendata, rect.w); + screendata += linestep; + b += bstep; + } + socket->write(buffer.constData(), bufferSize); + } else { + for (int i = 0; i < rect.h; ++i) { + socket->write((const char*)screendata, rect.w * bytesPerPixel); + screendata += linestep; + } + } + if (socket->state() == QAbstractSocket::UnconnectedState) + break; + } + socket->flush(); + +// QWSDisplay::ungrab(); +} + +inline QImage *QVNCServer::screenImage() const +{ + return qvnc_screen->image(); +} + +void QVNCServer::checkUpdate() +{ + if (!wantUpdate) + return; + + if (dirtyCursor) { +#ifndef QT_NO_QWS_CURSOR + Q_ASSERT(qvnc_cursor); + qvnc_cursor->write(); +#endif + cursor->sendClientCursor(); + dirtyCursor = false; + wantUpdate = false; + return; + } + + if (dirtyMap()->numDirty > 0) { + if (encoder) + encoder->write(); + wantUpdate = false; + } +} + +void QVNCServer::discardClient() +{ + timer->stop(); + state = Unconnected; + delete encoder; + encoder = 0; +#ifndef QT_NO_QWS_CURSOR + delete qvnc_cursor; + qvnc_cursor = 0; +#endif +// if (!qvnc_screen->screen()) +// QWSServer::instance()->enablePainting(false); +} + + + +QVNCScreenPrivate::QVNCScreenPrivate(QVNCScreen *parent, int screenId) + : dpiX(72), dpiY(72), doOnScreenSurface(false), refreshRate(25), + vncServer(0), q_ptr(parent) +{ +#if 0//ndef QT_NO_QWS_SIGNALHANDLER + QWSSignalHandler::instance()->addObject(this); +#endif + + vncServer = new QVNCServer(q_ptr, screenId); + vncServer->setRefreshRate(refreshRate); + + + Q_ASSERT(q_ptr->depth() == 32); + + dirty = new QVNCDirtyMapOptimized<quint32>(q_ptr); +} + +QVNCScreenPrivate::~QVNCScreenPrivate() +{ +} + + +void QVNCScreenPrivate::setDirty(const QRect& rect, bool force) +{ + if (rect.isEmpty()) + return; + +// if (q_ptr->screen()) +// q_ptr->screen()->setDirty(rect); + + if (!vncServer || !vncServer->isConnected()) { +// qDebug() << "QVNCScreenPrivate::setDirty() - Not connected"; + return; + } + const QRect r = rect; // .translated(-q_ptr->offset()); + const int x1 = r.x() / MAP_TILE_SIZE; + int y = r.y() / MAP_TILE_SIZE; + for (; (y <= r.bottom() / MAP_TILE_SIZE) && y < dirty->mapHeight; y++) + for (int x = x1; (x <= r.right() / MAP_TILE_SIZE) && x < dirty->mapWidth; x++) + dirty->setDirty(x, y, force); + + vncServer->setDirty(); +} + + + + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/vnc/qvncserver.h b/src/plugins/platforms/vnc/qvncserver.h new file mode 100644 index 0000000..7244bdf --- /dev/null +++ b/src/plugins/platforms/vnc/qvncserver.h @@ -0,0 +1,533 @@ +/**************************************************************************** +** +** 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 plugins 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$ +** +****************************************************************************/ + +#ifndef QSCREENVNC_P_H +#define QSCREENVNC_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the QLibrary class. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#include "qvncintegration.h" +#include "qvnccursor.h" +#define QT_NO_QWS_CURSOR + +#ifndef QT_NO_QWS_VNC + +#include <QtCore/qvarlengtharray.h> +#include <QtCore/qsharedmemory.h> +#include <QtNetwork/qtcpsocket.h> +#include <QtNetwork/qtcpserver.h> + +QT_BEGIN_NAMESPACE + +class QVNCServer; + +#ifndef QT_NO_QWS_CURSOR +class QVNCCursor : public QProxyScreenCursor +{ +public: + QVNCCursor(QVNCScreen *s); + ~QVNCCursor(); + + void hide(); + void show(); + void set(const QImage &image, int hotx, int hoty); + void move(int x, int y); + +private: + void setDirty(const QRect &r) const; + QVNCScreen *screen; +}; + +class QVNCClientCursor : public QProxyScreenCursor +{ +public: + QVNCClientCursor(QVNCServer *s); + ~QVNCClientCursor(); + + void set(const QImage &image, int hotx, int hoty); + void write() const; + +private: + QVNCServer *server; +}; +#endif // QT_NO_QWS_CURSOR + +#define MAP_TILE_SIZE 16 +#define MAP_WIDTH 1280 / MAP_TILE_SIZE +#define MAP_HEIGHT 1024 / MAP_TILE_SIZE + +class QVNCDirtyMap +{ +public: + QVNCDirtyMap(QVNCScreen *screen); + virtual ~QVNCDirtyMap(); + + void reset(); + bool dirty(int x, int y) const; + virtual void setDirty(int x, int y, bool force = false) = 0; + void setClean(int x, int y); + + int bytesPerPixel; + + int numDirty; + int mapWidth; + int mapHeight; + +protected: + uchar *map; + QVNCScreen *screen; + uchar *buffer; + int bufferWidth; + int bufferHeight; + int bufferStride; + int numTiles; +}; + +template <class T> +class QVNCDirtyMapOptimized : public QVNCDirtyMap +{ +public: + QVNCDirtyMapOptimized(QVNCScreen *screen) : QVNCDirtyMap(screen) {} + ~QVNCDirtyMapOptimized() {} + + void setDirty(int x, int y, bool force = false); +}; + +class QRfbRect +{ +public: + QRfbRect() {} + QRfbRect(quint16 _x, quint16 _y, quint16 _w, quint16 _h) { + x = _x; y = _y; w = _w; h = _h; + } + + void read(QTcpSocket *s); + void write(QTcpSocket *s) const; + + quint16 x; + quint16 y; + quint16 w; + quint16 h; +}; + +class QRfbPixelFormat +{ +public: + static int size() { return 16; } + + void read(QTcpSocket *s); + void write(QTcpSocket *s); + + int bitsPerPixel; + int depth; + bool bigEndian; + bool trueColor; + int redBits; + int greenBits; + int blueBits; + int redShift; + int greenShift; + int blueShift; +}; + +class QRfbServerInit +{ +public: + QRfbServerInit() { name = 0; } + ~QRfbServerInit() { delete[] name; } + + int size() const { return QRfbPixelFormat::size() + 8 + strlen(name); } + void setName(const char *n); + + void read(QTcpSocket *s); + void write(QTcpSocket *s); + + quint16 width; + quint16 height; + QRfbPixelFormat format; + char *name; +}; + +class QRfbSetEncodings +{ +public: + bool read(QTcpSocket *s); + + quint16 count; +}; + +class QRfbFrameBufferUpdateRequest +{ +public: + bool read(QTcpSocket *s); + + char incremental; + QRfbRect rect; +}; + +class QRfbKeyEvent +{ +public: + bool read(QTcpSocket *s); + + char down; + int keycode; + int unicode; +}; + +class QRfbPointerEvent +{ +public: + bool read(QTcpSocket *s); + + Qt::MouseButtons buttons; + enum { WheelNone, + WheelUp, + WheelDown, + WheelLeft, + WheelRight + } wheelDirection; + quint16 x; + quint16 y; +}; + +class QRfbClientCutText +{ +public: + bool read(QTcpSocket *s); + + quint32 length; +}; + +class QVNCScreenPrivate : public QObject +{ +public: + QVNCScreenPrivate(QVNCScreen *parent, int screenId); + ~QVNCScreenPrivate(); + + void setDirty(const QRect &rect, bool force = false); + void configure(); + + qreal dpiX; + qreal dpiY; + bool doOnScreenSurface; + QVNCDirtyMap *dirty; + int refreshRate; + QVNCServer *vncServer; + +#if !defined(QT_NO_QWS_MULTIPROCESS) && !defined(QT_NO_SHAREDMEMORY) + QSharedMemory shm; +#endif + + QVNCScreen *q_ptr; +}; + +class QRfbEncoder +{ +public: + QRfbEncoder(QVNCServer *s) : server(s) {} + virtual ~QRfbEncoder() {} + + virtual void write() = 0; + +protected: + QVNCServer *server; +}; + +class QRfbRawEncoder : public QRfbEncoder +{ +public: + QRfbRawEncoder(QVNCServer *s) : QRfbEncoder(s) {} + + void write(); + +private: + QByteArray buffer; +}; + +template <class SRC> class QRfbHextileEncoder; + +template <class SRC> +class QRfbSingleColorHextile +{ +public: + QRfbSingleColorHextile(QRfbHextileEncoder<SRC> *e) : encoder(e) {} + bool read(const uchar *data, int width, int height, int stride); + void write(QTcpSocket *socket) const; + +private: + QRfbHextileEncoder<SRC> *encoder; +}; + +template <class SRC> +class QRfbDualColorHextile +{ +public: + QRfbDualColorHextile(QRfbHextileEncoder<SRC> *e) : encoder(e) {} + bool read(const uchar *data, int width, int height, int stride); + void write(QTcpSocket *socket) const; + +private: + struct Rect { + quint8 xy; + quint8 wh; + } Q_PACKED rects[8 * 16]; + + quint8 numRects; + QRfbHextileEncoder<SRC> *encoder; + +private: + inline int lastx() const { return rectx(numRects); } + inline int lasty() const { return recty(numRects); } + inline int rectx(int r) const { return rects[r].xy >> 4; } + inline int recty(int r) const { return rects[r].xy & 0x0f; } + inline int width(int r) const { return (rects[r].wh >> 4) + 1; } + inline int height(int r) const { return (rects[r].wh & 0x0f) + 1; } + + inline void setX(int r, int x) { + rects[r].xy = (x << 4) | (rects[r].xy & 0x0f); + } + inline void setY(int r, int y) { + rects[r].xy = (rects[r].xy & 0xf0) | y; + } + inline void setWidth(int r, int width) { + rects[r].wh = ((width - 1) << 4) | (rects[r].wh & 0x0f); + } + inline void setHeight(int r, int height) { + rects[r].wh = (rects[r].wh & 0xf0) | (height - 1); + } + + inline void setWidth(int width) { setWidth(numRects, width); } + inline void setHeight(int height) { setHeight(numRects, height); } + inline void setX(int x) { setX(numRects, x); } + inline void setY(int y) { setY(numRects, y); } + void next(); +}; + +template <class SRC> +class QRfbMultiColorHextile +{ +public: + QRfbMultiColorHextile(QRfbHextileEncoder<SRC> *e) : encoder(e) {} + bool read(const uchar *data, int width, int height, int stride); + void write(QTcpSocket *socket) const; + +private: + inline quint8* rect(int r) { + return rects.data() + r * (bpp + 2); + } + inline const quint8* rect(int r) const { + return rects.constData() + r * (bpp + 2); + } + inline void setX(int r, int x) { + quint8 *ptr = rect(r) + bpp; + *ptr = (x << 4) | (*ptr & 0x0f); + } + inline void setY(int r, int y) { + quint8 *ptr = rect(r) + bpp; + *ptr = (*ptr & 0xf0) | y; + } + void setColor(SRC color); + inline int rectx(int r) const { + const quint8 *ptr = rect(r) + bpp; + return *ptr >> 4; + } + inline int recty(int r) const { + const quint8 *ptr = rect(r) + bpp; + return *ptr & 0x0f; + } + inline void setWidth(int r, int width) { + quint8 *ptr = rect(r) + bpp + 1; + *ptr = ((width - 1) << 4) | (*ptr & 0x0f); + } + inline void setHeight(int r, int height) { + quint8 *ptr = rect(r) + bpp + 1; + *ptr = (*ptr & 0xf0) | (height - 1); + } + + bool beginRect(); + void endRect(); + + static const int maxRectsSize = 16 * 16; + QVarLengthArray<quint8, maxRectsSize> rects; + + quint8 bpp; + quint8 numRects; + QRfbHextileEncoder<SRC> *encoder; +}; + +template <class SRC> +class QRfbHextileEncoder : public QRfbEncoder +{ +public: + QRfbHextileEncoder(QVNCServer *s); + void write(); + +private: + enum SubEncoding { + Raw = 1, + BackgroundSpecified = 2, + ForegroundSpecified = 4, + AnySubrects = 8, + SubrectsColoured = 16 + }; + + QByteArray buffer; + QRfbSingleColorHextile<SRC> singleColorHextile; + QRfbDualColorHextile<SRC> dualColorHextile; + QRfbMultiColorHextile<SRC> multiColorHextile; + + SRC bg; + SRC fg; + bool newBg; + bool newFg; + + friend class QRfbSingleColorHextile<SRC>; + friend class QRfbDualColorHextile<SRC>; + friend class QRfbMultiColorHextile<SRC>; +}; + +class QVNCServer : public QObject +{ + Q_OBJECT +public: + QVNCServer(QVNCScreen *screen); + QVNCServer(QVNCScreen *screen, int id); + ~QVNCServer(); + + void setDirty(); + void setDirtyCursor() { dirtyCursor = true; setDirty(); } + inline bool isConnected() const { return state == Connected; } + inline void setRefreshRate(int rate) { refreshRate = rate; } + + enum ClientMsg { SetPixelFormat = 0, + FixColourMapEntries = 1, + SetEncodings = 2, + FramebufferUpdateRequest = 3, + KeyEvent = 4, + PointerEvent = 5, + ClientCutText = 6 }; + + enum ServerMsg { FramebufferUpdate = 0, + SetColourMapEntries = 1 }; + + void convertPixels(char *dst, const char *src, int count) const; + + inline int clientBytesPerPixel() const { + return pixelFormat.bitsPerPixel / 8; + } + + inline QVNCScreen* screen() const { return qvnc_screen; } + inline QVNCDirtyMap* dirtyMap() const { return qvnc_screen->dirtyMap(); } + inline QTcpSocket* clientSocket() const { return client; } + QImage *screenImage() const; + inline bool doPixelConversion() const { return needConversion; } +#ifndef QT_NO_QWS_CURSOR + inline bool hasClientCursor() const { return qvnc_cursor != 0; } +#endif + + void setCursor(QVNCCursor * c) { cursor = c; } +private: + void setPixelFormat(); + void setEncodings(); + void frameBufferUpdateRequest(); + void pointerEvent(); + void keyEvent(); + void clientCutText(); + bool pixelConversionNeeded() const; + +private slots: + void newConnection(); + void readClient(); + void checkUpdate(); + void discardClient(); + +private: + void init(uint port); + enum ClientState { Unconnected, Protocol, Init, Connected }; + QTimer *timer; + QTcpServer *serverSocket; + QTcpSocket *client; + ClientState state; + quint8 msgType; + bool handleMsg; + QRfbPixelFormat pixelFormat; + Qt::KeyboardModifiers keymod; + Qt::MouseButtons buttons; + int encodingsPending; + int cutTextPending; + uint supportCopyRect : 1; + uint supportRRE : 1; + uint supportCoRRE : 1; + uint supportHextile : 1; + uint supportZRLE : 1; + uint supportCursor : 1; + uint supportDesktopSize : 1; + bool wantUpdate; + bool sameEndian; + bool needConversion; +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + bool swapBytes; +#endif + bool dirtyCursor; + int refreshRate; + QVNCScreen *qvnc_screen; +#ifndef QT_NO_QWS_CURSOR + QVNCClientCursor *qvnc_cursor; +#endif + + QRfbEncoder *encoder; + QVNCCursor *cursor; +}; + + +QT_END_NAMESPACE +#endif // QT_NO_QWS_VNC +#endif // QSCREENVNC_P_H diff --git a/src/plugins/platforms/vnc/vnc.pro b/src/plugins/platforms/vnc/vnc.pro new file mode 100644 index 0000000..07f8d88 --- /dev/null +++ b/src/plugins/platforms/vnc/vnc.pro @@ -0,0 +1,22 @@ +TARGET = qvncgraphicssystem +include(../../qpluginbase.pri) + +QT += network + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +SOURCES = main.cpp qvncintegration.cpp +HEADERS = qvncintegration.h + +HEADERS += qvncserver.h +SOURCES += qvncserver.cpp + +HEADERS += qvnccursor.h +SOURCES += qvnccursor.cpp + +include(../fb_base/fb_base.pri) +include(../fontdatabases/genericunix/genericunix.pri) + +target.path += $$[QT_INSTALL_PLUGINS]/platforms + +INSTALLS += target diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 722979d..5b0b6f3 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -2,17 +2,17 @@ TEMPLATE = subdirs SUBDIRS *= sqldrivers script bearer unix:!symbian { - contains(QT_CONFIG,iconv)|contains(QT_CONFIG,gnu-libiconv):SUBDIRS *= codecs + contains(QT_CONFIG,iconv)|contains(QT_CONFIG,gnu-libiconv)|contains(QT_CONFIG,sun-libiconv):SUBDIRS *= codecs } else { SUBDIRS *= codecs } !contains(QT_CONFIG, no-gui): SUBDIRS *= imageformats iconengines -!embedded:SUBDIRS *= graphicssystems +!embedded:!qpa:SUBDIRS *= graphicssystems embedded:SUBDIRS *= gfxdrivers decorations mousedrivers kbddrivers !win32:!embedded:!mac:!symbian:SUBDIRS *= inputmethods !symbian:!contains(QT_CONFIG, no-gui):SUBDIRS += accessible symbian:SUBDIRS += s60 contains(QT_CONFIG, phonon): SUBDIRS *= phonon contains(QT_CONFIG, multimedia): SUBDIRS *= audio - +qpa:SUBDIRS += platforms diff --git a/src/plugins/qpluginbase.pri b/src/plugins/qpluginbase.pri index 84009d8..45e3976 100644 --- a/src/plugins/qpluginbase.pri +++ b/src/plugins/qpluginbase.pri @@ -1,6 +1,6 @@ TEMPLATE = lib isEmpty(QT_MAJOR_VERSION) { - VERSION=4.7.1 + VERSION=4.8.0 } else { VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} } diff --git a/src/plugins/sqldrivers/sqlite_symbian/sqlite_symbian.pri b/src/plugins/sqldrivers/sqlite_symbian/sqlite_symbian.pri index 494c64c..ebeccc9 100644 --- a/src/plugins/sqldrivers/sqlite_symbian/sqlite_symbian.pri +++ b/src/plugins/sqldrivers/sqlite_symbian/sqlite_symbian.pri @@ -1,6 +1,12 @@ # We just want to include the sqlite3 binaries for Symbian for platforms that do not have them. !symbian-abld:!symbian-sbsv2 { !symbian_no_export_sqlite:!exists($${EPOCROOT}epoc32/release/armv5/lib/sqlite3.dso) { + contains(QMAKE_HOST.os,Windows) { + # Trick on Windows to do a touch on the file, since copy keeps the timestamp. + copyWithTouch = copy /y /b NUL+ + } else { + copyWithTouch = "$$QMAKE_COPY " + } symbian_sqlite3_zip_file = $$PWD/SQLite3_v9.2.zip # The QMAKE_COPY section is to update timestamp on the file. @@ -10,7 +16,7 @@ symbian_sqlite3_header.CONFIG = combine no_link symbian_sqlite3_header.dependency_type = TYPE_C symbian_sqlite3_header.commands = $$QMAKE_UNZIP -j ${QMAKE_FILE_NAME} epoc32/include/stdapis/${QMAKE_FILE_OUT_BASE}.h \ - && $$QMAKE_COPY ${QMAKE_FILE_OUT_BASE}.h ${QMAKE_FILE_OUT}.tmp \ + && $${copyWithTouch}${QMAKE_FILE_OUT_BASE}.h ${QMAKE_FILE_OUT}.tmp \ && $$QMAKE_DEL_FILE ${QMAKE_FILE_OUT_BASE}.h \ && $$QMAKE_MOVE ${QMAKE_FILE_OUT}.tmp ${QMAKE_FILE_OUT} silent:symbian_sqlite3_header.commands = @echo unzipping $@ && $$symbian_sqlite3_header.commands @@ -22,7 +28,7 @@ !isEmpty(OBJECTS_DIR):symbian_sqlite3_dso.output = $$OBJECTS_DIR/$$symbian_sqlite3_dso.output symbian_sqlite3_dso.CONFIG = combine no_link target_predeps symbian_sqlite3_dso.commands = $$QMAKE_UNZIP -j ${QMAKE_FILE_NAME} epoc32/release/armv5/lib/${QMAKE_FILE_OUT_BASE}.dso \ - && $$QMAKE_COPY ${QMAKE_FILE_OUT_BASE}.dso ${QMAKE_FILE_OUT}.tmp \ + && $${copyWithTouch}${QMAKE_FILE_OUT_BASE}.dso ${QMAKE_FILE_OUT}.tmp \ && $$QMAKE_DEL_FILE ${QMAKE_FILE_OUT_BASE}.dso \ && $$QMAKE_MOVE ${QMAKE_FILE_OUT}.tmp ${QMAKE_FILE_OUT} silent:symbian_sqlite3_dso.commands = @echo unzipping $@ && $$symbian_sqlite3_dso.commands diff --git a/src/qbase.pri b/src/qbase.pri index 4217618..76079f2 100644 --- a/src/qbase.pri +++ b/src/qbase.pri @@ -4,11 +4,10 @@ INCLUDEPATH *= $$QMAKE_INCDIR_QT/$$TARGET #just for today to have some compat isEmpty(QT_ARCH):!isEmpty(ARCH):QT_ARCH=$$ARCH #another compat that will rot for change #215700 TEMPLATE = lib isEmpty(QT_MAJOR_VERSION) { - VERSION=4.7.1 + VERSION=4.8.0 } else { VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} } -mac:!contains(QMAKE_EXT_C, .mm):QMAKE_EXT_C += .mm #load up the headers info CONFIG += qt_install_headers @@ -201,7 +200,7 @@ symbian { pu_header = "; Partial upgrade package for testing $${TARGET} changes without reinstalling everything" \ "$${LITERAL_HASH}{\"$${TARGET}\"}, ($$PARTIAL_UPGRADE_UID), $${QT_MAJOR_VERSION},$${QT_MINOR_VERSION},$${QT_PATCH_VERSION}, TYPE=PU" partial_upgrade.pkg_prerules = pu_header vendorinfo - partial_upgrade.sources = $$QMAKE_LIBDIR_QT/$${TARGET}.dll + partial_upgrade.files = $$QMAKE_LIBDIR_QT/$${TARGET}.dll partial_upgrade.path = c:/sys/bin DEPLOYMENT += partial_upgrade } diff --git a/src/qt3support/text/q3richtext.cpp b/src/qt3support/text/q3richtext.cpp index d82d0f0..d84a85b 100644 --- a/src/qt3support/text/q3richtext.cpp +++ b/src/qt3support/text/q3richtext.cpp @@ -8078,9 +8078,9 @@ bool Q3TextTable::down(Q3TextCursor *c, Q3TextDocument *&doc, Q3TextParagraph *& break; } } - doc = cell->richText(); if (!cell) return false; + doc = cell->richText(); parag = doc->firstParagraph(); idx = 0; ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); @@ -8116,9 +8116,9 @@ bool Q3TextTable::up(Q3TextCursor *c, Q3TextDocument *&doc, Q3TextParagraph *&pa break; } } - doc = cell->richText(); if (!cell) return false; + doc = cell->richText(); parag = doc->lastParagraph(); idx = parag->length() - 1; ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); diff --git a/src/qt3support/text/q3textstream.h b/src/qt3support/text/q3textstream.h index d0c4f48..0e26e08 100644 --- a/src/qt3support/text/q3textstream.h +++ b/src/qt3support/text/q3textstream.h @@ -272,13 +272,13 @@ private: int arg; // member function argument }; -Q_COMPAT_EXPORT inline Q3TextStream &operator>>( Q3TextStream &s, Q3TSFUNC f ) +Q_COMPAT_EXPORT_INLINE Q3TextStream &operator>>( Q3TextStream &s, Q3TSFUNC f ) { return (*f)( s ); } -Q_COMPAT_EXPORT inline Q3TextStream &operator<<( Q3TextStream &s, Q3TSFUNC f ) +Q_COMPAT_EXPORT_INLINE Q3TextStream &operator<<( Q3TextStream &s, Q3TSFUNC f ) { return (*f)( s ); } -Q_COMPAT_EXPORT inline Q3TextStream &operator<<( Q3TextStream &s, Q3TSManip m ) +Q_COMPAT_EXPORT_INLINE Q3TextStream &operator<<( Q3TextStream &s, Q3TSManip m ) { m.exec(s); return s; } Q_COMPAT_EXPORT Q3TextStream &bin( Q3TextStream &s ); // set bin notation diff --git a/src/qt3support/tools/q3cstring.h b/src/qt3support/tools/q3cstring.h index b280ebc..86a31fa 100644 --- a/src/qt3support/tools/q3cstring.h +++ b/src/qt3support/tools/q3cstring.h @@ -161,75 +161,75 @@ inline Q3CString &Q3CString::setNum(float n, char f, int prec) Q3CString non-member operators *****************************************************************************/ -Q_COMPAT_EXPORT inline bool operator==(const Q3CString &s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator==(const Q3CString &s1, const Q3CString &s2) { return qstrcmp(s1, s2) == 0; } -Q_COMPAT_EXPORT inline bool operator==(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator==(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) == 0; } -Q_COMPAT_EXPORT inline bool operator==(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator==(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) == 0; } -Q_COMPAT_EXPORT inline bool operator!=(const Q3CString &s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator!=(const Q3CString &s1, const Q3CString &s2) { return qstrcmp(s1, s2) != 0; } -Q_COMPAT_EXPORT inline bool operator!=(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator!=(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) != 0; } -Q_COMPAT_EXPORT inline bool operator!=(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator!=(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) != 0; } -Q_COMPAT_EXPORT inline bool operator<(const Q3CString &s1, const Q3CString& s2) +Q_COMPAT_EXPORT_INLINE bool operator<(const Q3CString &s1, const Q3CString& s2) { return qstrcmp(s1, s2) < 0; } -Q_COMPAT_EXPORT inline bool operator<(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator<(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) < 0; } -Q_COMPAT_EXPORT inline bool operator<(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator<(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) < 0; } -Q_COMPAT_EXPORT inline bool operator<=(const Q3CString &s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator<=(const Q3CString &s1, const Q3CString &s2) { return qstrcmp(s1, s2) <= 0; } -Q_COMPAT_EXPORT inline bool operator<=(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator<=(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) <= 0; } -Q_COMPAT_EXPORT inline bool operator<=(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator<=(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) <= 0; } -Q_COMPAT_EXPORT inline bool operator>(const Q3CString &s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator>(const Q3CString &s1, const Q3CString &s2) { return qstrcmp(s1, s2) > 0; } -Q_COMPAT_EXPORT inline bool operator>(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator>(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) > 0; } -Q_COMPAT_EXPORT inline bool operator>(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator>(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) > 0; } -Q_COMPAT_EXPORT inline bool operator>=(const Q3CString &s1, const Q3CString& s2) +Q_COMPAT_EXPORT_INLINE bool operator>=(const Q3CString &s1, const Q3CString& s2) { return qstrcmp(s1, s2) >= 0; } -Q_COMPAT_EXPORT inline bool operator>=(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE bool operator>=(const Q3CString &s1, const char *s2) { return qstrcmp(s1, s2) >= 0; } -Q_COMPAT_EXPORT inline bool operator>=(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE bool operator>=(const char *s1, const Q3CString &s2) { return qstrcmp(s1, s2) >= 0; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const Q3CString &s1, +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const Q3CString &s1, const Q3CString &s2) { Q3CString tmp(s1); tmp += s2; return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const Q3CString &s1, +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const Q3CString &s1, const QByteArray &s2) { QByteArray tmp(s1); tmp += s2; return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const QByteArray &s1, +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const QByteArray &s1, const Q3CString &s2) { QByteArray tmp(s1); @@ -237,28 +237,28 @@ Q_COMPAT_EXPORT inline const Q3CString operator+(const QByteArray &s1, return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const Q3CString &s1, const char *s2) +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const Q3CString &s1, const char *s2) { Q3CString tmp(s1); tmp += s2; return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const char *s1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const char *s1, const Q3CString &s2) { Q3CString tmp(s1); tmp += s2; return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(const Q3CString &s1, char c2) +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(const Q3CString &s1, char c2) { Q3CString tmp(s1); tmp += c2; return tmp; } -Q_COMPAT_EXPORT inline const Q3CString operator+(char c1, const Q3CString &s2) +Q_COMPAT_EXPORT_INLINE const Q3CString operator+(char c1, const Q3CString &s2) { Q3CString tmp; tmp += c1; diff --git a/src/qt3support/tools/q3valuevector.h b/src/qt3support/tools/q3valuevector.h index cdd5fcd..f86cb30 100644 --- a/src/qt3support/tools/q3valuevector.h +++ b/src/qt3support/tools/q3valuevector.h @@ -84,9 +84,9 @@ public: void resize(int n, const T& val = T()) { if (n < this->size()) - erase(this->begin() + n, this->end()); + this->erase(this->begin() + n, this->end()); else - insert(this->end(), n - this->size(), val); + this->insert(this->end(), n - this->size(), val); } diff --git a/src/qt_install.pri b/src/qt_install.pri index f906e92..268bb86 100644 --- a/src/qt_install.pri +++ b/src/qt_install.pri @@ -38,7 +38,7 @@ qt_install_headers { } } -embedded:equals(TARGET, QtGui) { +embedded|qpa: equals(TARGET, QtGui) { # install fonts for embedded INSTALLS += fonts fonts.path = $$[QT_INSTALL_LIBS]/fonts diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index 65b8781..2b3229e 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -37,7 +37,7 @@ symbian: { DESTDIR = $$QMAKE_LIBDIR_QT - qtlibraries.sources = \ + qtlibraries.files = \ $$QMAKE_LIBDIR_QT/QtCore$${QT_LIBINFIX}.dll \ $$QMAKE_LIBDIR_QT/QtXml$${QT_LIBINFIX}.dll \ $$QMAKE_LIBDIR_QT/QtGui$${QT_LIBINFIX}.dll \ @@ -82,7 +82,7 @@ symbian: { qts60plugindeployment = \ " \"$$pluginLocations/qts60plugin_5_0$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_5_0$${QT_LIBINFIX}.dll\"" - bearer_plugin.sources = $$QT_BUILD_TREE/plugins/bearer/qsymbianbearer$${QT_LIBINFIX}.dll + bearer_plugin.files = $$QT_BUILD_TREE/plugins/bearer/qsymbianbearer$${QT_LIBINFIX}.dll bearer_plugin.path = c:$$QT_PLUGINS_BASE_DIR/bearer DEPLOYMENT += bearer_plugin } @@ -121,25 +121,25 @@ symbian: { } qtlibraries.pkg_prerules += "(0x2002af5f), 0, 5, 0, {\"sqlite3\"}" - !contains(QT_CONFIG, no-jpeg): imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qjpeg$${QT_LIBINFIX}.dll - !contains(QT_CONFIG, no-gif): imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qgif$${QT_LIBINFIX}.dll - !contains(QT_CONFIG, no-mng): imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qmng$${QT_LIBINFIX}.dll - !contains(QT_CONFIG, no-tiff): imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qtiff$${QT_LIBINFIX}.dll - !contains(QT_CONFIG, no-ico): imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qico$${QT_LIBINFIX}.dll + !contains(QT_CONFIG, no-jpeg): imageformats_plugins.files += $$QT_BUILD_TREE/plugins/imageformats/qjpeg$${QT_LIBINFIX}.dll + !contains(QT_CONFIG, no-gif): imageformats_plugins.files += $$QT_BUILD_TREE/plugins/imageformats/qgif$${QT_LIBINFIX}.dll + !contains(QT_CONFIG, no-mng): imageformats_plugins.files += $$QT_BUILD_TREE/plugins/imageformats/qmng$${QT_LIBINFIX}.dll + !contains(QT_CONFIG, no-tiff): imageformats_plugins.files += $$QT_BUILD_TREE/plugins/imageformats/qtiff$${QT_LIBINFIX}.dll + !contains(QT_CONFIG, no-ico): imageformats_plugins.files += $$QT_BUILD_TREE/plugins/imageformats/qico$${QT_LIBINFIX}.dll imageformats_plugins.path = c:$$QT_PLUGINS_BASE_DIR/imageformats - codecs_plugins.sources = $$QT_BUILD_TREE/plugins/codecs/qcncodecs$${QT_LIBINFIX}.dll $$QT_BUILD_TREE/plugins/codecs/qjpcodecs$${QT_LIBINFIX}.dll $$QT_BUILD_TREE/plugins/codecs/qtwcodecs$${QT_LIBINFIX}.dll $$QT_BUILD_TREE/plugins/codecs/qkrcodecs$${QT_LIBINFIX}.dll + codecs_plugins.files = $$QT_BUILD_TREE/plugins/codecs/qcncodecs$${QT_LIBINFIX}.dll $$QT_BUILD_TREE/plugins/codecs/qjpcodecs$${QT_LIBINFIX}.dll $$QT_BUILD_TREE/plugins/codecs/qtwcodecs$${QT_LIBINFIX}.dll $$QT_BUILD_TREE/plugins/codecs/qkrcodecs$${QT_LIBINFIX}.dll codecs_plugins.path = c:$$QT_PLUGINS_BASE_DIR/codecs contains(QT_CONFIG, phonon-backend) { - phonon_backend_plugins.sources += $$QMAKE_LIBDIR_QT/phonon_mmf$${QT_LIBINFIX}.dll + phonon_backend_plugins.files += $$QMAKE_LIBDIR_QT/phonon_mmf$${QT_LIBINFIX}.dll phonon_backend_plugins.path = c:$$QT_PLUGINS_BASE_DIR/phonon_backend DEPLOYMENT += phonon_backend_plugins } # Support backup & restore for Qt libraries - qtbackup.sources = backup_registration.xml + qtbackup.files = backup_registration.xml qtbackup.path = c:/private/10202D56/import/packages/$$replace(TARGET.UID3, 0x,) DEPLOYMENT += qtlibraries \ @@ -149,35 +149,35 @@ symbian: { graphicssystems_plugins contains(QT_CONFIG, svg): { - qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtSvg$${QT_LIBINFIX}.dll - imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qsvg$${QT_LIBINFIX}.dll - iconengines_plugins.sources = $$QT_BUILD_TREE/plugins/iconengines/qsvgicon$${QT_LIBINFIX}.dll + qtlibraries.files += $$QMAKE_LIBDIR_QT/QtSvg$${QT_LIBINFIX}.dll + imageformats_plugins.files += $$QT_BUILD_TREE/plugins/imageformats/qsvg$${QT_LIBINFIX}.dll + iconengines_plugins.files = $$QT_BUILD_TREE/plugins/iconengines/qsvgicon$${QT_LIBINFIX}.dll iconengines_plugins.path = c:$$QT_PLUGINS_BASE_DIR/iconengines DEPLOYMENT += iconengines_plugins } contains(QT_CONFIG, phonon): { - qtlibraries.sources += $$QMAKE_LIBDIR_QT/phonon$${QT_LIBINFIX}.dll + qtlibraries.files += $$QMAKE_LIBDIR_QT/phonon$${QT_LIBINFIX}.dll } contains(QT_CONFIG, script): { - qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtScript$${QT_LIBINFIX}.dll + qtlibraries.files += $$QMAKE_LIBDIR_QT/QtScript$${QT_LIBINFIX}.dll } contains(QT_CONFIG, xmlpatterns): { - qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtXmlPatterns$${QT_LIBINFIX}.dll + qtlibraries.files += $$QMAKE_LIBDIR_QT/QtXmlPatterns$${QT_LIBINFIX}.dll } contains(QT_CONFIG, declarative): { - qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtDeclarative$${QT_LIBINFIX}.dll + qtlibraries.files += $$QMAKE_LIBDIR_QT/QtDeclarative$${QT_LIBINFIX}.dll - folderlistmodelImport.sources = $$QT_BUILD_TREE/imports/Qt/labs/folderlistmodel/qmlfolderlistmodelplugin$${QT_LIBINFIX}.dll - gesturesImport.sources = $$QT_BUILD_TREE/imports/Qt/labs/gestures/qmlgesturesplugin$${QT_LIBINFIX}.dll - particlesImport.sources = $$QT_BUILD_TREE/imports/Qt/labs/particles/qmlparticlesplugin$${QT_LIBINFIX}.dll + folderlistmodelImport.files = $$QT_BUILD_TREE/imports/Qt/labs/folderlistmodel/qmlfolderlistmodelplugin$${QT_LIBINFIX}.dll + gesturesImport.files = $$QT_BUILD_TREE/imports/Qt/labs/gestures/qmlgesturesplugin$${QT_LIBINFIX}.dll + particlesImport.files = $$QT_BUILD_TREE/imports/Qt/labs/particles/qmlparticlesplugin$${QT_LIBINFIX}.dll - folderlistmodelImport.sources += $$QT_SOURCE_TREE/src/imports/folderlistmodel/qmldir - gesturesImport.sources += $$QT_SOURCE_TREE/src/imports/gestures/qmldir - particlesImport.sources += $$QT_SOURCE_TREE/src/imports/particles/qmldir + folderlistmodelImport.files += $$QT_SOURCE_TREE/src/imports/folderlistmodel/qmldir + gesturesImport.files += $$QT_SOURCE_TREE/src/imports/gestures/qmldir + particlesImport.files += $$QT_SOURCE_TREE/src/imports/particles/qmldir folderlistmodelImport.path = c:$$QT_IMPORTS_BASE_DIR/Qt/labs/folderlistmodel gesturesImport.path = c:$$QT_IMPORTS_BASE_DIR/Qt/labs/gestures @@ -188,8 +188,8 @@ symbian: { graphicssystems_plugins.path = c:$$QT_PLUGINS_BASE_DIR/graphicssystems contains(QT_CONFIG, openvg) { - qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtOpenVG$${QT_LIBINFIX}.dll - graphicssystems_plugins.sources += $$QT_BUILD_TREE/plugins/graphicssystems/qvggraphicssystem$${QT_LIBINFIX}.dll + qtlibraries.files += $$QMAKE_LIBDIR_QT/QtOpenVG$${QT_LIBINFIX}.dll + graphicssystems_plugins.files += $$QT_BUILD_TREE/plugins/graphicssystems/qvggraphicssystem$${QT_LIBINFIX}.dll # OpenVG requires Symbian^3 or later pkg_platform_dependencies -= \ "[0x101F7961],0,0,0,{\"S60ProductID\"}" \ @@ -199,12 +199,12 @@ symbian: { } contains(QT_CONFIG, opengl) { - qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtOpenGL$${QT_LIBINFIX}.dll - graphicssystems_plugins.sources += $$QT_BUILD_TREE/plugins/graphicssystems/qglgraphicssystem$${QT_LIBINFIX}.dll + qtlibraries.files += $$QMAKE_LIBDIR_QT/QtOpenGL$${QT_LIBINFIX}.dll + graphicssystems_plugins.files += $$QT_BUILD_TREE/plugins/graphicssystems/qglgraphicssystem$${QT_LIBINFIX}.dll } contains(QT_CONFIG, multimedia){ - qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtMultimedia$${QT_LIBINFIX}.dll + qtlibraries.files += $$QMAKE_LIBDIR_QT/QtMultimedia$${QT_LIBINFIX}.dll } BLD_INF_RULES.prj_exports += "qt.iby $$CORE_MW_LAYER_IBY_EXPORT_PATH(qt.iby)" diff --git a/src/s60main/newallocator_hook.cpp b/src/s60main/newallocator_hook.cpp index 9ea2ef0..9cc6afb 100644 --- a/src/s60main/newallocator_hook.cpp +++ b/src/s60main/newallocator_hook.cpp @@ -41,11 +41,6 @@ #include <e32std.h> #include <qglobal.h> -#ifdef QT_EXPORTS_NOT_FROZEN -// If exports in Qt DLLs are not frozen in this build, then we have to pick up the -// allocator creation function by import link. We know the function will be present -// in the DLLs we test with, as we have to use the DLLs we have built. - struct SStdEpocThreadCreateInfo; Q_CORE_EXPORT TInt qt_symbian_SetupThreadHeap(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo); @@ -56,88 +51,8 @@ Q_CORE_EXPORT TInt qt_symbian_SetupThreadHeap(TBool aNotFirst, SStdEpocThreadCre * Uses link-time symbol preemption to capture a call from the application * startup. On return, there is some kind of heap allocator installed on the * thread. -*/ +*/ TInt UserHeap::SetupThreadHeap(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo) { return qt_symbian_SetupThreadHeap(aNotFirst, aInfo); } - -#else // QT_EXPORTS_NOT_FROZEN -// If we are using an export frozen build, it should be compatible with all 4.7.x Qt releases. -// We want to use the allocator creation function introduced in qtcore.dll after 4.7.1. But we -// can't import link to it, as it may not be present in whatever 4.7.x DLLs we are running with. -// So the function is found and called dynamically, by library lookup. If it is not found, we -// use the OS allocator creation functions instead. - -struct SThreadCreateInfo - { - TAny* iHandle; - TInt iType; - TThreadFunction iFunction; - TAny* iPtr; - TAny* iSupervisorStack; - TInt iSupervisorStackSize; - TAny* iUserStack; - TInt iUserStackSize; - TInt iInitialThreadPriority; - TPtrC iName; - TInt iTotalSize; // Size including any extras (must be a multiple of 8 bytes) - }; - -struct SStdEpocThreadCreateInfo : public SThreadCreateInfo - { - RAllocator* iAllocator; - TInt iHeapInitialSize; - TInt iHeapMaxSize; - TInt iPadding; // Make structure size a multiple of 8 bytes - }; - - -/* \internal - * - * Uses link-time symbol preemption to capture a call from the application - * startup. On return, there is some kind of heap allocator installed on the - * thread. -*/ -TInt UserHeap::SetupThreadHeap(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo) -{ - TInt r = KErrNone; - -#ifndef __WINS__ - // attempt to create the fast allocator through a known export ordinal in qtcore.dll - RLibrary qtcore; - if (qtcore.Load(_L("qtcore.dll")) == KErrNone) - { - const int qt_symbian_SetupThreadHeap_eabi_ordinal = 3713; - TLibraryFunction libFunc = qtcore.Lookup(qt_symbian_SetupThreadHeap_eabi_ordinal); - if (libFunc) - { - typedef int (*TSetupThreadHeapFunc)(TBool aNotFirst, SStdEpocThreadCreateInfo& aInfo); - TSetupThreadHeapFunc p_qt_symbian_SetupThreadHeap = TSetupThreadHeapFunc(libFunc); - r = (*p_qt_symbian_SetupThreadHeap)(aNotFirst, aInfo); - } - qtcore.Close(); - if (libFunc) - return r; - } -#endif - - // no fast allocator support - use default allocator creation - if (!aInfo.iAllocator && aInfo.iHeapInitialSize>0) - { - // new heap required - RHeap* pH = NULL; - r = UserHeap::CreateThreadHeap(aInfo, pH); - } - else if (aInfo.iAllocator) - { - // sharing a heap - RAllocator* pA = aInfo.iAllocator; - pA->Open(); - User::SwitchAllocator(pA); - r = KErrNone; - } - return r; -} - -#endif // QT_EXPORTS_NOT_FROZEN diff --git a/src/s60main/qts60main.cpp b/src/s60main/qts60main.cpp index 5fbeea5..c65344b 100644 --- a/src/s60main/qts60main.cpp +++ b/src/s60main/qts60main.cpp @@ -51,7 +51,8 @@ GLDEF_C TInt QtMainWrapper(); */ GLDEF_C TInt E32Main() { - CTrapCleanup *cleanupStack = q_check_ptr(CTrapCleanup::New()); + CTrapCleanup *cleanupStack = CTrapCleanup::New(); + Q_CHECK_PTR(cleanupStack); TInt err = 0; TRAP(err, err = QtMainWrapper()); delete cleanupStack; diff --git a/src/s60main/s60main.pro b/src/s60main/s60main.pro index 8ab3bd3..4c598e2 100644 --- a/src/s60main/s60main.pro +++ b/src/s60main/s60main.pro @@ -30,10 +30,7 @@ symbian { # Having MMP_RULES_DONT_EXPORT_ALL_CLASS_IMPEDIMENTA will cause s60main.lib be unlinkable # against GCCE apps, so remove it MMP_RULES -= $$MMP_RULES_DONT_EXPORT_ALL_CLASS_IMPEDIMENTA - linux-armcc:QMAKE_CXXFLAGS *= --export_all_vtbl - - # Flag if exports are not frozen to avoid lookup of qtcore allocator creation function by ordinal - contains(CONFIG, def_files_disabled): DEFINES += QT_EXPORTS_NOT_FROZEN + symbian-armcc:QMAKE_CXXFLAGS *= --export_all_vtbl } else { error("$$_FILE_ is intended only for Symbian!") } diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 128e9c3..2d5e5f4 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -1731,7 +1731,7 @@ QVariant QScriptEnginePrivate::toVariant(JSC::ExecState *exec, JSC::JSValue valu return variantValue(value); #ifndef QT_NO_QOBJECT else if (isQObject(value)) - return qVariantFromValue(toQObject(exec, value)); + return QVariant::fromValue(toQObject(exec, value)); #endif else if (isDate(value)) return QVariant(toDateTime(exec, value)); @@ -2455,10 +2455,6 @@ QScriptValue QScriptEngine::newQMetaObject( \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 13 - \warning This function is not available with MSVC 6. Use - qScriptValueFromQMetaObject() instead if you need to support that version - of the compiler. - \sa QScriptEngine::newQMetaObject() */ @@ -2466,14 +2462,17 @@ QScriptValue QScriptEngine::newQMetaObject( \fn QScriptValue qScriptValueFromQMetaObject(QScriptEngine *engine) \since 4.3 \relates QScriptEngine + \obsolete Uses \a engine to create a QScriptValue that represents the Qt class \c{T}. This function is equivalent to - QScriptEngine::scriptValueFromQMetaObject(). It is provided as a - work-around for MSVC 6, which doesn't support member template - functions. + QScriptEngine::scriptValueFromQMetaObject(). + + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. \sa QScriptEngine::newQMetaObject() */ @@ -3003,14 +3002,7 @@ JSC::JSValue QScriptEnginePrivate::create(JSC::ExecState *exec, int type, const case QMetaType::LongLong: return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const qlonglong*>(ptr))); case QMetaType::ULongLong: -#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804 -#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.") - return JSC::jsNumber(exec, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr))); -#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - return JSC::jsNumber(exec, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr))); -#else return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const qulonglong*>(ptr))); -#endif case QMetaType::Double: return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const double*>(ptr))); case QMetaType::QString: @@ -3054,7 +3046,7 @@ JSC::JSValue QScriptEnginePrivate::create(JSC::ExecState *exec, int type, const break; #endif case QMetaType::QVariant: - result = jscValueFromVariant(exec, *reinterpret_cast<const QVariant*>(ptr)); + result = eng->newVariant(*reinterpret_cast<const QVariant*>(ptr)); break; default: if (type == qMetaTypeId<QScriptValue>()) { @@ -3772,10 +3764,6 @@ QStringList QScriptEngine::importedExtensions() const to newVariant()); you can change this behavior by installing your own type conversion functions with qScriptRegisterMetaType(). - \warning This function is not available with MSVC 6. Use - qScriptValueFromValue() instead if you need to support that - version of the compiler. - \sa fromScriptValue(), qScriptRegisterMetaType() */ @@ -3789,10 +3777,6 @@ QStringList QScriptEngine::importedExtensions() const description of the built-in type conversion provided by QtScript. - \warning This function is not available with MSVC 6. Use - qScriptValueToValue() or qscriptvalue_cast() instead if you need - to support that version of the compiler. - \sa toScriptValue(), qScriptRegisterMetaType() */ @@ -3800,29 +3784,35 @@ QStringList QScriptEngine::importedExtensions() const \fn QScriptValue qScriptValueFromValue(QScriptEngine *engine, const T &value) \since 4.3 \relates QScriptEngine + \obsolete Creates a QScriptValue using the given \a engine with the given \a value of template type \c{T}. This function is equivalent to QScriptEngine::toScriptValue(). - It is provided as a work-around for MSVC 6, which doesn't support - member template functions. - \sa qScriptValueToValue() + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. + + \sa QScriptEngine::toScriptValue(), qscriptvalue_cast */ /*! \fn T qScriptValueToValue(const QScriptValue &value) \since 4.3 \relates QScriptEngine + \obsolete Returns the given \a value converted to the template type \c{T}. This function is equivalent to QScriptEngine::fromScriptValue(). - It is provided as a work-around for MSVC 6, which doesn't - support member template functions. - \sa qScriptValueFromValue() + \note This function was provided as a workaround for MSVC 6 + which did not support member template functions. It is advised + to use the other form in new code. + + \sa QScriptEngine::fromScriptValue() */ /*! @@ -3841,7 +3831,7 @@ QStringList QScriptEngine::importedExtensions() const \l{Conversion Between QtScript and C++ Types} for more information about the restrictions on types that can be used with QScriptValue. - \sa qScriptValueFromValue() + \sa QScriptEngine::fromScriptValue() */ /*! diff --git a/src/script/api/qscriptengine.h b/src/script/api/qscriptengine.h index 3212ed5..830d477 100644 --- a/src/script/api/qscriptengine.h +++ b/src/script/api/qscriptengine.h @@ -65,13 +65,11 @@ inline QScriptValue qscriptQMetaObjectConstructor(QScriptContext *, QScriptEngin class QRegExp; #endif -#ifndef QT_NO_MEMBER_TEMPLATES template <typename T> inline QScriptValue qScriptValueFromValue(QScriptEngine *, const T &); template <typename T> -inline T qScriptValueToValue(const QScriptValue &); -#endif +inline T qscriptvalue_cast(const QScriptValue &); class QScriptSyntaxCheckResultPrivate; class Q_SCRIPT_EXPORT QScriptSyntaxCheckResult @@ -196,9 +194,7 @@ public: QScriptValue newQMetaObject(const QMetaObject *metaObject, const QScriptValue &ctor = QScriptValue()); -# ifndef QT_NO_MEMBER_TEMPLATES template <class T> QScriptValue scriptValueFromQMetaObject(); -# endif // QT_NO_MEMBER_TEMPLATES #endif // QT_NO_QOBJECT @@ -213,7 +209,6 @@ public: -#ifndef QT_NO_MEMBER_TEMPLATES template <typename T> inline QScriptValue toScriptValue(const T &value) { @@ -222,9 +217,8 @@ public: template <typename T> inline T fromScriptValue(const QScriptValue &value) { - return qScriptValueToValue<T>(value); + return qscriptvalue_cast<T>(value); } -#endif // QT_NO_MEMBER_TEMPLATES void installTranslatorFunctions(const QScriptValue &object = QScriptValue()); @@ -285,19 +279,6 @@ private: }; #ifndef QT_NO_QOBJECT -template <class T> -inline QScriptValue qScriptValueFromQMetaObject( - QScriptEngine *engine -#ifndef qdoc - , T * /* dummy */ = 0 -#endif - ) -{ - typedef QScriptValue(*ConstructPtr)(QScriptContext *, QScriptEngine *, T *); - ConstructPtr cptr = qscriptQMetaObjectConstructor<T>; - return engine->newQMetaObject(&T::staticMetaObject, - engine->newFunction(reinterpret_cast<QScriptEngine::FunctionWithArgSignature>(cptr), 0)); -} #define Q_SCRIPT_DECLARE_QMETAOBJECT(T, _Arg1) \ template<> inline QScriptValue qscriptQMetaObjectConstructor<T>(QScriptContext *ctx, QScriptEngine *eng, T *) \ @@ -311,12 +292,26 @@ template<> inline QScriptValue qscriptQMetaObjectConstructor<T>(QScriptContext * return o; \ } -# ifndef QT_NO_MEMBER_TEMPLATES - template <class T> QScriptValue QScriptEngine::scriptValueFromQMetaObject() - { - return qScriptValueFromQMetaObject<T>(this); - } -# endif // QT_NO_MEMBER_TEMPLATES +template <class T> QScriptValue QScriptEngine::scriptValueFromQMetaObject() +{ + typedef QScriptValue(*ConstructPtr)(QScriptContext *, QScriptEngine *, T *); + ConstructPtr cptr = qscriptQMetaObjectConstructor<T>; + return newQMetaObject(&T::staticMetaObject, + newFunction(reinterpret_cast<FunctionWithArgSignature>(cptr), 0)); +} + +#ifdef QT_DEPRECATED +template <class T> +inline QT_DEPRECATED QScriptValue qScriptValueFromQMetaObject( + QScriptEngine *engine +#ifndef qdoc + , T * /* dummy */ = 0 +#endif + ) +{ + return engine->scriptValueFromQMetaObject<T>(); +} +#endif #endif // QT_NO_QOBJECT @@ -349,11 +344,7 @@ inline bool qscriptvalue_cast_helper(const QScriptValue &value, int type, void * } template<typename T> -T qscriptvalue_cast(const QScriptValue &value -#if !defined qdoc && defined Q_CC_MSVC && _MSC_VER < 1300 -, T * = 0 -#endif - ) +T qscriptvalue_cast(const QScriptValue &value) { T t; const int id = qMetaTypeId<T>(); @@ -366,19 +357,19 @@ T qscriptvalue_cast(const QScriptValue &value return T(); } -#if !defined Q_CC_MSVC || _MSC_VER >= 1300 template <> inline QVariant qscriptvalue_cast<QVariant>(const QScriptValue &value) { return value.toVariant(); } -#endif +#ifdef QT_DEPRECATED template <typename T> -inline T qScriptValueToValue(const QScriptValue &value) +inline QT_DEPRECATED T qScriptValueToValue(const QScriptValue &value) { return qscriptvalue_cast<T>(value); } +#endif inline void qScriptRegisterMetaType_helper(QScriptEngine *eng, int type, QScriptEngine::MarshalFunction mf, @@ -418,7 +409,7 @@ QScriptValue qScriptValueFromSequence(QScriptEngine *eng, const Container &cont) typename Container::const_iterator it; quint32 i; for (it = begin, i = 0; it != end; ++it, ++i) - a.setProperty(i, qScriptValueFromValue(eng, *it)); + a.setProperty(i, eng->toScriptValue(*it)); return a; } @@ -428,11 +419,7 @@ void qScriptValueToSequence(const QScriptValue &value, Container &cont) quint32 len = value.property(QLatin1String("length")).toUInt32(); for (quint32 i = 0; i < len; ++i) { QScriptValue item = value.property(i); -#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET - cont.push_back(qscriptvalue_cast<Container::value_type>(item)); -#else cont.push_back(qscriptvalue_cast<typename Container::value_type>(item)); -#endif } } diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index f494106..e6c3801 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -688,10 +688,6 @@ static bool LessThan(QScriptValue lhs, QScriptValue rhs) return false; case Number: -#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET - if (qIsNaN(lhs.toNumber()) || qIsNaN(rhs.toNumber())) - return false; -#endif return lhs.toNumber() < rhs.toNumber(); case Boolean: @@ -714,13 +710,7 @@ static bool LessThan(QScriptValue lhs, QScriptValue rhs) if (lhs.isString() && rhs.isString()) return lhs.toString() < rhs.toString(); - qsreal n1 = lhs.toNumber(); - qsreal n2 = rhs.toNumber(); -#if defined Q_CC_MSVC && !defined Q_CC_MSVC_NET - if (qIsNaN(n1) || qIsNaN(n2)) - return false; -#endif - return n1 < n2; + return lhs.toNumber() < rhs.toNumber(); } static bool Equals(QScriptValue lhs, QScriptValue rhs) diff --git a/src/script/bridge/qscriptclassobject.cpp b/src/script/bridge/qscriptclassobject.cpp index dd229f1..28f7bd1 100644 --- a/src/script/bridge/qscriptclassobject.cpp +++ b/src/script/bridge/qscriptclassobject.cpp @@ -211,7 +211,7 @@ JSC::JSValue JSC_HOST_CALL ClassObjectDelegate::call(JSC::ExecState *exec, JSC:: eng_p->pushContext(exec, thisValue, args, callee); QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame); QScriptValue scriptObject = eng_p->scriptValueFromJSCValue(obj); - QVariant result = scriptClass->extension(QScriptClass::Callable, qVariantFromValue(ctx)); + QVariant result = scriptClass->extension(QScriptClass::Callable, QVariant::fromValue(ctx)); eng_p->popContext(); eng_p->currentFrame = oldFrame; return QScriptEnginePrivate::jscValueFromVariant(exec, result); @@ -239,7 +239,7 @@ JSC::JSObject* ClassObjectDelegate::construct(JSC::ExecState *exec, JSC::JSObjec QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame); QScriptValue defaultObject = ctx->thisObject(); - QScriptValue result = qvariant_cast<QScriptValue>(scriptClass->extension(QScriptClass::Callable, qVariantFromValue(ctx))); + QScriptValue result = qvariant_cast<QScriptValue>(scriptClass->extension(QScriptClass::Callable, QVariant::fromValue(ctx))); if (!result.isObject()) result = defaultObject; eng_p->popContext(); @@ -256,7 +256,7 @@ bool ClassObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState *exe QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); QScript::SaveFrameHelper saveFrame(eng_p, exec); args << eng_p->scriptValueFromJSCValue(object) << eng_p->scriptValueFromJSCValue(value); - QVariant result = scriptClass()->extension(QScriptClass::HasInstance, qVariantFromValue(args)); + QVariant result = scriptClass()->extension(QScriptClass::HasInstance, QVariant::fromValue(args)); return result.toBool(); } diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp index 5e4f097..d24f2fe 100644 --- a/src/script/bridge/qscriptqobject.cpp +++ b/src/script/bridge/qscriptqobject.cpp @@ -664,7 +664,7 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c if (actual.isNumber()) { int ival = QScriptEnginePrivate::toInt32(exec, actual); if (m.valueToKey(ival) != 0) { - qVariantSetValue(v, ival); + v.setValue(ival); converted = true; matchDistance += 10; } @@ -672,7 +672,7 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c JSC::UString sval = QScriptEnginePrivate::toString(exec, actual); int ival = m.keyToValue(convertToLatin1(sval)); if (ival != -1) { - qVariantSetValue(v, ival); + v.setValue(ival); converted = true; matchDistance += 10; } @@ -1668,7 +1668,7 @@ static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChild(JSC::ExecState *exec QString name; if (args.size() != 0) name = args.at(0).toString(exec); - QObject *child = qFindChild<QObject*>(obj, name); + QObject *child = obj->findChild<QObject*>(name); QScriptEngine::QObjectWrapOptions opt = QScriptEngine::PreferExistingWrapperObject; return engine->newQObject(child, QScriptEngine::QtOwnership, opt); } @@ -1709,10 +1709,10 @@ static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChildren(JSC::ExecState *e } } else { const QString name(args.at(0).toString(exec)); - children = qFindChildren<QObject*>(obj, name); + children = obj->findChildren<QObject*>(name); } } else { - children = qFindChildren<QObject*>(obj, QString()); + children = obj->findChildren<QObject*>(QString()); } // create the result array with the children const int length = children.size(); diff --git a/src/script/script.pro b/src/script/script.pro index 4ee86d7..56d3f7a 100644 --- a/src/script/script.pro +++ b/src/script/script.pro @@ -39,10 +39,18 @@ wince* { LIBS += -lmmtimer } -mac { +!qpa:mac { DEFINES += ENABLE_JSC_MULTIPLE_THREADS=0 LIBS_PRIVATE += -framework AppKit } +qpa:mac { + DEFINES += ENABLE_JSC_MULTIPLE_THREADS=0 + contains(QT_CONFIG, coreservices) { + LIBS_PRIVATE += -framework CoreServices + } else { + LIBS_PRIVATE += -framework CoreFoundation + } +} include($$WEBKITDIR/JavaScriptCore/JavaScriptCore.pri) diff --git a/src/scripttools/debugging/qscriptdebuggercommand.cpp b/src/scripttools/debugging/qscriptdebuggercommand.cpp index fa223ec..5ca0535 100644 --- a/src/scripttools/debugging/qscriptdebuggercommand.cpp +++ b/src/scripttools/debugging/qscriptdebuggercommand.cpp @@ -256,7 +256,7 @@ QScriptBreakpointData QScriptDebuggerCommand::breakpointData() const void QScriptDebuggerCommand::setBreakpointData(const QScriptBreakpointData &data) { Q_D(QScriptDebuggerCommand); - d->attributes[BreakpointData] = qVariantFromValue(data); + d->attributes[BreakpointData] = QVariant::fromValue(data); } QScriptDebuggerValue QScriptDebuggerCommand::scriptValue() const @@ -268,7 +268,7 @@ QScriptDebuggerValue QScriptDebuggerCommand::scriptValue() const void QScriptDebuggerCommand::setScriptValue(const QScriptDebuggerValue &value) { Q_D(QScriptDebuggerCommand); - d->attributes[ScriptValue] = qVariantFromValue(value); + d->attributes[ScriptValue] = QVariant::fromValue(value); } int QScriptDebuggerCommand::contextIndex() const @@ -316,7 +316,7 @@ QScriptDebuggerValue QScriptDebuggerCommand::subordinateScriptValue() const void QScriptDebuggerCommand::setSubordinateScriptValue(const QScriptDebuggerValue &value) { Q_D(QScriptDebuggerCommand); - d->attributes[SubordinateScriptValue] = qVariantFromValue(value); + d->attributes[SubordinateScriptValue] = QVariant::fromValue(value); } int QScriptDebuggerCommand::snapshotId() const diff --git a/src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp b/src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp index 568af59..7616148 100644 --- a/src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp +++ b/src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp @@ -229,11 +229,11 @@ QScriptDebuggerResponse QScriptDebuggerCommandExecutor::execute( case QScriptDebuggerCommand::ScriptsCheckpoint: backend->scriptsCheckpoint(); - response.setResult(qVariantFromValue(backend->scriptsDelta())); + response.setResult(QVariant::fromValue(backend->scriptsDelta())); break; case QScriptDebuggerCommand::GetScriptsDelta: - response.setResult(qVariantFromValue(backend->scriptsDelta())); + response.setResult(QVariant::fromValue(backend->scriptsDelta())); break; case QScriptDebuggerCommand::ResolveScript: @@ -302,7 +302,7 @@ QScriptDebuggerResponse QScriptDebuggerCommandExecutor::execute( } break; case QScriptDebuggerCommand::ContextsCheckpoint: { - response.setResult(qVariantFromValue(backend->contextsCheckpoint())); + response.setResult(QVariant::fromValue(backend->contextsCheckpoint())); } break; case QScriptDebuggerCommand::GetPropertyExpressionValue: { @@ -441,7 +441,7 @@ QScriptDebuggerResponse QScriptDebuggerCommandExecutor::execute( result.addedProperties.append(dest); } backend->setIgnoreExceptions(didIgnoreExceptions); - response.setResult(qVariantFromValue(result)); + response.setResult(QVariant::fromValue(result)); } break; case QScriptDebuggerCommand::DeleteScriptObjectSnapshot: { diff --git a/src/scripttools/debugging/qscriptdebuggerconsole.cpp b/src/scripttools/debugging/qscriptdebuggerconsole.cpp index 2f7a998..268b30e 100644 --- a/src/scripttools/debugging/qscriptdebuggerconsole.cpp +++ b/src/scripttools/debugging/qscriptdebuggerconsole.cpp @@ -76,7 +76,7 @@ QT_BEGIN_NAMESPACE static QScriptValue debuggerResponseToScriptValue(QScriptEngine *eng, const QScriptDebuggerResponse &in) { QScriptValue out = eng->newObject(); - out.setProperty(QString::fromLatin1("result"), qScriptValueFromValue(eng, in.result())); + out.setProperty(QString::fromLatin1("result"), eng->toScriptValue(in.result())); out.setProperty(QString::fromLatin1("error"), QScriptValue(eng, in.error())); out.setProperty(QString::fromLatin1("async"), QScriptValue(eng, in.async())); return out; @@ -122,7 +122,7 @@ static QScriptValue breakpointMapToScriptValue(QScriptEngine *eng, const QScript QScriptValue out = eng->newObject(); QScriptBreakpointMap::const_iterator it; for (it = in.constBegin(); it != in.constEnd(); ++it) { - out.setProperty(QString::number(it.key()), qScriptValueFromValue(eng, it.value())); + out.setProperty(QString::number(it.key()), eng->toScriptValue(it.value())); } return out; } @@ -155,7 +155,7 @@ static QScriptValue scriptMapToScriptValue(QScriptEngine *eng, const QScriptScri QScriptValue out = eng->newObject(); QScriptScriptMap::const_iterator it; for (it = in.constBegin(); it != in.constEnd(); ++it) { - out.setProperty(QString::number(it.key()), qScriptValueFromValue(eng, it.value())); + out.setProperty(QString::number(it.key()), eng->toScriptValue(it.value())); } return out; } @@ -175,8 +175,8 @@ static QScriptValue consoleCommandToScriptValue( out.setProperty(QString::fromLatin1("group"), QScriptValue(eng, in->group())); out.setProperty(QString::fromLatin1("shortDescription"), QScriptValue(eng, in->shortDescription())); out.setProperty(QString::fromLatin1("longDescription"), QScriptValue(eng, in->longDescription())); - out.setProperty(QString::fromLatin1("aliases"), qScriptValueFromValue(eng, in->aliases())); - out.setProperty(QString::fromLatin1("seeAlso"), qScriptValueFromValue(eng, in->seeAlso())); + out.setProperty(QString::fromLatin1("aliases"), eng->toScriptValue(in->aliases())); + out.setProperty(QString::fromLatin1("seeAlso"), eng->toScriptValue(in->seeAlso())); return out; } @@ -207,7 +207,7 @@ static QScriptValue consoleCommandGroupMapToScriptValue( QScriptValue out = eng->newObject(); QScriptDebuggerConsoleCommandGroupMap::const_iterator it; for (it = in.constBegin(); it != in.constEnd(); ++it) { - out.setProperty(it.key(), qScriptValueFromValue(eng, it.value())); + out.setProperty(it.key(), eng->toScriptValue(it.value())); } return out; } @@ -238,7 +238,7 @@ static QScriptValue debuggerScriptValuePropertyToScriptValue(QScriptEngine *eng, { QScriptValue out = eng->newObject(); out.setProperty(QString::fromLatin1("name"), QScriptValue(eng, in.name())); - out.setProperty(QString::fromLatin1("value"), qScriptValueFromValue(eng, in.value())); + out.setProperty(QString::fromLatin1("value"), eng->toScriptValue(in.value())); out.setProperty(QString::fromLatin1("valueAsString"), QScriptValue(eng, in.valueAsString())); out.setProperty(QString::fromLatin1("flags"), QScriptValue(eng, static_cast<int>(in.flags()))); return out; diff --git a/src/scripttools/debugging/qscriptdebuggerconsolewidget.cpp b/src/scripttools/debugging/qscriptdebuggerconsolewidget.cpp index 5db012a..d0559c5 100644 --- a/src/scripttools/debugging/qscriptdebuggerconsolewidget.cpp +++ b/src/scripttools/debugging/qscriptdebuggerconsolewidget.cpp @@ -163,10 +163,10 @@ private: InputEdit *inputEdit; }; -class OutputEdit : public QPlainTextEdit +class QScriptDebuggerConsoleWidgetOutputEdit : public QPlainTextEdit { public: - OutputEdit(QWidget *parent = 0) + QScriptDebuggerConsoleWidgetOutputEdit(QWidget *parent = 0) : QPlainTextEdit(parent) { setFrameShape(QFrame::NoFrame); @@ -206,7 +206,7 @@ public: void _q_onCompletionTaskFinished(); CommandLine *commandLine; - OutputEdit *outputEdit; + QScriptDebuggerConsoleWidgetOutputEdit *outputEdit; int historyIndex; QString newInput; }; @@ -320,7 +320,7 @@ QScriptDebuggerConsoleWidget::QScriptDebuggerConsoleWidget(QWidget *parent) Q_D(QScriptDebuggerConsoleWidget); d->commandLine = new CommandLine(); d->commandLine->setPrompt(QString::fromLatin1("qsdb>")); - d->outputEdit = new OutputEdit(); + d->outputEdit = new QScriptDebuggerConsoleWidgetOutputEdit(); QVBoxLayout *vbox = new QVBoxLayout(this); vbox->setSpacing(0); vbox->setMargin(0); diff --git a/src/scripttools/debugging/qscriptdebuggerevent.cpp b/src/scripttools/debugging/qscriptdebuggerevent.cpp index f5f20cf..55df35b 100644 --- a/src/scripttools/debugging/qscriptdebuggerevent.cpp +++ b/src/scripttools/debugging/qscriptdebuggerevent.cpp @@ -216,7 +216,7 @@ QScriptDebuggerValue QScriptDebuggerEvent::scriptValue() const void QScriptDebuggerEvent::setScriptValue(const QScriptDebuggerValue &value) { Q_D(QScriptDebuggerEvent); - d->attributes[Value] = qVariantFromValue(value); + d->attributes[Value] = QVariant::fromValue(value); } void QScriptDebuggerEvent::setNestedEvaluate(bool nested) diff --git a/src/scripttools/debugging/qscriptdebuggerresponse.cpp b/src/scripttools/debugging/qscriptdebuggerresponse.cpp index 0caa3e2..382e604e 100644 --- a/src/scripttools/debugging/qscriptdebuggerresponse.cpp +++ b/src/scripttools/debugging/qscriptdebuggerresponse.cpp @@ -162,49 +162,49 @@ void QScriptDebuggerResponse::setResult(const QString &value) void QScriptDebuggerResponse::setResult(const QScriptBreakpointData &data) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(data); + d->result = QVariant::fromValue(data); } void QScriptDebuggerResponse::setResult(const QScriptBreakpointMap &breakpoints) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(breakpoints); + d->result = QVariant::fromValue(breakpoints); } void QScriptDebuggerResponse::setResult(const QScriptScriptMap &scripts) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(scripts); + d->result = QVariant::fromValue(scripts); } void QScriptDebuggerResponse::setResult(const QScriptScriptData &data) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(data); + d->result = QVariant::fromValue(data); } void QScriptDebuggerResponse::setResult(const QScriptDebuggerValue &value) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(value); + d->result = QVariant::fromValue(value); } void QScriptDebuggerResponse::setResult(const QScriptDebuggerValueList &values) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(values); + d->result = QVariant::fromValue(values); } void QScriptDebuggerResponse::setResult(const QScriptDebuggerValuePropertyList &props) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(props); + d->result = QVariant::fromValue(props); } void QScriptDebuggerResponse::setResult(const QScriptContextInfo &info) { Q_D(QScriptDebuggerResponse); - d->result = qVariantFromValue(info); + d->result = QVariant::fromValue(info); } int QScriptDebuggerResponse::resultAsInt() const diff --git a/src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp b/src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp index 117c2d6..83cabfd 100644 --- a/src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp +++ b/src/scripttools/debugging/qscriptdebuggerscriptedconsolecommand.cpp @@ -227,7 +227,7 @@ void QScriptDebuggerScriptedConsoleCommandJob::handleResponse( QScriptEngine *engine = d->command->globalObject.engine(); engine->setGlobalObject(d->command->globalObject); QScriptValueList args; - args.append(qScriptValueFromValue(engine, response)); + args.append(engine->toScriptValue(response)); args.append(QScriptValue(engine, commandId)); QScriptDebuggerConsoleGlobalObject *global; global = qobject_cast<QScriptDebuggerConsoleGlobalObject*>(d->command->globalObject.toQObject()); diff --git a/src/scripttools/debugging/qscriptdebugoutputwidget.cpp b/src/scripttools/debugging/qscriptdebugoutputwidget.cpp index 3bca96c..594a9dc 100644 --- a/src/scripttools/debugging/qscriptdebugoutputwidget.cpp +++ b/src/scripttools/debugging/qscriptdebugoutputwidget.cpp @@ -51,10 +51,10 @@ QT_BEGIN_NAMESPACE namespace { -class OutputEdit : public QPlainTextEdit +class QScriptDebugOutputWidgetOutputEdit : public QPlainTextEdit { public: - OutputEdit(QWidget *parent = 0) + QScriptDebugOutputWidgetOutputEdit(QWidget *parent = 0) : QPlainTextEdit(parent) { setReadOnly(true); @@ -85,7 +85,7 @@ public: QScriptDebugOutputWidgetPrivate(); ~QScriptDebugOutputWidgetPrivate(); - OutputEdit *outputEdit; + QScriptDebugOutputWidgetOutputEdit *outputEdit; }; QScriptDebugOutputWidgetPrivate::QScriptDebugOutputWidgetPrivate() @@ -100,7 +100,7 @@ QScriptDebugOutputWidget::QScriptDebugOutputWidget(QWidget *parent) : QScriptDebugOutputWidgetInterface(*new QScriptDebugOutputWidgetPrivate, parent, 0) { Q_D(QScriptDebugOutputWidget); - d->outputEdit = new OutputEdit(); + d->outputEdit = new QScriptDebugOutputWidgetOutputEdit(); QVBoxLayout *vbox = new QVBoxLayout(this); vbox->setMargin(0); vbox->setSpacing(0); diff --git a/src/scripttools/debugging/qscripterrorlogwidget.cpp b/src/scripttools/debugging/qscripterrorlogwidget.cpp index 735c546..fd9a939 100644 --- a/src/scripttools/debugging/qscripterrorlogwidget.cpp +++ b/src/scripttools/debugging/qscripterrorlogwidget.cpp @@ -52,10 +52,10 @@ QT_BEGIN_NAMESPACE namespace { -class OutputEdit : public QTextEdit +class QScriptErrorLogWidgetOutputEdit : public QTextEdit { public: - OutputEdit(QWidget *parent = 0) + QScriptErrorLogWidgetOutputEdit(QWidget *parent = 0) : QTextEdit(parent) { setReadOnly(true); @@ -80,7 +80,7 @@ public: QScriptErrorLogWidgetPrivate(); ~QScriptErrorLogWidgetPrivate(); - OutputEdit *outputEdit; + QScriptErrorLogWidgetOutputEdit *outputEdit; }; QScriptErrorLogWidgetPrivate::QScriptErrorLogWidgetPrivate() @@ -95,7 +95,7 @@ QScriptErrorLogWidget::QScriptErrorLogWidget(QWidget *parent) : QScriptErrorLogWidgetInterface(*new QScriptErrorLogWidgetPrivate, parent, 0) { Q_D(QScriptErrorLogWidget); - d->outputEdit = new OutputEdit(); + d->outputEdit = new QScriptErrorLogWidgetOutputEdit(); QVBoxLayout *vbox = new QVBoxLayout(this); vbox->setMargin(0); vbox->setSpacing(0); diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index 2261887..a060a01 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -420,10 +420,10 @@ QVariant QMYSQLResult::handle() const { #if MYSQL_VERSION_ID >= 40108 if(d->preparedQuery) - return d->meta ? qVariantFromValue(d->meta) : qVariantFromValue(d->stmt); + return d->meta ? QVariant::fromValue(d->meta) : qVariantFromValue(d->stmt); else #endif - return qVariantFromValue(d->result); + return QVariant::fromValue(d->result); } void QMYSQLResult::cleanup() @@ -1432,7 +1432,7 @@ QSqlRecord QMYSQLDriver::record(const QString& tablename) const QVariant QMYSQLDriver::handle() const { - return qVariantFromValue(d->mysql); + return QVariant::fromValue(d->mysql); } bool QMYSQLDriver::beginTransaction() diff --git a/src/sql/drivers/oci/qsql_oci.cpp b/src/sql/drivers/oci/qsql_oci.cpp index e11cf75..6870055 100644 --- a/src/sql/drivers/oci/qsql_oci.cpp +++ b/src/sql/drivers/oci/qsql_oci.cpp @@ -293,9 +293,9 @@ int QOCIResultPrivate::bindValue(OCIStmt *sql, OCIBind **hbnd, OCIError *err, in SQLT_FLT, indPtr, 0, 0, 0, 0, OCI_DEFAULT); break; case QVariant::UserType: - if (qVariantCanConvert<QOCIRowIdPointer>(val) && !isOutValue(pos)) { + if (val.canConvert<QOCIRowIdPointer>() && !isOutValue(pos)) { // use a const pointer to prevent a detach - const QOCIRowIdPointer rptr = qVariantValue<QOCIRowIdPointer>(val); + const QOCIRowIdPointer rptr = qvariant_cast<QOCIRowIdPointer>(val); r = OCIBindByPos(sql, hbnd, err, pos + 1, // it's an IN value, so const_cast is ok @@ -1364,8 +1364,8 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b break; } case QVariant::UserType: - if (qVariantCanConvert<QOCIRowIdPointer>(val)) { - const QOCIRowIdPointer rptr = qVariantValue<QOCIRowIdPointer>(val); + if (val.canConvert<QOCIRowIdPointer>()) { + const QOCIRowIdPointer rptr = qvariant_cast<QOCIRowIdPointer>(val); *reinterpret_cast<OCIRowid**>(dataPtr) = rptr->id; columns[i].lengths[row] = 0; break; @@ -1704,7 +1704,7 @@ QOCIResult::~QOCIResult() QVariant QOCIResult::handle() const { - return qVariantFromValue(d->sql); + return QVariant::fromValue(d->sql); } bool QOCIResult::reset (const QString& query) @@ -1932,7 +1932,7 @@ QVariant QOCIResult::lastInsertId() const int r = OCIAttrGet(d->sql, OCI_HTYPE_STMT, ptr.constData()->id, 0, OCI_ATTR_ROWID, d->err); if (r == OCI_SUCCESS) - return qVariantFromValue(ptr); + return QVariant::fromValue(ptr); } return QVariant(); } @@ -2534,7 +2534,7 @@ QString QOCIDriver::formatValue(const QSqlField &field, bool trimStrings) const QVariant QOCIDriver::handle() const { - return qVariantFromValue(d->env); + return QVariant::fromValue(d->env); } QString QOCIDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index 66dabfa..3e77779 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -62,15 +62,6 @@ QT_BEGIN_NAMESPACE // undefine this to prevent initial check of the ODBC driver #define ODBC_CHECK_DRIVER -// newer platform SDKs use SQLLEN instead of SQLINTEGER -#if defined(WIN32) && (_MSC_VER < 1300) && !defined(__MINGW64_VERSION_MAJOR) -# define QSQLLEN SQLINTEGER -# define QSQLULEN SQLUINTEGER -#else -# define QSQLLEN SQLLEN -# define QSQLULEN SQLULEN -#endif - static const int COLNAMESIZE = 256; //Map Qt parameter types to ODBC types static const SQLSMALLINT qParamType[4] = { SQL_PARAM_INPUT, SQL_PARAM_INPUT, SQL_PARAM_OUTPUT, SQL_PARAM_INPUT_OUTPUT }; @@ -360,7 +351,7 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni { QString fieldVal; SQLRETURN r = SQL_ERROR; - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; // NB! colSize must be a multiple of 2 for unicode enabled DBs if (colSize <= 0) { @@ -462,10 +453,10 @@ static QVariant qGetBinaryData(SQLHANDLE hStmt, int column) QByteArray fieldVal; SQLSMALLINT colNameLen; SQLSMALLINT colType; - QSQLULEN colSize; + SQLULEN colSize; SQLSMALLINT colScale; SQLSMALLINT nullable; - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; SQLRETURN r = SQL_ERROR; QVarLengthArray<SQLTCHAR> colName(COLNAMESIZE); @@ -499,7 +490,7 @@ static QVariant qGetBinaryData(SQLHANDLE hStmt, int column) break; if (lengthIndicator == SQL_NULL_DATA) return QVariant(QVariant::ByteArray); - if (lengthIndicator > QSQLLEN(colSize) || lengthIndicator == SQL_NO_TOTAL) { + if (lengthIndicator > SQLLEN(colSize) || lengthIndicator == SQL_NO_TOTAL) { read += colSize; colSize = 65536; } else { @@ -517,7 +508,7 @@ static QVariant qGetBinaryData(SQLHANDLE hStmt, int column) static QVariant qGetIntData(SQLHANDLE hStmt, int column, bool isSigned = true) { SQLINTEGER intbuf = 0; - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; SQLRETURN r = SQLGetData(hStmt, column+1, isSigned ? SQL_C_SLONG : SQL_C_ULONG, @@ -537,7 +528,7 @@ static QVariant qGetIntData(SQLHANDLE hStmt, int column, bool isSigned = true) static QVariant qGetDoubleData(SQLHANDLE hStmt, int column) { SQLDOUBLE dblbuf; - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; SQLRETURN r = SQLGetData(hStmt, column+1, SQL_C_DOUBLE, @@ -557,7 +548,7 @@ static QVariant qGetDoubleData(SQLHANDLE hStmt, int column) static QVariant qGetBigIntData(SQLHANDLE hStmt, int column, bool isSigned = true) { SQLBIGINT lngbuf = 0; - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; SQLRETURN r = SQLGetData(hStmt, column+1, isSigned ? SQL_C_SBIGINT : SQL_C_UBIGINT, @@ -601,7 +592,7 @@ static QSqlField qMakeFieldInfo(const QODBCPrivate* p, int i ) { SQLSMALLINT colNameLen; SQLSMALLINT colType; - QSQLULEN colSize; + SQLULEN colSize; SQLSMALLINT colScale; SQLSMALLINT nullable; SQLRETURN r = SQL_ERROR; @@ -621,7 +612,7 @@ static QSqlField qMakeFieldInfo(const QODBCPrivate* p, int i ) return QSqlField(); } - QSQLLEN unsignedFlag = SQL_FALSE; + SQLLEN unsignedFlag = SQL_FALSE; r = SQLColAttribute (p->hStmt, i + 1, SQL_DESC_UNSIGNED, @@ -1146,7 +1137,7 @@ QVariant QODBCResult::data(int field) return d->fieldCache.at(field); SQLRETURN r(0); - QSQLLEN lengthIndicator = 0; + SQLLEN lengthIndicator = 0; for (int i = d->fieldCacheIdx; i <= field; ++i) { // some servers do not support fetching column n after we already @@ -1256,7 +1247,7 @@ int QODBCResult::size() int QODBCResult::numRowsAffected() { - QSQLLEN affectedRowCount = 0; + SQLLEN affectedRowCount = 0; SQLRETURN r = SQLRowCount(d->hStmt, &affectedRowCount); if (r == SQL_SUCCESS) return affectedRowCount; @@ -1343,8 +1334,8 @@ bool QODBCResult::exec() SQLCloseCursor(d->hStmt); QList<QByteArray> tmpStorage; // holds temporary buffers - QVarLengthArray<QSQLLEN, 32> indicators(boundValues().count()); - memset(indicators.data(), 0, indicators.size() * sizeof(QSQLLEN)); + QVarLengthArray<SQLLEN, 32> indicators(boundValues().count()); + memset(indicators.data(), 0, indicators.size() * sizeof(SQLLEN)); // bind parameters - only positional binding allowed QVector<QVariant>& values = boundValues(); @@ -1354,7 +1345,7 @@ bool QODBCResult::exec() if (bindValueType(i) & QSql::Out) values[i].detach(); const QVariant &val = values.at(i); - QSQLLEN *ind = &indicators[i]; + SQLLEN *ind = &indicators[i]; if (val.isNull()) *ind = SQL_NULL_DATA; switch (val.type()) { diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index 2a4e595..179f7ba 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -279,7 +279,7 @@ QPSQLResult::~QPSQLResult() QVariant QPSQLResult::handle() const { - return qVariantFromValue(d->result); + return QVariant::fromValue(d->result); } void QPSQLResult::cleanup() @@ -706,7 +706,7 @@ QPSQLDriver::~QPSQLDriver() QVariant QPSQLDriver::handle() const { - return qVariantFromValue(d->connection); + return QVariant::fromValue(d->connection); } bool QPSQLDriver::hasFeature(DriverFeature f) const diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp index 4344af4..e5cc614 100644 --- a/src/sql/drivers/sqlite/qsql_sqlite.cpp +++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp @@ -452,7 +452,7 @@ QSqlRecord QSQLiteResult::record() const QVariant QSQLiteResult::handle() const { - return qVariantFromValue(d->stmt); + return QVariant::fromValue(d->stmt); } ///////////////////////////////////////////////////////// @@ -697,7 +697,7 @@ QSqlRecord QSQLiteDriver::record(const QString &tbl) const QVariant QSQLiteDriver::handle() const { - return qVariantFromValue(d->access); + return QVariant::fromValue(d->access); } QString QSQLiteDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const diff --git a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp index ea476e5..89f3ed3 100644 --- a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp +++ b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp @@ -342,7 +342,7 @@ QSqlRecord QSQLite2Result::record() const QVariant QSQLite2Result::handle() const { - return qVariantFromValue(d->currentMachine); + return QVariant::fromValue(d->currentMachine); } ///////////////////////////////////////////////////////// @@ -558,7 +558,7 @@ QSqlRecord QSQLite2Driver::record(const QString &tbl) const QVariant QSQLite2Driver::handle() const { - return qVariantFromValue(d->access); + return QVariant::fromValue(d->access); } QString QSQLite2Driver::escapeIdentifier(const QString &identifier, IdentifierType /*type*/) const diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp index 2ab37de..1cf5fde 100644 --- a/src/sql/kernel/qsqldatabase.cpp +++ b/src/sql/kernel/qsqldatabase.cpp @@ -166,7 +166,7 @@ public: static QSqlDatabase database(const QString& name, bool open); static void addDatabase(const QSqlDatabase &db, const QString & name); static void removeDatabase(const QString& name); - static void invalidateDb(const QSqlDatabase &db, const QString &name); + static void invalidateDb(const QSqlDatabase &db, const QString &name, bool doWarn = true); static DriverDict &driverDict(); static void cleanConnections(); }; @@ -200,7 +200,7 @@ void QSqlDatabasePrivate::cleanConnections() QConnectionDict::iterator it = dict->begin(); while (it != dict->end()) { - invalidateDb(it.value(), it.key()); + invalidateDb(it.value(), it.key(), false); ++it; } dict->clear(); @@ -232,9 +232,9 @@ QSqlDatabasePrivate *QSqlDatabasePrivate::shared_null() return &n; } -void QSqlDatabasePrivate::invalidateDb(const QSqlDatabase &db, const QString &name) +void QSqlDatabasePrivate::invalidateDb(const QSqlDatabase &db, const QString &name, bool doWarn) { - if (db.d->ref != 1) { + if (db.d->ref != 1 && doWarn) { qWarning("QSqlDatabasePrivate::removeDatabase: connection '%s' is still in use, " "all queries will cease to work.", name.toLocal8Bit().constData()); db.d->disable(); diff --git a/src/src.pro b/src/src.pro index 060f48b..c07d399 100644 --- a/src/src.pro +++ b/src/src.pro @@ -5,6 +5,7 @@ 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 +nacl: SRC_SUBDIRS -= src_network src_testlib !symbian:contains(QT_CONFIG, dbus):SRC_SUBDIRS += src_dbus !contains(QT_CONFIG, no-gui): SRC_SUBDIRS += src_gui !wince*:!symbian:!vxworks:contains(QT_CONFIG, qt3support): SRC_SUBDIRS += src_qt3support diff --git a/src/testlib/qabstracttestlogger_p.h b/src/testlib/qabstracttestlogger_p.h index c84f327..a996e88 100644 --- a/src/testlib/qabstracttestlogger_p.h +++ b/src/testlib/qabstracttestlogger_p.h @@ -95,6 +95,8 @@ public: virtual void addMessage(MessageTypes type, const char *message, const char *file = 0, int line = 0) = 0; + virtual void registerRandomSeed(unsigned int seed) = 0; + static void outputString(const char *msg); static bool isTtyOutput(); }; diff --git a/src/testlib/qplaintestlogger.cpp b/src/testlib/qplaintestlogger.cpp index 1a0e737..59248a9 100644 --- a/src/testlib/qplaintestlogger.cpp +++ b/src/testlib/qplaintestlogger.cpp @@ -384,6 +384,7 @@ namespace QTest { } QPlainTestLogger::QPlainTestLogger() +: randomSeed(9), hasRandomSeed(false) { #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) InitializeCriticalSection(&QTest::outputCriticalSection); @@ -415,10 +416,17 @@ void QPlainTestLogger::startLogging() QTest::qt_snprintf(buf, sizeof(buf), "Testing %s\n", QTestResult::currentTestObjectName()); } else { - QTest::qt_snprintf(buf, sizeof(buf), - "********* Start testing of %s *********\n" - "Config: Using QTest library " QTEST_VERSION_STR - ", Qt %s\n", QTestResult::currentTestObjectName(), qVersion()); + if (hasRandomSeed) { + QTest::qt_snprintf(buf, sizeof(buf), + "********* Start testing of %s *********\n" + "Config: Using QTest library " QTEST_VERSION_STR + ", Qt %s, Random seed %d\n", QTestResult::currentTestObjectName(), qVersion(), randomSeed); + } else { + QTest::qt_snprintf(buf, sizeof(buf), + "********* Start testing of %s *********\n" + "Config: Using QTest library " QTEST_VERSION_STR + ", Qt %s\n", QTestResult::currentTestObjectName(), qVersion()); + } } QTest::outputMessage(buf); } @@ -480,4 +488,10 @@ void QPlainTestLogger::addMessage(MessageTypes type, const char *message, QTest::printMessage(QTest::messageType2String(type), message, file, line); } +void QPlainTestLogger::registerRandomSeed(unsigned int seed) +{ + randomSeed = seed; + hasRandomSeed = true; +} + QT_END_NAMESPACE diff --git a/src/testlib/qplaintestlogger_p.h b/src/testlib/qplaintestlogger_p.h index f1f1d4e..9195600 100644 --- a/src/testlib/qplaintestlogger_p.h +++ b/src/testlib/qplaintestlogger_p.h @@ -75,6 +75,10 @@ public: void addMessage(MessageTypes type, const char *message, const char *file = 0, int line = 0); + void registerRandomSeed(unsigned int seed); +private: + unsigned int randomSeed; + bool hasRandomSeed; }; QT_END_NAMESPACE diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h index 633d635..aa9b2bd 100644 --- a/src/testlib/qtest.h +++ b/src/testlib/qtest.h @@ -159,7 +159,7 @@ template<> inline char *toString(const QVariant &v) if (!v.isNull()) { vstring.append(','); if (v.canConvert(QVariant::String)) { - vstring.append(qVariantValue<QString>(v).toLatin1()); + vstring.append(qvariant_cast<QString>(v).toLatin1()); } else { vstring.append("<value not representable as string>"); diff --git a/src/testlib/qtest_global.h b/src/testlib/qtest_global.h index a78113a..4dd0cb7 100644 --- a/src/testlib/qtest_global.h +++ b/src/testlib/qtest_global.h @@ -62,7 +62,7 @@ QT_MODULE(Test) # endif #endif -#if (defined (Q_CC_MSVC) && _MSC_VER < 1310) || defined (Q_CC_SUN) || defined (Q_CC_XLC) || (defined (Q_CC_GNU) && (__GNUC__ - 0 < 3)) || defined (Q_CC_NOKIAX86) +#if defined (Q_CC_SUN) || defined (Q_CC_XLC) || (defined (Q_CC_GNU) && (__GNUC__ - 0 < 3)) || defined (Q_CC_NOKIAX86) # define QTEST_NO_SPECIALIZATIONS #endif diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 17f1a6b..aae2786 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -826,25 +826,46 @@ namespace QTest { static QObject *currentTestObject = 0; - static struct TestFunction { - TestFunction():function(0), data(0) {} - ~TestFunction() { delete [] data; } - int function; - char *data; - } *testFuncs; - + class TestFunction { + public: + TestFunction() : function_(-1), data_(0) {} + void set(int function, char *data) { function_ = function; data_ = data; } + char *data() const { return data_; } + int function() const { return function_; } + ~TestFunction() { delete[] data_; } + private: + int function_; + char *data_; + }; /** - * Contains the count of test functions that was supplied - * on the command line, if any. Hence, if lastTestFuncIdx is - * more than zero, those functions should be run instead of + * Contains the list of test functions that was supplied + * on the command line, if any. Hence, if not empty, + * those functions should be run instead of * all appearing in the test case. */ - static int lastTestFuncIdx = -1; + static TestFunction * testFuncs = 0; + static int testFuncCount = 0; + + /** Don't leak testFuncs on exit even on error */ + static struct TestFuncCleanup + { + void cleanup() + { + delete[] testFuncs; + testFuncCount = 0; + testFuncs = 0; + } + + ~TestFuncCleanup() { cleanup(); } + } testFuncCleaner; static int keyDelay = -1; static int mouseDelay = -1; static int eventDelay = -1; + static bool randomOrder = false; static int keyVerbose = -1; + static unsigned int seed = 0; + static bool seedSet = false; #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) static bool noCrashHandler = false; #endif @@ -930,6 +951,43 @@ int Q_TESTLIB_EXPORT defaultKeyDelay() return keyDelay; } +void seedRandom() +{ + static bool randomSeeded = false; + if (!randomSeeded) { + if (!QTest::seedSet) { + QElapsedTimer timer; + timer.start(); + QTest::seed = timer.msecsSinceReference(); + } + qsrand(QTest::seed); + randomSeeded = true; + } +} + +int qTestRandomSeed() +{ + Q_ASSERT(QTest::seedSet); + return QTest::seed; +} + +template<typename T> +void swap(T * array, int pos, int otherPos) +{ + T tmp = array[pos]; + array[pos] = array[otherPos]; + array[otherPos] = tmp; +} + +template<typename T> +static void randomizeList(T * array, int size) +{ + for (int i = 0; i != size; i++) { + int pos = qrand() % size; + swap(array, pos, i); + } +} + static bool isValidSlot(const QMetaMethod &sl) { if (sl.access() != QMetaMethod::Private || !sl.parameterTypes().isEmpty() @@ -971,8 +1029,6 @@ static int qToInt(char *str) static void qParseArgs(int argc, char *argv[]) { - lastTestFuncIdx = -1; - const char *testOptions = " options:\n" " -functions : Returns a list of current testfunctions\n" @@ -985,6 +1041,9 @@ static void qParseArgs(int argc, char *argv[]) " -v1 : Print enter messages for each testfunction\n" " -v2 : Also print out each QVERIFY/QCOMPARE/QTEST\n" " -vs : Print every signal emitted\n" + " -random : Run testcases within each test in random order\n" + " -seed n : Positive integer to be used as seed for -random. If not specified,\n" + " the current time will be used as seed.\n" " -eventdelay ms : Set default delay for mouse and keyboard simulation to ms milliseconds\n" " -keydelay ms : Set default delay for keyboard simulation to ms milliseconds\n" " -mousedelay ms : Set default delay for mouse simulation to ms milliseconds\n" @@ -1100,6 +1159,22 @@ static void qParseArgs(int argc, char *argv[]) #endif } else if (strcmp(argv[i], "-eventcounter") == 0) { QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::EventCounter); + } else if (strcmp(argv[i], "-random") == 0) { + QTest::randomOrder = true; + } else if (strcmp(argv[i], "-seed") == 0) { + bool argumentOk = false; + if (i + 1 < argc) { + char * endpt = 0; + long longSeed = strtol(argv[++i], &endpt, 10); + argumentOk = (*endpt == '\0' && longSeed >= 0); + QTest::seed = longSeed; + } + if (!argumentOk) { + printf("-seed needs an extra positive integer parameter to specify the seed\n"); + exit(1); + } else { + QTest::seedSet = true; + } } else if (strcmp(argv[i], "-minimumvalue") == 0) { if (i + 1 >= argc) { printf("-minimumvalue needs an extra parameter to indicate the minimum time(ms)\n"); @@ -1140,6 +1215,10 @@ static void qParseArgs(int argc, char *argv[]) printf("Unknown option: '%s'\n\n%s", argv[i], testOptions); exit(1); } else { + if (!QTest::testFuncs) { + QTest::testFuncs = new QTest::TestFunction[512]; + } + int colon = -1; char buf[512], *data=0; int off; @@ -1161,17 +1240,16 @@ static void qParseArgs(int argc, char *argv[]) qPrintTestSlots(); exit(1); } - ++QTest::lastTestFuncIdx; - if (!QTest::testFuncs) { - struct Cleanup { ~Cleanup() { delete[] QTest::testFuncs; } }; - static Cleanup cleanup; - QTest::testFuncs = new TestFunction[512]; - } - QTest::testFuncs[QTest::lastTestFuncIdx].function = idx; - QTest::testFuncs[QTest::lastTestFuncIdx].data = data; - QTEST_ASSERT(QTest::lastTestFuncIdx < 512); + testFuncs[testFuncCount].set(idx, data); + testFuncCount++; + QTEST_ASSERT(QTest::testFuncCount < 512); } } + + if (QTest::seedSet && !QTest::randomOrder) { + printf("-seed requires -random\n"); + exit(1); + } } QBenchmarkResult qMedian(const QList<QBenchmarkResult> &container) @@ -1466,9 +1544,11 @@ static void qInvokeTestMethods(QObject *testObject) { const QMetaObject *metaObject = testObject->metaObject(); QTEST_ASSERT(metaObject); - - QTestLog::startLogging(); - + if (QTest::randomOrder) { + QTestLog::startLogging(QTest::seed); + } else { + QTestLog::startLogging(); + } QTestResult::setCurrentTestFunction("initTestCase"); QTestResult::setCurrentTestLocation(QTestResult::DataFunc); QTestTable::globalTestTable(); @@ -1484,21 +1564,31 @@ static void qInvokeTestMethods(QObject *testObject) if(!QTestResult::skipCurrentTest() && !previousFailed) { - if (lastTestFuncIdx >= 0) { - for (int i = 0; i <= lastTestFuncIdx; ++i) { - if (!qInvokeTestMethod(metaObject->method(testFuncs[i].function).signature(), - testFuncs[i].data)) + if (QTest::testFuncs) { + if (QTest::randomOrder) + randomizeList(QTest::testFuncs, QTest::testFuncCount); + for (int i = 0; i != QTest::testFuncCount; i++) { + if (!qInvokeTestMethod(metaObject->method(QTest::testFuncs[i].function()).signature(), + QTest::testFuncs[i].data())) { break; + } } + testFuncCleaner.cleanup(); } else { int methodCount = metaObject->methodCount(); - for (int i = 0; i < methodCount; ++i) { - QMetaMethod slotMethod = metaObject->method(i); - if (!isValidSlot(slotMethod)) + QMetaMethod *testMethods = new QMetaMethod[methodCount]; + for (int i = 0; i != methodCount; i++) + testMethods[i] = metaObject->method(i); + if (QTest::randomOrder) + randomizeList(testMethods, methodCount); + for (int i = 0; i != methodCount; i++) { + if (!isValidSlot(testMethods[i])) continue; - if (!qInvokeTestMethod(slotMethod.signature())) + if (!qInvokeTestMethod(testMethods[i].signature())) break; } + delete[] testMethods; + testMethods = 0; } } @@ -1689,6 +1779,9 @@ int QTest::qExec(QObject *testObject, int argc, char **argv) QTestResult::setCurrentTestObject(metaObject->className()); qParseArgs(argc, argv); + if (QTest::randomOrder) { + seedRandom(); + } #ifdef QTESTLIB_USE_VALGRIND if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) { const QStringList origAppArgs(QCoreApplication::arguments()); diff --git a/src/testlib/qtestlightxmlstreamer.cpp b/src/testlib/qtestlightxmlstreamer.cpp index 0ac9ea8..cc5397a 100644 --- a/src/testlib/qtestlightxmlstreamer.cpp +++ b/src/testlib/qtestlightxmlstreamer.cpp @@ -42,6 +42,7 @@ #include "qtestlightxmlstreamer.h" #include "qtestelement.h" #include "qtestelementattribute.h" +#include "qtestlogger_p.h" #include "QtTest/private/qtestlog_p.h" #include "QtTest/private/qtestresult_p.h" @@ -164,8 +165,13 @@ void QTestLightXmlStreamer::formatBeforeAttributes(const QTestElement *element, void QTestLightXmlStreamer::output(QTestElement *element) const { QTestCharBuffer buf; - QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n", + if (logger()->hasRandomSeed()) { + QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n <RandomSeed>%d</RandomSeed>\n", + qVersion(), QTEST_VERSION_STR, logger()->randomSeed() ); + } else { + QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n", qVersion(), QTEST_VERSION_STR ); + } outputString(buf.constData()); QTest::qt_asprintf(&buf, "</Environment>\n"); diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp index 398dec5..d58e231 100644 --- a/src/testlib/qtestlog.cpp +++ b/src/testlib/qtestlog.cpp @@ -168,6 +168,29 @@ namespace QTest { } } +void initLogger() +{ + switch (QTest::logMode) { + case QTestLog::Plain: + QTest::testLogger = new QPlainTestLogger; + break; + case QTestLog::XML:{ + if(QTest::flushMode == QTestLog::FLushOn) + QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Complete); + else + QTest::testLogger = new QTestLogger(QTestLogger::TLF_XML); + break; + }case QTestLog::LightXML:{ + if(QTest::flushMode == QTestLog::FLushOn) + QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Light); + else + QTest::testLogger = new QTestLogger(QTestLogger::TLF_LightXml); + break; + }case QTestLog::XunitXML: + QTest::testLogger = new QTestLogger(QTestLogger::TLF_XunitXml); + } +} + } QTestLog::QTestLog() @@ -268,32 +291,20 @@ void QTestLog::addBenchmarkResult(const QBenchmarkResult &result) QTest::testLogger->addBenchmarkResult(result); } -void QTestLog::startLogging() +void QTestLog::startLogging(unsigned int randomSeed) { QTEST_ASSERT(!QTest::testLogger); - - switch (QTest::logMode) { - case QTestLog::Plain: - QTest::testLogger = new QPlainTestLogger; - break; - case QTestLog::XML:{ - if(QTest::flushMode == QTestLog::FLushOn) - QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Complete); - else - QTest::testLogger = new QTestLogger(QTestLogger::TLF_XML); - break; - }case QTestLog::LightXML:{ - if(QTest::flushMode == QTestLog::FLushOn) - QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Light); - else - QTest::testLogger = new QTestLogger(QTestLogger::TLF_LightXml); - break; - }case QTestLog::XunitXML: - QTest::testLogger = new QTestLogger(QTestLogger::TLF_XunitXml); - } - + QTest::initLogger(); + QTest::testLogger->registerRandomSeed(randomSeed); QTest::testLogger->startLogging(); + QTest::oldMessageHandler = qInstallMsgHandler(QTest::messageHandler); +} +void QTestLog::startLogging() +{ + QTEST_ASSERT(!QTest::testLogger); + QTest::initLogger(); + QTest::testLogger->startLogging(); QTest::oldMessageHandler = qInstallMsgHandler(QTest::messageHandler); } diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h index d36ff04..01d39eb 100644 --- a/src/testlib/qtestlog_p.h +++ b/src/testlib/qtestlog_p.h @@ -83,6 +83,7 @@ public: static void info(const char *msg, const char *file, int line); static void startLogging(); + static void startLogging(unsigned int randomSeed); static void stopLogging(); static void setLogMode(LogMode mode); @@ -97,7 +98,6 @@ public: static void setMaxWarnings(int max); static void setFlushMode(FlushMode mode); - private: QTestLog(); ~QTestLog(); diff --git a/src/testlib/qtestlogger.cpp b/src/testlib/qtestlogger.cpp index f0be6be..cab97d1 100644 --- a/src/testlib/qtestlogger.cpp +++ b/src/testlib/qtestlogger.cpp @@ -62,7 +62,8 @@ QTestLogger::QTestLogger(int fm) warningCounter(0), skipCounter(0), systemCounter(0), qdebugCounter(0), qwarnCounter(0), qfatalCounter(0), - infoCounter(0) + infoCounter(0), randomSeed_(0), + hasRandomSeed_(false) { } @@ -133,6 +134,14 @@ void QTestLogger::stopLogging() property->addAttribute(QTest::AI_PropertyValue, qVersion()); properties->addLogElement(property); + if (hasRandomSeed()) { + property = new QTestElement(QTest::LET_Property); + property->addAttribute(QTest::AI_Name, "RandomSeed"); + QTest::qt_snprintf(buf, sizeof(buf), "%i", randomSeed()); + property->addAttribute(QTest::AI_PropertyValue, buf); + properties->addLogElement(property); + } + currentLogElement->addLogElement(properties); currentLogElement->addLogElement(iterator); @@ -420,5 +429,21 @@ int QTestLogger::infoCount() const return infoCounter; } +void QTestLogger::registerRandomSeed(unsigned int seed) +{ + randomSeed_ = seed; + hasRandomSeed_ = true; +} + +unsigned int QTestLogger::randomSeed() const +{ + return randomSeed_; +} + +bool QTestLogger::hasRandomSeed() const +{ + return hasRandomSeed_; +} + QT_END_NAMESPACE diff --git a/src/testlib/qtestlogger_p.h b/src/testlib/qtestlogger_p.h index bb7a358..8932a85 100644 --- a/src/testlib/qtestlogger_p.h +++ b/src/testlib/qtestlogger_p.h @@ -101,6 +101,9 @@ class QTestLogger : public QAbstractTestLogger int qwarnCount() const; int qfatalCount() const; int infoCount() const; + void registerRandomSeed(unsigned int seed); + unsigned int randomSeed() const; + bool hasRandomSeed() const; private: QTestElement *listOfTestcases; @@ -121,6 +124,8 @@ class QTestLogger : public QAbstractTestLogger int qwarnCounter; int qfatalCounter; int infoCounter; + unsigned int randomSeed_; + bool hasRandomSeed_; }; QT_END_NAMESPACE diff --git a/src/testlib/qtestresult.cpp b/src/testlib/qtestresult.cpp index 8c52a82..bbe3e7f 100644 --- a/src/testlib/qtestresult.cpp +++ b/src/testlib/qtestresult.cpp @@ -191,10 +191,13 @@ bool QTestResult::expectFail(const char *dataIndex, const char *comment, QTEST_ASSERT(comment); QTEST_ASSERT(mode > 0); - if (!isExpectFailData(dataIndex)) + if (!isExpectFailData(dataIndex)) { + delete[] comment; return true; // we don't care + } if (QTest::expectFailMode) { + delete[] comment; clearExpectFail(); addFailure("Already expecting a fail", file, line); return false; diff --git a/src/testlib/qtestxmlstreamer.cpp b/src/testlib/qtestxmlstreamer.cpp index f63c221..a6b8376 100644 --- a/src/testlib/qtestxmlstreamer.cpp +++ b/src/testlib/qtestxmlstreamer.cpp @@ -42,6 +42,7 @@ #include "qtestxmlstreamer.h" #include "qtestelement.h" #include "qtestelementattribute.h" +#include "qtestlogger_p.h" #include "QtTest/private/qtestlog_p.h" #include "QtTest/private/qtestresult_p.h" @@ -204,8 +205,13 @@ void QTestXmlStreamer::output(QTestElement *element) const quotedTc.constData()); outputString(buf.constData()); - QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n", - qVersion(), QTEST_VERSION_STR ); + if (logger()->hasRandomSeed()) { + QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n <RandomSeed>%d</RandomSeed>\n", + qVersion(), QTEST_VERSION_STR, logger()->randomSeed() ); + } else { + QTest::qt_asprintf(&buf, "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n", + qVersion(), QTEST_VERSION_STR ); + } outputString(buf.constData()); QTest::qt_asprintf(&buf, "</Environment>\n"); diff --git a/src/testlib/qxmltestlogger.cpp b/src/testlib/qxmltestlogger.cpp index 07e8ef0..2bf7d77 100644 --- a/src/testlib/qxmltestlogger.cpp +++ b/src/testlib/qxmltestlogger.cpp @@ -93,7 +93,7 @@ namespace QTest { QXmlTestLogger::QXmlTestLogger(XmlMode mode ) - :xmlmode(mode) + :xmlmode(mode), randomSeed(0), hasRandomSeed(false) { } @@ -116,11 +116,20 @@ void QXmlTestLogger::startLogging() outputString(buf.constData()); } - QTest::qt_asprintf(&buf, - "<Environment>\n" - " <QtVersion>%s</QtVersion>\n" - " <QTestVersion>"QTEST_VERSION_STR"</QTestVersion>\n" - "</Environment>\n", qVersion()); + if (hasRandomSeed) { + QTest::qt_asprintf(&buf, + "<Environment>\n" + " <QtVersion>%s</QtVersion>\n" + " <QTestVersion>"QTEST_VERSION_STR"</QTestVersion>\n" + " <RandomSeed>%d</RandomSeed>\n" + "</Environment>\n", qVersion(), randomSeed); + } else { + QTest::qt_asprintf(&buf, + "<Environment>\n" + " <QtVersion>%s</QtVersion>\n" + " <QTestVersion>"QTEST_VERSION_STR"</QTestVersion>\n" + "</Environment>\n", qVersion()); + } outputString(buf.constData()); } @@ -441,4 +450,10 @@ int QXmlTestLogger::xmlCdata(QTestCharBuffer* str, char const* src) return allocateStringFn(str, src, QXmlTestLogger::xmlCdata); } +void QXmlTestLogger::registerRandomSeed(unsigned int seed) +{ + randomSeed = seed; + hasRandomSeed = true; +} + QT_END_NAMESPACE diff --git a/src/testlib/qxmltestlogger_p.h b/src/testlib/qxmltestlogger_p.h index ae918dc..82dd8a6 100644 --- a/src/testlib/qxmltestlogger_p.h +++ b/src/testlib/qxmltestlogger_p.h @@ -79,6 +79,8 @@ public: void addMessage(MessageTypes type, const char *message, const char *file = 0, int line = 0); + void registerRandomSeed(unsigned int seed); + static int xmlCdata(QTestCharBuffer *dest, char const* src); static int xmlQuote(QTestCharBuffer *dest, char const* src); static int xmlCdata(QTestCharBuffer *dest, char const* src, size_t n); @@ -86,6 +88,8 @@ public: private: XmlMode xmlmode; + unsigned int randomSeed; + bool hasRandomSeed; }; QT_END_NAMESPACE diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro index a8186d8..c25d23d 100644 --- a/src/testlib/testlib.pro +++ b/src/testlib/testlib.pro @@ -70,8 +70,16 @@ wince*::LIBS += libcmt.lib \ coredll.lib \ winsock.lib mac:LIBS += -framework IOKit \ - -framework ApplicationServices \ -framework Security +!qpa:mac: LIBS += -framework ApplicationServices +qpa:mac: { + contains(QT_CONFIG, coreservices) { + LIBS_PRIVATE += -framework CoreServices + } else { + LIBS_PRIVATE += -framework CoreFoundation + } +} + include(../qbase.pri) QMAKE_TARGET_PRODUCT = QTestLib QMAKE_TARGET_DESCRIPTION = Qt \ diff --git a/src/tools/bootstrap/bootstrap.pri b/src/tools/bootstrap/bootstrap.pri index 1aa8121..f48c8c1 100644 --- a/src/tools/bootstrap/bootstrap.pri +++ b/src/tools/bootstrap/bootstrap.pri @@ -22,7 +22,9 @@ DEFINES += \ QT_NO_TEXTSTREAM \ QT_NO_THREAD \ QT_NO_UNICODETABLES \ - QT_NO_USING_NAMESPACE + QT_NO_USING_NAMESPACE \ + QT_NO_DEPRECATED + win32:DEFINES += QT_NODLL INCLUDEPATH += $$QT_BUILD_TREE/include \ diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index ba844ea..27b7336 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -25,7 +25,9 @@ DEFINES += \ QT_NO_TEXTSTREAM \ QT_NO_THREAD \ QT_NO_UNICODETABLES \ - QT_NO_USING_NAMESPACE + QT_NO_USING_NAMESPACE \ + QT_NO_DEPRECATED + win32:DEFINES += QT_NODLL INCLUDEPATH += $$QT_BUILD_TREE/include \ diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp index b06eb7a..e6fcd46 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.cpp +++ b/src/tools/uic/cpp/cppwriteinitialization.cpp @@ -139,13 +139,17 @@ namespace { << indent << "QWidgetList childWidgets;\n"; } - static inline bool isIconFormat44(const DomResourceIcon *i) { + static inline bool iconHasStatePixmaps(const DomResourceIcon *i) { return i->hasElementNormalOff() || i->hasElementNormalOn() || i->hasElementDisabledOff() || i->hasElementDisabledOn() || i->hasElementActiveOff() || i->hasElementActiveOn() || i->hasElementSelectedOff() || i->hasElementSelectedOn(); } + static inline bool isIconFormat44(const DomResourceIcon *i) { + return iconHasStatePixmaps(i) || !i->attributeTheme().isEmpty(); + } + // Check on properties. Filter out empty legacy pixmap/icon properties // as Designer pre 4.4 used to remove missing resource references. // This can no longer be handled by the code as we have 'setIcon(QIcon())' as well as 'QIcon icon' @@ -258,6 +262,9 @@ IconHandle::IconHandle(const DomResourceIcon *domIcon) : int IconHandle::compare(const IconHandle &rhs) const { + if (const int comp = m_domIcon->attributeTheme().compare(rhs.m_domIcon->attributeTheme())) + return comp; + const QString normalOff = m_domIcon->hasElementNormalOff() ? m_domIcon->elementNormalOff()->text() : QString(); const QString rhsNormalOff = rhs.m_domIcon->hasElementNormalOff() ? rhs.m_domIcon->elementNormalOff()->text() : QString(); if (const int comp = normalOff.compare(rhsNormalOff)) @@ -478,7 +485,8 @@ WriteInitialization::WriteInitialization(Uic *uic, bool activateScripts) : m_delayedOut(&m_delayedInitialization, QIODevice::WriteOnly), m_refreshOut(&m_refreshInitialization, QIODevice::WriteOnly), m_actionOut(&m_delayedActionInitialization, QIODevice::WriteOnly), - m_activateScripts(activateScripts), m_layoutWidget(false) + m_activateScripts(activateScripts), m_layoutWidget(false), + m_firstThemeIcon(true) { } @@ -1088,6 +1096,8 @@ void WriteInitialization::acceptLayoutItem(DomLayoutItem *node) const int colSpan = node->hasAttributeColSpan() ? node->attributeColSpan() : 1; addArgs = QString::fromLatin1("%1, %2, %3, %4, %5").arg(itemName).arg(row).arg(col).arg(rowSpan).arg(colSpan); + if (!node->attributeAlignment().isEmpty()) + addArgs += QLatin1String(", ") + node->attributeAlignment(); } else { if (layout->attributeClass() == QLatin1String("QFormLayout")) { methodPrefix = QLatin1String("set"); @@ -1097,6 +1107,8 @@ void WriteInitialization::acceptLayoutItem(DomLayoutItem *node) addArgs = QString::fromLatin1("%1, %2, %3").arg(row).arg(role).arg(itemName); } else { addArgs = itemName; + if (layout->attributeClass().contains(QLatin1String("Box")) && !node->attributeAlignment().isEmpty()) + addArgs += QLatin1String(", 0, ") + node->attributeAlignment(); } } @@ -1670,6 +1682,30 @@ QString WriteInitialization::writeFontProperties(const DomFont *f) return fontName; } +// Post 4.4 write resource icon +static void writeResourceIcon(QTextStream &output, + const QString &iconName, + const QString &indent, + const DomResourceIcon *i) +{ + if (i->hasElementNormalOff()) + output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOff()->text(), indent) << "), QSize(), QIcon::Normal, QIcon::Off);\n"; + if (i->hasElementNormalOn()) + output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOn()->text(), indent) << "), QSize(), QIcon::Normal, QIcon::On);\n"; + if (i->hasElementDisabledOff()) + output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementDisabledOff()->text(), indent) << "), QSize(), QIcon::Disabled, QIcon::Off);\n"; + if (i->hasElementDisabledOn()) + output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementDisabledOn()->text(), indent) << "), QSize(), QIcon::Disabled, QIcon::On);\n"; + if (i->hasElementActiveOff()) + output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementActiveOff()->text(), indent) << "), QSize(), QIcon::Active, QIcon::Off);\n"; + if (i->hasElementActiveOn()) + output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementActiveOn()->text(), indent) << "), QSize(), QIcon::Active, QIcon::On);\n"; + if (i->hasElementSelectedOff()) + output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementSelectedOff()->text(), indent) << "), QSize(), QIcon::Selected, QIcon::Off);\n"; + if (i->hasElementSelectedOn()) + output << indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementSelectedOn()->text(), indent) << "), QSize(), QIcon::Selected, QIcon::On);\n"; +} + QString WriteInitialization::writeIconProperties(const DomResourceIcon *i) { // check cache @@ -1683,25 +1719,41 @@ QString WriteInitialization::writeIconProperties(const DomResourceIcon *i) const QString iconName = m_driver->unique(QLatin1String("icon")); m_iconPropertiesNameMap.insert(IconHandle(i), iconName); if (isIconFormat44(i)) { - const QString pixmap = QLatin1String("QPixmap"); - m_output << m_indent << "QIcon " << iconName << ";\n"; - if (i->hasElementNormalOff()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOff()->text(), m_dindent) << "), QSize(), QIcon::Normal, QIcon::Off);\n"; - if (i->hasElementNormalOn()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOn()->text(), m_dindent) << "), QSize(), QIcon::Normal, QIcon::On);\n"; - if (i->hasElementDisabledOff()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementDisabledOff()->text(), m_dindent) << "), QSize(), QIcon::Disabled, QIcon::Off);\n"; - if (i->hasElementDisabledOn()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementDisabledOn()->text(), m_dindent) << "), QSize(), QIcon::Disabled, QIcon::On);\n"; - if (i->hasElementActiveOff()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementActiveOff()->text(), m_dindent) << "), QSize(), QIcon::Active, QIcon::Off);\n"; - if (i->hasElementActiveOn()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementActiveOn()->text(), m_dindent) << "), QSize(), QIcon::Active, QIcon::On);\n"; - if (i->hasElementSelectedOff()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementSelectedOff()->text(), m_dindent) << "), QSize(), QIcon::Selected, QIcon::Off);\n"; - if (i->hasElementSelectedOn()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementSelectedOn()->text(), m_dindent) << "), QSize(), QIcon::Selected, QIcon::On);\n"; - } else { // pre-4.4 legacy + if (i->attributeTheme().isEmpty()) { + // No theme: Write resource icon as is + m_output << m_indent << "QIcon " << iconName << ";\n"; + writeResourceIcon(m_output, iconName, m_indent, i); + } else { + // Theme: Generate code to check the theme and default to resource + const QString themeIconName = fixString(i->attributeTheme(), QString()); + if (iconHasStatePixmaps(i)) { + // Theme + default state pixmaps: + // Generate code to check the theme and default to state pixmaps + m_output << m_indent << "QIcon " << iconName << ";\n"; + const char themeNameStringVariableC[] = "iconThemeName"; + // Store theme name in a variable + m_output << m_indent; + if (m_firstThemeIcon) { // Declare variable string + m_output << "QString "; + m_firstThemeIcon = false; + } + m_output << themeNameStringVariableC << " = QString::fromUtf8(" + << themeIconName << ");\n"; + m_output << m_indent << "if (QIcon::hasThemeIcon(" + << themeNameStringVariableC + << ")) {\n" + << m_dindent << iconName << " = QIcon::fromTheme(" << themeNameStringVariableC << ");\n" + << m_indent << "} else {\n"; + writeResourceIcon(m_output, iconName, m_dindent, i); + m_output << m_indent << "}\n"; + } else { + // Theme, but no state pixmaps: Construct from theme directly. + m_output << m_indent << "QIcon " << iconName + << "(QIcon::fromTheme(QString::fromUtf8(" + << themeIconName << ")));\n"; + } // Theme, but not state + } // >= 4.4 + } else { // pre-4.4 legacy m_output << m_indent << "const QIcon " << iconName << " = " << pixCall(QLatin1String("QIcon"), i->text())<< ";\n"; } return iconName; diff --git a/src/tools/uic/cpp/cppwriteinitialization.h b/src/tools/uic/cpp/cppwriteinitialization.h index 7507166..b9cf2cd 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.h +++ b/src/tools/uic/cpp/cppwriteinitialization.h @@ -363,6 +363,7 @@ private: const bool m_activateScripts; bool m_layoutWidget; + bool m_firstThemeIcon; }; } // namespace CPP diff --git a/src/tools/uic/ui4.cpp b/src/tools/uic/ui4.cpp index e80523f..e094eaf 100644 --- a/src/tools/uic/ui4.cpp +++ b/src/tools/uic/ui4.cpp @@ -3673,6 +3673,7 @@ void DomLayoutItem::clear(bool clear_all) m_attr_rowSpan = 0; m_has_attr_colSpan = false; m_attr_colSpan = 0; + m_has_attr_alignment = false; } m_kind = Unknown; @@ -3694,6 +3695,7 @@ DomLayoutItem::DomLayoutItem() m_attr_rowSpan = 0; m_has_attr_colSpan = false; m_attr_colSpan = 0; + m_has_attr_alignment = false; m_widget = 0; m_layout = 0; m_spacer = 0; @@ -3727,6 +3729,10 @@ void DomLayoutItem::read(QXmlStreamReader &reader) setAttributeColSpan(attribute.value().toString().toInt()); continue; } + if (name == QLatin1String("alignment")) { + setAttributeAlignment(attribute.value().toString()); + continue; + } reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString()); } @@ -3779,6 +3785,8 @@ void DomLayoutItem::read(const QDomElement &node) setAttributeRowSpan(node.attribute(QLatin1String("rowspan")).toInt()); if (node.hasAttribute(QLatin1String("colspan"))) setAttributeColSpan(node.attribute(QLatin1String("colspan")).toInt()); + if (node.hasAttribute(QLatin1String("alignment"))) + setAttributeAlignment(node.attribute(QLatin1String("alignment"))); for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) { if (!n.isElement()) @@ -3828,6 +3836,9 @@ void DomLayoutItem::write(QXmlStreamWriter &writer, const QString &tagName) cons if (hasAttributeColSpan()) writer.writeAttribute(QLatin1String("colspan"), QString::number(attributeColSpan())); + if (hasAttributeAlignment()) + writer.writeAttribute(QLatin1String("alignment"), attributeAlignment()); + switch (kind()) { case Widget: { DomWidget* v = elementWidget(); @@ -7745,6 +7756,7 @@ void DomResourceIcon::clear(bool clear_all) if (clear_all) { m_text = QLatin1String(""); + m_has_attr_theme = false; m_has_attr_resource = false; } @@ -7762,6 +7774,7 @@ void DomResourceIcon::clear(bool clear_all) DomResourceIcon::DomResourceIcon() { m_children = 0; + m_has_attr_theme = false; m_has_attr_resource = false; m_text = QLatin1String(""); m_normalOff = 0; @@ -7791,6 +7804,10 @@ void DomResourceIcon::read(QXmlStreamReader &reader) foreach (const QXmlStreamAttribute &attribute, reader.attributes()) { QStringRef name = attribute.name(); + if (name == QLatin1String("theme")) { + setAttributeTheme(attribute.value().toString()); + continue; + } if (name == QLatin1String("resource")) { setAttributeResource(attribute.value().toString()); continue; @@ -7869,6 +7886,8 @@ void DomResourceIcon::read(QXmlStreamReader &reader) #ifdef QUILOADER_QDOM_READ void DomResourceIcon::read(const QDomElement &node) { + if (node.hasAttribute(QLatin1String("theme"))) + setAttributeTheme(node.attribute(QLatin1String("theme"))); if (node.hasAttribute(QLatin1String("resource"))) setAttributeResource(node.attribute(QLatin1String("resource"))); @@ -7938,6 +7957,9 @@ void DomResourceIcon::write(QXmlStreamWriter &writer, const QString &tagName) co { writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("resourceicon") : tagName.toLower()); + if (hasAttributeTheme()) + writer.writeAttribute(QLatin1String("theme"), attributeTheme()); + if (hasAttributeResource()) writer.writeAttribute(QLatin1String("resource"), attributeResource()); diff --git a/src/tools/uic/ui4.h b/src/tools/uic/ui4.h index 1f38f88..836175e 100644 --- a/src/tools/uic/ui4.h +++ b/src/tools/uic/ui4.h @@ -1427,6 +1427,11 @@ public: inline void setAttributeColSpan(int a) { m_attr_colSpan = a; m_has_attr_colSpan = true; } inline void clearAttributeColSpan() { m_has_attr_colSpan = false; } + inline bool hasAttributeAlignment() const { return m_has_attr_alignment; } + inline QString attributeAlignment() const { return m_attr_alignment; } + inline void setAttributeAlignment(const QString& a) { m_attr_alignment = a; m_has_attr_alignment = true; } + inline void clearAttributeAlignment() { m_has_attr_alignment = false; } + // child element accessors enum Kind { Unknown = 0, Widget, Layout, Spacer }; inline Kind kind() const { return m_kind; } @@ -1460,6 +1465,9 @@ private: int m_attr_colSpan; bool m_has_attr_colSpan; + QString m_attr_alignment; + bool m_has_attr_alignment; + // child element data Kind m_kind; DomWidget* m_widget; @@ -2809,6 +2817,11 @@ public: inline void setText(const QString &s) { m_text = s; } // attribute accessors + inline bool hasAttributeTheme() const { return m_has_attr_theme; } + inline QString attributeTheme() const { return m_attr_theme; } + inline void setAttributeTheme(const QString& a) { m_attr_theme = a; m_has_attr_theme = true; } + inline void clearAttributeTheme() { m_has_attr_theme = false; } + inline bool hasAttributeResource() const { return m_has_attr_resource; } inline QString attributeResource() const { return m_attr_resource; } inline void setAttributeResource(const QString& a) { m_attr_resource = a; m_has_attr_resource = true; } @@ -2868,6 +2881,9 @@ private: void clear(bool clear_all = true); // attribute data + QString m_attr_theme; + bool m_has_attr_theme; + QString m_attr_resource; bool m_has_attr_resource; diff --git a/src/tools/uic3/converter.cpp b/src/tools/uic3/converter.cpp index 2ee939d..8fac4d1 100644 --- a/src/tools/uic3/converter.cpp +++ b/src/tools/uic3/converter.cpp @@ -864,7 +864,7 @@ DomLayoutItem *Ui3Reader::createLayoutItem(const QDomElement &e) Variant var; var.createSize(0, 0); - QVariant def = qVariantFromValue(var); + QVariant def = QVariant::fromValue(var); Size size = asVariant(DomTool::readProperty(e, QLatin1String("sizeHint"), def)).size; QString sizeType = QLatin1String("QSizePolicy::") + DomTool::readProperty(e, QLatin1String("sizeType"), QLatin1String("Expanding")).toString(); diff --git a/src/tools/uic3/domtool.cpp b/src/tools/uic3/domtool.cpp index 526b41c..cefbbb4 100644 --- a/src/tools/uic3/domtool.cpp +++ b/src/tools/uic3/domtool.cpp @@ -169,7 +169,7 @@ QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValu n3 = n3.nextSibling().toElement(); } var.createRect(x, y, w, h); - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("point")) { QDomElement n3 = e.firstChild().toElement(); int x = 0, y = 0; @@ -181,7 +181,7 @@ QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValu n3 = n3.nextSibling().toElement(); } var.createPoint(x,y); - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("size")) { QDomElement n3 = e.firstChild().toElement(); int w = 0, h = 0; @@ -193,10 +193,10 @@ QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValu n3 = n3.nextSibling().toElement(); } var.createSize(w, h); - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("color")) { var.color = readColor(e); - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("font")) { QDomElement n3 = e.firstChild().toElement(); Font f; @@ -217,7 +217,7 @@ QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValu n3 = n3.nextSibling().toElement(); } var.font = f; - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("string")) { v = QVariant(e.firstChild().toText().data()); QDomElement n = e; @@ -258,10 +258,10 @@ QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValu var.sizePolicy.verstretch = n3.firstChild().toText().data().toInt(); n3 = n3.nextSibling().toElement(); } - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("cursor")) { var.createCursor(e.firstChild().toText().data().toInt()); - qVariantSetValue(v, var); + v.setValue(var); } else if (e.tagName() == QLatin1String("stringlist")) { QStringList lst; QDomElement n; diff --git a/src/tools/uic3/domtool.h b/src/tools/uic3/domtool.h index ad597a1..8fe0793 100644 --- a/src/tools/uic3/domtool.h +++ b/src/tools/uic3/domtool.h @@ -266,7 +266,7 @@ QT_BEGIN_NAMESPACE inline Variant asVariant(const QVariant &v) { Variant var; - var = qVariantValue<Variant>(v); + var = qvariant_cast<Variant>(v); return var; } diff --git a/src/xmlpatterns/api/quriloader.cpp b/src/xmlpatterns/api/quriloader.cpp index e0a7542..c653661 100644 --- a/src/xmlpatterns/api/quriloader.cpp +++ b/src/xmlpatterns/api/quriloader.cpp @@ -69,7 +69,7 @@ QNetworkReply *URILoader::createRequest(Operation op, const QNetworkRequest &req const QVariant variant(m_variableLoader->valueFor(m_namePool->allocateQName(QString(), name, QString()))); if(!variant.isNull() && variant.userType() == qMetaTypeId<QIODevice *>()) - return new QIODeviceDelegate(qVariantValue<QIODevice *>(variant)); + return new QIODeviceDelegate(qvariant_cast<QIODevice *>(variant)); else { /* If we're entering this code path, the variable URI identified a variable diff --git a/src/xmlpatterns/api/qvariableloader.cpp b/src/xmlpatterns/api/qvariableloader.cpp index 612fa67..648fda4 100644 --- a/src/xmlpatterns/api/qvariableloader.cpp +++ b/src/xmlpatterns/api/qvariableloader.cpp @@ -131,12 +131,12 @@ SequenceType::Ptr VariableLoader::announceExternalVariable(const QXmlName name, return CommonSequenceTypes::ExactlyOneAnyURI; else if(variant.userType() == qMetaTypeId<QXmlQuery>()) { - const QXmlQuery variableQuery(qVariantValue<QXmlQuery>(variant)); + const QXmlQuery variableQuery(qvariant_cast<QXmlQuery>(variant)); return variableQuery.d->expression()->staticType(); } else { - return makeGenericSequenceType(AtomicValue::qtToXDMType(qVariantValue<QXmlItem>(variant)), + return makeGenericSequenceType(AtomicValue::qtToXDMType(qvariant_cast<QXmlItem>(variant)), Cardinality::exactlyOne()); } } @@ -154,12 +154,12 @@ Item::Iterator::Ptr VariableLoader::evaluateSequence(const QXmlName name, return makeSingletonIterator(itemForName(name)); else if(variant.userType() == qMetaTypeId<QXmlQuery>()) { - const QXmlQuery variableQuery(qVariantValue<QXmlQuery>(variant)); + const QXmlQuery variableQuery(qvariant_cast<QXmlQuery>(variant)); return variableQuery.d->expression()->evaluateSequence(DynamicContext::Ptr(new TemporaryTreesRedirectingContext(variableQuery.d->dynamicContext(), context))); } - const QVariant v(qVariantValue<QXmlItem>(variant).toAtomicValue()); + const QVariant v(qvariant_cast<QXmlItem>(variant).toAtomicValue()); switch(v.type()) { @@ -179,7 +179,7 @@ Item VariableLoader::itemForName(const QXmlName &name) const if(variant.userType() == qMetaTypeId<QIODevice *>()) return Item(AnyURI::fromValue(QLatin1String("tag:trolltech.com,2007:QtXmlPatterns:QIODeviceVariable:") + m_namePool->stringForLocalName(name.localName()))); - const QXmlItem item(qVariantValue<QXmlItem>(variant)); + const QXmlItem item(qvariant_cast<QXmlItem>(variant)); if(item.isNode()) return Item::fromPublic(item); @@ -210,8 +210,8 @@ bool VariableLoader::isSameType(const QVariant &v1, return true; /* Ok, we have two QXmlItems. */ - const QXmlItem i1(qVariantValue<QXmlItem>(v1)); - const QXmlItem i2(qVariantValue<QXmlItem>(v2)); + const QXmlItem i1(qvariant_cast<QXmlItem>(v1)); + const QXmlItem i2(qvariant_cast<QXmlItem>(v2)); if(i1.isNode()) { diff --git a/src/xmlpatterns/api/qxmlquery.cpp b/src/xmlpatterns/api/qxmlquery.cpp index 55af49b..4d6a3b6 100644 --- a/src/xmlpatterns/api/qxmlquery.cpp +++ b/src/xmlpatterns/api/qxmlquery.cpp @@ -534,7 +534,7 @@ void QXmlQuery::bindVariable(const QXmlName &name, const QXmlItem &value) } const QPatternist::VariableLoader::Ptr vl(d->variableLoader()); - const QVariant variant(qVariantFromValue(value)); + const QVariant variant(QVariant::fromValue(value)); /* If the type of the variable changed(as opposed to only the value), * we will have to recompile. */ @@ -610,7 +610,7 @@ void QXmlQuery::bindVariable(const QXmlName &name, QIODevice *device) if(device) { - const QVariant variant(qVariantFromValue(device)); + const QVariant variant(QVariant::fromValue(device)); if(vl->invalidationRequired(name, variant)) d->recompileRequired(); @@ -1184,7 +1184,7 @@ void QXmlQuery::bindVariable(const QXmlName &name, const QXmlQuery &query) Q_ASSERT_X(query.isValid(), Q_FUNC_INFO, "The query being bound must be valid."); const QPatternist::VariableLoader::Ptr vl(d->variableLoader()); - const QVariant variant(qVariantFromValue(query)); + const QVariant variant(QVariant::fromValue(query)); if(vl->invalidationRequired(name, variant)) d->recompileRequired(); diff --git a/src/xmlpatterns/data/qatomicvalue.cpp b/src/xmlpatterns/data/qatomicvalue.cpp index c4f3578..5bb9a4f 100644 --- a/src/xmlpatterns/data/qatomicvalue.cpp +++ b/src/xmlpatterns/data/qatomicvalue.cpp @@ -121,7 +121,7 @@ QVariant AtomicValue::toQt(const AtomicValue *const value) || BuiltinTypes::xsHexBinary->xdtTypeMatches(t)) return QVariant(value->as<Base64Binary>()->asByteArray()); else if(BuiltinTypes::xsQName->xdtTypeMatches(t)) - return qVariantFromValue(value->as<QNameValue>()->qName()); + return QVariant::fromValue(value->as<QNameValue>()->qName()); else { /* A type we don't support in Qt. Includes xs:time currently. */ diff --git a/src/xmlpatterns/utils/qautoptr_p.h b/src/xmlpatterns/utils/qautoptr_p.h index 060e7be..173999f 100644 --- a/src/xmlpatterns/utils/qautoptr_p.h +++ b/src/xmlpatterns/utils/qautoptr_p.h @@ -122,7 +122,6 @@ namespace QPatternist return *this; } -#ifndef QT_NO_MEMBER_TEMPLATES template<typename L> operator AutoPtrRef<L>() { @@ -139,7 +138,6 @@ namespace QPatternist inline AutoPtr(AutoPtr<L>& other) : m_ptr(other.release()) { } -#endif inline T *release() { |