void _lv_indev_read_task(lv_task_t * task)是定时执行的输入设备任务回调函数。会处理输入设备的数据。
按下的处理:
static void indev_proc_press(lv_indev_proc_t * proc)
{
……
*首先从layer_sys,layer_top,scr_act按优级查找当前的活动对象
/* bool lv_obj_is_point_on_coords(lv_obj_t * obj, const lv_point_t * point)*/
indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point);
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);
new_obj_searched = true;
……
*如果按下时有throw动作手动停止。page drag后一般有throw动作。
/*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);
}
……
*如果当前的活动对与上一次的活动对象不一样。proc->types.pointer.act_obj是上一次的活动 对象,通知上一个活动对象PRESS_LOST(1次)。通知最近的对象被PRESSED(1次),并复位一些寄存器。
/*If a new object was found reset some variables and send a pressed signal*/
if(indev_obj_act != proc->types.pointer.act_obj) {
/*刚选中的活动对象不产生坐标向量值,把last_point与act_point同步*/
proc->types.pointer.last_point.x = proc->types.pointer.act_point.x;
proc->types.pointer.last_point.y = proc->types.pointer.act_point.y;
/*If a new object found the previous was lost, so send a signal*/
if(proc->types.pointer.act_obj != NULL) {
/*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);
if(indev_reset_check(proc)) return;
lv_event_send(last_obj, LV_EVENT_PRESS_LOST, NULL);
if(indev_reset_check(proc)) return;
}
proc->types.pointer.act_obj = indev_obj_act; /*Save the pressed object*/
proc->types.pointer.last_obj = indev_obj_act;
if(indev_obj_act != NULL) {
/* Save the time when the obj pressed to count long press time.*/
proc->pr_timestamp = lv_tick_get();
proc->long_pr_sent = 0;
proc->types.pointer.drag_limit_out = 0;
proc->types.pointer.drag_in_prog = 0;
proc->types.pointer.drag_sum.x = 0;
proc->types.pointer.drag_sum.y = 0;
proc->types.pointer.drag_dir = LV_DRAG_DIR_BOTH;
proc->types.pointer.gesture_sent = 0;
proc->types.pointer.gesture_sum.x = 0;
proc->types.pointer.gesture_sum.y = 0;
proc->types.pointer.vect.x = 0;
proc->types.pointer.vect.y = 0;
/*Search for 'top' attribute*/
lv_obj_t * i = indev_obj_act;
lv_obj_t * last_top = NULL;
while(i != NULL) {
if(i->top) last_top = i;
i = lv_obj_get_parent(i);
}
if(last_top != NULL) {
/*Move the last_top object to the foreground*/
lv_obj_move_foreground(last_top);
}
/*Send a signal about the press*/
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_PRESSED, indev_act);
if(indev_reset_check(proc)) return;
lv_event_send(indev_obj_act, LV_EVENT_PRESSED, NULL);
if(indev_reset_check(proc)) return;
if(indev_act->proc.wait_until_release) return;
/*Handle focus*/
indev_click_focus(&indev_act->proc);
if(indev_reset_check(proc)) return;
}
}
*构建drag_throw_vect(throw效果的向量)与vect(两次坐标输入向量)的相关性,方便释放时使用。
……
/*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;
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;
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--;
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--;
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;
……
*处理拖动、手势、长按、重复长按。PRESSING信号会一直发送。
/*If there is active object and it can be dragged run the drag*/
if(indev_obj_act != NULL)
{
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_PRESSING, indev_act);
if(indev_reset_check(proc)) return;
lv_event_send(indev_obj_act, LV_EVENT_PRESSING, NULL);
if(indev_reset_check(proc)) return;
if(indev_act->proc.wait_until_release) return;
indev_drag(proc);
indev_gesture(proc);
if(indev_reset_check(proc)) return;
/*If there is no drag then check for long press time*/
if(proc->types.pointer.drag_in_prog == 0 && proc->long_pr_sent == 0)
{
/*Send a signal about the long press if enough time elapsed*/
if(lv_tick_elaps(proc->pr_timestamp) > indev_act->driver.long_press_time)
{
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_LONG_PRESS, indev_act);
if(indev_reset_check(proc)) return;
lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, NULL);
if(indev_reset_check(proc)) return;
/*Mark the signal sending to do not send it again*/
proc->long_pr_sent = 1;
/*Save the long press time stamp for the long press repeat handler*/
proc->longpr_rep_timestamp = lv_tick_get();
}
}
/*Send long press repeated signal*/
if(proc->types.pointer.drag_in_prog == 0 && proc->long_pr_sent == 1)
{
/*Send a signal about the long press repeat if enough time elapsed*/
if(lv_tick_elaps(proc->longpr_rep_timestamp) > indev_act->driver.long_press_rep_time)
{
indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_LONG_PRESS_REP, indev_act);
if(indev_reset_check(proc)) return;
lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED_REPEAT, NULL);
if(indev_reset_check(proc)) return;
proc->longpr_rep_timestamp = lv_tick_get();
}
}
}
*indev_drag有两个变量,proc->types.pointer.drag_limit_out全局变量开启拖累后会一直为1,切到新对象才到写0。drag_just_started局部变量与limit_out同时置位控制方向,DRAG_BEGIN信号发送。
static void indev_drag(lv_indev_proc_t * proc)
{
lv_obj_t * drag_obj = get_dragged_obj(proc->types.pointer.act_obj);
bool drag_just_started = false;
uint8_t drag_dir; //saimen
if(drag_obj == NULL) return;
if(lv_obj_get_drag(drag_obj) == false) return;
lv_drag_dir_t allowed_dirs = lv_obj_get_drag_dir(drag_obj);
/*Count the movement by drag*/
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;
/*Enough move?*/
bool hor_en = false;
bool ver_en = false;
if(allowed_dirs == LV_DRAG_DIR_HOR || allowed_dirs == LV_DRAG_DIR_BOTH) {
hor_en = true;
}
if(allowed_dirs == LV_DRAG_DIR_VER || allowed_dirs == LV_DRAG_DIR_BOTH ||\
allowed_dirs == LV_DRAG_DIR_VER_ONLY_UP || allowed_dirs == LV_DRAG_DIR_VER_ONLY_DOWN) {
ver_en = true;
}
if(allowed_dirs == LV_DRAG_DIR_ONE) {
if(LV_MATH_ABS(proc->types.pointer.drag_sum.x) > LV_MATH_ABS(proc->types.pointer.drag_sum.y)) {
hor_en = true;
drag_dir = 0x10;
}
else {
ver_en = true;
drag_dir = 0x20;
}
}
/*If a move is greater then LV_DRAG_LIMIT then begin the drag*/
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;
drag_just_started = true;
if(drag_dir==0x10)
{
if(proc->types.pointer.drag_sum.x>0)
{
drag_dir |= 1;
}
else
{
drag_dir |= 2;
}
}
else
{
if(proc->types.pointer.drag_sum.y>0)
{
drag_dir |= 1;
}
else
{
drag_dir |= 2;
}
}
}
}
/*If the drag limit is exceeded handle the dragging*/
if(proc->types.pointer.drag_limit_out != 0) {
/*Set new position if the vector is not zero*/
if(proc->types.pointer.vect.x != 0 || proc->types.pointer.vect.y != 0) {
lv_coord_t prev_x = drag_obj->coords.x1;
lv_coord_t prev_y = drag_obj->coords.y1;
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));
/*Get the coordinates of the object and modify them*/
lv_coord_t act_x = lv_obj_get_x(drag_obj);
lv_coord_t act_y = lv_obj_get_y(drag_obj);
if(allowed_dirs == LV_DRAG_DIR_BOTH) {
if(drag_just_started) {
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;
}
}
else if(allowed_dirs == LV_DRAG_DIR_HOR) {
if(drag_just_started) {
proc->types.pointer.drag_dir = LV_DRAG_DIR_HOR;
proc->types.pointer.drag_sum.y = 0;
act_x += proc->types.pointer.drag_sum.x;
}
}
else if(allowed_dirs == LV_DRAG_DIR_VER) {
if(drag_just_started) {
proc->types.pointer.drag_dir = LV_DRAG_DIR_VER;
proc->types.pointer.drag_sum.x = 0;
act_y += proc->types.pointer.drag_sum.y;
}
}
else if(allowed_dirs == LV_DRAG_DIR_ONE) {
if(drag_just_started) {
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;
}
else {
proc->types.pointer.drag_dir = LV_DRAG_DIR_VER;
proc->types.pointer.drag_sum.x = 0;
act_y += proc->types.pointer.drag_sum.y;
}
}
}
else if (allowed_dirs == LV_DRAG_DIR_VER_ONLY_UP) {
if (drag_just_started) {
proc->types.pointer.drag_dir = LV_DRAG_DIR_VER;
proc->types.pointer.drag_sum.x = 0;
if (act_y + proc->types.pointer.drag_sum.y <= 0)
act_y += proc->types.pointer.drag_sum.y;
else
proc->types.pointer.drag_sum.y = 0;
}
}
else if (allowed_dirs == LV_DRAG_DIR_VER_ONLY_DOWN) {
if (drag_just_started) {
proc->types.pointer.drag_dir = LV_DRAG_DIR_VER;
proc->types.pointer.drag_sum.x = 0;
if (act_y + proc->types.pointer.drag_sum.y >= 0)
act_y += proc->types.pointer.drag_sum.y;
else
proc->types.pointer.drag_sum.y = 0;
}
}
/*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;
}
if (allowed_dirs == LV_DRAG_DIR_VER_ONLY_UP)
{
if (act_y + proc->types.pointer.vect.y <= 0)
act_y += proc->types.pointer.vect.y;
}
if (allowed_dirs == LV_DRAG_DIR_VER_ONLY_DOWN)
{
if (act_y + proc->types.pointer.vect.y >= 0)
act_y += proc->types.pointer.vect.y;
}
uint16_t inv_buf_size =
lv_disp_get_inv_buf_size(indev_act->driver.disp); /*Get the number of currently invalidated areas*/
lv_obj_set_pos(drag_obj, act_x, act_y);
proc->types.pointer.drag_in_prog = 1;
/*If the object didn't moved then clear the invalidated areas*/
if(drag_obj->coords.x1 == prev_x && drag_obj->coords.y1 == prev_y) {
/*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) {
uint16_t new_inv_buf_size = lv_disp_get_inv_buf_size(indev_act->driver.disp);
_lv_disp_pop_from_inv_buf(indev_act->driver.disp, new_inv_buf_size - inv_buf_size);
}
}
/*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);
lv_event_send(drag_obj, LV_EVENT_DRAG_BEGIN, &drag_dir);
if(indev_reset_check(proc)) return;
}
}
}
}
*indev_drag中的通过调用void lv_obj_set_pos()来改变坐标,触发滚动传输。第次坐标的改变都会通知到父、子对象还有自已。
释放的处理:
static void indev_proc_release(lv_indev_proc_t * proc)
等一下写