Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Registering custom gesture recognizer and handling the returned gesture type
Forum Updated to NodeBB v4.3 + New Features

Registering custom gesture recognizer and handling the returned gesture type

Scheduled Pinned Locked Moved Solved General and Desktop
8 Posts 3 Posters 2.4k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    Red Baron
    wrote on last edited by kshegunov
    #1

    When creating a custom gesture recognizer this has to be registered. As the documentation states

    The application takes ownership of the recognizer and returns the gesture type ID associated with it. For gesture recognizers which handle custom QGesture objects (i.e., those which return Qt::CustomGesture in a QGesture::gestureType() function) the return value is a generated gesture ID with the Qt::CustomGesture flag set.

    This means that it is completely legit to do (for example inside the widget's constructor):

    Widget::Widget(QWidget* parent)
    {
        // ...
        CustomGestureRecognizer* customRecognizer = new CustomGestureRecognizer();
        QGestureRecognizer::registerRecognizer(customRecognizer);
    }
    

    Note that due to the way registration of recognizers works we are required to allocate the recognizer dynamically! Otherwise you will experience a nasty segfault. :)

    In order to handle the specific gesture type in the even handler of our widget we are required to store it somewhere. Since Qt::GestureType QGestureRecognizer::registerRecognizer(QGestureRecognizer *recognizer) is a static method and due to the quote from above there are two plausible (omho) options here:

    • Store the registered type as a class member variable (or push it onto a vector, list etc. but again the container that stores it has to be alive throughout the lifecycle of the widget so that you can call upon it when receiving events) that is part of your custom QWidget

    • Store a pointer to the recognizer as a class member of your custom QWidgeT and also store the registered type inside the recognizer itself as a class member:

      class CustomGestureRecognizer : public QGestureRecognizer
      {
      public:
          CustomGestureRecognizer();
          QGestureRecognizer::Result recognize(QGesture* aState, QObject* aWatched, QEvent* aEvent);
          void setRegisteredGestureType(Qt::GestureType aGestureType);
          Qt::GestureType getRegisterdGestureType();
      private:
          Qt::GestureType registeredGestureType;
      };
      

    With the code above we can do:

    bool Widget::event(QEvent* event)
    {
        if (event->type() == QEvent::Gesture) {
            bool res = gestureEvent(static_cast<QGestureEvent*>(event));
            return res;
        }
    
        return QWidget::event(event);
    }
    
    bool Widget::gestureEvent(QGestureEvent* gestureEvent)
    {
        QGesture* gesture = Q_NULLPTR;
    
        if ((gesture = gestureEvent->gesture(Qt::SwipeGesture))) {
            bool res = gestureSwipeTriggered(static_cast<QSwipeGesture*>(gesture));
            return res;
        }
        else if ((gesture = gestureEvent->gesture(Qt::TapGesture))) {
            bool res = gestureTapTriggered(static_cast<QTapGesture*>(gesture));
            return res;
        }
        // Handle the CustomGesture type here
        else if ((gesture = gestureEvent->gesture(this->customGestureRecognizer->getRegisteredGestureType()))) {
            bool res = gestureCustomTriggered(gesture);
            return res;
        }
    
        return false;
    }
    
    bool Widget::gestureCustomTriggered(QGesture* aCustomGesture)
    {
        // Do something with recognized custom gesture
        return true;
    }
    

    We are in fact required to use the registered type since Qt::CustomGesture (equal to 256) is just as (also what the documentation states) a flag that is a base which, combined with an internally generated offset (256+1, 256+2, 256+3 ...), generates the actual gesture type for the custom gesture.

    Frankly I find storing everything together much better due to the fact that all the information related to the recognition will be part of the same object. The documentation doesn't mention what happens with the allocated instance of the recognizer upon unregistering it. I tried to call QGestureRecognizer::unregisterRecognizer(<registered_custom_gesture_type>) and all my application did was to stop processing the given custom gesture. It did not crash which would mean that the allocated instance is still available after unregistering it.

    I have to wonder why storing the registered custom gesture type inside the recognizer is not done but instead we have to handle the storing on our own especially because of that the application takes ownership of the recognizer and returns the gesture type ID associated with it thing. The documentation also doesn't mention ANYTHING about reusing custom gesture types. For example if we unregister our CustomGestureRecognizer what happens with it? Is the registered custom gesture type free to be taken by a different recognizer that is registered afterwards? Frankly the last wouldn't make much sense since processing a gesture event in the application needs to be something very specific and suddenly having a different gesture do what a previously registered other gesture has done would be confusing to the user. All this is (at least I couldn't find anything) undocumented behaviour and I would like to know how we are supposed to generally do all that I described above.

    Thanks in advance!

    kshegunovK 1 Reply Last reply
    0
    • R Red Baron

      When creating a custom gesture recognizer this has to be registered. As the documentation states

      The application takes ownership of the recognizer and returns the gesture type ID associated with it. For gesture recognizers which handle custom QGesture objects (i.e., those which return Qt::CustomGesture in a QGesture::gestureType() function) the return value is a generated gesture ID with the Qt::CustomGesture flag set.

      This means that it is completely legit to do (for example inside the widget's constructor):

      Widget::Widget(QWidget* parent)
      {
          // ...
          CustomGestureRecognizer* customRecognizer = new CustomGestureRecognizer();
          QGestureRecognizer::registerRecognizer(customRecognizer);
      }
      

      Note that due to the way registration of recognizers works we are required to allocate the recognizer dynamically! Otherwise you will experience a nasty segfault. :)

      In order to handle the specific gesture type in the even handler of our widget we are required to store it somewhere. Since Qt::GestureType QGestureRecognizer::registerRecognizer(QGestureRecognizer *recognizer) is a static method and due to the quote from above there are two plausible (omho) options here:

      • Store the registered type as a class member variable (or push it onto a vector, list etc. but again the container that stores it has to be alive throughout the lifecycle of the widget so that you can call upon it when receiving events) that is part of your custom QWidget

      • Store a pointer to the recognizer as a class member of your custom QWidgeT and also store the registered type inside the recognizer itself as a class member:

        class CustomGestureRecognizer : public QGestureRecognizer
        {
        public:
            CustomGestureRecognizer();
            QGestureRecognizer::Result recognize(QGesture* aState, QObject* aWatched, QEvent* aEvent);
            void setRegisteredGestureType(Qt::GestureType aGestureType);
            Qt::GestureType getRegisterdGestureType();
        private:
            Qt::GestureType registeredGestureType;
        };
        

      With the code above we can do:

      bool Widget::event(QEvent* event)
      {
          if (event->type() == QEvent::Gesture) {
              bool res = gestureEvent(static_cast<QGestureEvent*>(event));
              return res;
          }
      
          return QWidget::event(event);
      }
      
      bool Widget::gestureEvent(QGestureEvent* gestureEvent)
      {
          QGesture* gesture = Q_NULLPTR;
      
          if ((gesture = gestureEvent->gesture(Qt::SwipeGesture))) {
              bool res = gestureSwipeTriggered(static_cast<QSwipeGesture*>(gesture));
              return res;
          }
          else if ((gesture = gestureEvent->gesture(Qt::TapGesture))) {
              bool res = gestureTapTriggered(static_cast<QTapGesture*>(gesture));
              return res;
          }
          // Handle the CustomGesture type here
          else if ((gesture = gestureEvent->gesture(this->customGestureRecognizer->getRegisteredGestureType()))) {
              bool res = gestureCustomTriggered(gesture);
              return res;
          }
      
          return false;
      }
      
      bool Widget::gestureCustomTriggered(QGesture* aCustomGesture)
      {
          // Do something with recognized custom gesture
          return true;
      }
      

      We are in fact required to use the registered type since Qt::CustomGesture (equal to 256) is just as (also what the documentation states) a flag that is a base which, combined with an internally generated offset (256+1, 256+2, 256+3 ...), generates the actual gesture type for the custom gesture.

      Frankly I find storing everything together much better due to the fact that all the information related to the recognition will be part of the same object. The documentation doesn't mention what happens with the allocated instance of the recognizer upon unregistering it. I tried to call QGestureRecognizer::unregisterRecognizer(<registered_custom_gesture_type>) and all my application did was to stop processing the given custom gesture. It did not crash which would mean that the allocated instance is still available after unregistering it.

      I have to wonder why storing the registered custom gesture type inside the recognizer is not done but instead we have to handle the storing on our own especially because of that the application takes ownership of the recognizer and returns the gesture type ID associated with it thing. The documentation also doesn't mention ANYTHING about reusing custom gesture types. For example if we unregister our CustomGestureRecognizer what happens with it? Is the registered custom gesture type free to be taken by a different recognizer that is registered afterwards? Frankly the last wouldn't make much sense since processing a gesture event in the application needs to be something very specific and suddenly having a different gesture do what a previously registered other gesture has done would be confusing to the user. All this is (at least I couldn't find anything) undocumented behaviour and I would like to know how we are supposed to generally do all that I described above.

      Thanks in advance!

      kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on last edited by
      #2

      @Red-Baron said in Registering custom gesture recognizer and handling the returned gesture type:

      The documentation doesn't mention what happens with the allocated instance of the recognizer upon unregistering it. I tried to call QGestureRecognizer::unregisterRecognizer(<registered_custom_gesture_type>) and all my application did was to stop processing the given custom gesture. It did not crash which would mean that the allocated instance is still available after unregistering it.

      See below.

      For example if we unregister our CustomGestureRecognizer what happens with it?

      Since you own the recognizer (as you sourced from the docs) it's your own responsibility to clean it up.

      I have to wonder why storing the registered custom gesture type inside the recognizer is not done but instead we have to handle the storing on our own especially because of that the application takes ownership of the recognizer and returns the gesture type ID associated with it thing.

      See below.

      Is the registered custom gesture type free to be taken by a different recognizer that is registered afterwards?

      This is implementation detail (especially if not documented). Just save the integers you get for the different recognizers as you'd do if you were registering custom event and their event types.

      Frankly the last wouldn't make much sense since processing a gesture event in the application needs to be something very specific and suddenly having a different gesture do what a previously registered other gesture has done would be confusing to the user.

      It's just an integer and there's no problem if it changes when unregister-registering.

      Kind regards.

      Read and abide by the Qt Code of Conduct

      1 Reply Last reply
      2
      • R Offline
        R Offline
        Red Baron
        wrote on last edited by Red Baron
        #3

        Thanks for the detailed reply. I'm asking about the memory management since I have tried a couple of months ago to delete a recognizer that was registered inside the destructor of my widget and I got segmentation fault. Then I started digging in the source code of Qt and found what the "takes ownership" means - the gesture manager releases the memory and if you do that too (for a registered recognizer) you get a double free which is obviously not allowed. So basically unregistering the recognizer removes the ownership by the gesture manager and indeed I am the one who is responsible to clean up. Thanks again for the help!

        PS: Weird, I don't have "Mark as solved" in my "Topic tools". I've added "[Solved]" to the thread's name. Hope that a moderator sees it and marks it for me. Strange...

        kshegunovK 1 Reply Last reply
        0
        • R Red Baron

          Thanks for the detailed reply. I'm asking about the memory management since I have tried a couple of months ago to delete a recognizer that was registered inside the destructor of my widget and I got segmentation fault. Then I started digging in the source code of Qt and found what the "takes ownership" means - the gesture manager releases the memory and if you do that too (for a registered recognizer) you get a double free which is obviously not allowed. So basically unregistering the recognizer removes the ownership by the gesture manager and indeed I am the one who is responsible to clean up. Thanks again for the help!

          PS: Weird, I don't have "Mark as solved" in my "Topic tools". I've added "[Solved]" to the thread's name. Hope that a moderator sees it and marks it for me. Strange...

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by
          #4

          Yes. Taking ownership literally means to be responsible to free the object/resources. It's used quite often in the docs in border cases - where the user would create an object and pass it to Qt, or vice versa.

          PS: Weird, I don't have "Mark as solved" in my "Topic tools". I've added "[Solved]" to the thread's name. Hope that a moderator sees it and marks it for me. Strange...

          Your topic isn't a "question topic", that's why you don't see it. I'll convert and mark it.

          Read and abide by the Qt Code of Conduct

          R 1 Reply Last reply
          2
          • kshegunovK kshegunov

            Yes. Taking ownership literally means to be responsible to free the object/resources. It's used quite often in the docs in border cases - where the user would create an object and pass it to Qt, or vice versa.

            PS: Weird, I don't have "Mark as solved" in my "Topic tools". I've added "[Solved]" to the thread's name. Hope that a moderator sees it and marks it for me. Strange...

            Your topic isn't a "question topic", that's why you don't see it. I'll convert and mark it.

            R Offline
            R Offline
            Red Baron
            wrote on last edited by
            #5

            @kshegunov Thanks. XD

            1 Reply Last reply
            0
            • md2012M Offline
              md2012M Offline
              md2012
              wrote on last edited by md2012
              #6

              @Red-Baron @kshegunov
              Hello guys.
              im trying to creat a custom Finger sweep with only 1 touch point ,well i created the class it self .now im having problem with registering it to my custom widget:

              // Handle the CustomGesture type here
                  else if ((gesture = gestureEvent->gesture(this->customGestureRecognizer->getRegisteredGestureType()))) {
                      bool res = gestureCustomTriggered(gesture);
                      return res;
                  }
              

              in this part of your code , this wont indicate any customGestureRecognizer (which in my case the name is FingerSwipeGestureRecognizer ).
              here is the constructor of my widget :

              galary::galary(QWidget *parent) :
                  QDialog(parent),
                  ui(new Ui::galary)
              {
                  ui->setupUi(this);
              
                  setAttribute(Qt::WA_AcceptTouchEvents);
                  FingerSwipeGestureRecognizer* customRecognizer = new FingerSwipeGestureRecognizer;
                  QGestureRecognizer::registerRecognizer(customRecognizer);
                  grabGesture(Qt::CustomGesture);
              
              }
              

              custom gesture Recognizer in header file:

              class FingerSwipeGestureRecognizer : public QGestureRecognizer
               {
               public:
                   FingerSwipeGestureRecognizer();
              
                   QGesture *create(QObject *target);
                   QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event);
                   void reset(QGesture *state);
                   void setRegisteredGestureType(Qt::GestureType aGestureType);
                       Qt::GestureType getRegisterdGestureType();
                   private:
                       Qt::GestureType registeredGestureType;
               };
              
              

              is there anything that im missing ?

              R 1 Reply Last reply
              0
              • R Offline
                R Offline
                Red Baron
                wrote on last edited by
                #7

                QGestureRecognizer::registerRecognizer(customRecognizer); returns the type that you need to store somewhere (in my case I stored it inside my recognizer to keep things in the same spot). Use the returned type as argument for setRegisteredGestureType(...) and you are good to go.

                1 Reply Last reply
                0
                • md2012M md2012

                  @Red-Baron @kshegunov
                  Hello guys.
                  im trying to creat a custom Finger sweep with only 1 touch point ,well i created the class it self .now im having problem with registering it to my custom widget:

                  // Handle the CustomGesture type here
                      else if ((gesture = gestureEvent->gesture(this->customGestureRecognizer->getRegisteredGestureType()))) {
                          bool res = gestureCustomTriggered(gesture);
                          return res;
                      }
                  

                  in this part of your code , this wont indicate any customGestureRecognizer (which in my case the name is FingerSwipeGestureRecognizer ).
                  here is the constructor of my widget :

                  galary::galary(QWidget *parent) :
                      QDialog(parent),
                      ui(new Ui::galary)
                  {
                      ui->setupUi(this);
                  
                      setAttribute(Qt::WA_AcceptTouchEvents);
                      FingerSwipeGestureRecognizer* customRecognizer = new FingerSwipeGestureRecognizer;
                      QGestureRecognizer::registerRecognizer(customRecognizer);
                      grabGesture(Qt::CustomGesture);
                  
                  }
                  

                  custom gesture Recognizer in header file:

                  class FingerSwipeGestureRecognizer : public QGestureRecognizer
                   {
                   public:
                       FingerSwipeGestureRecognizer();
                  
                       QGesture *create(QObject *target);
                       QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event);
                       void reset(QGesture *state);
                       void setRegisteredGestureType(Qt::GestureType aGestureType);
                           Qt::GestureType getRegisterdGestureType();
                       private:
                           Qt::GestureType registeredGestureType;
                   };
                  
                  

                  is there anything that im missing ?

                  R Offline
                  R Offline
                  Red Baron
                  wrote on last edited by Red Baron
                  #8

                  @md2012 Also use it for the grabGesture(...) too. Qt::CustomGesture is something different. All custom gestures have the Qt::CustomGesture flag set unlike the predefine swipe, tap etc. which have their own (but part of the same enumeration).

                  1 Reply Last reply
                  0

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved