4#include "private/qgesturemanager_p.h"
5#include "private/qstandardgestures_p.h"
6#include "private/qwidget_p.h"
7#include "private/qgesture_p.h"
8#if QT_CONFIG(graphicsview)
9#include "private/qgraphicsitem_p.h"
12#include "private/qevent_p.h"
13#include "private/qapplication_p.h"
14#include "private/qwidgetwindow_p.h"
23#include <QtCore/QLoggingCategory>
24#include <QtCore/QVarLengthArray>
32#if !defined(Q_OS_MACOS)
36 static const char panTouchPointVariable[] =
"QT_PAN_TOUCHPOINTS";
42 qWarning(
"Ignoring invalid value of %s", panTouchPointVariable);
55 qRegisterMetaType<Qt::GestureState>();
57#if defined(Q_OS_MACOS)
83 qWarning(
"QGestureManager::registerGestureRecognizer: "
84 "the recognizer fails to create a gesture object, skipping registration.");
90 ++m_lastCustomGestureId;
104 m_deletedRecognizers.
insert(
g, recognizer);
110 ObjectGesture objectGesture =
iter.key();
111 if (objectGesture.gesture ==
type) {
114 m_gestureToRecognizer.
remove(
g);
115 m_obsoleteGestures[recognizer].
insert(
g);
126 if (
iter == m_objectGestures.
end())
130 for (
auto &
e : m_obsoleteGestures) {
135 m_deletedRecognizers.
remove(
g);
136 m_gestureToRecognizer.
remove(
g);
153 if (
object->isWidgetType()) {
154 if (
static_cast<QWidget *
>(
object)->d_func()->
data.in_destructor)
156 }
else if (
QGesture *
g = qobject_cast<QGesture *>(
object)) {
158#if QT_CONFIG(graphicsview)
160 Q_ASSERT(qobject_cast<QGraphicsObject *>(
object));
162 if (graphicsObject->QGraphicsItem::d_func()->inDestructor)
168 const auto states = m_objectGestures.
value(QGestureManager::ObjectGesture(
object,
type));
170 if (m_gestureToRecognizer.
value(
state) == recognizer)
178 state->setParent(
this);
183 if (lcGestureManager().isDebugEnabled())
186 m_objectGestures[QGestureManager::ObjectGesture(
object,
type)].append(
state);
187 m_gestureToRecognizer[
state] = recognizer;
235 bool consumeEventHint =
false;
239 ContextIterator contextEnd = contexts.end();
244 typeToRecognizerIterator = const_recognizers.
lowerBound(gestureType),
245 typeToRecognizerEnd = const_recognizers.
upperBound(gestureType);
246 for (; typeToRecognizerIterator != typeToRecognizerEnd; ++typeToRecognizerIterator) {
256 qCDebug(lcGestureManager) <<
"QGestureManager:Recognizer: gesture triggered: " <<
state <<
event;
257 triggeredGestures <<
state;
259 qCDebug(lcGestureManager) <<
"QGestureManager:Recognizer: gesture finished: " <<
state <<
event;
260 finishedGestures <<
state;
262 qCDebug(lcGestureManager) <<
"QGestureManager:Recognizer: maybe gesture: " <<
state <<
event;
263 newMaybeGestures <<
state;
265 qCDebug(lcGestureManager) <<
"QGestureManager:Recognizer: not gesture: " <<
state <<
event;
266 notGestures <<
state;
269 qCDebug(lcGestureManager) <<
"QGestureManager:Recognizer: ignored the event: " <<
state <<
event;
272 qCDebug(lcGestureManager) <<
"QGestureManager:Recognizer: hm, lets assume the recognizer"
277 qCDebug(lcGestureManager) <<
"QGestureManager: we were asked to consume the event: "
279 consumeEventHint =
true;
286 triggeredGestures &= m_activeGestures;
289 QSet<QGesture *> activeToMaybeGestures = m_activeGestures & newMaybeGestures;
299 m_maybeGestures += newMaybeGestures;
303 | finishedGestures | canceledGestures
305 m_maybeGestures -= notMaybeGestures;
307 Q_ASSERT((startedGestures & finishedGestures).isEmpty());
308 Q_ASSERT((startedGestures & newMaybeGestures).isEmpty());
309 Q_ASSERT((startedGestures & canceledGestures).isEmpty());
310 Q_ASSERT((finishedGestures & newMaybeGestures).isEmpty());
311 Q_ASSERT((finishedGestures & canceledGestures).isEmpty());
312 Q_ASSERT((canceledGestures & newMaybeGestures).isEmpty());
318 foreach (
QGesture *gesture, notStarted)
321 deliverEvents(notStarted, &undeliveredGestures);
322 finishedGestures -= undeliveredGestures;
325 m_activeGestures += startedGestures;
327 Q_ASSERT((m_activeGestures & triggeredGestures).
size() == triggeredGestures.size());
328 m_activeGestures -= finishedGestures;
329 m_activeGestures -= activeToMaybeGestures;
330 m_activeGestures -= canceledGestures;
333 foreach (
QGesture *gesture, startedGestures)
335 foreach (
QGesture *gesture, triggeredGestures)
337 foreach (
QGesture *gesture, finishedGestures)
339 foreach (
QGesture *gesture, canceledGestures)
341 foreach (
QGesture *gesture, activeToMaybeGestures)
344 if (!m_activeGestures.isEmpty() || !m_maybeGestures.
isEmpty() ||
345 !startedGestures.
isEmpty() || !triggeredGestures.isEmpty() ||
346 !finishedGestures.isEmpty() || !canceledGestures.
isEmpty()) {
347 qCDebug(lcGestureManager) <<
"QGestureManager::filterEventThroughContexts:"
348 <<
"\n\tactiveGestures:" << m_activeGestures
349 <<
"\n\tmaybeGestures:" << m_maybeGestures
350 <<
"\n\tstarted:" << startedGestures
351 <<
"\n\ttriggered:" << triggeredGestures
352 <<
"\n\tfinished:" << finishedGestures
353 <<
"\n\tcanceled:" << canceledGestures
354 <<
"\n\tmaybe-canceled:" << maybeToCanceledGestures;
358 deliverEvents(startedGestures+triggeredGestures+finishedGestures+canceledGestures,
359 &undeliveredGestures);
365 qCDebug(lcGestureManager) <<
"lets try to cancel some";
367 cancelGesturesForChildren(
g);
371 m_activeGestures -= undeliveredGestures;
375 finishedGestures + canceledGestures + undeliveredGestures + maybeToCanceledGestures;
376 foreach (
QGesture *gesture, endedGestures) {
378 m_gestureTargets.
remove(gesture);
383 m_gesturesToDelete.
clear();
385 return consumeEventHint;
389void QGestureManager::cancelGesturesForChildren(
QGesture *original)
392 QWidget *originatingWidget = m_gestureTargets.
value(original);
394 if (!originatingWidget)
403 while (
iter != m_activeGestures.
end()) {
407 qCDebug(lcGestureManager) <<
" found a gesture to cancel" << (*iter);
409 cancelledGestures << *
iter;
420 while (!almostCanceledGestures.
isEmpty()) {
425 while (
iter != almostCanceledGestures.
end()) {
439 deliverEvents(gestures, &undeliveredGestures);
446void QGestureManager::cleanupGesturesForRemovedRecognizer(
QGesture *gesture)
451 m_deletedRecognizers.
remove(gesture);
452 if (m_deletedRecognizers.
keys(recognizer).
isEmpty()) {
455 m_obsoleteGestures.
remove(recognizer);
467 if (!
w->d_func()->gestureContext.isEmpty()) {
468 for(ContextIterator
it =
w->d_func()->gestureContext.
constBegin(),
469 e =
w->d_func()->gestureContext.constEnd();
it !=
e; ++
it) {
475 w =
w->isWindow() ?
nullptr :
w->parentWidget();
478 for (ContextIterator
it =
w->d_func()->gestureContext.
constBegin(),
479 e =
w->d_func()->gestureContext.constEnd();
it !=
e; ++
it) {
481 if (!
types.contains(
it.key())) {
489 w =
w->parentWidget();
494#if QT_CONFIG(graphicsview)
500 if (!
item->QGraphicsItem::d_func()->gestureContext.isEmpty()) {
502 for(ContextIterator
it =
item->QGraphicsItem::d_func()->gestureContext.constBegin(),
503 e =
item->QGraphicsItem::d_func()->gestureContext.constEnd();
it !=
e; ++
it) {
513 for (ContextIterator
it =
item->QGraphicsItem::d_func()->gestureContext.constBegin(),
514 e =
item->QGraphicsItem::d_func()->gestureContext.constEnd();
it !=
e; ++
it) {
516 if (!
types.contains(
it.key())) {
532 QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(receiver);
534 if (widgetWindow && widgetWindow->
widget())
545void QGestureManager::getGestureTargets(
const QSet<QGesture*> &gestures,
550 GestureByTypes gestureByTypes;
553 foreach (
QGesture *gesture, gestures) {
554 QWidget *receiver = m_gestureTargets.
value(gesture,
nullptr);
557 gestureByTypes[gesture->
gestureType()].insert(receiver, gesture);
561 for (GestureByTypes::const_iterator git = gestureByTypes.cbegin(), gend = gestureByTypes.cend(); git != gend; ++git) {
568 =
w->d_func()->gestureContext.
constFind(git.key());
569 if (
it !=
w->d_func()->gestureContext.
constEnd()) {
573 (*conflicts)[
widget].append(wit.value());
581 w =
w->parentWidget();
584 (*normal)[
widget].append(wit.value());
596 GesturesPerWidget conflictedGestures;
597 GesturesPerWidget normalStartedGestures;
612 QWidget *
child = topLevel->childAt(topLevel->mapFromGlobal(pt));
630 qCDebug(lcGestureManager) <<
"QGestureManager::deliverEvent: could not find the target for gesture"
632 qWarning(
"QGestureManager::deliverEvent: could not find the target for gesture");
633 undeliveredGestures->
insert(gesture);
636 startedGestures.
insert(gesture);
638 normalStartedGestures[
target].append(gesture);
643 getGestureTargets(startedGestures, &conflictedGestures, &normalStartedGestures);
644 qCDebug(lcGestureManager) <<
"QGestureManager::deliverEvents:"
645 <<
"\nstarted: " << startedGestures
646 <<
"\nconflicted: " << conflictedGestures
647 <<
"\nnormal: " << normalStartedGestures
651 for (GesturesPerWidget::const_iterator
it = conflictedGestures.
constBegin(),
652 e = conflictedGestures.constEnd();
it !=
e; ++
it) {
655 qCDebug(lcGestureManager) <<
"QGestureManager::deliverEvents: sending GestureOverride to"
657 <<
"gestures:" << gestures;
663 event.setAccepted(
g,
false);
666 bool eventAccepted =
event.isAccepted();
667 const auto eventGestures =
event.gestures();
668 for (
QGesture *gesture : eventGestures) {
669 if (eventAccepted ||
event.isAccepted(gesture)) {
672 qCDebug(lcGestureManager) <<
"override event: gesture was accepted:" << gesture <<
w;
676 m_gestureTargets[gesture] =
w;
678 qCDebug(lcGestureManager) <<
"override event: gesture wasn't accepted. putting back:" << gesture;
686 for (GesturesPerWidget::const_iterator
it = normalStartedGestures.
constBegin(),
687 e = normalStartedGestures.constEnd();
it !=
e; ++
it) {
689 qCDebug(lcGestureManager) <<
"QGestureManager::deliverEvents: sending to" <<
it.key()
690 <<
"gestures:" <<
it.value();
693 bool eventAccepted =
event.isAccepted();
694 const auto eventGestures =
event.gestures();
695 for (
QGesture *gesture : eventGestures) {
697 (eventAccepted ||
event.isAccepted(gesture))) {
700 qCDebug(lcGestureManager) <<
"started gesture was delivered and accepted by" <<
w;
701 m_gestureTargets[gesture] =
w;
713 recognizer->
reset(gesture);
714 m_activeGestures.
remove(gesture);
716 cleanupGesturesForRemovedRecognizer(gesture);
723 return gm && gm->m_gestureOwners.
key(
o);
730#include "moc_qgesturemanager_p.cpp"
static QWidget * topLevelAt(const QPoint &p)
Returns the top-level widget at the given point; returns \nullptr if there is no such widget.
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
Type
This enum type defines the valid event types in Qt.
@ GraphicsSceneMouseRelease
@ GraphicsSceneMousePress
@ GraphicsSceneMouseDoubleClick
The QGestureEvent class provides the description of triggered gestures.
void recycle(QGesture *gesture)
Qt::GestureType registerGestureRecognizer(QGestureRecognizer *recognizer)
bool filterEventThroughContexts(const QMultiMap< QObject *, Qt::GestureType > &contexts, QEvent *event)
static bool gesturePending(QObject *o)
bool filterEvent(QWidget *receiver, QEvent *event)
void unregisterGestureRecognizer(Qt::GestureType type)
static QGestureManager * instance(InstanceCreation ic=ForceCreation)
QGestureManager(QObject *parent)
void cleanupCachedGestures(QObject *target, Qt::GestureType type)
The QGestureRecognizer class provides the infrastructure for gesture recognition.\inmodule QtWidgets.
virtual void reset(QGesture *state)
This function is called by the framework to reset a given gesture.
virtual Result recognize(QGesture *state, QObject *watched, QEvent *event)=0
Handles the given event for the watched object, updating the state of the gesture object as required,...
virtual QGesture * create(QObject *target)
This function is called by Qt to create a new QGesture object for the given target (QWidget or QGraph...
The QGesture class represents a gesture, containing properties that describe the corresponding user i...
Qt::GestureState state
the current state of the gesture
void setGestureCancelPolicy(GestureCancelPolicy policy)
Qt::GestureType gestureType
the type of the gesture
QPointF hotSpot
The point that is used to find the receiver for the gesture event.
bool hasHotSpot
whether the gesture has a hot-spot
QGraphicsObject * parentObject() const
The QGraphicsObject class provides a base class for all graphics items that require signals,...
bool remove(const Key &key)
Removes the item that has the key from the hash.
const_iterator cbegin() const noexcept
QList< Key > keys() const
Returns a list containing all the keys in the hash, in an arbitrary order.
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
T value(const Key &key) const noexcept
const_iterator cend() const noexcept
Key key(const T &value) const noexcept
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
bool isEmpty() const noexcept
void append(parameter_type t)
T value(const Key &key, const T &defaultValue=T()) const
iterator erase(const_iterator it)
iterator find(const Key &key)
const_iterator constBegin() const
const_iterator constEnd() const
iterator lowerBound(const Key &key)
iterator insert(const Key &key, const T &value)
size_type remove(const Key &key)
iterator upperBound(const Key &key)
QList< T > values() const
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
\inmodule QtCore\reentrant
bool remove(const T &value)
const_iterator constBegin() const noexcept
const_iterator constEnd() const noexcept
iterator erase(const_iterator i)
const_iterator constFind(const T &value) const
bool contains(const T &value) const
iterator insert(const T &value)
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
Combined button and popup list for selecting options.
@ DontStartGestureOnChildren
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
static bool logIgnoredEvent(QEvent::Type t)
static QT_BEGIN_NAMESPACE int panTouchPoints()
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei GLenum GLenum * types
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
bool contains(const AT &t) const noexcept
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent