diff options
Diffstat (limited to 'src/quick/items')
22 files changed, 280 insertions, 243 deletions
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index 1167f408f5..dab35f2a54 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -44,8 +44,10 @@ #include <private/qquickcontext2d_p.h> #include <private/qquickcontext2dtexture_p.h> #include <private/qsgadaptationlayer_p.h> +#include <qsgtextureprovider.h> #include <QtQuick/private/qquickpixmapcache_p.h> #include <QtGui/QGuiApplication> +#include <qsgtextureprovider.h> #include <qqmlinfo.h> #include <private/qqmlengine_p.h> @@ -1102,14 +1104,17 @@ bool QQuickCanvasItem::isImageLoaded(const QUrl& url) const QImage QQuickCanvasItem::toImage(const QRectF& rect) const { Q_D(const QQuickCanvasItem); - if (d->context) { - if (rect.isEmpty()) - return d->context->toImage(canvasWindow()); - else - return d->context->toImage(rect); - } - return QImage(); + if (!d->context) + return QImage(); + + const QRectF &rectSource = rect.isEmpty() ? canvasWindow() : rect; + const qreal dpr = window() ? window()->effectiveDevicePixelRatio() : qreal(1); + const QRectF rectScaled(rectSource.topLeft() * dpr, rectSource.size() * dpr); + + QImage image = d->context->toImage(rectScaled); + image.setDevicePixelRatio(dpr); + return image; } static const char* mimeToType(const QString &mime) diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index b9b701313e..1a6f530bfa 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -42,13 +42,16 @@ #include "qquickcanvasitem_p.h" #include <private/qquickcontext2dtexture_p.h> #include <private/qquickitem_p.h> +#if QT_CONFIG(quick_shadereffect) #include <QtQuick/private/qquickshadereffectsource_p.h> +#endif #include <qsgrendererinterface.h> #include <QtQuick/private/qsgcontext_p.h> #include <private/qquicksvgparser_p.h> +#if QT_CONFIG(quick_path) #include <private/qquickpath_p.h> - +#endif #include <private/qquickimage_p_p.h> #include <qqmlinfo.h> @@ -126,8 +129,6 @@ QT_BEGIN_NAMESPACE Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok); -#define DEGREES(t) ((t) * 180.0 / M_PI) - #define CHECK_CONTEXT(r) if (!r || !r->d()->context || !r->d()->context->bufferValid()) \ THROW_GENERIC_ERROR("Not a Context2D object"); @@ -567,9 +568,10 @@ struct QQuickJSContext2D : public QV4::Object static void method_set_shadowOffsetY(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); // should these two be on the proto? +#if QT_CONFIG(quick_path) static void method_get_path(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); static void method_set_path(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - +#endif static void method_get_font(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); static void method_set_font(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); static void method_get_textAlign(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); @@ -925,9 +927,9 @@ struct QQuickJSContext2DImageData : public QV4::Object static void method_get_height(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); static void method_get_data(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData); - static void markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *engine) { - static_cast<QQuickJSContext2DImageData::Data *>(that)->pixelData.mark(engine); - QV4::Object::markObjects(that, engine); + static void markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack) { + static_cast<QQuickJSContext2DImageData::Data *>(that)->pixelData.mark(markStack); + QV4::Object::markObjects(that, markStack); } }; @@ -958,7 +960,7 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionE *pixelData->d()->image = QImage(w, h, QImage::Format_ARGB32); pixelData->d()->image->fill(0x00000000); } else { - Q_ASSERT(image.width() == qRound(w) && image.height() == qRound(h)); + Q_ASSERT(image.width()== qRound(w * image.devicePixelRatio()) && image.height() == qRound(h * image.devicePixelRatio())); *pixelData->d()->image = image.format() == QImage::Format_ARGB32 ? image : image.convertToFormat(QImage::Format_ARGB32); } @@ -1639,7 +1641,7 @@ void QQuickJSContext2DPrototype::method_createConicalGradient(const QV4::Builtin if (callData->argc >= 3) { qreal x = callData->args[0].toNumber(); qreal y = callData->args[1].toNumber(); - qreal angle = DEGREES(callData->args[2].toNumber()); + qreal angle = qRadiansToDegrees(callData->args[2].toNumber()); if (!qt_is_finite(x) || !qt_is_finite(y)) { THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createConicalGradient(): Incorrect arguments"); } @@ -2032,6 +2034,7 @@ void QQuickJSContext2D::method_set_shadowOffsetY(const QV4::BuiltinFunction *, Q RETURN_UNDEFINED(); } +#if QT_CONFIG(quick_path) void QQuickJSContext2D::method_get_path(const QV4::BuiltinFunction *, QV4::Scope &scope, QV4::CallData *callData) { QV4::Scoped<QQuickJSContext2D> r(scope, callData->thisObject); @@ -2058,6 +2061,7 @@ void QQuickJSContext2D::method_set_path(const QV4::BuiltinFunction *, QV4::Scope r->d()->context->m_v4path.set(scope.engine, value); RETURN_UNDEFINED(); } +#endif // QT_CONFIG(quick_path) //rects /*! @@ -3364,7 +3368,7 @@ void QQuickContext2D::rotate(qreal angle) return; QTransform newTransform =state.matrix; - newTransform.rotate(DEGREES(angle)); + newTransform.rotate(qRadiansToDegrees(angle)); if (!newTransform.isInvertible()) { state.invertibleCTM = false; @@ -3373,7 +3377,7 @@ void QQuickContext2D::rotate(qreal angle) state.matrix = newTransform; buffer()->updateMatrix(state.matrix); - m_path = QTransform().rotate(-DEGREES(angle)).map(m_path); + m_path = QTransform().rotate(-qRadiansToDegrees(angle)).map(m_path); } void QQuickContext2D::shear(qreal h, qreal v) @@ -3770,8 +3774,8 @@ void QQuickContext2D::arc(qreal xc, qreal yc, qreal radius, qreal sar, qreal ear antiClockWise = !antiClockWise; //end hack - float sa = DEGREES(sar); - float ea = DEGREES(ear); + float sa = qRadiansToDegrees(sar); + float ea = qRadiansToDegrees(ear); double span = 0; @@ -4208,7 +4212,9 @@ QQuickContext2DEngineData::QQuickContext2DEngineData(QV4::ExecutionEngine *v4) proto->defineAccessorProperty(QStringLiteral("fillStyle"), QQuickJSContext2D::method_get_fillStyle, QQuickJSContext2D::method_set_fillStyle); proto->defineAccessorProperty(QStringLiteral("shadowColor"), QQuickJSContext2D::method_get_shadowColor, QQuickJSContext2D::method_set_shadowColor); proto->defineAccessorProperty(QStringLiteral("textBaseline"), QQuickJSContext2D::method_get_textBaseline, QQuickJSContext2D::method_set_textBaseline); +#if QT_CONFIG(quick_path) proto->defineAccessorProperty(QStringLiteral("path"), QQuickJSContext2D::method_get_path, QQuickJSContext2D::method_set_path); +#endif proto->defineAccessorProperty(QStringLiteral("lineJoin"), QQuickJSContext2D::method_get_lineJoin, QQuickJSContext2D::method_set_lineJoin); proto->defineAccessorProperty(QStringLiteral("lineWidth"), QQuickJSContext2D::method_get_lineWidth, QQuickJSContext2D::method_set_lineWidth); proto->defineAccessorProperty(QStringLiteral("textAlign"), QQuickJSContext2D::method_get_textAlign, QQuickJSContext2D::method_set_textAlign); diff --git a/src/quick/items/qquickdrag_p.h b/src/quick/items/qquickdrag_p.h index 357f72b3e7..17e9d8c690 100644 --- a/src/quick/items/qquickdrag_p.h +++ b/src/quick/items/qquickdrag_p.h @@ -248,7 +248,7 @@ class QQuickDragAttached : public QObject Q_PROPERTY(QObject *source READ source WRITE setSource NOTIFY sourceChanged RESET resetSource) Q_PROPERTY(QObject *target READ target NOTIFY targetChanged) Q_PROPERTY(QPointF hotSpot READ hotSpot WRITE setHotSpot NOTIFY hotSpotChanged) - Q_PROPERTY(QUrl imageSource READ imageSource WRITE setImageSource NOTIFY imageSourceChanged REVISION 8) + Q_PROPERTY(QUrl imageSource READ imageSource WRITE setImageSource NOTIFY imageSourceChanged) Q_PROPERTY(QStringList keys READ keys WRITE setKeys NOTIFY keysChanged) Q_PROPERTY(QVariantMap mimeData READ mimeData WRITE setMimeData NOTIFY mimeDataChanged) Q_PROPERTY(Qt::DropActions supportedActions READ supportedActions WRITE setSupportedActions NOTIFY supportedActionsChanged) diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 2671b9c9a2..19dd81b6fc 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -195,8 +195,8 @@ Item { */ /*! - \qmlproperty int QtQuick::MouseEvent::x - \qmlproperty int QtQuick::MouseEvent::y + \qmlproperty real QtQuick::MouseEvent::x + \qmlproperty real QtQuick::MouseEvent::y These properties hold the coordinates of the position supplied by the mouse event. */ @@ -342,8 +342,8 @@ Item { */ /*! - \qmlproperty int QtQuick::WheelEvent::x - \qmlproperty int QtQuick::WheelEvent::y + \qmlproperty real QtQuick::WheelEvent::x + \qmlproperty real QtQuick::WheelEvent::y These properties hold the coordinates of the position supplied by the wheel event. */ @@ -1225,9 +1225,24 @@ QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool i auto p = m_touchPoints.at(i); if (p->isAccepted()) continue; + // include points where item is the grabber bool isGrabber = p->exclusiveGrabber() == item; + // include newly pressed points inside the bounds bool isPressInside = p->state() == QQuickEventPoint::Pressed && item->contains(item->mapFromScene(p->scenePos())); - if (!(isGrabber || isPressInside || isFiltering)) + + // filtering: (childMouseEventFilter) include points that are grabbed by children of the target item + bool grabberIsChild = false; + auto parent = p->grabberItem(); + while (isFiltering && parent) { + if (parent == item) { + grabberIsChild = true; + break; + } + parent = parent->parentItem(); + } + bool filterRelevant = isFiltering && grabberIsChild; + + if (!(isGrabber || isPressInside || filterRelevant)) continue; const QTouchEvent::TouchPoint *tp = touchPointById(p->pointId()); diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 6306a48d48..40719c6324 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -255,6 +255,7 @@ QQuickFlickablePrivate::QQuickFlickablePrivate() , flickBoost(1.0), fixupMode(Normal), vTime(0), visibleArea(0) , flickableDirection(QQuickFlickable::AutoFlickDirection) , boundsBehavior(QQuickFlickable::DragAndOvershootBounds) + , boundsMovement(QQuickFlickable::FollowBoundsBehavior) , rebound(0) { } @@ -643,8 +644,10 @@ is finished. \section1 Limitations - \note Due to an implementation detail, items placed inside a Flickable cannot anchor to it by - \c id. Use \c parent instead. + \note Due to an implementation detail, items placed inside a Flickable + cannot anchor to the Flickable. Instead, use \l {Item::}{parent}, which + refers to the Flickable's \l contentItem. The size of the content item is + determined by \l contentWidth and \l contentHeight. */ /*! @@ -1575,16 +1578,18 @@ void QQuickFlickablePrivate::replayDelayedPress() void QQuickFlickablePrivate::setViewportX(qreal x) { Q_Q(QQuickFlickable); - if (pixelAligned) - x = -Round(-x); - - contentItem->setX(x); - if (contentItem->x() != x) - return; // reentered + qreal effectiveX = pixelAligned ? -Round(-x) : x; const qreal maxX = q->maxXExtent(); const qreal minX = q->minXExtent(); + if (boundsMovement == int(QQuickFlickable::StopAtBounds)) + effectiveX = qBound(maxX, effectiveX, minX); + + contentItem->setX(effectiveX); + if (contentItem->x() != effectiveX) + return; // reentered + qreal overshoot = 0.0; if (x <= maxX) overshoot = maxX - x; @@ -1600,16 +1605,18 @@ void QQuickFlickablePrivate::setViewportX(qreal x) void QQuickFlickablePrivate::setViewportY(qreal y) { Q_Q(QQuickFlickable); - if (pixelAligned) - y = -Round(-y); - - contentItem->setY(y); - if (contentItem->y() != y) - return; // reentered + qreal effectiveY = pixelAligned ? -Round(-y) : y; const qreal maxY = q->maxYExtent(); const qreal minY = q->minYExtent(); + if (boundsMovement == int(QQuickFlickable::StopAtBounds)) + effectiveY = qBound(maxY, effectiveY, minY); + + contentItem->setY(effectiveY); + if (contentItem->y() != effectiveY) + return; // reentered + qreal overshoot = 0.0; if (y <= maxY) overshoot = maxY - y; @@ -1869,8 +1876,9 @@ QQmlListProperty<QQuickItem> QQuickFlickable::flickableChildren() beyond the Flickable's boundaries, or overshoot the Flickable's boundaries when flicked. - This enables the feeling that the edges of the view are soft, - rather than a hard physical boundary. + When the \l boundsMovement is \c Flickable.FollowBoundsBehavior, a value + other than \c Flickable.StopAtBounds will give a feeling that the edges of + the view are soft, rather than a hard physical boundary. The \c boundsBehavior can be one of: @@ -1886,7 +1894,7 @@ QQmlListProperty<QQuickItem> QQuickFlickable::flickableChildren() boundary when flicked. \endlist - \sa horizontalOvershoot, verticalOvershoot + \sa horizontalOvershoot, verticalOvershoot, boundsMovement */ QQuickFlickable::BoundsBehavior QQuickFlickable::boundsBehavior() const { @@ -2303,7 +2311,8 @@ bool QQuickFlickable::filterMouseEvent(QQuickItem *receiver, QMouseEvent *event) bool receiverDisabled = receiver && !receiver->isEnabled(); bool stealThisEvent = d->stealMouse; - if ((stealThisEvent || contains(localPos)) && (!receiver || !receiver->keepMouseGrab() || receiverDisabled)) { + bool receiverKeepsGrab = receiver && (receiver->keepMouseGrab() || receiver->keepTouchGrab()); + if ((stealThisEvent || contains(localPos)) && (!receiver || !receiverKeepsGrab || receiverDisabled)) { QScopedPointer<QMouseEvent> mouseEvent(QQuickWindowPrivate::cloneMouseEvent(event, &localPos)); mouseEvent->setAccepted(false); @@ -2323,7 +2332,7 @@ bool QQuickFlickable::filterMouseEvent(QQuickItem *receiver, QMouseEvent *event) default: break; } - if ((receiver && stealThisEvent && !receiver->keepMouseGrab() && receiver != this) || receiverDisabled) { + if ((receiver && stealThisEvent && !receiverKeepsGrab && receiver != this) || receiverDisabled) { d->clearDelayedPress(); grabMouse(); } else if (d->delayedPressEvent) { @@ -2339,7 +2348,7 @@ bool QQuickFlickable::filterMouseEvent(QQuickItem *receiver, QMouseEvent *event) d->lastPosTime = -1; returnToBounds(); } - if (event->type() == QEvent::MouseButtonRelease || (receiver && receiver->keepMouseGrab() && !receiverDisabled)) { + if (event->type() == QEvent::MouseButtonRelease || (receiverKeepsGrab && !receiverDisabled)) { // mouse released, or another item has claimed the grab d->lastPosTime = -1; d->clearDelayedPress(); @@ -2696,7 +2705,11 @@ void QQuickFlickablePrivate::updateVelocity() The value is negative when the content is dragged or flicked beyond the beginning, and positive when beyond the end; \c 0.0 otherwise. - \sa verticalOvershoot, boundsBehavior + Whether the values are reported for dragging and/or flicking is determined by + \l boundsBehavior. The overshoot distance is reported even when \l boundsMovement + is \c Flickable.StopAtBounds. + + \sa verticalOvershoot, boundsBehavior, boundsMovement */ qreal QQuickFlickable::horizontalOvershoot() const { @@ -2713,7 +2726,11 @@ qreal QQuickFlickable::horizontalOvershoot() const The value is negative when the content is dragged or flicked beyond the beginning, and positive when beyond the end; \c 0.0 otherwise. - \sa horizontalOvershoot, boundsBehavior + Whether the values are reported for dragging and/or flicking is determined by + \l boundsBehavior. The overshoot distance is reported even when \l boundsMovement + is \c Flickable.StopAtBounds. + + \sa horizontalOvershoot, boundsBehavior, boundsMovement */ qreal QQuickFlickable::verticalOvershoot() const { @@ -2721,4 +2738,66 @@ qreal QQuickFlickable::verticalOvershoot() const return d->vData.overshoot; } +/*! + \qmlproperty enumeration QtQuick::Flickable::boundsMovement + \since 5.10 + + This property holds whether the flickable will give a feeling that the edges of the + view are soft, rather than a hard physical boundary. + + The \c boundsMovement can be one of: + + \list + \li Flickable.StopAtBounds - this allows implementing custom edge effects where the + contents do not follow drags or flicks beyond the bounds of the flickable. The values + of \l horizontalOvershoot and \l verticalOvershoot can be utilized to implement custom + edge effects. + \li Flickable.FollowBoundsBehavior (default) - whether the contents follow drags or + flicks beyond the bounds of the flickable is determined by \l boundsBehavior. + \endlist + + The following example keeps the contents within bounds and instead applies a flip + effect when flicked over horizontal bounds: + \code + Flickable { + id: flickable + boundsMovement: Flickable.StopAtBounds + boundsBehavior: Flickable.DragAndOvershootBounds + transform: Rotation { + axis { x: 0; y: 1; z: 0 } + origin.x: flickable.width / 2 + origin.y: flickable.height / 2 + angle: Math.min(30, Math.max(-30, flickable.horizontalOvershoot)) + } + } + \endcode + + The following example keeps the contents within bounds and instead applies an opacity + effect when dragged over vertical bounds: + \code + Flickable { + boundsMovement: Flickable.StopAtBounds + boundsBehavior: Flickable.DragOverBounds + opacity: Math.max(0.5, 1.0 - Math.abs(verticalOvershoot) / height) + } + \endcode + + \sa boundsBehavior, verticalOvershoot, horizontalOvershoot +*/ +QQuickFlickable::BoundsMovement QQuickFlickable::boundsMovement() const +{ + Q_D(const QQuickFlickable); + return d->boundsMovement; +} + +void QQuickFlickable::setBoundsMovement(BoundsMovement movement) +{ + Q_D(QQuickFlickable); + if (d->boundsMovement == movement) + return; + + d->boundsMovement = movement; + emit boundsMovementChanged(); +} + QT_END_NAMESPACE diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h index 52cade1472..7558ee7df8 100644 --- a/src/quick/items/qquickflickable_p.h +++ b/src/quick/items/qquickflickable_p.h @@ -80,6 +80,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickFlickable : public QQuickItem Q_PROPERTY(qreal verticalVelocity READ verticalVelocity NOTIFY verticalVelocityChanged) Q_PROPERTY(BoundsBehavior boundsBehavior READ boundsBehavior WRITE setBoundsBehavior NOTIFY boundsBehaviorChanged) + Q_PROPERTY(BoundsMovement boundsMovement READ boundsMovement WRITE setBoundsMovement NOTIFY boundsMovementChanged REVISION 10) Q_PROPERTY(QQuickTransition *rebound READ rebound WRITE setRebound NOTIFY reboundChanged) Q_PROPERTY(qreal maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity NOTIFY maximumFlickVelocityChanged) Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged) @@ -132,6 +133,15 @@ public: BoundsBehavior boundsBehavior() const; void setBoundsBehavior(BoundsBehavior); + enum BoundsMovement { + // StopAtBounds = 0x0, + FollowBoundsBehavior = 0x1 + }; + Q_ENUM(BoundsMovement) + + BoundsMovement boundsMovement() const; + void setBoundsMovement(BoundsMovement movement); + QQuickTransition *rebound() const; void setRebound(QQuickTransition *transition); @@ -237,6 +247,7 @@ Q_SIGNALS: void flickableDirectionChanged(); void interactiveChanged(); void boundsBehaviorChanged(); + Q_REVISION(10) void boundsMovementChanged(); void reboundChanged(); void maximumFlickVelocityChanged(); void flickDecelerationChanged(); diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h index 1ceff22dfc..8609a15fcd 100644 --- a/src/quick/items/qquickflickable_p_p.h +++ b/src/quick/items/qquickflickable_p_p.h @@ -247,6 +247,7 @@ public: QQuickFlickableVisibleArea *visibleArea; QQuickFlickable::FlickableDirection flickableDirection; QQuickFlickable::BoundsBehavior boundsBehavior; + QQuickFlickable::BoundsMovement boundsMovement; QQuickTransition *rebound; void viewportAxisMoved(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp index f3d7dc4b56..bf982117e8 100644 --- a/src/quick/items/qquickimage.cpp +++ b/src/quick/items/qquickimage.cpp @@ -559,7 +559,8 @@ void QQuickImage::updatePaintedGeometry() void QQuickImage::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { QQuickImageBase::geometryChanged(newGeometry, oldGeometry); - updatePaintedGeometry(); + if (newGeometry.size() != oldGeometry.size()) + updatePaintedGeometry(); } QRectF QQuickImage::boundingRect() const diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 1edc54aca2..bfc4a59851 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -6780,8 +6780,27 @@ bool QQuickItem::heightValid() const } /*! - \internal - */ + \since 5.10 + + Returns the size of the item. + + \sa setSize, width, height + */ + +QSizeF QQuickItem::size() const +{ + Q_D(const QQuickItem); + return QSizeF(d->width, d->height); +} + + +/*! + \since 5.10 + + Sets the size of the item to \a size. + + \sa size, setWidth, setHeight + */ void QQuickItem::setSize(const QSizeF &size) { Q_D(QQuickItem); @@ -8456,19 +8475,19 @@ struct QQuickItemWrapper : public QObjectWrapper { struct QQuickItemWrapper : public QV4::QObjectWrapper { V4_OBJECT2(QQuickItemWrapper, QV4::QObjectWrapper) - static void markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e); + static void markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack); }; DEFINE_OBJECT_VTABLE(QQuickItemWrapper); -void QQuickItemWrapper::markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e) +void QQuickItemWrapper::markObjects(QV4::Heap::Base *that, QV4::MarkStack *markStack) { QObjectWrapper::Data *This = static_cast<QObjectWrapper::Data *>(that); if (QQuickItem *item = static_cast<QQuickItem*>(This->object())) { for (QQuickItem *child : qAsConst(QQuickItemPrivate::get(item)->childItems)) - QV4::QObjectWrapper::markWrapper(child, e); + QV4::QObjectWrapper::markWrapper(child, markStack); } - QV4::QObjectWrapper::markObjects(that, e); + QV4::QObjectWrapper::markObjects(that, markStack); } quint64 QQuickItemPrivate::_q_createJSWrapper(QV4::ExecutionEngine *engine) diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index 279d052db9..1d174ca979 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -237,6 +237,7 @@ public: void setImplicitHeight(qreal); qreal implicitHeight() const; + QSizeF size() const; void setSize(const QSizeF &size); TransformOrigin transformOrigin() const; diff --git a/src/quick/items/qquickitemanimation.cpp b/src/quick/items/qquickitemanimation.cpp index 9873622f41..874130b137 100644 --- a/src/quick/items/qquickitemanimation.cpp +++ b/src/quick/items/qquickitemanimation.cpp @@ -327,7 +327,7 @@ QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &act } if (scale != 0) - rotation = qAtan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI; + rotation = qRadiansToDegrees(qAtan2(transform.m12() / scale, transform.m11() / scale)); else { qmlWarning(this) << QQuickParentAnimation::tr("Unable to preserve appearance under scale of 0"); ok = false; diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index eeffe1ee48..13f23c918a 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -273,7 +273,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType<QQuickAnchorSet>(); qmlRegisterType<QQuickAnchorAnimation>(uri, major, minor,"AnchorAnimation"); qmlRegisterType<QQuickParentAnimation>(uri, major, minor,"ParentAnimation"); -#if QT_CONFIG(quick_canvas) +#if QT_CONFIG(quick_path) qmlRegisterType<QQuickPathAnimation>("QtQuick",2,0,"PathAnimation"); qmlRegisterType<QQuickPathInterpolator>("QtQuick",2,0,"PathInterpolator"); #endif @@ -389,6 +389,8 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) #if QT_CONFIG(quick_shadereffect) qmlRegisterType<QQuickShaderEffectSource, 2>(uri, 2, 9, "ShaderEffectSource"); #endif + + qmlRegisterType<QQuickFlickable, 10>(uri, 2, 10, "Flickable"); } static void initResources() diff --git a/src/quick/items/qquickpainteditem_p.h b/src/quick/items/qquickpainteditem_p.h index 742e786335..3e160ed55a 100644 --- a/src/quick/items/qquickpainteditem_p.h +++ b/src/quick/items/qquickpainteditem_p.h @@ -51,7 +51,9 @@ // We mean it. // +#include "qquickpainteditem.h" #include "qquickitem_p.h" +#include "qquickpainteditem.h" #include <QtGui/qcolor.h> QT_BEGIN_NAMESPACE diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp index 70fc5fa65f..05882d0464 100644 --- a/src/quick/items/qquickpositioners.cpp +++ b/src/quick/items/qquickpositioners.cpp @@ -48,19 +48,8 @@ QT_BEGIN_NAMESPACE -// The default item change types that positioners are interested in. -static const QQuickItemPrivate::ChangeTypes explicitSizeItemChangeTypes = - QQuickItemPrivate::Geometry - | QQuickItemPrivate::SiblingOrder - | QQuickItemPrivate::Visibility - | QQuickItemPrivate::Destroyed; - -// The item change types for positioners that are only interested in the implicit -// size of the items they manage. These are used if useImplicitSize is true. -// useImplicitSize should be set in the constructor, before any items are added. -static const QQuickItemPrivate::ChangeTypes implicitSizeItemChangeTypes = - QQuickItemPrivate::ImplicitWidth - | QQuickItemPrivate::ImplicitHeight +static const QQuickItemPrivate::ChangeTypes watchedChanges + = QQuickItemPrivate::Geometry | QQuickItemPrivate::SiblingOrder | QQuickItemPrivate::Visibility | QQuickItemPrivate::Destroyed; @@ -68,15 +57,13 @@ static const QQuickItemPrivate::ChangeTypes implicitSizeItemChangeTypes = void QQuickBasePositionerPrivate::watchChanges(QQuickItem *other) { QQuickItemPrivate *otherPrivate = QQuickItemPrivate::get(other); - otherPrivate->addItemChangeListener(this, useImplicitSize - ? implicitSizeItemChangeTypes : explicitSizeItemChangeTypes); + otherPrivate->addItemChangeListener(this, watchedChanges); } void QQuickBasePositionerPrivate::unwatchChanges(QQuickItem* other) { QQuickItemPrivate *otherPrivate = QQuickItemPrivate::get(other); - otherPrivate->removeItemChangeListener(this, useImplicitSize - ? implicitSizeItemChangeTypes : explicitSizeItemChangeTypes); + otherPrivate->removeItemChangeListener(this, watchedChanges); } @@ -336,7 +323,7 @@ void QQuickBasePositioner::prePositioning() if (wIdx < 0) { d->watchChanges(child); posItem.isNew = true; - if (!childPrivate->explicitVisible || !d->itemWidth(child) || !d->itemHeight(child)) { + if (!childPrivate->explicitVisible || !child->width() || !child->height()) { posItem.isVisible = false; posItem.index = -1; unpositionedItems.append(posItem); @@ -358,7 +345,7 @@ void QQuickBasePositioner::prePositioning() PositionedItem *item = &oldItems[wIdx]; // Items are only omitted from positioning if they are explicitly hidden // i.e. their positioning is not affected if an ancestor is hidden. - if (!childPrivate->explicitVisible || !d->itemWidth(child) || !d->itemHeight(child)) { + if (!childPrivate->explicitVisible || !child->width() || !child->height()) { item->isVisible = false; item->index = -1; unpositionedItems.append(*item); @@ -957,7 +944,6 @@ QQuickColumn::QQuickColumn(QQuickItem *parent) void QQuickColumn::doPositioning(QSizeF *contentSize) { //Precondition: All items in the positioned list have a valid item pointer and should be positioned - QQuickBasePositionerPrivate *d = static_cast<QQuickBasePositionerPrivate*>(QQuickBasePositionerPrivate::get(this)); qreal voffset = topPadding(); const qreal padding = leftPadding() + rightPadding(); contentSize->setWidth(qMax(contentSize->width(), padding)); @@ -966,9 +952,9 @@ void QQuickColumn::doPositioning(QSizeF *contentSize) PositionedItem &child = positionedItems[ii]; positionItem(child.itemX() + leftPadding() - child.leftPadding, voffset, &child); child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); - contentSize->setWidth(qMax(contentSize->width(), d->itemWidth(child.item) + padding)); + contentSize->setWidth(qMax(contentSize->width(), child.item->width() + padding)); - voffset += d->itemHeight(child.item); + voffset += child.item->height(); voffset += spacing(); } @@ -1236,9 +1222,9 @@ void QQuickRow::doPositioning(QSizeF *contentSize) hoffsets << hoffset; } - contentSize->setHeight(qMax(contentSize->height(), d->itemHeight(child.item) + padding)); + contentSize->setHeight(qMax(contentSize->height(), child.item->height() + padding)); - hoffset += d->itemWidth(child.item); + hoffset += child.item->width(); hoffset += spacing(); } @@ -1259,7 +1245,7 @@ void QQuickRow::doPositioning(QSizeF *contentSize) int acc = 0; for (int ii = 0; ii < positionedItems.count(); ++ii) { PositionedItem &child = positionedItems[ii]; - hoffset = end - hoffsets[acc++] - d->itemWidth(child.item); + hoffset = end - hoffsets[acc++] - child.item->width(); positionItem(hoffset, child.itemY() + topPadding() - child.topPadding, &child); child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); } @@ -1760,12 +1746,10 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) break; const PositionedItem &child = positionedItems.at(childIndex++); - const qreal childWidth = d->itemWidth(child.item); - const qreal childHeight = d->itemHeight(child.item); - if (childWidth > maxColWidth[j]) - maxColWidth[j] = childWidth; - if (childHeight > maxRowHeight[i]) - maxRowHeight[i] = childHeight; + if (child.item->width() > maxColWidth[j]) + maxColWidth[j] = child.item->width(); + if (child.item->height() > maxRowHeight[i]) + maxRowHeight[i] = child.item->height(); } } } else { @@ -1780,12 +1764,10 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) break; const PositionedItem &child = positionedItems.at(childIndex++); - const qreal childWidth = d->itemWidth(child.item); - const qreal childHeight = d->itemHeight(child.item); - if (childWidth > maxColWidth[j]) - maxColWidth[j] = childWidth; - if (childHeight > maxRowHeight[i]) - maxRowHeight[i] = childHeight; + if (child.item->width() > maxColWidth[j]) + maxColWidth[j] = child.item->width(); + if (child.item->height() > maxRowHeight[i]) + maxRowHeight[i] = child.item->height(); } } } @@ -1827,22 +1809,20 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) for (int i = 0; i < positionedItems.count(); ++i) { PositionedItem &child = positionedItems[i]; qreal childXOffset = xoffset; - const qreal childWidth = d->itemWidth(child.item); - const qreal childHeight = d->itemHeight(child.item); if (effectiveHAlign() == AlignRight) - childXOffset += maxColWidth[curCol] - childWidth; + childXOffset += maxColWidth[curCol] - child.item->width(); else if (hItemAlign() == AlignHCenter) - childXOffset += (maxColWidth[curCol] - childWidth)/2.0; + childXOffset += (maxColWidth[curCol] - child.item->width())/2.0; if (!d->isLeftToRight()) childXOffset -= maxColWidth[curCol]; qreal alignYOffset = yoffset; if (m_vItemAlign == AlignVCenter) - alignYOffset += (maxRowHeight[curRow] - childHeight)/2.0; + alignYOffset += (maxRowHeight[curRow] - child.item->height())/2.0; else if (m_vItemAlign == AlignBottom) - alignYOffset += maxRowHeight[curRow] - childHeight; + alignYOffset += maxRowHeight[curRow] - child.item->height(); positionItem(childXOffset, alignYOffset, &child); child.updatePadding(leftPadding(), topPadding(), rightPadding(), bottomPadding()); @@ -2160,17 +2140,15 @@ void QQuickFlow::doPositioning(QSizeF *contentSize) for (int i = 0; i < positionedItems.count(); ++i) { PositionedItem &child = positionedItems[i]; - const qreal childWidth = d->itemWidth(child.item); - const qreal childHeight = d->itemHeight(child.item); if (d->flow == LeftToRight) { - if (widthValid() && hoffset != hoffset1 && hoffset + childWidth + hoffset2 > width()) { + if (widthValid() && hoffset != hoffset1 && hoffset + child.item->width() + hoffset2 > width()) { hoffset = hoffset1; voffset += linemax + spacing(); linemax = 0; } } else { - if (heightValid() && voffset != voffset1 && voffset + childHeight + bottomPadding() > height()) { + if (heightValid() && voffset != voffset1 && voffset + child.item->height() + bottomPadding() > height()) { voffset = voffset1; hoffset += linemax + spacing(); linemax = 0; @@ -2187,17 +2165,17 @@ void QQuickFlow::doPositioning(QSizeF *contentSize) child.bottomPadding = bottomPadding(); } - contentSize->setWidth(qMax(contentSize->width(), hoffset + childWidth + hoffset2)); - contentSize->setHeight(qMax(contentSize->height(), voffset + childHeight + bottomPadding())); + contentSize->setWidth(qMax(contentSize->width(), hoffset + child.item->width() + hoffset2)); + contentSize->setHeight(qMax(contentSize->height(), voffset + child.item->height() + bottomPadding())); if (d->flow == LeftToRight) { - hoffset += childWidth; + hoffset += child.item->width(); hoffset += spacing(); - linemax = qMax(linemax, childHeight); + linemax = qMax(linemax, child.item->height()); } else { - voffset += childHeight; + voffset += child.item->height(); voffset += spacing(); - linemax = qMax(linemax, childWidth); + linemax = qMax(linemax, child.item->width()); } } @@ -2212,7 +2190,7 @@ void QQuickFlow::doPositioning(QSizeF *contentSize) int acc = 0; for (int i = 0; i < positionedItems.count(); ++i) { PositionedItem &child = positionedItems[i]; - hoffset = end - hoffsets[acc++] - d->itemWidth(child.item); + hoffset = end - hoffsets[acc++] - child.item->width(); positionItemX(hoffset, &child); child.leftPadding = leftPadding(); child.rightPadding = rightPadding(); @@ -2236,18 +2214,4 @@ void QQuickFlow::reportConflictingAnchors() qmlWarning(this) << "Cannot specify anchors for items inside Flow." << " Flow will not function."; } -QQuickImplicitRow::QQuickImplicitRow(QQuickItem *parent) - : QQuickRow(parent) -{ - QQuickBasePositionerPrivate *d = QQuickBasePositioner::get(this); - d->useImplicitSize = true; -} - -QQuickImplicitGrid::QQuickImplicitGrid(QQuickItem *parent) - : QQuickGrid(parent) -{ - QQuickBasePositionerPrivate *d = QQuickBasePositioner::get(this); - d->useImplicitSize = true; -} - QT_END_NAMESPACE diff --git a/src/quick/items/qquickpositioners_p.h b/src/quick/items/qquickpositioners_p.h index cfe163b4c1..9ae7029d69 100644 --- a/src/quick/items/qquickpositioners_p.h +++ b/src/quick/items/qquickpositioners_p.h @@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE class QQuickBasePositionerPrivate; -class Q_QUICK_PRIVATE_EXPORT QQuickPositionerAttached : public QObject +class QQuickPositionerAttached : public QObject { Q_OBJECT @@ -132,11 +132,6 @@ public: static QQuickPositionerAttached *qmlAttachedProperties(QObject *obj); - static QQuickBasePositionerPrivate* get(QQuickBasePositioner *positioner) - { - return positioner->d_func(); - } - void updateAttachedProperties(QQuickPositionerAttached *specificProperty = 0, QQuickItem *specificPropertyOwner = 0) const; qreal padding() const; @@ -187,7 +182,7 @@ protected: virtual void doPositioning(QSizeF *contentSize)=0; virtual void reportConflictingAnchors()=0; - class Q_QUICK_PRIVATE_EXPORT PositionedItem + class PositionedItem { public : PositionedItem(QQuickItem *i); @@ -232,7 +227,7 @@ private: Q_DECLARE_PRIVATE(QQuickBasePositioner) }; -class Q_QUICK_PRIVATE_EXPORT QQuickColumn : public QQuickBasePositioner +class Q_AUTOTEST_EXPORT QQuickColumn : public QQuickBasePositioner { Q_OBJECT public: @@ -246,7 +241,7 @@ private: }; class QQuickRowPrivate; -class Q_QUICK_PRIVATE_EXPORT QQuickRow: public QQuickBasePositioner +class Q_AUTOTEST_EXPORT QQuickRow: public QQuickBasePositioner { Q_OBJECT Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged) @@ -271,7 +266,7 @@ private: }; class QQuickGridPrivate; -class Q_QUICK_PRIVATE_EXPORT QQuickGrid : public QQuickBasePositioner +class Q_AUTOTEST_EXPORT QQuickGrid : public QQuickBasePositioner { Q_OBJECT Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged) @@ -358,7 +353,7 @@ private: }; class QQuickFlowPrivate; -class Q_QUICK_PRIVATE_EXPORT QQuickFlow: public QQuickBasePositioner +class Q_AUTOTEST_EXPORT QQuickFlow: public QQuickBasePositioner { Q_OBJECT Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged) @@ -391,22 +386,6 @@ private: Q_DECLARE_PRIVATE(QQuickFlow) }; -class Q_QUICK_PRIVATE_EXPORT QQuickImplicitRow : public QQuickRow -{ - Q_OBJECT - -public: - QQuickImplicitRow(QQuickItem *parent = nullptr); -}; - -class Q_QUICK_PRIVATE_EXPORT QQuickImplicitGrid : public QQuickGrid -{ - Q_OBJECT - -public: - QQuickImplicitGrid(QQuickItem *parent = nullptr); -}; - QT_END_NAMESPACE @@ -414,8 +393,6 @@ QML_DECLARE_TYPE(QQuickColumn) QML_DECLARE_TYPE(QQuickRow) QML_DECLARE_TYPE(QQuickGrid) QML_DECLARE_TYPE(QQuickFlow) -QML_DECLARE_TYPE(QQuickImplicitRow) -QML_DECLARE_TYPE(QQuickImplicitGrid) QML_DECLARE_TYPE(QQuickBasePositioner) QML_DECLARE_TYPEINFO(QQuickBasePositioner, QML_HAS_ATTACHED_PROPERTIES) diff --git a/src/quick/items/qquickpositioners_p_p.h b/src/quick/items/qquickpositioners_p_p.h index 1a7051615c..0be4c56df6 100644 --- a/src/quick/items/qquickpositioners_p_p.h +++ b/src/quick/items/qquickpositioners_p_p.h @@ -89,14 +89,10 @@ public: QLazilyAllocated<ExtraData> extra; QQuickBasePositionerPrivate() - : spacing(0) - , type(QQuickBasePositioner::None) - , transitioner(0) - , positioningDirty(false) - , doingPositioning(false) - , anchorConflict(false) - , useImplicitSize(false) - , layoutDirection(Qt::LeftToRight) + : spacing(0), type(QQuickBasePositioner::None) + , transitioner(0), positioningDirty(false) + , doingPositioning(false), anchorConflict(false), layoutDirection(Qt::LeftToRight) + { } @@ -123,7 +119,6 @@ public: bool positioningDirty : 1; bool doingPositioning : 1; bool anchorConflict : 1; - bool useImplicitSize : 1; Qt::LayoutDirection layoutDirection; @@ -179,34 +174,6 @@ public: { } - void itemImplicitWidthChanged(QQuickItem *) override - { - Q_ASSERT(useImplicitSize); - setPositioningDirty(); - } - - void itemImplicitHeightChanged(QQuickItem *) override - { - Q_ASSERT(useImplicitSize); - setPositioningDirty(); - } - - qreal itemWidth(QQuickItem *item) const - { - if (Q_LIKELY(!useImplicitSize)) - return item->width(); - - return item->implicitWidth(); - } - - qreal itemHeight(QQuickItem *item) const - { - if (Q_LIKELY(!useImplicitSize)) - return item->height(); - - return item->implicitHeight(); - } - inline qreal padding() const { return extra.isAllocated() ? extra->padding : 0.0; } void setTopPadding(qreal value, bool reset = false); void setLeftPadding(qreal value, bool reset = false); diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp index 03d96aea1f..e2a20f9e7e 100644 --- a/src/quick/items/qquickrendercontrol.cpp +++ b/src/quick/items/qquickrendercontrol.cpp @@ -385,6 +385,9 @@ QImage QQuickRenderControl::grab() cd->syncSceneGraph(); render(); grabContent = qt_gl_read_framebuffer(d->window->size() * d->window->effectiveDevicePixelRatio(), false, false); + if (QQuickRenderControl::renderWindowFor(d->window)) { + grabContent.setDevicePixelRatio(d->window->effectiveDevicePixelRatio()); + } #endif } else if (d->window->rendererInterface()->graphicsApi() == QSGRendererInterface::Software) { QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window); diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp index 436d7b33ce..d317c1d19b 100644 --- a/src/quick/items/qquickshadereffect.cpp +++ b/src/quick/items/qquickshadereffect.cpp @@ -873,9 +873,11 @@ void QQuickShaderEffectPrivate::updatePolish() q->m_impl->maybeUpdateShaders(); } +#if QT_CONFIG(opengl) bool QQuickShaderEffect::isOpenGLShaderEffect() const { return m_glImpl != Q_NULLPTR; } +#endif QT_END_NAMESPACE diff --git a/src/quick/items/qquickshadereffect_p.h b/src/quick/items/qquickshadereffect_p.h index d269dc5e50..30bd018098 100644 --- a/src/quick/items/qquickshadereffect_p.h +++ b/src/quick/items/qquickshadereffect_p.h @@ -117,7 +117,9 @@ public: bool isComponentComplete() const; QString parseLog(); +#if QT_CONFIG(opengl) bool isOpenGLShaderEffect() const; +#endif Q_SIGNALS: void fragmentShaderChanged(); diff --git a/src/quick/items/qquickstateoperations.cpp b/src/quick/items/qquickstateoperations.cpp index b40a9e2843..a4ce13a199 100644 --- a/src/quick/items/qquickstateoperations.cpp +++ b/src/quick/items/qquickstateoperations.cpp @@ -101,7 +101,7 @@ void QQuickParentChangePrivate::doChange(QQuickItem *targetParent, QQuickItem *s } if (scale != 0) - rotation = qAtan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI; + rotation = qRadiansToDegrees(qAtan2(transform.m12() / scale, transform.m11() / scale)); else { qmlWarning(q) << QQuickParentChange::tr("Unable to preserve appearance under scale of 0"); ok = false; diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp index 555fd233b3..2dce3e9ec8 100644 --- a/src/quick/items/qquicktextcontrol.cpp +++ b/src/quick/items/qquicktextcontrol.cpp @@ -769,52 +769,8 @@ void QQuickTextControl::processEvent(QEvent *e, const QMatrix &matrix) case QEvent::ShortcutOverride: if (d->interactionFlags & Qt::TextEditable) { QKeyEvent* ke = static_cast<QKeyEvent *>(e); - if (ke->modifiers() == Qt::NoModifier - || ke->modifiers() == Qt::ShiftModifier - || ke->modifiers() == Qt::KeypadModifier) { - if (ke->key() < Qt::Key_Escape) { - ke->accept(); - } else { - switch (ke->key()) { - case Qt::Key_Return: - case Qt::Key_Enter: - case Qt::Key_Delete: - case Qt::Key_Home: - case Qt::Key_End: - case Qt::Key_Backspace: - case Qt::Key_Left: - case Qt::Key_Right: - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_Tab: - ke->accept(); - default: - break; - } - } -#if QT_CONFIG(shortcut) - } else if (ke == QKeySequence::Copy - || ke == QKeySequence::Paste - || ke == QKeySequence::Cut - || ke == QKeySequence::Redo - || ke == QKeySequence::Undo - || ke == QKeySequence::MoveToNextWord - || ke == QKeySequence::MoveToPreviousWord - || ke == QKeySequence::MoveToStartOfDocument - || ke == QKeySequence::MoveToEndOfDocument - || ke == QKeySequence::SelectNextWord - || ke == QKeySequence::SelectPreviousWord - || ke == QKeySequence::SelectStartOfLine - || ke == QKeySequence::SelectEndOfLine - || ke == QKeySequence::SelectStartOfBlock - || ke == QKeySequence::SelectEndOfBlock - || ke == QKeySequence::SelectStartOfDocument - || ke == QKeySequence::SelectEndOfDocument - || ke == QKeySequence::SelectAll - ) { + if (isCommonTextEditShortcut(ke)) ke->accept(); -#endif - } } break; default: diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 0105e84cd6..888b0cde85 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -748,6 +748,7 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber) QQuickItem *oldGrabber = q->mouseGrabberItem(); qCDebug(DBG_MOUSE_TARGET) << "grabber" << oldGrabber << "->" << grabber; + bool fromTouch = false; if (grabber && touchMouseId != -1 && touchMouseDevice) { // update the touch item for mouse touch id to the new grabber @@ -758,6 +759,7 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber) for (auto handler : point->passiveGrabbers()) point->cancelPassiveGrab(handler); } + fromTouch = true; } else { QQuickPointerEvent *event = QQuickPointerDevice::genericMouseDevice()->pointerEvent(); Q_ASSERT(event->pointCount() == 1); @@ -771,8 +773,11 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber) if (oldGrabber) { QEvent e(QEvent::UngrabMouse); QSet<QQuickItem *> hasFiltered; - if (!sendFilteredMouseEvent(oldGrabber->parentItem(), oldGrabber, &e, &hasFiltered)) + if (!sendFilteredMouseEvent(oldGrabber->parentItem(), oldGrabber, &e, &hasFiltered)) { oldGrabber->mouseUngrabEvent(); + if (fromTouch) + oldGrabber->touchUngrabEvent(); + } } } @@ -2503,7 +2508,6 @@ void QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *e } else for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem)) { QDragMoveEvent *moveEvent = static_cast<QDragMoveEvent *>(event); if (deliverDragEvent(grabber, **grabItem, moveEvent)) { - moveEvent->setAccepted(true); for (++grabItem; grabItem != grabber->end();) { QPointF p = (**grabItem)->mapFromScene(moveEvent->pos()); if ((**grabItem)->contains(p)) { @@ -2578,7 +2582,10 @@ bool QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickIte event->keyboardModifiers(), event->type()); QQuickDropEventEx::copyActions(&translatedEvent, *event); + translatedEvent.setAccepted(event->isAccepted()); QCoreApplication::sendEvent(item, &translatedEvent); + event->setAccepted(translatedEvent.isAccepted()); + event->setDropAction(translatedEvent.dropAction()); if (event->type() == QEvent::DragEnter) { if (translatedEvent.isAccepted()) { grabber->grab(item); @@ -2726,18 +2733,23 @@ bool QQuickWindowPrivate::sendFilteredPointerEvent(QQuickPointerEvent *event, QQ break; } + bool touchMouseUnset = (touchMouseId == -1); // Only deliver mouse event if it is the touchMouseId or it could become the touchMouseId - if (touchMouseId == -1 || touchMouseId == tp.id()) { + if (touchMouseUnset || touchMouseId == tp.id()) { // convert filteringParentTouchEvent (which is already transformed wrt local position, velocity, etc.) // into a synthetic mouse event, and let childMouseEventFilter() have another chance with that QScopedPointer<QMouseEvent> mouseEvent(touchToMouseEvent(t, tp, filteringParentTouchEvent.data(), item, false)); + // If a filtering item calls QQuickWindow::mouseGrabberItem(), it should + // report the touchpoint's grabber. Whenever we send a synthetic mouse event, + // touchMouseId and touchMouseDevice must be set, even if it's only temporarily and isn't grabbed. + touchMouseId = tp.id(); + touchMouseDevice = event->device(); if (filteringParent->childMouseEventFilter(item, mouseEvent.data())) { qCDebug(DBG_TOUCH) << "touch event intercepted as synth mouse event by childMouseEventFilter of " << filteringParent; if (t != QEvent::MouseButtonRelease) { qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << hex << tp.id() << "->" << filteringParent; - touchMouseId = tp.id(); - touchMouseDevice = event->device(); touchMouseDevice->pointerEvent()->pointById(tp.id())->setGrabberItem(filteringParent); + touchMouseUnset = false; // We want to leave touchMouseId and touchMouseDevice set filteringParent->grabMouse(); auto pointerEventPoint = pte->pointById(tp.id()); for (auto handler : pointerEventPoint->passiveGrabbers()) { @@ -2748,9 +2760,15 @@ bool QQuickWindowPrivate::sendFilteredPointerEvent(QQuickPointerEvent *event, QQ } ret = true; } + if (touchMouseUnset) { + // Now that we're done sending a synth mouse event, and it wasn't grabbed, + // the touchpoint is no longer acting as a synthetic mouse. Restore previous state. + touchMouseId = -1; + touchMouseDevice = nullptr; + } // Only one touchpoint can be treated as a synthetic mouse, so after childMouseEventFilter // has been called once, we're done with this loop over the touchpoints. - break; + break; } } } @@ -3542,6 +3560,11 @@ void QQuickWindow::setRenderTarget(QOpenGLFramebufferObject *fbo) The specified FBO must be created in the context of the window or one that shares with it. + \note \a fboId can also be set to 0. In this case rendering will target the + default framebuffer of whichever surface is current when the scenegraph + renders. \a size must still be valid, specifying the dimensions of the + surface. + \note This function only has an effect when using the default OpenGL scene graph adaptation. @@ -3648,6 +3671,7 @@ QImage QQuickWindow::grabWindow() bool alpha = format().alphaBufferSize() > 0 && color().alpha() < 255; QImage image = qt_gl_read_framebuffer(size() * effectiveDevicePixelRatio(), alpha, alpha); + image.setDevicePixelRatio(effectiveDevicePixelRatio()); d->cleanupNodesOnShutdown(); d->context->invalidate(); context.doneCurrent(); |