Custom Gestures

Updated: October 28, 2024

You can define gesture recognizers to detect gestures that are not already supported by the Gestures library (custom gestures). Gesture recognizers that are used to detect custom gestures can be compiled with the application code and added to a gesture set in the same way that system gesture recognizers are added to a gesture set.

Custom gesture recognizer data types and functions

If you're defining your own custom gesture recognizers, you will need to provide the following as part of the definition and implementation of your own gesture recognizer:

Definition of your custom gesture

typedef struct {
   gesture_base_t base; /* The gesture base data structure. */
   ...                  /* The information specific to your custom gesture */
   int timer_id; /* The ID of the timer for this custom gesture (if needed) */
} gesture_custom_t;
            

This structure represents information for your custom gesture recognizer; this structure must include gesture_base_t followed by additional members to capture your specific information. For example, if your custom gesture recognizer uses a timer, you need to include the ID of the timer as a specific parameter.

Definition and implementation of the alloc() function

gesture_custom_t* custom_gesture_alloc(gesture_custom_params_t* params,
                                       gesture_callback_f callback,
                                       struct gestures_set* set);
               
where types and parameters are as follows:
gesture_custom_t
The structure of your custom gesture recognizer.
custom_gesture_alloc
The name of your gesture's alloc() function.
gesture_custom_params_t
A structure that represents the parameters of your custom gesture recognizer.
callback
The application gesture callback.
set
A gesture set that your custom gesture recognizer is to be added to.
Your alloc() function must:
  1. Allocate the memory necessary for your custom gesture recognizer.
  2. Invoke gesture_base_init() to initialize the gesture base data structure.
  3. Invoke gesture_set_add() to add your custom gesture to the gesture set.
  4. Set the gesture recognizer type as GESTURE_USER.
  5. Set the process_event(), the reset(), and the free() functions.
  6. Set the gesture callback: callback.
  7. Perform any custom gesture-specific initialization that isn't part of the reset.
  8. Store the custom gesture-specific parameters with the gesture recognizer, and set default parameters. If your custom gesture recognizer uses a timer, use gesture_timer_create() to obtain the ID for your timer.

Definition and implementation of the process_event() function

gesture_state_e (*process_event)(struct contact_id_map* map,
                                 struct gesture_base* gesture,
                                 mtouch_event_t* event, int* consumed)
               
Your process_event() function must handle state transitions and return the new, or unchanged, gesture recognizer state. If your custom gesture is time-based, you will need to adjust the timers accordingly. The Gestures library provides API functions for you to set and reset your timers.

Definition and implementation of the free() function

void (*free)(struct gesture_base* gesture)
             

Your free() function must release all the memory that's associated with your gesture recognizer that was allocated by your alloc() function.

Definition and implementation of the reset() function

void (*reset)(struct gesture_base* gesture);
               

Your reset() function must reset the gesture-specific data structures to their initial states.

Definition of parameters specific to your custom gesture (optional)

This is a structure that represents the parameters specific to your custom gesture recognizer.

Definition of states specific to your custom gesture (optional)

These are constants that represent the states specific to your custom gesture recognizer; these states are in addition to the set of states defined in gesture_state_e.

Definition and implementation of the gesture_timer_callback() function (optional)

gesture_state_e(*gesture_timer_callback_t)(struct gesture_base* gesture, void* param);
                

Gesture sets provide time-based notifications to gesture recognizers that use timers. A notification is implemented as a callback function to the gesture recognizer. If your custom gesture recognizer is timer-based, you need to implement this timer callback function.

A gesture recognizer can transition states on timer events. Similar to the process_event() function for mtouch events, the gesture recognizer's time-based state transitions are accomplished by its timer callback function. This function returns the new, or unchanged, state based on the timer event received.

Contact ID map

A contact ID is an identifier that is used to identify mtouch events. The mtouch event data structure contains the contact_id element that is assigned a value from a zero-based index and corresponds to the individual fingers that touch the screen. The contact ID doesn't change until that finger is released.

User-defined gestures typically need to associate a specific mtouch event with a contact ID for the purpose of associating the streams of events with the finger that caused them. The contact ID from the mtouch event can't be used directly by the custom gesture. Instead, user-defined gestures need to invoke map_contact_id() to obtain a zero-based contact ID that is remapped from the gesture set's perspective.

The remapping is necessary because a contact ID of 1 for an mtouch event could actually correspond to a gesture set's contact ID 0. This mapping could be the case if there are multiple gesture sets in play, or if the user's finger is resting on the touch-sensitive bevel.

Helper functions

Helper functions are available if you are defining your own gestures. These functions are:

void save_coords(mtouch_event_t *event,gesture_coords_t *coords)
This function saves the coordinates of a mtouch event in the specified gesture_coords_t data structure. This is useful if your gesture is sensitive to the placement of the touch event. For example, in a double-tap gesture, the coordinates of the first tap are saved and compared to the coordinates of the second tap. If these coordinates are within an acceptable range, the gesture recognizer can consider the gesture to be a double tap.
int32_t diff_time_ms(gesture_coords_t *coords1, gesture_coords_t *coords2)
This function returns the elapsed time between the two specified gesture events. This is useful if your gesture is dependent on the receipt of multiple mtouch events. For example, in a double-tap gesture, the time elapsed between the first and second tap cannot exceed an acceptable time. If too much time has elapsed between the two taps, the double-tap gesture is considered to have failed.
uint32_t max_displacement_abs(gesture_coords_t *coords1, gesture_coords_t *coords2)
This function returns the maximum displacement, in pixels, between two gesture events. For example, if the absolute value of the difference between the x coordinates of the two gestures is greater than the absolute value of the difference between the y coordinates, the former is returned by the function. For example, in a double-tap gesture, this function can be used to help determine whether or not the two taps received are close enough together on the screen to be considered a double-tap gesture.
int map_contact_id(struct contact_id_map *map, unsigned contact_id)
This function remaps contact identifiers from mtouch events to contact identifiers to be used by gestures. This function is typically one of the first calls in your custom gesture recognizer's process_event() function. You need to first map the contact_id from the mtouch event received to a contact_id that can be used by your custom gesture recognizer.
int gesture_timer_create(struct gesture_base* gesture, gesture_timer_callback_t callback, void* param)
This function creates a new timer that invokes your gesture recognizer's timer callback function when expired. You need to use this function if your gesture recognizer is time-based.
int gesture_timer_set_now(struct gesture_base* gesture, int timer_id, unsigned ms)
This function sets a timer using the current time as the reference time. You can use this if your gesture recognizer is time-based.
int gesture_timer_set_ms(struct gesture_base* gesture, int timer_id, unsigned ms, _Uint64t base_nsec)
This function sets a timer using a specified timestamp as the reference time. You can use this if your gesture recognizer is time-based.
int gesture_timer_set_event(struct gesture_base* gesture, int timer_id, unsigned ms, struct mtouch_event* base_event)
This function sets a timer using an mtouch event timestamp as the reference time. You can use this if your gesture recognizer is time-based.
void gesture_timer_destroy(struct gesture_base* gesture, int timer_id)
This function resets the specified timer. You can use this if your gesture recognizer is time-based.
int gesture_timer_query(struct gesture_base* gesture, int timer_id, int* pending, _Uint64t* expiry)
This function queries the information for the specified timer. You can use this if your gesture recognizer is time-based.
  翻译: