From 17a1c12a4520c4ae756e7dd5c08b2386ef84673a Mon Sep 17 00:00:00 2001 From: Olivier JG Date: Wed, 7 Dec 2016 11:57:03 -0600 Subject: Add pressAndHoldInterval to MouseArea Introduce pressAndHoldInterval to allow setting the pressAndHold delay per-MouseArea. [ChangeLog][QtQml][MouseArea] Introduce pressAndHoldInterval property, which controls the elapsed time before pressAndHold is emitted. Task-Id: QTBUG-47662 Change-Id: Ic2173335033a6ed0d4b652333020f030de63a8e7 Reviewed-by: Michael Brasser --- src/quick/items/qquickitemsmodule.cpp | 2 ++ src/quick/items/qquickmousearea.cpp | 47 +++++++++++++++++++++++++++++++++-- src/quick/items/qquickmousearea_p.h | 6 +++++ src/quick/items/qquickmousearea_p_p.h | 1 + 4 files changed, 54 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 8dd4a96b62..dbe30fbc83 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -368,6 +368,8 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) #if QT_CONFIG(quick_shadereffect) qmlRegisterType("QtQuick", 2, 8, "BorderImageMesh"); #endif + + qmlRegisterType(uri, 2, 9, "MouseArea"); } static void initResources() diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index 5e30bf9e0a..79c957832a 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -60,7 +60,8 @@ Q_DECLARE_LOGGING_CATEGORY(DBG_HOVER_TRACE) QQuickMouseAreaPrivate::QQuickMouseAreaPrivate() : enabled(true), scrollGestureEnabled(true), hovered(false), longPress(false), moved(false), stealMouse(false), doubleClick(false), preventStealing(false), - propagateComposedEvents(false), overThreshold(false), pressed(0) + propagateComposedEvents(false), overThreshold(false), pressed(0), + pressAndHoldInterval(-1) #if QT_CONFIG(draganddrop) , drag(0) #endif @@ -685,7 +686,7 @@ void QQuickMouseArea::mousePressEvent(QMouseEvent *event) #endif setHovered(true); d->startScene = event->windowPos(); - d->pressAndHoldTimer.start(QGuiApplication::styleHints()->mousePressAndHoldInterval(), this); + d->pressAndHoldTimer.start(pressAndHoldInterval(), this); setKeepMouseGrab(d->stealMouse); event->setAccepted(setPressed(event->button(), true, event->source())); } @@ -1294,6 +1295,48 @@ void QQuickMouseArea::setCursorShape(Qt::CursorShape shape) #endif + +/*! + \qmlproperty int QtQuick::MouseArea::pressAndHoldInterval + \since 5.9 + + This property overrides the elapsed time in milliseconds before + \c pressAndHold is emitted. + + If not explicitly set -- or after reset -- the value follows + \c QStyleHints::mousePressAndHoldInterval. + + Typically it's sufficient to set this property globally using the + application style hint. This property should be used when varying intervals + are needed for certain MouseAreas. + + \sa pressAndHold +*/ +int QQuickMouseArea::pressAndHoldInterval() const +{ + Q_D(const QQuickMouseArea); + return d->pressAndHoldInterval > -1 ? + d->pressAndHoldInterval : QGuiApplication::styleHints()->mousePressAndHoldInterval(); +} + +void QQuickMouseArea::setPressAndHoldInterval(int interval) +{ + Q_D(QQuickMouseArea); + if (interval != d->pressAndHoldInterval) { + d->pressAndHoldInterval = interval; + emit pressAndHoldIntervalChanged(); + } +} + +void QQuickMouseArea::resetPressAndHoldInterval() +{ + Q_D(QQuickMouseArea); + if (d->pressAndHoldInterval > -1) { + d->pressAndHoldInterval = -1; + emit pressAndHoldIntervalChanged(); + } +} + /*! \qmlpropertygroup QtQuick::MouseArea::drag \qmlproperty Item QtQuick::MouseArea::drag.target diff --git a/src/quick/items/qquickmousearea_p.h b/src/quick/items/qquickmousearea_p.h index d90c8e1baa..ee166a2082 100644 --- a/src/quick/items/qquickmousearea_p.h +++ b/src/quick/items/qquickmousearea_p.h @@ -84,6 +84,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickMouseArea : public QQuickItem Q_PROPERTY(Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape RESET unsetCursor NOTIFY cursorShapeChanged) #endif Q_PROPERTY(bool containsPress READ containsPress NOTIFY containsPressChanged REVISION 1) + Q_PROPERTY(int pressAndHoldInterval READ pressAndHoldInterval WRITE setPressAndHoldInterval NOTIFY pressAndHoldIntervalChanged RESET resetPressAndHoldInterval REVISION 9) public: QQuickMouseArea(QQuickItem *parent=0); @@ -125,6 +126,10 @@ public: void setCursorShape(Qt::CursorShape shape); #endif + int pressAndHoldInterval() const; + void setPressAndHoldInterval(int interval); + void resetPressAndHoldInterval(); + Q_SIGNALS: void hoveredChanged(); void pressedChanged(); @@ -152,6 +157,7 @@ Q_SIGNALS: void exited(); void canceled(); Q_REVISION(1) void containsPressChanged(); + Q_REVISION(9) void pressAndHoldIntervalChanged(); protected: void setHovered(bool); diff --git a/src/quick/items/qquickmousearea_p_p.h b/src/quick/items/qquickmousearea_p_p.h index 456b1866a3..2fa5f7cd44 100644 --- a/src/quick/items/qquickmousearea_p_p.h +++ b/src/quick/items/qquickmousearea_p_p.h @@ -95,6 +95,7 @@ public: bool propagateComposedEvents : 1; bool overThreshold : 1; Qt::MouseButtons pressed; + int pressAndHoldInterval; #if QT_CONFIG(draganddrop) QQuickDrag *drag; #endif -- cgit v1.2.3 From c4eefa4a8d6d3e95062deb78229940460a7ef605 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 22 Nov 2016 11:25:46 +0100 Subject: Keys: add shortcutOverride signal This allows an item to accept the shortcutOverride event, preventing e.g. Shortcut from stealing key events. The original use case that prompted the creation of this patch was using a Popup from Controls 2 to create a keyboard shortcut editor. When the user wanted to cancel the shortcut that they were editing, they could press escape, but Popup would grab the shortcut and close itself. As the test case demonstrates, the same problem occurs with the Shortcut type in Qt Quick. [ChangeLog][QtQuick][Keys] Added shortcutOverride signal to Keys attached object to allow prevention of e.g. Shortcut from stealing key events. Task-number: QTBUG-57098 Change-Id: I594e4ea17ec417d8c7d93c6cf347c1a1a2e62b93 Reviewed-by: Shawn Rutledge Reviewed-by: Robin Burchell --- src/quick/items/qquickitem.cpp | 66 +++++++++++++++++++++++++++++++++++++++ src/quick/items/qquickitem_p.h | 4 +++ src/quick/util/qquickshortcut.cpp | 2 +- 3 files changed, 71 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index ca8ef7ba2e..504446a8be 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -333,6 +333,12 @@ QVariant QQuickItemKeyFilter::inputMethodQuery(Qt::InputMethodQuery query) const } #endif // im +void QQuickItemKeyFilter::shortcutOverride(QKeyEvent *event) +{ + if (m_next) + m_next->shortcutOverride(event); +} + void QQuickItemKeyFilter::componentComplete() { if (m_next) m_next->componentComplete(); @@ -934,6 +940,46 @@ bool QQuickKeysAttached::isConnected(const char *signalName) const The corresponding handler is \c onReleased. */ +/*! + \qmlsignal QtQuick::Keys::shortcutOverride(KeyEvent event) + \since 5.9 + + This signal is emitted when a key has been pressed that could potentially + be used as a shortcut. The \a event parameter provides information about + the event. + + Set \c event.accepted to \c true if you wish to prevent the pressed key + from being used as a shortcut by other types, such as \l Shortcut. For + example: + + \code + Item { + id: escapeItem + focus: true + + // Ensure that we get escape key press events first. + Keys.onShortcutOverride: event.accepted = (event.key === Qt.Key_Escape) + + Keys.onEscapePressed: { + console.log("escapeItem is handling escape"); + event.accepted = true; + } + } + + Shortcut { + sequence: "Escape" + onActivated: console.log("Shortcut is handling escape") + } + \endcode + + As with the other signals, \c shortcutOverride will only be emitted for an + item if that item has \l {Item::}{activeFocus}. + + The corresponding handler is \c onShortcutOverride. + + \sa Shortcut +*/ + /*! \qmlsignal QtQuick::Keys::digit0Pressed(KeyEvent event) @@ -1426,6 +1472,16 @@ QVariant QQuickKeysAttached::inputMethodQuery(Qt::InputMethodQuery query) const } #endif // im +void QQuickKeysAttached::shortcutOverride(QKeyEvent *event) +{ + Q_D(QQuickKeysAttached); + QQuickKeyEvent &keyEvent = d->theKeyEvent; + keyEvent.reset(*event); + emit shortcutOverride(&keyEvent); + + event->setAccepted(keyEvent.isAccepted()); +} + QQuickKeysAttached *QQuickKeysAttached::qmlAttachedProperties(QObject *obj) { return new QQuickKeysAttached(obj); @@ -5019,6 +5075,13 @@ void QQuickItemPrivate::deliverInputMethodEvent(QInputMethodEvent *e) } #endif // im +void QQuickItemPrivate::deliverShortcutOverrideEvent(QKeyEvent *event) +{ + if (extra.isAllocated() && extra->keyHandler) { + extra->keyHandler->shortcutOverride(event); + } +} + /*! Called when \a change occurs for this item. @@ -7652,6 +7715,9 @@ bool QQuickItem::event(QEvent *ev) case QEvent::KeyRelease: d->deliverKeyEvent(static_cast(ev)); break; + case QEvent::ShortcutOverride: + d->deliverShortcutOverrideEvent(static_cast(ev)); + break; case QEvent::FocusIn: focusInEvent(static_cast(ev)); break; diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 3002b73a8c..c0c9bd46bd 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -559,6 +559,7 @@ public: #if QT_CONFIG(im) void deliverInputMethodEvent(QInputMethodEvent *); #endif + void deliverShortcutOverrideEvent(QKeyEvent *); bool isTransparentForPositioner() const; void setTransparentForPositioner(bool trans); @@ -622,6 +623,7 @@ public: virtual void inputMethodEvent(QInputMethodEvent *event, bool post); virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const; #endif + virtual void shortcutOverride(QKeyEvent *event); virtual void componentComplete(); bool m_processPost; @@ -813,6 +815,7 @@ Q_SIGNALS: void priorityChanged(); void pressed(QQuickKeyEvent *event); void released(QQuickKeyEvent *event); + void shortcutOverride(QQuickKeyEvent *event); void digit0Pressed(QQuickKeyEvent *event); void digit1Pressed(QQuickKeyEvent *event); void digit2Pressed(QQuickKeyEvent *event); @@ -861,6 +864,7 @@ private: void inputMethodEvent(QInputMethodEvent *, bool post) Q_DECL_OVERRIDE; QVariant inputMethodQuery(Qt::InputMethodQuery query) const Q_DECL_OVERRIDE; #endif + void shortcutOverride(QKeyEvent *event) override; static QByteArray keyToSignal(int key); bool isConnected(const char *signalName) const; diff --git a/src/quick/util/qquickshortcut.cpp b/src/quick/util/qquickshortcut.cpp index a0a58f2e02..72d9c889e3 100644 --- a/src/quick/util/qquickshortcut.cpp +++ b/src/quick/util/qquickshortcut.cpp @@ -73,7 +73,7 @@ It is also possible to set multiple shortcut \l sequences, so that the shortcut can be \l activated via several different sequences of key presses. - \sa Keys + \sa Keys, {Keys::}{shortcutOverride()} */ /*! \qmlsignal QtQuick::Shortcut::activated() -- cgit v1.2.3