diff options
52 files changed, 1225 insertions, 454 deletions
diff --git a/demos/embedded/anomaly/src/flickcharm.cpp b/demos/embedded/anomaly/src/flickcharm.cpp index 0b9e68e..b7e2151 100644 --- a/demos/embedded/anomaly/src/flickcharm.cpp +++ b/demos/embedded/anomaly/src/flickcharm.cpp @@ -49,20 +49,112 @@ #include <QList> #include <QMouseEvent> #include <QScrollBar> +#include <QTime> #include <QWebFrame> #include <QWebView> #include <QDebug> +const int fingerAccuracyThreshold = 3; + struct FlickData { - typedef enum { Steady, Pressed, ManualScroll, AutoScroll, Stop } State; + typedef enum { + Steady, // Interaction without scrolling + ManualScroll, // Scrolling manually with the finger on the screen + AutoScroll, // Scrolling automatically + AutoScrollAcceleration // Scrolling automatically but a finger is on the screen + } State; State state; QWidget *widget; QPoint pressPos; - QPoint offset; - QPoint dragPos; + QPoint lastPos; QPoint speed; + QTime speedTimer; QList<QEvent*> ignored; + QTime accelerationTimer; + bool lastPosValid:1; + bool waitingAcceleration:1; + + FlickData() + : lastPosValid(false) + , waitingAcceleration(false) + {} + + void resetSpeed() + { + speed = QPoint(); + lastPosValid = false; + } + void updateSpeed(const QPoint &newPosition) + { + if (lastPosValid) { + const int timeElapsed = speedTimer.elapsed(); + if (timeElapsed) { + const QPoint newPixelDiff = (newPosition - lastPos); + const QPoint pixelsPerSecond = newPixelDiff * (1000 / timeElapsed); + // fingers are inacurates, we ignore small changes to avoid stopping the autoscroll because + // of a small horizontal offset when scrolling vertically + const int newSpeedY = (qAbs(pixelsPerSecond.y()) > fingerAccuracyThreshold) ? pixelsPerSecond.y() : 0; + const int newSpeedX = (qAbs(pixelsPerSecond.x()) > fingerAccuracyThreshold) ? pixelsPerSecond.x() : 0; + if (state == AutoScrollAcceleration) { + const int max = 4000; // px by seconds + const int oldSpeedY = speed.y(); + const int oldSpeedX = speed.x(); + if ((oldSpeedY <= 0 && newSpeedY <= 0) || (oldSpeedY >= 0 && newSpeedY >= 0) + && (oldSpeedX <= 0 && newSpeedX <= 0) || (oldSpeedX >= 0 && newSpeedX >= 0)) { + speed.setY(qBound(-max, (oldSpeedY + (newSpeedY / 4)), max)); + speed.setX(qBound(-max, (oldSpeedX + (newSpeedX / 4)), max)); + } else { + speed = QPoint(); + } + } else { + const int max = 2500; // px by seconds + // we average the speed to avoid strange effects with the last delta + if (!speed.isNull()) { + speed.setX(qBound(-max, (speed.x() / 4) + (newSpeedX * 3 / 4), max)); + speed.setY(qBound(-max, (speed.y() / 4) + (newSpeedY * 3 / 4), max)); + } else { + speed = QPoint(newSpeedX, newSpeedY); + } + } + } + } else { + lastPosValid = true; + } + speedTimer.start(); + lastPos = newPosition; + } + + // scroll by dx, dy + // return true if the widget was scrolled + bool scrollWidget(const int dx, const int dy) + { + QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea*>(widget); + if (scrollArea) { + const int x = scrollArea->horizontalScrollBar()->value(); + const int y = scrollArea->verticalScrollBar()->value(); + scrollArea->horizontalScrollBar()->setValue(x - dx); + scrollArea->verticalScrollBar()->setValue(y - dy); + return (scrollArea->horizontalScrollBar()->value() != x + || scrollArea->verticalScrollBar()->value() != y); + } + + QWebView *webView = qobject_cast<QWebView*>(widget); + if (webView) { + QWebFrame *frame = webView->page()->mainFrame(); + const QPoint position = frame->scrollPosition(); + frame->setScrollPosition(position - QPoint(dx, dy)); + return frame->scrollPosition() != position; + } + return false; + } + + bool scrollTo(const QPoint &newPosition) + { + const QPoint delta = newPosition - lastPos; + updateSpeed(newPosition); + return scrollWidget(delta.x(), delta.y()); + } }; class FlickCharmPrivate @@ -70,6 +162,13 @@ class FlickCharmPrivate public: QHash<QWidget*, FlickData*> flickData; QBasicTimer ticker; + QTime timeCounter; + void startTicker(QObject *object) + { + if (!ticker.isActive()) + ticker.start(15, object); + timeCounter.start(); + } }; FlickCharm::FlickCharm(QObject *parent): QObject(parent) @@ -148,46 +247,14 @@ void FlickCharm::deactivateFrom(QWidget *widget) } } -static QPoint scrollOffset(QWidget *widget) +static QPoint deaccelerate(const QPoint &speed, const int deltatime) { - int x = 0, y = 0; - - QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea*>(widget); - if (scrollArea) { - x = scrollArea->horizontalScrollBar()->value(); - y = scrollArea->verticalScrollBar()->value(); - } - - QWebView *webView = qobject_cast<QWebView*>(widget); - if (webView) { - QWebFrame *frame = webView->page()->mainFrame(); - x = frame->evaluateJavaScript("window.scrollX").toInt(); - y = frame->evaluateJavaScript("window.scrollY").toInt(); - } - - return QPoint(x, y); -} - -static void setScrollOffset(QWidget *widget, const QPoint &p) -{ - QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea*>(widget); - if (scrollArea) { - scrollArea->horizontalScrollBar()->setValue(p.x()); - scrollArea->verticalScrollBar()->setValue(p.y()); - } + const int deltaSpeed = deltatime; - QWebView *webView = qobject_cast<QWebView*>(widget); - QWebFrame *frame = webView ? webView->page()->mainFrame() : 0; - if (frame) - frame->evaluateJavaScript(QString("window.scrollTo(%1,%2);").arg(p.x()).arg(p.y())); -} - -static QPoint deaccelerate(const QPoint &speed, int a = 1, int max = 64) -{ - int x = qBound(-max, speed.x(), max); - int y = qBound(-max, speed.y(), max); - x = (x == 0) ? x : (x > 0) ? qMax(0, x - a) : qMin(0, x + a); - y = (y == 0) ? y : (y > 0) ? qMax(0, y - a) : qMin(0, y + a); + int x = speed.x(); + int y = speed.y(); + x = (x == 0) ? x : (x > 0) ? qMax(0, x - deltaSpeed) : qMin(0, x + deltaSpeed); + y = (y == 0) ? y : (y > 0) ? qMax(0, y - deltaSpeed) : qMin(0, y + deltaSpeed); return QPoint(x, y); } @@ -196,22 +263,24 @@ bool FlickCharm::eventFilter(QObject *object, QEvent *event) if (!object->isWidgetType()) return false; - QEvent::Type type = event->type(); - if (type != QEvent::MouseButtonPress && - type != QEvent::MouseButtonRelease && - type != QEvent::MouseMove) - return false; + const QEvent::Type type = event->type(); - QMouseEvent *mouseEvent = 0; - switch (event->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseMove: - mouseEvent = static_cast<QMouseEvent*>(event); - break; + switch (type) { + case QEvent::MouseButtonPress: + case QEvent::MouseMove: + case QEvent::MouseButtonRelease: + break; + case QEvent::MouseButtonDblClick: // skip double click + return true; + default: + return false; } - if (!mouseEvent || mouseEvent->modifiers() != Qt::NoModifier) + QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event); + if (type == QEvent::MouseMove && mouseEvent->buttons() != Qt::LeftButton) + return false; + + if (mouseEvent->modifiers() != Qt::NoModifier) return false; QWidget *viewport = qobject_cast<QWidget*>(object); @@ -219,89 +288,83 @@ bool FlickCharm::eventFilter(QObject *object, QEvent *event) if (!viewport || !data || data->ignored.removeAll(event)) return false; + const QPoint mousePos = mouseEvent->pos(); bool consumed = false; switch (data->state) { case FlickData::Steady: - if (mouseEvent->type() == QEvent::MouseButtonPress) - if (mouseEvent->buttons() == Qt::LeftButton) { - consumed = true; - data->state = FlickData::Pressed; - data->pressPos = mouseEvent->pos(); - data->offset = scrollOffset(data->widget); - } - break; - - case FlickData::Pressed: - if (mouseEvent->type() == QEvent::MouseButtonRelease) { + if (type == QEvent::MouseButtonPress) { + consumed = true; + data->pressPos = mousePos; + } else if (type == QEvent::MouseButtonRelease) { consumed = true; - data->state = FlickData::Steady; - QMouseEvent *event1 = new QMouseEvent(QEvent::MouseButtonPress, data->pressPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); - QMouseEvent *event2 = new QMouseEvent(*mouseEvent); + QMouseEvent *event2 = new QMouseEvent(QEvent::MouseButtonRelease, + data->pressPos, Qt::LeftButton, + Qt::LeftButton, Qt::NoModifier); data->ignored << event1; data->ignored << event2; QApplication::postEvent(object, event1); QApplication::postEvent(object, event2); - } - if (mouseEvent->type() == QEvent::MouseMove) { + } else if (type == QEvent::MouseMove) { consumed = true; - data->state = FlickData::ManualScroll; - data->dragPos = QCursor::pos(); - if (!d->ticker.isActive()) - d->ticker.start(20, this); + data->scrollTo(mousePos); + + const QPoint delta = mousePos - data->pressPos; + if (delta.x() > fingerAccuracyThreshold || delta.y() > fingerAccuracyThreshold) + data->state = FlickData::ManualScroll; } break; case FlickData::ManualScroll: - if (mouseEvent->type() == QEvent::MouseMove) { + if (type == QEvent::MouseMove) { consumed = true; - QPoint delta = mouseEvent->pos() - data->pressPos; - setScrollOffset(data->widget, data->offset - delta); - } - if (mouseEvent->type() == QEvent::MouseButtonRelease) { + data->scrollTo(mousePos); + } else if (type == QEvent::MouseButtonRelease) { consumed = true; data->state = FlickData::AutoScroll; + data->lastPosValid = false; + d->startTicker(this); } break; case FlickData::AutoScroll: - if (mouseEvent->type() == QEvent::MouseButtonPress) { + if (type == QEvent::MouseButtonPress) { consumed = true; - data->state = FlickData::Stop; - data->speed = QPoint(0, 0); - data->pressPos = mouseEvent->pos(); - data->offset = scrollOffset(data->widget); - } - if (mouseEvent->type() == QEvent::MouseButtonRelease) { + data->state = FlickData::AutoScrollAcceleration; + data->waitingAcceleration = true; + data->accelerationTimer.start(); + data->updateSpeed(mousePos); + data->pressPos = mousePos; + } else if (type == QEvent::MouseButtonRelease) { consumed = true; data->state = FlickData::Steady; - data->speed = QPoint(0, 0); + data->resetSpeed(); } break; - case FlickData::Stop: - if (mouseEvent->type() == QEvent::MouseButtonRelease) { + case FlickData::AutoScrollAcceleration: + if (type == QEvent::MouseMove) { consumed = true; - data->state = FlickData::Steady; - } - if (mouseEvent->type() == QEvent::MouseMove) { + data->updateSpeed(mousePos); + data->accelerationTimer.start(); + if (data->speed.isNull()) + data->state = FlickData::ManualScroll; + } else if (type == QEvent::MouseButtonRelease) { consumed = true; - data->state = FlickData::ManualScroll; - data->dragPos = QCursor::pos(); - if (!d->ticker.isActive()) - d->ticker.start(20, this); + data->state = FlickData::AutoScroll; + data->waitingAcceleration = false; + data->lastPosValid = false; } break; - default: break; } - - return consumed; + data->lastPos = mousePos; + return true; } void FlickCharm::timerEvent(QTimerEvent *event) @@ -311,25 +374,29 @@ void FlickCharm::timerEvent(QTimerEvent *event) while (item.hasNext()) { item.next(); FlickData *data = item.value(); - - if (data->state == FlickData::ManualScroll) { - count++; - data->speed = QCursor::pos() - data->dragPos; - data->dragPos = QCursor::pos(); + if (data->state == FlickData::AutoScrollAcceleration + && data->waitingAcceleration + && data->accelerationTimer.elapsed() > 40) { + data->state = FlickData::ManualScroll; + data->resetSpeed(); } + if (data->state == FlickData::AutoScroll || data->state == FlickData::AutoScrollAcceleration) { + const int timeElapsed = d->timeCounter.elapsed(); + const QPoint delta = (data->speed) * timeElapsed / 1000; + bool hasScrolled = data->scrollWidget(delta.x(), delta.y()); - if (data->state == FlickData::AutoScroll) { - count++; - data->speed = deaccelerate(data->speed); - QPoint p = scrollOffset(data->widget); - setScrollOffset(data->widget, p - data->speed); - if (data->speed == QPoint(0, 0)) + if (data->speed.isNull() || !hasScrolled) data->state = FlickData::Steady; + else + count++; + data->speed = deaccelerate(data->speed, timeElapsed); } } if (!count) d->ticker.stop(); + else + d->timeCounter.start(); QObject::timerEvent(event); } diff --git a/demos/embedded/fluidlauncher/fluidlauncher.pro b/demos/embedded/fluidlauncher/fluidlauncher.pro index b47f6a0..bb8835b 100644 --- a/demos/embedded/fluidlauncher/fluidlauncher.pro +++ b/demos/embedded/fluidlauncher/fluidlauncher.pro @@ -163,6 +163,11 @@ symbian { resource.sources += $${EPOCROOT}$$HW_ZDIR$$APP_RESOURCE_DIR/anomaly.rsc mifs.sources += \ $${EPOCROOT}$$HW_ZDIR$$APP_RESOURCE_DIR/anomaly.mif + + # Since Fluidlauncher itself doesn't link webkit, we won't get dependency automatically + executables.pkg_prerules += \ + "; Dependency to Qt Webkit" \ + "(0x200267C2), $${QT_MAJOR_VERSION}, $${QT_MINOR_VERSION}, $${QT_PATCH_VERSION}, {\"QtWebKit\"}" } contains(QT_CONFIG, phonon) { diff --git a/mkspecs/features/symbian/qt.prf b/mkspecs/features/symbian/qt.prf index 0f5b08b..99f5ece 100644 --- a/mkspecs/features/symbian/qt.prf +++ b/mkspecs/features/symbian/qt.prf @@ -28,6 +28,13 @@ contains(CONFIG, qt):!contains(TARGET.UID3, 0x2001E61C):!contains(TARGET.UID3, 0 default_deployment.pkg_prerules += \ "; Default dependency to Qt libraries" \ "(0x2001E61C), $${QT_MAJOR_VERSION}, $${QT_MINOR_VERSION}, $${QT_PATCH_VERSION}, {\"Qt\"}" + + # Projects linking to webkit need dependency to webkit + contains(QT, webkit): { + default_deployment.pkg_prerules += \ + "; Dependency to Qt Webkit" \ + "(0x200267C2), $${QT_MAJOR_VERSION}, $${QT_MINOR_VERSION}, $${QT_PATCH_VERSION}, {\"QtWebKit\"}" + } } isEmpty(TARGET.EPOCSTACKSIZE):TARGET.EPOCSTACKSIZE = 0x14000 diff --git a/mkspecs/linux-g++-maemo/qmake.conf b/mkspecs/linux-g++-maemo/qmake.conf index c39ba2c..b0f3ca3 100644 --- a/mkspecs/linux-g++-maemo/qmake.conf +++ b/mkspecs/linux-g++-maemo/qmake.conf @@ -5,6 +5,7 @@ MAKEFILE_GENERATOR = UNIX TEMPLATE = app CONFIG += qt warn_on release incremental link_prl +CONFIG += nostrip QT += core gui QMAKE_INCREMENTAL_STYLE = sublib diff --git a/src/3rdparty/webkit/JavaScriptCore/ChangeLog b/src/3rdparty/webkit/JavaScriptCore/ChangeLog index d7d2d57..50cff63 100644 --- a/src/3rdparty/webkit/JavaScriptCore/ChangeLog +++ b/src/3rdparty/webkit/JavaScriptCore/ChangeLog @@ -1,3 +1,15 @@ +2009-12-18 Yongjun Zhang <yongjun.zhang@nokia.com> + + Reviewed by Simon Hausmann. + + https://bugs.webkit.org/show_bug.cgi?id=32713 + [Qt] make wtf/Assertions.h compile in winscw compiler. + + Add string arg before ellipsis to help winscw compiler resolve variadic + macro definitions in wtf/Assertions.h. + + * wtf/Assertions.h: + 2009-11-30 Jan-Arve Sæther <jan-arve.saether@nokia.com> Reviewed by Simon Hausmann. diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.h b/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.h index f529a62..aa72e5a 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/Assertions.h @@ -158,8 +158,8 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann #define ASSERT(assertion) ((void)0) #if COMPILER(MSVC7) #define ASSERT_WITH_MESSAGE(assertion) ((void)0) -#elif PLATFORM(SYMBIAN) -#define ASSERT_WITH_MESSAGE(assertion...) ((void)0) +#elif COMPILER(WINSCW) +#define ASSERT_WITH_MESSAGE(assertion, arg...) ((void)0) #else #define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0) #endif /* COMPILER(MSVC7) */ @@ -176,8 +176,8 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann while (0) #if COMPILER(MSVC7) #define ASSERT_WITH_MESSAGE(assertion) ((void)0) -#elif PLATFORM(SYMBIAN) -#define ASSERT_WITH_MESSAGE(assertion...) ((void)0) +#elif COMPILER(WINSCW) +#define ASSERT_WITH_MESSAGE(assertion, arg...) ((void)0) #else #define ASSERT_WITH_MESSAGE(assertion, ...) do \ if (!(assertion)) { \ @@ -219,11 +219,11 @@ while (0) /* FATAL */ -#if FATAL_DISABLED && !COMPILER(MSVC7) && !PLATFORM(SYMBIAN) +#if FATAL_DISABLED && !COMPILER(MSVC7) && !COMPILER(WINSCW) #define FATAL(...) ((void)0) #elif COMPILER(MSVC7) #define FATAL() ((void)0) -#elif PLATFORM(SYMBIAN) +#elif COMPILER(WINSCW) #define FATAL(args...) ((void)0) #else #define FATAL(...) do { \ @@ -234,24 +234,24 @@ while (0) /* LOG_ERROR */ -#if ERROR_DISABLED && !COMPILER(MSVC7) && !PLATFORM(SYMBIAN) +#if ERROR_DISABLED && !COMPILER(MSVC7) && !COMPILER(WINSCW) #define LOG_ERROR(...) ((void)0) #elif COMPILER(MSVC7) #define LOG_ERROR() ((void)0) -#elif PLATFORM(SYMBIAN) -#define LOG_ERROR(args...) ((void)0) +#elif COMPILER(WINSCW) +#define LOG_ERROR(arg...) ((void)0) #else #define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__) #endif /* LOG */ -#if LOG_DISABLED && !COMPILER(MSVC7) && !PLATFORM(SYMBIAN) +#if LOG_DISABLED && !COMPILER(MSVC7) && !COMPILER(WINSCW) #define LOG(channel, ...) ((void)0) #elif COMPILER(MSVC7) #define LOG() ((void)0) -#elif PLATFORM(SYMBIAN) -#define LOG(channel, args...) ((void)0) +#elif COMPILER(WINSCW) +#define LOG(arg...) ((void)0) #else #define LOG(channel, ...) WTFLog(&JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__) #define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) @@ -260,12 +260,12 @@ while (0) /* LOG_VERBOSE */ -#if LOG_DISABLED && !COMPILER(MSVC7) && !PLATFORM(SYMBIAN) +#if LOG_DISABLED && !COMPILER(MSVC7) && !COMPILER(WINSCW) #define LOG_VERBOSE(channel, ...) ((void)0) #elif COMPILER(MSVC7) #define LOG_VERBOSE(channel) ((void)0) -#elif PLATFORM(SYMBIAN) -#define LOG_VERBOSE(channel, args...) ((void)0) +#elif COMPILER(WINSCW) +#define LOG_VERBOSE(channel, arg...) ((void)0) #else #define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__) #endif diff --git a/src/3rdparty/webkit/VERSION b/src/3rdparty/webkit/VERSION index e6813a1..daa3be7 100644 --- a/src/3rdparty/webkit/VERSION +++ b/src/3rdparty/webkit/VERSION @@ -8,4 +8,4 @@ The commit imported was from the and has the sha1 checksum - de77f8ee69c434bde9306c8f407ee2e443a00188 + 70b5989bdeea2f73bd950099fc0f0e954550ef54 diff --git a/src/3rdparty/webkit/WebCore/ChangeLog b/src/3rdparty/webkit/WebCore/ChangeLog index c60a5d4..03bb1fb 100644 --- a/src/3rdparty/webkit/WebCore/ChangeLog +++ b/src/3rdparty/webkit/WebCore/ChangeLog @@ -1,3 +1,76 @@ +2009-12-30 Janne Koskinen <janne.p.koskinen@digia.com> + + Reviewed by Simon Hausmann. + + [Qt] Add support for Symbian def files + + * WebCore.pro: + +2009-12-30 Simon Hausmann <simon.hausmann@nokia.com> + + Unreviewed Qt/Symbian build fix. + + Don't build network state notifier support when building inside of Qt. + Otherwise the Qt build depends on an external module that itself depends + on Qt again. + + * WebCore.pro: + +2009-12-30 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Simon Hausmann. + + Turn off DataGrid support by default. + + No new tests, as there is no new functionality. + + * WebCore.pro: + +2009-12-17 Yael Aharon <yael.aharon@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] support navigator.onLine and ononline/onoffline events. + https://bugs.webkit.org/show_bug.cgi?id=32555 + + Hooked up Bearer Management to NetworkStateNotifier. This solution is available + only if QtMobility's Bearer Management is installed. + + * WebCore.pro: + * platform/network/NetworkStateNotifier.h: + * platform/network/qt/NetworkStateNotifierPrivate.h: Added. + * platform/network/qt/NetworkStateNotifierQt.cpp: Added. + (WebCore::NetworkStateNotifierPrivate::NetworkStateNotifierPrivate): + (WebCore::NetworkStateNotifierPrivate::onlineStateChanged): + (WebCore::NetworkStateNotifierPrivate::~NetworkStateNotifierPrivate): + (WebCore::NetworkStateNotifier::updateState): + (WebCore::NetworkStateNotifier::NetworkStateNotifier): + +2009-12-17 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Tor Arne Vestbø. + + [Qt] Symbian build fix: Don't include QtXml/qxmlstream.h but omit the prefix, to + make sure we pick up the header file from QtCore. That is where the implementation + is compiled. + + * dom/XMLTokenizer.h: + +2009-12-14 Holger Hans Peter Freyther <zecke@selfish.org> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Add manual test for JavaScript prompt corner case + https://bugs.webkit.org/show_bug.cgi?id=30914 + + The patch is based on the work done by Gupta Manish. + + Verify behavior of the JavaScript prompt function. Currently + Qt is not behaving like other WebKit ports and Firefox in + regards to accepting the prompt but not entering a text. + + * manual-tests/qt/java-script-prompt.html: Added. + 2009-12-21 Andreas Kling <andreas.kling@nokia.com> Reviewed by Darin Adler. diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro index 9239089..be64e3b 100644 --- a/src/3rdparty/webkit/WebCore/WebCore.pro +++ b/src/3rdparty/webkit/WebCore/WebCore.pro @@ -136,7 +136,7 @@ contains(DEFINES, ENABLE_SINGLE_THREADED=1) { !contains(DEFINES, ENABLE_SHARED_WORKERS=.): DEFINES += ENABLE_SHARED_WORKERS=1 !contains(DEFINES, ENABLE_WORKERS=.): DEFINES += ENABLE_WORKERS=1 !contains(DEFINES, ENABLE_XHTMLMP=.): DEFINES += ENABLE_XHTMLMP=0 -!contains(DEFINES, ENABLE_DATAGRID=.): DEFINES += ENABLE_DATAGRID=1 +!contains(DEFINES, ENABLE_DATAGRID=.): DEFINES += ENABLE_DATAGRID=0 # SVG support !contains(DEFINES, ENABLE_SVG=0) { @@ -180,6 +180,15 @@ contains(DEFINES, ENABLE_SINGLE_THREADED=1) { else:DEFINES += ENABLE_XSLT=0 } +!CONFIG(QTDIR_build):!contains(DEFINES, ENABLE_QT_BEARER=.) { + symbian: { + exists($${EPOCROOT}epoc32/release/winscw/udeb/QtBearer.lib)| \ + exists($${EPOCROOT}epoc32/release/armv5/lib/QtBearer.lib) { + DEFINES += ENABLE_QT_BEARER=1 + } + } +} + DEFINES += WTF_USE_JAVASCRIPTCORE_BINDINGS=1 WTF_CHANGES=1 # Used to compute defaults for the build-webkit script @@ -2860,6 +2869,17 @@ contains(DEFINES, ENABLE_XHTMLMP=1) { FEATURE_DEFINES_JAVASCRIPT += ENABLE_XHTMLMP=1 } +contains(DEFINES, ENABLE_QT_BEARER=1) { + HEADERS += \ + platform/network/qt/NetworkStateNotifierPrivate.h + + SOURCES += \ + platform/network/qt/NetworkStateNotifierQt.cpp + + LIBS += -lQtBearer + +} + contains(DEFINES, ENABLE_SVG=1) { FEATURE_DEFINES_JAVASCRIPT += ENABLE_SVG=1 @@ -3382,16 +3402,15 @@ CONFIG(QTDIR_build):isEqual(QT_MAJOR_VERSION, 4):greaterThan(QT_MINOR_VERSION, 4 } } -# Temporary workaround to pick up the DEF file from the same place as all the others symbian { shared { contains(MMP_RULES, defBlock) { MMP_RULES -= defBlock MMP_RULES += "$${LITERAL_HASH}ifdef WINSCW" \ - "DEFFILE ../../../s60installs/bwins/$${TARGET}.def" \ + "DEFFILE ../WebKit/qt/symbian/bwins/$${TARGET}.def" \ "$${LITERAL_HASH}elif defined EABI" \ - "DEFFILE ../../../s60installs/eabi/$${TARGET}.def" \ + "DEFFILE ../WebKit/qt/symbian/eabi/$${TARGET}.def" \ "$${LITERAL_HASH}endif" } } diff --git a/src/3rdparty/webkit/WebCore/dom/XMLTokenizer.h b/src/3rdparty/webkit/WebCore/dom/XMLTokenizer.h index e1ee09f..a83e73a 100644 --- a/src/3rdparty/webkit/WebCore/dom/XMLTokenizer.h +++ b/src/3rdparty/webkit/WebCore/dom/XMLTokenizer.h @@ -34,7 +34,7 @@ #include <wtf/OwnPtr.h> #if USE(QXMLSTREAM) -#include <QtXml/qxmlstream.h> +#include <qxmlstream.h> #else #include <libxml/tree.h> #include <libxml/xmlstring.h> diff --git a/src/3rdparty/webkit/WebCore/platform/network/NetworkStateNotifier.h b/src/3rdparty/webkit/WebCore/platform/network/NetworkStateNotifier.h index 0189f5f..f8c5654 100644 --- a/src/3rdparty/webkit/WebCore/platform/network/NetworkStateNotifier.h +++ b/src/3rdparty/webkit/WebCore/platform/network/NetworkStateNotifier.h @@ -46,6 +46,10 @@ typedef const struct __SCDynamicStore * SCDynamicStoreRef; namespace WebCore { +#if (PLATFORM(QT) && ENABLE(QT_BEARER)) +class NetworkStateNotifierPrivate; +#endif + class NetworkStateNotifier { public: NetworkStateNotifier(); @@ -78,10 +82,14 @@ private: #elif PLATFORM(CHROMIUM) NetworkStateNotifierPrivate p; + +#elif PLATFORM(QT) && ENABLE(QT_BEARER) + friend class NetworkStateNotifierPrivate; + NetworkStateNotifierPrivate* p; #endif }; -#if !PLATFORM(MAC) && !PLATFORM(WIN) && !PLATFORM(CHROMIUM) +#if !PLATFORM(MAC) && !PLATFORM(WIN) && !PLATFORM(CHROMIUM) && !(PLATFORM(QT) && ENABLE(QT_BEARER)) inline NetworkStateNotifier::NetworkStateNotifier() : m_isOnLine(true) diff --git a/src/3rdparty/webkit/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h b/src/3rdparty/webkit/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h new file mode 100644 index 0000000..7af6392 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef NetworkStateNotifierPrivate_h +#define NetworkStateNotifierPrivate_h + +#include <QObject> + +namespace QtMobility { +class QNetworkConfigurationManager; +} + +namespace WebCore { + +class NetworkStateNotifier; + +class NetworkStateNotifierPrivate : public QObject { + Q_OBJECT +public: + NetworkStateNotifierPrivate(NetworkStateNotifier* notifier); + ~NetworkStateNotifierPrivate(); +public slots: + void onlineStateChanged(bool); + +public: + QtMobility::QNetworkConfigurationManager* m_configurationManager; + bool m_online; + NetworkStateNotifier* m_notifier; +}; + +} // namespace WebCore + +#endif diff --git a/src/3rdparty/webkit/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp b/src/3rdparty/webkit/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp new file mode 100644 index 0000000..f74398b --- /dev/null +++ b/src/3rdparty/webkit/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp @@ -0,0 +1,73 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "NetworkStateNotifier.h" + +#include "NetworkStateNotifierPrivate.h" +#include "qnetworkconfigmanager.h" + +using namespace QtMobility; + +namespace WebCore { + +NetworkStateNotifierPrivate::NetworkStateNotifierPrivate(NetworkStateNotifier* notifier) + : m_configurationManager(new QNetworkConfigurationManager()) + , m_online(m_configurationManager->isOnline()) + , m_notifier(notifier) +{ + Q_ASSERT(notifier); + connect(m_configurationManager, SIGNAL(onlineStateChanged(bool)), this, SLOT(onlineStateChanged(bool))); +} + +void NetworkStateNotifierPrivate::onlineStateChanged(bool isOnline) +{ + if (m_online == isOnline) + return; + + m_online = isOnline; + m_notifier->updateState(); +} + +NetworkStateNotifierPrivate::~NetworkStateNotifierPrivate() +{ + delete m_configurationManager; +} + +void NetworkStateNotifier::updateState() +{ + if (m_isOnLine == p->m_online) + return; + + m_isOnLine = p->m_online; + if (m_networkStateChangedFunction) + m_networkStateChangedFunction(); +} + +NetworkStateNotifier::NetworkStateNotifier() + : m_isOnLine(true) + , m_networkStateChangedFunction(0) +{ + p = new NetworkStateNotifierPrivate(this); + m_isOnLine = p->m_online; +} + +} // namespace WebCore + +#include "moc_NetworkStateNotifierPrivate.cpp" diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp index 35f6e0c..6d08c32 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp @@ -1849,7 +1849,8 @@ bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg) The program may provide an optional message, \a msg, as well as a default value for the input in \a defaultValue. If the prompt was cancelled by the user the implementation should return false; otherwise the - result should be written to \a result and true should be returned. + result should be written to \a result and true should be returned. If the prompt was not cancelled by the + user, the implementation should return true and the result string must not be null. The default implementation uses QInputDialog::getText. */ diff --git a/src/3rdparty/webkit/WebKit/qt/ChangeLog b/src/3rdparty/webkit/WebKit/qt/ChangeLog index 37d527fa..4ab5bfb 100644 --- a/src/3rdparty/webkit/WebKit/qt/ChangeLog +++ b/src/3rdparty/webkit/WebKit/qt/ChangeLog @@ -1,3 +1,39 @@ +2009-12-30 Janne Koskinen <janne.p.koskinen@digia.com> + + Reviewed by Simon Hausmann. + + Upstream Symbian def files from Qt 4.6. + + These files define the ABI of QtWebKit on Symbian. + + * symbian/bwins/QtWebKitu.def: Added. + * symbian/eabi/QtWebKitu.def: Added. + +2009-12-14 Holger Hans Peter Freyther <zecke@selfish.org> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Fix JavaScript prompt behavior for empty/null strings. + https://bugs.webkit.org/show_bug.cgi?id=30914 + + The patch is based on the work done by Gupta Manish. + + In the default implementation of the JavaScript prompt + we are using a QInputDialog to get the text and this has + one quirk with regard to not entering any text. + + In other WebKit ports and in Firefox an empty string is + returned but in the Qt case it is a null string. + + Change the API documentation in QWebPage to mention we want to + have a non null string but do the fixup in the ChromeClientQt + to support existing code. + + * Api/qwebpage.cpp: + (QWebPage::javaScriptPrompt): Change API documentation + * WebCoreSupport/ChromeClientQt.cpp: + (WebCore::ChromeClientQt::runJavaScriptPrompt): Fixup null QString + 2009-12-21 David Boddie <dboddie@trolltech.com> Reviewed by Simon Hausmann. diff --git a/src/3rdparty/webkit/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp b/src/3rdparty/webkit/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp index 26cf6f6..c5d2792 100644 --- a/src/3rdparty/webkit/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp +++ b/src/3rdparty/webkit/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp @@ -278,7 +278,14 @@ bool ChromeClientQt::runJavaScriptPrompt(Frame* f, const String& message, const QString x = result; FrameLoaderClientQt *fl = static_cast<FrameLoaderClientQt*>(f->loader()->client()); bool rc = m_webPage->javaScriptPrompt(fl->webFrame(), (QString)message, (QString)defaultValue, &x); - result = x; + + // Fix up a quirk in the QInputDialog class. If no input happened the string should be empty + // but it is null. See https://bugs.webkit.org/show_bug.cgi?id=30914. + if (rc && result.isNull()) + result = String(""); + else + result = x; + return rc; } diff --git a/src/s60installs/bwins/QtWebKitu.def b/src/3rdparty/webkit/WebKit/qt/symbian/bwins/QtWebKitu.def index e5631f8..e5631f8 100644 --- a/src/s60installs/bwins/QtWebKitu.def +++ b/src/3rdparty/webkit/WebKit/qt/symbian/bwins/QtWebKitu.def diff --git a/src/s60installs/eabi/QtWebKitu.def b/src/3rdparty/webkit/WebKit/qt/symbian/eabi/QtWebKitu.def index 4aad884..4aad884 100644 --- a/src/s60installs/eabi/QtWebKitu.def +++ b/src/3rdparty/webkit/WebKit/qt/symbian/eabi/QtWebKitu.def diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 71414ce..ea262bf 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -825,10 +825,9 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const ret |= RootFlag; } else { QString baseName = fileName(BaseName); - if ((baseName.size() > 1 - && baseName.at(0) == QLatin1Char('.') && baseName.at(1) != QLatin1Char('.')) + if ((baseName.size() > 0 && baseName.at(0) == QLatin1Char('.')) # if !defined(QWS) && defined(Q_OS_MAC) - || _q_isMacHidden(d->filePath) + || _q_isMacHidden(d->filePath) # endif ) { ret |= HiddenFlag; diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 36cf67b..9f336a6 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -1590,13 +1590,10 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::Fil ret |= LocalDiskFlag; if (d->doStat()) { ret |= ExistsFlag; - if (d->filePath == QLatin1String("/") || isDriveRoot(d->filePath) || isUncRoot(d->filePath)) { + if (d->filePath == QLatin1String("/") || isDriveRoot(d->filePath) || isUncRoot(d->filePath)) ret |= RootFlag; - } else if (d->fileAttrib & FILE_ATTRIBUTE_HIDDEN) { - QString baseName = fileName(BaseName); - if (baseName != QLatin1String(".") && baseName != QLatin1String("..")) - ret |= HiddenFlag; - } + else if (d->fileAttrib & FILE_ATTRIBUTE_HIDDEN) + ret |= HiddenFlag; } } return ret; diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index fd51bcf..6ac6468 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -3864,14 +3864,18 @@ QByteArray QUrlPrivate::toEncoded(QUrl::FormattingOptions options) const url += "//"; if ((options & QUrl::RemoveUserInfo) != QUrl::RemoveUserInfo) { + bool hasUserOrPass = false; if (!userName.isEmpty()) { url += encodedUserName; - if (!(options & QUrl::RemovePassword) && !password.isEmpty()) { - url += ':'; - url += encodedPassword; - } - url += '@'; + hasUserOrPass = true; } + if (!(options & QUrl::RemovePassword) && !password.isEmpty()) { + url += ':'; + url += encodedPassword; + hasUserOrPass = true; + } + if (hasUserOrPass) + url += '@'; } if (host.startsWith(QLatin1Char('['))) { diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp index 994da10..ff0a93e 100644 --- a/src/dbus/qdbusabstractinterface.cpp +++ b/src/dbus/qdbusabstractinterface.cpp @@ -561,13 +561,7 @@ void QDBusAbstractInterface::connectNotify(const char *signal) QDBusConnectionPrivate *conn = d->connectionPrivate(); if (conn) { - // do we know what our owner is? - QString owner; - if (!d->service.isEmpty() && d->currentOwner.isNull()) - owner = QLatin1String(""); - else - owner = d->currentOwner; - conn->connectRelay(d->service, owner, d->path, d->interface, + conn->connectRelay(d->service, d->path, d->interface, this, signal); } } @@ -585,7 +579,7 @@ void QDBusAbstractInterface::disconnectNotify(const char *signal) QDBusConnectionPrivate *conn = d->connectionPrivate(); if (conn) - conn->disconnectRelay(d->service, d->currentOwner, d->path, d->interface, + conn->disconnectRelay(d->service, d->path, d->interface, this, signal); } diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index d7088ff..47893cc 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -619,10 +619,8 @@ bool QDBusConnection::connect(const QString &service, const QString &path, const if (interface.isEmpty() && name.isEmpty()) return false; - QString owner = d->getNameOwner(service); // we don't care if the owner is empty - // it might get started later QDBusWriteLocker locker(ConnectAction, d); - return d->connectSignal(service, owner, path, interface, name, argumentMatch, signature, receiver, slot); + return d->connectSignal(service, path, interface, name, argumentMatch, signature, receiver, slot); } /*! diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index d6f7598..32e057c 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -119,7 +119,7 @@ public: struct SignalHook { inline SignalHook() : obj(0), midx(-1) { } - QString owner, service, path, signature; + QString service, path, signature; QObject* obj; int midx; QList<int> params; @@ -155,7 +155,13 @@ public: typedef QMultiHash<QString, SignalHook> SignalHookHash; typedef QHash<QString, QDBusMetaObject* > MetaObjectHash; typedef QHash<QByteArray, int> MatchRefCountHash; - typedef QHash<QString, int> WatchedServicesHash; + + struct WatchedServiceData { + WatchedServiceData() : refcount(0) {} + QString owner; + int refcount; + }; + typedef QHash<QString, WatchedServiceData> WatchedServicesHash; public: // public methods are entry points from other objects @@ -177,7 +183,7 @@ public: QDBusPendingCallPrivate *sendWithReplyAsync(const QDBusMessage &message, int timeout = -1); int sendWithReplyAsync(const QDBusMessage &message, QObject *receiver, const char *returnMethod, const char *errorMethod, int timeout = -1); - bool connectSignal(const QString &service, const QString &owner, const QString &path, const QString& interface, + bool connectSignal(const QString &service, const QString &path, const QString& interface, const QString &name, const QStringList &argumentMatch, const QString &signature, QObject *receiver, const char *slot); void connectSignal(const QString &key, const SignalHook &hook); @@ -186,10 +192,10 @@ public: const QString &name, const QStringList &argumentMatch, const QString &signature, QObject *receiver, const char *slot); void registerObject(const ObjectTreeNode *node); - void connectRelay(const QString &service, const QString ¤tOwner, + void connectRelay(const QString &service, const QString &path, const QString &interface, QDBusAbstractInterface *receiver, const char *signal); - void disconnectRelay(const QString &service, const QString ¤tOwner, + void disconnectRelay(const QString &service, const QString &path, const QString &interface, QDBusAbstractInterface *receiver, const char *signal); @@ -223,6 +229,8 @@ private: bool isServiceRegisteredByThread(const QString &serviceName) const; + QString getNameOwnerNoCache(const QString &service); + protected: void customEvent(QEvent *e); void timerEvent(QTimerEvent *e); @@ -271,7 +279,7 @@ public: QDBusError lastError; QStringList serviceNames; - WatchedServicesHash watchedServiceNames; + WatchedServicesHash watchedServices; SignalHookHash signalHooks; MatchRefCountHash matchRefCounts; ObjectTreeNode rootNode; @@ -284,7 +292,7 @@ public: // static methods static int findSlot(QObject *obj, const QByteArray &normalizedName, QList<int>& params); static bool prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key, - const QString &service, const QString &owner, + const QString &service, const QString &path, const QString &interface, const QString &name, const QStringList &argMatch, QObject *receiver, const char *signal, int minMIdx, diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 40febc4..ea02005 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -390,7 +390,7 @@ static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, v } // extern "C" -static QByteArray buildMatchRule(const QString &service, const QString & /*owner*/, +static QByteArray buildMatchRule(const QString &service, const QString &objectPath, const QString &interface, const QString &member, const QStringList &argMatch, const QString & /*signature*/) { @@ -523,7 +523,7 @@ qDBusSignalFilter(DBusConnection *connection, DBusMessage *message, void *data) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(message); - qDBusDebug() << QThread::currentThread() << "got message:" << amsg; + qDBusDebug() << d << "got message:" << amsg; return d->handleMessage(amsg) ? DBUS_HANDLER_RESULT_HANDLED : @@ -913,7 +913,7 @@ void QDBusConnectionPrivate::deliverCall(QObject *object, int /*flags*/, const Q if (msg.isReplyRequired() && !msg.isDelayedReply()) { if (!fail) { // normal reply - qDBusDebug() << QThread::currentThread() << "Automatically sending reply:" << outputArgs; + qDBusDebug() << this << "Automatically sending reply:" << outputArgs; send(msg.createReply(outputArgs)); } else { // generate internal error @@ -947,7 +947,6 @@ QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p) QDBusMetaTypeId::init(); rootNode.flags = 0; - watchedServiceNames[QLatin1String(DBUS_SERVICE_DBUS)] = 1; } QDBusConnectionPrivate::~QDBusConnectionPrivate() @@ -1179,11 +1178,15 @@ void QDBusConnectionPrivate::_q_serviceOwnerChanged(const QString &name, { Q_UNUSED(oldOwner); QDBusWriteLocker locker(UpdateSignalHookOwnerAction, this); - QMutableHashIterator<QString, SignalHook> it(signalHooks); - it.toFront(); - while (it.hasNext()) - if (it.next().value().service == name) - it.value().owner = newOwner; + WatchedServicesHash::Iterator it = watchedServices.find(name); + if (it == watchedServices.end()) + return; + if (oldOwner != it->owner) + qWarning("QDBusConnection: name '%s' had owner '%s' but we thought it was '%s'", + qPrintable(name), qPrintable(oldOwner), qPrintable(it->owner)); + + qDBusDebug() << this << "Updating name" << name << "from" << oldOwner << "to" << newOwner; + it->owner = newOwner; } int QDBusConnectionPrivate::findSlot(QObject* obj, const QByteArray &normalizedName, @@ -1201,7 +1204,7 @@ int QDBusConnectionPrivate::findSlot(QObject* obj, const QByteArray &normalizedN } bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hook, QString &key, - const QString &service, const QString &owner, + const QString &service, const QString &path, const QString &interface, const QString &name, const QStringList &argMatch, QObject *receiver, const char *signal, int minMIdx, @@ -1220,7 +1223,6 @@ bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hoo } hook.service = service; - hook.owner = owner; // we don't care if the service has an owner yet hook.path = path; hook.obj = receiver; hook.argumentMatch = argMatch; @@ -1245,7 +1247,7 @@ bool QDBusConnectionPrivate::prepareHook(QDBusConnectionPrivate::SignalHook &hoo hook.signature += QLatin1String( QDBusMetaType::typeToSignature( hook.params.at(i) ) ); } - hook.matchRule = buildMatchRule(service, owner, path, interface, mname, argMatch, hook.signature); + hook.matchRule = buildMatchRule(service, path, interface, mname, argMatch, hook.signature); return true; // connect to this signal } @@ -1488,8 +1490,14 @@ void QDBusConnectionPrivate::handleSignal(const QString &key, const QDBusMessage //qDBusDebug() << signalHooks.keys(); for ( ; it != end && it.key() == key; ++it) { const SignalHook &hook = it.value(); - if (!hook.owner.isNull() && hook.owner != msg.service()) - continue; + if (!hook.service.isEmpty()) { + const QString owner = + shouldWatchService(hook.service) ? + watchedServices.value(hook.service).owner : + hook.service; + if (owner != msg.service()) + continue; + } if (!hook.path.isEmpty() && hook.path != msg.path()) continue; if (!hook.signature.isEmpty() && hook.signature != msg.signature()) @@ -1652,15 +1660,18 @@ void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusError } QString busService = QLatin1String(DBUS_SERVICE_DBUS); - connectSignal(busService, QString(), QString(), QString(), QLatin1String("NameAcquired"), QStringList(), QString(), + WatchedServicesHash::mapped_type &bus = watchedServices[busService]; + bus.refcount = 1; + bus.owner = getNameOwnerNoCache(busService); + connectSignal(busService, QString(), QString(), QLatin1String("NameAcquired"), QStringList(), QString(), this, SLOT(registerService(QString))); - connectSignal(busService, QString(), QString(), QString(), QLatin1String("NameLost"), QStringList(), QString(), + connectSignal(busService, QString(), QString(), QLatin1String("NameLost"), QStringList(), QString(), this, SLOT(unregisterService(QString))); q_dbus_connection_add_filter(connection, qDBusSignalFilter, this, 0); - //qDebug("base service: %s", service); + qDBusDebug() << this << ": connected successfully"; // schedule a dispatch: QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection); @@ -1695,7 +1706,7 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call) msg = QDBusMessagePrivate::fromDBusMessage(reply); q_dbus_message_unref(reply); } - qDBusDebug() << QThread::currentThread() << "got message reply (async):" << msg; + qDBusDebug() << connection << "got message reply (async):" << msg; // Check if the reply has the expected signature call->checkReceivedSignature(); @@ -1763,7 +1774,7 @@ int QDBusConnectionPrivate::send(const QDBusMessage& message) q_dbus_message_set_no_reply(msg, true); // the reply would not be delivered to anything - qDBusDebug() << QThread::currentThread() << "sending message (no reply):" << message; + qDBusDebug() << this << "sending message (no reply):" << message; checkThread(); bool isOk = q_dbus_connection_send(connection, msg, 0); int serial = 0; @@ -1795,7 +1806,7 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message, return QDBusMessage::createError(err); } - qDBusDebug() << QThread::currentThread() << "sending message (blocking):" << message; + qDBusDebug() << this << "sending message (blocking):" << message; QDBusErrorInternal error; DBusMessage *reply = q_dbus_connection_send_with_reply_and_block(connection, msg, timeout, error); @@ -1808,7 +1819,7 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message, QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(reply); q_dbus_message_unref(reply); - qDBusDebug() << QThread::currentThread() << "got message reply (blocking):" << amsg; + qDBusDebug() << this << "got message reply (blocking):" << amsg; return amsg; } else { // use the event loop @@ -1835,7 +1846,7 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message, QDBusMessage QDBusConnectionPrivate::sendWithReplyLocal(const QDBusMessage &message) { - qDBusDebug() << QThread::currentThread() << "sending message via local-loop:" << message; + qDBusDebug() << this << "sending message via local-loop:" << message; QDBusMessage localCallMsg = QDBusMessagePrivate::makeLocal(*this, message); bool handled = handleMessage(localCallMsg); @@ -1862,7 +1873,7 @@ QDBusMessage QDBusConnectionPrivate::sendWithReplyLocal(const QDBusMessage &mess } // there is a reply - qDBusDebug() << QThread::currentThread() << "got message via local-loop:" << localReplyMsg; + qDBusDebug() << this << "got message via local-loop:" << localReplyMsg; return localReplyMsg; } @@ -1896,7 +1907,7 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM return pcall; } - qDBusDebug() << QThread::currentThread() << "sending message (async):" << message; + qDBusDebug() << this << "sending message (async):" << message; DBusPendingCall *pending = 0; QDBusDispatchLocker locker(SendWithReplyAsyncAction, this); @@ -1968,7 +1979,7 @@ int QDBusConnectionPrivate::sendWithReplyAsync(const QDBusMessage &message, QObj return 1; } -bool QDBusConnectionPrivate::connectSignal(const QString &service, const QString &owner, +bool QDBusConnectionPrivate::connectSignal(const QString &service, const QString &path, const QString &interface, const QString &name, const QStringList &argumentMatch, const QString &signature, QObject *receiver, const char *slot) @@ -1981,7 +1992,7 @@ bool QDBusConnectionPrivate::connectSignal(const QString &service, const QString name2.detach(); hook.signature = signature; - if (!prepareHook(hook, key, service, owner, path, interface, name, argumentMatch, receiver, slot, 0, false)) + if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0, false)) return false; // don't connect // avoid duplicating: @@ -1990,7 +2001,6 @@ bool QDBusConnectionPrivate::connectSignal(const QString &service, const QString for ( ; it != end && it.key() == key; ++it) { const QDBusConnectionPrivate::SignalHook &entry = it.value(); if (entry.service == hook.service && - entry.owner == hook.owner && entry.path == hook.path && entry.signature == hook.signature && entry.obj == hook.obj && @@ -2035,16 +2045,19 @@ void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook // Successfully connected the signal // Do we need to watch for this name? if (shouldWatchService(hook.service)) { - WatchedServicesHash::Iterator it = watchedServiceNames.find(hook.service); - if (it != watchedServiceNames.end()) { + WatchedServicesHash::mapped_type &data = watchedServices[hook.service]; + if (data.refcount) { // already watching - ++it.value(); + ++data.refcount; } else { // we need to watch for this service changing QString dbusServerService = QLatin1String(DBUS_SERVICE_DBUS); - connectSignal(dbusServerService, dbusServerService, QString(), QLatin1String(DBUS_INTERFACE_DBUS), + connectSignal(dbusServerService, QString(), QLatin1String(DBUS_INTERFACE_DBUS), QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); + data.owner = getNameOwnerNoCache(hook.service); + qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:" + << data.owner << ")"; } } } @@ -2064,7 +2077,7 @@ bool QDBusConnectionPrivate::disconnectSignal(const QString &service, name2.detach(); hook.signature = signature; - if (!prepareHook(hook, key, service, QString(), path, interface, name, argumentMatch, receiver, slot, 0, false)) + if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0, false)) return false; // don't disconnect // avoid duplicating: @@ -2073,7 +2086,6 @@ bool QDBusConnectionPrivate::disconnectSignal(const QString &service, for ( ; it != end && it.key() == key; ++it) { const QDBusConnectionPrivate::SignalHook &entry = it.value(); if (entry.service == hook.service && - //entry.owner == hook.owner && entry.path == hook.path && entry.signature == hook.signature && entry.obj == hook.obj && @@ -2093,16 +2105,16 @@ QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it) { const SignalHook &hook = it.value(); - WatchedServicesHash::Iterator sit = watchedServiceNames.find(hook.service); - if (sit != watchedServiceNames.end()) { - if (sit.value() == 1) { - watchedServiceNames.erase(sit); + WatchedServicesHash::Iterator sit = watchedServices.find(hook.service); + if (sit != watchedServices.end()) { + if (sit.value().refcount == 1) { + watchedServices.erase(sit); QString dbusServerService = QLatin1String(DBUS_SERVICE_DBUS); disconnectSignal(dbusServerService, QString(), QLatin1String(DBUS_INTERFACE_DBUS), QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); } else { - --sit.value(); + --sit.value().refcount; } } @@ -2154,7 +2166,7 @@ void QDBusConnectionPrivate::registerObject(const ObjectTreeNode *node) } } -void QDBusConnectionPrivate::connectRelay(const QString &service, const QString &owner, +void QDBusConnectionPrivate::connectRelay(const QString &service, const QString &path, const QString &interface, QDBusAbstractInterface *receiver, const char *signal) @@ -2164,7 +2176,7 @@ void QDBusConnectionPrivate::connectRelay(const QString &service, const QString SignalHook hook; QString key; - if (!prepareHook(hook, key, service, owner, path, interface, QString(), QStringList(), receiver, signal, + if (!prepareHook(hook, key, service, path, interface, QString(), QStringList(), receiver, signal, QDBusAbstractInterface::staticMetaObject.methodCount(), true)) return; // don't connect @@ -2175,7 +2187,6 @@ void QDBusConnectionPrivate::connectRelay(const QString &service, const QString for ( ; it != end && it.key() == key; ++it) { const SignalHook &entry = it.value(); if (entry.service == hook.service && - entry.owner == hook.owner && entry.path == hook.path && entry.signature == hook.signature && entry.obj == hook.obj && @@ -2186,7 +2197,7 @@ void QDBusConnectionPrivate::connectRelay(const QString &service, const QString connectSignal(key, hook); } -void QDBusConnectionPrivate::disconnectRelay(const QString &service, const QString &owner, +void QDBusConnectionPrivate::disconnectRelay(const QString &service, const QString &path, const QString &interface, QDBusAbstractInterface *receiver, const char *signal) @@ -2196,7 +2207,7 @@ void QDBusConnectionPrivate::disconnectRelay(const QString &service, const QStri SignalHook hook; QString key; - if (!prepareHook(hook, key, service, owner, path, interface, QString(), QStringList(), receiver, signal, + if (!prepareHook(hook, key, service, path, interface, QString(), QStringList(), receiver, signal, QDBusAbstractInterface::staticMetaObject.methodCount(), true)) return; // don't connect @@ -2207,7 +2218,6 @@ void QDBusConnectionPrivate::disconnectRelay(const QString &service, const QStri for ( ; it != end && it.key() == key; ++it) { const SignalHook &entry = it.value(); if (entry.service == hook.service && - entry.owner == hook.owner && entry.path == hook.path && entry.signature == hook.signature && entry.obj == hook.obj && @@ -2225,9 +2235,23 @@ QString QDBusConnectionPrivate::getNameOwner(const QString& serviceName) { if (QDBusUtil::isValidUniqueConnectionName(serviceName)) return serviceName; - if (!connection || !QDBusUtil::isValidBusName(serviceName)) + if (!connection) return QString(); + { + // acquire a read lock for the cache + QReadLocker locker(&lock); + WatchedServicesHash::ConstIterator it = watchedServices.constFind(serviceName); + if (it != watchedServices.constEnd()) + return it->owner; + } + + // not cached + return getNameOwnerNoCache(serviceName); +} + +QString QDBusConnectionPrivate::getNameOwnerNoCache(const QString &serviceName) +{ QDBusMessage msg = QDBusMessage::createMethodCall(QLatin1String(DBUS_SERVICE_DBUS), QLatin1String(DBUS_PATH_DBUS), QLatin1String(DBUS_INTERFACE_DBUS), QLatin1String("GetNameOwner")); diff --git a/src/dbus/qdbusmarshaller.cpp b/src/dbus/qdbusmarshaller.cpp index d732ad0..28cec7d 100644 --- a/src/dbus/qdbusmarshaller.cpp +++ b/src/dbus/qdbusmarshaller.cpp @@ -387,7 +387,6 @@ bool QDBusMarshaller::appendVariantInternal(const QVariant &arg) switch (*signature) { #ifdef __OPTIMIZE__ case DBUS_TYPE_BYTE: - case DBUS_TYPE_BOOLEAN: case DBUS_TYPE_INT16: case DBUS_TYPE_UINT16: case DBUS_TYPE_INT32: @@ -397,6 +396,9 @@ bool QDBusMarshaller::appendVariantInternal(const QVariant &arg) case DBUS_TYPE_DOUBLE: qIterAppend(&iterator, ba, *signature, arg.constData()); return true; + case DBUS_TYPE_BOOLEAN: + append( arg.toBool() ); + return true; #else case DBUS_TYPE_BYTE: append( qvariant_cast<uchar>(arg) ); diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 074f3eb..7580446 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -471,7 +471,6 @@ QImageReaderPrivate::QImageReaderPrivate(QImageReader *qq) handler = 0; quality = -1; imageReaderError = QImageReader::UnknownError; - errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Unknown error")); q = qq; } @@ -1214,11 +1213,12 @@ bool QImageReader::jumpToImage(int imageNumber) } /*! - For image formats that support animation, this function returns - the number of times the animation should loop. Otherwise, it - returns -1. + For image formats that support animation, this function returns the number + of times the animation should loop. If this function returns -1, it can + either mean the animation should loop forever, or that an error occurred. + If an error occurred, canRead() will return false. - \sa supportsAnimation(), QImageIOHandler::loopCount() + \sa supportsAnimation(), QImageIOHandler::loopCount(), canRead() */ int QImageReader::loopCount() const { @@ -1228,13 +1228,13 @@ int QImageReader::loopCount() const } /*! - For image formats that support animation, this function returns - the total number of images in the animation. + For image formats that support animation, this function returns the total + number of images in the animation. If the format does not support + animation, 0 is returned. - Certain animation formats do not support this feature, in which - case 0 is returned. + This function returns -1 if an error occurred. - \sa supportsAnimation(), QImageIOHandler::imageCount() + \sa supportsAnimation(), QImageIOHandler::imageCount(), canRead() */ int QImageReader::imageCount() const { @@ -1244,11 +1244,13 @@ int QImageReader::imageCount() const } /*! - For image formats that support animation, this function returns - the number of milliseconds to wait until displaying the next frame - in the animation. Otherwise, 0 is returned. + For image formats that support animation, this function returns the number + of milliseconds to wait until displaying the next frame in the animation. + If the image format doesn't support animation, 0 is returned. + + This function returns -1 if an error occurred. - \sa supportsAnimation(), QImageIOHandler::nextImageDelay() + \sa supportsAnimation(), QImageIOHandler::nextImageDelay(), canRead() */ int QImageReader::nextImageDelay() const { @@ -1258,11 +1260,13 @@ int QImageReader::nextImageDelay() const } /*! - For image formats that support animation, this function returns - the sequence number of the current frame. Otherwise, -1 is - returned. + For image formats that support animation, this function returns the + sequence number of the current frame. If the image format doesn't support + animation, 0 is returned. + + This function returns -1 if an error occurred. - \sa supportsAnimation(), QImageIOHandler::currentImageNumber() + \sa supportsAnimation(), QImageIOHandler::currentImageNumber(), canRead() */ int QImageReader::currentImageNumber() const { @@ -1302,6 +1306,8 @@ QImageReader::ImageReaderError QImageReader::error() const */ QString QImageReader::errorString() const { + if (d->errorString.isEmpty()) + return QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Unknown error")); return d->errorString; } diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 1b01e6f..3c1d7e9 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -375,7 +375,7 @@ int QRasterPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const case QPaintDevice::PdmWidthMM: return qRound(d->width * 25.4 / qt_defaultDpiX()); case QPaintDevice::PdmHeightMM: - return qRound(d->width * 25.4 / qt_defaultDpiY()); + return qRound(d->height * 25.4 / qt_defaultDpiY()); case QPaintDevice::PdmNumColors: return d->colortable.size(); case QPaintDevice::PdmDepth: diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 14c863b..1de0f32 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -67,6 +67,9 @@ QT_BEGIN_NAMESPACE # define Q_INTERNAL_WIN_NO_THROW #endif +// avoid going through QImage::scanLine() which calls detach +#define FAST_SCAN_LINE(data, bpl, y) (data + (y) * bpl) + /* All PNG files load to the minimal QImage equivalent. @@ -510,7 +513,7 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage) && outImage->format() == QImage::Format_Indexed8) { int color_table_size = outImage->colorCount(); for (int y=0; y<(int)height; ++y) { - uchar *p = outImage->scanLine(y); + uchar *p = FAST_SCAN_LINE(data, bpl, y); uchar *end = p + width; while (p < end) { if (*p >= color_table_size) diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp index 8ec9efb..f2d51f7 100644 --- a/src/gui/image/qppmhandler.cpp +++ b/src/gui/image/qppmhandler.cpp @@ -264,7 +264,7 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy bool gray = format == "pgm"; if (format == "pbm") { - image = image.convertToFormat(QImage::Format_MonoLSB); + image = image.convertToFormat(QImage::Format_Mono); } else if (image.depth() == 1) { image = image.convertToFormat(QImage::Format_Indexed8); } else { diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index e0b1499..cbc3fe1 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -9782,13 +9782,12 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) } #endif - if (newParent) { - if (QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore()) { + if (QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore()) { + if (newParent) oldBs->removeDirtyWidget(this); - // Move the widget and all its static children from - // the old backing store to the new one. - oldBs->moveStaticWidgets(this); - } + // Move the widget and all its static children from + // the old backing store to the new one. + oldBs->moveStaticWidgets(this); } if ((QApplicationPrivate::app_compile_version < 0x040200 diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 8b40931..aff3ac0 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -1065,7 +1065,7 @@ QRect QRenderRule::boxRect(const QRect& cr, int flags) const r.adjust(-p[LeftEdge], -p[TopEdge], p[RightEdge], p[BottomEdge]); } } - if (!hasNativeBorder() && (flags & Border)) { + if (hasBorder() && (flags & Border)) { const int *b = border()->borders; r.adjust(-b[LeftEdge], -b[TopEdge], b[RightEdge], b[BottomEdge]); } diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 9d545b9..d28d5f3 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -393,7 +393,7 @@ QGLEngineShaderManager::~QGLEngineShaderManager() removeCustomStage(); } -uint QGLEngineShaderManager::getUniformLocation(Uniform id) +GLuint QGLEngineShaderManager::getUniformLocation(Uniform id) { if (!currentShaderProg) return 0; @@ -428,9 +428,9 @@ uint QGLEngineShaderManager::getUniformLocation(Uniform id) } -void QGLEngineShaderManager::optimiseForBrushTransform(const QTransform &transform) +void QGLEngineShaderManager::optimiseForBrushTransform(QTransform::TransformationType transformType) { - Q_UNUSED(transform); // Currently ignored + Q_UNUSED(transformType); // Currently ignored } void QGLEngineShaderManager::setDirty() diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 50c1432..1ec4cdc 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -454,7 +454,7 @@ public: // There are optimisations we can do, depending on the brush transform: // 1) May not have to apply perspective-correction // 2) Can use lower precision for matrix - void optimiseForBrushTransform(const QTransform &transform); + void optimiseForBrushTransform(QTransform::TransformationType transformType); void setSrcPixelType(Qt::BrushStyle); void setSrcPixelType(PixelSrcType); // For non-brush sources, like pixmaps & images void setOpacityMode(OpacityMode); @@ -463,7 +463,7 @@ public: void setCustomStage(QGLCustomShaderStage* stage); void removeCustomStage(); - uint getUniformLocation(Uniform id); + GLuint getUniformLocation(Uniform id); void setDirty(); // someone has manually changed the current shader program bool useCorrectShaderProg(); // returns true if the shader program needed to be changed diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index abe52fe..e679db8 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -359,10 +359,10 @@ QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate() void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id) { // glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); //### Is it always this texture unit? - if (id != GLuint(-1) && id == lastTexture) + if (id != GLuint(-1) && id == lastTextureUsed) return; - lastTexture = id; + lastTextureUsed = id; if (smoothPixmapTransform) { glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -389,23 +389,26 @@ inline QColor qt_premultiplyColor(QColor c, GLfloat opacity) void QGL2PaintEngineExPrivate::setBrush(const QBrush& brush) { - Q_ASSERT(brush.style() != Qt::NoBrush); - if (qbrush_fast_equals(currentBrush, brush)) return; + const Qt::BrushStyle newStyle = qbrush_style(brush); + Q_ASSERT(newStyle != Qt::NoBrush); + currentBrush = brush; + brushUniformsDirty = true; // All brushes have at least one uniform + + if (newStyle > Qt::SolidPattern) + brushTextureDirty = true; - brushTextureDirty = true; - brushUniformsDirty = true; if (currentBrush.style() == Qt::TexturePattern && qHasPixmapTexture(brush) && brush.texture().isQBitmap()) { shaderManager->setSrcPixelType(QGLEngineShaderManager::TextureSrcWithPattern); } else { - shaderManager->setSrcPixelType(currentBrush.style()); + shaderManager->setSrcPixelType(newStyle); } - shaderManager->optimiseForBrushTransform(currentBrush.transform()); + shaderManager->optimiseForBrushTransform(currentBrush.transform().type()); } @@ -606,12 +609,18 @@ void QGL2PaintEngineExPrivate::updateMatrix() const GLfloat wfactor = 2.0f / width; const GLfloat hfactor = -2.0f / height; + if (addOffset) { + pmvMatrix[2][0] = (wfactor * (transform.dx() + 0.49f)) - transform.m33(); + pmvMatrix[2][1] = (hfactor * (transform.dy() + 0.49f)) + transform.m33(); + } else { + pmvMatrix[2][0] = (wfactor * transform.dx()) - transform.m33(); + pmvMatrix[2][1] = (hfactor * transform.dy()) + transform.m33(); + } + pmvMatrix[0][0] = (wfactor * transform.m11()) - transform.m13(); pmvMatrix[1][0] = (wfactor * transform.m21()) - transform.m23(); - pmvMatrix[2][0] = (wfactor * transform.dx() ) - transform.m33(); pmvMatrix[0][1] = (hfactor * transform.m12()) + transform.m13(); pmvMatrix[1][1] = (hfactor * transform.m22()) + transform.m23(); - pmvMatrix[2][1] = (hfactor * transform.dy() ) + transform.m33(); pmvMatrix[0][2] = transform.m13(); pmvMatrix[1][2] = transform.m23(); pmvMatrix[2][2] = transform.m33(); @@ -701,7 +710,14 @@ static inline void setCoords(GLfloat *coords, const QGLRect &rect) void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern) { // Setup for texture drawing + currentBrush = noBrush; shaderManager->setSrcPixelType(pattern ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc); + + if (addOffset) { + addOffset = false; + matrixDirty = true; + } + if (prepareForDraw(opaque)) shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); @@ -756,7 +772,7 @@ void QGL2PaintEngineEx::beginNativePainting() Q_UNUSED(ctx); #endif - d->lastTexture = GLuint(-1); + d->lastTextureUsed = GLuint(-1); d->dirtyStencilRegion = QRect(0, 0, d->width, d->height); d->resetGLState(); @@ -783,12 +799,6 @@ void QGL2PaintEngineEx::endNativePainting() d->needsSync = true; } -const QGLContext *QGL2PaintEngineEx::context() -{ - Q_D(QGL2PaintEngineEx); - return d->ctx; -} - void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode) { if (newMode == mode) @@ -799,7 +809,7 @@ void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode) glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); glDisableVertexAttribArray(QT_OPACITY_ATTR); - lastTexture = GLuint(-1); + lastTextureUsed = GLuint(-1); } if (newMode == TextDrawingMode) { @@ -850,15 +860,16 @@ struct QGL2PEVectorPathCache qreal iscale; }; -void qopengl2paintengine_cleanup_vectorpath(QPaintEngineEx *engine, void *data) +void QGL2PaintEngineExPrivate::cleanupVectorPath(QPaintEngineEx *engine, void *data) { QGL2PEVectorPathCache *c = (QGL2PEVectorPathCache *) data; #ifdef QT_OPENGL_CACHE_AS_VBOS - QGL2PaintEngineExPrivate *d = QGL2PaintEngineExPrivate::getData((QGL2PaintEngineEx *) engine); - d->unusedVBOSToClean << c->vbo; + Q_ASSERT(engine->type() == QPaintEngine::OpenGL2); + static_cast<QGL2PaintEngineEx *>(engine)->d_func()->unusedVBOSToClean << c->vbo; if (c->ibo) d->unusedIBOSToClean << c->ibo; #else + Q_UNUSED(engine); qFree(c->vertices); qFree(c->indices); #endif @@ -870,6 +881,16 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) { transferMode(BrushDrawingMode); + const QOpenGL2PaintEngineState *s = q->state(); + const bool newAddOffset = !(s->renderHints & QPainter::Antialiasing) && + (qbrush_style(currentBrush) == Qt::SolidPattern) && + !multisamplingAlwaysEnabled; + + if (addOffset != newAddOffset) { + addOffset = newAddOffset; + matrixDirty = true; + } + // Might need to call updateMatrix to re-calculate inverseScale if (matrixDirty) updateMatrix(); @@ -911,7 +932,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) } } else { cache = new QGL2PEVectorPathCache; - data = const_cast<QVectorPath &>(path).addCacheData(q, cache, qopengl2paintengine_cleanup_vectorpath); + data = const_cast<QVectorPath &>(path).addCacheData(q, cache, cleanupVectorPath); updateCache = true; } @@ -1376,31 +1397,14 @@ void QGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush) { Q_D(QGL2PaintEngineEx); - Qt::BrushStyle style = qbrush_style(brush); - if (style == Qt::NoBrush) + if (qbrush_style(brush) == Qt::NoBrush) return; + if (!d->inRenderText) ensureActive(); - QOpenGL2PaintEngineState *s = state(); - bool doOffset = !(s->renderHints & QPainter::Antialiasing) && - (style == Qt::SolidPattern) && - !d->multisamplingAlwaysEnabled; - - if (doOffset) { - d->temporaryTransform = s->matrix; - QTransform tx = QTransform::fromTranslate(.49, .49); - s->matrix = s->matrix * tx; - d->matrixDirty = true; - } - d->setBrush(brush); d->fill(path); - - if (doOffset) { - s->matrix = d->temporaryTransform; - d->matrixDirty = true; - } } extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp @@ -1410,9 +1414,8 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) { Q_D(QGL2PaintEngineEx); - Qt::PenStyle penStyle = qpen_style(pen); const QBrush &penBrush = qpen_brush(pen); - if (penStyle == Qt::NoPen || qbrush_style(penBrush) == Qt::NoBrush) + if (qpen_style(pen) == Qt::NoPen || qbrush_style(penBrush) == Qt::NoBrush) return; QOpenGL2PaintEngineState *s = state(); @@ -1423,45 +1426,47 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) } ensureActive(); + d->setBrush(penBrush); + d->stroke(path, pen); +} - bool doOffset = !(s->renderHints & QPainter::Antialiasing) && !d->multisamplingAlwaysEnabled; - if (doOffset) { - d->temporaryTransform = s->matrix; - QTransform tx = QTransform::fromTranslate(0.49, .49); - s->matrix = s->matrix * tx; - d->matrixDirty = true; +void QGL2PaintEngineExPrivate::stroke(const QVectorPath &path, const QPen &pen) +{ + const QOpenGL2PaintEngineState *s = q->state(); + const bool newAddOffset = !(s->renderHints & QPainter::Antialiasing) && !multisamplingAlwaysEnabled; + if (addOffset != newAddOffset) { + addOffset = newAddOffset; + matrixDirty = true; } - bool opaque = penBrush.isOpaque() && s->opacity > 0.99; - d->setBrush(penBrush); - d->transferMode(BrushDrawingMode); + const Qt::PenStyle penStyle = qpen_style(pen); + const QBrush &penBrush = qpen_brush(pen); + const bool opaque = penBrush.isOpaque() && s->opacity > 0.99; + + transferMode(BrushDrawingMode); // updateMatrix() is responsible for setting the inverse scale on // the strokers, so we need to call it here and not wait for // prepareForDraw() down below. - d->updateMatrix(); + updateMatrix(); if (penStyle == Qt::SolidLine) { - d->stroker.process(path, pen); + stroker.process(path, pen); } else { // Some sort of dash - d->dasher.process(path, pen); + dasher.process(path, pen); - QVectorPath dashStroke(d->dasher.points(), - d->dasher.elementCount(), - d->dasher.elementTypes()); - d->stroker.process(dashStroke, pen); + QVectorPath dashStroke(dasher.points(), + dasher.elementCount(), + dasher.elementTypes()); + stroker.process(dashStroke, pen); } - - QGLContext *ctx = d->ctx; - Q_UNUSED(ctx); - if (opaque) { - d->prepareForDraw(opaque); + prepareForDraw(opaque); glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); - glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, false, 0, d->stroker.vertices()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, d->stroker.vertexCount() / 2); + glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, false, 0, stroker.vertices()); + glDrawArrays(GL_TRIANGLE_STRIP, 0, stroker.vertexCount() / 2); // QBrush b(Qt::green); // d->setBrush(&b); @@ -1479,30 +1484,25 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) : width; if (pen.isCosmetic()) - extra = extra * d->inverseScale; + extra = extra * inverseScale; QRectF bounds = path.controlPointRect().adjusted(-extra, -extra, extra, extra); - d->fillStencilWithVertexArray(d->stroker.vertices(), d->stroker.vertexCount() / 2, + fillStencilWithVertexArray(stroker.vertices(), stroker.vertexCount() / 2, 0, 0, bounds, QGL2PaintEngineExPrivate::TriStripStrokeFillMode); glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); // Pass when any bit is set, replace stencil value with 0 glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT); - d->prepareForDraw(false); + prepareForDraw(false); // Stencil the brush onto the dest buffer - d->composite(bounds); + composite(bounds); glStencilMask(0); - d->updateClipScissorTest(); - } - - if (doOffset) { - s->matrix = d->temporaryTransform; - d->matrixDirty = true; + updateClipScissorTest(); } } @@ -1542,7 +1542,7 @@ void QGL2PaintEngineEx::renderHintsChanged() #endif Q_D(QGL2PaintEngineEx); - d->lastTexture = GLuint(-1); + d->lastTextureUsed = GLuint(-1); d->brushTextureDirty = true; // qDebug("QGL2PaintEngineEx::renderHintsChanged() not implemented!"); } @@ -1711,6 +1711,11 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly if (textureCoordinateArray.data() != oldTextureCoordinateDataPtr) glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data()); + if (addOffset) { + addOffset = false; + matrixDirty = true; + } + QBrush pensBrush = q->state()->pen.brush(); setBrush(pensBrush); @@ -1808,20 +1813,31 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints) { + Q_D(QGL2PaintEngineEx); // Use fallback for extended composition modes. if (state()->composition_mode > QPainter::CompositionMode_Plus) { QPaintEngineEx::drawPixmaps(drawingData, dataCount, pixmap, hints); return; } - Q_D(QGL2PaintEngineEx); + ensureActive(); + d->drawPixmaps(drawingData, dataCount, pixmap, hints); +} + +void QGL2PaintEngineExPrivate::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints) +{ GLfloat dx = 1.0f / pixmap.size().width(); GLfloat dy = 1.0f / pixmap.size().height(); - d->vertexCoordinateArray.clear(); - d->textureCoordinateArray.clear(); - d->opacityArray.reset(); + vertexCoordinateArray.clear(); + textureCoordinateArray.clear(); + opacityArray.reset(); + + if (addOffset) { + addOffset = false; + matrixDirty = true; + } bool allOpaque = true; @@ -1838,31 +1854,28 @@ void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int d QGLPoint bottomRight(right * c - bottom * s, right * s + bottom * c); QGLPoint bottomLeft(-right * c - bottom * s, -right * s + bottom * c); - d->vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y()); - d->vertexCoordinateArray.lineToArray(-bottomLeft.x + drawingData[i].point.x(), -bottomLeft.y + drawingData[i].point.y()); - d->vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y()); - d->vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y()); - d->vertexCoordinateArray.lineToArray(bottomLeft.x + drawingData[i].point.x(), bottomLeft.y + drawingData[i].point.y()); - d->vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(-bottomLeft.x + drawingData[i].point.x(), -bottomLeft.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(bottomLeft.x + drawingData[i].point.x(), bottomLeft.y + drawingData[i].point.y()); + vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y()); QGLRect src(drawingData[i].source.left() * dx, drawingData[i].source.top() * dy, drawingData[i].source.right() * dx, drawingData[i].source.bottom() * dy); - d->textureCoordinateArray.lineToArray(src.right, src.bottom); - d->textureCoordinateArray.lineToArray(src.right, src.top); - d->textureCoordinateArray.lineToArray(src.left, src.top); - d->textureCoordinateArray.lineToArray(src.left, src.top); - d->textureCoordinateArray.lineToArray(src.left, src.bottom); - d->textureCoordinateArray.lineToArray(src.right, src.bottom); + textureCoordinateArray.lineToArray(src.right, src.bottom); + textureCoordinateArray.lineToArray(src.right, src.top); + textureCoordinateArray.lineToArray(src.left, src.top); + textureCoordinateArray.lineToArray(src.left, src.top); + textureCoordinateArray.lineToArray(src.left, src.bottom); + textureCoordinateArray.lineToArray(src.right, src.bottom); - qreal opacity = drawingData[i].opacity * state()->opacity; - d->opacityArray << opacity << opacity << opacity << opacity << opacity << opacity; + qreal opacity = drawingData[i].opacity * q->state()->opacity; + opacityArray << opacity << opacity << opacity << opacity << opacity << opacity; allOpaque &= (opacity >= 0.99f); } - ensureActive(); - - QGLContext *ctx = d->ctx; glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); QGLTexture *texture = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption @@ -1870,27 +1883,28 @@ void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int d if (texture->options & QGLContext::InvertedYBindOption) { // Flip texture y-coordinate. - QGLPoint *data = d->textureCoordinateArray.data(); + QGLPoint *data = textureCoordinateArray.data(); for (int i = 0; i < 6 * dataCount; ++i) data[i].y = 1 - data[i].y; } - d->transferMode(ImageArrayDrawingMode); + transferMode(ImageArrayDrawingMode); bool isBitmap = pixmap.isQBitmap(); bool isOpaque = !isBitmap && (!pixmap.hasAlphaChannel() || (hints & QDrawPixmaps::OpaqueHint)) && allOpaque; - d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, - state()->renderHints & QPainter::SmoothPixmapTransform, texture->id); + updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, + q->state()->renderHints & QPainter::SmoothPixmapTransform, texture->id); // Setup for texture drawing - d->shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc); - if (d->prepareForDraw(isOpaque)) - d->shaderManager->currentProgram()->setUniformValue(d->location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); + currentBrush = noBrush; + shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc); + if (prepareForDraw(isOpaque)) + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); if (isBitmap) { - QColor col = qt_premultiplyColor(state()->pen.color(), (GLfloat)state()->opacity); - d->shaderManager->currentProgram()->setUniformValue(d->location(QGLEngineShaderManager::PatternColor), col); + QColor col = qt_premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col); } glDrawArrays(GL_TRIANGLES, 0, 6 * dataCount); @@ -1922,7 +1936,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) d->compositionModeDirty = true; d->opacityUniformDirty = true; d->needsSync = true; - d->use_system_clip = !systemClip().isEmpty(); + d->useSystemClip = !systemClip().isEmpty(); d->currentBrush = QBrush(); d->dirtyStencilRegion = QRect(0, 0, d->width, d->height); @@ -2047,12 +2061,12 @@ void QGL2PaintEngineExPrivate::updateClipScissorTest() #else QRect bounds = q->state()->rectangleClip; if (!q->state()->clipEnabled) { - if (use_system_clip) + if (useSystemClip) bounds = systemClip.boundingRect(); else bounds = QRect(0, 0, width, height); } else { - if (use_system_clip) + if (useSystemClip) bounds = bounds.intersected(systemClip.boundingRect()); else bounds = bounds.intersected(QRect(0, 0, width, height)); @@ -2107,6 +2121,11 @@ void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint value) { transferMode(BrushDrawingMode); + if (addOffset) { + addOffset = false; + matrixDirty = true; + } + if (matrixDirty) updateMatrix(); @@ -2206,7 +2225,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) switch (op) { case Qt::NoClip: - if (d->use_system_clip) { + if (d->useSystemClip) { state()->clipTestEnabled = true; state()->currentClip = 1; } else { @@ -2278,13 +2297,13 @@ void QGL2PaintEngineExPrivate::systemStateChanged() q->state()->clipChanged = true; if (systemClip.isEmpty()) { - use_system_clip = false; + useSystemClip = false; } else { if (q->paintDevice()->devType() == QInternal::Widget && currentClipWidget) { QWidgetPrivate *widgetPrivate = qt_widget_private(currentClipWidget->window()); - use_system_clip = widgetPrivate->extra && widgetPrivate->extra->inRenderWithPainter; + useSystemClip = widgetPrivate->extra && widgetPrivate->extra->inRenderWithPainter; } else { - use_system_clip = true; + useSystemClip = true; } } @@ -2294,19 +2313,19 @@ void QGL2PaintEngineExPrivate::systemStateChanged() q->state()->currentClip = 1; maxClip = 1; - q->state()->rectangleClip = use_system_clip ? systemClip.boundingRect() : QRect(0, 0, width, height); + q->state()->rectangleClip = useSystemClip ? systemClip.boundingRect() : QRect(0, 0, width, height); updateClipScissorTest(); if (systemClip.rectCount() == 1) { if (systemClip.boundingRect() == QRect(0, 0, width, height)) - use_system_clip = false; + useSystemClip = false; #ifndef QT_GL_NO_SCISSOR_TEST // scissoring takes care of the system clip return; #endif } - if (use_system_clip) { + if (useSystemClip) { clearClip(0); QPainterPath path; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index c78b011..0746221 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -105,13 +105,8 @@ public: ~QGL2PaintEngineEx(); bool begin(QPaintDevice *device); - bool end(); - void ensureActive(); - - 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); + bool end(); virtual void clipEnabledChanged(); virtual void penChanged(); @@ -122,20 +117,21 @@ public: virtual void renderHintsChanged(); virtual void transformChanged(); - + virtual void drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr); virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); + virtual void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints); virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags = Qt::AutoColor); - virtual void drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr); - virtual void drawTextItem(const QPointF &p, const QTextItem &textItem); + 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 drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints); Type type() const { return OpenGL2; } - void setState(QPainterState *s); - QPainterState *createState(QPainterState *orig) const; + virtual void setState(QPainterState *s); + virtual QPainterState *createState(QPainterState *orig) const; inline QOpenGL2PaintEngineState *state() { return static_cast<QOpenGL2PaintEngineState *>(QPaintEngineEx::state()); } @@ -146,8 +142,6 @@ public: void beginNativePainting(); void endNativePainting(); - const QGLContext* context(); - QPixmapFilter *pixmapFilter(int type, const QPixmapFilter *prototype); void setRenderTextActive(bool); @@ -169,10 +163,12 @@ public: QGL2PaintEngineExPrivate(QGL2PaintEngineEx *q_ptr) : q(q_ptr), + shaderManager(0), width(0), height(0), ctx(0), + useSystemClip(true), + addOffset(false), inverseScale(1), - shaderManager(0), inRenderText(false) { } @@ -184,45 +180,62 @@ public: void updateCompositionMode(); void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = -1); - void setBrush(const QBrush& brush); - - void transferMode(EngineMode newMode); void resetGLState(); - // fill, drawOutline, drawTexture & drawCachedGlyphs are the rendering entry points: + // fill, stroke, drawTexture, drawPixmaps & drawCachedGlyphs are the main rendering entry-points, + // however writeClip can also be thought of as en entry point as it does similar things. void fill(const QVectorPath &path); + void stroke(const QVectorPath &path, const QPen &pen); void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false); + void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints); void drawCachedGlyphs(const QPointF &p, QFontEngineGlyphCache::Type glyphType, const QTextItemInt &ti); + // draws whatever is in the vertex array: void drawVertexArrays(const float *data, int *stops, int stopCount, GLenum primitive); void drawVertexArrays(QGL2PEXVertexArray &vertexArray, GLenum primitive) { drawVertexArrays((const float *) vertexArray.data(), vertexArray.stops(), vertexArray.stopCount(), primitive); } - // ^ draws whatever is in the vertex array + // Composites the bounding rect onto dest buffer: void composite(const QGLRect& boundingRect); - // ^ Composites the bounding rect onto dest buffer + // Calls drawVertexArrays to render into stencil buffer: void fillStencilWithVertexArray(const float *data, int count, int *stops, int stopCount, const QGLRect &bounds, StencilFillMode mode); void fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill) { fillStencilWithVertexArray((const float *) vertexArray.data(), 0, vertexArray.stops(), vertexArray.stopCount(), vertexArray.boundingRect(), useWindingFill ? WindingFillMode : OddEvenFillMode); } - // ^ Calls drawVertexArrays to render into stencil buffer - - bool prepareForDraw(bool srcPixelsAreOpaque); - // ^ returns whether the current program changed or not + void setBrush(const QBrush& brush); + void transferMode(EngineMode newMode); + bool prepareForDraw(bool srcPixelsAreOpaque); // returns true if the program has changed inline void useSimpleShader(); + inline GLuint location(const QGLEngineShaderManager::Uniform uniform) { + return shaderManager->getUniformLocation(uniform); + } + void prepareDepthRangeForRenderText(); void restoreDepthRangeForRenderText(); + void clearClip(uint value); + void writeClip(const QVectorPath &path, uint value); + void resetClipIfNeeded(); + + void updateClipScissorTest(); + void setScissor(const QRect &rect); + void regenerateClip(); + void systemStateChanged(); + + static QGLEngineShaderManager* shaderManagerForEngine(QGL2PaintEngineEx *engine) { return engine->d_func()->shaderManager; } static QGL2PaintEngineExPrivate *getData(QGL2PaintEngineEx *engine) { return engine->d_func(); } + static void cleanupVectorPath(QPaintEngineEx *engine, void *data); + QGL2PaintEngineEx* q; + QGLEngineShaderManager* shaderManager; QGLPaintDevice* device; int width, height; QGLContext *ctx; @@ -239,41 +252,25 @@ public: bool opacityUniformDirty; bool stencilClean; // Has the stencil not been used for clipping so far? + bool useSystemClip; QRegion dirtyStencilRegion; QRect currentScissorBounds; uint maxClip; QBrush currentBrush; // May not be the state's brush! - - GLfloat inverseScale; + const QBrush noBrush; QGL2PEXVertexArray vertexCoordinateArray; QGL2PEXVertexArray textureCoordinateArray; QDataBuffer<GLfloat> opacityArray; - GLfloat staticVertexCoordinateArray[8]; GLfloat staticTextureCoordinateArray[8]; + bool addOffset; // When enabled, adds a 0.49,0.49 offset to matrix in updateMatrix GLfloat pmvMatrix[3][3]; + GLfloat inverseScale; - QGLEngineShaderManager* shaderManager; - - void clearClip(uint value); - void writeClip(const QVectorPath &path, uint value); - void resetClipIfNeeded(); - - void updateClipScissorTest(); - void setScissor(const QRect &rect); - void regenerateClip(); - void systemStateChanged(); - uint use_system_clip : 1; - - uint location(QGLEngineShaderManager::Uniform uniform) - { - return shaderManager->getUniformLocation(uniform); - } - - GLuint lastTexture; + GLuint lastTextureUsed; bool needsSync; bool inRenderText; @@ -285,7 +282,6 @@ public: QTriangulatingStroker stroker; QDashedStrokeProcessor dasher; - QTransform temporaryTransform; QScopedPointer<QPixmapFilter> convolutionFilter; QScopedPointer<QPixmapFilter> colorizeFilter; diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp index ed7fdff..8dae02a 100644 --- a/src/opengl/qpaintengine_opengl.cpp +++ b/src/opengl/qpaintengine_opengl.cpp @@ -4522,6 +4522,12 @@ typedef QHash<QFontEngine*, QGLGlyphHash*> QGLFontGlyphHash; typedef QHash<quint64, QGLFontTexture*> QGLFontTexHash; typedef QHash<const QGLContext*, QGLFontGlyphHash*> QGLContextHash; +static inline void qt_delete_glyph_hash(QGLGlyphHash *hash) +{ + qDeleteAll(*hash); + delete hash; +} + class QGLGlyphCache : public QObject { Q_OBJECT @@ -4562,7 +4568,7 @@ void QGLGlyphCache::fontEngineDestroyed(QObject *o) if (font_cache->find(fe) != font_cache->end()) { ctx = keys.at(i); QGLGlyphHash *cache = font_cache->take(fe); - delete cache; + qt_delete_glyph_hash(cache); break; } } @@ -4599,7 +4605,7 @@ void QGLGlyphCache::cleanupContext(const QGLContext *ctx) QList<QFontEngine *> keys = font_cache->keys(); for (int i=0; i < keys.size(); ++i) { QFontEngine *fe = keys.at(i); - delete font_cache->take(fe); + qt_delete_glyph_hash(font_cache->take(fe)); quint64 font_key = (reinterpret_cast<quint64>(ctx) << 32) | reinterpret_cast<quint64>(fe); QGLFontTexture *font_tex = qt_font_textures.take(font_key); if (font_tex) { @@ -4640,7 +4646,9 @@ void QGLGlyphCache::cleanCache() QList<const QGLContext *> keys = qt_context_cache.keys(); for (int i=0; i < keys.size(); ++i) { QGLFontGlyphHash *font_cache = qt_context_cache.value(keys.at(i)); - qDeleteAll(*font_cache); + QGLFontGlyphHash::Iterator it = font_cache->begin(); + for (; it != font_cache->end(); ++it) + qt_delete_glyph_hash(it.value()); font_cache->clear(); } qDeleteAll(qt_context_cache); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 4744eb6..bb26d29 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -1063,7 +1063,7 @@ static inline bool setIntOption(const QStringList &arguments, const QString &var static inline QColor colorFromName(const QString &name) { - QRegExp rx("#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])"); + QRegExp rx(QLatin1String("#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])")); rx.setCaseSensitivity(Qt::CaseInsensitive); if (rx.exactMatch(name)) { Q_ASSERT(rx.captureCount() == 4); @@ -1278,7 +1278,14 @@ bool QDirectFBScreen::connect(const QString &displaySpec) #ifdef QT_NO_DIRECTFB_WM result = d_ptr->primarySurface->GetSize(d_ptr->primarySurface, &w, &h); #elif (Q_DIRECTFB_VERSION >= 0x010000) - result = d_ptr->dfbScreen->GetSize(d_ptr->dfbScreen, &w, &h); + IDirectFBSurface *layerSurface; + if (d_ptr->dfbLayer->GetSurface(d_ptr->dfbLayer, &layerSurface) != DFB_OK) { + result = layerSurface->GetSize(layerSurface, &w, &h); + layerSurface->Release(layerSurface); + } + if (w <= 0 || h <= 0) { + result = d_ptr->dfbScreen->GetSize(d_ptr->dfbScreen, &w, &h); + } #else qWarning("QDirectFBScreen::connect: DirectFB versions prior to 1.0 do not offer a way\n" "query the size of the primary surface in windowed mode. You have to specify\n" diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp index c95b63c..dee0e52 100644 --- a/src/plugins/imageformats/gif/qgifhandler.cpp +++ b/src/plugins/imageformats/gif/qgifhandler.cpp @@ -54,6 +54,10 @@ QT_BEGIN_NAMESPACE #define Q_TRANSPARENT 0x00ffffff +// avoid going through QImage::scanLine() which calls detach +#define FAST_SCAN_LINE(bits, bpl, y) (bits + (y) * bpl) + + /* Incremental image decoder for GIF image format. @@ -135,7 +139,7 @@ private: int frame; bool out_of_bounds; bool digress; - void nextY(QImage *image); + void nextY(unsigned char *bits, int bpl); void disposePrevious(QImage *image); }; @@ -232,6 +236,10 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, // CompuServe Incorporated. GIF(sm) is a Service Mark property of // CompuServe Incorporated." + image->detach(); + int bpl = image->bytesPerLine(); + unsigned char *bits = image->bits(); + #define LM(l, m) (((m)<<8)|l) digress = false; const int initial = length; @@ -335,7 +343,9 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, QImage::Format format = trans_index >= 0 ? QImage::Format_ARGB32 : QImage::Format_RGB32; if (image->isNull()) { (*image) = QImage(swidth, sheight, format); - memset(image->bits(), 0, image->byteCount()); + bpl = image->bytesPerLine(); + bits = image->bits(); + memset(bits, 0, image->byteCount()); // ### size of the upcoming frame, should rather // be known before decoding it. @@ -393,11 +403,13 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, backingstore = QImage(qMax(backingstore.width(), w), qMax(backingstore.height(), h), QImage::Format_RGB32); - memset(image->bits(), 0, image->byteCount()); + memset(bits, 0, image->byteCount()); } + const int dest_bpl = backingstore.bytesPerLine(); + unsigned char *dest_data = backingstore.bits(); for (int ln=0; ln<h; ln++) { - memcpy(backingstore.scanLine(ln), - image->scanLine(t+ln)+l, w*sizeof(QRgb)); + memcpy(FAST_SCAN_LINE(dest_data, dest_bpl, ln), + FAST_SCAN_LINE(bits, bpl, t+ln) + l, w*sizeof(QRgb)); } } @@ -470,14 +482,14 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, if (needfirst) { firstcode=oldcode=code; if (!out_of_bounds && image->height() > y && firstcode!=trans_index) - ((QRgb*)image->scanLine(y))[x] = color(firstcode); + ((QRgb*)FAST_SCAN_LINE(bits, bpl, y))[x] = color(firstcode); x++; if (x>=swidth) out_of_bounds = true; needfirst=false; if (x>=left+width) { x=left; out_of_bounds = left>=swidth || y>=sheight; - nextY(image); + nextY(bits, bpl); } } else { incode=code; @@ -515,7 +527,7 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, const QRgb *map = lcmap ? localcmap : globalcmap; QRgb *line = 0; if (!out_of_bounds && h > y) - line = (QRgb*)image->scanLine(y); + line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y); while (sp>stack) { const uchar index = *(--sp); if (!out_of_bounds && h > y && index!=trans_index) { @@ -529,9 +541,9 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, if (x>=left+width) { x=left; out_of_bounds = left>=swidth || y>=sheight; - nextY(image); + nextY(bits, bpl); if (!out_of_bounds && h > y) - line = (QRgb*)image->scanLine(y); + line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y); } } } @@ -644,7 +656,7 @@ void QGIFFormat::fillRect(QImage *image, int col, int row, int w, int h, QRgb co } } -void QGIFFormat::nextY(QImage *image) +void QGIFFormat::nextY(unsigned char *bits, int bpl) { int my; switch (interlace) { @@ -660,7 +672,7 @@ void QGIFFormat::nextY(QImage *image) // Don't dup with transparency if (trans_index < 0) { for (i=1; i<=my; i++) { - memcpy(image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb), + memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb), (right-left+1)*sizeof(QRgb)); } } @@ -689,7 +701,7 @@ void QGIFFormat::nextY(QImage *image) // Don't dup with transparency if (trans_index < 0) { for (i=1; i<=my; i++) { - memcpy(image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb), + memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb), (right-left+1)*sizeof(QRgb)); } } @@ -713,7 +725,7 @@ void QGIFFormat::nextY(QImage *image) // Don't dup with transparency if (trans_index < 0) { for (i=1; i<=my; i++) { - memcpy(image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb), + memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb), (right-left+1)*sizeof(QRgb)); } } diff --git a/src/s60installs/qt.iby b/src/s60installs/qt.iby index 41eb562..f24ac4b 100644 --- a/src/s60installs/qt.iby +++ b/src/s60installs/qt.iby @@ -90,27 +90,27 @@ file=ABI_DIR\BUILD_DIR\qts60plugin_5_0.dll SHARED_LIB_DIR\qts60plugin_5_0.dll S60_APP_RESOURCE(s60main) // imageformats stubs -data=\epoc32\winscw\c\resource\qt\plugins\imageformats\qgif.qtplugin resource\qt\plugins\imageformats\qgif.qtplugin -data=\epoc32\winscw\c\resource\qt\plugins\imageformats\qico.qtplugin resource\qt\plugins\imageformats\qico.qtplugin -data=\epoc32\winscw\c\resource\qt\plugins\imageformats\qjpeg.qtplugin resource\qt\plugins\imageformats\qjpeg.qtplugin -data=\epoc32\winscw\c\resource\qt\plugins\imageformats\qmng.qtplugin resource\qt\plugins\imageformats\qmng.qtplugin -data=\epoc32\winscw\c\resource\qt\plugins\imageformats\qsvg.qtplugin resource\qt\plugins\imageformats\qsvg.qtplugin -data=\epoc32\winscw\c\resource\qt\plugins\imageformats\qtiff.qtplugin resource\qt\plugins\imageformats\qtiff.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qgif.qtplugin resource\qt\plugins\imageformats\qgif.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qico.qtplugin resource\qt\plugins\imageformats\qico.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qjpeg.qtplugin resource\qt\plugins\imageformats\qjpeg.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qmng.qtplugin resource\qt\plugins\imageformats\qmng.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qsvg.qtplugin resource\qt\plugins\imageformats\qsvg.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qtiff.qtplugin resource\qt\plugins\imageformats\qtiff.qtplugin // codecs stubs -data=\epoc32\winscw\c\resource\qt\plugins\codecs\qcncodecs.qtplugin resource\qt\plugins\codecs\qcncodecs.qtplugin -data=\epoc32\winscw\c\resource\qt\plugins\codecs\qjpcodecs.qtplugin resource\qt\plugins\codecs\qjpcodecs.qtplugin -data=\epoc32\winscw\c\resource\qt\plugins\codecs\qkrcodecs.qtplugin resource\qt\plugins\codecs\qkrcodecs.qtplugin -data=\epoc32\winscw\c\resource\qt\plugins\codecs\qtwcodecs.qtplugin resource\qt\plugins\codecs\qtwcodecs.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qcncodecs.qtplugin resource\qt\plugins\codecs\qcncodecs.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qjpcodecs.qtplugin resource\qt\plugins\codecs\qjpcodecs.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qkrcodecs.qtplugin resource\qt\plugins\codecs\qkrcodecs.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qtwcodecs.qtplugin resource\qt\plugins\codecs\qtwcodecs.qtplugin // iconengines stubs -data=\epoc32\winscw\c\resource\qt\plugins\iconengines\qsvgicon.qtplugin resource\qt\plugins\iconengines\qsvgicon.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qsvgicon.qtplugin resource\qt\plugins\iconengines\qsvgicon.qtplugin // Phonon MMF backend -data=\epoc32\winscw\c\resource\qt\plugins\phonon_backend\phonon_mmf.qtplugin resource\qt\plugins\phonon_backend\phonon_mmf.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\phonon_mmf.qtplugin resource\qt\plugins\phonon_backend\phonon_mmf.qtplugin // graphicssystems -data=\epoc32\winscw\c\resource\qt\plugins\graphicssystems\qvggraphicssystem.qtplugin resource\qt\plugins\graphicssystems\qvggraphicssystem.qtplugin +data=\epoc32\data\qt\qtlibspluginstubs\qvggraphicssystem.qtplugin resource\qt\plugins\graphicssystems\qvggraphicssystem.qtplugin // Stub sis file data=ZSYSTEM\install\qt.sis System\Install\qt.sis diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index 37adfa9..e024396 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -105,10 +105,6 @@ symbian: { qtlibraries.sources += QtDeclarative.dll } - contains(QT_CONFIG, webkit): { - qtlibraries.sources += QtWebKit.dll - } - graphicssystems_plugins.path = c:$$QT_PLUGINS_BASE_DIR/graphicssystems contains(QT_CONFIG, openvg) { qtlibraries.sources += QtOpenVG.dll @@ -117,4 +113,9 @@ symbian: { BLD_INF_RULES.prj_exports += "qt.iby $$CORE_MW_LAYER_IBY_EXPORT_PATH(qt.iby)" BLD_INF_RULES.prj_exports += "qtdemoapps.iby $$CORE_APP_LAYER_IBY_EXPORT_PATH(qtdemoapps.iby)" + PLUGIN_STUBS = $$files(qmakepluginstubs/*) + for(STUB, PLUGIN_STUBS) { + STUB_FILENAME = $$basename(STUB) + BLD_INF_RULES.prj_exports += "qmakepluginstubs/$${STUB_FILENAME} /epoc32/data/qt/qtlibspluginstubs/$${STUB_FILENAME}" + } } diff --git a/tests/auto/qfileinfo/tst_qfileinfo.cpp b/tests/auto/qfileinfo/tst_qfileinfo.cpp index 77172fe..0ced51e 100644 --- a/tests/auto/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/qfileinfo/tst_qfileinfo.cpp @@ -1087,8 +1087,8 @@ void tst_QFileInfo::isHidden_data() #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) QTest::newRow("C:/RECYCLER") << QString::fromLatin1("C:/RECYCLER") << true; - QTest::newRow("C:/RECYCLER/.") << QString::fromLatin1("C:/RECYCLER/.") << false; - QTest::newRow("C:/RECYCLER/..") << QString::fromLatin1("C:/RECYCLER/..") << false; + QTest::newRow("C:/RECYCLER/.") << QString::fromLatin1("C:/RECYCLER/.") << true; + QTest::newRow("C:/RECYCLER/..") << QString::fromLatin1("C:/RECYCLER/..") << true; #endif #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) @@ -1096,13 +1096,9 @@ void tst_QFileInfo::isHidden_data() && !QDir().mkdir("./.hidden-directory")) qWarning("Unable to create directory './.hidden-directory'. Some tests will fail."); - QTest::newRow("./.hidden-directory") << QString("./.hidden-directory") << true; - QTest::newRow("./.hidden-directory/.") << QString("./.hidden-directory/.") << false; - QTest::newRow("./.hidden-directory/..") << QString("./.hidden-directory/..") << false; - QTest::newRow("/path/to/.hidden-directory") << QDir::currentPath() + QString("/.hidden-directory") << true; - QTest::newRow("/path/to/.hidden-directory/.") << QDir::currentPath() + QString("/.hidden-directory/.") << false; - QTest::newRow("/path/to/.hidden-directory/..") << QDir::currentPath() + QString("/.hidden-directory/..") << false; + QTest::newRow("/path/to/.hidden-directory/.") << QDir::currentPath() + QString("/.hidden-directory/.") << true; + QTest::newRow("/path/to/.hidden-directory/..") << QDir::currentPath() + QString("/.hidden-directory/..") << true; #endif #if defined(Q_OS_MAC) diff --git a/tests/auto/qimagereader/images/endless-anim.gif b/tests/auto/qimagereader/images/endless-anim.gif Binary files differnew file mode 100644 index 0000000..00df8da --- /dev/null +++ b/tests/auto/qimagereader/images/endless-anim.gif diff --git a/tests/auto/qimagereader/images/four-frames.gif b/tests/auto/qimagereader/images/four-frames.gif Binary files differnew file mode 100644 index 0000000..6aff2e0 --- /dev/null +++ b/tests/auto/qimagereader/images/four-frames.gif diff --git a/tests/auto/qimagereader/qimagereader.qrc b/tests/auto/qimagereader/qimagereader.qrc index 11b9406..58f2f74 100644 --- a/tests/auto/qimagereader/qimagereader.qrc +++ b/tests/auto/qimagereader/qimagereader.qrc @@ -57,5 +57,7 @@ <file>images/qt6.gif</file> <file>images/qt7.gif</file> <file>images/qt8.gif</file> + <file>images/endless-anim.gif</file> + <file>images/four-frames.gif</file> </qresource> </RCC> diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp index 630cc03..8cfaac5 100644 --- a/tests/auto/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/qimagereader/tst_qimagereader.cpp @@ -141,6 +141,7 @@ private slots: #if defined QTEST_HAVE_GIF void gifHandlerBugs(); void animatedGif(); + void gifImageCount(); #endif void readCorruptImage_data(); @@ -725,6 +726,13 @@ void tst_QImageReader::gifHandlerBugs() QVERIFY(!im1.isNull()); QVERIFY(!im2.isNull()); QCOMPARE(im1.convertToFormat(QImage::Format_ARGB32), im2.convertToFormat(QImage::Format_ARGB32)); } + + // Check the undocumented feature. + { + QImageReader io(prefix + "endless-anim.gif"); + QVERIFY(io.canRead()); + QCOMPARE(io.loopCount(), -1); + } } void tst_QImageReader::animatedGif() @@ -739,6 +747,136 @@ void tst_QImageReader::animatedGif() image = io.read(); } } + +// http://bugreports.qt.nokia.com/browse/QTBUG-6696 +// Check the count of images in various call orders... +void tst_QImageReader::gifImageCount() +{ + // just read every frame... and see how much we got.. + { + QImageReader io(":images/four-frames.gif"); + + QVERIFY(io.canRead()); + QImage blackFrame = io.read(); + + QVERIFY(io.canRead()); + QImage whiteFrame = io.read(); + + QVERIFY(io.canRead()); + QImage greenFrame = io.read(); + + QVERIFY(io.canRead()); + QImage blueFrame = io.read(); + + QVERIFY(!io.canRead()); + QImage emptyFrame = io.read(); + + QVERIFY(!io.canRead()); + QCOMPARE(blackFrame.pixel(0,0), qRgb(0, 0, 0)); + QCOMPARE(blackFrame.size(), QSize(64,64)); + + QCOMPARE(whiteFrame.pixel(0,0), qRgb(0xff, 0xff, 0xff)); + QCOMPARE(whiteFrame.size(), QSize(64,64)); + + QCOMPARE(greenFrame.pixel(0,0), qRgb(0x0, 0xff, 0x0)); + QCOMPARE(greenFrame.size(), QSize(64,64)); + + QCOMPARE(blueFrame.pixel(0,0), qRgb(0x0, 0x0, 0xff)); + QCOMPARE(blueFrame.size(), QSize(64,64)); + QVERIFY(emptyFrame.isNull()); + } + + // Read and get the size + { + QImageReader io(":images/four-frames.gif"); + + QVERIFY(io.canRead()); + QCOMPARE(io.size(), QSize(64,64)); + + QVERIFY(io.canRead()); + QCOMPARE(io.size(), QSize(64,64)); + QCOMPARE(io.size(), QSize(64,64)); + QVERIFY(io.canRead()); + QImage blackFrame = io.read(); + + QVERIFY(io.canRead()); + QCOMPARE(io.size(), QSize(64,64)); + QCOMPARE(io.size(), QSize(64,64)); + QVERIFY(io.canRead()); + QImage whiteFrame = io.read(); + + QVERIFY(io.canRead()); + QCOMPARE(io.size(), QSize(64,64)); + QCOMPARE(io.size(), QSize(64,64)); + QVERIFY(io.canRead()); + QImage greenFrame = io.read(); + + QVERIFY(io.canRead()); + QCOMPARE(io.size(), QSize(64,64)); + QCOMPARE(io.size(), QSize(64,64)); + QVERIFY(io.canRead()); + QImage blueFrame = io.read(); + + QVERIFY(!io.canRead()); + QCOMPARE(io.size(), QSize()); + QCOMPARE(io.size(), QSize()); + QVERIFY(!io.canRead()); + QImage emptyFrame = io.read(); + + QVERIFY(!io.canRead()); + QCOMPARE(blackFrame.pixel(0,0), qRgb(0, 0, 0)); + QCOMPARE(blackFrame.size(), QSize(64,64)); + + QCOMPARE(whiteFrame.pixel(0,0), qRgb(0xff, 0xff, 0xff)); + QCOMPARE(whiteFrame.size(), QSize(64,64)); + + QCOMPARE(greenFrame.pixel(0,0), qRgb(0x0, 0xff, 0x0)); + QCOMPARE(greenFrame.size(), QSize(64,64)); + + QCOMPARE(blueFrame.pixel(0,0), qRgb(0x0, 0x0, 0xff)); + QCOMPARE(blueFrame.size(), QSize(64,64)); + QVERIFY(emptyFrame.isNull()); + } + + // Do a Size query as substitute for canRead + { + QImageReader io(":images/four-frames.gif"); + + QCOMPARE(io.size(), QSize(64,64)); + QCOMPARE(io.size(), QSize(64,64)); + QImage blackFrame = io.read(); + + QCOMPARE(io.size(), QSize(64,64)); + QCOMPARE(io.size(), QSize(64,64)); + QImage whiteFrame = io.read(); + + QCOMPARE(io.size(), QSize(64,64)); + QCOMPARE(io.size(), QSize(64,64)); + QImage greenFrame = io.read(); + + QCOMPARE(io.size(), QSize(64,64)); + QCOMPARE(io.size(), QSize(64,64)); + QImage blueFrame = io.read(); + + QCOMPARE(io.size(), QSize()); + QVERIFY(!io.canRead()); + QImage emptyFrame = io.read(); + + QVERIFY(!io.canRead()); + QCOMPARE(blackFrame.pixel(0,0), qRgb(0, 0, 0)); + QCOMPARE(blackFrame.size(), QSize(64,64)); + + QCOMPARE(whiteFrame.pixel(0,0), qRgb(0xff, 0xff, 0xff)); + QCOMPARE(whiteFrame.size(), QSize(64,64)); + + QCOMPARE(greenFrame.pixel(0,0), qRgb(0x0, 0xff, 0x0)); + QCOMPARE(greenFrame.size(), QSize(64,64)); + + QCOMPARE(blueFrame.pixel(0,0), qRgb(0x0, 0x0, 0xff)); + QCOMPARE(blueFrame.size(), QSize(64,64)); + QVERIFY(emptyFrame.isNull()); + } +} #endif class Server : public QObject diff --git a/tests/auto/qurl/tst_qurl.cpp b/tests/auto/qurl/tst_qurl.cpp index 03e77aa..70cfb61 100644 --- a/tests/auto/qurl/tst_qurl.cpp +++ b/tests/auto/qurl/tst_qurl.cpp @@ -1682,6 +1682,12 @@ void tst_QUrl::toString_constructed_data() << QByteArray("//qt.nokia.com/index.html"); QTest::newRow("data2") << QString::fromLatin1("file") << n << n << n << -1 << QString::fromLatin1("/root") << QByteArray() << n << QString::fromLatin1("file:///root") << QByteArray("file:///root"); + QTest::newRow("userAndPass") << QString::fromLatin1("http") << QString::fromLatin1("dfaure") << QString::fromLatin1("kde") + << "kde.org" << 443 << QString::fromLatin1("/") << QByteArray() << n + << QString::fromLatin1("http://dfaure:kde@kde.org:443/") << QByteArray("http://dfaure:kde@kde.org:443/"); + QTest::newRow("PassWithoutUser") << QString::fromLatin1("http") << n << QString::fromLatin1("kde") + << "kde.org" << 443 << QString::fromLatin1("/") << QByteArray() << n + << QString::fromLatin1("http://:kde@kde.org:443/") << QByteArray("http://:kde@kde.org:443/"); } void tst_QUrl::toString_constructed() @@ -1717,6 +1723,7 @@ void tst_QUrl::toString_constructed() QVERIFY(url.isValid()); QCOMPARE(url.toString(), asString); + QCOMPARE(QString::fromLatin1(url.toEncoded()), QString::fromLatin1(asEncoded)); // readable in case of differences QCOMPARE(url.toEncoded(), asEncoded); } diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 3e14b56..2d04cc5 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -66,6 +66,8 @@ #include <private/qapplication_p.h> #include <qcalendarwidget.h> #include <qmainwindow.h> +#include <qdockwidget.h> +#include <qtoolbar.h> #include <QtGui/qpaintengine.h> #include <private/qbackingstore_p.h> @@ -356,6 +358,7 @@ private slots: void paintOnScreenPossible(); #endif void reparentStaticWidget(); + void QTBUG6883_reparentStaticWidget2(); #ifdef Q_WS_QWS void updateOutsideSurfaceClip(); #endif @@ -8728,6 +8731,31 @@ void tst_QWidget::reparentStaticWidget() // Please don't crash. paintOnScreen.resize(paintOnScreen.size() + QSize(2, 2)); QTest::qWait(20); + +} + +void tst_QWidget::QTBUG6883_reparentStaticWidget2() +{ + QMainWindow mw; + QDockWidget *one = new QDockWidget("one", &mw); + mw.addDockWidget(Qt::LeftDockWidgetArea, one , Qt::Vertical); + + QWidget *child = new QWidget(); + child->setPalette(Qt::red); + child->setAutoFillBackground(true); + child->setAttribute(Qt::WA_StaticContents); + child->resize(100, 100); + one->setWidget(child); + + QToolBar *mainTools = mw.addToolBar("Main Tools"); + mainTools->addWidget(new QLineEdit); + + mw.show(); + QTest::qWaitForWindowShown(&mw); + + one->setFloating(true); + QTest::qWait(20); + //do not crash } #ifdef Q_WS_QWS @@ -9726,7 +9754,7 @@ public: void deleteBackingStore() { if (static_cast<QWidgetPrivate*>(d_ptr.data())->maybeBackingStore()) { - delete static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStore; + delete static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStore; static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStore = 0; } } diff --git a/tests/auto/uiloader/baseline/css_qtbug6855.ui b/tests/auto/uiloader/baseline/css_qtbug6855.ui new file mode 100644 index 0000000..0727f6b --- /dev/null +++ b/tests/auto/uiloader/baseline/css_qtbug6855.ui @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Form</class> + <widget class="QWidget" name="Form"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>212</width> + <height>108</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <property name="styleSheet"> + <string notr="true">QPushButton { padding: 20px; }</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QPushButton" name="pushButton"> + <property name="text"> + <string>Text not cropped</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>258</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>218</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/tests/benchmarks/benchmarks.pro b/tests/benchmarks/benchmarks.pro index bb20dcf..0f760a1 100644 --- a/tests/benchmarks/benchmarks.pro +++ b/tests/benchmarks/benchmarks.pro @@ -5,6 +5,7 @@ SUBDIRS = containers-associative \ qbytearray \ qfileinfo \ qfile_vs_qnetworkaccessmanager \ + qhostinfo \ qpainter \ qtestlib-simple events \ qiodevice \ diff --git a/tests/benchmarks/qhostinfo/main.cpp b/tests/benchmarks/qhostinfo/main.cpp new file mode 100644 index 0000000..389443b --- /dev/null +++ b/tests/benchmarks/qhostinfo/main.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** 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 test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QDebug> +#include <QHostInfo> +#include <QStringList> +#include <QString> + +#include <qtest.h> +#include <qtesteventloop.h> + +class tst_qhostinfo : public QObject +{ + Q_OBJECT +private slots: + void lookupSpeed(); +}; + +class SignalReceiver : public QObject +{ + Q_OBJECT +public: + SignalReceiver(int nrc) : receiveCount(0), neededReceiveCount(nrc) {}; + int receiveCount; + int neededReceiveCount; +public slots: + void resultsReady(const QHostInfo) { + receiveCount++; + if (receiveCount == neededReceiveCount) + QTestEventLoop::instance().exitLoop(); + } +}; + +void tst_qhostinfo::lookupSpeed() +{ + QStringList hostnameList; + hostnameList << "www.ovi.com" << "www.nokia.com" << "qt.nokia.com" << "www.trolltech.com" << "troll.no" + << "www.qtcentre.org" << "forum.nokia.com" << "www.forum.nokia.com" << "wiki.forum.nokia.com" + << "www.nokia.no" << "nokia.de" << "127.0.0.1" << "----"; + // also add some duplicates: + hostnameList << "www.nokia.com" << "127.0.0.1" << "www.trolltech.com"; + const int COUNT = hostnameList.size(); + + SignalReceiver receiver(COUNT); + + QBENCHMARK { + for (int i = 0; i < hostnameList.size(); i++) + QHostInfo::lookupHost(hostnameList.at(i), &receiver, SLOT(resultsReady(const QHostInfo))); + QTestEventLoop::instance().enterLoop(20); + QVERIFY(!QTestEventLoop::instance().timeout()); + } +} + + +QTEST_MAIN(tst_qhostinfo) + +#include "main.moc" diff --git a/tests/benchmarks/qhostinfo/qhostinfo.pro b/tests/benchmarks/qhostinfo/qhostinfo.pro new file mode 100755 index 0000000..f18d6d7 --- /dev/null +++ b/tests/benchmarks/qhostinfo/qhostinfo.pro @@ -0,0 +1,13 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_qhostinfo +DEPENDPATH += . +INCLUDEPATH += . + +QT -= gui +QT += network + +CONFIG += release + +# Input +SOURCES += main.cpp |