feat(indev): Add rotation and two fingers swipe gestures support (#7865)
This commit is contained in:
@@ -161,25 +161,44 @@ Multi-touch gestures
|
||||
|
||||
LVGL has the ability to recognize multi-touch gestures, when a gesture
|
||||
is detected a ``LV_EVENT_GESTURE`` is passed to the object on which the
|
||||
gesture occurred. Currently, only the pinch gesture is supported
|
||||
more gesture types will be implemented soon.
|
||||
gesture occurred. Currently, these multi-touch gestures are supported:
|
||||
|
||||
- Two fingers pinch (up and down)
|
||||
- Two fingers rotation
|
||||
- Two fingers swipe (infinite)
|
||||
|
||||
To enable the multi-touch gesture recognition set the
|
||||
``LV_USE_GESTURE_RECOGNITION`` option in the ``lv_conf.h`` file.
|
||||
|
||||
Touch event collection
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
Currently, the system sends the events if the gestures are in one of the following states:
|
||||
|
||||
The driver or application collects touch events until the indev read callback
|
||||
is called. It is the responsibility of the driver to call
|
||||
the gesture recognition function of the appropriate type. For example
|
||||
to recognise pinch gestures call ``lv_indev_gesture_detect_pinch``.
|
||||
- ``LV_INDEV_GESTURE_STATE_RECOGNIZED``: The gesture has been recognized and is now active.
|
||||
- ``LV_INDEV_GESTURE_STATE_ENDED``: The gesture has ended.
|
||||
|
||||
After calling the gesture detection function, it's necessary to call
|
||||
the ``lv_indev_set_gesture_data`` function to set the ``gesture_data``
|
||||
and ``gesture_type`` fields of the structure ``lv_indev_data_t``
|
||||
|
||||
.. code-block::
|
||||
Multi-touch gestures overview
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To recognize multi touch gestures, recognizers are used. The structure ``lv_indev_t`` contains
|
||||
an array of recognizers, one per gesture type. These recognizers are initialized internally by ``lv_indev_create`` by calling
|
||||
``lv_indev_gesture_init_recognizers`` after the indev device is created. The the recognizers can then be configured to
|
||||
modify the gestures thresholds. These thresholds are used to be able to recognize the gesture only after the threshold
|
||||
have been reached. They can be set-up like this:
|
||||
|
||||
- ``lv_indev_set_pinch_up_threshold(lv_indev_t * indev, float threshold)``: Set the pinch up (zoom in) threshold in pixels.
|
||||
- ``lv_indev_set_pinch_down_threshold(lv_indev_t * indev, float threshold)``: Set the pinch down (zoom out) threshold in pixels.
|
||||
- ``lv_indev_set_rotation_rad_threshold(lv_indev_t * indev, float threshold)``: Set the rotation angle threshold in radians.
|
||||
|
||||
The recognizers can then be updated to recognize the gestures by calling ``lv_indev_gesture_recognizers_update``.
|
||||
This must be done in the user defined indev ``read_cb``. This will iterate over the recognizers and stop once it detects a
|
||||
recognized or ended gesture. For now only one multi-touch gesture can be recognized/ended at a time.
|
||||
|
||||
Once the recognizers are updated, calling ``lv_indev_gesture_recognizers_set_data`` will update the ``lv_indev_data_t`` structure.
|
||||
It is meant to be done in the indev ``read_cb``. This allows the future ``lv_event_t`` to eb filled with multi-touch gesture info.
|
||||
|
||||
Here is an example of the ``read_cb``:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* The recognizer keeps the state of the gesture */
|
||||
static lv_indev_gesture_recognizer_t recognizer;
|
||||
@@ -194,34 +213,146 @@ and ``gesture_type`` fields of the structure ``lv_indev_data_t``
|
||||
{
|
||||
|
||||
lv_indev_touch_data_t * touch;
|
||||
uint8_t i;
|
||||
|
||||
|
||||
touch = &touches[0];
|
||||
lv_indev_gesture_detect_pinch(recognizer, &touches[0],
|
||||
touch_cnt);
|
||||
lv_indev_update_recognizers(drv, &touches[0], touch_cnt);
|
||||
|
||||
touch_cnt = 0;
|
||||
|
||||
/* Set the gesture information, before returning to LVGL */
|
||||
lv_indev_set_gesture_data(data, recognizer);
|
||||
lv_indev_gesture_recognizers_set_data(drv, data);
|
||||
|
||||
}
|
||||
|
||||
A touch event is represented by the ``lv_indev_touch_data_t`` structure, the fields
|
||||
being 1:1 compatible with events emitted by the `libinput <https://wayland.freedesktop.org/libinput/doc/latest/>`_ library
|
||||
The user is in charge of collecting the necessary touches events from the driver until the indev ``read_cb`` is called.
|
||||
It must then convert the specific driver input to ``lv_indev_touch_data_t`` to be processed by the ``read_cb`` at a later point.
|
||||
Here is an example using ``libinput``:
|
||||
|
||||
Handling touch events
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
.. code-block:: c
|
||||
|
||||
Touch events are handled like any other event. First, setup a listener for the ``LV_EVENT_GESTURE`` event type by defining and setting the callback function.
|
||||
/**
|
||||
* @brief Convert the libinput to lvgl's representation of touch event
|
||||
* @param ev a pointer to the lib input event
|
||||
*/
|
||||
static void touch_event_queue_add(struct libinput_event *ev)
|
||||
{
|
||||
struct libinput_event_touch *touch_ev;
|
||||
lv_indev_touch_data_t *cur;
|
||||
lv_indev_touch_data_t *t;
|
||||
uint32_t time;
|
||||
int i;
|
||||
int id;
|
||||
int type;
|
||||
|
||||
The state or scale of the pinch gesture can be retrieved by
|
||||
calling the ``lv_event_get_pinch_scale`` and ``lv_indev_get_gesture_state`` from within the
|
||||
callback.
|
||||
type = libinput_event_get_type(ev);
|
||||
touch_ev = libinput_event_get_touch_event(ev);
|
||||
id = libinput_event_touch_get_slot(touch_ev);
|
||||
time = libinput_event_touch_get_time(touch_ev);
|
||||
|
||||
/* Get the last event for contact point */
|
||||
t = &touches[0];
|
||||
cur = NULL;
|
||||
|
||||
for (i = 0; i < touch_cnt; i++) {
|
||||
if (t->id == id) {
|
||||
cur = t;
|
||||
}
|
||||
t++;
|
||||
}
|
||||
|
||||
if (cur != NULL && cur->timestamp == time) {
|
||||
/* Previous event has the same timestamp - ignore duplicate event */
|
||||
return;
|
||||
}
|
||||
|
||||
if (cur == NULL ||
|
||||
type == LIBINPUT_EVENT_TOUCH_UP ||
|
||||
type == LIBINPUT_EVENT_TOUCH_DOWN) {
|
||||
|
||||
/* create new event */
|
||||
cur = &touches[touch_cnt];
|
||||
touch_cnt++;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case LIBINPUT_EVENT_TOUCH_DOWN:
|
||||
case LIBINPUT_EVENT_TOUCH_MOTION:
|
||||
|
||||
cur->point.x = (int) libinput_event_touch_get_x_transformed(touch_ev, SCREEN_WIDTH);
|
||||
cur->point.y = (int) libinput_event_touch_get_y_transformed(touch_ev, SCREEN_HEIGHT);
|
||||
cur->state = LV_INDEV_STATE_PRESSED;
|
||||
break;
|
||||
|
||||
case LIBINPUT_EVENT_TOUCH_UP:
|
||||
|
||||
cur->state = LV_INDEV_STATE_RELEASED;
|
||||
cur->point.x = 0;
|
||||
cur->point.y = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
cur->timestamp = time;
|
||||
cur->id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Filter out libinput events that are not related to touches
|
||||
* @param ev a pointer to the lib input event
|
||||
*/
|
||||
static void process_libinput_event(struct libinput_event *ev)
|
||||
{
|
||||
int type;
|
||||
|
||||
type = libinput_event_get_type(ev);
|
||||
|
||||
switch (type) {
|
||||
case LIBINPUT_EVENT_TOUCH_MOTION:
|
||||
case LIBINPUT_EVENT_TOUCH_DOWN:
|
||||
case LIBINPUT_EVENT_TOUCH_UP:
|
||||
/* Filter only touch events */
|
||||
touch_event_queue_add(ev);
|
||||
break;
|
||||
default:
|
||||
/* Skip an unrelated libinput event */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
From this setup, the user can now register events callbacks to react to ``LV_EVENT_GESTURE``.
|
||||
|
||||
.. note::
|
||||
A touch event is represented by the ``lv_indev_touch_data_t`` structure, the fields
|
||||
being 1:1 compatible with events emitted by the `libinput <https://wayland.freedesktop.org/libinput/doc/latest/>`_ library
|
||||
|
||||
|
||||
Handling multi-touch gesture events
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Once a gesture is recognized or ended, a ``LV_EVENT_GESTURE`` is sent. The user can the use these functions to
|
||||
gather more information about the gesture:
|
||||
|
||||
- ``lv_event_get_gesture_type(lv_event_t * gesture_event)``: Get the type of the gesture. To be
|
||||
used to check which multi-touch gesture is currently reported.
|
||||
- ``lv_indev_gesture_state_t lv_event_get_gesture_state(lv_event_t * gesture_event, lv_indev_gesture_type_t type)``: Get the
|
||||
state of the gesture. It can be one of those:
|
||||
|
||||
- ``LV_INDEV_GESTURE_STATE_NONE``: The gesture is not active.
|
||||
- ``LV_INDEV_GESTURE_STATE_RECOGNIZED``: The gesture is recognized and can be used.
|
||||
- ``LV_INDEV_GESTURE_STATE_ENDED``: The gesture ended.
|
||||
|
||||
These functions allow the user to confirm the gesture is the expected one and that it is in a usable state.
|
||||
The user can then request the gestures values with the following functions:
|
||||
|
||||
- ``lv_event_get_pinch_scale(lv_event_t * gesture_event)``: Get the pinch scale. Only relevant for pinch gesture.
|
||||
- ``lv_event_get_rotation(lv_event_t * gesture_event)``: Get the rotation in radians. Only relevant for rotation gesture.
|
||||
- ``lv_event_get_two_fingers_swipe_distance(lv_event_t * gesture_event)``: Get the distance in pixels from the gesture staring center.
|
||||
Only relevant for two fingers swipe gesture.
|
||||
- ``lv_event_get_two_fingers_swipe_dir(lv_event_t * gesture_event)``: Get the direction from the starting center. Only relevant for
|
||||
two fingers swipe gesture.
|
||||
|
||||
This allow the user to react to the gestures and to use the gestures values. An example of such an application is available in
|
||||
the source tree ``examples/others/gestures/lv_example_gestures.c``.
|
||||
|
||||
An example of such an application is available in
|
||||
the source tree ``examples/others/gestures/lv_example_gestures.c``
|
||||
|
||||
Keypad or Keyboard
|
||||
------------------
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
* the gesture recognition API, please refer to lv_indev_gesture.h or the documentation
|
||||
* for more details
|
||||
*
|
||||
* The application starts with a single rectangle that is scaled when a pinch gesture
|
||||
* is detected. A single finger moves the rectangle around,
|
||||
* The application starts with a single rectangle. The user can then
|
||||
* - Pinch the rectangle to scale it
|
||||
* - Rotate the rectangle to rotate it
|
||||
* - Two fingers swipe the rectangle to see the direction and the distance of the swipe
|
||||
*
|
||||
* Copyright (c) 2024 EDGEMTech Ltd
|
||||
*
|
||||
@@ -26,10 +28,14 @@
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define RECT_INIT_WIDTH 300.0
|
||||
#define RECT_INIT_HEIGHT 300.0
|
||||
#define RECT_INIT_WIDTH 300
|
||||
#define RECT_INIT_HEIGHT 300
|
||||
#define RECT_COLOR 0xC1BCFF
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.1415926f
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
@@ -39,7 +45,8 @@
|
||||
**********************/
|
||||
|
||||
static void label_scale(lv_event_t * gesture_event);
|
||||
static void label_move(lv_event_t * event);
|
||||
static void label_rotate(lv_event_t * gesture_event);
|
||||
static void label_swipe(lv_event_t * gesture_event);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@@ -47,10 +54,10 @@ static void label_move(lv_event_t * event);
|
||||
|
||||
static lv_obj_t * label;
|
||||
static lv_style_t label_style;
|
||||
static float label_width;
|
||||
static float label_height;
|
||||
static float label_x;
|
||||
static float label_y;
|
||||
static uint32_t label_width;
|
||||
static uint32_t label_height;
|
||||
static uint32_t label_x;
|
||||
static uint32_t label_y;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
@@ -60,6 +67,7 @@ static float label_y;
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
|
||||
/**
|
||||
* Entry point it creates the screen, and the label
|
||||
* Set event callbacks on the label
|
||||
@@ -70,15 +78,16 @@ void lv_example_gestures(void)
|
||||
|
||||
label_width = RECT_INIT_WIDTH;
|
||||
label_height = RECT_INIT_HEIGHT;
|
||||
label_y = label_x = 300;
|
||||
label_x = LV_HOR_RES / 2 - (label_width / 2);
|
||||
label_y = LV_VER_RES / 2 - (label_height / 2);
|
||||
|
||||
root_view = lv_screen_active();
|
||||
|
||||
lv_obj_set_style_bg_color(root_view, lv_color_hex(0xFFFFFF), LV_PART_MAIN);
|
||||
lv_obj_set_style_bg_color(root_view, lv_color_hex(0xffffff), LV_PART_MAIN);
|
||||
label = lv_label_create(root_view);
|
||||
lv_obj_remove_flag(root_view, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
lv_label_set_text(label, "Zoom or move");
|
||||
lv_label_set_text(label, "Zoom, rotate or move");
|
||||
lv_obj_add_flag(label, LV_OBJ_FLAG_CLICKABLE);
|
||||
|
||||
lv_style_init(&label_style);
|
||||
@@ -93,9 +102,9 @@ void lv_example_gestures(void)
|
||||
|
||||
lv_obj_add_style(label, &label_style, LV_STATE_DEFAULT);
|
||||
|
||||
lv_obj_add_event_cb(label, label_rotate, LV_EVENT_GESTURE, label);
|
||||
lv_obj_add_event_cb(label, label_scale, LV_EVENT_GESTURE, label);
|
||||
lv_obj_add_event_cb(label, label_move, LV_EVENT_PRESSING, label);
|
||||
|
||||
lv_obj_add_event_cb(label, label_swipe, LV_EVENT_GESTURE, label);
|
||||
}
|
||||
|
||||
/**********************
|
||||
@@ -103,8 +112,56 @@ void lv_example_gestures(void)
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Called when a pinch event occurs - scales the label
|
||||
* @param gesture_event point to a LV_EVENT_PINCH event
|
||||
* Called when a LV_EVENT_GESTURE event occurs - update the label if the gesture is a swipe
|
||||
* @param gesture_event pointer to a LV_EVENT_GESTURE event
|
||||
*/
|
||||
static void label_swipe(lv_event_t * gesture_event)
|
||||
{
|
||||
|
||||
lv_dir_t dir;
|
||||
lv_indev_gesture_state_t state;
|
||||
char * text;
|
||||
|
||||
if(lv_event_get_gesture_type(gesture_event) != LV_INDEV_GESTURE_TWO_FINGERS_SWIPE) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = lv_event_get_gesture_state(gesture_event, LV_INDEV_GESTURE_TWO_FINGERS_SWIPE);
|
||||
dir = lv_event_get_two_fingers_swipe_dir(gesture_event);
|
||||
|
||||
if(state == LV_INDEV_GESTURE_STATE_ENDED) {
|
||||
|
||||
text = "NONE";
|
||||
lv_label_set_text(label, text);
|
||||
}
|
||||
else if(state == LV_INDEV_GESTURE_STATE_RECOGNIZED) {
|
||||
|
||||
switch(dir) {
|
||||
case LV_DIR_LEFT:
|
||||
text = "LEFT";
|
||||
break;
|
||||
case LV_DIR_RIGHT:
|
||||
text = "RIGHT";
|
||||
break;
|
||||
case LV_DIR_TOP:
|
||||
text = "TOP";
|
||||
break;
|
||||
case LV_DIR_BOTTOM:
|
||||
text = "BOTTOM";
|
||||
break;
|
||||
default:
|
||||
text = "???";
|
||||
break;
|
||||
}
|
||||
|
||||
lv_label_set_text_fmt(label, "%s - %f", text, lv_event_get_two_fingers_swipe_distance(gesture_event));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a LV_EVENT_GESTURE event occurs - scales the label if the gesture is a pinch
|
||||
* @param gesture_event pointer to a LV_EVENT_GESTURE event
|
||||
*/
|
||||
static void label_scale(lv_event_t * gesture_event)
|
||||
{
|
||||
@@ -112,87 +169,115 @@ static void label_scale(lv_event_t * gesture_event)
|
||||
static int initial_w = -1;
|
||||
static int initial_h = -1;
|
||||
lv_indev_gesture_state_t state;
|
||||
lv_point_t center_pnt;
|
||||
static lv_point_t center_pnt;
|
||||
static float base_scale = 1.0;
|
||||
float scale;
|
||||
float label_width_float;
|
||||
float label_height_float;
|
||||
|
||||
scale = lv_event_get_pinch_scale(gesture_event);
|
||||
state = lv_event_get_gesture_state(gesture_event);
|
||||
/* Ensure the gesture is a pinch */
|
||||
if(lv_event_get_gesture_type(gesture_event) != LV_INDEV_GESTURE_PINCH) {
|
||||
return;
|
||||
}
|
||||
|
||||
lv_indev_get_point(lv_indev_active(), ¢er_pnt);
|
||||
state = lv_event_get_gesture_state(gesture_event, LV_INDEV_GESTURE_PINCH);
|
||||
|
||||
scale = base_scale * lv_event_get_pinch_scale(gesture_event);
|
||||
|
||||
/* Reset state when the gesture ended */
|
||||
if(state == LV_INDEV_GESTURE_STATE_ENDED) {
|
||||
|
||||
/* Pinch gesture has ended - reset the width/height for the next pinch gesture*/
|
||||
initial_w = -1;
|
||||
initial_h = -1;
|
||||
|
||||
LV_LOG_USER("label end scale: %g, state: %d", scale, state);
|
||||
base_scale = scale;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(initial_h == -1 || initial_w == -1) {
|
||||
/* The first time the gesture is recognized, save its center */
|
||||
if(state == LV_INDEV_GESTURE_STATE_RECOGNIZED) {
|
||||
|
||||
LV_ASSERT(state == LV_INDEV_GESTURE_STATE_RECOGNIZED);
|
||||
if((initial_h == -1 || initial_w == -1)) {
|
||||
|
||||
/* Pinch gesture has been recognized - this is the first event in a series of recognized events */
|
||||
/* The scaling is applied relative to the original width/height of the rectangle */
|
||||
initial_w = (int)label_width;
|
||||
initial_h = (int)label_height;
|
||||
/* Pinch gesture has been recognized - this is the first event in a series of recognized events */
|
||||
/* The scaling is applied relative to the original width/height of the rectangle */
|
||||
initial_w = label_width;
|
||||
initial_h = label_height;
|
||||
center_pnt.x = lv_obj_get_x(label) + label_width / 2;
|
||||
center_pnt.y = lv_obj_get_y(label) + label_height / 2;
|
||||
}
|
||||
|
||||
LV_LOG_USER("label start scale: %g", scale);
|
||||
/* The gesture is recognized, we can now use the scale */
|
||||
|
||||
/* Avoids a situation where the rectangle becomes too small or too big,
|
||||
* adding limits */
|
||||
if(scale < 0.4f) {
|
||||
scale = 0.4f;
|
||||
}
|
||||
else if(scale > 2.0f) {
|
||||
scale = 2.0f;
|
||||
}
|
||||
|
||||
label_x = center_pnt.x - label_width / 2;
|
||||
label_y = center_pnt.y - label_height / 2;
|
||||
|
||||
label_width_float = (float)RECT_INIT_WIDTH * scale;
|
||||
label_height_float = (float)RECT_INIT_HEIGHT * scale;
|
||||
|
||||
/* Update position and size */
|
||||
lv_style_set_width(&label_style, (int)label_width_float);
|
||||
lv_style_set_height(&label_style, (int)label_height_float);
|
||||
lv_style_set_x(&label_style, (int)label_x);
|
||||
lv_style_set_y(&label_style, (int)label_y);
|
||||
|
||||
lv_obj_add_style(label, &label_style, LV_STATE_DEFAULT);
|
||||
|
||||
label_width = (int)label_width_float;
|
||||
label_height = (int)label_height_float;
|
||||
}
|
||||
|
||||
/* The gesture has started or is on-going */
|
||||
|
||||
/* Avoids a situation where the rectangle becomes too small,
|
||||
* do not perform the scaling - leave straight away */
|
||||
if(scale < 0.4) {
|
||||
return;
|
||||
}
|
||||
|
||||
label_width = initial_w * scale;
|
||||
label_height = initial_h * scale;
|
||||
label_x = center_pnt.x - label_width / 2;
|
||||
label_y = center_pnt.y - label_height / 2;
|
||||
|
||||
LV_LOG_USER("label scale: %g label x: %g label y: %g w: %g h: %g",
|
||||
scale, label_x, label_y, label_width, label_height);
|
||||
|
||||
/* Update position and size */
|
||||
lv_style_set_width(&label_style, (int)label_width);
|
||||
lv_style_set_height(&label_style, (int)label_height);
|
||||
lv_style_set_x(&label_style, (int)label_x);
|
||||
lv_style_set_y(&label_style, (int)label_y);
|
||||
|
||||
lv_obj_add_style(label, &label_style, LV_STATE_DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called when a LV_EVENT_PRESSING occurs on the rectangle - moves the label
|
||||
* @param event pointer to the event
|
||||
* Called when a LV_EVENT_GESTURE event occurs - rotate the label if the gesture is a rotation
|
||||
* @param gesture_event pointer to a LV_EVENT_GESTURE event
|
||||
*/
|
||||
static void label_move(lv_event_t * event)
|
||||
static void label_rotate(lv_event_t * gesture_event)
|
||||
{
|
||||
lv_point_t pnt;
|
||||
|
||||
float angle_degrees = 0.f;
|
||||
static float start_angle = 0.f;
|
||||
lv_indev_gesture_state_t state;
|
||||
|
||||
state = lv_event_get_gesture_state(event);
|
||||
lv_indev_get_point(lv_indev_active(), &pnt);
|
||||
|
||||
/* Do not move and when a pinch gesture is ongoing */
|
||||
if(state == LV_INDEV_GESTURE_STATE_RECOGNIZED) {
|
||||
if(lv_event_get_gesture_type(gesture_event) != LV_INDEV_GESTURE_ROTATE) {
|
||||
return;
|
||||
}
|
||||
|
||||
LV_LOG_USER("label move x: %" LV_PRId32 ", y: %" LV_PRId32, pnt.x, pnt.y);
|
||||
state = lv_event_get_gesture_state(gesture_event, LV_INDEV_GESTURE_ROTATE);
|
||||
|
||||
label_x = pnt.x - label_width / 2;
|
||||
label_y = pnt.y - label_height / 2;
|
||||
/* Calculate new angle. The x10 is due to lv_obj_set_style_transform_rotation using x10 angle in parameter */
|
||||
angle_degrees = start_angle + 10.0f * (lv_event_get_rotation(gesture_event) * 180.0f / M_PI);
|
||||
|
||||
/* Update position */
|
||||
lv_style_set_x(&label_style, (int)label_x);
|
||||
lv_style_set_y(&label_style, (int)label_y);
|
||||
/* Once the gesture ends, save the current angle to the start_angle */
|
||||
if(state == LV_INDEV_GESTURE_STATE_ENDED) {
|
||||
|
||||
lv_obj_add_style(label, &label_style, LV_STATE_DEFAULT);
|
||||
start_angle = angle_degrees;
|
||||
}
|
||||
|
||||
/* If the gesture is recognized, rotate the label */
|
||||
if(state == LV_INDEV_GESTURE_STATE_RECOGNIZED) {
|
||||
|
||||
/* Need to set the pivot to the center of the widget to not rotate
|
||||
around the top-left corner */
|
||||
lv_obj_set_style_transform_pivot_x(label, lv_obj_get_width(label) / 2, 0);
|
||||
lv_obj_set_style_transform_pivot_y(label, lv_obj_get_height(label) / 2, 0);
|
||||
|
||||
lv_obj_set_style_transform_rotation(label, (int) angle_degrees, 0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* LV_USE_GESTURE_RECOGNITION && LV_USE_FLOAT */
|
||||
|
||||
@@ -120,7 +120,6 @@ struct input {
|
||||
lv_indev_touch_data_t touches[10];
|
||||
uint8_t touch_event_cnt;
|
||||
uint8_t primary_id;
|
||||
lv_indev_gesture_recognizer_t recognizer;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -2382,24 +2381,21 @@ static void _lv_wayland_touch_read(lv_indev_t * drv, lv_indev_data_t * data)
|
||||
{
|
||||
|
||||
struct window * window = lv_display_get_user_data(lv_indev_get_display(drv));
|
||||
lv_indev_gesture_recognizer_t * recognizer;
|
||||
|
||||
if(!window || window->closed) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Collect touches if there are any - send them to the gesture recognizer */
|
||||
recognizer = &window->body->input.recognizer;
|
||||
lv_indev_gesture_recognizers_update(drv, &window->body->input.touches[0],
|
||||
window->body->input.touch_event_cnt);
|
||||
|
||||
LV_LOG_TRACE("collected touch events: %d", window->body->input.touch_event_cnt);
|
||||
|
||||
lv_indev_gesture_detect_pinch(recognizer, &window->body->input.touches[0],
|
||||
window->body->input.touch_event_cnt);
|
||||
|
||||
window->body->input.touch_event_cnt = 0;
|
||||
|
||||
/* Set the gesture information, before returning to LVGL */
|
||||
lv_indev_set_gesture_data(data, recognizer);
|
||||
lv_indev_gesture_recognizers_set_data(drv, data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ static void indev_gesture(lv_indev_t * indev);
|
||||
static bool indev_reset_check(lv_indev_t * indev);
|
||||
static void indev_read_core(lv_indev_t * indev, lv_indev_data_t * data);
|
||||
static void indev_reset_core(lv_indev_t * indev, lv_obj_t * obj);
|
||||
static void indev_init_gesture_recognizers(lv_indev_t * indev);
|
||||
static lv_result_t send_event(lv_event_code_t code, void * param);
|
||||
|
||||
static void indev_scroll_throw_anim_start(lv_indev_t * indev);
|
||||
@@ -141,6 +142,9 @@ lv_indev_t * lv_indev_create(void)
|
||||
indev->gesture_limit = LV_INDEV_DEF_GESTURE_LIMIT;
|
||||
indev->gesture_min_velocity = LV_INDEV_DEF_GESTURE_MIN_VELOCITY;
|
||||
indev->rotary_sensitivity = LV_INDEV_DEF_ROTARY_SENSITIVITY;
|
||||
|
||||
indev_init_gesture_recognizers(indev);
|
||||
|
||||
return indev;
|
||||
}
|
||||
|
||||
@@ -729,8 +733,12 @@ static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data)
|
||||
i->pointer.act_point.y = data->point.y;
|
||||
i->pointer.diff = data->enc_diff;
|
||||
|
||||
i->gesture_type = data->gesture_type;
|
||||
i->gesture_data = data->gesture_data;
|
||||
#if LV_USE_GESTURE_RECOGNITION
|
||||
for(int gest = 0; gest < LV_INDEV_GESTURE_CNT; gest++) {
|
||||
i->gesture_type[gest] = data->gesture_type[gest];
|
||||
i->gesture_data[gest] = data->gesture_data[gest];
|
||||
}
|
||||
#endif
|
||||
|
||||
/*Process the diff first as scrolling will be processed in indev_proc_release*/
|
||||
indev_proc_pointer_diff(i);
|
||||
@@ -1296,19 +1304,30 @@ static void indev_proc_press(lv_indev_t * indev)
|
||||
indev->pointer.press_moved = 1;
|
||||
}
|
||||
|
||||
/* Send a gesture event to a potential indev cb callback, even if no object was found */
|
||||
if(indev->gesture_type != LV_INDEV_GESTURE_NONE) {
|
||||
lv_indev_send_event(indev, LV_EVENT_GESTURE, indev_act);
|
||||
#if LV_USE_GESTURE_RECOGNITION
|
||||
for(int i = 0; i < LV_INDEV_GESTURE_CNT; i++) {
|
||||
/* Send a gesture event to a potential indev cb callback, even if no object was found */
|
||||
if(indev->gesture_type[i] != LV_INDEV_GESTURE_NONE) {
|
||||
indev->cur_gesture = (lv_indev_gesture_type_t) i;
|
||||
lv_indev_send_event(indev, LV_EVENT_GESTURE, indev_act);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(indev_obj_act) {
|
||||
const bool is_enabled = !lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED);
|
||||
|
||||
if(indev->gesture_type != LV_INDEV_GESTURE_NONE) {
|
||||
/* NOTE: hardcoded to pinch for now */
|
||||
if(send_event(LV_EVENT_GESTURE, indev_act) == LV_RESULT_INVALID) return;
|
||||
}
|
||||
#if LV_USE_GESTURE_RECOGNITION
|
||||
for(int i = 0; i < LV_INDEV_GESTURE_CNT; i++) {
|
||||
|
||||
if(indev->gesture_type[i] != LV_INDEV_GESTURE_NONE) {
|
||||
indev->cur_gesture = (lv_indev_gesture_type_t) i;
|
||||
if(send_event(LV_EVENT_GESTURE, indev_act) == LV_RESULT_INVALID) return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(is_enabled) {
|
||||
if(send_event(LV_EVENT_PRESSING, indev_act) == LV_RESULT_INVALID) return;
|
||||
}
|
||||
@@ -1400,20 +1419,32 @@ static void indev_proc_release(lv_indev_t * indev)
|
||||
lv_timer_pause(indev->read_timer);
|
||||
}
|
||||
|
||||
#if LV_USE_GESTURE_RECOGNITION
|
||||
/* Send a gesture event to a potential indev cb callback, even if no object was found */
|
||||
if(indev->gesture_type != LV_INDEV_GESTURE_NONE) {
|
||||
lv_indev_send_event(indev, LV_EVENT_GESTURE, indev_act);
|
||||
for(int i = 0; i < LV_INDEV_GESTURE_CNT; i++) {
|
||||
|
||||
if(indev->gesture_type[i] != LV_INDEV_GESTURE_NONE) {
|
||||
indev_act->cur_gesture = (lv_indev_gesture_type_t) i;
|
||||
lv_indev_send_event(indev, LV_EVENT_GESTURE, indev_act);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(indev_obj_act) {
|
||||
LV_LOG_INFO("released");
|
||||
|
||||
const bool is_enabled = !lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED);
|
||||
|
||||
if(is_enabled && indev->gesture_type != LV_INDEV_GESTURE_NONE) {
|
||||
if(send_event(LV_EVENT_GESTURE, indev_act) == LV_RESULT_INVALID) return;
|
||||
#if LV_USE_GESTURE_RECOGNITION
|
||||
for(int i = 0; i < LV_INDEV_GESTURE_CNT; i++) {
|
||||
if(is_enabled && indev->gesture_type[i] != LV_INDEV_GESTURE_NONE) {
|
||||
indev_act->cur_gesture = (lv_indev_gesture_type_t) i;
|
||||
if(send_event(LV_EVENT_GESTURE, indev_act) == LV_RESULT_INVALID) return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
if(is_enabled) {
|
||||
if(send_event(LV_EVENT_RELEASED, indev_act) == LV_RESULT_INVALID) return;
|
||||
}
|
||||
@@ -1851,3 +1882,21 @@ static void indev_scroll_throw_anim_start(lv_indev_t * indev)
|
||||
|
||||
indev->scroll_throw_anim = lv_anim_start(&a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize this indev's recognizers. It specify their recognizer function
|
||||
* @param indev pointer to the indev containing the recognizers to initialize
|
||||
*/
|
||||
static void indev_init_gesture_recognizers(lv_indev_t * indev)
|
||||
{
|
||||
#if LV_USE_GESTURE_RECOGNITION
|
||||
indev->recognizers[LV_INDEV_GESTURE_NONE].recog_fn = NULL;
|
||||
indev->recognizers[LV_INDEV_GESTURE_PINCH].recog_fn = lv_indev_gesture_detect_pinch;
|
||||
indev->recognizers[LV_INDEV_GESTURE_ROTATE].recog_fn = lv_indev_gesture_detect_rotation;
|
||||
indev->recognizers[LV_INDEV_GESTURE_TWO_FINGERS_SWIPE].recog_fn = lv_indev_gesture_detect_two_fingers_swipe;
|
||||
indev->recognizers[LV_INDEV_GESTURE_SCROLL].recog_fn = NULL;
|
||||
indev->recognizers[LV_INDEV_GESTURE_SWIPE].recog_fn = NULL;
|
||||
#else
|
||||
LV_UNUSED(indev);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ typedef enum {
|
||||
LV_INDEV_GESTURE_PINCH,
|
||||
LV_INDEV_GESTURE_SWIPE,
|
||||
LV_INDEV_GESTURE_ROTATE,
|
||||
LV_INDEV_GESTURE_TWO_FINGERS_SWIPE,
|
||||
LV_INDEV_GESTURE_SCROLL, /* Used with scrollwheels */
|
||||
LV_INDEV_GESTURE_CNT, /* Total number of gestures types */
|
||||
} lv_indev_gesture_type_t;
|
||||
@@ -68,8 +69,8 @@ typedef struct {
|
||||
lv_indev_state_t state; /**< LV_INDEV_STATE_RELEASED or LV_INDEV_STATE_PRESSED*/
|
||||
bool continue_reading; /**< If set to true, the read callback is invoked again, unless the device is in event-driven mode*/
|
||||
|
||||
lv_indev_gesture_type_t gesture_type;
|
||||
void * gesture_data;
|
||||
lv_indev_gesture_type_t gesture_type[LV_INDEV_GESTURE_CNT]; /* Current gesture types, per gesture */
|
||||
void * gesture_data[LV_INDEV_GESTURE_CNT]; /* Used to store data per gesture */
|
||||
|
||||
} lv_indev_data_t;
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#define LV_GESTURE_PINCH_DOWN_THRESHOLD 0.75f /* Default value - start sending events when reached */
|
||||
#define LV_GESTURE_PINCH_UP_THRESHOLD 1.5f /* Default value - start sending events when reached */
|
||||
#define LV_GESTURE_PINCH_MAX_INITIAL_SCALE 2.5f /* Default value */
|
||||
#define LV_GESTURE_ROTATION_ANGLE_RAD_THRESHOLD 0.2f /* Default value - start sending events when reached */
|
||||
|
||||
|
||||
/********************
|
||||
@@ -46,7 +47,10 @@ static void process_touch_event(lv_indev_touch_data_t * touch, lv_indev_gesture_
|
||||
static void gesture_update_center_point(lv_indev_gesture_t * gesture, int touch_points_nb);
|
||||
static void gesture_calculate_factors(lv_indev_gesture_t * gesture, int touch_points_nb);
|
||||
static void reset_recognizer(lv_indev_gesture_recognizer_t * recognizer);
|
||||
static lv_indev_gesture_recognizer_t * lv_indev_get_gesture_recognizer(lv_event_t * gesture_event);
|
||||
static lv_indev_gesture_recognizer_t * lv_indev_get_gesture_recognizer(lv_event_t * gesture_event,
|
||||
lv_indev_gesture_type_t type);
|
||||
static lv_dir_t calculate_swipe_dir(lv_indev_gesture_recognizer_t * recognizer);
|
||||
static lv_indev_gesture_type_t get_first_recognized_or_ended_gesture(lv_indev_t * indev);
|
||||
|
||||
/********************
|
||||
* STATIC VARIABLES
|
||||
@@ -55,16 +59,20 @@ static lv_indev_gesture_recognizer_t * lv_indev_get_gesture_recognizer(lv_event_
|
||||
/********************
|
||||
* MACROS
|
||||
********************/
|
||||
#define SQUARE(x) ((x) * (x))
|
||||
#define SQUARE_SUM(x, y) (SQUARE(x) + SQUARE(y))
|
||||
|
||||
/********************
|
||||
* GLOBAL FUNCTIONS
|
||||
********************/
|
||||
|
||||
void lv_indev_set_pinch_up_threshold(lv_indev_gesture_recognizer_t * recognizer, float threshold)
|
||||
void lv_indev_set_pinch_up_threshold(lv_indev_t * indev, float threshold)
|
||||
{
|
||||
/* A up threshold MUST always be bigger than 1 */
|
||||
LV_ASSERT(threshold > 1.0f);
|
||||
|
||||
lv_indev_gesture_recognizer_t * recognizer = &indev->recognizers[LV_INDEV_GESTURE_PINCH];
|
||||
|
||||
if(recognizer->config == NULL) {
|
||||
recognizer->config = lv_malloc_zeroed(sizeof(lv_indev_gesture_configuration_t));
|
||||
LV_ASSERT_MALLOC(recognizer->config);
|
||||
@@ -74,11 +82,13 @@ void lv_indev_set_pinch_up_threshold(lv_indev_gesture_recognizer_t * recognizer,
|
||||
recognizer->config->pinch_up_threshold = threshold;
|
||||
}
|
||||
|
||||
void lv_indev_set_pinch_down_threshold(lv_indev_gesture_recognizer_t * recognizer, float threshold)
|
||||
void lv_indev_set_pinch_down_threshold(lv_indev_t * indev, float threshold)
|
||||
{
|
||||
/* A down threshold MUST always be smaller than 1 */
|
||||
LV_ASSERT(threshold < 1.0f);
|
||||
|
||||
lv_indev_gesture_recognizer_t * recognizer = &indev->recognizers[LV_INDEV_GESTURE_PINCH];
|
||||
|
||||
if(recognizer->config == NULL) {
|
||||
recognizer->config = lv_malloc_zeroed(sizeof(lv_indev_gesture_configuration_t));
|
||||
LV_ASSERT_MALLOC(recognizer->config);
|
||||
@@ -88,6 +98,23 @@ void lv_indev_set_pinch_down_threshold(lv_indev_gesture_recognizer_t * recognize
|
||||
recognizer->config->pinch_down_threshold = threshold;
|
||||
}
|
||||
|
||||
void lv_indev_set_rotation_rad_threshold(lv_indev_t * indev, float threshold)
|
||||
{
|
||||
/* A rotation threshold MUST always be a positive number */
|
||||
LV_ASSERT(threshold > 0.0f);
|
||||
|
||||
lv_indev_gesture_recognizer_t * recognizer = &indev->recognizers[LV_INDEV_GESTURE_ROTATE];
|
||||
|
||||
if(recognizer->config == NULL) {
|
||||
|
||||
recognizer->config = lv_malloc_zeroed(sizeof(lv_indev_gesture_configuration_t));
|
||||
LV_ASSERT(recognizer->config != NULL);
|
||||
recognizer->config->rotation_angle_rad_threshold = LV_GESTURE_ROTATION_ANGLE_RAD_THRESHOLD;
|
||||
}
|
||||
|
||||
recognizer->config->rotation_angle_rad_threshold = threshold;
|
||||
}
|
||||
|
||||
void lv_indev_get_gesture_primary_point(lv_indev_gesture_recognizer_t * recognizer, lv_point_t * point)
|
||||
{
|
||||
if(recognizer->info->motions[0].finger != -1) {
|
||||
@@ -114,13 +141,48 @@ bool lv_indev_recognizer_is_active(lv_indev_gesture_recognizer_t * recognizer)
|
||||
float lv_event_get_pinch_scale(lv_event_t * gesture_event)
|
||||
{
|
||||
lv_indev_gesture_recognizer_t * recognizer;
|
||||
if((recognizer = lv_indev_get_gesture_recognizer(gesture_event)) == NULL) {
|
||||
|
||||
if((recognizer = lv_indev_get_gesture_recognizer(gesture_event, LV_INDEV_GESTURE_PINCH)) == NULL) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return recognizer->scale;
|
||||
}
|
||||
|
||||
float lv_event_get_rotation(lv_event_t * gesture_event)
|
||||
{
|
||||
lv_indev_gesture_recognizer_t * recognizer;
|
||||
|
||||
if((recognizer = lv_indev_get_gesture_recognizer(gesture_event, LV_INDEV_GESTURE_ROTATE)) == NULL) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return recognizer->rotation;
|
||||
}
|
||||
|
||||
float lv_event_get_two_fingers_swipe_distance(lv_event_t * gesture_event)
|
||||
{
|
||||
lv_indev_gesture_recognizer_t * recognizer;
|
||||
|
||||
if((recognizer = lv_indev_get_gesture_recognizer(gesture_event, LV_INDEV_GESTURE_TWO_FINGERS_SWIPE)) == NULL) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return recognizer->distance;
|
||||
}
|
||||
|
||||
lv_dir_t lv_event_get_two_fingers_swipe_dir(lv_event_t * gesture_event)
|
||||
{
|
||||
|
||||
lv_indev_gesture_recognizer_t * recognizer;
|
||||
|
||||
if((recognizer = lv_indev_get_gesture_recognizer(gesture_event, LV_INDEV_GESTURE_TWO_FINGERS_SWIPE)) == NULL) {
|
||||
return LV_DIR_NONE;
|
||||
}
|
||||
|
||||
return recognizer->two_fingers_swipe_dir;
|
||||
}
|
||||
|
||||
void lv_indev_get_gesture_center_point(lv_indev_gesture_recognizer_t * recognizer, lv_point_t * point)
|
||||
{
|
||||
if(lv_indev_recognizer_is_active(recognizer) == false) {
|
||||
@@ -133,18 +195,30 @@ void lv_indev_get_gesture_center_point(lv_indev_gesture_recognizer_t * recognize
|
||||
point->y = recognizer->info->center.y;
|
||||
}
|
||||
|
||||
lv_indev_gesture_state_t lv_event_get_gesture_state(lv_event_t * gesture_event)
|
||||
lv_indev_gesture_state_t lv_event_get_gesture_state(lv_event_t * gesture_event, lv_indev_gesture_type_t type)
|
||||
{
|
||||
lv_indev_gesture_recognizer_t * recognizer;
|
||||
if((recognizer = lv_indev_get_gesture_recognizer(gesture_event)) == NULL) {
|
||||
|
||||
if((recognizer = lv_indev_get_gesture_recognizer(gesture_event, type)) == NULL) {
|
||||
return LV_INDEV_GESTURE_STATE_NONE;
|
||||
}
|
||||
|
||||
return recognizer->state;
|
||||
}
|
||||
|
||||
lv_indev_gesture_type_t lv_event_get_gesture_type(lv_event_t * gesture_event)
|
||||
{
|
||||
lv_indev_t * indev = (lv_indev_t *) gesture_event->param;
|
||||
|
||||
void lv_indev_set_gesture_data(lv_indev_data_t * data, lv_indev_gesture_recognizer_t * recognizer)
|
||||
if(indev == NULL) {
|
||||
return LV_INDEV_GESTURE_NONE;
|
||||
}
|
||||
|
||||
return indev->cur_gesture;
|
||||
}
|
||||
|
||||
void lv_indev_set_gesture_data(lv_indev_data_t * data, lv_indev_gesture_recognizer_t * recognizer,
|
||||
lv_indev_gesture_type_t type)
|
||||
{
|
||||
bool is_active;
|
||||
lv_point_t cur_pnt;
|
||||
@@ -161,8 +235,8 @@ void lv_indev_set_gesture_data(lv_indev_data_t * data, lv_indev_gesture_recogniz
|
||||
data->point.x = cur_pnt.x;
|
||||
data->point.y = cur_pnt.y;
|
||||
|
||||
data->gesture_type = LV_INDEV_GESTURE_NONE;
|
||||
data->gesture_data = NULL;
|
||||
data->gesture_type[type] = LV_INDEV_GESTURE_NONE;
|
||||
data->gesture_data[type] = NULL;
|
||||
|
||||
/* The call below returns false if there are no active contact points */
|
||||
/* - OR when the gesture has ended, false is considered as a RELEASED state */
|
||||
@@ -180,13 +254,13 @@ void lv_indev_set_gesture_data(lv_indev_data_t * data, lv_indev_gesture_recogniz
|
||||
lv_indev_get_gesture_center_point(recognizer, &cur_pnt);
|
||||
data->point.x = cur_pnt.x;
|
||||
data->point.y = cur_pnt.y;
|
||||
data->gesture_type = LV_INDEV_GESTURE_PINCH;
|
||||
data->gesture_data = (void *) recognizer;
|
||||
data->gesture_type[type] = type;
|
||||
data->gesture_data[type] = (void *) recognizer;
|
||||
break;
|
||||
|
||||
case LV_INDEV_GESTURE_STATE_ENDED:
|
||||
data->gesture_type = LV_INDEV_GESTURE_PINCH;
|
||||
data->gesture_data = (void *) recognizer;
|
||||
data->gesture_type[type] = type;
|
||||
data->gesture_data[type] = (void *) recognizer;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -222,7 +296,7 @@ void lv_indev_gesture_detect_pinch(lv_indev_gesture_recognizer_t * recognizer, l
|
||||
process_touch_event(touch, r->info);
|
||||
touches++;
|
||||
|
||||
LV_LOG_TRACE("processed touch ev: %d finger id: %d state: %d x: %" LV_PRId32 " y: %" LV_PRId32 " finger_cnt: %d",
|
||||
LV_LOG_TRACE("processed touch ev: %d finger id: %d state: %d x: %" LV_PRId32 " y: %" LV_PRId32 " finger_cnt: %d",
|
||||
i, touch->id, touch->state, touch->point.x, touch->point.y, r->info->finger_cnt);
|
||||
}
|
||||
|
||||
@@ -230,8 +304,6 @@ void lv_indev_gesture_detect_pinch(lv_indev_gesture_recognizer_t * recognizer, l
|
||||
|
||||
if(r->info->finger_cnt == 2) {
|
||||
switch(r->state) {
|
||||
case LV_INDEV_GESTURE_STATE_ENDED:
|
||||
case LV_INDEV_GESTURE_STATE_CANCELED:
|
||||
case LV_INDEV_GESTURE_STATE_NONE:
|
||||
|
||||
/* 2 fingers down - potential pinch or swipe */
|
||||
@@ -239,38 +311,28 @@ void lv_indev_gesture_detect_pinch(lv_indev_gesture_recognizer_t * recognizer, l
|
||||
gesture_update_center_point(r->info, 2);
|
||||
r->state = LV_INDEV_GESTURE_STATE_ONGOING;
|
||||
break;
|
||||
|
||||
case LV_INDEV_GESTURE_STATE_ONGOING:
|
||||
case LV_INDEV_GESTURE_STATE_RECOGNIZED:
|
||||
|
||||
/* It's an ongoing pinch gesture - update the factors */
|
||||
gesture_calculate_factors(r->info, 2);
|
||||
|
||||
if(r->info->scale > LV_GESTURE_PINCH_MAX_INITIAL_SCALE &&
|
||||
r->state == LV_INDEV_GESTURE_STATE_ONGOING) {
|
||||
if(r->info->scale > LV_GESTURE_PINCH_MAX_INITIAL_SCALE) {
|
||||
r->state = LV_INDEV_GESTURE_STATE_CANCELED;
|
||||
break;
|
||||
}
|
||||
|
||||
LV_ASSERT_NULL(r->config);
|
||||
|
||||
if(r->info->scale > r->config->pinch_up_threshold ||
|
||||
r->info->scale < r->config->pinch_down_threshold) {
|
||||
|
||||
if(r->info->scale > 1.0f) {
|
||||
r->scale = r->info->scale - (r->config->pinch_up_threshold - 1.0f);
|
||||
|
||||
}
|
||||
else if(r->info->scale < 1.0f) {
|
||||
|
||||
r->scale = r->info->scale + (1.0f - r->config->pinch_down_threshold);
|
||||
}
|
||||
|
||||
r->type = LV_INDEV_GESTURE_PINCH;
|
||||
r->state = LV_INDEV_GESTURE_STATE_RECOGNIZED;
|
||||
}
|
||||
break;
|
||||
|
||||
case LV_INDEV_GESTURE_STATE_RECOGNIZED:
|
||||
/* It's an ongoing pinch gesture - update the factors */
|
||||
gesture_calculate_factors(r->info, 2);
|
||||
LV_ASSERT(r->info != NULL);
|
||||
r->scale = r->info->scale;
|
||||
r->type = LV_INDEV_GESTURE_PINCH;
|
||||
break;
|
||||
case LV_INDEV_GESTURE_STATE_ENDED:
|
||||
case LV_INDEV_GESTURE_STATE_CANCELED:
|
||||
reset_recognizer(r);
|
||||
break;
|
||||
default:
|
||||
LV_ASSERT_MSG(true, "invalid gesture recognizer state");
|
||||
}
|
||||
@@ -280,17 +342,13 @@ void lv_indev_gesture_detect_pinch(lv_indev_gesture_recognizer_t * recognizer, l
|
||||
case LV_INDEV_GESTURE_STATE_RECOGNIZED:
|
||||
/* Gesture has ended */
|
||||
r->state = LV_INDEV_GESTURE_STATE_ENDED;
|
||||
r->type = LV_INDEV_GESTURE_PINCH;
|
||||
break;
|
||||
|
||||
case LV_INDEV_GESTURE_STATE_ONGOING:
|
||||
/* User lifted a finger before reaching threshold */
|
||||
r->state = LV_INDEV_GESTURE_STATE_CANCELED;
|
||||
reset_recognizer(r);
|
||||
break;
|
||||
|
||||
case LV_INDEV_GESTURE_STATE_CANCELED:
|
||||
case LV_INDEV_GESTURE_STATE_ENDED:
|
||||
case LV_INDEV_GESTURE_STATE_CANCELED:
|
||||
reset_recognizer(r);
|
||||
break;
|
||||
|
||||
@@ -300,16 +358,296 @@ void lv_indev_gesture_detect_pinch(lv_indev_gesture_recognizer_t * recognizer, l
|
||||
}
|
||||
}
|
||||
|
||||
void lv_indev_gesture_detect_rotation(lv_indev_gesture_recognizer_t * recognizer, lv_indev_touch_data_t * touches,
|
||||
uint16_t touch_cnt)
|
||||
{
|
||||
lv_indev_touch_data_t * touch;
|
||||
lv_indev_gesture_recognizer_t * r = recognizer;
|
||||
uint8_t i;
|
||||
|
||||
if(r->info == NULL) {
|
||||
LV_LOG_TRACE("init gesture info");
|
||||
r->info = init_gesture_info();
|
||||
}
|
||||
|
||||
if(r->config == NULL) {
|
||||
LV_LOG_TRACE("init gesture configuration - set defaults");
|
||||
r->config = lv_malloc_zeroed(sizeof(lv_indev_gesture_configuration_t));
|
||||
|
||||
LV_ASSERT(r->config != NULL);
|
||||
}
|
||||
|
||||
/* Process collected touch events */
|
||||
for(i = 0; i < touch_cnt; i++) {
|
||||
|
||||
touch = touches;
|
||||
process_touch_event(touch, r->info);
|
||||
touches++;
|
||||
|
||||
LV_LOG_TRACE("processed touch ev: %d finger id: %d state: %d x: %" LV_PRId32 " y: %" LV_PRId32 " finger_cnt: %d",
|
||||
i, touch->id, touch->state, touch->point.x, touch->point.y, r->info->finger_cnt);
|
||||
}
|
||||
|
||||
LV_LOG_TRACE("Current finger count: %d state: %d", r->info->finger_cnt, r->state);
|
||||
|
||||
if(r->info->finger_cnt == 2) {
|
||||
switch(r->state) {
|
||||
case LV_INDEV_GESTURE_STATE_NONE:
|
||||
/* 2 fingers down - potential rotation or swipe */
|
||||
reset_recognizer(recognizer);
|
||||
gesture_update_center_point(r->info, 2);
|
||||
r->state = LV_INDEV_GESTURE_STATE_ONGOING;
|
||||
break;
|
||||
case LV_INDEV_GESTURE_STATE_ONGOING:
|
||||
/* Update the rotation from the inputs */
|
||||
gesture_calculate_factors(r->info, 2);
|
||||
if(fabs(r->info->rotation - r->info->p_rotation) > r->config->rotation_angle_rad_threshold) {
|
||||
|
||||
gesture_update_center_point(r->info, 2);
|
||||
r->state = LV_INDEV_GESTURE_STATE_RECOGNIZED;
|
||||
}
|
||||
break;
|
||||
case LV_INDEV_GESTURE_STATE_RECOGNIZED:
|
||||
/* It's a recognized rotation gesture - update the factors */
|
||||
gesture_calculate_factors(r->info, 2);
|
||||
r->type = LV_INDEV_GESTURE_ROTATE;
|
||||
r->rotation = r->info->rotation;
|
||||
break;
|
||||
case LV_INDEV_GESTURE_STATE_ENDED:
|
||||
case LV_INDEV_GESTURE_STATE_CANCELED:
|
||||
reset_recognizer(r);
|
||||
r->type = LV_INDEV_GESTURE_NONE;
|
||||
r->state = LV_INDEV_GESTURE_STATE_CANCELED;
|
||||
break;
|
||||
default:
|
||||
LV_ASSERT_MSG(true, "invalid gesture recognizer state");
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch(r->state) {
|
||||
case LV_INDEV_GESTURE_STATE_RECOGNIZED:
|
||||
/* Gesture has ended */
|
||||
r->type = LV_INDEV_GESTURE_ROTATE;
|
||||
r->state = LV_INDEV_GESTURE_STATE_ENDED;
|
||||
break;
|
||||
case LV_INDEV_GESTURE_STATE_ONGOING:
|
||||
/* User lifted a finger before reaching threshold */
|
||||
reset_recognizer(r);
|
||||
break;
|
||||
case LV_INDEV_GESTURE_STATE_CANCELED:
|
||||
case LV_INDEV_GESTURE_STATE_ENDED:
|
||||
reset_recognizer(r);
|
||||
break;
|
||||
default:
|
||||
LV_ASSERT_MSG(true, "invalid gesture recognizer state");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_indev_gesture_detect_two_fingers_swipe(lv_indev_gesture_recognizer_t * recognizer,
|
||||
lv_indev_touch_data_t * touches,
|
||||
uint16_t touch_cnt)
|
||||
{
|
||||
lv_indev_touch_data_t * touch;
|
||||
lv_indev_gesture_recognizer_t * r = recognizer;
|
||||
uint8_t i;
|
||||
float dist;
|
||||
|
||||
if(r->info == NULL) {
|
||||
LV_LOG_TRACE("init gesture info");
|
||||
r->info = init_gesture_info();
|
||||
}
|
||||
|
||||
if(r->config == NULL) {
|
||||
LV_LOG_TRACE("init gesture configuration - set defaults");
|
||||
r->config = lv_malloc_zeroed(sizeof(lv_indev_gesture_configuration_t));
|
||||
|
||||
LV_ASSERT(r->config != NULL);
|
||||
}
|
||||
|
||||
/* Process collected touch events */
|
||||
for(i = 0; i < touch_cnt; i++) {
|
||||
|
||||
touch = touches;
|
||||
process_touch_event(touch, r->info);
|
||||
touches++;
|
||||
|
||||
LV_LOG_TRACE("processed touch ev: %d finger id: %d state: %d x: %" LV_PRId32 " y: %" LV_PRId32 " finger_cnt: %d",
|
||||
i, touch->id, touch->state, touch->point.x, touch->point.y, r->info->finger_cnt);
|
||||
}
|
||||
|
||||
LV_LOG_TRACE("Current finger count: %d state: %d", r->info->finger_cnt, r->state);
|
||||
|
||||
if(r->info->finger_cnt == 2) {
|
||||
|
||||
switch(r->state) {
|
||||
case LV_INDEV_GESTURE_STATE_NONE:
|
||||
/* 2 fingers down - potential rotation or swipe */
|
||||
reset_recognizer(recognizer);
|
||||
gesture_update_center_point(r->info, 2);
|
||||
r->state = LV_INDEV_GESTURE_STATE_ONGOING;
|
||||
break;
|
||||
case LV_INDEV_GESTURE_STATE_ONGOING:
|
||||
/* The gesture is ongoing, now wait for the distance from the center
|
||||
to be higher than the threshold to pass it as recognized */
|
||||
gesture_calculate_factors(r->info, 2);
|
||||
dist = SQUARE_SUM(r->info->delta_x, r->info->delta_y);
|
||||
if(dist > SQUARE(lv_indev_active()->gesture_limit)) {
|
||||
r->state = LV_INDEV_GESTURE_STATE_RECOGNIZED;
|
||||
}
|
||||
break;
|
||||
case LV_INDEV_GESTURE_STATE_RECOGNIZED:
|
||||
/* The gesture is now recognized, and will stay recognized
|
||||
until a finger is lifted */
|
||||
gesture_calculate_factors(r->info, 2);
|
||||
r->distance = (float) sqrt(SQUARE_SUM(r->info->delta_x, r->info->delta_y));
|
||||
r->two_fingers_swipe_dir = calculate_swipe_dir(r);
|
||||
r->type = LV_INDEV_GESTURE_TWO_FINGERS_SWIPE;
|
||||
break;
|
||||
case LV_INDEV_GESTURE_STATE_ENDED:
|
||||
case LV_INDEV_GESTURE_STATE_CANCELED:
|
||||
reset_recognizer(r);
|
||||
break;
|
||||
default:
|
||||
LV_ASSERT_MSG(true, "invalid gesture recognizer state");
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
switch(r->state) {
|
||||
case LV_INDEV_GESTURE_STATE_RECOGNIZED:
|
||||
/* Gesture has ended */
|
||||
r->state = LV_INDEV_GESTURE_STATE_ENDED;
|
||||
r->type = LV_INDEV_GESTURE_TWO_FINGERS_SWIPE;
|
||||
break;
|
||||
case LV_INDEV_GESTURE_STATE_ONGOING:
|
||||
/* User lifted a finger before reaching threshold */
|
||||
reset_recognizer(r);
|
||||
r->state = LV_INDEV_GESTURE_STATE_ENDED;
|
||||
break;
|
||||
case LV_INDEV_GESTURE_STATE_CANCELED:
|
||||
case LV_INDEV_GESTURE_STATE_ENDED:
|
||||
reset_recognizer(r);
|
||||
r->state = LV_INDEV_GESTURE_STATE_NONE;
|
||||
break;
|
||||
default:
|
||||
LV_ASSERT_MSG(true, "invalid gesture recognizer state");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_indev_gesture_recognizers_update(lv_indev_t * indev, lv_indev_touch_data_t * touches, uint16_t touch_cnt)
|
||||
{
|
||||
lv_indev_gesture_type_t type;
|
||||
|
||||
/* First check if a recognizer state is RECOGNIZED or ENDED. *
|
||||
* In that case, call its recongizer function and reset the other*/
|
||||
type = get_first_recognized_or_ended_gesture(indev);
|
||||
if(type != LV_INDEV_GESTURE_NONE) {
|
||||
|
||||
for(int i = 0; i < LV_INDEV_GESTURE_CNT; i++) {
|
||||
|
||||
if(indev->recognizers[i].recog_fn != NULL) {
|
||||
|
||||
/* Update all recognizers to let them process input */
|
||||
indev->recognizers[i].recog_fn(&indev->recognizers[i], &touches[0], touch_cnt);
|
||||
|
||||
/* Then reset the recognizers which did not repport RECONIZED or ENDED */
|
||||
if(((lv_indev_gesture_type_t)i) != type) {
|
||||
|
||||
reset_recognizer(&indev->recognizers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
/* Otherwise call all recognizer functions, and stop as soon as one recognizer *
|
||||
* reports the state RECOGNIZED or ENDED */
|
||||
for(int i = 0; i < LV_INDEV_GESTURE_CNT; i++) {
|
||||
|
||||
if(indev->recognizers[i].recog_fn != NULL) {
|
||||
|
||||
indev->recognizers[i].recog_fn(&indev->recognizers[i], &touches[0], touch_cnt);
|
||||
|
||||
/* If the new state is RECOGNIZED or ENDED */
|
||||
if(indev->recognizers[i].state == LV_INDEV_GESTURE_STATE_RECOGNIZED ||
|
||||
indev->recognizers[i].state == LV_INDEV_GESTURE_STATE_ENDED) {
|
||||
|
||||
/* Reset the others registered recognizers */
|
||||
for(int j = 0; j < LV_INDEV_GESTURE_CNT; j++) {
|
||||
|
||||
if(j != i && indev->recognizers[j].recog_fn != NULL) {
|
||||
|
||||
reset_recognizer(&indev->recognizers[j]);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lv_indev_gesture_recognizers_set_data(lv_indev_t * indev, lv_indev_data_t * data)
|
||||
{
|
||||
lv_indev_gesture_type_t type;
|
||||
type = get_first_recognized_or_ended_gesture(indev);
|
||||
|
||||
/* If a gesture is RECOGNIZED or ENDED, set only its data */
|
||||
if(type != LV_INDEV_GESTURE_NONE) {
|
||||
lv_indev_set_gesture_data(data, &indev->recognizers[type], type);
|
||||
}
|
||||
else {
|
||||
/* Otherwise, set data from all initialized recognizer */
|
||||
for(int i = 0; i < LV_INDEV_GESTURE_CNT; i++) {
|
||||
|
||||
if(indev->recognizers[i].recog_fn != NULL) {
|
||||
|
||||
lv_indev_set_gesture_data(data, &indev->recognizers[i], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/********************
|
||||
* STATIC FUNCTIONS
|
||||
********************/
|
||||
|
||||
/**
|
||||
* Get the gesture recognizer associated to the event
|
||||
* @param gesture_event an LV_GESTURE_EVENT event
|
||||
* @return A pointer to the gesture recognizer that emitted the event
|
||||
* Caluclate the direction from the starting center of a two fingers swipe gesture
|
||||
* @param recognizer pointer to the recognizer handling the two fingers
|
||||
* swipe gesture
|
||||
* @return the direction of the swipe, from the starting center
|
||||
*/
|
||||
lv_indev_gesture_recognizer_t * lv_indev_get_gesture_recognizer(lv_event_t * gesture_event)
|
||||
static lv_dir_t calculate_swipe_dir(lv_indev_gesture_recognizer_t * recognizer)
|
||||
{
|
||||
|
||||
float abs_x = LV_ABS(recognizer->info->delta_x);
|
||||
float abs_y = LV_ABS(recognizer->info->delta_y);
|
||||
|
||||
if(abs_x > abs_y) {
|
||||
|
||||
return recognizer->info->delta_x > 0 ? LV_DIR_RIGHT : LV_DIR_LEFT;
|
||||
}
|
||||
else {
|
||||
|
||||
return recognizer->info->delta_y > 0 ? LV_DIR_BOTTOM : LV_DIR_TOP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the gesture recognizer associated to the event
|
||||
* @param gesture_event an LV_GESTURE_EVENT event
|
||||
* @param type the type of the recognizer we want to get
|
||||
* @return a pointer to the gesture recognizer that emitted the event
|
||||
*/
|
||||
lv_indev_gesture_recognizer_t * lv_indev_get_gesture_recognizer(lv_event_t * gesture_event,
|
||||
lv_indev_gesture_type_t type)
|
||||
{
|
||||
lv_indev_t * indev;
|
||||
|
||||
@@ -317,9 +655,9 @@ lv_indev_gesture_recognizer_t * lv_indev_get_gesture_recognizer(lv_event_t * ges
|
||||
|
||||
indev = (lv_indev_t *) gesture_event->param;
|
||||
|
||||
if(indev == NULL || indev->gesture_data == NULL) return NULL;
|
||||
if(indev == NULL || indev->gesture_data[type] == NULL) return NULL;
|
||||
|
||||
return (lv_indev_gesture_recognizer_t *) indev->gesture_data;
|
||||
return (lv_indev_gesture_recognizer_t *) indev->gesture_data[type];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -331,22 +669,36 @@ static void reset_recognizer(lv_indev_gesture_recognizer_t * recognizer)
|
||||
uint8_t finger_cnt;
|
||||
lv_indev_gesture_t * info;
|
||||
lv_indev_gesture_configuration_t * conf;
|
||||
lv_recognizer_func_t recog_fn;
|
||||
|
||||
if(recognizer == NULL) return;
|
||||
|
||||
finger_cnt = recognizer->info->finger_cnt;
|
||||
info = recognizer->info;
|
||||
conf = recognizer->config;
|
||||
recog_fn = recognizer->recog_fn;
|
||||
|
||||
/* Set everything to zero but preserve the motion descriptors,
|
||||
* which are located at the start of the lv_indev_gesture_t struct */
|
||||
lv_memzero((uint8_t *)info + sizeof(info->motions), sizeof(lv_indev_gesture_t) - sizeof(info->motions));
|
||||
lv_memzero(recognizer, sizeof(lv_indev_gesture_recognizer_t));
|
||||
|
||||
info->finger_cnt = finger_cnt;
|
||||
recognizer->scale = info->scale = 1;
|
||||
recognizer->info = info;
|
||||
recognizer->config = conf;
|
||||
recognizer->recog_fn = recog_fn;
|
||||
|
||||
recognizer->scale = 1;
|
||||
recognizer->rotation = 0.0;
|
||||
|
||||
recognizer->info->rotation = 0.0;
|
||||
recognizer->info->p_rotation = 0.0;
|
||||
recognizer->info->scale = 1.0;
|
||||
recognizer->info->delta_x = 0.0;
|
||||
recognizer->info->delta_y = 0.0;
|
||||
recognizer->info->finger_cnt = finger_cnt;
|
||||
|
||||
recognizer->state = LV_INDEV_GESTURE_STATE_NONE;
|
||||
recognizer->type = LV_INDEV_GESTURE_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -362,6 +714,7 @@ static lv_indev_gesture_t * init_gesture_info(void)
|
||||
LV_ASSERT_MALLOC(info);
|
||||
|
||||
info->scale = 1;
|
||||
info->rotation = 0.0;
|
||||
|
||||
for(i = 0; i < LV_GESTURE_MAX_POINTS; i++) {
|
||||
info->motions[i].finger = -1;
|
||||
@@ -587,15 +940,33 @@ static void gesture_calculate_factors(lv_indev_gesture_t * gesture, int touch_po
|
||||
d_x = (motion->point.x - center_x);
|
||||
d_y = (motion->point.y - center_y);
|
||||
a += g->scale_factors_x[i] * d_x + g->scale_factors_y[i] * d_y;
|
||||
b += g->scale_factors_x[i] * d_y + g->scale_factors_y[i] * d_x;
|
||||
b += g->scale_factors_x[i] * d_y - g->scale_factors_y[i] * d_x;
|
||||
}
|
||||
}
|
||||
|
||||
g->rotation = g->p_rotation + atan2f(b, a);
|
||||
g->scale = g->p_scale * sqrtf((a * a) + (b * b));
|
||||
|
||||
g->center.x = (int32_t)center_x;
|
||||
g->center.y = (int32_t)center_y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of the first gesture which reports either a LV_INDEV_GESTURE_STATE_RECOGNIZED
|
||||
* or LV_INDEV_GESTURE_STATE_ENDED state
|
||||
* @param indev pointer to the indev device from which we want to check the gestures states
|
||||
* @return the type of the gesture having the state LV_INDEV_GESTURE_STATE_RECOGNIZED or
|
||||
* LV_INDEV_GESTURE_STATE_ENDED, if found
|
||||
* LV_INDEV_GESTURE_NONE otherwise
|
||||
*/
|
||||
static lv_indev_gesture_type_t get_first_recognized_or_ended_gesture(lv_indev_t * indev)
|
||||
{
|
||||
|
||||
for(int i = 0; i < LV_INDEV_GESTURE_CNT; i++) {
|
||||
if(indev->recognizers[i].state == LV_INDEV_GESTURE_STATE_RECOGNIZED ||
|
||||
indev->recognizers[i].state == LV_INDEV_GESTURE_STATE_ENDED)
|
||||
return (lv_indev_gesture_type_t) i;
|
||||
}
|
||||
|
||||
return LV_INDEV_GESTURE_NONE;
|
||||
}
|
||||
|
||||
|
||||
#endif /* LV_USE_GESTURE_RECOGNITION */
|
||||
|
||||
@@ -38,9 +38,14 @@ extern "C" {
|
||||
struct lv_indev_gesture;
|
||||
struct lv_indev_gesture_configuration;
|
||||
|
||||
typedef struct lv_indev_gesture_recognizer lv_indev_gesture_recognizer_t;
|
||||
typedef struct lv_indev_touch_data lv_indev_touch_data_t;
|
||||
|
||||
typedef struct lv_indev_gesture lv_indev_gesture_t;
|
||||
typedef struct lv_indev_gesture_configuration lv_indev_gesture_configuration_t;
|
||||
|
||||
typedef void (*lv_recognizer_func_t)(lv_indev_gesture_recognizer_t *, lv_indev_touch_data_t *, uint16_t);
|
||||
|
||||
/* The states of a gesture recognizer */
|
||||
typedef enum {
|
||||
LV_INDEV_GESTURE_STATE_NONE = 0, /* Beginning & end */
|
||||
@@ -52,15 +57,15 @@ typedef enum {
|
||||
|
||||
/* Data structures for touch events - used to repsensent a libinput event */
|
||||
/* Emitted by devices capable of tracking identifiable contacts (type B) */
|
||||
typedef struct {
|
||||
struct lv_indev_touch_data {
|
||||
lv_point_t point; /* Coordinates of the touch */
|
||||
lv_indev_state_t state; /* The state i.e PRESSED or RELEASED */
|
||||
uint8_t id; /* Identification/slot of the contact point */
|
||||
uint32_t timestamp; /* Timestamp in milliseconds */
|
||||
} lv_indev_touch_data_t;
|
||||
};
|
||||
|
||||
/* Gesture recognizer */
|
||||
typedef struct {
|
||||
struct lv_indev_gesture_recognizer {
|
||||
lv_indev_gesture_type_t type; /* The detected gesture type */
|
||||
lv_indev_gesture_state_t state; /* The gesture state ongoing, recognized */
|
||||
lv_indev_gesture_t * info; /* Information on the motion of each touch point */
|
||||
@@ -68,10 +73,12 @@ typedef struct {
|
||||
float rotation; /* Relevant for rotation */
|
||||
float distance; /* Relevant for swipes */
|
||||
float speed;
|
||||
lv_dir_t two_fingers_swipe_dir; /* Relevant for swipes */
|
||||
|
||||
lv_indev_gesture_configuration_t * config;
|
||||
|
||||
} lv_indev_gesture_recognizer_t;
|
||||
lv_indev_gesture_configuration_t * config; /* The recognizer config, containing the gestures
|
||||
thresholds */
|
||||
lv_recognizer_func_t recog_fn; /* The recognizer function that this recongnizer must execute */
|
||||
};
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
@@ -81,7 +88,8 @@ typedef struct {
|
||||
/* PINCH Gesture */
|
||||
|
||||
/**
|
||||
* Detects a pinch gesture
|
||||
* Pinch gesture recognizer function
|
||||
* Will update the recognizer data
|
||||
* @param recognizer pointer to a gesture recognizer
|
||||
* @param touches pointer to the first element of the collected touch events
|
||||
* @param touch_cnt length of passed touch event array.
|
||||
@@ -89,39 +97,86 @@ typedef struct {
|
||||
void lv_indev_gesture_detect_pinch(lv_indev_gesture_recognizer_t * recognizer, lv_indev_touch_data_t * touches,
|
||||
uint16_t touch_cnt);
|
||||
|
||||
/**
|
||||
* Rotation gesture recognizer function
|
||||
* Will update the recognizer data
|
||||
* @param recognizer pointer to a gesture recognizer
|
||||
* @param touches pointer to the first element of the collected touch events
|
||||
* @param touch_cnt length of passed touch event array.
|
||||
*/
|
||||
void lv_indev_gesture_detect_rotation(lv_indev_gesture_recognizer_t * recognizer, lv_indev_touch_data_t * touches,
|
||||
uint16_t touch_cnt);
|
||||
|
||||
/**
|
||||
* Two finger swipe gesture recognizer function
|
||||
* Will update the recognizer data
|
||||
* @param recognizer pointer to a gesture recognizer
|
||||
* @param touches pointer to the first element of the collected touch events
|
||||
* @param touch_cnt length of passed touch event array.
|
||||
*/
|
||||
void lv_indev_gesture_detect_two_fingers_swipe(lv_indev_gesture_recognizer_t * recognizer,
|
||||
lv_indev_touch_data_t * touches,
|
||||
uint16_t touch_cnt);
|
||||
|
||||
/**
|
||||
* Set the threshold for the pinch gesture scale up, when the scale factor of gesture
|
||||
* reaches the threshold events get sent
|
||||
* @param recognizer pointer to a gesture recognizer
|
||||
* @param touches pointer to the first element of the collected touch events
|
||||
* @param touch_cnt length of passed touch event array.
|
||||
* @param indev pointer to the indev device containing the pinch recognizer
|
||||
* @param threshold threshold for a pinch up gesture to be recognized
|
||||
*/
|
||||
void lv_indev_set_pinch_up_threshold(lv_indev_gesture_recognizer_t * recognizer, float threshold);
|
||||
void lv_indev_set_pinch_up_threshold(lv_indev_t * indev, float threshold);
|
||||
|
||||
/**
|
||||
* Set the threshold for the pinch gesture scale down, when the scale factor of gesture
|
||||
* reaches the threshold events get sent
|
||||
* @param recognizer pointer to a gesture recognizer
|
||||
* @param touches pointer to the first element of the collected touch events
|
||||
* @param touch_cnt length of passed touch event array.
|
||||
* @param indev pointer to the indev device containing the pinch recognizer
|
||||
* @param threshold threshold for a pinch down gesture to be recognized
|
||||
*/
|
||||
void lv_indev_set_pinch_down_threshold(lv_indev_gesture_recognizer_t * recognizer, float threshold);
|
||||
void lv_indev_set_pinch_down_threshold(lv_indev_t * indev, float threshold);
|
||||
|
||||
/**
|
||||
* Set the rotation threshold in radian for the rotation gesture
|
||||
* @param indev pointer to the indev device containing the rotation recognizer
|
||||
* @param threshold threshold in radian for a rotation gesture to be recognized
|
||||
*/
|
||||
void lv_indev_set_rotation_rad_threshold(lv_indev_t * indev, float threshold);
|
||||
|
||||
/**
|
||||
* Obtains the current scale of a pinch gesture
|
||||
* @param gesture_event pointer to a gesture recognizer event
|
||||
* @param gesture_event pointer to a gesture event
|
||||
* @return the scale of the current gesture
|
||||
*/
|
||||
float lv_event_get_pinch_scale(lv_event_t * gesture_event);
|
||||
|
||||
/**
|
||||
* Obtains the current angle in radian of a rotation gesture
|
||||
* @param gesture_event pointer to a gesture event
|
||||
* @return the rotation angle in radian of the current gesture
|
||||
*/
|
||||
float lv_event_get_rotation(lv_event_t * gesture_event);
|
||||
|
||||
/**
|
||||
* Obtains the current distance in pixels of a two fingers swipe gesture, from the starting center
|
||||
* @param gesture_event pointer to a gesture event
|
||||
* @return the distance from the center, in pixels, of the current gesture
|
||||
*/
|
||||
float lv_event_get_two_fingers_swipe_distance(lv_event_t * gesture_event);
|
||||
|
||||
/**
|
||||
* Obtains the current direction from the center of a two finger swipe
|
||||
* @param gesture_event pointer to a gesture event
|
||||
* @return the rotation angle in radian of the current gesture
|
||||
*/
|
||||
lv_dir_t lv_event_get_two_fingers_swipe_dir(lv_event_t * gesture_event);
|
||||
|
||||
/**
|
||||
* Sets the state of the recognizer to a indev data structure,
|
||||
* it is usually called from the indev read callback
|
||||
* @param data the indev data
|
||||
* @param recognizer pointer to a gesture recognizer
|
||||
*/
|
||||
void lv_indev_set_gesture_data(lv_indev_data_t * data, lv_indev_gesture_recognizer_t * recognizer);
|
||||
void lv_indev_set_gesture_data(lv_indev_data_t * data, lv_indev_gesture_recognizer_t * recognizer,
|
||||
lv_indev_gesture_type_t type);
|
||||
|
||||
/**
|
||||
* Obtains the center point of a gesture
|
||||
@@ -135,7 +190,14 @@ void lv_indev_get_gesture_center_point(lv_indev_gesture_recognizer_t * recognize
|
||||
* @param gesture_event pointer to a gesture recognizer event
|
||||
* @return current state of the gesture recognizer
|
||||
*/
|
||||
lv_indev_gesture_state_t lv_event_get_gesture_state(lv_event_t * gesture_event);
|
||||
lv_indev_gesture_state_t lv_event_get_gesture_state(lv_event_t * gesture_event, lv_indev_gesture_type_t type);
|
||||
|
||||
/**
|
||||
* Obtains the current event type of the gesture recognizer attached to an event
|
||||
* @param gesture_event pointer to a gesture recognizer event
|
||||
* @return current event type of the gesture recognizer
|
||||
*/
|
||||
lv_indev_gesture_type_t lv_event_get_gesture_type(lv_event_t * gesture_event);
|
||||
|
||||
/**
|
||||
* Obtains the coordinates of the current primary point
|
||||
@@ -151,6 +213,23 @@ void lv_indev_get_gesture_primary_point(lv_indev_gesture_recognizer_t * recogniz
|
||||
*/
|
||||
bool lv_indev_recognizer_is_active(lv_indev_gesture_recognizer_t * recognizer);
|
||||
|
||||
/**
|
||||
* Update the recognizers. It execute the recognizers functions and checks for
|
||||
* LV_GESTURE_STATE_RECOGNIZED or LV_GESTURE_STATE_ENDED gestures.
|
||||
* To be called in the indev read_cb.
|
||||
* @param indev pointer to the indev containing from which the reconizer need an update
|
||||
* @param touches indev touch data array, containing the last touch data from indev
|
||||
* since the last recognizers update
|
||||
* @param touch_cnt number of indev touch data in touches
|
||||
*/
|
||||
void lv_indev_gesture_recognizers_update(lv_indev_t * indev, lv_indev_touch_data_t * touches, uint16_t touch_cnt);
|
||||
|
||||
/**
|
||||
* Set the lv_indev_data_t struct from the recognizer data.
|
||||
* To be called in the indev read_cb.
|
||||
*/
|
||||
void lv_indev_gesture_recognizers_set_data(lv_indev_t * indev, lv_indev_data_t * data);
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
|
||||
@@ -69,10 +69,14 @@ struct lv_indev_gesture {
|
||||
|
||||
};
|
||||
|
||||
/* Recognizer configuration. It stores the thresholds needed to detect the gestures and
|
||||
* consider them as recognized. Once recognized, indev start sending LV_GESTURE event
|
||||
*/
|
||||
struct lv_indev_gesture_configuration {
|
||||
|
||||
float pinch_up_threshold; /* When the gesture reaches the threshold - start sending events */
|
||||
float pinch_down_threshold; /* When the gesture reaches the threshold - start sending events */
|
||||
float pinch_up_threshold; /* Threshold for the pinch up gesture to be recognized - in pixels */
|
||||
float pinch_down_threshold; /* Threshold for the pinch down gesture to be recognized - in pixels */
|
||||
float rotation_angle_rad_threshold; /* Threshold for the rotation gesture to be recognized - in radians */
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ extern "C" {
|
||||
#include "lv_indev.h"
|
||||
#include "../misc/lv_anim.h"
|
||||
#include "lv_indev_scroll.h"
|
||||
#include "lv_indev_gesture.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -117,8 +118,12 @@ struct _lv_indev_t {
|
||||
lv_event_list_t event_list;
|
||||
lv_anim_t * scroll_throw_anim;
|
||||
|
||||
lv_indev_gesture_type_t gesture_type;
|
||||
void * gesture_data;
|
||||
#if LV_USE_GESTURE_RECOGNITION
|
||||
lv_indev_gesture_recognizer_t recognizers[LV_INDEV_GESTURE_CNT];
|
||||
lv_indev_gesture_type_t cur_gesture;
|
||||
void * gesture_data[LV_INDEV_GESTURE_CNT];
|
||||
lv_indev_gesture_type_t gesture_type[LV_INDEV_GESTURE_CNT];
|
||||
#endif
|
||||
};
|
||||
|
||||
/**********************
|
||||
@@ -133,6 +138,7 @@ struct _lv_indev_t {
|
||||
*/
|
||||
lv_obj_t * lv_indev_find_scroll_obj(lv_indev_t * indev);
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
Reference in New Issue
Block a user