mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-21 22:52:46 +08:00
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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+63
-14
@@ -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;
|
||||
|
||||
|
||||
+426
-55
File diff suppressed because it is too large
Load Diff
@@ -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