diff options
Diffstat (limited to 'src/quick/items')
-rw-r--r-- | src/quick/items/qquickitem.cpp | 91 | ||||
-rw-r--r-- | src/quick/items/qquickitem.h | 7 | ||||
-rw-r--r-- | src/quick/items/qquickitem_p.h | 6 | ||||
-rw-r--r-- | src/quick/items/qquickmousearea.cpp | 25 | ||||
-rw-r--r-- | src/quick/items/qquickmousearea_p.h | 2 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 50 | ||||
-rw-r--r-- | src/quick/items/qquickwindow_p.h | 7 |
7 files changed, 169 insertions, 19 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index fefddad4b6..5930b5fb0b 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -68,6 +68,10 @@ #include <private/qqmlaccessors_p.h> #include <QtQuick/private/qquickaccessibleattached_p.h> +#ifndef QT_NO_CURSOR +# include <QtGui/qcursor.h> +#endif + #include <float.h> // XXX todo Check that elements that create items handle memory correctly after visual ownership change @@ -2266,6 +2270,10 @@ void QQuickItemPrivate::derefWindow() } if (c->mouseGrabberItem == q) c->mouseGrabberItem = 0; +#ifndef QT_NO_CURSOR + if (c->cursorItem == q) + c->cursorItem = 0; +#endif if ( hoverEnabled ) c->hoverItems.removeAll(q); if (itemNodeInstance) @@ -2429,6 +2437,7 @@ QQuickItemPrivate::QQuickItemPrivate() , inheritMirrorFromItem(false) , isAccessible(false) , culled(false) + , hasCursor(false) , dirtyAttributes(0) , nextDirtyItem(0) , prevDirtyItem(0) @@ -5113,6 +5122,88 @@ void QQuickItem::setAcceptHoverEvents(bool enabled) d->hoverEnabled = enabled; } +#ifndef QT_NO_CURSOR + + +/*! + Returns the cursor shape for this item. + + The mouse cursor will assume this shape when it is over this + item, unless an override cursor is set. + See the \l{Qt::CursorShape}{list of predefined cursor objects} for a + range of useful shapes. + + If no cursor shape has been set this returns a cursor with the Qt::ArrowCursor shape, however + another cursor shape may be displayed if an overlapping item has a valid cursor. + + \sa setCursor(), unsetCursor() +*/ + +QCursor QQuickItem::cursor() const +{ + Q_D(const QQuickItem); + return d->extra.isAllocated() + ? d->extra->cursor + : QCursor(); +} + +/*! + Sets the \a cursor shape for this item. + + \sa cursor(), unsetCursor() +*/ + +void QQuickItem::setCursor(const QCursor &cursor) +{ + Q_D(QQuickItem); + + Qt::CursorShape oldShape = d->extra.isAllocated() ? d->extra->cursor.shape() : Qt::ArrowCursor; + + if (oldShape != cursor.shape() || oldShape >= Qt::LastCursor || cursor.shape() >= Qt::LastCursor) { + d->extra.value().cursor = cursor; + if (d->window) { + QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(d->window); + if (windowPrivate->cursorItem == this) + d->window->setCursor(cursor); + } + } + + if (!d->hasCursor) { + d->hasCursor = true; + if (d->window) { + QPointF pos = d->window->mapFromGlobal(QGuiApplicationPrivate::lastCursorPosition.toPoint()); + if (contains(mapFromScene(pos))) + QQuickWindowPrivate::get(d->window)->updateCursor(pos); + } + } +} + +/*! + Clears the cursor shape for this item. + + \sa cursor(), setCursor() +*/ + +void QQuickItem::unsetCursor() +{ + Q_D(QQuickItem); + if (!d->hasCursor) + return; + d->hasCursor = false; + if (d->extra.isAllocated()) + d->extra->cursor = QCursor(); + + if (d->window) { + QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(d->window); + if (windowPrivate->cursorItem == this) { + QPointF pos = d->window->mapFromGlobal(QGuiApplicationPrivate::lastCursorPosition.toPoint()); + windowPrivate->updateCursor(pos); + } + } +} + +#endif + void QQuickItem::grabMouse() { Q_D(QQuickItem); diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index 61bb3250ea..8854449d2b 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -80,6 +80,7 @@ private: Q_DECLARE_PRIVATE(QQuickTransform) }; +class QCursor; class QQuickItemLayer; class QQmlV8Function; class QQuickState; @@ -282,6 +283,12 @@ public: bool acceptHoverEvents() const; void setAcceptHoverEvents(bool enabled); +#ifndef QT_NO_CURSOR + QCursor cursor() const; + void setCursor(const QCursor &cursor); + void unsetCursor(); +#endif + bool isUnderMouse() const; void grabMouse(); void ungrabMouse(); diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index adfe384b25..9dc7344b89 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -342,6 +342,9 @@ public: QQuickLayoutMirroringAttached* layoutDirectionAttached; QQuickItemKeyFilter *keyHandler; mutable QQuickItemLayer *layer; +#ifndef QT_NO_CURSOR + QCursor cursor; +#endif QPointF userTransformOriginPoint; int effectRefCount; @@ -408,7 +411,8 @@ public: bool inheritMirrorFromItem:1; bool isAccessible:1; bool culled:1; - // bool dummy:2 + bool hasCursor:1; + // bool dummy:1 // Bit 32 enum DirtyType { diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index 5cfd62ff8f..85a224fc93 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -1136,15 +1136,6 @@ void QQuickMouseArea::setHovered(bool h) d->hovered = h; emit hoveredChanged(); d->hovered ? emit entered() : emit exited(); -#ifndef QT_NO_CURSOR - if (d->cursor) { - if (d->hovered) { - window()->setCursor(QCursor(*d->cursor)); - } else { - window()->unsetCursor(); - } - } -#endif } } @@ -1274,19 +1265,19 @@ bool QQuickMouseArea::setPressed(Qt::MouseButton button, bool p) #ifndef QT_NO_CURSOR Qt::CursorShape QQuickMouseArea::cursorShape() const { - Q_D(const QQuickMouseArea); - if (d->cursor) - return d->cursor->shape(); - return Qt::ArrowCursor; + return cursor().shape(); } void QQuickMouseArea::setCursorShape(Qt::CursorShape shape) { - Q_D(QQuickMouseArea); - setHoverEnabled(true); - delete d->cursor; - d->cursor = new QCursor(shape); + if (cursor().shape() == shape) + return; + + setCursor(shape); + + emit cursorShapeChanged(); } + #endif /*! diff --git a/src/quick/items/qquickmousearea_p.h b/src/quick/items/qquickmousearea_p.h index 8a8de3bdc3..3385485cac 100644 --- a/src/quick/items/qquickmousearea_p.h +++ b/src/quick/items/qquickmousearea_p.h @@ -144,7 +144,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickMouseArea : public QQuickItem Q_PROPERTY(bool preventStealing READ preventStealing WRITE setPreventStealing NOTIFY preventStealingChanged) Q_PROPERTY(bool propagateComposedEvents READ propagateComposedEvents WRITE setPropagateComposedEvents NOTIFY propagateComposedEventsChanged) #ifndef QT_NO_CURSOR - Q_PROPERTY(Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape NOTIFY cursorShapeChanged) + Q_PROPERTY(Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape RESET unsetCursor NOTIFY cursorShapeChanged) #endif public: diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 1d3adea5cb..4cfe1a101c 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -326,6 +326,9 @@ QQuickWindowPrivate::QQuickWindowPrivate() : rootItem(0) , activeFocusItem(0) , mouseGrabberItem(0) +#ifndef QT_NO_CURSOR + , cursorItem(0) +#endif , touchMouseId(-1) , touchMousePressTimestamp(0) , renderWithoutShowing(false) @@ -1301,6 +1304,10 @@ void QQuickWindow::mouseMoveEvent(QMouseEvent *event) qWarning() << "QQuickWindow::mouseMoveEvent()" << event->localPos() << event->button() << event->buttons(); #endif +#ifndef QT_NO_CURSOR + d->updateCursor(event->windowPos()); +#endif + if (!d->mouseGrabberItem) { if (d->lastMousePosition.isNull()) d->lastMousePosition = event->windowPos(); @@ -1832,6 +1839,49 @@ bool QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickIte } #endif // QT_NO_DRAGANDDROP +#ifndef QT_NO_CURSOR +void QQuickWindowPrivate::updateCursor(const QPointF &scenePos) +{ + Q_Q(QQuickWindow); + + QQuickItem *oldCursorItem = cursorItem; + cursorItem = findCursorItem(rootItem, scenePos); + + if (cursorItem != oldCursorItem) { + if (cursorItem) + q->setCursor(cursorItem->cursor()); + else + q->unsetCursor(); + } +} + +QQuickItem *QQuickWindowPrivate::findCursorItem(QQuickItem *item, const QPointF &scenePos) +{ + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); + if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) { + QPointF p = item->mapFromScene(scenePos); + if (!item->contains(p)) + return 0; + } + + QList<QQuickItem *> children = itemPrivate->paintOrderChildItems(); + for (int ii = children.count() - 1; ii >= 0; --ii) { + QQuickItem *child = children.at(ii); + if (!child->isVisible() || !child->isEnabled()) + continue; + if (QQuickItem *cursorItem = findCursorItem(child, scenePos)) + return cursorItem; + } + + if (itemPrivate->hasCursor) { + QPointF p = item->mapFromScene(scenePos); + if (item->contains(p)) + return item; + } + return 0; +} +#endif + bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem *item, QTouchEvent *event) { if (!target) diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 52e46ca6a8..267c8d3104 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -113,6 +113,9 @@ public: // Keeps track of the item currently receiving mouse events QQuickItem *mouseGrabberItem; +#ifndef QT_NO_CURSOR + QQuickItem *cursorItem; +#endif #ifndef QT_NO_DRAGANDDROP QQuickDragGrabber dragGrabber; #endif @@ -145,6 +148,10 @@ public: void deliverDragEvent(QQuickDragGrabber *, QEvent *); bool deliverDragEvent(QQuickDragGrabber *, QQuickItem *, QDragMoveEvent *); #endif +#ifndef QT_NO_CURSOR + void updateCursor(const QPointF &scenePos); + QQuickItem *findCursorItem(QQuickItem *item, const QPointF &scenePos); +#endif QList<QQuickItem*> hoverItems; enum FocusOption { |