1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/notrynohigh-BabyOS

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
lv_indev.c 54 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
notrynohigh Отправлено 12 месяцев назад 8fe2fcd
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639
/**
* @file lv_indev.c
*
*/
/*********************
* INCLUDES
********************/
#include "lv_indev_private.h"
#include "lv_indev_scroll.h"
#include "../display/lv_display_private.h"
#include "../core/lv_global.h"
#include "../core/lv_obj.h"
#include "../core/lv_group.h"
#include "../core/lv_refr.h"
#include "../tick/lv_tick.h"
#include "../misc/lv_timer.h"
#include "../misc/lv_math.h"
#include "../misc/lv_profiler.h"
#include "../stdlib/lv_string.h"
/*********************
* DEFINES
*********************/
/*Drag threshold in pixels*/
#define LV_INDEV_DEF_SCROLL_LIMIT 10
/*Drag throw slow-down in [%]. Greater value -> faster slow-down*/
#define LV_INDEV_DEF_SCROLL_THROW 10
/*Long press time in milliseconds.
*Time to send `LV_EVENT_LONG_PRESSSED`)*/
#define LV_INDEV_DEF_LONG_PRESS_TIME 400
/*Repeated trigger period in long press [ms]
*Time between `LV_EVENT_LONG_PRESSED_REPEAT*/
#define LV_INDEV_DEF_LONG_PRESS_REP_TIME 100
/*Gesture threshold in pixels*/
#define LV_INDEV_DEF_GESTURE_LIMIT 50
/*Gesture min velocity at release before swipe (pixels)*/
#define LV_INDEV_DEF_GESTURE_MIN_VELOCITY 3
/**< Rotary diff count will be multiplied by this and divided by 256 */
#define LV_INDEV_DEF_ROTARY_SENSITIVITY 256
#if LV_INDEV_DEF_SCROLL_THROW <= 0
#warning "LV_INDEV_DEF_SCROLL_THROW must be greater than 0"
#endif
#define indev_act LV_GLOBAL_DEFAULT()->indev_active
#define indev_obj_act LV_GLOBAL_DEFAULT()->indev_obj_active
#define indev_ll_head &(LV_GLOBAL_DEFAULT()->indev_ll)
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
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);
static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data);
static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data);
static void indev_proc_press(lv_indev_t * indev);
static void indev_proc_release(lv_indev_t * indev);
static void indev_proc_pointer_diff(lv_indev_t * indev);
static lv_obj_t * pointer_search_obj(lv_display_t * disp, lv_point_t * p);
static void indev_proc_reset_query_handler(lv_indev_t * indev);
static void indev_click_focus(lv_indev_t * indev);
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 lv_result_t send_event(lv_event_code_t code, void * param);
static void indev_scroll_throw_anim_start(lv_indev_t * indev);
static void indev_scroll_throw_anim_cb(void * var, int32_t v);
static void indev_scroll_throw_anim_completed_cb(lv_anim_t * anim);
static inline void indev_scroll_throw_anim_reset(lv_indev_t * indev)
{
if(indev) {
indev->pointer.scroll_throw_vect.x = 0;
indev->pointer.scroll_throw_vect.y = 0;
indev->scroll_throw_anim = NULL;
}
}
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
#if LV_USE_LOG && LV_LOG_TRACE_INDEV
#define LV_TRACE_INDEV(...) LV_LOG_TRACE(__VA_ARGS__)
#else
#define LV_TRACE_INDEV(...)
#endif
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_indev_t * lv_indev_create(void)
{
lv_display_t * disp = lv_display_get_default();
if(disp == NULL) {
LV_LOG_WARN("no display was created so far");
}
lv_indev_t * indev = _lv_ll_ins_head(indev_ll_head);
LV_ASSERT_MALLOC(indev);
if(indev == NULL) {
return NULL;
}
lv_memzero(indev, sizeof(lv_indev_t));
indev->reset_query = 1;
indev->enabled = 1;
indev->read_timer = lv_timer_create(lv_indev_read_timer_cb, LV_DEF_REFR_PERIOD, indev);
indev->disp = lv_display_get_default();
indev->type = LV_INDEV_TYPE_NONE;
indev->mode = LV_INDEV_MODE_TIMER;
indev->scroll_limit = LV_INDEV_DEF_SCROLL_LIMIT;
indev->scroll_throw = LV_INDEV_DEF_SCROLL_THROW;
indev->long_press_time = LV_INDEV_DEF_LONG_PRESS_TIME;
indev->long_press_repeat_time = LV_INDEV_DEF_LONG_PRESS_REP_TIME;
indev->gesture_limit = LV_INDEV_DEF_GESTURE_LIMIT;
indev->gesture_min_velocity = LV_INDEV_DEF_GESTURE_MIN_VELOCITY;
indev->rotary_sensitvity = LV_INDEV_DEF_ROTARY_SENSITIVITY;
return indev;
}
void lv_indev_delete(lv_indev_t * indev)
{
LV_ASSERT_NULL(indev);
lv_indev_send_event(indev, LV_EVENT_DELETE, NULL);
lv_event_remove_all(&(indev->event_list));
/*Clean up the read timer first*/
if(indev->read_timer) lv_timer_delete(indev->read_timer);
/*Remove the input device from the list*/
_lv_ll_remove(indev_ll_head, indev);
/*Free the memory of the input device*/
lv_free(indev);
}
lv_indev_t * lv_indev_get_next(lv_indev_t * indev)
{
if(indev == NULL)
return _lv_ll_get_head(indev_ll_head);
else
return _lv_ll_get_next(indev_ll_head, indev);
}
void indev_read_core(lv_indev_t * indev, lv_indev_data_t * data)
{
LV_PROFILER_BEGIN;
lv_memzero(data, sizeof(lv_indev_data_t));
/* For touchpad sometimes users don't set the last pressed coordinate on release.
* So be sure a coordinates are initialized to the last point */
if(indev->type == LV_INDEV_TYPE_POINTER) {
data->point.x = indev->pointer.last_raw_point.x;
data->point.y = indev->pointer.last_raw_point.y;
}
/*Similarly set at least the last key in case of the user doesn't set it on release*/
else if(indev->type == LV_INDEV_TYPE_KEYPAD) {
data->key = indev->keypad.last_key;
}
/*For compatibility assume that used button was enter (encoder push)*/
else if(indev->type == LV_INDEV_TYPE_ENCODER) {
data->key = LV_KEY_ENTER;
}
if(indev->read_cb) {
LV_TRACE_INDEV("calling indev_read_cb");
indev->read_cb(indev, data);
}
else {
LV_LOG_WARN("indev_read_cb is not registered");
}
LV_PROFILER_END;
}
void lv_indev_read_timer_cb(lv_timer_t * timer)
{
lv_indev_read(timer->user_data);
}
void lv_indev_read(lv_indev_t * indev)
{
if(indev == NULL) return;
LV_TRACE_INDEV("begin");
indev_act = indev;
/*Read and process all indevs*/
if(indev->disp == NULL) return; /*Not assigned to any displays*/
/*Handle reset query before processing the point*/
indev_proc_reset_query_handler(indev);
if((indev->enabled == 0) ||
(indev->disp->prev_scr != NULL)) return; /*Input disabled or screen animation active*/
LV_PROFILER_BEGIN;
bool continue_reading;
lv_indev_data_t data;
do {
/*Read the data*/
indev_read_core(indev, &data);
continue_reading = indev->mode != LV_INDEV_MODE_EVENT && data.continue_reading;
/*The active object might be deleted even in the read function*/
indev_proc_reset_query_handler(indev);
indev_obj_act = NULL;
indev->state = data.state;
/*Save the last activity time*/
if(indev->state == LV_INDEV_STATE_PRESSED) {
indev->disp->last_activity_time = lv_tick_get();
}
else if(indev->type == LV_INDEV_TYPE_ENCODER && data.enc_diff) {
indev->disp->last_activity_time = lv_tick_get();
}
if(indev->type == LV_INDEV_TYPE_POINTER) {
indev_pointer_proc(indev, &data);
}
else if(indev->type == LV_INDEV_TYPE_KEYPAD) {
indev_keypad_proc(indev, &data);
}
else if(indev->type == LV_INDEV_TYPE_ENCODER) {
indev_encoder_proc(indev, &data);
}
else if(indev->type == LV_INDEV_TYPE_BUTTON) {
indev_button_proc(indev, &data);
}
/*Handle reset query if it happened in during processing*/
indev_proc_reset_query_handler(indev);
} while(continue_reading);
/*End of indev processing, so no act indev*/
indev_act = NULL;
indev_obj_act = NULL;
LV_TRACE_INDEV("finished");
LV_PROFILER_END;
}
void lv_indev_enable(lv_indev_t * indev, bool enable)
{
if(indev) {
indev->enabled = (uint8_t) enable;
}
else {
lv_indev_t * i = lv_indev_get_next(NULL);
while(i) {
i->enabled = (uint8_t) enable;
i = lv_indev_get_next(i);
}
}
}
lv_indev_t * lv_indev_active(void)
{
return indev_act;
}
void lv_indev_set_type(lv_indev_t * indev, lv_indev_type_t indev_type)
{
if(indev == NULL) return;
indev->type = indev_type;
indev->reset_query = 1;
}
void lv_indev_set_read_cb(lv_indev_t * indev, lv_indev_read_cb_t read_cb)
{
if(indev == NULL) return;
indev->read_cb = read_cb;
}
void lv_indev_set_user_data(lv_indev_t * indev, void * user_data)
{
if(indev == NULL) return;
indev->user_data = user_data;
}
void lv_indev_set_driver_data(lv_indev_t * indev, void * driver_data)
{
if(indev == NULL) return;
indev->driver_data = driver_data;
}
lv_indev_read_cb_t lv_indev_get_read_cb(lv_indev_t * indev)
{
if(indev == NULL) {
LV_LOG_WARN("lv_indev_get_read_cb: indev was NULL");
return NULL;
}
return indev->read_cb;
}
lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev)
{
if(indev == NULL) return LV_INDEV_TYPE_NONE;
return indev->type;
}
lv_indev_state_t lv_indev_get_state(const lv_indev_t * indev)
{
if(indev == NULL) return LV_INDEV_STATE_RELEASED;
return indev->state;
}
lv_group_t * lv_indev_get_group(const lv_indev_t * indev)
{
if(indev == NULL) return NULL;
return indev->group;
}
lv_display_t * lv_indev_get_display(const lv_indev_t * indev)
{
if(indev == NULL) return NULL;
return indev->disp;
}
void lv_indev_set_display(lv_indev_t * indev, lv_display_t * disp)
{
if(indev == NULL) return;
indev->disp = disp;
}
void * lv_indev_get_user_data(const lv_indev_t * indev)
{
if(indev == NULL) return NULL;
return indev->user_data;
}
void * lv_indev_get_driver_data(const lv_indev_t * indev)
{
if(indev == NULL) return NULL;
return indev->driver_data;
}
void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj)
{
if(indev) {
indev_reset_core(indev, obj);
}
else {
lv_indev_t * i = lv_indev_get_next(NULL);
while(i) {
indev_reset_core(i, obj);
i = lv_indev_get_next(i);
}
indev_obj_act = NULL;
}
}
void lv_indev_reset_long_press(lv_indev_t * indev)
{
indev->long_pr_sent = 0;
indev->longpr_rep_timestamp = lv_tick_get();
indev->pr_timestamp = lv_tick_get();
}
void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj)
{
if(indev->type != LV_INDEV_TYPE_POINTER) return;
indev->cursor = cur_obj;
lv_obj_set_parent(indev->cursor, lv_display_get_layer_sys(indev->disp));
lv_obj_set_pos(indev->cursor, indev->pointer.act_point.x, indev->pointer.act_point.y);
lv_obj_remove_flag(indev->cursor, LV_OBJ_FLAG_CLICKABLE);
lv_obj_add_flag(indev->cursor, LV_OBJ_FLAG_IGNORE_LAYOUT | LV_OBJ_FLAG_FLOATING);
}
void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group)
{
if(indev && (indev->type == LV_INDEV_TYPE_KEYPAD || indev->type == LV_INDEV_TYPE_ENCODER)) {
indev->group = group;
}
}
void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t points[])
{
if(indev && indev->type == LV_INDEV_TYPE_BUTTON) {
indev->btn_points = points;
}
}
void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point)
{
if(indev == NULL) {
point->x = 0;
point->y = 0;
}
else if(indev->type != LV_INDEV_TYPE_POINTER && indev->type != LV_INDEV_TYPE_BUTTON) {
point->x = -1;
point->y = -1;
}
else {
point->x = indev->pointer.act_point.x;
point->y = indev->pointer.act_point.y;
}
}
lv_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev)
{
return indev->pointer.gesture_dir;
}
uint32_t lv_indev_get_key(const lv_indev_t * indev)
{
uint32_t key = 0;
if(indev && indev->type == LV_INDEV_TYPE_KEYPAD)
key = indev->keypad.last_key;
return key;
}
lv_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev)
{
if(indev == NULL) return false;
if(indev->type != LV_INDEV_TYPE_POINTER && indev->type != LV_INDEV_TYPE_BUTTON) return false;
return indev->pointer.scroll_dir;
}
lv_obj_t * lv_indev_get_scroll_obj(const lv_indev_t * indev)
{
if(indev == NULL) return NULL;
if(indev->type != LV_INDEV_TYPE_POINTER && indev->type != LV_INDEV_TYPE_BUTTON) return NULL;
return indev->pointer.scroll_obj;
}
void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point)
{
point->x = 0;
point->y = 0;
if(indev == NULL) return;
if(indev->type == LV_INDEV_TYPE_POINTER || indev->type == LV_INDEV_TYPE_BUTTON) {
point->x = indev->pointer.vect.x;
point->y = indev->pointer.vect.y;
}
}
void lv_indev_wait_release(lv_indev_t * indev)
{
if(indev == NULL)return;
indev->wait_until_release = 1;
}
lv_obj_t * lv_indev_get_active_obj(void)
{
return indev_obj_act;
}
lv_timer_t * lv_indev_get_read_timer(lv_indev_t * indev)
{
if(indev == NULL) {
LV_LOG_WARN("lv_indev_get_read_timer: indev was NULL");
return NULL;
}
return indev->read_timer;
}
lv_indev_mode_t lv_indev_get_mode(lv_indev_t * indev)
{
if(indev) return indev->mode;
return LV_INDEV_MODE_NONE;
}
void lv_indev_set_mode(lv_indev_t * indev, lv_indev_mode_t mode)
{
if(indev == NULL || indev->mode == mode)
return;
indev->mode = mode;
if(indev->read_timer) {
if(mode == LV_INDEV_MODE_EVENT) {
lv_timer_pause(indev->read_timer);
}
else if(mode == LV_INDEV_MODE_TIMER) {
/* use default timer mode*/
lv_timer_set_cb(indev->read_timer, lv_indev_read_timer_cb);
lv_timer_resume(indev->read_timer);
}
}
}
lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point)
{
lv_obj_t * found_p = NULL;
/*If this obj is hidden the children are hidden too so return immediately*/
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return NULL;
lv_point_t p_trans = *point;
lv_obj_transform_point(obj, &p_trans, LV_OBJ_POINT_TRANSFORM_FLAG_INVERSE);
bool hit_test_ok = lv_obj_hit_test(obj, &p_trans);
/*If the point is on this object check its children too*/
lv_area_t obj_coords = obj->coords;
if(lv_obj_has_flag(obj, LV_OBJ_FLAG_OVERFLOW_VISIBLE)) {
int32_t ext_draw_size = _lv_obj_get_ext_draw_size(obj);
lv_area_increase(&obj_coords, ext_draw_size, ext_draw_size);
}
if(_lv_area_is_point_on(&obj_coords, &p_trans, 0)) {
int32_t i;
uint32_t child_cnt = lv_obj_get_child_count(obj);
/*If a child matches use it*/
for(i = child_cnt - 1; i >= 0; i--) {
lv_obj_t * child = obj->spec_attr->children[i];
found_p = lv_indev_search_obj(child, &p_trans);
if(found_p) return found_p;
}
}
/*If not return earlier for a clicked child and this obj's hittest was ok use it
*else return NULL*/
if(hit_test_ok) return obj;
else return NULL;
}
void lv_indev_add_event_cb(lv_indev_t * indev, lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data)
{
LV_ASSERT_NULL(indev);
lv_event_add(&indev->event_list, event_cb, filter, user_data);
}
uint32_t lv_indev_get_event_count(lv_indev_t * indev)
{
LV_ASSERT_NULL(indev);
return lv_event_get_count(&indev->event_list);
}
lv_event_dsc_t * lv_indev_get_event_dsc(lv_indev_t * indev, uint32_t index)
{
LV_ASSERT_NULL(indev);
return lv_event_get_dsc(&indev->event_list, index);
}
bool lv_indev_remove_event(lv_indev_t * indev, uint32_t index)
{
LV_ASSERT_NULL(indev);
return lv_event_remove(&indev->event_list, index);
}
uint32_t lv_indev_remove_event_cb_with_user_data(lv_indev_t * indev, lv_event_cb_t event_cb, void * user_data)
{
LV_ASSERT_NULL(indev);
uint32_t event_cnt = lv_indev_get_event_count(indev);
uint32_t removed_count = 0;
int32_t i;
for(i = event_cnt - 1; i >= 0; i--) {
lv_event_dsc_t * dsc = lv_indev_get_event_dsc(indev, i);
if(dsc && dsc->cb == event_cb && dsc->user_data == user_data) {
lv_indev_remove_event(indev, i);
removed_count ++;
}
}
return removed_count;
}
lv_result_t lv_indev_send_event(lv_indev_t * indev, lv_event_code_t code, void * param)
{
lv_event_t e;
lv_memzero(&e, sizeof(e));
e.code = code;
e.current_target = indev;
e.original_target = indev;
e.param = param;
lv_result_t res;
res = lv_event_send(&indev->event_list, &e, true);
if(res != LV_RESULT_OK) return res;
res = lv_event_send(&indev->event_list, &e, false);
if(res != LV_RESULT_OK) return res;
return res;
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* 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
*/
static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data)
{
lv_display_t * disp = i->disp;
/*Save the raw points so they can be used again in indev_read_core*/
i->pointer.last_raw_point.x = data->point.x;
i->pointer.last_raw_point.y = data->point.y;
if(disp->rotation == LV_DISPLAY_ROTATION_180 || disp->rotation == LV_DISPLAY_ROTATION_270) {
data->point.x = disp->hor_res - data->point.x - 1;
data->point.y = disp->ver_res - data->point.y - 1;
}
if(disp->rotation == LV_DISPLAY_ROTATION_90 || disp->rotation == LV_DISPLAY_ROTATION_270) {
int32_t tmp = data->point.y;
data->point.y = data->point.x;
data->point.x = disp->ver_res - tmp - 1;
}
/*Simple sanity check*/
if(data->point.x < 0) {
LV_LOG_WARN("X is %d which is smaller than zero", (int)data->point.x);
}
if(data->point.x >= lv_display_get_horizontal_resolution(i->disp)) {
LV_LOG_WARN("X is %d which is greater than hor. res", (int)data->point.x);
}
if(data->point.y < 0) {
LV_LOG_WARN("Y is %d which is smaller than zero", (int)data->point.y);
}
if(data->point.y >= lv_display_get_vertical_resolution(i->disp)) {
LV_LOG_WARN("Y is %d which is greater than ver. res", (int)data->point.y);
}
/*Move the cursor if set and moved*/
if(i->cursor != NULL &&
(i->pointer.last_point.x != data->point.x || i->pointer.last_point.y != data->point.y)) {
lv_obj_set_pos(i->cursor, data->point.x, data->point.y);
}
i->pointer.act_point.x = data->point.x;
i->pointer.act_point.y = data->point.y;
i->pointer.diff = data->enc_diff;
/*Process the diff first as scrolling will be processed in indev_proc_release*/
indev_proc_pointer_diff(i);
if(i->state == LV_INDEV_STATE_PRESSED) {
indev_proc_press(i);
}
else {
indev_proc_release(i);
}
i->pointer.last_point.x = i->pointer.act_point.x;
i->pointer.last_point.y = i->pointer.act_point.y;
}
/**
* 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)
{
if(data->state == LV_INDEV_STATE_PRESSED && i->wait_until_release) return;
if(i->wait_until_release) {
i->wait_until_release = 0;
i->pr_timestamp = 0;
i->long_pr_sent = 0;
i->keypad.last_state = LV_INDEV_STATE_RELEASED; /*To skip the processing of release*/
}
/*Save the last key. *It must be done here else `lv_indev_get_key` will return the last key in events*/
uint32_t prev_key = i->keypad.last_key;
i->keypad.last_key = data->key;
lv_group_t * g = i->group;
if(g == NULL) return;
indev_obj_act = lv_group_get_focused(g);
if(indev_obj_act == NULL) return;
const bool is_enabled = !lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED);
/*Save the previous state so we can detect state changes below and also set the last state now
*so if any event handler on the way returns `LV_RESULT_INVALID` the last state is remembered
*for the next time*/
uint32_t prev_state = i->keypad.last_state;
i->keypad.last_state = data->state;
/*Key press happened*/
if(data->state == LV_INDEV_STATE_PRESSED && prev_state == LV_INDEV_STATE_RELEASED) {
LV_LOG_INFO("%" LV_PRIu32 " key is pressed", data->key);
i->pr_timestamp = lv_tick_get();
/*Move the focus on NEXT*/
if(data->key == LV_KEY_NEXT) {
lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/
lv_group_focus_next(g);
if(indev_reset_check(i)) return;
}
/*Move the focus on PREV*/
else if(data->key == LV_KEY_PREV) {
lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/
lv_group_focus_prev(g);
if(indev_reset_check(i)) return;
}
else if(is_enabled) {
/*Simulate a press on the object if ENTER was pressed*/
if(data->key == LV_KEY_ENTER) {
/*Send the ENTER as a normal KEY*/
lv_group_send_data(g, LV_KEY_ENTER);
if(indev_reset_check(i)) return;
if(send_event(LV_EVENT_PRESSED, indev_act) == LV_RESULT_INVALID) return;
}
else if(data->key == LV_KEY_ESC) {
/*Send the ESC as a normal KEY*/
lv_group_send_data(g, LV_KEY_ESC);
if(indev_reset_check(i)) return;
if(send_event(LV_EVENT_CANCEL, indev_act) == LV_RESULT_INVALID) return;
}
/*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/
else {
lv_group_send_data(g, data->key);
if(indev_reset_check(i)) return;
}
}
}
/*Pressing*/
else if(is_enabled && data->state == LV_INDEV_STATE_PRESSED && prev_state == LV_INDEV_STATE_PRESSED) {
if(data->key == LV_KEY_ENTER) {
if(send_event(LV_EVENT_PRESSING, indev_act) == LV_RESULT_INVALID) return;
}
/*Long press time has elapsed?*/
if(i->long_pr_sent == 0 && lv_tick_elaps(i->pr_timestamp) > i->long_press_time) {
i->long_pr_sent = 1;
if(data->key == LV_KEY_ENTER) {
i->longpr_rep_timestamp = lv_tick_get();
if(send_event(LV_EVENT_LONG_PRESSED, indev_act) == LV_RESULT_INVALID) return;
}
}
/*Long press repeated time has elapsed?*/
else if(i->long_pr_sent != 0 &&
lv_tick_elaps(i->longpr_rep_timestamp) > i->long_press_repeat_time) {
i->longpr_rep_timestamp = lv_tick_get();
/*Send LONG_PRESS_REP on ENTER*/
if(data->key == LV_KEY_ENTER) {
if(send_event(LV_EVENT_LONG_PRESSED_REPEAT, indev_act) == LV_RESULT_INVALID) return;
}
/*Move the focus on NEXT again*/
else if(data->key == LV_KEY_NEXT) {
lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/
lv_group_focus_next(g);
if(indev_reset_check(i)) return;
}
/*Move the focus on PREV again*/
else if(data->key == LV_KEY_PREV) {
lv_group_set_editing(g, false); /*Editing is not used by KEYPAD is be sure it is disabled*/
lv_group_focus_prev(g);
if(indev_reset_check(i)) return;
}
/*Just send other keys again to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT)*/
else {
lv_group_send_data(g, data->key);
if(indev_reset_check(i)) return;
}
}
}
/*Release happened*/
else if(is_enabled && data->state == LV_INDEV_STATE_RELEASED && prev_state == LV_INDEV_STATE_PRESSED) {
LV_LOG_INFO("%" LV_PRIu32 " key is released", data->key);
/*The user might clear the key when it was released. Always release the pressed key*/
data->key = prev_key;
if(data->key == LV_KEY_ENTER) {
if(send_event(LV_EVENT_RELEASED, indev_act) == LV_RESULT_INVALID) return;
if(i->long_pr_sent == 0) {
if(send_event(LV_EVENT_SHORT_CLICKED, indev_act) == LV_RESULT_INVALID) return;
}
if(send_event(LV_EVENT_CLICKED, indev_act) == LV_RESULT_INVALID) return;
}
i->pr_timestamp = 0;
i->long_pr_sent = 0;
}
indev_obj_act = NULL;
}
/**
* 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)
{
if(data->state == LV_INDEV_STATE_PRESSED && i->wait_until_release) return;
if(i->wait_until_release) {
i->wait_until_release = 0;
i->pr_timestamp = 0;
i->long_pr_sent = 0;
i->keypad.last_state = LV_INDEV_STATE_RELEASED; /*To skip the processing of release*/
}
/*Save the last keys before anything else.
*They need to be already saved if the function returns for any reason*/
lv_indev_state_t last_state = i->keypad.last_state;
i->keypad.last_state = data->state;
i->keypad.last_key = data->key;
lv_group_t * g = i->group;
if(g == NULL) return;
indev_obj_act = lv_group_get_focused(g);
if(indev_obj_act == NULL) return;
/*Process the steps they are valid only with released button*/
if(data->state != LV_INDEV_STATE_RELEASED) {
data->enc_diff = 0;
}
const bool is_enabled = !lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED);
/*Button press happened*/
if(data->state == LV_INDEV_STATE_PRESSED && last_state == LV_INDEV_STATE_RELEASED) {
LV_LOG_INFO("pressed");
i->pr_timestamp = lv_tick_get();
if(data->key == LV_KEY_ENTER) {
bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) ||
lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE);
if(lv_group_get_editing(g) == true || editable_or_scrollable == false) {
if(is_enabled) {
if(send_event(LV_EVENT_PRESSED, indev_act) == LV_RESULT_INVALID) return;
}
}
}
else if(data->key == LV_KEY_LEFT) {
/*emulate encoder left*/
data->enc_diff--;
}
else if(data->key == LV_KEY_RIGHT) {
/*emulate encoder right*/
data->enc_diff++;
}
else if(data->key == LV_KEY_ESC) {
/*Send the ESC as a normal KEY*/
lv_group_send_data(g, LV_KEY_ESC);
if(indev_reset_check(i)) return;
if(is_enabled) {
if(send_event(LV_EVENT_CANCEL, indev_act) == LV_RESULT_INVALID) return;
}
}
/*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/
else {
lv_group_send_data(g, data->key);
if(indev_reset_check(i)) return;
}
}
/*Pressing*/
else if(data->state == LV_INDEV_STATE_PRESSED && last_state == LV_INDEV_STATE_PRESSED) {
/*Long press*/
if(i->long_pr_sent == 0 && lv_tick_elaps(i->pr_timestamp) > i->long_press_time) {
i->long_pr_sent = 1;
i->longpr_rep_timestamp = lv_tick_get();
if(data->key == LV_KEY_ENTER) {
bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) ||
lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE);
/*On enter long press toggle edit mode.*/
if(editable_or_scrollable) {
/*Don't leave edit mode if there is only one object (nowhere to navigate)*/
if(lv_group_get_obj_count(g) > 1) {
LV_LOG_INFO("toggling edit mode");
lv_group_set_editing(g, lv_group_get_editing(g) ? false : true); /*Toggle edit mode on long press*/
lv_obj_remove_state(indev_obj_act, LV_STATE_PRESSED); /*Remove the pressed state manually*/
}
}
/*If not editable then just send a long press event*/
else {
if(is_enabled) {
if(send_event(LV_EVENT_LONG_PRESSED, indev_act) == LV_RESULT_INVALID) return;
}
}
}
i->long_pr_sent = 1;
}
/*Long press repeated time has elapsed?*/
else if(i->long_pr_sent != 0 && lv_tick_elaps(i->longpr_rep_timestamp) > i->long_press_repeat_time) {
i->longpr_rep_timestamp = lv_tick_get();
if(data->key == LV_KEY_ENTER) {
if(is_enabled) {
if(send_event(LV_EVENT_LONG_PRESSED_REPEAT, indev_act) == LV_RESULT_INVALID) return;
}
}
else if(data->key == LV_KEY_LEFT) {
/*emulate encoder left*/
data->enc_diff--;
}
else if(data->key == LV_KEY_RIGHT) {
/*emulate encoder right*/
data->enc_diff++;
}
else {
lv_group_send_data(g, data->key);
if(indev_reset_check(i)) return;
}
}
}
/*Release happened*/
else if(data->state == LV_INDEV_STATE_RELEASED && last_state == LV_INDEV_STATE_PRESSED) {
LV_LOG_INFO("released");
if(data->key == LV_KEY_ENTER) {
bool editable_or_scrollable = lv_obj_is_editable(indev_obj_act) ||
lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_SCROLLABLE);
/*The button was released on a non-editable object. Just send enter*/
if(editable_or_scrollable == false) {
if(is_enabled) {
if(send_event(LV_EVENT_RELEASED, indev_act) == LV_RESULT_INVALID) return;
}
if(i->long_pr_sent == 0 && is_enabled) {
if(send_event(LV_EVENT_SHORT_CLICKED, indev_act) == LV_RESULT_INVALID) return;
}
if(is_enabled) {
if(send_event(LV_EVENT_CLICKED, indev_act) == LV_RESULT_INVALID) return;
}
}
/*An object is being edited and the button is released.*/
else if(lv_group_get_editing(g)) {
/*Ignore long pressed enter release because it comes from mode switch*/
if(!i->long_pr_sent || lv_group_get_obj_count(g) <= 1) {
if(is_enabled) {
if(send_event(LV_EVENT_RELEASED, indev_act) == LV_RESULT_INVALID) return;
if(send_event(LV_EVENT_SHORT_CLICKED, indev_act) == LV_RESULT_INVALID) return;
if(send_event(LV_EVENT_CLICKED, indev_act) == LV_RESULT_INVALID) return;
}
lv_group_send_data(g, LV_KEY_ENTER);
if(indev_reset_check(i)) return;
}
else {
lv_obj_remove_state(indev_obj_act, LV_STATE_PRESSED); /*Remove the pressed state manually*/
}
}
/*If the focused object is editable and now in navigate mode then on enter switch edit
mode*/
else if(!i->long_pr_sent) {
LV_LOG_INFO("entering edit mode");
lv_group_set_editing(g, true); /*Set edit mode*/
}
}
i->pr_timestamp = 0;
i->long_pr_sent = 0;
}
indev_obj_act = NULL;
/*if encoder steps or simulated steps via left/right keys*/
if(data->enc_diff != 0) {
/*In edit mode send LEFT/RIGHT keys*/
if(lv_group_get_editing(g)) {
LV_LOG_INFO("rotated by %+d (edit)", data->enc_diff);
int32_t s;
if(data->enc_diff < 0) {
for(s = 0; s < -data->enc_diff; s++) {
lv_group_send_data(g, LV_KEY_LEFT);
if(indev_reset_check(i)) return;
}
}
else if(data->enc_diff > 0) {
for(s = 0; s < data->enc_diff; s++) {
lv_group_send_data(g, LV_KEY_RIGHT);
if(indev_reset_check(i)) return;
}
}
}
/*In navigate mode focus on the next/prev objects*/
else {
LV_LOG_INFO("rotated by %+d (nav)", data->enc_diff);
int32_t s;
if(data->enc_diff < 0) {
for(s = 0; s < -data->enc_diff; s++) {
lv_group_focus_prev(g);
if(indev_reset_check(i)) return;
}
}
else if(data->enc_diff > 0) {
for(s = 0; s < data->enc_diff; s++) {
lv_group_focus_next(g);
if(indev_reset_check(i)) return;
}
}
}
}
}
/**
* Process new points from an 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
*/
static void indev_button_proc(lv_indev_t * i, lv_indev_data_t * data)
{
/*Die gracefully if i->btn_points is NULL*/
if(i->btn_points == NULL) {
LV_LOG_WARN("btn_points is NULL");
return;
}
int32_t x = i->btn_points[data->btn_id].x;
int32_t y = i->btn_points[data->btn_id].y;
if(LV_INDEV_STATE_RELEASED != data->state) {
if(data->state == LV_INDEV_STATE_PRESSED) {
LV_LOG_INFO("button %" LV_PRIu32 " is pressed (x:%d y:%d)", data->btn_id, (int)x, (int)y);
}
else {
LV_LOG_INFO("button %" LV_PRIu32 " is released (x:%d y:%d)", data->btn_id, (int)x, (int)y);
}
}
/*If a new point comes always make a release*/
if(data->state == LV_INDEV_STATE_PRESSED) {
if(i->pointer.last_point.x != x ||
i->pointer.last_point.y != y) {
indev_proc_release(i);
}
}
if(indev_reset_check(i)) return;
/*Save the new points*/
i->pointer.act_point.x = x;
i->pointer.act_point.y = y;
if(data->state == LV_INDEV_STATE_PRESSED) indev_proc_press(i);
else indev_proc_release(i);
if(indev_reset_check(i)) return;
i->pointer.last_point.x = i->pointer.act_point.x;
i->pointer.last_point.y = i->pointer.act_point.y;
}
/**
* Process the pressed state of LV_INDEV_TYPE_POINTER input devices
* @param indev pointer to an input device 'proc'
*/
static void indev_proc_press(lv_indev_t * indev)
{
LV_LOG_INFO("pressed at x:%d y:%d", (int)indev->pointer.act_point.x,
(int)indev->pointer.act_point.y);
indev_obj_act = indev->pointer.act_obj;
if(indev->wait_until_release != 0) return;
lv_display_t * disp = indev_act->disp;
bool new_obj_searched = false;
/*If there is no last object then search*/
if(indev_obj_act == NULL) {
indev_obj_act = pointer_search_obj(disp, &indev->pointer.act_point);
new_obj_searched = true;
}
/*If there is an active object it's not scrolled and not protected also search*/
else if(indev->pointer.scroll_obj == NULL &&
lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_PRESS_LOCK) == false) {
indev_obj_act = pointer_search_obj(disp, &indev->pointer.act_point);
new_obj_searched = true;
}
/*The scroll object might have scroll throw. Stop it manually*/
if(new_obj_searched && indev->pointer.scroll_obj) {
/*Attempt to stop scroll throw animation firstly*/
if(indev->scroll_throw_anim) {
lv_anim_delete(indev, indev_scroll_throw_anim_cb);
indev->scroll_throw_anim = NULL;
}
_lv_indev_scroll_throw_handler(indev);
if(indev_reset_check(indev)) return;
}
/*If a new object was found reset some variables and send a pressed event handler*/
if(indev_obj_act != indev->pointer.act_obj) {
indev->pointer.last_point.x = indev->pointer.act_point.x;
indev->pointer.last_point.y = indev->pointer.act_point.y;
/*If a new object found the previous was lost, so send a PRESS_LOST event*/
if(indev->pointer.act_obj != NULL) {
/*Save the obj because in special cases `act_obj` can change in the event */
lv_obj_t * last_obj = indev->pointer.act_obj;
lv_obj_send_event(last_obj, LV_EVENT_PRESS_LOST, indev_act);
if(indev_reset_check(indev)) return;
/*Do nothing until release and a new press*/
lv_indev_reset(indev, NULL);
lv_indev_wait_release(indev);
return;
}
indev->pointer.act_obj = indev_obj_act; /*Save the pressed object*/
indev->pointer.last_obj = indev_obj_act;
if(indev_obj_act != NULL) {
/*Save the time when the obj pressed to count long press time.*/
indev->pr_timestamp = lv_tick_get();
indev->long_pr_sent = 0;
indev->pointer.scroll_sum.x = 0;
indev->pointer.scroll_sum.y = 0;
indev->pointer.scroll_dir = LV_DIR_NONE;
indev->pointer.scroll_obj = NULL;
indev->pointer.gesture_dir = LV_DIR_NONE;
indev->pointer.gesture_sent = 0;
indev->pointer.gesture_sum.x = 0;
indev->pointer.gesture_sum.y = 0;
indev->pointer.vect.x = 0;
indev->pointer.vect.y = 0;
const bool is_enabled = !lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED);
if(is_enabled) {
if(send_event(LV_EVENT_PRESSED, indev_act) == LV_RESULT_INVALID) return;
}
if(indev_act->wait_until_release) return;
/*Handle focus*/
indev_click_focus(indev_act);
if(indev_reset_check(indev)) return;
}
}
/*Calculate the vector and apply a low pass filter: new value = 0.5 * old_value + 0.5 * new_value*/
indev->pointer.vect.x = indev->pointer.act_point.x - indev->pointer.last_point.x;
indev->pointer.vect.y = indev->pointer.act_point.y - indev->pointer.last_point.y;
indev->pointer.scroll_throw_vect.x = (indev->pointer.scroll_throw_vect.x + indev->pointer.vect.x) / 2;
indev->pointer.scroll_throw_vect.y = (indev->pointer.scroll_throw_vect.y + indev->pointer.vect.y) / 2;
indev->pointer.scroll_throw_vect_ori = indev->pointer.scroll_throw_vect;
if(indev_obj_act) {
const bool is_enabled = !lv_obj_has_state(indev_obj_act, LV_STATE_DISABLED);
if(is_enabled) {
if(send_event(LV_EVENT_PRESSING, indev_act) == LV_RESULT_INVALID) return;
}
if(indev_act->wait_until_release) return;
_lv_indev_scroll_handler(indev);
if(indev_reset_check(indev)) return;
indev_gesture(indev);
if(indev_reset_check(indev)) return;
if(indev->mode == LV_INDEV_MODE_EVENT && indev->read_timer && lv_timer_get_paused(indev->read_timer)) {
lv_timer_resume(indev->read_timer);
}
/*If there is no scrolling then check for long press time*/
if(indev->pointer.scroll_obj == NULL && indev->long_pr_sent == 0) {
/*Send a long press event if enough time elapsed*/
if(lv_tick_elaps(indev->pr_timestamp) > indev_act->long_press_time) {
if(is_enabled) {
if(send_event(LV_EVENT_LONG_PRESSED, indev_act) == LV_RESULT_INVALID) return;
}
/*Mark it to do not send the event again*/
indev->long_pr_sent = 1;
/*Save the long press time stamp for the long press repeat handler*/
indev->longpr_rep_timestamp = lv_tick_get();
}
}
if(indev->pointer.scroll_obj == NULL && indev->long_pr_sent == 1) {
if(lv_tick_elaps(indev->longpr_rep_timestamp) > indev_act->long_press_repeat_time) {
if(is_enabled) {
if(send_event(LV_EVENT_LONG_PRESSED_REPEAT, indev_act) == LV_RESULT_INVALID) return;
}
indev->longpr_rep_timestamp = lv_tick_get();
}
}
}
}
/**
* Process the released state of LV_INDEV_TYPE_POINTER input devices
* @param proc pointer to an input device 'proc'
*/
static void indev_proc_release(lv_indev_t * indev)
{
if(indev->wait_until_release) {
lv_obj_send_event(indev->pointer.act_obj, LV_EVENT_PRESS_LOST, indev_act);
if(indev_reset_check(indev)) return;
indev->pointer.act_obj = NULL;
indev->pointer.last_obj = NULL;
indev->pr_timestamp = 0;
indev->longpr_rep_timestamp = 0;
indev->wait_until_release = 0;
}
indev_obj_act = indev->pointer.act_obj;
lv_obj_t * scroll_obj = indev->pointer.scroll_obj;
if(indev->mode == LV_INDEV_MODE_EVENT && indev->read_timer && !lv_timer_get_paused(indev->read_timer)) {
lv_timer_pause(indev->read_timer);
}
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) {
if(send_event(LV_EVENT_RELEASED, indev_act) == LV_RESULT_INVALID) return;
}
if(is_enabled) {
if(scroll_obj == NULL) {
if(indev->long_pr_sent == 0) {
if(send_event(LV_EVENT_SHORT_CLICKED, indev_act) == LV_RESULT_INVALID) return;
}
if(send_event(LV_EVENT_CLICKED, indev_act) == LV_RESULT_INVALID) return;
}
else {
if(send_event(LV_EVENT_SCROLL_THROW_BEGIN, indev_act) == LV_RESULT_INVALID) return;
}
}
indev->pointer.act_obj = NULL;
indev->pr_timestamp = 0;
indev->longpr_rep_timestamp = 0;
/*Get the transformed vector with this object*/
if(scroll_obj) {
int16_t angle = 0;
int16_t scale_x = 256;
int16_t scale_y = 256;
lv_point_t pivot = { 0, 0 };
lv_obj_t * parent = scroll_obj;
while(parent) {
angle += lv_obj_get_style_transform_rotation(parent, 0);
int32_t zoom_act_x = lv_obj_get_style_transform_scale_x_safe(parent, 0);
int32_t zoom_act_y = lv_obj_get_style_transform_scale_y_safe(parent, 0);
scale_x = (scale_x * zoom_act_x) >> 8;
scale_y = (scale_x * zoom_act_y) >> 8;
parent = lv_obj_get_parent(parent);
}
if(angle != 0 || scale_y != LV_SCALE_NONE || scale_x != LV_SCALE_NONE) {
angle = -angle;
scale_x = (256 * 256) / scale_x;
scale_y = (256 * 256) / scale_y;
lv_point_transform(&indev->pointer.scroll_throw_vect, angle, scale_x, scale_y, &pivot, false);
lv_point_transform(&indev->pointer.scroll_throw_vect_ori, angle, scale_x, scale_y, &pivot, false);
}
}
}
if(scroll_obj) {
if(!indev->scroll_throw_anim) {
indev_scroll_throw_anim_start(indev);
}
if(indev_reset_check(indev)) return;
}
}
static void indev_proc_pointer_diff(lv_indev_t * indev)
{
lv_obj_t * obj = indev->pointer.last_pressed;
if(obj == NULL) return;
if(indev->pointer.diff == 0) return;
indev_obj_act = obj;
bool editable = lv_obj_is_editable(obj);
if(editable) {
uint32_t indev_sensitivity = indev->rotary_sensitvity;
uint32_t obj_sensitivity = lv_obj_get_style_rotary_sensitivity(indev_obj_act, 0);
int32_t diff = (int32_t)((int32_t)indev->pointer.diff * indev_sensitivity * obj_sensitivity + 32768) >> 16;
send_event(LV_EVENT_ROTARY, &diff);
}
else {
int32_t vect = indev->pointer.diff > 0 ? indev->scroll_limit : -indev->scroll_limit;
indev->pointer.vect.y = vect;
indev->pointer.act_obj = obj;
lv_obj_t * scroll_obj = lv_indev_find_scroll_obj(indev);
if(scroll_obj == NULL) return;
uint32_t indev_sensitivity = indev->rotary_sensitvity;
uint32_t obj_sensitivity = lv_obj_get_style_rotary_sensitivity(scroll_obj, 0);
int32_t diff = (int32_t)((int32_t)indev->pointer.diff * indev_sensitivity * obj_sensitivity + 32768) >> 16;
indev->pointer.scroll_throw_vect.y = diff;
indev->pointer.scroll_throw_vect_ori.y = diff;
_lv_indev_scroll_handler(indev);
}
}
static lv_obj_t * pointer_search_obj(lv_display_t * disp, lv_point_t * p)
{
indev_obj_act = lv_indev_search_obj(lv_display_get_layer_sys(disp), p);
if(indev_obj_act) return indev_obj_act;
indev_obj_act = lv_indev_search_obj(lv_display_get_layer_top(disp), p);
if(indev_obj_act) return indev_obj_act;
/* Search the object in the active screen */
indev_obj_act = lv_indev_search_obj(lv_display_get_screen_active(disp), p);
if(indev_obj_act) return indev_obj_act;
indev_obj_act = lv_indev_search_obj(lv_display_get_layer_bottom(disp), p);
return indev_obj_act;
}
/**
* 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->reset_query) {
indev->pointer.act_obj = NULL;
indev->pointer.last_obj = NULL;
indev->pointer.scroll_obj = NULL;
indev->long_pr_sent = 0;
indev->pr_timestamp = 0;
indev->longpr_rep_timestamp = 0;
indev->pointer.scroll_sum.x = 0;
indev->pointer.scroll_sum.y = 0;
indev->pointer.scroll_dir = LV_DIR_NONE;
indev->pointer.scroll_obj = NULL;
indev->pointer.scroll_throw_vect.x = 0;
indev->pointer.scroll_throw_vect.y = 0;
indev->pointer.gesture_sum.x = 0;
indev->pointer.gesture_sum.y = 0;
indev->reset_query = 0;
indev_obj_act = NULL;
}
}
/**
* Handle focus/defocus on click for POINTER input devices
* @param proc pointer to the state of the indev
*/
static void indev_click_focus(lv_indev_t * indev)
{
/*Handle click focus*/
if(lv_obj_has_flag(indev_obj_act, LV_OBJ_FLAG_CLICK_FOCUSABLE) == false) {
return;
}
lv_group_t * g_act = lv_obj_get_group(indev_obj_act);
lv_group_t * g_prev = indev->pointer.last_pressed ? lv_obj_get_group(indev->pointer.last_pressed) : NULL;
/*If both the last and act. obj. are in the same group (or have no group)*/
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(indev)) return;
}
/*The object are not in group*/
else {
if(indev->pointer.last_pressed != indev_obj_act) {
lv_obj_send_event(indev->pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act);
if(indev_reset_check(indev)) return;
lv_obj_send_event(indev_obj_act, LV_EVENT_FOCUSED, indev_act);
if(indev_reset_check(indev)) return;
}
}
}
/*The object are not in the same group (in different groups or one has no group)*/
else {
/*If the prev. obj. is not in a group then defocus it.*/
if(g_prev == NULL && indev->pointer.last_pressed) {
lv_obj_send_event(indev->pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act);
if(indev_reset_check(indev)) return;
}
/*Focus on a non-group object*/
else {
if(indev->pointer.last_pressed) {
/*If the prev. object also wasn't in a group defocus it*/
if(g_prev == NULL) {
lv_obj_send_event(indev->pointer.last_pressed, LV_EVENT_DEFOCUSED, indev_act);
if(indev_reset_check(indev)) return;
}
/*If the prev. object also was in a group at least "LEAVE" it instead of defocus*/
else {
lv_obj_send_event(indev->pointer.last_pressed, LV_EVENT_LEAVE, indev_act);
if(indev_reset_check(indev)) return;
}
}
}
/*Focus to the act. in its group*/
if(g_act) {
lv_group_focus_obj(indev_obj_act);
if(indev_reset_check(indev)) return;
}
else {
lv_obj_send_event(indev_obj_act, LV_EVENT_FOCUSED, indev_act);
if(indev_reset_check(indev)) return;
}
}
indev->pointer.last_pressed = indev_obj_act;
}
/**
* Handle the gesture of indev_proc_p->pointer.act_obj
* @param indev pointer to an input device state
*/
void indev_gesture(lv_indev_t * indev)
{
if(indev->pointer.scroll_obj) return;
if(indev->pointer.gesture_sent) return;
lv_obj_t * gesture_obj = indev->pointer.act_obj;
/*If gesture parent is active check recursively the gesture attribute*/
while(gesture_obj && lv_obj_has_flag(gesture_obj, LV_OBJ_FLAG_GESTURE_BUBBLE)) {
gesture_obj = lv_obj_get_parent(gesture_obj);
}
if(gesture_obj == NULL) return;
if((LV_ABS(indev->pointer.vect.x) < indev_act->gesture_min_velocity) &&
(LV_ABS(indev->pointer.vect.y) < indev_act->gesture_min_velocity)) {
indev->pointer.gesture_sum.x = 0;
indev->pointer.gesture_sum.y = 0;
}
/*Count the movement by gesture*/
indev->pointer.gesture_sum.x += indev->pointer.vect.x;
indev->pointer.gesture_sum.y += indev->pointer.vect.y;
if((LV_ABS(indev->pointer.gesture_sum.x) > indev_act->gesture_limit) ||
(LV_ABS(indev->pointer.gesture_sum.y) > indev_act->gesture_limit)) {
indev->pointer.gesture_sent = 1;
if(LV_ABS(indev->pointer.gesture_sum.x) > LV_ABS(indev->pointer.gesture_sum.y)) {
if(indev->pointer.gesture_sum.x > 0)
indev->pointer.gesture_dir = LV_DIR_RIGHT;
else
indev->pointer.gesture_dir = LV_DIR_LEFT;
}
else {
if(indev->pointer.gesture_sum.y > 0)
indev->pointer.gesture_dir = LV_DIR_BOTTOM;
else
indev->pointer.gesture_dir = LV_DIR_TOP;
}
lv_obj_send_event(gesture_obj, LV_EVENT_GESTURE, indev_act);
if(indev_reset_check(indev)) return;
lv_indev_send_event(indev_act, LV_EVENT_LONG_PRESSED, gesture_obj);
if(indev_reset_check(indev_act)) return;
}
}
/**
* 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'
* @return true if indev query should be immediately truncated.
*/
static bool indev_reset_check(lv_indev_t * indev)
{
if(indev->reset_query) {
indev_obj_act = NULL;
}
return indev->reset_query;
}
/**
* Reset the indev and send event to active obj and scroll obj
* @param indev pointer to an input device
* @param obj pointer to obj
*/
static void indev_reset_core(lv_indev_t * indev, lv_obj_t * obj)
{
lv_obj_t * act_obj = NULL;
lv_obj_t * scroll_obj = NULL;
indev->reset_query = 1;
if(indev_act == indev) indev_obj_act = NULL;
if(indev->type == LV_INDEV_TYPE_POINTER || indev->type == LV_INDEV_TYPE_KEYPAD) {
if(obj == NULL || indev->pointer.last_pressed == obj) {
indev->pointer.last_pressed = NULL;
}
if(obj == NULL || indev->pointer.act_obj == obj) {
if(indev->pointer.act_obj) {
/* Avoid recursive calls */
act_obj = indev->pointer.act_obj;
indev->pointer.act_obj = NULL;
lv_obj_send_event(act_obj, LV_EVENT_INDEV_RESET, indev);
lv_indev_send_event(indev, LV_EVENT_INDEV_RESET, act_obj);
act_obj = NULL;
}
}
if(obj == NULL || indev->pointer.last_obj == obj) {
indev->pointer.last_obj = NULL;
}
if(obj == NULL || indev->pointer.scroll_obj == obj) {
if(indev->pointer.scroll_obj) {
/* Avoid recursive calls */
scroll_obj = indev->pointer.scroll_obj;
indev->pointer.scroll_obj = NULL;
lv_obj_send_event(scroll_obj, LV_EVENT_INDEV_RESET, indev);
lv_indev_send_event(indev, LV_EVENT_INDEV_RESET, act_obj);
scroll_obj = NULL;
}
}
}
}
static lv_result_t send_event(lv_event_code_t code, void * param)
{
lv_obj_send_event(indev_obj_act, code, param);
if(indev_reset_check(indev_act)) return LV_RESULT_INVALID;
if(code == LV_EVENT_PRESSED ||
code == LV_EVENT_CLICKED ||
code == LV_EVENT_RELEASED ||
code == LV_EVENT_LONG_PRESSED ||
code == LV_EVENT_LONG_PRESSED_REPEAT ||
code == LV_EVENT_ROTARY) {
lv_indev_send_event(indev_act, code, indev_obj_act);
if(indev_reset_check(indev_act)) return LV_RESULT_INVALID;
}
return LV_RESULT_OK;
}
static void indev_scroll_throw_anim_cb(void * var, int32_t v)
{
LV_ASSERT_NULL(var);
LV_UNUSED(v);
lv_indev_t * indev = (lv_indev_t *)var;
_lv_indev_scroll_throw_handler(indev);
if(indev->pointer.scroll_dir == LV_DIR_NONE || indev->pointer.scroll_obj == NULL) {
if(indev->scroll_throw_anim) {
LV_LOG_INFO("stop animation");
lv_anim_delete(indev, indev_scroll_throw_anim_cb);
}
}
}
static void indev_scroll_throw_anim_completed_cb(lv_anim_t * anim)
{
if(anim) {
indev_scroll_throw_anim_reset((lv_indev_t *)anim->var);
}
}
static void indev_scroll_throw_anim_start(lv_indev_t * indev)
{
LV_ASSERT_NULL(indev);
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, indev);
lv_anim_set_duration(&a, 1024);
lv_anim_set_values(&a, 0, 1024);
lv_anim_set_exec_cb(&a, indev_scroll_throw_anim_cb);
lv_anim_set_completed_cb(&a, indev_scroll_throw_anim_completed_cb);
lv_anim_set_deleted_cb(&a, indev_scroll_throw_anim_completed_cb);
lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
indev->scroll_throw_anim = lv_anim_start(&a);
}

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/notrynohigh-BabyOS.git
git@gitlife.ru:oschina-mirror/notrynohigh-BabyOS.git
oschina-mirror
notrynohigh-BabyOS
notrynohigh-BabyOS
master