2017-10-09 15:21:26 +02:00
|
|
|
/**
|
2019-04-08 14:40:41 +02:00
|
|
|
* @file lv_indev.c
|
2018-06-19 09:49:58 +02:00
|
|
|
*
|
2017-10-09 15:21:26 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*********************
|
|
|
|
* INCLUDES
|
|
|
|
********************/
|
2017-11-26 23:57:39 +01:00
|
|
|
#include "lv_indev.h"
|
2019-02-12 15:38:13 +01:00
|
|
|
#include "lv_disp.h"
|
|
|
|
#include "lv_obj.h"
|
2017-10-09 15:21:26 +02:00
|
|
|
|
|
|
|
#include "../lv_hal/lv_hal_tick.h"
|
2017-11-30 11:35:33 +01:00
|
|
|
#include "../lv_core/lv_group.h"
|
2018-02-24 15:36:06 +01:00
|
|
|
#include "../lv_core/lv_refr.h"
|
2017-11-23 20:42:14 +01:00
|
|
|
#include "../lv_misc/lv_task.h"
|
2017-11-24 17:48:47 +01:00
|
|
|
#include "../lv_misc/lv_math.h"
|
2017-10-09 15:21:26 +02:00
|
|
|
|
|
|
|
/*********************
|
|
|
|
* DEFINES
|
|
|
|
*********************/
|
|
|
|
|
2019-04-02 12:15:35 +02:00
|
|
|
#if LV_INDEV_DEF_DRAG_THROW <= 0
|
2020-02-26 19:48:27 +01:00
|
|
|
#warning "LV_INDEV_DRAG_THROW must be greater than 0"
|
2019-02-10 06:53:11 -05:00
|
|
|
#endif
|
|
|
|
|
2017-10-09 15:21:26 +02:00
|
|
|
/**********************
|
|
|
|
* TYPEDEFS
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
/**********************
|
|
|
|
* STATIC PROTOTYPES
|
|
|
|
**********************/
|
2018-01-10 09:42:52 +01:00
|
|
|
|
2018-02-24 13:17:39 +01:00
|
|
|
static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data);
|
|
|
|
static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data);
|
2018-09-24 22:59:48 +02:00
|
|
|
static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data);
|
2018-02-24 13:17:39 +01:00
|
|
|
static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data);
|
|
|
|
static void indev_proc_press(lv_indev_proc_t * proc);
|
|
|
|
static void indev_proc_release(lv_indev_proc_t * proc);
|
2018-02-06 11:42:50 -08:00
|
|
|
static void indev_proc_reset_query_handler(lv_indev_t * indev);
|
2020-02-02 16:08:39 +01:00
|
|
|
static void indev_click_focus(lv_indev_proc_t * proc);
|
2019-09-17 16:07:30 +02:00
|
|
|
static void indev_drag(lv_indev_proc_t * proc);
|
2019-02-26 16:07:40 +01:00
|
|
|
static void indev_drag_throw(lv_indev_proc_t * proc);
|
2019-09-17 14:38:55 +02:00
|
|
|
static lv_obj_t * get_dragged_obj(lv_obj_t * obj);
|
2020-01-16 19:24:08 -05:00
|
|
|
static void indev_gesture(lv_indev_proc_t * proc);
|
2019-06-06 06:05:40 +02:00
|
|
|
static bool indev_reset_check(lv_indev_proc_t * proc);
|
2017-10-09 15:21:26 +02:00
|
|
|
|
|
|
|
/**********************
|
|
|
|
* STATIC VARIABLES
|
|
|
|
**********************/
|
2018-06-19 09:49:58 +02:00
|
|
|
static lv_indev_t * indev_act;
|
2019-05-20 09:42:31 -07:00
|
|
|
static lv_obj_t * indev_obj_act = NULL;
|
2017-10-09 15:21:26 +02:00
|
|
|
|
|
|
|
/**********************
|
|
|
|
* MACROS
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
/**********************
|
|
|
|
* GLOBAL FUNCTIONS
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize the display input device subsystem
|
|
|
|
*/
|
2017-10-10 16:17:23 +02:00
|
|
|
void lv_indev_init(void)
|
2017-10-09 15:21:26 +02:00
|
|
|
{
|
2020-01-28 22:15:45 +01:00
|
|
|
lv_indev_reset(NULL, NULL); /*Reset all input devices*/
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
|
2019-04-02 12:15:35 +02:00
|
|
|
/**
|
|
|
|
* Called periodically to read the input devices
|
|
|
|
* @param param pointer to and input device to read
|
|
|
|
*/
|
2019-04-27 11:32:13 +02:00
|
|
|
void lv_indev_read_task(lv_task_t * task)
|
2019-04-02 12:15:35 +02:00
|
|
|
{
|
|
|
|
LV_LOG_TRACE("indev read task started");
|
|
|
|
|
|
|
|
lv_indev_data_t data;
|
|
|
|
|
2019-04-27 11:32:13 +02:00
|
|
|
indev_act = task->user_data;
|
2019-04-02 12:15:35 +02:00
|
|
|
|
|
|
|
/*Read and process all indevs*/
|
2019-04-04 07:15:40 +02:00
|
|
|
if(indev_act->driver.disp == NULL) return; /*Not assigned to any displays*/
|
2017-10-09 15:21:26 +02:00
|
|
|
|
2019-04-02 12:15:35 +02:00
|
|
|
/*Handle reset query before processing the point*/
|
|
|
|
indev_proc_reset_query_handler(indev_act);
|
|
|
|
|
|
|
|
if(indev_act->proc.disabled) return;
|
|
|
|
bool more_to_read;
|
|
|
|
do {
|
|
|
|
/*Read the data*/
|
|
|
|
more_to_read = lv_indev_read(indev_act, &data);
|
|
|
|
|
|
|
|
/*The active object might deleted even in the read function*/
|
|
|
|
indev_proc_reset_query_handler(indev_act);
|
2019-05-21 15:49:50 +02:00
|
|
|
indev_obj_act = NULL;
|
2019-04-02 12:15:35 +02:00
|
|
|
|
|
|
|
indev_act->proc.state = data.state;
|
|
|
|
|
2019-05-25 16:53:56 +02:00
|
|
|
/*Save the last activity time*/
|
2019-04-02 12:15:35 +02:00
|
|
|
if(indev_act->proc.state == LV_INDEV_STATE_PR) {
|
2019-04-04 07:07:17 +02:00
|
|
|
indev_act->driver.disp->last_activity_time = lv_tick_get();
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else if(indev_act->driver.type == LV_INDEV_TYPE_ENCODER && data.enc_diff) {
|
2019-05-25 16:53:56 +02:00
|
|
|
indev_act->driver.disp->last_activity_time = lv_tick_get();
|
2019-04-02 12:15:35 +02:00
|
|
|
}
|
2019-05-25 16:53:56 +02:00
|
|
|
|
2019-04-02 12:15:35 +02:00
|
|
|
if(indev_act->driver.type == LV_INDEV_TYPE_POINTER) {
|
|
|
|
indev_pointer_proc(indev_act, &data);
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else if(indev_act->driver.type == LV_INDEV_TYPE_KEYPAD) {
|
2019-04-02 12:15:35 +02:00
|
|
|
indev_keypad_proc(indev_act, &data);
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else if(indev_act->driver.type == LV_INDEV_TYPE_ENCODER) {
|
2019-04-02 12:15:35 +02:00
|
|
|
indev_encoder_proc(indev_act, &data);
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else if(indev_act->driver.type == LV_INDEV_TYPE_BUTTON) {
|
2019-04-02 12:15:35 +02:00
|
|
|
indev_button_proc(indev_act, &data);
|
|
|
|
}
|
|
|
|
/*Handle reset query if it happened in during processing*/
|
|
|
|
indev_proc_reset_query_handler(indev_act);
|
|
|
|
} while(more_to_read);
|
|
|
|
|
|
|
|
/*End of indev processing, so no act indev*/
|
2019-06-06 06:05:40 +02:00
|
|
|
indev_act = NULL;
|
2019-05-21 15:49:50 +02:00
|
|
|
indev_obj_act = NULL;
|
2019-04-02 12:15:35 +02:00
|
|
|
|
|
|
|
LV_LOG_TRACE("indev read task finished");
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the currently processed input device. Can be used in action functions too.
|
2019-04-04 07:15:40 +02:00
|
|
|
* @return pointer to the currently processed input device or NULL if no input device processing
|
|
|
|
* right now
|
2017-10-09 15:21:26 +02:00
|
|
|
*/
|
|
|
|
lv_indev_t * lv_indev_get_act(void)
|
|
|
|
{
|
|
|
|
return indev_act;
|
|
|
|
}
|
|
|
|
|
2018-07-13 00:37:28 +02:00
|
|
|
/**
|
|
|
|
* Get the type of an input device
|
|
|
|
* @param indev pointer to an input device
|
|
|
|
* @return the type of the input device from `lv_hal_indev_type_t` (`LV_INDEV_TYPE_...`)
|
|
|
|
*/
|
2019-03-29 16:10:18 +01:00
|
|
|
lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev)
|
2018-07-13 00:37:28 +02:00
|
|
|
{
|
2018-10-05 17:22:49 +02:00
|
|
|
if(indev == NULL) return LV_INDEV_TYPE_NONE;
|
2018-07-13 00:37:28 +02:00
|
|
|
|
2018-10-05 17:22:49 +02:00
|
|
|
return indev->driver.type;
|
2018-07-13 00:37:28 +02:00
|
|
|
}
|
2020-01-28 22:15:45 +01:00
|
|
|
|
2017-10-09 15:21:26 +02:00
|
|
|
/**
|
|
|
|
* Reset one or all input devices
|
2017-12-17 01:54:09 +01:00
|
|
|
* @param indev pointer to an input device to reset or NULL to reset all of them
|
2020-01-28 22:15:45 +01:00
|
|
|
* @param obj pointer to an object which triggers the reset.
|
2017-10-09 15:21:26 +02:00
|
|
|
*/
|
2020-01-28 22:15:45 +01:00
|
|
|
void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj)
|
2017-10-09 15:21:26 +02:00
|
|
|
{
|
2020-01-28 22:15:45 +01:00
|
|
|
if(indev) {
|
2019-04-04 07:15:40 +02:00
|
|
|
indev->proc.reset_query = 1;
|
2020-04-09 12:25:50 +02:00
|
|
|
if(indev_act == indev) indev_obj_act = NULL;
|
2020-01-28 22:15:45 +01:00
|
|
|
if(obj == NULL || indev->proc.types.pointer.last_pressed == obj) {
|
|
|
|
indev->proc.types.pointer.last_pressed = NULL;
|
|
|
|
}
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else {
|
2019-04-04 07:07:17 +02:00
|
|
|
lv_indev_t * i = lv_indev_get_next(NULL);
|
2017-10-09 15:21:26 +02:00
|
|
|
while(i) {
|
2017-11-29 13:08:03 +01:00
|
|
|
i->proc.reset_query = 1;
|
2020-04-09 12:25:50 +02:00
|
|
|
if(indev_act == i) indev_obj_act = NULL;
|
2020-01-28 22:15:45 +01:00
|
|
|
if(obj == NULL || i->proc.types.pointer.last_pressed == obj) {
|
|
|
|
i->proc.types.pointer.last_pressed = NULL;
|
|
|
|
}
|
2019-04-04 16:44:16 +02:00
|
|
|
i = lv_indev_get_next(i);
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reset the long press state of an input device
|
2017-12-17 01:54:09 +01:00
|
|
|
* @param indev pointer to an input device
|
2017-10-09 15:21:26 +02:00
|
|
|
*/
|
2019-03-13 22:08:20 +01:00
|
|
|
void lv_indev_reset_long_press(lv_indev_t * indev)
|
2017-10-09 15:21:26 +02:00
|
|
|
{
|
2019-04-04 07:15:40 +02:00
|
|
|
indev->proc.long_pr_sent = 0;
|
2017-12-17 01:54:09 +01:00
|
|
|
indev->proc.longpr_rep_timestamp = lv_tick_get();
|
2019-04-04 07:15:40 +02:00
|
|
|
indev->proc.pr_timestamp = lv_tick_get();
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
|
2017-10-10 16:17:23 +02:00
|
|
|
/**
|
2019-03-13 22:08:20 +01:00
|
|
|
* Enable or disable an input devices
|
|
|
|
* @param indev pointer to an input device
|
|
|
|
* @param en true: enable; false: disable
|
2017-10-10 16:17:23 +02:00
|
|
|
*/
|
2019-03-13 22:08:20 +01:00
|
|
|
void lv_indev_enable(lv_indev_t * indev, bool en)
|
2017-10-10 16:17:23 +02:00
|
|
|
{
|
2019-03-13 22:08:20 +01:00
|
|
|
if(!indev) return;
|
2017-10-10 16:17:23 +02:00
|
|
|
|
2019-08-26 09:05:30 +02:00
|
|
|
indev->proc.disabled = en ? 0 : 1;
|
2017-10-10 16:17:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-02-24 13:17:39 +01:00
|
|
|
* Set a cursor for a pointer input device (for LV_INPUT_TYPE_POINTER and LV_INPUT_TYPE_BUTTON)
|
|
|
|
* @param indev pointer to an input device
|
2017-10-10 16:17:23 +02:00
|
|
|
* @param cur_obj pointer to an object to be used as cursor
|
|
|
|
*/
|
2018-06-19 09:49:58 +02:00
|
|
|
void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj)
|
2017-10-10 16:17:23 +02:00
|
|
|
{
|
2018-12-18 07:33:55 +01:00
|
|
|
if(indev->driver.type != LV_INDEV_TYPE_POINTER) return;
|
2017-11-19 19:28:45 +01:00
|
|
|
|
2019-03-07 00:05:16 +01:00
|
|
|
indev->cursor = cur_obj;
|
|
|
|
lv_obj_set_parent(indev->cursor, lv_disp_get_layer_sys(indev->driver.disp));
|
2019-06-06 06:05:40 +02:00
|
|
|
lv_obj_set_pos(indev->cursor, indev->proc.types.pointer.act_point.x, indev->proc.types.pointer.act_point.y);
|
2017-10-10 16:17:23 +02:00
|
|
|
}
|
|
|
|
|
2019-03-07 00:05:16 +01:00
|
|
|
#if LV_USE_GROUP
|
2017-11-19 19:28:45 +01:00
|
|
|
/**
|
2018-02-24 13:17:39 +01:00
|
|
|
* Set a destination group for a keypad input device (for LV_INDEV_TYPE_KEYPAD)
|
|
|
|
* @param indev pointer to an input device
|
2017-11-19 19:28:45 +01:00
|
|
|
* @param group point to a group
|
|
|
|
*/
|
2018-06-19 09:49:58 +02:00
|
|
|
void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group)
|
2017-11-19 19:28:45 +01:00
|
|
|
{
|
2019-02-28 13:05:47 +01:00
|
|
|
if(indev->driver.type == LV_INDEV_TYPE_KEYPAD || indev->driver.type == LV_INDEV_TYPE_ENCODER) {
|
2019-03-07 00:05:16 +01:00
|
|
|
indev->group = group;
|
2019-02-28 13:05:47 +01:00
|
|
|
}
|
2017-11-19 19:28:45 +01:00
|
|
|
}
|
2017-11-21 14:52:23 +01:00
|
|
|
#endif
|
2017-10-10 16:17:23 +02:00
|
|
|
|
2017-10-09 15:21:26 +02:00
|
|
|
/**
|
2018-02-24 13:17:39 +01:00
|
|
|
* Set the an array of points for LV_INDEV_TYPE_BUTTON.
|
|
|
|
* These points will be assigned to the buttons to press a specific point on the screen
|
|
|
|
* @param indev pointer to an input device
|
|
|
|
* @param group point to a group
|
|
|
|
*/
|
2020-04-07 14:26:44 +02:00
|
|
|
void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t points[])
|
2018-02-24 13:17:39 +01:00
|
|
|
{
|
2019-02-28 13:05:47 +01:00
|
|
|
if(indev->driver.type == LV_INDEV_TYPE_BUTTON) {
|
2019-03-07 00:05:16 +01:00
|
|
|
indev->btn_points = points;
|
2019-02-28 13:05:47 +01:00
|
|
|
}
|
2018-02-24 13:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the last point of an input device (for LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON)
|
2017-10-09 15:21:26 +02:00
|
|
|
* @param indev pointer to an input device
|
|
|
|
* @param point pointer to a point to store the result
|
|
|
|
*/
|
2018-07-30 06:52:29 +02:00
|
|
|
void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point)
|
2017-10-09 15:21:26 +02:00
|
|
|
{
|
2020-03-10 20:55:32 +01:00
|
|
|
if(indev == NULL) {
|
|
|
|
point->x = 0;
|
|
|
|
point->y = 0;
|
|
|
|
return;
|
|
|
|
}
|
2018-02-24 13:17:39 +01:00
|
|
|
if(indev->driver.type != LV_INDEV_TYPE_POINTER && indev->driver.type != LV_INDEV_TYPE_BUTTON) {
|
2018-07-13 00:37:28 +02:00
|
|
|
point->x = -1;
|
|
|
|
point->y = -1;
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else {
|
2019-02-26 19:46:37 +01:00
|
|
|
point->x = indev->proc.types.pointer.act_point.x;
|
|
|
|
point->y = indev->proc.types.pointer.act_point.y;
|
2018-02-24 13:17:39 +01:00
|
|
|
}
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
|
2020-01-16 19:24:08 -05:00
|
|
|
/**
|
|
|
|
* Get the current gesture direct
|
|
|
|
* @param indev pointer to an input device
|
|
|
|
* @return current gesture direct
|
2020-02-17 14:36:32 +01:00
|
|
|
*/
|
2020-01-16 19:24:08 -05:00
|
|
|
lv_gesture_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev)
|
|
|
|
{
|
|
|
|
return indev->proc.types.pointer.gesture_dir;
|
|
|
|
}
|
|
|
|
|
2018-08-09 07:30:10 +02:00
|
|
|
/**
|
2019-03-17 07:59:38 +01:00
|
|
|
* Get the last pressed key of an input device (for LV_INDEV_TYPE_KEYPAD)
|
2018-08-09 07:30:10 +02:00
|
|
|
* @param indev pointer to an input device
|
|
|
|
* @return the last pressed key (0 on error)
|
|
|
|
*/
|
|
|
|
uint32_t lv_indev_get_key(const lv_indev_t * indev)
|
|
|
|
{
|
2019-04-04 07:15:40 +02:00
|
|
|
if(indev->driver.type != LV_INDEV_TYPE_KEYPAD)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return indev->proc.types.keypad.last_key;
|
2018-08-09 07:30:10 +02:00
|
|
|
}
|
|
|
|
|
2017-10-09 15:21:26 +02:00
|
|
|
/**
|
2019-04-04 07:15:40 +02:00
|
|
|
* Check if there is dragging with an input device or not (for LV_INDEV_TYPE_POINTER and
|
|
|
|
* LV_INDEV_TYPE_BUTTON)
|
2017-10-09 15:21:26 +02:00
|
|
|
* @param indev pointer to an input device
|
|
|
|
* @return true: drag is in progress
|
|
|
|
*/
|
2018-07-30 06:52:29 +02:00
|
|
|
bool lv_indev_is_dragging(const lv_indev_t * indev)
|
2017-10-09 15:21:26 +02:00
|
|
|
{
|
2017-11-05 00:48:57 +01:00
|
|
|
if(indev == NULL) return false;
|
2019-06-06 06:05:40 +02:00
|
|
|
if(indev->driver.type != LV_INDEV_TYPE_POINTER && indev->driver.type != LV_INDEV_TYPE_BUTTON) return false;
|
2019-02-26 19:46:37 +01:00
|
|
|
return indev->proc.types.pointer.drag_in_prog == 0 ? false : true;
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-04-04 07:15:40 +02:00
|
|
|
* Get the types.pointer.vector of dragging of an input device (for LV_INDEV_TYPE_POINTER and
|
|
|
|
* LV_INDEV_TYPE_BUTTON)
|
2017-10-09 15:21:26 +02:00
|
|
|
* @param indev pointer to an input device
|
2019-02-26 19:46:37 +01:00
|
|
|
* @param point pointer to a point to store the types.pointer.vector
|
2017-10-09 15:21:26 +02:00
|
|
|
*/
|
2018-07-30 06:52:29 +02:00
|
|
|
void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point)
|
2017-10-09 15:21:26 +02:00
|
|
|
{
|
2018-11-11 19:56:30 +01:00
|
|
|
if(indev == NULL) {
|
|
|
|
point->x = 0;
|
|
|
|
point->y = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-24 13:17:39 +01:00
|
|
|
if(indev->driver.type != LV_INDEV_TYPE_POINTER && indev->driver.type != LV_INDEV_TYPE_BUTTON) {
|
|
|
|
point->x = 0;
|
|
|
|
point->y = 0;
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else {
|
2019-02-26 19:46:37 +01:00
|
|
|
point->x = indev->proc.types.pointer.vect.x;
|
|
|
|
point->y = indev->proc.types.pointer.vect.y;
|
2018-02-24 13:17:39 +01:00
|
|
|
}
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
|
2019-09-19 14:58:07 +02:00
|
|
|
/**
|
|
|
|
* Manually finish dragging.
|
|
|
|
* `LV_SIGNAL_DRAG_END` and `LV_EVENT_DRAG_END` will be sent.
|
|
|
|
* @param indev pointer to an input device
|
|
|
|
* @return `LV_RES_INV` if the object being dragged was deleted. Else `LV_RES_OK`.
|
|
|
|
*/
|
|
|
|
lv_res_t lv_indev_finish_drag(lv_indev_t * indev)
|
|
|
|
{
|
|
|
|
if(indev == NULL) return LV_RES_OK;
|
|
|
|
if(indev->driver.type != LV_INDEV_TYPE_POINTER) return LV_RES_OK;
|
|
|
|
if(indev->proc.types.pointer.drag_in_prog == 0) return LV_RES_OK;
|
|
|
|
|
|
|
|
indev->proc.types.pointer.drag_in_prog = 0;
|
|
|
|
indev->proc.types.pointer.drag_throw_vect.x = 0;
|
|
|
|
indev->proc.types.pointer.drag_throw_vect.y = 0;
|
|
|
|
|
|
|
|
lv_obj_t * drag_obj;
|
|
|
|
drag_obj = get_dragged_obj(indev->proc.types.pointer.act_obj);
|
|
|
|
if(drag_obj == NULL) return LV_RES_OK;
|
|
|
|
|
|
|
|
lv_res_t res;
|
|
|
|
res = drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_END, NULL);
|
|
|
|
if(res != LV_RES_OK) return res;
|
|
|
|
|
|
|
|
res = lv_event_send(drag_obj, LV_EVENT_DRAG_END, NULL);
|
|
|
|
if(res != LV_RES_OK) return res;
|
2019-10-31 08:51:34 +01:00
|
|
|
|
|
|
|
return res;
|
2019-09-19 14:58:07 +02:00
|
|
|
}
|
|
|
|
|
2017-10-09 15:21:26 +02:00
|
|
|
/**
|
|
|
|
* Do nothing until the next release
|
|
|
|
* @param indev pointer to an input device
|
|
|
|
*/
|
|
|
|
void lv_indev_wait_release(lv_indev_t * indev)
|
|
|
|
{
|
2020-03-26 14:08:25 +08:00
|
|
|
if(indev == NULL)return;
|
2019-03-22 06:35:17 +01:00
|
|
|
indev->proc.wait_until_release = 1;
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-04-02 12:15:35 +02:00
|
|
|
* Get a pointer to the indev read task to
|
|
|
|
* modify its parameters with `lv_task_...` functions.
|
|
|
|
* @param indev pointer to an input device
|
|
|
|
* @return pointer to the indev read refresher task. (NULL on error)
|
2017-10-09 15:21:26 +02:00
|
|
|
*/
|
2019-04-02 12:15:35 +02:00
|
|
|
lv_task_t * lv_indev_get_read_task(lv_disp_t * indev)
|
2017-10-09 15:21:26 +02:00
|
|
|
{
|
2019-04-02 12:15:35 +02:00
|
|
|
if(!indev) {
|
|
|
|
LV_LOG_WARN("lv_indev_get_read_task: indev was NULL");
|
|
|
|
return NULL;
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
|
2019-04-02 12:15:35 +02:00
|
|
|
return indev->refr_task;
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
|
2019-05-20 09:42:31 -07:00
|
|
|
/**
|
2019-05-21 15:49:50 +02:00
|
|
|
* Gets a pointer to the currently active object in the currently processed input device.
|
|
|
|
* @return pointer to currently active object or NULL if no active object
|
2019-05-20 09:42:31 -07:00
|
|
|
*/
|
2019-05-21 15:49:50 +02:00
|
|
|
lv_obj_t * lv_indev_get_obj_act(void)
|
|
|
|
{
|
2019-05-20 09:42:31 -07:00
|
|
|
return indev_obj_act;
|
2019-05-19 10:56:34 -07:00
|
|
|
}
|
|
|
|
|
2019-04-02 12:15:35 +02:00
|
|
|
/**********************
|
|
|
|
* STATIC FUNCTIONS
|
|
|
|
**********************/
|
2018-02-24 13:17:39 +01:00
|
|
|
|
2017-10-09 15:21:26 +02:00
|
|
|
/**
|
2018-02-24 13:17:39 +01:00
|
|
|
* Process a new point from LV_INDEV_TYPE_POINTER input device
|
|
|
|
* @param i pointer to an input device
|
|
|
|
* @param data pointer to the data read from the input device
|
2017-10-09 15:21:26 +02:00
|
|
|
*/
|
2018-02-24 13:17:39 +01:00
|
|
|
static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data)
|
2017-10-09 15:21:26 +02:00
|
|
|
{
|
2018-02-24 13:17:39 +01:00
|
|
|
/*Move the cursor if set and moved*/
|
2019-06-06 06:05:40 +02:00
|
|
|
if(i->cursor != NULL &&
|
|
|
|
(i->proc.types.pointer.last_point.x != data->point.x || i->proc.types.pointer.last_point.y != data->point.y)) {
|
2019-03-07 00:05:16 +01:00
|
|
|
lv_obj_set_pos(i->cursor, data->point.x, data->point.y);
|
2018-02-24 13:17:39 +01:00
|
|
|
}
|
|
|
|
|
2019-02-26 19:46:37 +01:00
|
|
|
i->proc.types.pointer.act_point.x = data->point.x;
|
|
|
|
i->proc.types.pointer.act_point.y = data->point.y;
|
2018-02-24 13:17:39 +01:00
|
|
|
|
2018-06-19 09:49:58 +02:00
|
|
|
if(i->proc.state == LV_INDEV_STATE_PR) {
|
2018-02-24 13:17:39 +01:00
|
|
|
indev_proc_press(&i->proc);
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else {
|
2018-02-24 13:17:39 +01:00
|
|
|
indev_proc_release(&i->proc);
|
|
|
|
}
|
|
|
|
|
2019-02-26 19:46:37 +01:00
|
|
|
i->proc.types.pointer.last_point.x = i->proc.types.pointer.act_point.x;
|
|
|
|
i->proc.types.pointer.last_point.y = i->proc.types.pointer.act_point.y;
|
2018-02-24 13:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Process a new point from LV_INDEV_TYPE_KEYPAD input device
|
|
|
|
* @param i pointer to an input device
|
|
|
|
* @param data pointer to the data read from the input device
|
|
|
|
*/
|
|
|
|
static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data)
|
|
|
|
{
|
2019-03-07 00:05:16 +01:00
|
|
|
#if LV_USE_GROUP
|
2019-03-22 06:35:17 +01:00
|
|
|
if(data->state == LV_INDEV_STATE_PR && i->proc.wait_until_release) return;
|
|
|
|
|
|
|
|
if(i->proc.wait_until_release) {
|
2019-04-04 07:15:40 +02:00
|
|
|
i->proc.wait_until_release = 0;
|
|
|
|
i->proc.pr_timestamp = 0;
|
|
|
|
i->proc.long_pr_sent = 0;
|
|
|
|
i->proc.types.keypad.last_state = LV_INDEV_STATE_REL; /*To skip the processing of release*/
|
2019-03-22 06:35:17 +01:00
|
|
|
}
|
|
|
|
|
2019-03-07 00:05:16 +01:00
|
|
|
lv_group_t * g = i->group;
|
2019-02-28 13:05:47 +01:00
|
|
|
if(g == NULL) return;
|
2018-02-24 14:39:15 +01:00
|
|
|
|
2019-05-20 09:42:31 -07:00
|
|
|
indev_obj_act = lv_group_get_focused(g);
|
|
|
|
if(indev_obj_act == NULL) return;
|
2019-02-26 09:25:46 +01:00
|
|
|
|
2019-03-17 07:59:38 +01:00
|
|
|
/*Save the last key to compare it with the current latter on RELEASE*/
|
|
|
|
uint32_t prev_key = i->proc.types.keypad.last_key;
|
|
|
|
|
|
|
|
/* Save the last key.
|
|
|
|
* It must be done here else `lv_indev_get_key` will return the last key in events and signals*/
|
|
|
|
i->proc.types.keypad.last_key = data->key;
|
|
|
|
|
2019-03-25 14:17:23 +01:00
|
|
|
/* Save the previous state so we can detect state changes below and also set the last state now
|
|
|
|
* so if any signal/event handler on the way returns `LV_RES_INV` the last state is remembered
|
|
|
|
* for the next time*/
|
2019-04-04 07:15:40 +02:00
|
|
|
uint32_t prev_state = i->proc.types.keypad.last_state;
|
2019-03-25 14:17:23 +01:00
|
|
|
i->proc.types.keypad.last_state = data->state;
|
|
|
|
|
|
|
|
/*Key press happened*/
|
2019-04-04 07:15:40 +02:00
|
|
|
if(data->state == LV_INDEV_STATE_PR && prev_state == LV_INDEV_STATE_REL) {
|
2019-03-25 14:17:23 +01:00
|
|
|
i->proc.pr_timestamp = lv_tick_get();
|
|
|
|
|
|
|
|
/*Simulate a press on the object if ENTER was pressed*/
|
2019-04-08 14:36:20 +02:00
|
|
|
if(data->key == LV_KEY_ENTER) {
|
2019-04-03 22:36:10 -07:00
|
|
|
/*Send the ENTER as a normal KEY*/
|
2019-04-08 14:40:41 +02:00
|
|
|
lv_group_send_data(g, LV_KEY_ENTER);
|
2019-04-03 22:36:10 -07:00
|
|
|
|
2019-05-20 09:42:31 -07:00
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_PRESSED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-05-20 09:42:31 -07:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_PRESSED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else if(data->key == LV_KEY_ESC) {
|
2019-04-03 22:36:10 -07:00
|
|
|
/*Send the ESC as a normal KEY*/
|
2019-04-08 14:40:41 +02:00
|
|
|
lv_group_send_data(g, LV_KEY_ESC);
|
2019-03-25 14:17:23 +01:00
|
|
|
|
2019-05-20 09:42:31 -07:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_CANCEL, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-25 14:17:23 +01:00
|
|
|
}
|
|
|
|
/*Move the focus on NEXT*/
|
2019-04-08 14:36:20 +02:00
|
|
|
else if(data->key == LV_KEY_NEXT) {
|
2019-06-06 06:05:40 +02:00
|
|
|
lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/
|
2019-03-25 14:17:23 +01:00
|
|
|
lv_group_focus_next(g);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-25 14:17:23 +01:00
|
|
|
}
|
|
|
|
/*Move the focus on PREV*/
|
2019-04-08 14:36:20 +02:00
|
|
|
else if(data->key == LV_KEY_PREV) {
|
2019-06-06 06:05:40 +02:00
|
|
|
lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/
|
2019-03-25 14:17:23 +01:00
|
|
|
lv_group_focus_prev(g);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-25 14:17:23 +01:00
|
|
|
}
|
2019-04-03 22:36:10 -07:00
|
|
|
/*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/
|
2019-03-25 14:17:23 +01:00
|
|
|
else {
|
|
|
|
lv_group_send_data(g, data->key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*Pressing*/
|
2019-04-04 07:15:40 +02:00
|
|
|
else if(data->state == LV_INDEV_STATE_PR && prev_state == LV_INDEV_STATE_PR) {
|
2020-03-10 20:55:32 +01:00
|
|
|
|
|
|
|
if(data->key == LV_KEY_ENTER) {
|
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_PRESSING, NULL);
|
|
|
|
if(indev_reset_check(&i->proc)) return;
|
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_PRESSING, NULL);
|
|
|
|
if(indev_reset_check(&i->proc)) return;
|
|
|
|
}
|
|
|
|
|
2019-03-25 14:17:23 +01:00
|
|
|
/*Long press time has elapsed?*/
|
2019-06-06 06:05:40 +02:00
|
|
|
if(i->proc.long_pr_sent == 0 && lv_tick_elaps(i->proc.pr_timestamp) > i->driver.long_press_time) {
|
2019-03-25 14:17:23 +01:00
|
|
|
i->proc.long_pr_sent = 1;
|
2019-04-08 14:36:20 +02:00
|
|
|
if(data->key == LV_KEY_ENTER) {
|
2019-03-25 14:17:23 +01:00
|
|
|
i->proc.longpr_rep_timestamp = lv_tick_get();
|
2019-05-20 09:42:31 -07:00
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_LONG_PRESS, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-05-20 09:42:31 -07:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-25 14:17:23 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/*Long press repeated time has elapsed?*/
|
2019-04-04 07:15:40 +02:00
|
|
|
else if(i->proc.long_pr_sent != 0 &&
|
|
|
|
lv_tick_elaps(i->proc.longpr_rep_timestamp) > i->driver.long_press_rep_time) {
|
2019-03-25 14:17:23 +01:00
|
|
|
|
|
|
|
i->proc.longpr_rep_timestamp = lv_tick_get();
|
|
|
|
|
|
|
|
/*Send LONG_PRESS_REP on ENTER*/
|
2019-04-08 14:36:20 +02:00
|
|
|
if(data->key == LV_KEY_ENTER) {
|
2019-05-20 09:42:31 -07:00
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_LONG_PRESS_REP, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-05-20 09:42:31 -07:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED_REPEAT, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-01 06:26:03 +01:00
|
|
|
}
|
2019-03-25 14:17:23 +01:00
|
|
|
/*Move the focus on NEXT again*/
|
2019-04-08 14:36:20 +02:00
|
|
|
else if(data->key == LV_KEY_NEXT) {
|
2019-06-06 06:05:40 +02:00
|
|
|
lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/
|
2019-03-01 06:26:03 +01:00
|
|
|
lv_group_focus_next(g);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-01 06:26:03 +01:00
|
|
|
}
|
2019-03-25 14:17:23 +01:00
|
|
|
/*Move the focus on PREV again*/
|
2019-04-08 14:36:20 +02:00
|
|
|
else if(data->key == LV_KEY_PREV) {
|
2019-06-06 06:05:40 +02:00
|
|
|
lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/
|
2019-03-01 06:26:03 +01:00
|
|
|
lv_group_focus_prev(g);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-01 06:26:03 +01:00
|
|
|
}
|
2019-03-25 14:17:23 +01:00
|
|
|
/*Just send other keys again to the object (e.g. 'A' or `LV_GORUP_KEY_RIGHT)*/
|
2019-03-01 06:26:03 +01:00
|
|
|
else {
|
|
|
|
lv_group_send_data(g, data->key);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2018-10-05 17:22:49 +02:00
|
|
|
}
|
2018-02-24 14:39:15 +01:00
|
|
|
}
|
2019-03-25 14:17:23 +01:00
|
|
|
}
|
|
|
|
/*Release happened*/
|
2019-04-04 07:15:40 +02:00
|
|
|
else if(data->state == LV_INDEV_STATE_REL && prev_state == LV_INDEV_STATE_PR) {
|
2019-03-25 14:17:23 +01:00
|
|
|
/*The user might clear the key when it was released. Always release the pressed key*/
|
|
|
|
data->key = prev_key;
|
2019-04-08 14:36:20 +02:00
|
|
|
if(data->key == LV_KEY_ENTER) {
|
2019-03-25 14:17:23 +01:00
|
|
|
|
2019-05-20 09:42:31 -07:00
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_RELEASED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-25 14:17:23 +01:00
|
|
|
|
|
|
|
if(i->proc.long_pr_sent == 0) {
|
2019-05-20 09:42:31 -07:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2018-10-05 17:22:49 +02:00
|
|
|
}
|
2019-03-07 00:42:08 +01:00
|
|
|
|
2019-05-20 09:42:31 -07:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_CLICKED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-07 00:42:08 +01:00
|
|
|
|
2019-05-20 09:42:31 -07:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_RELEASED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2018-09-24 22:59:48 +02:00
|
|
|
}
|
2019-03-25 14:17:23 +01:00
|
|
|
i->proc.pr_timestamp = 0;
|
|
|
|
i->proc.long_pr_sent = 0;
|
|
|
|
}
|
2019-05-20 09:42:31 -07:00
|
|
|
indev_obj_act = NULL;
|
2018-10-09 15:03:46 +02:00
|
|
|
#else
|
|
|
|
(void)data; /*Unused*/
|
2019-04-04 07:15:40 +02:00
|
|
|
(void)i; /*Unused*/
|
2018-09-24 22:59:48 +02:00
|
|
|
#endif
|
|
|
|
}
|
2018-09-24 00:35:19 +02:00
|
|
|
|
2018-09-24 22:59:48 +02:00
|
|
|
/**
|
|
|
|
* Process a new point from LV_INDEV_TYPE_ENCODER input device
|
|
|
|
* @param i pointer to an input device
|
|
|
|
* @param data pointer to the data read from the input device
|
|
|
|
*/
|
|
|
|
static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data)
|
|
|
|
{
|
2019-03-07 00:05:16 +01:00
|
|
|
#if LV_USE_GROUP
|
2019-03-22 06:35:17 +01:00
|
|
|
|
|
|
|
if(data->state == LV_INDEV_STATE_PR && i->proc.wait_until_release) return;
|
|
|
|
|
|
|
|
if(i->proc.wait_until_release) {
|
2019-04-04 07:15:40 +02:00
|
|
|
i->proc.wait_until_release = 0;
|
|
|
|
i->proc.pr_timestamp = 0;
|
|
|
|
i->proc.long_pr_sent = 0;
|
|
|
|
i->proc.types.keypad.last_state = LV_INDEV_STATE_REL; /*To skip the processing of release*/
|
2019-03-22 06:35:17 +01:00
|
|
|
}
|
|
|
|
|
2019-05-08 16:08:05 +02:00
|
|
|
/* Save the last keys before anything else.
|
|
|
|
* They need to be already saved if the the function returns for any reason*/
|
2019-06-06 06:05:40 +02:00
|
|
|
lv_indev_state_t last_state = i->proc.types.keypad.last_state;
|
2019-05-08 16:08:05 +02:00
|
|
|
i->proc.types.keypad.last_state = data->state;
|
|
|
|
i->proc.types.keypad.last_key = data->key;
|
|
|
|
|
2019-03-07 00:05:16 +01:00
|
|
|
lv_group_t * g = i->group;
|
2019-02-28 13:05:47 +01:00
|
|
|
if(g == NULL) return;
|
2018-09-24 00:35:19 +02:00
|
|
|
|
2019-05-20 09:42:31 -07:00
|
|
|
indev_obj_act = lv_group_get_focused(g);
|
|
|
|
if(indev_obj_act == NULL) return;
|
2019-05-08 16:08:05 +02:00
|
|
|
|
2018-09-24 22:59:48 +02:00
|
|
|
/*Process the steps first. They are valid only with released button*/
|
|
|
|
if(data->state == LV_INDEV_STATE_REL) {
|
|
|
|
/*In edit mode send LEFT/RIGHT keys*/
|
2019-02-28 13:05:47 +01:00
|
|
|
if(lv_group_get_editing(g)) {
|
2018-09-25 11:16:37 +02:00
|
|
|
int32_t s;
|
2018-09-24 22:59:48 +02:00
|
|
|
if(data->enc_diff < 0) {
|
2019-04-08 14:36:20 +02:00
|
|
|
for(s = 0; s < -data->enc_diff; s++) lv_group_send_data(g, LV_KEY_LEFT);
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else if(data->enc_diff > 0) {
|
2019-04-08 14:36:20 +02:00
|
|
|
for(s = 0; s < data->enc_diff; s++) lv_group_send_data(g, LV_KEY_RIGHT);
|
2018-09-24 22:59:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/*In navigate mode focus on the next/prev objects*/
|
2018-09-25 11:16:37 +02:00
|
|
|
else {
|
|
|
|
int32_t s;
|
2018-09-24 22:59:48 +02:00
|
|
|
if(data->enc_diff < 0) {
|
2019-02-28 13:05:47 +01:00
|
|
|
for(s = 0; s < -data->enc_diff; s++) lv_group_focus_prev(g);
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else if(data->enc_diff > 0) {
|
2019-02-28 13:05:47 +01:00
|
|
|
for(s = 0; s < data->enc_diff; s++) lv_group_focus_next(g);
|
2018-09-24 22:59:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-01 22:23:59 +01:00
|
|
|
/*Refresh the focused object. It might change due to lv_group_focus_prev/next*/
|
2019-05-20 09:42:31 -07:00
|
|
|
indev_obj_act = lv_group_get_focused(g);
|
|
|
|
if(indev_obj_act == NULL) return;
|
2019-03-01 22:23:59 +01:00
|
|
|
|
|
|
|
/*Button press happened*/
|
2019-05-08 16:08:05 +02:00
|
|
|
if(data->state == LV_INDEV_STATE_PR && last_state == LV_INDEV_STATE_REL) {
|
2019-03-12 15:17:28 +01:00
|
|
|
bool editable = false;
|
2019-05-20 09:42:31 -07:00
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_GET_EDITABLE, &editable);
|
2019-03-12 15:17:28 +01:00
|
|
|
|
2018-09-24 22:59:48 +02:00
|
|
|
i->proc.pr_timestamp = lv_tick_get();
|
2019-03-07 00:05:16 +01:00
|
|
|
if(lv_group_get_editing(g) == true || editable == false) {
|
2019-05-20 09:42:31 -07:00
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_PRESSED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-12 14:46:02 +01:00
|
|
|
|
2019-05-20 09:42:31 -07:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_PRESSED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-07 00:05:16 +01:00
|
|
|
}
|
2018-09-24 22:59:48 +02:00
|
|
|
}
|
|
|
|
/*Pressing*/
|
2019-06-06 06:05:40 +02:00
|
|
|
else if(data->state == LV_INDEV_STATE_PR && last_state == LV_INDEV_STATE_PR) {
|
|
|
|
if(i->proc.long_pr_sent == 0 && lv_tick_elaps(i->proc.pr_timestamp) > i->driver.long_press_time) {
|
2019-03-12 15:17:28 +01:00
|
|
|
bool editable = false;
|
2019-05-20 09:42:31 -07:00
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_GET_EDITABLE, &editable);
|
2019-03-12 15:17:28 +01:00
|
|
|
|
2019-03-01 22:23:59 +01:00
|
|
|
/*On enter long press toggle edit mode.*/
|
2018-10-05 17:22:49 +02:00
|
|
|
if(editable) {
|
2019-03-12 14:46:02 +01:00
|
|
|
/*Don't leave edit mode if there is only one object (nowhere to navigate)*/
|
|
|
|
if(lv_ll_is_empty(&g->obj_ll) == false) {
|
2019-06-06 06:05:40 +02:00
|
|
|
lv_group_set_editing(g, lv_group_get_editing(g) ? false : true); /*Toggle edit mode on long press*/
|
2019-03-01 22:23:59 +01:00
|
|
|
}
|
2018-09-24 22:59:48 +02:00
|
|
|
}
|
|
|
|
/*If not editable then just send a long press signal*/
|
|
|
|
else {
|
2019-05-20 09:42:31 -07:00
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_LONG_PRESS, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-05-20 09:42:31 -07:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2018-09-24 22:59:48 +02:00
|
|
|
}
|
|
|
|
i->proc.long_pr_sent = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*Release happened*/
|
2019-06-06 06:05:40 +02:00
|
|
|
else if(data->state == LV_INDEV_STATE_REL && last_state == LV_INDEV_STATE_PR) {
|
2018-09-24 22:59:48 +02:00
|
|
|
|
2019-03-12 15:17:28 +01:00
|
|
|
bool editable = false;
|
2019-05-20 09:42:31 -07:00
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_GET_EDITABLE, &editable);
|
2019-03-12 15:17:28 +01:00
|
|
|
|
2018-09-24 22:59:48 +02:00
|
|
|
/*The button was released on a non-editable object. Just send enter*/
|
2019-03-01 22:23:59 +01:00
|
|
|
if(editable == false) {
|
2019-05-20 09:42:31 -07:00
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_RELEASED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-12 14:46:02 +01:00
|
|
|
|
2019-05-20 09:42:31 -07:00
|
|
|
if(i->proc.long_pr_sent == 0) lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-07 00:42:08 +01:00
|
|
|
|
2019-05-20 09:42:31 -07:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_CLICKED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-07 00:05:16 +01:00
|
|
|
|
2019-05-20 09:42:31 -07:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_RELEASED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2018-09-24 22:59:48 +02:00
|
|
|
}
|
2019-03-12 14:46:02 +01:00
|
|
|
/*An object is being edited and the button is released. */
|
2019-02-28 13:05:47 +01:00
|
|
|
else if(g->editing) {
|
2019-03-12 14:46:02 +01:00
|
|
|
/*Ignore long pressed enter release because it comes from mode switch*/
|
2019-03-01 22:23:59 +01:00
|
|
|
if(!i->proc.long_pr_sent || lv_ll_is_empty(&g->obj_ll)) {
|
2019-05-20 09:42:31 -07:00
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_RELEASED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-12 14:46:02 +01:00
|
|
|
|
2019-05-20 09:42:31 -07:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-07 00:42:08 +01:00
|
|
|
|
2019-05-20 09:42:31 -07:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_CLICKED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-12 14:46:02 +01:00
|
|
|
|
2019-05-20 09:42:31 -07:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_RELEASED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(&i->proc)) return;
|
2019-03-12 14:46:02 +01:00
|
|
|
|
2019-04-08 14:36:20 +02:00
|
|
|
lv_group_send_data(g, LV_KEY_ENTER);
|
2019-03-01 22:23:59 +01:00
|
|
|
}
|
2018-09-24 22:59:48 +02:00
|
|
|
}
|
2019-04-04 07:15:40 +02:00
|
|
|
/*If the focused object is editable and now in navigate mode then on enter switch edit
|
|
|
|
mode*/
|
2019-02-28 13:05:47 +01:00
|
|
|
else if(editable && !g->editing && !i->proc.long_pr_sent) {
|
2019-04-04 07:15:40 +02:00
|
|
|
lv_group_set_editing(g, true); /*Set edit mode*/
|
2018-02-24 13:17:39 +01:00
|
|
|
}
|
2018-02-24 14:39:15 +01:00
|
|
|
|
|
|
|
i->proc.pr_timestamp = 0;
|
|
|
|
i->proc.long_pr_sent = 0;
|
2018-02-24 13:17:39 +01:00
|
|
|
}
|
2019-05-20 09:42:31 -07:00
|
|
|
indev_obj_act = NULL;
|
2018-10-09 15:03:46 +02:00
|
|
|
#else
|
|
|
|
(void)data; /*Unused*/
|
2019-04-04 07:15:40 +02:00
|
|
|
(void)i; /*Unused*/
|
2018-02-24 13:17:39 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-10-09 15:21:26 +02:00
|
|
|
* Process new points from a input device. indev->state.pressed has to be set
|
|
|
|
* @param indev pointer to an input device state
|
|
|
|
* @param x x coordinate of the next point
|
|
|
|
* @param y y coordinate of the next point
|
2018-02-24 13:17:39 +01:00
|
|
|
*/
|
|
|
|
static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data)
|
|
|
|
{
|
2020-05-04 15:56:13 +02:00
|
|
|
/* Die gracefully if i->btn_points is NULL */
|
|
|
|
if (i->btn_points == NULL) {
|
|
|
|
LV_LOG_WARN("indev_button_proc: btn_points was NULL");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-07 00:05:16 +01:00
|
|
|
i->proc.types.pointer.act_point.x = i->btn_points[data->btn_id].x;
|
|
|
|
i->proc.types.pointer.act_point.y = i->btn_points[data->btn_id].y;
|
2018-02-24 13:17:39 +01:00
|
|
|
|
|
|
|
/*Still the same point is pressed*/
|
2019-02-26 19:46:37 +01:00
|
|
|
if(i->proc.types.pointer.last_point.x == i->proc.types.pointer.act_point.x &&
|
2019-06-06 06:05:40 +02:00
|
|
|
i->proc.types.pointer.last_point.y == i->proc.types.pointer.act_point.y && data->state == LV_INDEV_STATE_PR) {
|
2018-02-24 13:17:39 +01:00
|
|
|
indev_proc_press(&i->proc);
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else {
|
2018-02-24 13:17:39 +01:00
|
|
|
/*If a new point comes always make a release*/
|
|
|
|
indev_proc_release(&i->proc);
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
2018-02-24 13:17:39 +01:00
|
|
|
|
2019-02-26 19:46:37 +01:00
|
|
|
i->proc.types.pointer.last_point.x = i->proc.types.pointer.act_point.x;
|
|
|
|
i->proc.types.pointer.last_point.y = i->proc.types.pointer.act_point.y;
|
2018-02-24 13:17:39 +01:00
|
|
|
}
|
2017-10-09 15:21:26 +02:00
|
|
|
|
|
|
|
/**
|
2018-02-24 13:17:39 +01:00
|
|
|
* Process the pressed state of LV_INDEV_TYPE_POINER input devices
|
|
|
|
* @param indev pointer to an input device 'proc'
|
2019-03-07 00:05:16 +01:00
|
|
|
* @return LV_RES_OK: no indev reset required; LV_RES_INV: indev reset is required
|
2017-10-09 15:21:26 +02:00
|
|
|
*/
|
2018-02-24 13:17:39 +01:00
|
|
|
static void indev_proc_press(lv_indev_proc_t * proc)
|
2017-10-09 15:21:26 +02:00
|
|
|
{
|
2019-05-21 15:56:27 +02:00
|
|
|
indev_obj_act = proc->types.pointer.act_obj;
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2019-03-22 06:35:17 +01:00
|
|
|
if(proc->wait_until_release != 0) return;
|
2017-10-09 15:21:26 +02:00
|
|
|
|
2019-02-20 10:16:33 +01:00
|
|
|
lv_disp_t * disp = indev_act->driver.disp;
|
2019-08-16 16:43:05 +02:00
|
|
|
bool new_obj_searched = false;
|
2019-02-20 10:16:33 +01:00
|
|
|
|
2017-10-09 15:21:26 +02:00
|
|
|
/*If there is no last object then search*/
|
2019-05-21 15:49:50 +02:00
|
|
|
if(indev_obj_act == NULL) {
|
2019-12-09 04:21:56 +07:00
|
|
|
indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point);
|
2020-02-26 19:48:27 +01:00
|
|
|
if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp),
|
|
|
|
&proc->types.pointer.act_point);
|
|
|
|
if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_scr_act(disp),
|
|
|
|
&proc->types.pointer.act_point);
|
2019-08-16 16:43:05 +02:00
|
|
|
new_obj_searched = true;
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
2018-02-24 11:26:06 +01:00
|
|
|
/*If there is last object but it is not dragged and not protected also search*/
|
2019-02-26 19:46:37 +01:00
|
|
|
else if(proc->types.pointer.drag_in_prog == 0 &&
|
2019-05-21 15:49:50 +02:00
|
|
|
lv_obj_is_protected(indev_obj_act, LV_PROTECT_PRESS_LOST) == false) {
|
2019-12-09 04:21:56 +07:00
|
|
|
indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point);
|
2020-02-26 19:48:27 +01:00
|
|
|
if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp),
|
|
|
|
&proc->types.pointer.act_point);
|
|
|
|
if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_scr_act(disp),
|
|
|
|
&proc->types.pointer.act_point);
|
2019-08-16 16:43:05 +02:00
|
|
|
new_obj_searched = true;
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
2018-02-24 11:26:06 +01:00
|
|
|
/*If a dragable or a protected object was the last then keep it*/
|
2017-10-09 15:21:26 +02:00
|
|
|
else {
|
|
|
|
}
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2019-08-16 16:43:05 +02:00
|
|
|
/*The last object might have drag throw. Stop it manually*/
|
|
|
|
if(new_obj_searched && proc->types.pointer.last_obj) {
|
|
|
|
proc->types.pointer.drag_throw_vect.x = 0;
|
|
|
|
proc->types.pointer.drag_throw_vect.y = 0;
|
|
|
|
indev_drag_throw(proc);
|
|
|
|
}
|
|
|
|
|
2020-03-10 18:29:41 +01:00
|
|
|
/*Do not use disabled objects*/
|
2020-04-26 10:18:49 +02:00
|
|
|
if(indev_obj_act && (lv_obj_get_state(indev_obj_act, LV_OBJ_PART_MAIN) & LV_STATE_DISABLED)) {
|
2020-03-10 18:29:41 +01:00
|
|
|
indev_obj_act = proc->types.pointer.act_obj;
|
|
|
|
}
|
|
|
|
|
2017-10-09 15:21:26 +02:00
|
|
|
/*If a new object was found reset some variables and send a pressed signal*/
|
2019-05-21 15:49:50 +02:00
|
|
|
if(indev_obj_act != proc->types.pointer.act_obj) {
|
2019-02-26 19:46:37 +01:00
|
|
|
proc->types.pointer.last_point.x = proc->types.pointer.act_point.x;
|
|
|
|
proc->types.pointer.last_point.y = proc->types.pointer.act_point.y;
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2017-10-09 15:21:26 +02:00
|
|
|
/*If a new object found the previous was lost, so send a signal*/
|
2019-02-26 19:46:37 +01:00
|
|
|
if(proc->types.pointer.act_obj != NULL) {
|
2019-05-21 15:49:50 +02:00
|
|
|
/*Save the obj because in special cases `act_obj` can change in the signal function*/
|
|
|
|
lv_obj_t * last_obj = proc->types.pointer.act_obj;
|
|
|
|
|
|
|
|
last_obj->signal_cb(last_obj, LV_SIGNAL_PRESS_LOST, indev_act);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2019-05-21 15:49:50 +02:00
|
|
|
lv_event_send(last_obj, LV_EVENT_PRESS_LOST, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2019-08-16 16:43:05 +02:00
|
|
|
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2019-06-06 06:05:40 +02:00
|
|
|
proc->types.pointer.act_obj = indev_obj_act; /*Save the pressed object*/
|
2019-05-21 15:49:50 +02:00
|
|
|
proc->types.pointer.last_obj = indev_obj_act;
|
2018-11-11 19:56:30 +01:00
|
|
|
|
2019-05-21 15:49:50 +02:00
|
|
|
if(indev_obj_act != NULL) {
|
2019-09-17 14:38:55 +02:00
|
|
|
/* Save the time when the obj pressed to count long press time.*/
|
2019-04-04 07:15:40 +02:00
|
|
|
proc->pr_timestamp = lv_tick_get();
|
|
|
|
proc->long_pr_sent = 0;
|
2019-02-27 06:04:30 +01:00
|
|
|
proc->types.pointer.drag_limit_out = 0;
|
2019-04-04 07:15:40 +02:00
|
|
|
proc->types.pointer.drag_in_prog = 0;
|
|
|
|
proc->types.pointer.drag_sum.x = 0;
|
|
|
|
proc->types.pointer.drag_sum.y = 0;
|
2019-12-31 22:13:32 +01:00
|
|
|
proc->types.pointer.drag_dir = LV_DRAG_DIR_BOTH;
|
2020-01-16 19:24:08 -05:00
|
|
|
proc->types.pointer.gesture_sent = 0;
|
|
|
|
proc->types.pointer.gesture_sum.x = 0;
|
|
|
|
proc->types.pointer.gesture_sum.y = 0;
|
2019-04-04 07:15:40 +02:00
|
|
|
proc->types.pointer.vect.x = 0;
|
|
|
|
proc->types.pointer.vect.y = 0;
|
2017-10-09 15:21:26 +02:00
|
|
|
|
|
|
|
/*Search for 'top' attribute*/
|
2019-05-21 15:49:50 +02:00
|
|
|
lv_obj_t * i = indev_obj_act;
|
2017-10-09 15:21:26 +02:00
|
|
|
lv_obj_t * last_top = NULL;
|
2018-06-19 09:49:58 +02:00
|
|
|
while(i != NULL) {
|
2019-05-09 15:55:01 +02:00
|
|
|
if(i->top) last_top = i;
|
2018-06-19 09:49:58 +02:00
|
|
|
i = lv_obj_get_parent(i);
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if(last_top != NULL) {
|
2018-06-19 09:49:58 +02:00
|
|
|
/*Move the last_top object to the foreground*/
|
2019-05-03 19:25:58 +02:00
|
|
|
lv_obj_move_foreground(last_top);
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*Send a signal about the press*/
|
2019-05-21 15:49:50 +02:00
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_PRESSED, indev_act);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2019-05-21 15:49:50 +02:00
|
|
|
|
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_PRESSED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2020-02-02 16:08:39 +01:00
|
|
|
|
2019-11-18 07:03:03 +01:00
|
|
|
if(indev_act->proc.wait_until_release) return;
|
2020-02-12 08:54:03 +01:00
|
|
|
|
|
|
|
/*Handle focus*/
|
|
|
|
indev_click_focus(&indev_act->proc);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
}
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2019-02-26 19:46:37 +01:00
|
|
|
/*Calculate the types.pointer.vector*/
|
|
|
|
proc->types.pointer.vect.x = proc->types.pointer.act_point.x - proc->types.pointer.last_point.x;
|
|
|
|
proc->types.pointer.vect.y = proc->types.pointer.act_point.y - proc->types.pointer.last_point.y;
|
2017-10-09 15:21:26 +02:00
|
|
|
|
2019-02-27 06:04:30 +01:00
|
|
|
proc->types.pointer.drag_throw_vect.x = (proc->types.pointer.drag_throw_vect.x * 5) >> 3;
|
|
|
|
proc->types.pointer.drag_throw_vect.y = (proc->types.pointer.drag_throw_vect.y * 5) >> 3;
|
2019-02-26 16:07:40 +01:00
|
|
|
|
2019-04-04 07:15:40 +02:00
|
|
|
if(proc->types.pointer.drag_throw_vect.x < 0)
|
|
|
|
proc->types.pointer.drag_throw_vect.x++;
|
|
|
|
else if(proc->types.pointer.drag_throw_vect.x > 0)
|
|
|
|
proc->types.pointer.drag_throw_vect.x--;
|
2019-02-26 16:07:40 +01:00
|
|
|
|
2019-04-04 07:15:40 +02:00
|
|
|
if(proc->types.pointer.drag_throw_vect.y < 0)
|
|
|
|
proc->types.pointer.drag_throw_vect.y++;
|
|
|
|
else if(proc->types.pointer.drag_throw_vect.y > 0)
|
|
|
|
proc->types.pointer.drag_throw_vect.y--;
|
2019-02-26 16:07:40 +01:00
|
|
|
|
2019-02-27 06:04:30 +01:00
|
|
|
proc->types.pointer.drag_throw_vect.x += (proc->types.pointer.vect.x * 4) >> 3;
|
|
|
|
proc->types.pointer.drag_throw_vect.y += (proc->types.pointer.vect.y * 4) >> 3;
|
2019-02-26 16:07:40 +01:00
|
|
|
|
2017-10-12 16:59:09 +02:00
|
|
|
/*If there is active object and it can be dragged run the drag*/
|
2019-05-21 15:49:50 +02:00
|
|
|
if(indev_obj_act != NULL) {
|
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_PRESSING, indev_act);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2019-05-21 15:49:50 +02:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_PRESSING, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2019-11-18 07:03:03 +01:00
|
|
|
if(indev_act->proc.wait_until_release) return;
|
2017-10-09 15:21:26 +02:00
|
|
|
|
2018-02-24 13:17:39 +01:00
|
|
|
indev_drag(proc);
|
2020-01-16 19:24:08 -05:00
|
|
|
indev_gesture(proc);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2017-10-09 15:21:26 +02:00
|
|
|
|
2017-10-12 16:59:09 +02:00
|
|
|
/*If there is no drag then check for long press time*/
|
2019-02-26 19:46:37 +01:00
|
|
|
if(proc->types.pointer.drag_in_prog == 0 && proc->long_pr_sent == 0) {
|
2017-10-12 16:59:09 +02:00
|
|
|
/*Send a signal about the long press if enough time elapsed*/
|
2019-04-02 12:15:35 +02:00
|
|
|
if(lv_tick_elaps(proc->pr_timestamp) > indev_act->driver.long_press_time) {
|
2019-05-21 15:49:50 +02:00
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_LONG_PRESS, indev_act);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2019-05-21 15:49:50 +02:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2017-10-09 15:21:26 +02:00
|
|
|
|
2017-10-12 16:59:09 +02:00
|
|
|
/*Mark the signal sending to do not send it again*/
|
2018-02-24 13:17:39 +01:00
|
|
|
proc->long_pr_sent = 1;
|
2017-10-12 16:59:09 +02:00
|
|
|
|
|
|
|
/*Save the long press time stamp for the long press repeat handler*/
|
2018-02-24 13:17:39 +01:00
|
|
|
proc->longpr_rep_timestamp = lv_tick_get();
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
2017-10-12 16:59:09 +02:00
|
|
|
}
|
|
|
|
/*Send long press repeated signal*/
|
2019-02-26 19:46:37 +01:00
|
|
|
if(proc->types.pointer.drag_in_prog == 0 && proc->long_pr_sent == 1) {
|
2019-05-21 15:49:50 +02:00
|
|
|
/*Send a signal about the long press repeat if enough time elapsed*/
|
2019-04-02 12:15:35 +02:00
|
|
|
if(lv_tick_elaps(proc->longpr_rep_timestamp) > indev_act->driver.long_press_rep_time) {
|
2019-05-21 15:49:50 +02:00
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_LONG_PRESS_REP, indev_act);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2019-05-21 15:49:50 +02:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED_REPEAT, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2018-02-24 13:17:39 +01:00
|
|
|
proc->longpr_rep_timestamp = lv_tick_get();
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-02-24 13:17:39 +01:00
|
|
|
* Process the released state of LV_INDEV_TYPE_POINER input devices
|
|
|
|
* @param proc pointer to an input device 'proc'
|
2017-10-09 15:21:26 +02:00
|
|
|
*/
|
2018-02-24 13:17:39 +01:00
|
|
|
static void indev_proc_release(lv_indev_proc_t * proc)
|
2017-10-09 15:21:26 +02:00
|
|
|
{
|
2019-03-22 06:35:17 +01:00
|
|
|
if(proc->wait_until_release != 0) {
|
2019-04-04 07:15:40 +02:00
|
|
|
proc->types.pointer.act_obj = NULL;
|
2019-02-26 19:46:37 +01:00
|
|
|
proc->types.pointer.last_obj = NULL;
|
2019-04-04 07:15:40 +02:00
|
|
|
proc->pr_timestamp = 0;
|
|
|
|
proc->longpr_rep_timestamp = 0;
|
|
|
|
proc->wait_until_release = 0;
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
2019-05-21 15:49:50 +02:00
|
|
|
indev_obj_act = proc->types.pointer.act_obj;
|
2017-10-09 15:21:26 +02:00
|
|
|
|
2019-03-03 11:20:49 +01:00
|
|
|
/*Forget the act obj and send a released signal */
|
2019-05-21 15:49:50 +02:00
|
|
|
if(indev_obj_act) {
|
2019-09-17 14:38:55 +02:00
|
|
|
|
2018-09-13 22:49:16 +02:00
|
|
|
/* If the object was protected against press lost then it possible that
|
2019-03-02 01:49:08 +01:00
|
|
|
* the object is already not pressed but still it is the `act_obj`.
|
2019-04-04 07:15:40 +02:00
|
|
|
* In this case send the `LV_SIGNAL_RELEASED/CLICKED` instead of `LV_SIGNAL_PRESS_LOST` if
|
|
|
|
* the indev is ON the `types.pointer.act_obj` */
|
2019-05-21 15:49:50 +02:00
|
|
|
if(lv_obj_is_protected(indev_obj_act, LV_PROTECT_PRESS_LOST)) {
|
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_RELEASED, indev_act);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2019-03-09 05:51:33 +01:00
|
|
|
|
2019-04-04 16:44:16 +02:00
|
|
|
if(proc->types.pointer.drag_in_prog == 0) {
|
|
|
|
if(proc->long_pr_sent == 0) {
|
2019-05-21 15:49:50 +02:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2019-04-04 16:44:16 +02:00
|
|
|
}
|
2019-03-09 05:51:33 +01:00
|
|
|
|
2019-05-21 15:49:50 +02:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_CLICKED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2019-02-26 09:25:46 +01:00
|
|
|
}
|
2019-03-07 00:05:16 +01:00
|
|
|
|
2019-05-21 15:49:50 +02:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_RELEASED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2018-09-13 22:49:16 +02:00
|
|
|
}
|
2019-03-07 00:05:16 +01:00
|
|
|
/* The simple case: `act_obj` was not protected against press lost.
|
2019-06-16 07:51:36 +02:00
|
|
|
* If it is already not pressed then `indev_proc_press` would set `indev_obj_act = NULL`*/
|
2018-09-13 22:49:16 +02:00
|
|
|
else {
|
2019-05-21 15:49:50 +02:00
|
|
|
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_RELEASED, indev_act);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2019-02-26 16:07:40 +01:00
|
|
|
|
2019-02-27 06:04:30 +01:00
|
|
|
if(proc->long_pr_sent == 0 && proc->types.pointer.drag_in_prog == 0) {
|
2019-05-21 15:49:50 +02:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2019-02-26 09:25:46 +01:00
|
|
|
}
|
2019-03-07 00:05:16 +01:00
|
|
|
|
2019-07-26 13:22:09 +02:00
|
|
|
if(proc->types.pointer.drag_in_prog == 0) {
|
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_CLICKED, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
}
|
2019-03-07 00:05:16 +01:00
|
|
|
|
2019-05-21 15:49:50 +02:00
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_RELEASED, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2018-09-13 22:49:16 +02:00
|
|
|
}
|
2018-10-15 19:33:34 +02:00
|
|
|
|
2019-06-16 07:51:36 +02:00
|
|
|
/*Send LV_EVENT_DRAG_THROW_BEGIN if required */
|
|
|
|
/*If drag parent is active check recursively the drag_parent attribute*/
|
2019-09-17 14:38:55 +02:00
|
|
|
lv_obj_t * drag_obj = get_dragged_obj(indev_obj_act);
|
2019-06-16 07:51:36 +02:00
|
|
|
if(drag_obj) {
|
|
|
|
if(lv_obj_get_drag_throw(drag_obj) && proc->types.pointer.drag_in_prog) {
|
2019-09-19 14:58:07 +02:00
|
|
|
if(drag_obj->signal_cb) drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_THROW_BEGIN, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
|
2019-06-16 07:51:36 +02:00
|
|
|
lv_event_send(drag_obj, LV_EVENT_DRAG_THROW_BEGIN, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-26 19:46:37 +01:00
|
|
|
proc->types.pointer.act_obj = NULL;
|
2019-04-04 07:15:40 +02:00
|
|
|
proc->pr_timestamp = 0;
|
|
|
|
proc->longpr_rep_timestamp = 0;
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
2018-06-19 09:49:58 +02:00
|
|
|
|
|
|
|
/*The reset can be set in the signal function.
|
2017-10-09 15:21:26 +02:00
|
|
|
* In case of reset query ignore the remaining parts.*/
|
2019-02-26 19:46:37 +01:00
|
|
|
if(proc->types.pointer.last_obj != NULL && proc->reset_query == 0) {
|
2018-02-24 13:17:39 +01:00
|
|
|
indev_drag_throw(proc);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-07 13:07:00 +01:00
|
|
|
/**
|
|
|
|
* Process a new point from LV_INDEV_TYPE_BUTTON input device
|
|
|
|
* @param i pointer to an input device
|
|
|
|
* @param data pointer to the data read from the input device
|
|
|
|
* Reset input device if a reset query has been sent to it
|
|
|
|
* @param indev pointer to an input device
|
|
|
|
*/
|
|
|
|
static void indev_proc_reset_query_handler(lv_indev_t * indev)
|
|
|
|
{
|
|
|
|
if(indev->proc.reset_query) {
|
2019-04-04 07:15:40 +02:00
|
|
|
indev->proc.types.pointer.act_obj = NULL;
|
|
|
|
indev->proc.types.pointer.last_obj = NULL;
|
|
|
|
indev->proc.types.pointer.drag_limit_out = 0;
|
|
|
|
indev->proc.types.pointer.drag_in_prog = 0;
|
|
|
|
indev->proc.long_pr_sent = 0;
|
|
|
|
indev->proc.pr_timestamp = 0;
|
|
|
|
indev->proc.longpr_rep_timestamp = 0;
|
|
|
|
indev->proc.types.pointer.drag_sum.x = 0;
|
|
|
|
indev->proc.types.pointer.drag_sum.y = 0;
|
2019-12-31 22:13:32 +01:00
|
|
|
indev->proc.types.pointer.drag_dir = LV_DRAG_DIR_BOTH;
|
2019-02-27 06:04:30 +01:00
|
|
|
indev->proc.types.pointer.drag_throw_vect.x = 0;
|
|
|
|
indev->proc.types.pointer.drag_throw_vect.y = 0;
|
2020-01-16 19:24:08 -05:00
|
|
|
indev->proc.types.pointer.gesture_sum.x = 0;
|
|
|
|
indev->proc.types.pointer.gesture_sum.y = 0;
|
2019-04-04 07:15:40 +02:00
|
|
|
indev->proc.reset_query = 0;
|
2019-06-06 06:05:40 +02:00
|
|
|
indev_obj_act = NULL;
|
2018-03-07 13:07:00 +01:00
|
|
|
}
|
|
|
|
}
|
2017-10-09 15:21:26 +02:00
|
|
|
/**
|
2019-12-09 04:21:56 +07:00
|
|
|
* Search the most top, clickable object by a point
|
2017-10-09 15:21:26 +02:00
|
|
|
* @param obj pointer to a start object, typically the screen
|
2019-12-09 04:21:56 +07:00
|
|
|
* @param point pointer to a point for searhing the most top child
|
2018-06-19 09:49:58 +02:00
|
|
|
* @return pointer to the found object or NULL if there was no suitable object
|
2017-10-09 15:21:26 +02:00
|
|
|
*/
|
2020-02-26 19:48:27 +01:00
|
|
|
lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point)
|
2017-10-09 15:21:26 +02:00
|
|
|
{
|
|
|
|
lv_obj_t * found_p = NULL;
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2019-04-11 06:26:41 +02:00
|
|
|
/*If the point is on this object check its children too*/
|
2019-12-22 13:51:02 +00:00
|
|
|
if(lv_obj_hittest(obj, point)) {
|
2017-10-09 15:21:26 +02:00
|
|
|
lv_obj_t * i;
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2020-02-26 19:48:27 +01:00
|
|
|
LV_LL_READ(obj->child_ll, i) {
|
2019-12-09 04:21:56 +07:00
|
|
|
found_p = lv_indev_search_obj(i, point);
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2017-10-09 15:21:26 +02:00
|
|
|
/*If a child was found then break*/
|
|
|
|
if(found_p != NULL) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2017-11-30 14:46:16 +01:00
|
|
|
/*If then the children was not ok, and this obj is clickable
|
2017-10-09 15:21:26 +02:00
|
|
|
* and it or its parent is not hidden then save this object*/
|
2020-03-10 18:29:41 +01:00
|
|
|
if(found_p == NULL && lv_obj_get_click(obj) != false) {
|
2018-06-19 09:49:58 +02:00
|
|
|
lv_obj_t * hidden_i = obj;
|
|
|
|
while(hidden_i != NULL) {
|
|
|
|
if(lv_obj_get_hidden(hidden_i) == true) break;
|
|
|
|
hidden_i = lv_obj_get_parent(hidden_i);
|
|
|
|
}
|
|
|
|
/*No parent found with hidden == true*/
|
|
|
|
if(hidden_i == NULL) found_p = obj;
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
}
|
2018-06-19 09:49:58 +02:00
|
|
|
|
|
|
|
return found_p;
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
|
2020-02-02 16:08:39 +01:00
|
|
|
/**
|
|
|
|
* Handle focus/defocus on click for POINTER inpt devices
|
|
|
|
* @param proc pointer to the state of the indev
|
|
|
|
*/
|
|
|
|
static void indev_click_focus(lv_indev_proc_t * proc)
|
|
|
|
{
|
|
|
|
/*Handle click focus*/
|
|
|
|
if(lv_obj_is_protected(indev_obj_act, LV_PROTECT_CLICK_FOCUS) == false &&
|
2020-02-26 19:48:27 +01:00
|
|
|
proc->types.pointer.last_pressed != indev_obj_act) {
|
2020-02-02 16:08:39 +01:00
|
|
|
#if LV_USE_GROUP
|
|
|
|
lv_group_t * g_act = lv_obj_get_group(indev_obj_act);
|
|
|
|
lv_group_t * g_prev = proc->types.pointer.last_pressed ? lv_obj_get_group(proc->types.pointer.last_pressed) : NULL;
|
|
|
|
|
|
|
|
/*If both the last and act. obj. are in the same group (or no group but it's also the same) */
|
|
|
|
if(g_act == g_prev) {
|
|
|
|
/*The objects are in a group*/
|
|
|
|
if(g_act) {
|
|
|
|
lv_group_focus_obj(indev_obj_act);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
}
|
|
|
|
/*The object are not in group*/
|
|
|
|
else {
|
|
|
|
if(proc->types.pointer.last_pressed) {
|
|
|
|
lv_signal_send(proc->types.pointer.last_pressed, LV_SIGNAL_DEFOCUS, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
}
|
|
|
|
|
|
|
|
lv_signal_send(indev_obj_act, LV_SIGNAL_FOCUS, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_FOCUSED, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*The object are not in the same group (in different group or one in not a group)*/
|
|
|
|
else {
|
|
|
|
/*Focus to the act. its group*/
|
|
|
|
if(g_act) {
|
|
|
|
lv_group_focus_obj(indev_obj_act);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
}
|
|
|
|
/*If the prev. obj. is not in a group then defocus it.*/
|
|
|
|
if(g_prev == NULL && proc->types.pointer.last_pressed) {
|
|
|
|
lv_signal_send(proc->types.pointer.last_pressed, LV_SIGNAL_DEFOCUS, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
}
|
|
|
|
/*Focus on a non-group object*/
|
|
|
|
else {
|
|
|
|
if(proc->types.pointer.last_pressed) {
|
|
|
|
/*If the prev. object also wasn't in a group defocus it*/
|
|
|
|
if(g_prev == NULL) {
|
|
|
|
lv_signal_send(proc->types.pointer.last_pressed, LV_SIGNAL_DEFOCUS, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
}
|
|
|
|
/*If the prev. object also was in a group at least "LEAVE" it instead of defocus*/
|
|
|
|
else {
|
|
|
|
lv_signal_send(proc->types.pointer.last_pressed, LV_SIGNAL_LEAVE, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_LEAVE, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lv_signal_send(indev_obj_act, LV_SIGNAL_FOCUS, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_FOCUSED, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if(proc->types.pointer.last_pressed) {
|
|
|
|
lv_signal_send(proc->types.pointer.last_pressed, LV_SIGNAL_DEFOCUS, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
lv_event_send(proc->types.pointer.last_pressed, LV_EVENT_DEFOCUSED, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
}
|
|
|
|
|
|
|
|
lv_signal_send(indev_obj_act, LV_SIGNAL_FOCUS, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
lv_event_send(indev_obj_act, LV_EVENT_FOCUSED, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
#endif
|
|
|
|
proc->types.pointer.last_pressed = indev_obj_act;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-10-09 15:21:26 +02:00
|
|
|
/**
|
2019-02-26 19:46:37 +01:00
|
|
|
* Handle the dragging of indev_proc_p->types.pointer.act_obj
|
2017-10-09 15:21:26 +02:00
|
|
|
* @param indev pointer to a input device state
|
|
|
|
*/
|
2019-09-17 16:07:30 +02:00
|
|
|
static void indev_drag(lv_indev_proc_t * proc)
|
2017-10-09 15:21:26 +02:00
|
|
|
{
|
2019-09-17 16:07:30 +02:00
|
|
|
lv_obj_t * drag_obj = get_dragged_obj(proc->types.pointer.act_obj);
|
2019-04-09 16:57:33 -04:00
|
|
|
bool drag_just_started = false;
|
2018-06-19 09:49:58 +02:00
|
|
|
|
|
|
|
if(drag_obj == NULL) return;
|
2017-10-09 15:21:26 +02:00
|
|
|
|
|
|
|
if(lv_obj_get_drag(drag_obj) == false) return;
|
|
|
|
|
2019-09-18 16:03:29 +02:00
|
|
|
|
2019-04-05 08:48:39 -04:00
|
|
|
lv_drag_dir_t allowed_dirs = lv_obj_get_drag_dir(drag_obj);
|
2019-04-04 21:51:13 -04:00
|
|
|
|
2018-11-25 12:02:16 +01:00
|
|
|
/*Count the movement by drag*/
|
2019-09-17 16:07:30 +02:00
|
|
|
if(proc->types.pointer.drag_limit_out == 0) {
|
|
|
|
proc->types.pointer.drag_sum.x += proc->types.pointer.vect.x;
|
|
|
|
proc->types.pointer.drag_sum.y += proc->types.pointer.vect.y;
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2019-11-03 15:45:24 +01:00
|
|
|
/*Enough move?*/
|
2019-09-17 14:38:55 +02:00
|
|
|
bool hor_en = false;
|
|
|
|
bool ver_en = false;
|
2019-09-17 16:07:30 +02:00
|
|
|
if(allowed_dirs == LV_DRAG_DIR_HOR || allowed_dirs == LV_DRAG_DIR_BOTH) {
|
2019-09-17 14:38:55 +02:00
|
|
|
hor_en = true;
|
|
|
|
}
|
|
|
|
|
2019-09-17 16:07:30 +02:00
|
|
|
if(allowed_dirs == LV_DRAG_DIR_VER || allowed_dirs == LV_DRAG_DIR_BOTH) {
|
2019-09-17 14:38:55 +02:00
|
|
|
ver_en = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(allowed_dirs == LV_DRAG_DIR_ONE) {
|
2019-09-17 16:07:30 +02:00
|
|
|
if(LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y)) {
|
2019-09-17 14:38:55 +02:00
|
|
|
hor_en = true;
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else {
|
2019-09-17 14:38:55 +02:00
|
|
|
ver_en = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-09 15:21:26 +02:00
|
|
|
/*If a move is greater then LV_DRAG_LIMIT then begin the drag*/
|
2019-09-17 16:07:30 +02:00
|
|
|
if((hor_en && LV_MATH_ABS(proc->types.pointer.drag_sum.x) >= indev_act->driver.drag_limit) ||
|
|
|
|
(ver_en && LV_MATH_ABS(proc->types.pointer.drag_sum.y) >= indev_act->driver.drag_limit)) {
|
|
|
|
proc->types.pointer.drag_limit_out = 1;
|
2019-04-10 08:40:52 +02:00
|
|
|
drag_just_started = true;
|
2018-06-19 09:49:58 +02:00
|
|
|
}
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2019-02-26 16:07:40 +01:00
|
|
|
/*If the drag limit is exceeded handle the dragging*/
|
2019-09-17 16:07:30 +02:00
|
|
|
if(proc->types.pointer.drag_limit_out != 0) {
|
2017-10-09 15:21:26 +02:00
|
|
|
/*Set new position if the vector is not zero*/
|
2019-09-17 16:07:30 +02:00
|
|
|
if(proc->types.pointer.vect.x != 0 || proc->types.pointer.vect.y != 0) {
|
2019-02-27 06:04:30 +01:00
|
|
|
|
2019-04-04 07:15:40 +02:00
|
|
|
lv_coord_t prev_x = drag_obj->coords.x1;
|
|
|
|
lv_coord_t prev_y = drag_obj->coords.y1;
|
2019-01-31 03:17:15 +01:00
|
|
|
lv_coord_t prev_par_w = lv_obj_get_width(lv_obj_get_parent(drag_obj));
|
|
|
|
lv_coord_t prev_par_h = lv_obj_get_height(lv_obj_get_parent(drag_obj));
|
2018-04-03 12:21:07 +02:00
|
|
|
|
2018-02-24 15:36:06 +01:00
|
|
|
/*Get the coordinates of the object and modify them*/
|
2019-04-10 06:21:54 +02:00
|
|
|
lv_coord_t act_x = lv_obj_get_x(drag_obj);
|
|
|
|
lv_coord_t act_y = lv_obj_get_y(drag_obj);
|
2017-10-09 15:21:26 +02:00
|
|
|
|
2019-09-17 16:07:30 +02:00
|
|
|
if(allowed_dirs == LV_DRAG_DIR_BOTH) {
|
2019-04-09 16:57:33 -04:00
|
|
|
if(drag_just_started) {
|
2019-09-17 16:07:30 +02:00
|
|
|
proc->types.pointer.drag_dir = LV_DRAG_DIR_BOTH;
|
|
|
|
act_x += proc->types.pointer.drag_sum.x;
|
|
|
|
act_y += proc->types.pointer.drag_sum.y;
|
2019-04-09 16:57:33 -04:00
|
|
|
}
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else if(allowed_dirs == LV_DRAG_DIR_HOR) {
|
2019-04-09 16:57:33 -04:00
|
|
|
if(drag_just_started) {
|
2019-09-17 16:07:30 +02:00
|
|
|
proc->types.pointer.drag_dir = LV_DRAG_DIR_HOR;
|
|
|
|
proc->types.pointer.drag_sum.y = 0;
|
|
|
|
act_x += proc->types.pointer.drag_sum.x;
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else if(allowed_dirs == LV_DRAG_DIR_VER) {
|
2019-04-09 16:57:33 -04:00
|
|
|
if(drag_just_started) {
|
2019-09-17 16:07:30 +02:00
|
|
|
proc->types.pointer.drag_dir = LV_DRAG_DIR_VER;
|
|
|
|
proc->types.pointer.drag_sum.x = 0;
|
|
|
|
act_y += proc->types.pointer.drag_sum.y;
|
2019-04-09 16:57:33 -04:00
|
|
|
}
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else if(allowed_dirs == LV_DRAG_DIR_ONE) {
|
2019-09-17 14:38:55 +02:00
|
|
|
if(drag_just_started) {
|
2019-09-17 16:07:30 +02:00
|
|
|
if(LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y)) {
|
|
|
|
proc->types.pointer.drag_dir = LV_DRAG_DIR_HOR;
|
|
|
|
proc->types.pointer.drag_sum.y = 0;
|
|
|
|
act_x += proc->types.pointer.drag_sum.x;
|
2020-02-26 19:48:27 +01:00
|
|
|
}
|
|
|
|
else {
|
2019-09-17 16:07:30 +02:00
|
|
|
proc->types.pointer.drag_dir = LV_DRAG_DIR_VER;
|
|
|
|
proc->types.pointer.drag_sum.x = 0;
|
|
|
|
act_y += proc->types.pointer.drag_sum.y;
|
2019-09-17 14:38:55 +02:00
|
|
|
}
|
|
|
|
}
|
2019-10-31 08:51:34 +01:00
|
|
|
}
|
2019-09-17 14:38:55 +02:00
|
|
|
|
2019-11-03 15:45:24 +01:00
|
|
|
/*Move the object*/
|
|
|
|
if(allowed_dirs == LV_DRAG_DIR_HOR ||
|
|
|
|
allowed_dirs == LV_DRAG_DIR_BOTH ||
|
|
|
|
(allowed_dirs == LV_DRAG_DIR_ONE &&
|
|
|
|
LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y))) {
|
|
|
|
act_x += proc->types.pointer.vect.x;
|
|
|
|
}
|
|
|
|
if(allowed_dirs == LV_DRAG_DIR_VER ||
|
|
|
|
allowed_dirs == LV_DRAG_DIR_BOTH ||
|
|
|
|
(allowed_dirs == LV_DRAG_DIR_ONE &&
|
|
|
|
LV_MATH_ABS(proc->types.pointer.drag_sum.x) < LV_MATH_ABS(proc->types.pointer.drag_sum.y))) {
|
|
|
|
act_y += proc->types.pointer.vect.y;
|
|
|
|
}
|
|
|
|
|
2020-01-24 14:55:56 +01:00
|
|
|
uint16_t inv_buf_size =
|
|
|
|
lv_disp_get_inv_buf_size(indev_act->driver.disp); /*Get the number of currently invalidated areas*/
|
|
|
|
|
2019-10-31 08:51:34 +01:00
|
|
|
lv_obj_set_pos(drag_obj, act_x, act_y);
|
|
|
|
proc->types.pointer.drag_in_prog = 1;
|
2019-09-17 14:38:55 +02:00
|
|
|
|
2018-02-24 15:36:06 +01:00
|
|
|
/*If the object didn't moved then clear the invalidated areas*/
|
2019-04-08 13:50:58 -04:00
|
|
|
if(drag_obj->coords.x1 == prev_x && drag_obj->coords.y1 == prev_y) {
|
2019-01-31 03:17:15 +01:00
|
|
|
/*In a special case if the object is moved on a page and
|
|
|
|
* the scrollable has fit == true and the object is dragged of the page then
|
|
|
|
* while its coordinate is not changing only the parent's size is reduced */
|
|
|
|
lv_coord_t act_par_w = lv_obj_get_width(lv_obj_get_parent(drag_obj));
|
|
|
|
lv_coord_t act_par_h = lv_obj_get_height(lv_obj_get_parent(drag_obj));
|
|
|
|
if(act_par_w == prev_par_w && act_par_h == prev_par_h) {
|
2019-02-12 15:38:13 +01:00
|
|
|
uint16_t new_inv_buf_size = lv_disp_get_inv_buf_size(indev_act->driver.disp);
|
2019-06-06 06:05:40 +02:00
|
|
|
lv_disp_pop_from_inv_buf(indev_act->driver.disp, new_inv_buf_size - inv_buf_size);
|
2019-01-31 03:17:15 +01:00
|
|
|
}
|
2018-02-24 15:36:06 +01:00
|
|
|
}
|
2020-01-24 14:55:56 +01:00
|
|
|
|
|
|
|
/*Set the drag in progress flag*/
|
|
|
|
/*Send the drag begin signal on first move*/
|
|
|
|
if(drag_just_started) {
|
|
|
|
drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_BEGIN, indev_act);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
|
|
|
|
lv_event_send(drag_obj, LV_EVENT_DRAG_BEGIN, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
}
|
|
|
|
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle throwing by drag if the drag is ended
|
|
|
|
* @param indev pointer to an input device state
|
|
|
|
*/
|
2019-02-26 16:07:40 +01:00
|
|
|
static void indev_drag_throw(lv_indev_proc_t * proc)
|
2017-10-09 15:21:26 +02:00
|
|
|
{
|
2019-02-27 06:04:30 +01:00
|
|
|
if(proc->types.pointer.drag_in_prog == 0) return;
|
2017-10-09 15:21:26 +02:00
|
|
|
|
2019-09-17 14:38:55 +02:00
|
|
|
lv_obj_t * drag_obj = get_dragged_obj(proc->types.pointer.last_obj);
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2019-09-17 14:38:55 +02:00
|
|
|
if(drag_obj == NULL) return;
|
2017-10-09 15:21:26 +02:00
|
|
|
|
|
|
|
/*Return if the drag throw is not enabled*/
|
2018-06-19 09:49:58 +02:00
|
|
|
if(lv_obj_get_drag_throw(drag_obj) == false) {
|
2019-02-27 06:04:30 +01:00
|
|
|
proc->types.pointer.drag_in_prog = 0;
|
2019-02-26 09:25:46 +01:00
|
|
|
drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_END, indev_act);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2019-04-19 05:32:21 +02:00
|
|
|
|
|
|
|
lv_event_send(drag_obj, LV_EVENT_DRAG_END, NULL);
|
2017-10-09 15:21:26 +02:00
|
|
|
return;
|
|
|
|
}
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2019-04-05 08:48:39 -04:00
|
|
|
lv_drag_dir_t allowed_dirs = lv_obj_get_drag_dir(drag_obj);
|
2019-04-04 21:51:13 -04:00
|
|
|
|
2017-10-09 15:21:26 +02:00
|
|
|
/*Reduce the vectors*/
|
2019-04-04 07:15:40 +02:00
|
|
|
proc->types.pointer.drag_throw_vect.x =
|
|
|
|
proc->types.pointer.drag_throw_vect.x * (100 - indev_act->driver.drag_throw) / 100;
|
|
|
|
proc->types.pointer.drag_throw_vect.y =
|
|
|
|
proc->types.pointer.drag_throw_vect.y * (100 - indev_act->driver.drag_throw) / 100;
|
2018-06-19 09:49:58 +02:00
|
|
|
|
2019-04-04 07:15:40 +02:00
|
|
|
if(proc->types.pointer.drag_throw_vect.x != 0 || proc->types.pointer.drag_throw_vect.y != 0) {
|
2018-11-11 19:56:30 +01:00
|
|
|
/*Get the coordinates and modify them*/
|
|
|
|
lv_area_t coords_ori;
|
|
|
|
lv_obj_get_coords(drag_obj, &coords_ori);
|
2019-02-27 06:04:30 +01:00
|
|
|
lv_coord_t act_x = lv_obj_get_x(drag_obj) + proc->types.pointer.drag_throw_vect.x;
|
|
|
|
lv_coord_t act_y = lv_obj_get_y(drag_obj) + proc->types.pointer.drag_throw_vect.y;
|
2019-04-04 21:51:13 -04:00
|
|
|
|
2019-09-17 16:07:30 +02:00
|
|
|
if(allowed_dirs == LV_DRAG_DIR_BOTH) lv_obj_set_pos(drag_obj, act_x, act_y);
|
2019-09-17 14:38:55 +02:00
|
|
|
else if(allowed_dirs == LV_DRAG_DIR_HOR) lv_obj_set_x(drag_obj, act_x);
|
|
|
|
else if(allowed_dirs == LV_DRAG_DIR_VER) lv_obj_set_y(drag_obj, act_y);
|
|
|
|
else if(allowed_dirs == LV_DRAG_DIR_ONE) {
|
|
|
|
if(proc->types.pointer.drag_sum.x) lv_obj_set_x(drag_obj, act_x);
|
|
|
|
else lv_obj_set_y(drag_obj, act_y);
|
|
|
|
}
|
2018-11-11 19:56:30 +01:00
|
|
|
lv_area_t coord_new;
|
|
|
|
lv_obj_get_coords(drag_obj, &coord_new);
|
|
|
|
|
2017-11-06 16:27:00 +01:00
|
|
|
/*If non of the coordinates are changed then do not continue throwing*/
|
2019-02-27 06:04:30 +01:00
|
|
|
if((coords_ori.x1 == coord_new.x1 || proc->types.pointer.drag_throw_vect.x == 0) &&
|
2019-04-04 07:15:40 +02:00
|
|
|
(coords_ori.y1 == coord_new.y1 || proc->types.pointer.drag_throw_vect.y == 0)) {
|
|
|
|
proc->types.pointer.drag_in_prog = 0;
|
|
|
|
proc->types.pointer.vect.x = 0;
|
|
|
|
proc->types.pointer.vect.y = 0;
|
2019-02-27 06:04:30 +01:00
|
|
|
proc->types.pointer.drag_throw_vect.x = 0;
|
|
|
|
proc->types.pointer.drag_throw_vect.y = 0;
|
2019-02-26 09:25:46 +01:00
|
|
|
drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_END, indev_act);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2019-09-17 14:38:55 +02:00
|
|
|
|
2019-04-19 05:32:21 +02:00
|
|
|
lv_event_send(drag_obj, LV_EVENT_DRAG_END, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2017-11-06 16:27:00 +01:00
|
|
|
}
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
2019-04-04 07:15:40 +02:00
|
|
|
/*If the types.pointer.vectors become 0 -> types.pointer.drag_in_prog = 0 and send a drag end
|
|
|
|
signal*/
|
2017-10-09 15:21:26 +02:00
|
|
|
else {
|
2019-02-27 06:04:30 +01:00
|
|
|
proc->types.pointer.drag_in_prog = 0;
|
2019-02-26 09:25:46 +01:00
|
|
|
drag_obj->signal_cb(drag_obj, LV_SIGNAL_DRAG_END, indev_act);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2019-04-19 05:32:21 +02:00
|
|
|
lv_event_send(drag_obj, LV_EVENT_DRAG_END, NULL);
|
2019-05-20 09:52:18 -07:00
|
|
|
if(indev_reset_check(proc)) return;
|
2017-10-09 15:21:26 +02:00
|
|
|
}
|
|
|
|
}
|
2019-05-20 09:52:18 -07:00
|
|
|
|
2019-09-17 14:38:55 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the really dragged object by taking `drag_parent` into account.
|
|
|
|
* @param obj the start obejct
|
|
|
|
* @return the object to really drag
|
|
|
|
*/
|
|
|
|
static lv_obj_t * get_dragged_obj(lv_obj_t * obj)
|
|
|
|
{
|
2019-09-19 14:58:07 +02:00
|
|
|
if(obj == NULL) return NULL;
|
2019-09-17 14:38:55 +02:00
|
|
|
lv_obj_t * drag_obj = obj;
|
|
|
|
while(lv_obj_get_drag_parent(drag_obj) != false && drag_obj != NULL) {
|
|
|
|
drag_obj = lv_obj_get_parent(drag_obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
return drag_obj;
|
|
|
|
}
|
|
|
|
|
2020-01-16 19:24:08 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle the gesture of indev_proc_p->types.pointer.act_obj
|
|
|
|
* @param indev pointer to a input device state
|
|
|
|
*/
|
|
|
|
static void indev_gesture(lv_indev_proc_t * proc)
|
|
|
|
{
|
|
|
|
|
2020-02-26 19:48:27 +01:00
|
|
|
if(proc->types.pointer.drag_in_prog) return;
|
|
|
|
if(proc->types.pointer.gesture_sent) return;
|
|
|
|
|
|
|
|
lv_obj_t * gesture_obj = proc->types.pointer.act_obj;
|
|
|
|
|
|
|
|
/*If gesture parent is active check recursively the drag_parent attribute*/
|
|
|
|
while(gesture_obj && lv_obj_get_gesture_parent(gesture_obj)) {
|
|
|
|
gesture_obj = lv_obj_get_parent(gesture_obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(gesture_obj == NULL) return;
|
|
|
|
|
|
|
|
if((LV_MATH_ABS(proc->types.pointer.vect.x) < indev_act->driver.gesture_min_velocity) &&
|
|
|
|
(LV_MATH_ABS(proc->types.pointer.vect.y) < indev_act->driver.gesture_min_velocity)) {
|
|
|
|
proc->types.pointer.gesture_sum.x = 0;
|
|
|
|
proc->types.pointer.gesture_sum.y = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*Count the movement by gesture*/
|
|
|
|
proc->types.pointer.gesture_sum.x += proc->types.pointer.vect.x;
|
|
|
|
proc->types.pointer.gesture_sum.y += proc->types.pointer.vect.y;
|
|
|
|
|
|
|
|
if((LV_MATH_ABS(proc->types.pointer.gesture_sum.x) > indev_act->driver.gesture_limit) ||
|
|
|
|
(LV_MATH_ABS(proc->types.pointer.gesture_sum.y) > indev_act->driver.gesture_limit)) {
|
|
|
|
|
|
|
|
proc->types.pointer.gesture_sent = 1;
|
|
|
|
|
|
|
|
if(LV_MATH_ABS(proc->types.pointer.gesture_sum.x) > LV_MATH_ABS(proc->types.pointer.gesture_sum.y)) {
|
|
|
|
if(proc->types.pointer.gesture_sum.x > 0)
|
|
|
|
proc->types.pointer.gesture_dir = LV_GESTURE_DIR_RIGHT;
|
|
|
|
else
|
|
|
|
proc->types.pointer.gesture_dir = LV_GESTURE_DIR_LEFT;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(proc->types.pointer.gesture_sum.y > 0)
|
|
|
|
proc->types.pointer.gesture_dir = LV_GESTURE_DIR_BOTTOM;
|
|
|
|
else
|
|
|
|
proc->types.pointer.gesture_dir = LV_GESTURE_DIR_TOP;
|
|
|
|
}
|
|
|
|
|
|
|
|
gesture_obj->signal_cb(gesture_obj, LV_SIGNAL_GESTURE, indev_act);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
lv_event_send(gesture_obj, LV_EVENT_GESTURE, NULL);
|
|
|
|
if(indev_reset_check(proc)) return;
|
|
|
|
}
|
2020-01-16 19:24:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-05-20 09:52:18 -07:00
|
|
|
/**
|
|
|
|
* Checks if the reset_query flag has been set. If so, perform necessary global indev cleanup actions
|
|
|
|
* @param proc pointer to an input device 'proc'
|
2020-01-28 22:15:45 +01:00
|
|
|
* @return true if indev query should be immediately truncated.
|
2019-05-20 09:52:18 -07:00
|
|
|
*/
|
2019-06-06 06:05:40 +02:00
|
|
|
static bool indev_reset_check(lv_indev_proc_t * proc)
|
2019-05-21 15:49:50 +02:00
|
|
|
{
|
2019-05-20 09:52:18 -07:00
|
|
|
if(proc->reset_query) {
|
|
|
|
indev_obj_act = NULL;
|
|
|
|
}
|
2019-05-21 15:49:50 +02:00
|
|
|
|
|
|
|
return proc->reset_query ? true : false;
|
2019-05-20 09:52:18 -07:00
|
|
|
}
|