Example: Code snippets of a defining a custom gesture
QNX SDP8.0Gestures Library ReferenceAPIDeveloperProgramming
This example contains most of the code snippets that illustrate what you need in order to define a custom gesture.
custom_gesture.h
#include <gestures/types.h>
/* The stucture custom_gesture_params_t represents the parameters for the custom gesture. */
typedef struct {
unsigned max_displacement; /* The maximum distance the finger can move before
the custom gesture fails. */
unsigned max_hold_ms; /* The maximum time the finger can remain touching
the screen before the custom gesture fails. */
unsigned max_delay_ms; /* The time between the first release and the second touch. */
} custom_gesture_params_t;
/* The enumeration custom_gesture_state_e defines additional states the custom
* gesture can transition between. */
typedef enum {
CT_STATE_INIT = 0,
CT_STATE_FIRST_TOUCH,
CT_STATE_FIRST_RELEASE,
CT_STATE_SECOND_TOUCH,
CT_STATE_SECOND_RELEASE
} custom_gesture_state_e;
/* The structure gesture_custom_gesture_t carries data about the custom gesture. */
typedef struct {
gesture_base_t base; /* The gesture base data structure. */
custom_gesture_params_t params; /* The custom gesture parameters. */
gesture_coords_t first_touch; /* The coordinates of the first touch. */
gesture_coords_t first_release; /* The coordinates of the first release. */
gesture_coords_t second_touch; /* The coordinates of the second touch. */
gesture_coords_t second_release; /* The coordinates of the second release. */
custom_gesture_state_e dt_state; /* The intermediate state of the custom gesture. */
int fail_timer; /* The ID of the timer for this gesture. */
} gesture_custom_gesture_t;
/* Allocate and initialize the custom gesture structure */
gesture_custom_gesture_t* custom_gesture_gesture_alloc(custom_gesture_params_t* params,
gesture_callback_f callback,
struct gestures_set* set);
/* Initialize the custom parameters */
void custom_gesture_gesture_default_params(custom_gesture_params_t* params);
custom_gesture.c
/*The example below shows the implementation of a custom user-defined gesture. */
#include <sys/types.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include <gestures/set.h>
#include <gestures/timer.h>
#include <custom_gesture.h>
#include <input/event_types.h>
#include <gestures/defaults.h>
/* Custom free() function */
void custom_gesture_gesture_free(gesture_base_t* gesture)
{
free(gesture);
}
/* Custom helper function */
static int _check_valid(gesture_coords_t* coords1, gesture_coords_t* coords2,
unsigned max_displacement, unsigned max_ms)
{
return ((max_displacement_abs(coords1, coords2) <= max_displacement) &&
(diff_time_ms(coords1, coords2) <= max_ms));
}
/* Custom process_event() function */
gesture_state_e custom_gesture_gesture_process_event(struct contact_id_map* map,
gesture_base_t* gesture,
mtouch_event_t* event,
int* consumed)
{
gesture_custom_gesture_t* custom_gesture = (gesture_custom_gesture_t*)gesture;
gesture_coords_t coords;
gesture_coords_t* compare_coords;
int set_id = map_contact_id(map, event->contact_id);
if (set_id < 0) {
error("process_event() called with event with invalid contact_id");
goto failed;
}
switch (custom_gesture->base.state) {
case GESTURE_STATE_UNRECOGNIZED:
switch (event->event_type) {
case INPUT_EVENT_MTOUCH_TOUCH:
if (set_id > 0) {
goto failed;
} else if (custom_gesture->dt_state > CT_STATE_FIRST_TOUCH) {
gesture_timer_clear(gesture, custom_gesture->fail_timer);
save_coords(event, &custom_gesture->second_touch);
if (!_check_valid(&custom_gesture->first_release,
&custom_gesture->second_touch,
custom_gesture->params.max_displacement,
custom_gesture->params.max_delay_ms)) {
goto failed;
}
custom_gesture->dt_state = CT_STATE_SECOND_TOUCH;
} else {
save_coords(event, &custom_gesture->first_touch);
custom_gesture->dt_state = CT_STATE_FIRST_TOUCH;
}
goto nochange;
case INPUT_EVENT_MTOUCH_MOVE:
save_coords(event, &coords);
if (custom_gesture->dt_state >= CT_STATE_SECOND_TOUCH) {
compare_coords = &custom_gesture->second_touch;
} else {
compare_coords = &custom_gesture->first_touch;
}
if (!_check_valid(compare_coords, &coords,
custom_gesture->params.max_displacement,
custom_gesture->params.max_hold_ms)) {
goto failed;
}
goto nochange;
case INPUT_EVENT_MTOUCH_RELEASE:
if (custom_gesture->dt_state >= CT_STATE_SECOND_TOUCH) {
save_coords(event, &custom_gesture->second_release);
if (!_check_valid(&custom_gesture->second_touch,
&custom_gesture->second_release,
custom_gesture->params.max_displacement,
custom_gesture->params.max_hold_ms)) {
goto failed;
}
custom_gesture->dt_state = CT_STATE_SECOND_RELEASE;
goto complete;
} else {
save_coords(event, &custom_gesture->first_release);
if (!_check_valid(&custom_gesture->first_touch,
&custom_gesture->first_release,
custom_gesture->params.max_displacement,
custom_gesture->params.max_hold_ms)) {
goto failed;
}
custom_gesture->dt_state = CT_STATE_FIRST_RELEASE;
/* Set a timer in case an event doesn't come in */
gesture_timer_set_event(gesture,
custom_gesture->fail_timer,
custom_gesture->params.max_delay_ms,
event);
}
goto nochange;
default:
warn("Unhandled switch/case: %d", event->event_type);
goto failed;
}
case GESTURE_STATE_RECOGNIZED:
error("GESTURE_STATE_RECOGNIZED is an invalid state for double tap");
break;
case GESTURE_STATE_UPDATING:
error("GESTURE_STATE_UPDATING is an invalid state for double tap");
break;
case GESTURE_STATE_COMPLETE:
error("process_event() called on complete gesture");
break;
case GESTURE_STATE_FAILED:
error("process_event() called on failed gesture");
break;
case GESTURE_STATE_NONE:
error("process_event() called on uninitialized gesture");
break;
}
nochange:
*consumed = 0;
return custom_gesture->base.state;
failed:
*consumed = 0;
return GESTURE_STATE_FAILED;
complete:
*consumed = 1;
return GESTURE_STATE_COMPLETE;
}
/* Custom timer callback */
static gesture_state_e
timeout(gesture_base_t* base, void* param)
{
return GESTURE_STATE_FAILED;
}
/* Custom reset() function */
void custom_gesture_gesture_reset(gesture_base_t* gesture)
{
gesture_custom_gesture_t* custom_gesture = (gesture_custom_gesture_t*)gesture;
custom_gesture->dt_state = CT_STATE_INIT;
}
/* Initialize custom gesture parameters with default values. */
void custom_gesture_gesture_default_params(custom_gesture_params_t* params)
{
params->max_displacement = GESTURE_MAX_MOVE_TOLERANCE_PIX;
params->max_hold_ms = GESTURE_MAX_TAP_DELAY_MS;
params->max_delay_ms = GESTURE_MIN_HOLD_DELAY_MS;
}
/* Custom alloc() function */
gesture_custom_gesture_t* custom_gesture_gesture_alloc(custom_gesture_params_t* params,
gesture_callback_f callback,
struct gestures_set* set)
{
gesture_custom_gesture_t* custom_gesture = calloc(1, sizeof(*custom_gesture));
if (NULL == custom_gesture) {
return NULL;
}
gesture_base_init(&custom_gesture->base);
gestures_set_add(set, &custom_gesture->base);
custom_gesture->base.type = GESTURE_USER;
custom_gesture->base.funcs.free = custom_gesture_gesture_free;
custom_gesture->base.funcs.process_event = custom_gesture_gesture_process_event;
custom_gesture->base.funcs.reset = custom_gesture_gesture_reset;
custom_gesture->base.callback = callback;
custom_gesture->fail_timer = gesture_timer_create(&custom_gesture->base, timeout, NULL);
custom_gesture_gesture_reset(&custom_gesture->base);
if (NULL != params) {
custom_gesture->params = *params;
} else {
custom_gesture_gesture_default_params(&custom_gesture->params);
}
return custom_gesture;
}
Page updated: