Search code examples
c++windowsqtgestureqt4.6

How to prevent timeout removal of gestures in MayBeGesture state?


I am in the process of implementing a touch-based input system, using Qt 4.6.3 running on Microsoft Windows 7. To keep state machines at a manageable complexity I decided to go with the framework's gesture recognition infrastructure. I have been following the Gestures Programming guide and implemented and registered my QGestureRecognizer-derived classes for each gesture.

Most gesture recognizers work as expected, with one exception: My Single Finger Pan exposes inexplicable (to me) behavior. Since I wish to keep a small tolerance window before triggering a Pan gesture, the event for the initial contact (either mouse or touch) has to report a MayBeGesture result, and will only request moving forward to the Qt::GestureStarted state by returning TriggerGesture.

This is the relevant code section:

class CSingleFingerPanGestureRecognizer : public QGestureRecognizer
{
public:
    virtual QGestureRecognizer::Result recognize( QGesture* state,
                                                  QObject*,
                                                  QEvent* event ) {
        CSingleFingerPanGesture& panState = *static_cast< CSingleFingerPanGesture* >( state );

        QGestureRecognizer::Result result;

        switch ( event->type() ) {
        case QEvent::TouchBegin: {
            const QTouchEvent& touchEvent = *static_cast< const QTouchEvent* >( event );
            // Filter out multi-touch gestures
            if ( touchEvent.touchPoints().size() == 1 ) {
                QTouchEvent::TouchPoint p = touchEvent.touchPoints().at(0);
                panState.startPos = p.pos();
                result = QGestureRecognizer::MayBeGesture;
            }
            break;
        }
        case QEvent::MouseButtonPress: {
            const QMouseEvent& mouseEvent = *static_cast< const QMouseEvent* >( event );
            panState.startPos = mouseEvent.posF();
            result = QGestureRecognizer::MayBeGesture;
            break;
        }

        // ...
        }
        return result;
    }
    // ...
};

Although mouse and touch input are handled identically, and both return the same Result-flag, the overall behavior is different. In particular, when interacting with a touch surface, a gesture at state MayBeGesture is removed from the gesture lists after 3 seconds (see QGestureManager::timerEvent), and by doing so apparently cancels out other gestures. While mouse gestures are also removed from the m_maybeGestures-list this does not expose the undesirable effect.

Questions:

  1. Why are gestures automatically removed from the m_maybeGestures-list?
  2. Is there a way to prevent gestures from being removed from the m_maybeGestures-list?
  3. Why is removing a gesture from the m_maybeGestures-list handled differently depending on the input type?

Solution

  • To answer my own question:

    1. There is practically no reason for this behavior as explained in [#QTBUG-9926] Remove kill timer for maybeGestures from QGestureManager.
    2. The timer controlling arbitrary removal of gestures in MayBeGesture state was removed in Qt 4.7. If arbitrary removal of gestures is a problem, upgrade to Qt 4.7 or later.
    3. Upon further investigation there was no difference in handling mouse and touch input. The only difference is in input characteristics. While touch input generates a continuous stream of Update events, a single left button down event does not. It is the handling of the Update events that eventually triggers the removal of gestures.