From 281c24d9169396a62f409de6dce3545f8d48ca8b Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Mon, 23 Apr 2018 13:13:31 +0200 Subject: Fix QQuickListViewPrivate::snapItemAt for lists with spacing If lists had spacing, snapping would have gaps where snapItemAt would return nullptr eventhough there were items above and below in the list. I.e. if we have a list with items of size 100, and a spacing of 100, and scroll to 110 (right below the first item), then the first item would fail because this is false: itemTop+itemSize()/2 >= pos (50 >= 110) And the next item (the one we should have snapped to), would fail because this is false: itemTop-prevItemSize/2 < pos (200-100/2 < 110) The meaning of first part was probably to see if the middle of the current item is inside the view. The meaning of the second part was probably to see if the middle of the previous item is outside the view. This patch refactors the code so it's more visible what's happening and fixes the bug by taking the spacing into account when computing the position of the halfway positions. Task-number: QTBUG-59852 Change-Id: I60eec0d16e91d2f22d70b97d11bcde5d88ac2997 Reviewed-by: Mitch Curtis --- src/quick/items/qquicklistview.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/quick/items') diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 33becd71ec..60f7efae12 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -538,8 +538,13 @@ FxViewItem *QQuickListViewPrivate::snapItemAt(qreal pos) qreal itemTop = item->position(); if (highlight && itemTop >= pos && item->endPosition() <= pos + highlight->size()) return item; - if (itemTop+item->size()/2 >= pos && itemTop-prevItemSize/2 < pos) + + // Middle of item and spacing (i.e. the middle of the distance between this item and the next + qreal halfwayToNextItem = itemTop + (item->size()+spacing) / 2; + qreal halfwayToPrevItem = itemTop - (prevItemSize+spacing) / 2; + if (halfwayToNextItem >= pos && halfwayToPrevItem < pos) snapItem = item; + prevItemSize = item->size(); } return snapItem; -- cgit v1.2.3 From 22bb2f5b68dc9e3c3608629629460513bf213938 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 25 Apr 2018 15:04:38 +0200 Subject: Add handling of device pixel ratio to animated sprites MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I472f61241d1875daf0de0a597bf27c019314f48f Task-number: QTBUG-50119 Reviewed-by: Mitch Curtis Reviewed-by: Morten Johan Sørvig --- src/quick/items/qquickanimatedsprite.cpp | 4 ++- src/quick/items/qquickimagebase_p.h | 2 +- src/quick/items/qquicksprite.cpp | 7 ++++- src/quick/items/qquicksprite_p.h | 12 ++++++++ src/quick/items/qquickspriteengine.cpp | 50 ++++++++++++++++++++------------ src/quick/items/qquickspritesequence.cpp | 2 +- 6 files changed, 54 insertions(+), 23 deletions(-) (limited to 'src/quick/items') diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp index 190c48ac88..887c30f999 100644 --- a/src/quick/items/qquickanimatedsprite.cpp +++ b/src/quick/items/qquickanimatedsprite.cpp @@ -527,6 +527,8 @@ void QQuickAnimatedSprite::setSource(QUrl arg) Q_D(QQuickAnimatedSprite); if (d->m_sprite->m_source != arg) { + const qreal targetDevicePixelRatio = (window() ? window()->effectiveDevicePixelRatio() : qApp->devicePixelRatio()); + d->m_sprite->setDevicePixelRatio(targetDevicePixelRatio); d->m_sprite->setSource(arg); Q_EMIT sourceChanged(arg); reloadImage(); @@ -713,7 +715,7 @@ QSGSpriteNode* QQuickAnimatedSprite::initNode() QSGSpriteNode *node = d->sceneGraphContext()->createSpriteNode(); - d->m_sheetSize = QSize(image.size()); + d->m_sheetSize = QSize(image.size() / image.devicePixelRatioF()); node->setTexture(window()->createTextureFromImage(image)); d->m_spriteEngine->start(0); node->setTime(0.0f); diff --git a/src/quick/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h index eb04a1d162..d8d0be9b8c 100644 --- a/src/quick/items/qquickimagebase_p.h +++ b/src/quick/items/qquickimagebase_p.h @@ -98,7 +98,7 @@ public: virtual void setAutoTransform(bool transform); bool autoTransform() const; - void resolve2xLocalFile(const QUrl &url, qreal targetDevicePixelRatio, QUrl *sourceUrl, qreal *sourceDevicePixelRatio); + static void resolve2xLocalFile(const QUrl &url, qreal targetDevicePixelRatio, QUrl *sourceUrl, qreal *sourceDevicePixelRatio); // Use a virtual rather than a signal->signal to avoid the huge // connect/conneciton overhead for this rare case. diff --git a/src/quick/items/qquicksprite.cpp b/src/quick/items/qquicksprite.cpp index 6b8567439b..8c59a68982 100644 --- a/src/quick/items/qquicksprite.cpp +++ b/src/quick/items/qquicksprite.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qquicksprite_p.h" +#include "qquickimagebase_p.h" #include #include #include @@ -222,6 +223,7 @@ QQuickSprite::QQuickSprite(QObject *parent) , m_frameDuration(unsetDuration) , m_frameDurationVariation(0) , m_frameSync(false) + , m_devicePixelRatio(1.0) { } @@ -265,7 +267,10 @@ void QQuickSprite::startImageLoading() if (!e) qWarning() << "QQuickSprite: Cannot find QQmlEngine - this class is only for use in QML and may not work"; } - m_pix.load(e, m_source); + QUrl loadUrl = m_source; + QQuickImageBase::resolve2xLocalFile(m_source, m_devicePixelRatio, &loadUrl, &m_devicePixelRatio); + + m_pix.load(e, loadUrl); } } diff --git a/src/quick/items/qquicksprite_p.h b/src/quick/items/qquicksprite_p.h index 8e119a80a9..fab9e75190 100644 --- a/src/quick/items/qquicksprite_p.h +++ b/src/quick/items/qquicksprite_p.h @@ -168,6 +168,16 @@ public: return m_frameSync; } + void setDevicePixelRatio(qreal dpr) + { + m_devicePixelRatio = dpr; + } + + qreal devicePixelRatio() const + { + return m_devicePixelRatio; + } + Q_SIGNALS: void sourceChanged(QUrl arg); @@ -308,6 +318,7 @@ private: friend class QQuickAnimatedSprite; friend class QQuickSpriteEngine; friend class QQuickStochasticEngine; + int m_generatedCount; int m_framesPerRow; int m_rowY; @@ -325,6 +336,7 @@ private: int m_frameDuration; int m_frameDurationVariation; bool m_frameSync; + qreal m_devicePixelRatio; QQuickPixmap m_pix; }; diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp index 1fd15e61e3..03f0fa94a4 100644 --- a/src/quick/items/qquickspriteengine.cpp +++ b/src/quick/items/qquickspriteengine.cpp @@ -390,6 +390,7 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) int w = 0; m_maxFrames = 0; m_imageStateCount = 0; + qreal pixelRatio = 1.0; for (QQuickSprite* state : qAsConst(m_sprites)) { if (state->frames() > m_maxFrames) @@ -413,6 +414,8 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) if (!state->m_frameHeight) state->m_frameHeight = img.height(); + pixelRatio = qMax(pixelRatio, state->devicePixelRatio()); + if (state->frames() * state->frameWidth() > maxSize){ struct helper{ static int divRoundUp(int a, int b){return (a+b-1)/b;} @@ -437,43 +440,58 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) } } + if (h > maxSize){ + qWarning() << "SpriteEngine: Too many animations to fit in one texture..."; + qWarning() << "SpriteEngine: Your texture max size today is " << maxSize; + return QImage(); + } + //maxFrames is max number in a line of the texture - QImage image(w, h, QImage::Format_ARGB32_Premultiplied); + QImage image(w * pixelRatio, h * pixelRatio, QImage::Format_ARGB32_Premultiplied); + image.setDevicePixelRatio(pixelRatio); image.fill(0); QPainter p(&image); int y = 0; for (QQuickSprite* state : qAsConst(m_sprites)) { QImage img(state->m_pix.image()); - int frameWidth = state->m_frameWidth; - int frameHeight = state->m_frameHeight; - if (img.height() == frameHeight && img.width() < maxSize){//Simple case - p.drawImage(0,y,img.copy(state->m_frameX,0,state->m_frames * frameWidth, frameHeight)); + const int frameWidth = state->m_frameWidth; + const int frameHeight = state->m_frameHeight; + const int imgHeight = img.height() / state->devicePixelRatio(); + const int imgWidth = img.width() / state->devicePixelRatio(); + if (imgHeight == frameHeight && imgWidth < maxSize){ //Simple case + p.drawImage(QRect(0, y, state->m_frames * frameWidth, frameHeight), + img, + QRect(state->m_frameX * state->devicePixelRatio(), 0, state->m_frames * frameWidth * state->devicePixelRatio(), frameHeight * state->devicePixelRatio())); state->m_rowStartX = 0; state->m_rowY = y; y += frameHeight; - }else{//Chopping up image case - state->m_framesPerRow = image.width()/frameWidth; + } else { //Chopping up image case + state->m_framesPerRow = w/frameWidth; state->m_rowY = y; int x = 0; int curX = state->m_frameX; int curY = state->m_frameY; int framesLeft = state->frames(); while (framesLeft > 0){ - if (image.width() - x + curX <= img.width()){//finish a row in image (dest) - int copied = image.width() - x; + if (w - x + curX <= imgWidth){//finish a row in image (dest) + int copied = w - x; framesLeft -= copied/frameWidth; - p.drawImage(x,y,img.copy(curX,curY,copied,frameHeight)); + p.drawImage(QRect(x, y, copied, frameHeight), + img, + QRect(curX * state->devicePixelRatio(), curY * state->devicePixelRatio(), copied * state->devicePixelRatio(), frameHeight * state->devicePixelRatio())); y += frameHeight; curX += copied; x = 0; - if (curX == img.width()){ + if (curX == imgWidth){ curX = 0; curY += frameHeight; } }else{//finish a row in img (src) - int copied = img.width() - curX; + int copied = imgWidth - curX; framesLeft -= copied/frameWidth; - p.drawImage(x,y,img.copy(curX,curY,copied,frameHeight)); + p.drawImage(QRect(x, y, copied, frameHeight), + img, + QRect(curX * state->devicePixelRatio(), curY * state->devicePixelRatio(), copied * state->devicePixelRatio(), frameHeight * state->devicePixelRatio())); curY += frameHeight; x += copied; curX = 0; @@ -484,12 +502,6 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) } } - if (image.height() > maxSize){ - qWarning() << "SpriteEngine: Too many animations to fit in one texture..."; - qWarning() << "SpriteEngine: Your texture max size today is " << maxSize; - return QImage(); - } - #ifdef SPRITE_IMAGE_DEBUG QString fPath = QDir::tempPath() + "/SpriteImage.%1.png"; int acc = 0; diff --git a/src/quick/items/qquickspritesequence.cpp b/src/quick/items/qquickspritesequence.cpp index 72761ab82b..df6a6e336e 100644 --- a/src/quick/items/qquickspritesequence.cpp +++ b/src/quick/items/qquickspritesequence.cpp @@ -226,7 +226,7 @@ QSGSpriteNode *QQuickSpriteSequence::initNode() QSGSpriteNode *node = d->sceneGraphContext()->createSpriteNode(); - d->m_sheetSize = QSize(image.size()); + d->m_sheetSize = QSize(image.size() / image.devicePixelRatioF()); node->setTexture(window()->createTextureFromImage(image)); d->m_spriteEngine->start(0); node->setTime(0.0f); -- cgit v1.2.3 From 2f397aa15a13efbadf6c1bc378bb134ac1e655c5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 23 Apr 2018 14:49:58 +0200 Subject: Fix crash when using drag with Drag.Automatic QQuickPointerTouchEvent::m_event is 0 when calling QQuickPointerTouchEvent::isPressEvent(). Add a convenience function with a check returning the Qt::TouchPointStates. Task-number: QTBUG-44976 Change-Id: I2433ec3c56adeda2de190ca46aed8413a1357c55 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickevents.cpp | 13 ++++++++++--- src/quick/items/qquickevents_p_p.h | 2 ++ 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'src/quick/items') diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 1be4bafe28..3343ea3fa7 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -1572,6 +1572,13 @@ void QQuickPointerTouchEvent::clearGrabbers() const { } } +Qt::TouchPointStates QQuickPointerTouchEvent::touchPointStates() const +{ + return m_event + ? static_cast(m_event)->touchPointStates() + : Qt::TouchPointStates(); +} + /*! Returns whether the given \a handler is the exclusive grabber of any touchpoint within this event. @@ -1586,17 +1593,17 @@ bool QQuickPointerTouchEvent::hasExclusiveGrabber(const QQuickPointerHandler *ha bool QQuickPointerTouchEvent::isPressEvent() const { - return static_cast(m_event)->touchPointStates() & Qt::TouchPointPressed; + return touchPointStates() & Qt::TouchPointPressed; } bool QQuickPointerTouchEvent::isUpdateEvent() const { - return static_cast(m_event)->touchPointStates() & (Qt::TouchPointMoved | Qt::TouchPointStationary); + return touchPointStates() & (Qt::TouchPointMoved | Qt::TouchPointStationary); } bool QQuickPointerTouchEvent::isReleaseEvent() const { - return static_cast(m_event)->touchPointStates() & Qt::TouchPointReleased; + return touchPointStates() & Qt::TouchPointReleased; } QVector QQuickPointerEvent::unacceptedPressedPointScenePositions() const diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h index 2a1e9dc184..00ee0e18f9 100644 --- a/src/quick/items/qquickevents_p_p.h +++ b/src/quick/items/qquickevents_p_p.h @@ -510,6 +510,8 @@ public: QTouchEvent *asTouchEvent() const; private: + Qt::TouchPointStates touchPointStates() const; + int m_pointCount = 0; QVector m_touchPoints; mutable QMouseEvent m_synthMouseEvent; -- cgit v1.2.3 From f9686bc68696ad1e99a0587f15d05300d003d990 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 9 Apr 2018 15:41:02 +0200 Subject: QQuickItem: Guard against null deref in transformations Change-Id: Ieb14322c104d816842e04e521b556bfc11855f1c Task-number: QTBUG-67024 Reviewed-by: Robin Burchell Reviewed-by: Michael Brasser --- src/quick/items/qquickitem.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/quick/items') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 3a0aea517c..3d650bf223 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -3134,6 +3134,9 @@ void QQuickItemPrivate::itemToParentTransform(QTransform &t) const */ QTransform QQuickItemPrivate::windowToGlobalTransform() const { + if (Q_UNLIKELY(window == nullptr)) + return QTransform(); + QPoint quickWidgetOffset; QWindow *renderWindow = QQuickRenderControl::renderWindowFor(window, &quickWidgetOffset); QPointF pos = (renderWindow ? renderWindow : window)->mapToGlobal(quickWidgetOffset); @@ -3145,6 +3148,9 @@ QTransform QQuickItemPrivate::windowToGlobalTransform() const */ QTransform QQuickItemPrivate::globalToWindowTransform() const { + if (Q_UNLIKELY(window == nullptr)) + return QTransform(); + QPoint quickWidgetOffset; QWindow *renderWindow = QQuickRenderControl::renderWindowFor(window, &quickWidgetOffset); QPointF pos = (renderWindow ? renderWindow : window)->mapToGlobal(quickWidgetOffset); -- cgit v1.2.3 From a609554c031fd57d9a2a3905f5a02cc6b4aa19e9 Mon Sep 17 00:00:00 2001 From: Louis du Verdier Date: Mon, 2 Apr 2018 20:25:37 +0200 Subject: Fix crash when changing the source of AnimatedImage after a frame change QMovie emits the signals updated() and frameChanged(), and restarts right after its timer to prepare for the next frame. Since AnimatedImage destroys its underlying QMovie when its source changes, the lines after emit frameChanged() in QMovie will use free'd memory and will most of the time produce a crash. This fix delays the destruction of the underlying QMovie of AnimatedImage using deleteLater() to prevent this kind of behavior from happening without impact/behavior change in the code of QMovie. Unit tests added as well to cover this situation. This commit also fixes a similar crash when Component.onCompleted is called and when the source changes in the associated callback. Task-number: QTBUG-67427 Change-Id: Ic6568a1bc251e5fa2ee1cf8e5f50eaa56c3007db Reviewed-by: VaL Doroshchuk Reviewed-by: Shawn Rutledge Reviewed-by: Louis du Verdier --- src/quick/items/qquickanimatedimage.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/quick/items') diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp index 26dfdb07a6..075c4a7d72 100644 --- a/src/quick/items/qquickanimatedimage.cpp +++ b/src/quick/items/qquickanimatedimage.cpp @@ -426,15 +426,18 @@ void QQuickAnimatedImage::movieRequestFinished() } bool pausedAtStart = d->paused; - if (d->playing) + if (d->movie && d->playing) d->movie->start(); - if (pausedAtStart) + if (d->movie && pausedAtStart) d->movie->setPaused(true); - if (d->paused || !d->playing) { + if (d->movie && (d->paused || !d->playing)) { d->movie->jumpToFrame(d->presetCurrentFrame); d->presetCurrentFrame = 0; } - d->setPixmap(*d->infoForCurrentFrame(qmlEngine(this))); + + QQuickPixmap *pixmap = d->infoForCurrentFrame(qmlEngine(this)); + if (pixmap) + d->setPixmap(*pixmap); if (isPlaying() != d->oldPlaying) emit playingChanged(); @@ -512,7 +515,10 @@ void QQuickAnimatedImagePrivate::setMovie(QMovie *m) Q_Q(QQuickAnimatedImage); const int oldFrameCount = q->frameCount(); - delete movie; + if (movie) { + movie->disconnect(); + movie->deleteLater(); + } movie = m; if (oldFrameCount != q->frameCount()) -- cgit v1.2.3 From 1f3713a2b40a467e8a8c552d0980dbdd9f7a1ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Fri, 11 May 2018 13:36:52 +0200 Subject: Fix bug where Ungrab event was not sent clearGrabbers() will also clear QQuickWindow::mouseGrabberItem(), so we have to retrieve a copy of the mouse grabber item in advance of calling clearGrabbers(). This could happen when a filtering parent actually called grabMouse() on mouse release(!) event. Change-Id: I287214dbdff802707be625d73c38dd9c5d723aef Task-number: QTBUG-68030 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickwindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/quick/items') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 48eba6a7a0..0f617733c4 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -2311,8 +2311,9 @@ void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event) deliverMouseEvent(event->asPointerMouseEvent()); // failsafe: never allow any kind of grab to persist after release if (event->isReleaseEvent() && event->buttons() == Qt::NoButton) { + QQuickItem *oldGrabber = q->mouseGrabberItem(); event->clearGrabbers(); - sendUngrabEvent(q->mouseGrabberItem(), false); + sendUngrabEvent(oldGrabber, false); } } else if (event->asPointerTouchEvent()) { deliverTouchEvent(event->asPointerTouchEvent()); -- cgit v1.2.3 From 28d849c059dfe6bf957cb1fe46e66815c87d50e9 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 7 May 2018 14:04:17 +0200 Subject: MouseArea: set pressed state to Qt::NoButton not nullptr Correction to 499ec43937e926e4f2fa57a9baa455fcb3862262 Change-Id: I9f9fb7cf3a0a04611e7f0a31f57147fbbc03c1a5 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickmousearea.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick/items') diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index 052da9fe82..c9316c0406 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -910,7 +910,7 @@ void QQuickMouseArea::ungrabMouse() if (d->pressed) { // if our mouse grab has been removed (probably by Flickable), fix our // state - d->pressed = nullptr; + d->pressed = Qt::NoButton; d->stealMouse = false; d->doubleClick = false; d->overThreshold = false; -- cgit v1.2.3 From a6b740869d369dacb8700042aa5da35183a03b5a Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Wed, 9 May 2018 14:00:07 +0900 Subject: Fix build without features.gestures Change-Id: Id2fb6419be9a35ddaa24106d3022e72070cb908d Reviewed-by: Shawn Rutledge Reviewed-by: Oswald Buddenhagen --- src/quick/items/qquickevents.cpp | 11 ++++++++++- src/quick/items/qquickevents_p_p.h | 8 ++++++++ src/quick/items/qquickwindow.cpp | 6 ++++++ 3 files changed, 24 insertions(+), 1 deletion(-) (limited to 'src/quick/items') diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 3343ea3fa7..d964f2bb32 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -1388,6 +1388,7 @@ void QQuickPointerTouchEvent::localize(QQuickItem *target) point->localizePosition(target); } +#if QT_CONFIG(gestures) QQuickPointerEvent *QQuickPointerNativeGestureEvent::reset(QEvent *event) { auto ev = static_cast(event); @@ -1417,6 +1418,7 @@ void QQuickPointerNativeGestureEvent::localize(QQuickItem *target) { m_gesturePoint->localizePosition(target); } +#endif // QT_CONFIG(gestures) QQuickEventPoint *QQuickPointerMouseEvent::point(int i) const { if (i == 0) @@ -1430,11 +1432,13 @@ QQuickEventPoint *QQuickPointerTouchEvent::point(int i) const { return nullptr; } +#if QT_CONFIG(gestures) QQuickEventPoint *QQuickPointerNativeGestureEvent::point(int i) const { if (i == 0) return m_gesturePoint; return nullptr; } +#endif // QT_CONFIG(gestures) QQuickEventPoint::QQuickEventPoint(QQuickPointerEvent *parent) : QObject(parent), m_pointId(0), m_exclusiveGrabber(nullptr), m_timestamp(0), m_pressTimestamp(0), @@ -1662,6 +1666,7 @@ QMouseEvent *QQuickPointerTouchEvent::syntheticMouseEvent(int pointID, QQuickIte return &m_synthMouseEvent; } +#if QT_CONFIG(gestures) /*! Returns the exclusive grabber of this event, if any, in a vector. */ @@ -1719,6 +1724,7 @@ qreal QQuickPointerNativeGestureEvent::value() const { return static_cast(m_event)->value(); } +#endif // QT_CONFIG(gestures) /*! \internal @@ -1742,12 +1748,13 @@ QQuickEventPoint *QQuickPointerTouchEvent::pointById(int pointId) const { return nullptr; } +#if QT_CONFIG(gestures) QQuickEventPoint *QQuickPointerNativeGestureEvent::pointById(int pointId) const { if (m_gesturePoint && pointId == m_gesturePoint->pointId()) return m_gesturePoint; return nullptr; } - +#endif /*! \internal @@ -1866,6 +1873,7 @@ QTouchEvent *QQuickPointerTouchEvent::asTouchEvent() const return static_cast(m_event); } +#if QT_CONFIG(gestures) bool QQuickPointerNativeGestureEvent::allPointsAccepted() const { return m_gesturePoint->isAccepted(); } @@ -1878,6 +1886,7 @@ bool QQuickPointerNativeGestureEvent::allPointsGrabbed() const { return m_gesturePoint->exclusiveGrabber() != nullptr; } +#endif // QT_CONFIG(gestures) #ifndef QT_NO_DEBUG_STREAM diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h index 00ee0e18f9..bb6726706d 100644 --- a/src/quick/items/qquickevents_p_p.h +++ b/src/quick/items/qquickevents_p_p.h @@ -66,7 +66,9 @@ QT_BEGIN_NAMESPACE class QQuickPointerDevice; class QQuickPointerEvent; class QQuickPointerMouseEvent; +#if QT_CONFIG(gestures) class QQuickPointerNativeGestureEvent; +#endif class QQuickPointerTabletEvent; class QQuickPointerTouchEvent; class QQuickPointerHandler; @@ -414,11 +416,15 @@ public: // helpers for C++ only (during event delivery) virtual QQuickPointerMouseEvent *asPointerMouseEvent() { return nullptr; } virtual QQuickPointerTouchEvent *asPointerTouchEvent() { return nullptr; } virtual QQuickPointerTabletEvent *asPointerTabletEvent() { return nullptr; } +#if QT_CONFIG(gestures) virtual QQuickPointerNativeGestureEvent *asPointerNativeGestureEvent() { return nullptr; } +#endif virtual const QQuickPointerMouseEvent *asPointerMouseEvent() const { return nullptr; } virtual const QQuickPointerTouchEvent *asPointerTouchEvent() const { return nullptr; } virtual const QQuickPointerTabletEvent *asPointerTabletEvent() const { return nullptr; } +#if QT_CONFIG(gestures) virtual const QQuickPointerNativeGestureEvent *asPointerNativeGestureEvent() const { return nullptr; } +#endif virtual bool allPointsAccepted() const = 0; virtual bool allUpdatedPointsAccepted() const = 0; virtual bool allPointsGrabbed() const = 0; @@ -519,6 +525,7 @@ private: Q_DISABLE_COPY(QQuickPointerTouchEvent) }; +#if QT_CONFIG(gestures) class Q_QUICK_PRIVATE_EXPORT QQuickPointerNativeGestureEvent : public QQuickPointerEvent { Q_OBJECT @@ -553,6 +560,7 @@ private: Q_DISABLE_COPY(QQuickPointerNativeGestureEvent) }; +#endif // QT_CONFIG(gestures) // ### Qt 6: move this to qtbase, replace QTouchDevice and the enums in QTabletEvent diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 0f617733c4..535770e9f9 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -2225,8 +2225,10 @@ QQuickPointerEvent *QQuickWindowPrivate::queryPointerEventInstance(QQuickPointer for (QQuickPointerEvent *e : pointerEventInstances) { // If device can generate native gestures (e.g. a trackpad), there might be two QQuickPointerEvents: // QQuickPointerNativeGestureEvent and QQuickPointerTouchEvent. Use eventType to disambiguate. +#if QT_CONFIG(gestures) if (eventType == QEvent::NativeGesture && !qobject_cast(e)) continue; +#endif // Otherwise we assume there's only one event type per device. // More disambiguation tests might need to be added above if that changes later. if (e->device() == device) @@ -2250,9 +2252,11 @@ QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QQuickPointerDevic break; case QQuickPointerDevice::TouchPad: case QQuickPointerDevice::TouchScreen: +#if QT_CONFIG(gestures) if (eventType == QEvent::NativeGesture) ev = new QQuickPointerNativeGestureEvent(q, device); else // assume QEvent::Type is one of TouchBegin/Update/End +#endif ev = new QQuickPointerTouchEvent(q, device); break; default: @@ -2287,9 +2291,11 @@ QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QEvent *event) con dev = QQuickPointerDevice::touchDevice(static_cast(event)->device()); break; // TODO tablet event types +#if QT_CONFIG(gestures) case QEvent::NativeGesture: dev = QQuickPointerDevice::touchDevice(static_cast(event)->device()); break; +#endif default: break; } -- cgit v1.2.3 From 9ef0d2da99f4593d50c16912d00bef121bb76f9b Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Thu, 26 Apr 2018 13:53:54 +0200 Subject: Fix for input method commit that ends with newline If the input method event contains a commit text that ends with a newline, text, the commit string is inserted first. This changes the current block. This change makes sure that we apply the formatting changes (including removing the old preedit text) to the old block in this specific case. This is a copy of change 6cece0f43a18dc8c9dbf5bc49ce515714f090725 in qtbase, since the code is duplicated. Task-number: QTBUG-67836 Change-Id: I531d3f1dce51d840acc0ef7fda9e7affb3192327 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/items/qquicktextcontrol.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/quick/items') diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp index e3080dfe48..1cb12235c1 100644 --- a/src/quick/items/qquicktextcontrol.cpp +++ b/src/quick/items/qquicktextcontrol.cpp @@ -1304,8 +1304,12 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) cursor.removeSelectedText(); } + QTextBlock block; + // insert commit string if (!e->commitString().isEmpty() || e->replacementLength()) { + if (e->commitString().endsWith(QChar::LineFeed)) + block = cursor.block(); // Remember the block where the preedit text is QTextCursor c = cursor; c.setPosition(c.position() + e->replacementStart()); c.setPosition(c.position() + e->replacementLength(), QTextCursor::KeepAnchor); @@ -1324,7 +1328,9 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) } } - QTextBlock block = cursor.block(); + if (!block.isValid()) + block = cursor.block(); + QTextLayout *layout = block.layout(); if (isGettingInput) { layout->setPreeditArea(cursor.position() - block.position(), e->preeditString()); -- cgit v1.2.3 From be4c4877b35ad1b6983cf194e61f0dad1d123af5 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Sat, 12 May 2018 00:12:24 +0200 Subject: Pass the arguments correctly to QRadialGradient The parameters for createRadialGradient indicate the position and radius for the two circles. Therefore the radius arguments should be used with their respective circle positions. Task-number: QTBUG-67960 Change-Id: Ifacba4d43939bafeed451e713250f716a11d30d1 Reviewed-by: Shawn Rutledge --- src/quick/items/context2d/qquickcontext2d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick/items') diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index af8048f2e4..addcf9b540 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -1637,7 +1637,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(const QV4::Scoped gradient(scope, scope.engine->memoryManager->allocObject()); QV4::ScopedObject p(scope, ed->gradientProto.value()); gradient->setPrototype(p); - *gradient->d()->brush = QRadialGradient(QPointF(x1, y1), r0+r1, QPointF(x0, y0)); + *gradient->d()->brush = QRadialGradient(QPointF(x1, y1), r1, QPointF(x0, y0), r0); RETURN_RESULT(*gradient); } -- cgit v1.2.3 From 710f9507c0ebf01d9e9f717e676b9c3b1b94ee8a Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 7 May 2018 14:56:26 +0200 Subject: setGrabberItem: consistently call touchUngrabEvent or mouseUngrabEvent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calling grabberItem() to get the old grabber must come before setting m_exclusiveGrabber. Then we call oldGrabberItem->touchUngrabEvent() or oldGrabberItem->mouseUngrabEvent() as appropriate. Now the responsibility for this is moved from QQuickItem::grabMouse() to QQuickEventPoint::setGrabberItem() (which it calls). Task-number: QTBUG-65648 Change-Id: Ia6219cb798d7f671ccc4006d51eeb87dbdbda3ef Reviewed-by: Jan Arve Sæther --- src/quick/items/qquickevents.cpp | 10 ++++++---- src/quick/items/qquickitem.cpp | 5 +---- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'src/quick/items') diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index d964f2bb32..d020ad7c4c 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -849,14 +849,16 @@ void QQuickEventPoint::setGrabberItem(QQuickItem *grabber) qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << hex << m_pointId << pointStateString(this) << ": grab" << m_exclusiveGrabber << "->" << grabber; } + QQuickItem *oldGrabberItem = grabberItem(); m_exclusiveGrabber = QPointer(grabber); m_grabberIsHandler = false; m_sceneGrabPos = m_scenePos; - QQuickItem *oldGrabberItem = grabberItem(); - if (oldGrabberHandler) + if (oldGrabberHandler) { oldGrabberHandler->onGrabChanged(oldGrabberHandler, (grabber ? CancelGrabExclusive : UngrabExclusive), this); - else if (oldGrabberItem && oldGrabberItem != grabber && grabber && pointerEvent()->asPointerTouchEvent()) - oldGrabberItem->touchUngrabEvent(); + } else if (oldGrabberItem && oldGrabberItem != grabber && grabber && grabber->window()) { + QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(grabber->window()); + windowPriv->sendUngrabEvent(oldGrabberItem, windowPriv->isDeliveringTouchAsMouse()); + } for (QPointer passiveGrabber : m_passiveGrabbers) passiveGrabber->onGrabChanged(passiveGrabber, OverrideGrabPassive, this); } diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 3d650bf223..70bb7db2b0 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -7462,11 +7462,8 @@ void QQuickItem::grabMouse() auto point = fromTouch ? windowPriv->pointerEventInstance(windowPriv->touchMouseDevice)->pointById(windowPriv->touchMouseId) : windowPriv->pointerEventInstance(QQuickPointerDevice::genericMouseDevice())->point(0); - if (point) { - QQuickItem *oldGrabber = point->grabberItem(); + if (point) point->setGrabberItem(this); - windowPriv->sendUngrabEvent(oldGrabber, fromTouch); - } } /*! -- cgit v1.2.3 From b7a1bcd83a8f68185b617b860cef6f2d2d7c8d9b Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 1 Jun 2018 11:08:59 +0200 Subject: Fix subrect of mismatched dpr sprite image Scale the subrect to fit image dpr. Task-number: QTBUG-68490 Task-number: QTBUG-68582 Change-Id: I6b0a9af73013dc6cf2b65103d5868f45da8e338e Reviewed-by: Mitch Curtis --- src/quick/items/qquickspriteengine.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/quick/items') diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp index 03f0fa94a4..be297bbe76 100644 --- a/src/quick/items/qquickspriteengine.cpp +++ b/src/quick/items/qquickspriteengine.cpp @@ -456,12 +456,12 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) QImage img(state->m_pix.image()); const int frameWidth = state->m_frameWidth; const int frameHeight = state->m_frameHeight; - const int imgHeight = img.height() / state->devicePixelRatio(); - const int imgWidth = img.width() / state->devicePixelRatio(); + const int imgHeight = img.height() / img.devicePixelRatioF(); + const int imgWidth = img.width() / img.devicePixelRatioF(); if (imgHeight == frameHeight && imgWidth < maxSize){ //Simple case p.drawImage(QRect(0, y, state->m_frames * frameWidth, frameHeight), img, - QRect(state->m_frameX * state->devicePixelRatio(), 0, state->m_frames * frameWidth * state->devicePixelRatio(), frameHeight * state->devicePixelRatio())); + QRect(state->m_frameX * img.devicePixelRatioF(), 0, state->m_frames * frameWidth * img.devicePixelRatioF(), frameHeight * img.devicePixelRatioF())); state->m_rowStartX = 0; state->m_rowY = y; y += frameHeight; @@ -478,7 +478,7 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) framesLeft -= copied/frameWidth; p.drawImage(QRect(x, y, copied, frameHeight), img, - QRect(curX * state->devicePixelRatio(), curY * state->devicePixelRatio(), copied * state->devicePixelRatio(), frameHeight * state->devicePixelRatio())); + QRect(curX * img.devicePixelRatioF(), curY * img.devicePixelRatioF(), copied * img.devicePixelRatioF(), frameHeight * img.devicePixelRatioF())); y += frameHeight; curX += copied; x = 0; @@ -491,7 +491,7 @@ QImage QQuickSpriteEngine::assembledImage(int maxSize) framesLeft -= copied/frameWidth; p.drawImage(QRect(x, y, copied, frameHeight), img, - QRect(curX * state->devicePixelRatio(), curY * state->devicePixelRatio(), copied * state->devicePixelRatio(), frameHeight * state->devicePixelRatio())); + QRect(curX * img.devicePixelRatioF(), curY * img.devicePixelRatioF(), copied * img.devicePixelRatioF(), frameHeight * img.devicePixelRatioF())); curY += frameHeight; x += copied; curX = 0; -- cgit v1.2.3