diff options
Diffstat (limited to 'src/quicktemplates/qquickdrawer.cpp')
-rw-r--r-- | src/quicktemplates/qquickdrawer.cpp | 851 |
1 files changed, 851 insertions, 0 deletions
diff --git a/src/quicktemplates/qquickdrawer.cpp b/src/quicktemplates/qquickdrawer.cpp new file mode 100644 index 0000000000..678d434629 --- /dev/null +++ b/src/quicktemplates/qquickdrawer.cpp @@ -0,0 +1,851 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qquickdrawer_p.h" +#include "qquickdrawer_p_p.h" +#include "qquickpopupitem_p_p.h" +#include "qquickpopuppositioner_p_p.h" + +#include <QtGui/qstylehints.h> +#include <QtGui/private/qguiapplication_p.h> +#include <QtQml/qqmlinfo.h> +#include <QtQuick/private/qquickwindow_p.h> +#include <QtQuick/private/qquickanimation_p.h> +#include <QtQuick/private/qquicktransition_p.h> +#include <QtQuickTemplates2/private/qquickoverlay_p.h> + +QT_BEGIN_NAMESPACE + +/*! + \qmltype Drawer + \inherits Popup +//! \instantiates QQuickDrawer + \inqmlmodule QtQuick.Controls + \since 5.7 + \ingroup qtquickcontrols-navigation + \ingroup qtquickcontrols-popups + \brief Side panel that can be opened and closed using a swipe gesture. + + Drawer provides a swipe-based side panel, similar to those often used in + touch interfaces to provide a central location for navigation. + + \image qtquickcontrols-drawer.gif + + Drawer can be positioned at any of the four edges of the content item. + The drawer above is positioned against the left edge of the window. The + drawer is then opened by \e "dragging" it out from the left edge of the + window. + + \code + import QtQuick + import QtQuick.Controls + + ApplicationWindow { + id: window + visible: true + + Drawer { + id: drawer + width: 0.66 * window.width + height: window.height + + Label { + text: "Content goes here!" + anchors.centerIn: parent + } + } + } + \endcode + + Drawer is a special type of popup that resides at one of the window \l {edge}{edges}. + By default, Drawer re-parents itself to the window \c overlay, and therefore operates + on window coordinates. It is also possible to manually set the \l{Popup::}{parent} to + something else to make the drawer operate in a specific coordinate space. + + Drawer can be configured to cover only part of its window edge. The following example + illustrates how Drawer can be positioned to appear below a window header: + + \code + import QtQuick + import QtQuick.Controls + + ApplicationWindow { + id: window + visible: true + + header: ToolBar { } + + Drawer { + y: header.height + width: window.width * 0.6 + height: window.height - header.height + } + } + \endcode + + The \l position property determines how much of the drawer is visible, as + a value between \c 0.0 and \c 1.0. It is not possible to set the x-coordinate + (or horizontal margins) of a drawer at the left or right window edge, or the + y-coordinate (or vertical margins) of a drawer at the top or bottom window edge. + + In the image above, the application's contents are \e "pushed" across the + screen. This is achieved by applying a translation to the contents: + + \code + import QtQuick + import QtQuick.Controls + + ApplicationWindow { + id: window + width: 200 + height: 228 + visible: true + + Drawer { + id: drawer + width: 0.66 * window.width + height: window.height + } + + Label { + id: content + + text: "Aa" + font.pixelSize: 96 + anchors.fill: parent + verticalAlignment: Label.AlignVCenter + horizontalAlignment: Label.AlignHCenter + + transform: Translate { + x: drawer.position * content.width * 0.33 + } + } + } + \endcode + + If you would like the application's contents to stay where they are when + the drawer is opened, don't apply a translation. + + Drawer can be configured as a non-closable persistent side panel by + making the Drawer \l {Popup::modal}{non-modal} and \l {interactive} + {non-interactive}. See the \l {Qt Quick Controls 2 - Gallery}{Gallery} + example for more details. + + \note On some platforms, certain edges may be reserved for system + gestures and therefore cannot be used with Drawer. For example, the + top and bottom edges may be reserved for system notifications and + control centers on Android and iOS. + + \sa SwipeView, {Customizing Drawer}, {Navigation Controls}, {Popup Controls} +*/ + +class QQuickDrawerPositioner : public QQuickPopupPositioner +{ +public: + QQuickDrawerPositioner(QQuickDrawer *drawer) : QQuickPopupPositioner(drawer) { } + + void reposition() override; +}; + +qreal QQuickDrawerPrivate::offsetAt(const QPointF &point) const +{ + qreal offset = positionAt(point) - position; + + // don't jump when dragged open + if (offset > 0 && position > 0 && !contains(point)) + offset = 0; + + return offset; +} + +qreal QQuickDrawerPrivate::positionAt(const QPointF &point) const +{ + Q_Q(const QQuickDrawer); + QQuickWindow *window = q->window(); + if (!window) + return 0; + + auto size = QSizeF(q->width(), q->height()); + + switch (effectiveEdge()) { + case Qt::TopEdge: + if (edge == Qt::LeftEdge || edge == Qt::RightEdge) + size.transpose(); + return point.y() / size.height(); + case Qt::LeftEdge: + if (edge == Qt::TopEdge || edge == Qt::BottomEdge) + size.transpose(); + return point.x() / size.width(); + case Qt::RightEdge: + if (edge == Qt::TopEdge || edge == Qt::BottomEdge) + size.transpose(); + return (window->width() - point.x()) / size.width(); + case Qt::BottomEdge: + if (edge == Qt::LeftEdge || edge == Qt::RightEdge) + size.transpose(); + return (window->height() - point.y()) / size.height(); + default: + return 0; + } +} + +QQuickPopupPositioner *QQuickDrawerPrivate::getPositioner() +{ + Q_Q(QQuickDrawer); + if (!positioner) + positioner = new QQuickDrawerPositioner(q); + return positioner; +} + +void QQuickDrawerPositioner::reposition() +{ + if (m_positioning) + return; + + QQuickDrawer *drawer = static_cast<QQuickDrawer*>(popup()); + QQuickWindow *window = drawer->window(); + if (!window) + return; + + const qreal position = drawer->position(); + QQuickItem *popupItem = drawer->popupItem(); + switch (drawer->edge()) { + case Qt::LeftEdge: + popupItem->setX((position - 1.0) * popupItem->width()); + break; + case Qt::RightEdge: + popupItem->setX(window->width() - position * popupItem->width()); + break; + case Qt::TopEdge: + popupItem->setY((position - 1.0) * popupItem->height()); + break; + case Qt::BottomEdge: + popupItem->setY(window->height() - position * popupItem->height()); + break; + } + + QQuickPopupPositioner::reposition(); +} + +void QQuickDrawerPrivate::showDimmer() +{ + // managed in setPosition() +} + +void QQuickDrawerPrivate::hideDimmer() +{ + // managed in setPosition() +} + +void QQuickDrawerPrivate::resizeDimmer() +{ + if (!dimmer || !window) + return; + + const QQuickOverlay *overlay = QQuickOverlay::overlay(window); + + QRectF geometry(0, 0, overlay ? overlay->width() : 0, overlay ? overlay->height() : 0); + + if (edge == Qt::LeftEdge || edge == Qt::RightEdge) { + geometry.setY(popupItem->y()); + geometry.setHeight(popupItem->height()); + } else { + geometry.setX(popupItem->x()); + geometry.setWidth(popupItem->width()); + } + + dimmer->setPosition(geometry.topLeft()); + dimmer->setSize(geometry.size()); +} + +bool QQuickDrawerPrivate::isWithinDragMargin(const QPointF &pos) const +{ + Q_Q(const QQuickDrawer); + switch (effectiveEdge()) { + case Qt::LeftEdge: + return pos.x() <= q->dragMargin(); + case Qt::RightEdge: + return pos.x() >= q->window()->width() - q->dragMargin(); + case Qt::TopEdge: + return pos.y() <= q->dragMargin(); + case Qt::BottomEdge: + return pos.y() >= q->window()->height() - q->dragMargin(); + default: + Q_UNREACHABLE(); + break; + } + return false; +} + +bool QQuickDrawerPrivate::startDrag(QEvent *event) +{ + delayedEnterTransition = false; + if (!window || !interactive || dragMargin < 0.0 || qFuzzyIsNull(dragMargin)) + return false; + + switch (event->type()) { + case QEvent::MouseButtonPress: + if (QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); isWithinDragMargin(mouseEvent->scenePosition())) { + // watch future events and grab the mouse once it has moved + // sufficiently fast or far (in grabMouse). + delayedEnterTransition = true; + mouseEvent->addPassiveGrabber(mouseEvent->point(0), popupItem); + handleMouseEvent(window->contentItem(), mouseEvent); + return false; + } + break; + +#if QT_CONFIG(quicktemplates2_multitouch) + case QEvent::TouchBegin: + case QEvent::TouchUpdate: { + auto *touchEvent = static_cast<QTouchEvent *>(event); + for (const QTouchEvent::TouchPoint &point : touchEvent->points()) { + if (point.state() == QEventPoint::Pressed && isWithinDragMargin(point.scenePosition())) { + delayedEnterTransition = true; + touchEvent->addPassiveGrabber(point, popupItem); + handleTouchEvent(window->contentItem(), touchEvent); + return false; + } + } + break; + } +#endif + + default: + break; + } + + return false; +} + +static inline bool keepGrab(QQuickItem *item) +{ + return item->keepMouseGrab() || item->keepTouchGrab(); +} + +bool QQuickDrawerPrivate::grabMouse(QQuickItem *item, QMouseEvent *event) +{ + Q_Q(QQuickDrawer); + handleMouseEvent(item, event); + + if (!window || !interactive || keepGrab(popupItem) || keepGrab(item)) + return false; + + const QPointF movePoint = event->scenePosition(); + + // Flickable uses a hard-coded threshold of 15 for flicking, and + // QStyleHints::startDragDistance for dragging. Drawer uses a bit + // larger threshold to avoid being too eager to steal touch (QTBUG-50045) + const int threshold = qMax(20, QGuiApplication::styleHints()->startDragDistance() + 5); + bool overThreshold = false; + Qt::Edge effEdge = effectiveEdge(); + if (position > 0 || dragMargin > 0) { + const bool xOverThreshold = QQuickWindowPrivate::dragOverThreshold(movePoint.x() - pressPoint.x(), Qt::XAxis, event, threshold); + const bool yOverThreshold = QQuickWindowPrivate::dragOverThreshold(movePoint.y() - pressPoint.y(), Qt::YAxis, event, threshold); + if (effEdge == Qt::LeftEdge || effEdge == Qt::RightEdge) + overThreshold = xOverThreshold && !yOverThreshold; + else + overThreshold = yOverThreshold && !xOverThreshold; + } + + // Don't be too eager to steal presses outside the drawer (QTBUG-53929) + if (overThreshold && qFuzzyCompare(position, qreal(1.0)) && !contains(movePoint)) { + if (effEdge == Qt::LeftEdge || effEdge == Qt::RightEdge) + overThreshold = qAbs(movePoint.x() - q->width()) < dragMargin; + else + overThreshold = qAbs(movePoint.y() - q->height()) < dragMargin; + } + + if (overThreshold) { + if (delayedEnterTransition) { + prepareEnterTransition(); + reposition(); + delayedEnterTransition = false; + } + + popupItem->grabMouse(); + popupItem->setKeepMouseGrab(true); + offset = offsetAt(movePoint); + } + + return overThreshold; +} + +#if QT_CONFIG(quicktemplates2_multitouch) +bool QQuickDrawerPrivate::grabTouch(QQuickItem *item, QTouchEvent *event) +{ + Q_Q(QQuickDrawer); + bool handled = handleTouchEvent(item, event); + + if (!window || !interactive || keepGrab(popupItem) || keepGrab(item) || !event->touchPointStates().testFlag(QEventPoint::Updated)) + return handled; + + bool overThreshold = false; + for (const QTouchEvent::TouchPoint &point : event->points()) { + if (!acceptTouch(point) || point.state() != QEventPoint::Updated) + continue; + + const QPointF movePoint = point.scenePosition(); + + // Flickable uses a hard-coded threshold of 15 for flicking, and + // QStyleHints::startDragDistance for dragging. Drawer uses a bit + // larger threshold to avoid being too eager to steal touch (QTBUG-50045) + const int threshold = qMax(20, QGuiApplication::styleHints()->startDragDistance() + 5); + const Qt::Edge effEdge = effectiveEdge(); + if (position > 0 || dragMargin > 0) { + const bool xOverThreshold = QQuickWindowPrivate::dragOverThreshold(movePoint.x() - pressPoint.x(), Qt::XAxis, &point, threshold); + const bool yOverThreshold = QQuickWindowPrivate::dragOverThreshold(movePoint.y() - pressPoint.y(), Qt::YAxis, &point, threshold); + if (effEdge == Qt::LeftEdge || effEdge == Qt::RightEdge) + overThreshold = xOverThreshold && !yOverThreshold; + else + overThreshold = yOverThreshold && !xOverThreshold; + } + + // Don't be too eager to steal presses outside the drawer (QTBUG-53929) + if (overThreshold && qFuzzyCompare(position, qreal(1.0)) && !contains(movePoint)) { + if (effEdge == Qt::LeftEdge || effEdge == Qt::RightEdge) + overThreshold = qAbs(movePoint.x() - q->width()) < dragMargin; + else + overThreshold = qAbs(movePoint.y() - q->height()) < dragMargin; + } + + if (overThreshold) { + if (delayedEnterTransition) { + prepareEnterTransition(); + reposition(); + delayedEnterTransition = false; + } + event->setExclusiveGrabber(point, popupItem); + popupItem->setKeepTouchGrab(true); + offset = offsetAt(movePoint); + } + } + + return overThreshold; +} +#endif + +static const qreal openCloseVelocityThreshold = 300; + +// Overrides QQuickPopupPrivate::blockInput, which is called by +// QQuickPopupPrivate::handlePress/Move/Release, which we call in our own +// handlePress/Move/Release overrides. +// This implementation conflates two things: should the event going to the item get +// modally blocked by us? Or should we accept the event and become the grabber? +// Those are two fundamentally different questions for the drawer as a (usually) +// interactive control. +bool QQuickDrawerPrivate::blockInput(QQuickItem *item, const QPointF &point) const +{ + // We want all events, if mouse/touch is already grabbed. + if (popupItem->keepMouseGrab() || popupItem->keepTouchGrab()) + return true; + + // Don't block input to drawer's children/content. + if (popupItem->isAncestorOf(item)) + return false; + + // Don't block outside a drawer's background dimming + if (dimmer && !dimmer->contains(dimmer->mapFromScene(point))) + return false; + + // Accept all events within drag area. + if (isWithinDragMargin(point)) + return true; + + // Accept all other events if drawer is modal. + return modal; +} + +bool QQuickDrawerPrivate::handlePress(QQuickItem *item, const QPointF &point, ulong timestamp) +{ + offset = 0; + velocityCalculator.startMeasuring(point, timestamp); + + if (!QQuickPopupPrivate::handlePress(item, point, timestamp)) + return interactive && popupItem == item; + + return true; +} + +bool QQuickDrawerPrivate::handleMove(QQuickItem *item, const QPointF &point, ulong timestamp) +{ + Q_Q(QQuickDrawer); + if (!QQuickPopupPrivate::handleMove(item, point, timestamp)) + return false; + + // limit/reset the offset to the edge of the drawer when pushed from the outside + if (qFuzzyCompare(position, qreal(1.0)) && !contains(point)) + offset = 0; + + bool isGrabbed = popupItem->keepMouseGrab() || popupItem->keepTouchGrab(); + if (isGrabbed) + q->setPosition(positionAt(point) - offset); + + return isGrabbed; +} + +bool QQuickDrawerPrivate::handleRelease(QQuickItem *item, const QPointF &point, ulong timestamp) +{ + auto cleanup = qScopeGuard([this] { + popupItem->setKeepMouseGrab(false); + popupItem->setKeepTouchGrab(false); + pressPoint = QPointF(); + touchId = -1; + }); + if (pressPoint.isNull()) + return false; + if (!popupItem->keepMouseGrab() && !popupItem->keepTouchGrab()) { + velocityCalculator.reset(); + return QQuickPopupPrivate::handleRelease(item, point, timestamp); + } + + velocityCalculator.stopMeasuring(point, timestamp); + Qt::Edge effEdge = effectiveEdge(); + qreal velocity = 0; + if (effEdge == Qt::LeftEdge || effEdge == Qt::RightEdge) + velocity = velocityCalculator.velocity().x(); + else + velocity = velocityCalculator.velocity().y(); + + // the velocity is calculated so that swipes from left to right + // and top to bottom have positive velocity, and swipes from right + // to left and bottom to top have negative velocity. + // + // - top/left edge: positive velocity opens, negative velocity closes + // - bottom/right edge: negative velocity opens, positive velocity closes + // + // => invert the velocity for bottom and right edges, for the threshold comparison below + if (effEdge == Qt::RightEdge || effEdge == Qt::BottomEdge) + velocity = -velocity; + + if (position > 0.7 || velocity > openCloseVelocityThreshold) { + transitionManager.transitionEnter(); + } else if (position < 0.3 || velocity < -openCloseVelocityThreshold) { + transitionManager.transitionExit(); + } else { + switch (effEdge) { + case Qt::LeftEdge: + if (point.x() - pressPoint.x() > 0) + transitionManager.transitionEnter(); + else + transitionManager.transitionExit(); + break; + case Qt::RightEdge: + if (point.x() - pressPoint.x() < 0) + transitionManager.transitionEnter(); + else + transitionManager.transitionExit(); + break; + case Qt::TopEdge: + if (point.y() - pressPoint.y() > 0) + transitionManager.transitionEnter(); + else + transitionManager.transitionExit(); + break; + case Qt::BottomEdge: + if (point.y() - pressPoint.y() < 0) + transitionManager.transitionEnter(); + else + transitionManager.transitionExit(); + break; + } + } + + // the cleanup() lambda will run before return + return popupItem->keepMouseGrab() || popupItem->keepTouchGrab(); +} + +void QQuickDrawerPrivate::handleUngrab() +{ + QQuickPopupPrivate::handleUngrab(); + + velocityCalculator.reset(); +} + +static QList<QQuickStateAction> prepareTransition(QQuickDrawer *drawer, QQuickTransition *transition, qreal to) +{ + QList<QQuickStateAction> actions; + if (!transition || !QQuickPopupPrivate::get(drawer)->window || !transition->enabled()) + return actions; + + qmlExecuteDeferred(transition); + + QQmlProperty defaultTarget(drawer, QLatin1String("position")); + QQmlListProperty<QQuickAbstractAnimation> animations = transition->animations(); + int count = animations.count(&animations); + for (int i = 0; i < count; ++i) { + QQuickAbstractAnimation *anim = animations.at(&animations, i); + anim->setDefaultTarget(defaultTarget); + } + + actions << QQuickStateAction(drawer, QLatin1String("position"), to); + return actions; +} + +bool QQuickDrawerPrivate::prepareEnterTransition() +{ + Q_Q(QQuickDrawer); + enterActions = prepareTransition(q, enter, 1.0); + return QQuickPopupPrivate::prepareEnterTransition(); +} + +bool QQuickDrawerPrivate::prepareExitTransition() +{ + Q_Q(QQuickDrawer); + exitActions = prepareTransition(q, exit, 0.0); + return QQuickPopupPrivate::prepareExitTransition(); +} + +QQuickPopup::PopupType QQuickDrawerPrivate::resolvedPopupType() const +{ + // For now, a drawer will always be shown in-scene + return QQuickPopup::Item; +} + +bool QQuickDrawerPrivate::setEdge(Qt::Edge e) +{ + Q_Q(QQuickDrawer); + switch (e) { + case Qt::LeftEdge: + case Qt::RightEdge: + allowVerticalMove = true; + allowVerticalResize = true; + allowHorizontalMove = false; + allowHorizontalResize = false; + break; + case Qt::TopEdge: + case Qt::BottomEdge: + allowVerticalMove = false; + allowVerticalResize = false; + allowHorizontalMove = true; + allowHorizontalResize = true; + break; + default: + qmlWarning(q) << "invalid edge value - valid values are: " + << "Qt.TopEdge, Qt.LeftEdge, Qt.RightEdge, Qt.BottomEdge"; + return false; + } + + edge = e; + return true; +} + +QQuickDrawer::QQuickDrawer(QObject *parent) + : QQuickPopup(*(new QQuickDrawerPrivate), parent) +{ + Q_D(QQuickDrawer); + d->dragMargin = QGuiApplication::styleHints()->startDragDistance(); + d->setEdge(Qt::LeftEdge); + + setFocus(true); + setModal(true); + setFiltersChildMouseEvents(true); + setClosePolicy(CloseOnEscape | CloseOnReleaseOutside); +} + +/*! + \qmlproperty enumeration QtQuick.Controls::Drawer::edge + + This property holds the edge of the window at which the drawer will + open from. The acceptable values are: + + \value Qt.TopEdge The top edge of the window. + \value Qt.LeftEdge The left edge of the window (default). + \value Qt.RightEdge The right edge of the window. + \value Qt.BottomEdge The bottom edge of the window. +*/ +Qt::Edge QQuickDrawer::edge() const +{ + Q_D(const QQuickDrawer); + return d->edge; +} + +Qt::Edge QQuickDrawerPrivate::effectiveEdge() const +{ + auto realEdge = edge; + qreal rotation = window->contentItem()->rotation(); + const bool clockwise = rotation > 0; + while (qAbs(rotation) >= 90) { + rotation -= clockwise ? 90 : -90; + switch (realEdge) { + case Qt::LeftEdge: + realEdge = clockwise ? Qt::TopEdge : Qt::BottomEdge; + break; + case Qt::TopEdge: + realEdge = clockwise ? Qt::RightEdge : Qt::LeftEdge; + break; + case Qt::RightEdge: + realEdge = clockwise ? Qt::BottomEdge : Qt::TopEdge; + break; + case Qt::BottomEdge: + realEdge = clockwise ? Qt::LeftEdge : Qt::RightEdge; + break; + } + } + return realEdge; +} + +void QQuickDrawer::setEdge(Qt::Edge edge) +{ + Q_D(QQuickDrawer); + if (d->edge == edge) + return; + + if (!d->setEdge(edge)) + return; + + if (isComponentComplete()) + d->reposition(); + emit edgeChanged(); +} + +/*! + \qmlproperty real QtQuick.Controls::Drawer::position + + This property holds the position of the drawer relative to its final + destination. That is, the position will be \c 0.0 when the drawer + is fully closed, and \c 1.0 when fully open. +*/ +qreal QQuickDrawer::position() const +{ + Q_D(const QQuickDrawer); + return d->position; +} + +void QQuickDrawer::setPosition(qreal position) +{ + Q_D(QQuickDrawer); + position = qBound<qreal>(0.0, position, 1.0); + if (qFuzzyCompare(d->position, position)) + return; + + d->position = position; + if (isComponentComplete()) + d->reposition(); + if (d->dimmer) + d->dimmer->setOpacity(position); + emit positionChanged(); +} + +/*! + \qmlproperty real QtQuick.Controls::Drawer::dragMargin + + This property holds the distance from the screen edge within which + drag actions will open the drawer. Setting the value to \c 0 or less + prevents opening the drawer by dragging. + + The default value is \c Qt.styleHints.startDragDistance. + + \sa interactive +*/ +qreal QQuickDrawer::dragMargin() const +{ + Q_D(const QQuickDrawer); + return d->dragMargin; +} + +void QQuickDrawer::setDragMargin(qreal margin) +{ + Q_D(QQuickDrawer); + if (qFuzzyCompare(d->dragMargin, margin)) + return; + + d->dragMargin = margin; + emit dragMarginChanged(); +} + +void QQuickDrawer::resetDragMargin() +{ + setDragMargin(QGuiApplication::styleHints()->startDragDistance()); +} + +/*! + \since QtQuick.Controls 2.2 (Qt 5.9) + \qmlproperty bool QtQuick.Controls::Drawer::interactive + + This property holds whether the drawer is interactive. A non-interactive + drawer does not react to swipes. + + The default value is \c true. + + \sa dragMargin +*/ +bool QQuickDrawer::isInteractive() const +{ + Q_D(const QQuickDrawer); + return d->interactive; +} + +void QQuickDrawer::setInteractive(bool interactive) +{ + Q_D(QQuickDrawer); + if (d->interactive == interactive) + return; + + setFiltersChildMouseEvents(interactive); + d->interactive = interactive; + emit interactiveChanged(); +} + +bool QQuickDrawer::childMouseEventFilter(QQuickItem *child, QEvent *event) +{ + Q_D(QQuickDrawer); + switch (event->type()) { +#if QT_CONFIG(quicktemplates2_multitouch) + case QEvent::TouchUpdate: + return d->grabTouch(child, static_cast<QTouchEvent *>(event)); + case QEvent::TouchBegin: + case QEvent::TouchEnd: + return d->handleTouchEvent(child, static_cast<QTouchEvent *>(event)); +#endif + case QEvent::MouseMove: + return d->grabMouse(child, static_cast<QMouseEvent *>(event)); + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + return d->handleMouseEvent(child, static_cast<QMouseEvent *>(event)); + default: + break; + } + return false; +} + +void QQuickDrawer::mouseMoveEvent(QMouseEvent *event) +{ + Q_D(QQuickDrawer); + d->grabMouse(d->popupItem, event); +} + +bool QQuickDrawer::overlayEvent(QQuickItem *item, QEvent *event) +{ + Q_D(QQuickDrawer); + switch (event->type()) { +#if QT_CONFIG(quicktemplates2_multitouch) + case QEvent::TouchUpdate: + return d->grabTouch(item, static_cast<QTouchEvent *>(event)); +#endif + case QEvent::MouseMove: + return d->grabMouse(item, static_cast<QMouseEvent *>(event)); + default: + break; + } + return QQuickPopup::overlayEvent(item, event); +} + +#if QT_CONFIG(quicktemplates2_multitouch) +void QQuickDrawer::touchEvent(QTouchEvent *event) +{ + Q_D(QQuickDrawer); + d->grabTouch(d->popupItem, event); +} +#endif + +void QQuickDrawer::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + Q_D(QQuickDrawer); + QQuickPopup::geometryChange(newGeometry, oldGeometry); + d->resizeDimmer(); +} + +QT_END_NAMESPACE + +#include "moc_qquickdrawer_p.cpp" |