diff options
30 files changed, 873 insertions, 114 deletions
diff --git a/demos/composition/composition.cpp b/demos/composition/composition.cpp index e03f3e6..deca5dc 100644 --- a/demos/composition/composition.cpp +++ b/demos/composition/composition.cpp @@ -48,6 +48,8 @@ #include <QMouseEvent> #include <qmath.h> +const int animationInterval = 15; // update every 16 ms = ~60FPS + CompositionWidget::CompositionWidget(QWidget *parent) : QWidget(parent) { @@ -236,6 +238,7 @@ CompositionRenderer::CompositionRenderer(QWidget *parent) : ArthurFrame(parent) { m_animation_enabled = true; + m_animationTimer = startTimer(animationInterval); #ifdef Q_WS_QWS m_image = QPixmap(":res/composition/flower.jpg"); m_image.setAlphaChannel(QPixmap(":res/composition/flower_alpha.jpg")); @@ -264,6 +267,20 @@ QRectF rectangle_around(const QPointF &p, const QSizeF &size = QSize(250, 200)) return rect; } +void CompositionRenderer::setAnimationEnabled(bool enabled) +{ + if (m_animation_enabled == enabled) + return; + m_animation_enabled = enabled; + if (enabled) { + Q_ASSERT(!m_animationTimer); + m_animationTimer = startTimer(animationInterval); + } else { + killTimer(m_animationTimer); + m_animationTimer = 0; + } +} + void CompositionRenderer::updateCirclePos() { if (m_current_object != NoObject) @@ -471,10 +488,6 @@ void CompositionRenderer::paint(QPainter *painter) painter->drawImage(0, 0, m_buffer); #endif } - - if (m_animation_enabled && m_current_object == NoObject) { - updateCirclePos(); - } } void CompositionRenderer::mousePressEvent(QMouseEvent *e) @@ -489,6 +502,10 @@ void CompositionRenderer::mousePressEvent(QMouseEvent *e) } else { m_current_object = NoObject; } + if (m_animation_enabled) { + killTimer(m_animationTimer); + m_animationTimer = 0; + } } void CompositionRenderer::mouseMoveEvent(QMouseEvent *e) @@ -500,7 +517,15 @@ void CompositionRenderer::mouseReleaseEvent(QMouseEvent *) { m_current_object = NoObject; - if (m_animation_enabled) + if (m_animation_enabled) { + Q_ASSERT(!m_animationTimer); + m_animationTimer = startTimer(animationInterval); + } +} + +void CompositionRenderer::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == m_animationTimer) updateCirclePos(); } diff --git a/demos/composition/composition.h b/demos/composition/composition.h index 1123531..f5a9fc3 100644 --- a/demos/composition/composition.h +++ b/demos/composition/composition.h @@ -109,10 +109,6 @@ public: void paint(QPainter *); - void mousePressEvent(QMouseEvent *); - void mouseMoveEvent(QMouseEvent *); - void mouseReleaseEvent(QMouseEvent *); - void setCirclePos(const QPointF &pos); QSize sizeHint() const { return QSize(500, 400); } @@ -121,6 +117,12 @@ public: int circleColor() const { return m_circle_hue; } int circleAlpha() const { return m_circle_alpha; } +protected: + void mousePressEvent(QMouseEvent *); + void mouseMoveEvent(QMouseEvent *); + void mouseReleaseEvent(QMouseEvent *); + void timerEvent(QTimerEvent *); + public slots: void setClearMode() { m_composition_mode = QPainter::CompositionMode_Clear; update(); } void setSourceMode() { m_composition_mode = QPainter::CompositionMode_Source; update(); } @@ -150,7 +152,7 @@ public slots: void setCircleAlpha(int alpha) { m_circle_alpha = alpha; update(); } void setCircleColor(int hue) { m_circle_hue = hue; update(); } - void setAnimationEnabled(bool enabled) { m_animation_enabled = enabled; update(); } + void setAnimationEnabled(bool enabled); private: void updateCirclePos(); @@ -177,6 +179,7 @@ private: ObjectType m_current_object; bool m_animation_enabled; + int m_animationTimer; #ifdef QT_OPENGL_SUPPORT QGLPixelBuffer *m_pbuffer; diff --git a/dist/changes-4.6.3 b/dist/changes-4.6.3 new file mode 100644 index 0000000..57cc453 --- /dev/null +++ b/dist/changes-4.6.3 @@ -0,0 +1,159 @@ +Qt 4.6.3 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 4.6.0. For more details, +refer to the online documentation included in this distribution. The +documentation is also available online: + + http://qt.nokia.com/doc/4.6 + +The Qt version 4.6 series is binary compatible with the 4.5.x series. +Applications compiled for 4.5 will continue to run with 4.6. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker, the (now obsolete) Task +Tracker, or the Merge Request queue of the public source repository. + +Qt Bug Tracker: http://bugreports.qt.nokia.com +Task Tracker: http://qt.nokia.com/developer/task-tracker +Merge Request: http://qt.gitorious.org + +**************************************************************************** +* General * +**************************************************************************** + +New features +------------ + + - SomeClass, SomeOtherClass + * New classes for foo, bar and baz + +Optimizations +------------- + + - Optimized foo in QSomeClass + * See list of Important Behavior Changes below + + +**************************************************************************** +* Library * +**************************************************************************** + +QtCore +------ + + - foo + * bar + +QtGui +----- + + - foo + * bar + +QtDBus +------ + + - foo + * bar + +QtNetwork +--------- + + - foo + * bar + +QtOpenGL +-------- + + - foo + * bar + +QtScript +-------- + + - foo + * bar + +QtSql +----- + + - foo + * bar + +QtXml +----- + + - foo + * bar + +Qt Plugins +---------- + + - foo + * bar + +Third party components +---------------------- + + - Updated foo to version 2.3.9. + + - Updated bar to the latest version from baz.org. + + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Qt for Unix (X11 and Mac OS X) +------------------------------ + + - + +Qt for Linux/X11 +---------------- + + - + +Qt for Windows +-------------- + + - + +Qt for Mac OS X +--------------- + + - + +Qt for Embedded Linux +--------------------- + + - + +DirectFB +-------- + + - + +Qt for Windows CE +----------------- + + - + +**************************************************************************** +* Tools * +**************************************************************************** + + - Designer + * foo + + - qdoc3 + * bar + + - Linguist + * baz + +**************************************************************************** +* Important Behavior Changes * +**************************************************************************** + + - + diff --git a/doc/src/objectmodel/signalsandslots.qdoc b/doc/src/objectmodel/signalsandslots.qdoc index 951a396..0f3f618 100644 --- a/doc/src/objectmodel/signalsandslots.qdoc +++ b/doc/src/objectmodel/signalsandslots.qdoc @@ -379,7 +379,7 @@ \section1 Signals And Slots With Default Arguments The signatures of signals and slots may contain arguments, and the - arguments can have defualt values. Consider QObject::destroyed(): + arguments can have default values. Consider QObject::destroyed(): \code void destroyed(QObject* = 0); diff --git a/src/corelib/codecs/qtextcodec.h b/src/corelib/codecs/qtextcodec.h index a099dd9..23c91c7 100644 --- a/src/corelib/codecs/qtextcodec.h +++ b/src/corelib/codecs/qtextcodec.h @@ -170,8 +170,10 @@ private: friend class QXmlStreamWriter; friend class QXmlStreamWriterPrivate; +#if defined Q_XMLSTREAM_RENAME_SYMBOLS friend class QCoreXmlStreamWriter; friend class QCoreXmlStreamWriterPrivate; +#endif }; class Q_CORE_EXPORT QTextDecoder { diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index 82d3b79..f27ecc1 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -156,6 +156,13 @@ QT_BEGIN_NAMESPACE data, followed by the data. Note that any encoding/decoding of the data (apart from the length quint32) must be done by you. + \section1 Reading and writing Qt collection classes + + The Qt collection classes can also be serialized to a QDataStream. + These include QList, QLinkedList, QVector, QSet, QHash, and QMap. + These classes have have stream operators declared as non-member of + the class. + \target Serializing Qt Classes \section1 Reading and writing other Qt classes. diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp index f088ded..731406f 100644 --- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp +++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp @@ -260,12 +260,22 @@ void QKqueueFileSystemWatcherEngine::run() DEBUG() << "QKqueueFileSystemWatcherEngine: processing kevent" << kev.ident << kev.filter; if (fd == kqpipe[0]) { - char c; - if (read(kqpipe[0], &c, 1) != 1) { + // read all pending data from the pipe + QByteArray ba; + ba.resize(kev.data); + if (read(kqpipe[0], ba.data(), ba.size()) != ba.size()) { perror("QKqueueFileSystemWatcherEngine: error reading from pipe"); return; } - switch (c) { + // read the command from the buffer (but break and return on 'q') + char cmd = 0; + for (int i = 0; i < ba.size(); ++i) { + cmd = ba.constData()[i]; + if (cmd == 'q') + break; + } + // handle the command + switch (cmd) { case 'q': DEBUG() << "QKqueueFileSystemWatcherEngine: thread received 'q', exiting..."; return; @@ -273,7 +283,7 @@ void QKqueueFileSystemWatcherEngine::run() DEBUG() << "QKqueueFileSystemWatcherEngine: thread received '@', continuing..."; break; default: - DEBUG() << "QKqueueFileSystemWatcherEngine: thread received unknow message" << c; + DEBUG() << "QKqueueFileSystemWatcherEngine: thread received unknow message" << cmd; break; } } else { diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index bec0075..139075f 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -1484,7 +1484,7 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const { //### what to do with permissions if we don't use NTFS // for now just add all permissions and what about exe missions ?? - // also qt_ntfs_permission_lookup is now not set by defualt ... should it ? + // also qt_ntfs_permission_lookup is now not set by default ... should it ? ret |= QAbstractFileEngine::ReadOtherPerm | QAbstractFileEngine::ReadGroupPerm | QAbstractFileEngine::ReadOwnerPerm | QAbstractFileEngine::ReadUserPerm | QAbstractFileEngine::WriteUserPerm | QAbstractFileEngine::WriteOwnerPerm diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index cbc87f3..93becc8 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -68,6 +68,14 @@ extern uint qGlobalPostedEventsCount(); # define QS_RAWINPUT 0x0400 #endif +#ifndef WM_TOUCH +# define WM_TOUCH 0x0240 +#endif +#ifndef WM_GESTURE +# define WM_GESTURE 0x0119 +# define WM_GESTURENOTIFY 0x011A +#endif + enum { WM_QT_SOCKETNOTIFIER = WM_USER, WM_QT_SENDPOSTEDEVENTS = WM_USER + 1, @@ -714,6 +722,9 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) && msg.message <= WM_MOUSELAST) || msg.message == WM_MOUSEWHEEL || msg.message == WM_MOUSEHWHEEL + || msg.message == WM_TOUCH + || msg.message == WM_GESTURE + || msg.message == WM_GESTURENOTIFY || msg.message == WM_CLOSE)) { // queue user input events for later processing haveMessage = false; diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h index 1f7fdb2..aa5603d 100644 --- a/src/corelib/tools/qcontiguouscache.h +++ b/src/corelib/tools/qcontiguouscache.h @@ -221,22 +221,29 @@ void QContiguousCache<T>::setCapacity(int asize) x.d->alloc = asize; x.d->count = qMin(d->count, asize); x.d->offset = d->offset + d->count - x.d->count; - x.d->start = x.d->offset % x.d->alloc; - T *dest = x.p->array + (x.d->start + x.d->count-1) % x.d->alloc; - T *src = p->array + (d->start + d->count-1) % d->alloc; + if(asize) + x.d->start = x.d->offset % x.d->alloc; + else + x.d->start = 0; + int oldcount = x.d->count; - while (oldcount--) { - if (QTypeInfo<T>::isComplex) { - new (dest) T(*src); - } else { - *dest = *src; + if(oldcount) + { + T *dest = x.p->array + (x.d->start + x.d->count-1) % x.d->alloc; + T *src = p->array + (d->start + d->count-1) % d->alloc; + while (oldcount--) { + if (QTypeInfo<T>::isComplex) { + new (dest) T(*src); + } else { + *dest = *src; + } + if (dest == x.p->array) + dest = x.p->array + x.d->alloc; + dest--; + if (src == p->array) + src = p->array + d->alloc; + src--; } - if (dest == x.p->array) - dest = x.p->array + x.d->alloc; - dest--; - if (src == p->array) - src = p->array + d->alloc; - src--; } /* free old */ free(p); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 44abf7b..6cb4924 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1937,7 +1937,7 @@ int QDBusConnectionPrivate::sendWithReplyAsync(const QDBusMessage &message, QObj QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, timeout); Q_ASSERT(pcall); - // has it already finished (dispatched locally)? + // has it already finished with success (dispatched locally)? if (pcall->replyMessage.type() == QDBusMessage::ReplyMessage) { pcall->setReplyCallback(receiver, returnMethod); processFinishedCall(pcall); @@ -1945,33 +1945,24 @@ int QDBusConnectionPrivate::sendWithReplyAsync(const QDBusMessage &message, QObj return 1; } + // either it hasn't finished or it has finished with error + if (errorMethod) { + pcall->watcherHelper = new QDBusPendingCallWatcherHelper; + connect(pcall->watcherHelper, SIGNAL(error(QDBusError,QDBusMessage)), receiver, errorMethod, + Qt::QueuedConnection); + pcall->watcherHelper->moveToThread(thread()); + } + // has it already finished and is an error reply message? if (pcall->replyMessage.type() == QDBusMessage::ErrorMessage) { - if (errorMethod) { - pcall->watcherHelper = new QDBusPendingCallWatcherHelper; - connect(pcall->watcherHelper, SIGNAL(error(QDBusError,QDBusMessage)), receiver, errorMethod); - pcall->watcherHelper->moveToThread(thread()); - } processFinishedCall(pcall); delete pcall; return 1; } - // has it already finished with error? - if (pcall->replyMessage.type() != QDBusMessage::InvalidMessage) { - delete pcall; - return 0; - } - pcall->autoDelete = true; pcall->ref.ref(); - pcall->setReplyCallback(receiver, returnMethod); - if (errorMethod) { - pcall->watcherHelper = new QDBusPendingCallWatcherHelper; - connect(pcall->watcherHelper, SIGNAL(error(QDBusError,QDBusMessage)), receiver, errorMethod); - pcall->watcherHelper->moveToThread(thread()); - } return 1; } diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 3cdf8ce..2f208b7 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -357,19 +357,22 @@ default, child items are stacked on top of the parent item. But setting this flag, the child will be stacked behind it. This flag is useful for drop shadow effects and for decoration objects that follow the parent - item's geometry without drawing on top of it. + item's geometry without drawing on top of it. This flag was introduced + in Qt 4.5. \value ItemUsesExtendedStyleOption The item makes use of either - \l{QStyleOptionGraphicsItem::}{exposedRect} or - \l{QStyleOptionGraphicsItem::}{matrix} in QStyleOptionGraphicsItem. By default, - the \l{QStyleOptionGraphicsItem::}{exposedRect} is initialized to the item's - boundingRect() and the \l{QStyleOptionGraphicsItem::}{matrix} is untransformed. - You can enable this flag for the style options to be set up with more - fine-grained values. - Note that QStyleOptionGraphicsItem::levelOfDetail is unaffected by this flag + \l{QStyleOptionGraphicsItem::} {exposedRect} or + \l{QStyleOptionGraphicsItem::} {matrix} in + QStyleOptionGraphicsItem. By default, the + \l{QStyleOptionGraphicsItem::} {exposedRect} is initialized to the + item's boundingRect() and the + \l{QStyleOptionGraphicsItem::}{matrix} is untransformed. You can + enable this flag for the style options to be set up with more + fine-grained values. Note that + QStyleOptionGraphicsItem::levelOfDetail is unaffected by this flag and always initialized to 1. Use - QStyleOptionGraphicsItem::levelOfDetailFromTransform() if you need a higher - value. + QStyleOptionGraphicsItem::levelOfDetailFromTransform() if you need + a higher value. This flag was introduced in Qt 4.6. \value ItemHasNoContents The item does not paint anything (i.e., calling paint() on the item has no effect). You should set this flag on items that @@ -387,9 +390,10 @@ used for Asian languages. This flag was introduced in Qt 4.6. - \value ItemNegativeZStacksBehindParent The item automatically stacks behind - it's parent if it's z-value is negative. This flag enables setZValue() to - toggle ItemStacksBehindParent. + \value ItemNegativeZStacksBehindParent The item automatically + stacks behind it's parent if it's z-value is negative. This flag + enables setZValue() to toggle ItemStacksBehindParent. This flag + was introduced in Qt 4.6. \value ItemIsPanel The item is a panel. A panel provides activation and contained focus handling. Only one panel can be active at a time (see diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 66707fc..4472272 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5132,6 +5132,8 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool } /*! + \obsolete + Paints the given \a items using the provided \a painter, after the background has been drawn, and before the foreground has been drawn. All painting is done in \e scene coordinates. Before @@ -5154,7 +5156,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool \snippet doc/src/snippets/graphicssceneadditemsnippet.cpp 0 - \obsolete Since Qt 4.6, this function is not called anymore unless + Since Qt 4.6, this function is not called anymore unless the QGraphicsView::IndirectPainting flag is given as an Optimization flag. @@ -5710,8 +5712,15 @@ void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent) item->d_ptr->acceptedTouchBeginEvent = true; bool res = sendTouchBeginEvent(item, &touchEvent) && touchEvent.isAccepted(); - if (!res) + if (!res) { + // forget about these touch points, we didn't handle them + for (int i = 0; i < touchEvent.touchPoints().count(); ++i) { + const QTouchEvent::TouchPoint &touchPoint = touchEvent.touchPoints().at(i); + itemForTouchPointId.remove(touchPoint.id()); + sceneCurrentTouchPoints.remove(touchPoint.id()); + } ignoreSceneTouchEvent = false; + } break; } default: @@ -5902,13 +5911,21 @@ void QGraphicsScenePrivate::getGestureTargets(const QSet<QGesture *> &gestures, QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport); QList<QGraphicsObject *> result; for (int j = 0; j < items.size(); ++j) { - QGraphicsObject *item = items.at(j)->toGraphicsObject(); - if (!item) - continue; - QGraphicsItemPrivate *d = item->QGraphicsItem::d_func(); - if (d->gestureContext.contains(gestureType)) { - result.append(item); + QGraphicsItem *item = items.at(j); + + // Check if the item is blocked by a modal panel and use it as + // a target instead of this item. + (void) item->isBlockedByModalPanel(&item); + + if (QGraphicsObject *itemobj = item->toGraphicsObject()) { + QGraphicsItemPrivate *d = item->d_func(); + if (d->gestureContext.contains(gestureType)) { + result.append(itemobj); + } } + // Don't propagate through panels. + if (item->isPanel()) + break; } DEBUG() << "QGraphicsScenePrivate::getGestureTargets:" << gesture << result; diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm index c7c7caf..df09185 100644 --- a/src/gui/kernel/qeventdispatcher_mac.mm +++ b/src/gui/kernel/qeventdispatcher_mac.mm @@ -492,6 +492,14 @@ static bool IsMouseOrKeyEvent( NSEvent* event ) case NSOtherMouseDown: case NSOtherMouseUp: case NSOtherMouseDragged: +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + case NSEventTypeGesture: // touch events + case NSEventTypeMagnify: + case NSEventTypeSwipe: + case NSEventTypeRotate: + case NSEventTypeBeginGesture: + case NSEventTypeEndGesture: +#endif result = true; break; diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 7a3da20..070491d 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -8092,20 +8092,43 @@ void qInitDrawhelperAsm() qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_sse3dnow; } #endif // 3DNOW - extern void qt_blend_rgb32_on_rgb32_sse(uchar *destPixels, int dbpl, - const uchar *srcPixels, int sbpl, - int w, int h, - int const_alpha); - extern void qt_blend_argb32_on_argb32_sse(uchar *destPixels, int dbpl, - const uchar *srcPixels, int sbpl, - int w, int h, - int const_alpha); - qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse; - qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse; - qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse; - qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse; - } + +#ifdef QT_HAVE_SSE2 + if (features & SSE2) { + extern void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + extern void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + + + qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2; + qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2; + } else +#endif + { + extern void qt_blend_rgb32_on_rgb32_sse(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + extern void qt_blend_argb32_on_argb32_sse(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + + + qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse; + qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse; + } +} #endif // SSE #ifdef QT_HAVE_IWMMXT diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index dd6fa1b..6ac64d3 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -57,6 +57,217 @@ QT_BEGIN_NAMESPACE +/* + * Multiply the components of pixelVector by alphaChannel + * Each 32bits components of alphaChannel must be in the form 0x00AA00AA + * colorMask must have 0x00ff00ff on each 32 bits component + * half must have the value 128 (0x80) for each 32 bits compnent + */ +#define BYTE_MUL_SSE2(result, pixelVector, alphaChannel, colorMask, half) \ +{ \ + /* 1. separate the colors in 2 vectors so each color is on 16 bits \ + (in order to be multiplied by the alpha \ + each 32 bit of dstVectorAG are in the form 0x00AA00GG \ + each 32 bit of dstVectorRB are in the form 0x00RR00BB */\ + __m128i pixelVectorAG = _mm_srli_epi16(pixelVector, 8); \ + __m128i pixelVectorRB = _mm_and_si128(pixelVector, colorMask); \ + \ + /* 2. multiply the vectors by the alpha channel */\ + pixelVectorAG = _mm_mullo_epi16(pixelVectorAG, alphaChannel); \ + pixelVectorRB = _mm_mullo_epi16(pixelVectorRB, alphaChannel); \ + \ + /* 3. devide by 255, that's the tricky part. \ + we do it like for BYTE_MUL(), with bit shift: X/255 ~= (X + X/256 + rounding)/256 */ \ + /** so first (X + X/256 + rounding) */\ + pixelVectorRB = _mm_add_epi16(pixelVectorRB, _mm_srli_epi16(pixelVectorRB, 8)); \ + pixelVectorRB = _mm_add_epi16(pixelVectorRB, half); \ + pixelVectorAG = _mm_add_epi16(pixelVectorAG, _mm_srli_epi16(pixelVectorAG, 8)); \ + pixelVectorAG = _mm_add_epi16(pixelVectorAG, half); \ + \ + /** second devide by 256 */\ + pixelVectorRB = _mm_srli_epi16(pixelVectorRB, 8); \ + /** for AG, we could >> 8 to divide followed by << 8 to put the \ + bytes in the correct position. By masking instead, we execute \ + only one instruction */\ + pixelVectorAG = _mm_andnot_si128(colorMask, pixelVectorAG); \ + \ + /* 4. combine the 2 pairs of colors */ \ + result = _mm_or_si128(pixelVectorAG, pixelVectorRB); \ +} + +/* + * Each 32bits components of alphaChannel must be in the form 0x00AA00AA + * oneMinusAlphaChannel must be 255 - alpha for each 32 bits component + * colorMask must have 0x00ff00ff on each 32 bits component + * half must have the value 128 (0x80) for each 32 bits compnent + */ +#define INTERPOLATE_PIXEL_255_SSE2(result, srcVector, dstVector, alphaChannel, oneMinusAlphaChannel, colorMask, half) { \ + /* interpolate AG */\ + __m128i srcVectorAG = _mm_srli_epi16(srcVector, 8); \ + __m128i dstVectorAG = _mm_srli_epi16(dstVector, 8); \ + __m128i srcVectorAGalpha = _mm_mullo_epi16(srcVectorAG, alphaChannel); \ + __m128i dstVectorAGoneMinusAlphalpha = _mm_mullo_epi16(dstVectorAG, oneMinusAlphaChannel); \ + __m128i finalAG = _mm_add_epi16(srcVectorAGalpha, dstVectorAGoneMinusAlphalpha); \ + finalAG = _mm_add_epi16(finalAG, _mm_srli_epi16(finalAG, 8)); \ + finalAG = _mm_add_epi16(finalAG, half); \ + finalAG = _mm_andnot_si128(colorMask, finalAG); \ + \ + /* interpolate RB */\ + __m128i srcVectorRB = _mm_and_si128(srcVector, colorMask); \ + __m128i dstVectorRB = _mm_and_si128(dstVector, colorMask); \ + __m128i srcVectorRBalpha = _mm_mullo_epi16(srcVectorRB, alphaChannel); \ + __m128i dstVectorRBoneMinusAlphalpha = _mm_mullo_epi16(dstVectorRB, oneMinusAlphaChannel); \ + __m128i finalRB = _mm_add_epi16(srcVectorRBalpha, dstVectorRBoneMinusAlphalpha); \ + finalRB = _mm_add_epi16(finalRB, _mm_srli_epi16(finalRB, 8)); \ + finalRB = _mm_add_epi16(finalRB, half); \ + finalRB = _mm_srli_epi16(finalRB, 8); \ + \ + /* combine */\ + result = _mm_or_si128(finalAG, finalRB); \ +} + +void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha) +{ + const quint32 *src = (const quint32 *) srcPixels; + quint32 *dst = (uint *) destPixels; + if (const_alpha == 256) { + const __m128i alphaMask = _mm_set1_epi32(0xff000000); + const __m128i nullVector = _mm_set1_epi32(0); + const __m128i half = _mm_set1_epi16(0x80); + const __m128i one = _mm_set1_epi16(0xff); + const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); + for (int y = 0; y < h; ++y) { + int x = 0; + for (; x < w-3; x += 4) { + const __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); + const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask); + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) { + // all opaque + _mm_storeu_si128((__m128i *)&dst[x], srcVector); + } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) { + // not fully transparent + // result = s + d * (1-alpha) + + // extract the alpha channel on 2 x 16 bits + // so we have room for the multiplication + // each 32 bits will be in the form 0x00AA00AA + // with A being the 1 - alpha + __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); + alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); + alphaChannel = _mm_sub_epi16(one, alphaChannel); + + const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); + __m128i destMultipliedByOneMinusAlpha; + BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); + + // result = s + d * (1-alpha) + const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); + _mm_storeu_si128((__m128i *)&dst[x], result); + } + } + for (; x<w; ++x) { + uint s = src[x]; + if (s >= 0xff000000) + dst[x] = s; + else if (s != 0) + dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); + } + dst = (quint32 *)(((uchar *) dst) + dbpl); + src = (const quint32 *)(((const uchar *) src) + sbpl); + } + } else if (const_alpha != 0) { + // dest = (s + d * sia) * ca + d * cia + // = s * ca + d * (sia * ca + cia) + // = s * ca + d * (1 - sa*ca) + const_alpha = (const_alpha * 255) >> 8; + const __m128i nullVector = _mm_set1_epi32(0); + const __m128i half = _mm_set1_epi16(0x80); + const __m128i one = _mm_set1_epi16(0xff); + const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); + const __m128i constAlphaVector = _mm_set1_epi16(const_alpha); + for (int y = 0; y < h; ++y) { + int x = 0; + for (; x < w-3; x += 4) { + __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVector, nullVector)) != 0xffff) { + BYTE_MUL_SSE2(srcVector, srcVector, constAlphaVector, colorMask, half); + + __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); + alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); + alphaChannel = _mm_sub_epi16(one, alphaChannel); + + const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); + __m128i destMultipliedByOneMinusAlpha; + BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); + + const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); + _mm_storeu_si128((__m128i *)&dst[x], result); + } + } + for (; x<w; ++x) { + quint32 s = src[x]; + if (s != 0) { + s = BYTE_MUL(s, const_alpha); + dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); + } + } + dst = (quint32 *)(((uchar *) dst) + dbpl); + src = (const quint32 *)(((const uchar *) src) + sbpl); + } + } +} + +// qblendfunctions.cpp +void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + +void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha) +{ + const quint32 *src = (const quint32 *) srcPixels; + quint32 *dst = (uint *) destPixels; + if (const_alpha != 256) { + if (const_alpha != 0) { + const __m128i nullVector = _mm_set1_epi32(0); + const __m128i half = _mm_set1_epi16(0x80); + const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); + + const_alpha = (const_alpha * 255) >> 8; + int one_minus_const_alpha = 255 - const_alpha; + const __m128i constAlphaVector = _mm_set1_epi16(const_alpha); + const __m128i oneMinusConstAlpha = _mm_set1_epi16(one_minus_const_alpha); + for (int y = 0; y < h; ++y) { + int x = 0; + for (; x < w-3; x += 4) { + __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVector, nullVector)) != 0xffff) { + const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); + __m128i result; + INTERPOLATE_PIXEL_255_SSE2(result, srcVector, dstVector, constAlphaVector, oneMinusConstAlpha, colorMask, half); + _mm_storeu_si128((__m128i *)&dst[x], result); + } + } + for (; x<w; ++x) { + quint32 s = src[x]; + s = BYTE_MUL(s, const_alpha); + dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], one_minus_const_alpha); + } + dst = (quint32 *)(((uchar *) dst) + dbpl); + src = (const quint32 *)(((const uchar *) src) + sbpl); + } + } + } else { + qt_blend_rgb32_on_rgb32(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha); + } +} + void qt_memfill32_sse2(quint32 *dest, quint32 value, int count) { if (count < 7) { diff --git a/src/gui/painting/qdrawhelper_x86_p.h b/src/gui/painting/qdrawhelper_x86_p.h index 30aadd0..d7282a7 100644 --- a/src/gui/painting/qdrawhelper_x86_p.h +++ b/src/gui/painting/qdrawhelper_x86_p.h @@ -114,6 +114,14 @@ void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *src, int width, int height, int stride); +void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); +void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); #endif // QT_HAVE_SSE2 #ifdef QT_HAVE_IWMMXT diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index b0e632a..2a3036b 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -283,20 +283,17 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() // connection might be closed to signal the end of data if (socketState == QAbstractSocket::UnconnectedState) { - if (!socket->bytesAvailable()) { + if (socket->bytesAvailable() <= 0) { if (reply && reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) { + // finish this reply. this case happens when the server did not send a content length reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState; allDone(); } else { - // try to reconnect/resend before sending an error. - if (reconnectAttempts-- > 0) { - closeAndResendCurrentRequest(); - } else if (reply) { - reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::RemoteHostClosedError, socket); - emit reply->finishedWithError(QNetworkReply::RemoteHostClosedError, reply->d_func()->errorString); - QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); - } + handleUnexpectedEOF(); + return; } + } else { + // socket not connected but still bytes for reading.. just continue in this function } } @@ -311,18 +308,10 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() } case QHttpNetworkReplyPrivate::ReadingStatusState: { qint64 statusBytes = reply->d_func()->readStatus(socket); - if (statusBytes == -1 && reconnectAttempts <= 0) { - // too many errors reading/receiving/parsing the status, close the socket and emit error - close(); - reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::ProtocolFailure, socket); - emit reply->finishedWithError(QNetworkReply::ProtocolFailure, reply->d_func()->errorString); - QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); - break; - } else if (statusBytes == -1) { - reconnectAttempts--; - reply->d_func()->clear(); - closeAndResendCurrentRequest(); - break; + if (statusBytes == -1) { + // connection broke while reading status. also handled if later _q_disconnected is called + handleUnexpectedEOF(); + return; } bytes += statusBytes; lastStatus = reply->d_func()->statusCode; @@ -330,7 +319,13 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() } case QHttpNetworkReplyPrivate::ReadingHeaderState: { QHttpNetworkReplyPrivate *replyPrivate = reply->d_func(); - bytes += replyPrivate->readHeader(socket); + qint64 headerBytes = replyPrivate->readHeader(socket); + if (headerBytes == -1) { + // connection broke while reading headers. also handled if later _q_disconnected is called + handleUnexpectedEOF(); + return; + } + bytes += headerBytes; if (replyPrivate->state == QHttpNetworkReplyPrivate::ReadingDataState) { if (replyPrivate->isGzipped() && replyPrivate->autoDecompress) { // remove the Content-Length from header @@ -430,6 +425,23 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() } } +// called when unexpectedly reading a -1 or when data is expected but socket is closed +void QHttpNetworkConnectionChannel::handleUnexpectedEOF() +{ + if (reconnectAttempts <= 0) { + // too many errors reading/receiving/parsing the status, close the socket and emit error + requeueCurrentlyPipelinedRequests(); + close(); + reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::RemoteHostClosedError, socket); + emit reply->finishedWithError(QNetworkReply::RemoteHostClosedError, reply->d_func()->errorString); + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + } else { + reconnectAttempts--; + reply->d_func()->clear(); + closeAndResendCurrentRequest(); + } +} + bool QHttpNetworkConnectionChannel::ensureConnection() { QAbstractSocket::SocketState socketState = socket->state(); @@ -799,9 +811,10 @@ void QHttpNetworkConnectionChannel::_q_disconnected() { // read the available data before closing if (isSocketWaiting() || isSocketReading()) { - state = QHttpNetworkConnectionChannel::ReadingState; - if (reply) + if (reply) { + state = QHttpNetworkConnectionChannel::ReadingState; _q_receiveReply(); + } } else if (state == QHttpNetworkConnectionChannel::IdleState && resendCurrent) { // re-sending request because the socket was in ClosingState QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index 75ab50d..5032d2b 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -157,6 +157,7 @@ public: void requeueCurrentlyPipelinedRequests(); void detectPipeliningSupport(); + void handleUnexpectedEOF(); void closeAndResendCurrentRequest(); void eatWhitespace(); diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index ecdcca8..1c2db2f 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -1298,11 +1298,23 @@ static bool qInvokeTestMethod(const char *slotName, const char *data=0) const int dataCount = table.dataCount(); QTestResult::setSkipCurrentTest(false); + // Data tag requested but none available? + if (data && !dataCount) { + // Let empty data tag through. + if (!*data) + data = 0; + else { + printf("Unknown testdata for function %s: '%s'\n", slotName, data); + printf("Function has no testdata.\n"); + return false; + } + } + /* For each entry in the data table, do: */ do { if (!data || !qstrcmp(data, table.testData(curDataIndex)->dataTag())) { foundFunction = true; - QTestDataSetter s(table.isEmpty() ? static_cast<QTestData *>(0) + QTestDataSetter s(curDataIndex >= dataCount ? static_cast<QTestData *>(0) : table.testData(curDataIndex)); qInvokeTestMethodDataEntry(slot); diff --git a/tests/auto/gestures/tst_gestures.cpp b/tests/auto/gestures/tst_gestures.cpp index 952136b..986227d 100644 --- a/tests/auto/gestures/tst_gestures.cpp +++ b/tests/auto/gestures/tst_gestures.cpp @@ -333,6 +333,8 @@ private slots: void unregisterRecognizer(); void autoCancelGestures(); void autoCancelGestures2(); + void panelPropagation(); + void panelStacksBehindParent(); }; tst_Gestures::tst_Gestures() @@ -1457,9 +1459,7 @@ void tst_Gestures::autoCancelGestures2() event.serial = CustomGesture::SerialStartedThreshold; event.hasHotSpot = true; event.hotSpot = mapToGlobal(QPointF(5, 5), child, &view); - // qDebug() << event.hotSpot; scene.sendEvent(child, &event); - //QEventLoop().exec(); QCOMPARE(parent->events.all.count(), 1); QCOMPARE(child->events.started.count(), 1); QCOMPARE(child->events.canceled.count(), 1); @@ -1471,5 +1471,172 @@ void tst_Gestures::autoCancelGestures2() QCOMPARE(parent->events.all.count(), 2); } +void tst_Gestures::panelPropagation() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item0 = new GestureItem("item0"); + scene.addItem(item0); + item0->setPos(0, 0); + item0->size = QRectF(0, 0, 200, 200); + item0->grabGesture(CustomGesture::GestureType); + item0->setZValue(1); + + GestureItem *item1 = new GestureItem("item1"); + item1->grabGesture(CustomGesture::GestureType); + scene.addItem(item1); + item1->setPos(10, 10); + item1->size = QRectF(0, 0, 180, 180); + item1->setZValue(2); + + GestureItem *item1_child1 = new GestureItem("item1_child1[panel]"); + item1_child1->setFlags(QGraphicsItem::ItemIsPanel); + item1_child1->setParentItem(item1); + item1_child1->grabGesture(CustomGesture::GestureType); + item1_child1->setPos(10, 10); + item1_child1->size = QRectF(0, 0, 160, 160); + item1_child1->setZValue(5); + + GestureItem *item1_child1_child1 = new GestureItem("item1_child1_child1"); + item1_child1_child1->setParentItem(item1_child1); + item1_child1_child1->grabGesture(CustomGesture::GestureType); + item1_child1_child1->setPos(10, 10); + item1_child1_child1->size = QRectF(0, 0, 140, 140); + item1_child1_child1->setZValue(10); + + view.show(); + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + view.viewport()->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; + + CustomEvent event; + event.hotSpot = mapToGlobal(QPointF(5, 5), item1_child1_child1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item0, &scene); + + QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(item1_child1_child1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 1); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 1); + QCOMPARE(item1->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(item0->gestureEventsReceived, 0); + QCOMPARE(item0->gestureOverrideEventsReceived, 0); + + item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset(); + + event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item1, &scene); + + QCOMPARE(item1_child1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1->gestureOverrideEventsReceived, 1); + QCOMPARE(item0->gestureEventsReceived, 0); + QCOMPARE(item0->gestureOverrideEventsReceived, 1); + + item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset(); + // try with a modal panel + item1_child1->setPanelModality(QGraphicsItem::PanelModal); + + event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item1, &scene); + + QCOMPARE(item1_child1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(item0->gestureEventsReceived, 0); + QCOMPARE(item0->gestureOverrideEventsReceived, 0); + + item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset(); + // try with a modal panel, however set the hotspot to be outside of the + // panel and its parent + item1_child1->setPanelModality(QGraphicsItem::PanelModal); + + event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item1, &scene); + + QCOMPARE(item1_child1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(item0->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item0->gestureOverrideEventsReceived, 0); + + item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset(); + // try with a scene modal panel + item1_child1->setPanelModality(QGraphicsItem::SceneModal); + + event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item0, &scene); + + QCOMPARE(item1_child1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(item0->gestureEventsReceived, 0); + QCOMPARE(item0->gestureOverrideEventsReceived, 0); +} + +void tst_Gestures::panelStacksBehindParent() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item1 = new GestureItem("item1"); + item1->grabGesture(CustomGesture::GestureType); + scene.addItem(item1); + item1->setPos(10, 10); + item1->size = QRectF(0, 0, 180, 180); + item1->setZValue(2); + + GestureItem *panel = new GestureItem("panel"); + panel->setFlags(QGraphicsItem::ItemIsPanel | QGraphicsItem::ItemStacksBehindParent); + panel->setPanelModality(QGraphicsItem::PanelModal); + panel->setParentItem(item1); + panel->grabGesture(CustomGesture::GestureType); + panel->setPos(-10, -10); + panel->size = QRectF(0, 0, 200, 200); + panel->setZValue(5); + + view.show(); + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + view.viewport()->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + + CustomEvent event; + event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item1, &scene); + + QCOMPARE(item1->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(panel->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(panel->gestureOverrideEventsReceived, 0); +} + QTEST_MAIN(tst_Gestures) #include "tst_gestures.moc" diff --git a/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp b/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp index 5a23274..f64e815 100644 --- a/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp +++ b/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp @@ -71,6 +71,8 @@ private slots: void contiguousCacheBenchmark(); void setCapacity(); + + void zeroCapacity(); }; QTEST_MAIN(tst_QContiguousCache) @@ -476,4 +478,14 @@ void tst_QContiguousCache::setCapacity() } } +void tst_QContiguousCache::zeroCapacity() +{ + QContiguousCache<int> contiguousCache; + QCOMPARE(contiguousCache.capacity(),0); + contiguousCache.setCapacity(10); + QCOMPARE(contiguousCache.capacity(),10); + contiguousCache.setCapacity(0); + QCOMPARE(contiguousCache.capacity(),0); +} + #include "tst_qcontiguouscache.moc" diff --git a/tests/auto/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/qdbusconnection/tst_qdbusconnection.cpp index 5e2f3a9..96209b1 100644 --- a/tests/auto/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/qdbusconnection/tst_qdbusconnection.cpp @@ -80,6 +80,8 @@ class tst_QDBusConnection: public QObject int signalsReceived; public slots: void oneSlot() { ++signalsReceived; } + void exitLoop() { ++signalsReceived; QTestEventLoop::instance().exitLoop(); } + void secondCallWithCallback(); private slots: void noConnection(); @@ -102,6 +104,7 @@ private slots: void multipleInterfacesInQObject(); void slotsWithLessParameters(); + void nestedCallWithCallback(); public: QString serviceName() const { return "com.trolltech.Qt.Autotests.QDBusConnection"; } @@ -618,6 +621,32 @@ void tst_QDBusConnection::slotsWithLessParameters() QCOMPARE(signalsReceived, 1); } +void tst_QDBusConnection::secondCallWithCallback() +{ + qDebug("Hello"); + QDBusConnection con = QDBusConnection::sessionBus(); + QDBusMessage msg = QDBusMessage::createMethodCall(con.baseService(), "/test", QString(), + "test0"); + con.callWithCallback(msg, this, SLOT(exitLoop()), SLOT(secondCallWithCallback())); +} + +void tst_QDBusConnection::nestedCallWithCallback() +{ + TestObject testObject; + QDBusConnection connection = QDBusConnection::sessionBus(); + QVERIFY(connection.registerObject("/test", &testObject, + QDBusConnection::ExportAllContents)); + + QDBusMessage msg = QDBusMessage::createMethodCall(connection.baseService(), "/test", QString(), + "ThisFunctionDoesntExist"); + signalsReceived = 0; + + connection.callWithCallback(msg, this, SLOT(exitLoop()), SLOT(secondCallWithCallback()), 10); + QTestEventLoop::instance().enterLoop(15); + QVERIFY(!QTestEventLoop::instance().timeout()); + QCOMPARE(signalsReceived, 1); +} + QString MyObject::path; QTEST_MAIN(tst_QDBusConnection) diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index eec4797..5fecc86 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -2034,6 +2034,11 @@ void tst_QNetworkReply::ioGetFromHttpBrokenServer_data() QTest::newRow("invalid-version+disconnect") << QByteArray("HTTP/123 200 ") << true; QTest::newRow("invalid-version2+disconnect") << QByteArray("HTTP/a.\033 200 ") << true; QTest::newRow("invalid-reply-code+disconnect") << QByteArray("HTTP/1.0 fuu ") << true; + + QTest::newRow("immediate disconnect") << QByteArray("") << true; + QTest::newRow("justHalfStatus+disconnect") << QByteArray("HTTP/1.1") << true; + QTest::newRow("justStatus+disconnect") << QByteArray("HTTP/1.1 200 OK\r\n") << true; + QTest::newRow("justStatusAndHalfHeaders+disconnect") << QByteArray("HTTP/1.1 200 OK\r\nContent-L") << true; } void tst_QNetworkReply::ioGetFromHttpBrokenServer() diff --git a/tests/auto/qprocess/tst_qprocess.cpp b/tests/auto/qprocess/tst_qprocess.cpp index ee3bb40..8dae9a0 100644 --- a/tests/auto/qprocess/tst_qprocess.cpp +++ b/tests/auto/qprocess/tst_qprocess.cpp @@ -1652,7 +1652,7 @@ void tst_QProcess::failToStart() QSignalSpy finishedSpy(&process, SIGNAL(finished(int))); QSignalSpy finishedSpy2(&process, SIGNAL(finished(int, QProcess::ExitStatus))); -// Mac OS X and HP-UX have a really low defualt process limit (~100), so spawning +// Mac OS X and HP-UX have a really low default process limit (~100), so spawning // to many processes here will cause test failures later on. #if defined Q_OS_HPUX const int attempts = 15; diff --git a/tests/auto/qscriptjstestsuite/tst_qscriptjstestsuite.cpp b/tests/auto/qscriptjstestsuite/tst_qscriptjstestsuite.cpp index 41df98c..10ff488 100644 --- a/tests/auto/qscriptjstestsuite/tst_qscriptjstestsuite.cpp +++ b/tests/auto/qscriptjstestsuite/tst_qscriptjstestsuite.cpp @@ -688,7 +688,7 @@ tst_Suite::tst_Suite() addExpectedFailure("ecma/TypeConversion/9.3.1-3.js", "- -\"0x80000000\"", willFixInNextReleaseMessage); #endif -#ifdef Q_OS_WIN +#ifdef Q_CC_MSVC addExpectedFailure("ecma_3/Expressions/11.7.3-01.js", "11.7.3 - >>> should evaluate operands in order: order", "QTBUG-8056"); addExpectedFailure("ecma_3/Operators/order-01.js", "operator evaluation order: 11.7.3 >>>", "QTBUG-8056"); addExpectedFailure("ecma_3/Operators/order-01.js", "operator evaluation order: 11.13.2 >>>=", "QTBUG-8056"); diff --git a/tests/auto/qscriptstring/tst_qscriptstring.cpp b/tests/auto/qscriptstring/tst_qscriptstring.cpp index f336dbe..808b643 100644 --- a/tests/auto/qscriptstring/tst_qscriptstring.cpp +++ b/tests/auto/qscriptstring/tst_qscriptstring.cpp @@ -87,6 +87,8 @@ void tst_QScriptString::test() QScriptString str2 = str; QVERIFY(!str2.isValid()); + + QCOMPARE(str.toArrayIndex(), quint32(0xffffffff)); } for (int x = 0; x < 2; ++x) { @@ -172,6 +174,7 @@ void tst_QScriptString::toArrayIndex_data() QTest::newRow("0a") << QString::fromLatin1("0a") << false << quint32(0xffffffff); QTest::newRow("0x1") << QString::fromLatin1("0x1") << false << quint32(0xffffffff); QTest::newRow("01") << QString::fromLatin1("01") << false << quint32(0xffffffff); + QTest::newRow("101a") << QString::fromLatin1("101a") << false << quint32(0xffffffff); QTest::newRow("4294967294") << QString::fromLatin1("4294967294") << true << quint32(0xfffffffe); QTest::newRow("4294967295") << QString::fromLatin1("4294967295") << false << quint32(0xffffffff); } diff --git a/tests/auto/qtouchevent/tst_qtouchevent.cpp b/tests/auto/qtouchevent/tst_qtouchevent.cpp index 639f8e4..bb80fde 100644 --- a/tests/auto/qtouchevent/tst_qtouchevent.cpp +++ b/tests/auto/qtouchevent/tst_qtouchevent.cpp @@ -193,6 +193,7 @@ private slots: void multiPointRawEventTranslationOnTouchPad(); void deleteInEventHandler(); void deleteInRawEventTranslation(); + void crashInQGraphicsSceneAfterNotHandlingTouchBegin(); }; void tst_QTouchEvent::touchDisabledByDefault() @@ -1303,6 +1304,36 @@ void tst_QTouchEvent::deleteInRawEventTranslation() qt_translateRawTouchEvent(&touchWidget, QTouchEvent::TouchScreen, rawTouchPoints); } +void tst_QTouchEvent::crashInQGraphicsSceneAfterNotHandlingTouchBegin() +{ + QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 100, 100); + rect->setAcceptTouchEvents(true); + + QGraphicsRectItem *mainRect = new QGraphicsRectItem(0, 0, 100, 100, rect); + mainRect->setBrush(Qt::lightGray); + + QGraphicsRectItem *button = new QGraphicsRectItem(-20, -20, 40, 40, mainRect); + button->setPos(50, 50); + button->setBrush(Qt::darkGreen); + + QGraphicsView view; + QGraphicsScene scene; + scene.addItem(rect); + scene.setSceneRect(0,0,100,100); + view.setScene(&scene); + + view.show(); + QTest::qWaitForWindowShown(&view); + + QPoint centerPos = view.mapFromScene(rect->boundingRect().center()); + // Touch the button + QTest::touchEvent(view.viewport()).press(0, centerPos); + QTest::touchEvent(view.viewport()).release(0, centerPos); + // Touch outside of the button + QTest::touchEvent(view.viewport()).press(0, view.mapFromScene(QPoint(10, 10))); + QTest::touchEvent(view.viewport()).release(0, view.mapFromScene(QPoint(10, 10))); +} + QTEST_MAIN(tst_QTouchEvent) #include "tst_qtouchevent.moc" diff --git a/tests/auto/qurl/tst_qurl.cpp b/tests/auto/qurl/tst_qurl.cpp index f108f4c..72ce393 100644 --- a/tests/auto/qurl/tst_qurl.cpp +++ b/tests/auto/qurl/tst_qurl.cpp @@ -1832,7 +1832,7 @@ void tst_QUrl::compat_constructor_01_data() QTest::addColumn<QString>("res"); //next we fill it with data - QTest::newRow( "data0" ) << QString("Makefile") << QString("Makefile"); // nolonger add file by defualt + QTest::newRow( "data0" ) << QString("Makefile") << QString("Makefile"); // nolonger add file by default QTest::newRow( "data1" ) << QString("Makefile") << QString("Makefile"); QTest::newRow( "data2" ) << QString("ftp://ftp.qt.nokia.com/qt/INSTALL") << QString("ftp://ftp.qt.nokia.com/qt/INSTALL"); QTest::newRow( "data3" ) << QString("ftp://ftp.qt.nokia.com/qt/INSTALL") << QString("ftp://ftp.qt.nokia.com/qt/INSTALL"); diff --git a/tests/auto/qxmlstream/XML-Test-Suite/xmlconf/ibm/valid/P60/ibm60v01.xml b/tests/auto/qxmlstream/XML-Test-Suite/xmlconf/ibm/valid/P60/ibm60v01.xml index edf9fee..050a340 100644 --- a/tests/auto/qxmlstream/XML-Test-Suite/xmlconf/ibm/valid/P60/ibm60v01.xml +++ b/tests/auto/qxmlstream/XML-Test-Suite/xmlconf/ibm/valid/P60/ibm60v01.xml @@ -10,10 +10,10 @@ <!ATTLIST one chapter CDATA #IMPLIED>
<!ATTLIST two chapter CDATA #REQUIRED>
<!ATTLIST three chapter CDATA #FIXED "JavaBeans">
- <!ATTLIST four chapter CDATA 'defualt'>
+ <!ATTLIST four chapter CDATA 'default'>
]>
<Java><one chapter="Introduction"/>
<three chapter="JavaBeans"/>
Positive test
DefaultDecl attributes values IMPLIED, REQUIRED, FIXED and default
-</Java>
\ No newline at end of file +</Java>
|