LVGL 编码器 输入处理

/**
 * 处理来自LV_INDEV_TYPE_ENCODER输入设备的新点
 * @param i 指向输入设备的指针
 * @param data 指向从输入设备读取的数据的指针
 */
static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data)
{
    // 如果当前状态为按下且等待释放标志被设置,则直接返回,不处理
    if(data->state == LV_INDEV_STATE_PRESSED && i->proc.wait_until_release) return;

    // 如果设置了等待释放标志,则重置相关处理状态
    if(i->proc.wait_until_release)
    {
        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_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->proc.types.keypad.last_state;// 保存上一个状态
    i->proc.types.keypad.last_state = data->state;// 更新当前状态
    i->proc.types.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;// 如果状态不是释放,则步进差值置为0
    }

    /*Refresh the focused object. It might change due to lv_group_focus_prev/next*/
    // 刷新焦点对象。由于可能通过lv_group_focus_prev/next更改,需要重新获取
    indev_obj_act = lv_group_get_focused(g);

    if(indev_obj_act == NULL) return;

    /*Button press happened*/
    // 按钮按下事件处理
    if(data->state == LV_INDEV_STATE_PRESSED && last_state == LV_INDEV_STATE_RELEASED)
    {
        LV_LOG_INFO("pressed");// 记录按下信息

        i->proc.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)
            {
                lv_event_send(indev_obj_act, LV_EVENT_PRESSED, indev_act);

                if(indev_reset_check(&i->proc)) 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*/
            // 将ESC作为普通按键发送
            lv_group_send_data(g, LV_KEY_ESC);

            if(indev_reset_check(&i->proc)) return;

            lv_event_send(indev_obj_act, LV_EVENT_CANCEL, indev_act);

            if(indev_reset_check(&i->proc)) return;
        }
        /*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/
        // 将其他按键直接发送给对象(例如'A'或`LV_GROUP_KEY_RIGHT`)
        else
        {
            lv_group_send_data(g, data->key);

            if(indev_reset_check(&i->proc)) return;
        }
    }
    /*Pressing*/
    // 持续按压处理
    else if(data->state == LV_INDEV_STATE_PRESSED && last_state == LV_INDEV_STATE_PRESSED)
    {
        /*Long press*/
        // 长按处理
        uint32_t time1 = lv_tick_elaps(i->proc.pr_timestamp);  
        uint32_t time2 = i->driver->long_press_time; 
        uint32_t time12 = (time1 > time2) ? 1:0;    
        
        uint32_t time3 = lv_tick_elaps(i->proc.longpr_rep_timestamp);
        uint32_t time4 = i->driver->long_press_repeat_time;    
        uint32_t time34 = (time3 > time4) ? 1:0;  
        
        if(i->proc.long_pr_sent == 0 && time12)
        {

            i->proc.long_pr_sent = 1;
            i->proc.longpr_rep_timestamp = lv_tick_get();

            // 长按ENTER键的特殊处理
            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.*/
                // 在可编辑或可滚动对象上长按ENTER键切换编辑模式
                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_clear_state(indev_obj_act, LV_STATE_PRESSED);    /*Remove the pressed state manually*/// 手动移除按压状态
                    }
                }
                /*If not editable then just send a long press Call the ancestor's event handler*/
                // 如果对象不可编辑,则仅发送长按事件
                else
                {
                    lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, indev_act);

                    if(indev_reset_check(&i->proc)) return;
                }
            }

            i->proc.long_pr_sent = 1;
        }
        /*Long press repeated time has elapsed?*/
        // 长按重复时间已到?
        
        else if(i->proc.long_pr_sent != 0 && time34)
        {

            i->proc.longpr_rep_timestamp = lv_tick_get();

            // 根据按键类型进行长按重复事件的处理
            if(data->key == LV_KEY_ENTER)
            {
                lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED_REPEAT, indev_act);

                if(indev_reset_check(&i->proc)) 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->proc)) return;
            }

        }

    }
    /*Release happened*/
    // 释放事件处理
    else if(data->state == LV_INDEV_STATE_RELEASED && last_state == LV_INDEV_STATE_PRESSED)
    {
        LV_LOG_INFO("released"); // 记录释放信息

        // 释放ENTER键的特殊处理
        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*/
            // 在非可编辑对象上释放按钮。仅发送enter
            if(editable_or_scrollable == false)
            {
                lv_event_send(indev_obj_act, LV_EVENT_RELEASED, indev_act);

                if(indev_reset_check(&i->proc)) return;

                if(i->proc.long_pr_sent == 0) lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, indev_act);

                if(indev_reset_check(&i->proc)) return;

                lv_event_send(indev_obj_act, LV_EVENT_CLICKED, indev_act);

                if(indev_reset_check(&i->proc)) 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->proc.long_pr_sent || lv_group_get_obj_count(g) <= 1)
                {
                    lv_event_send(indev_obj_act, LV_EVENT_RELEASED, indev_act);

                    if(indev_reset_check(&i->proc)) return;

                    lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, indev_act);

                    if(indev_reset_check(&i->proc)) return;

                    lv_event_send(indev_obj_act, LV_EVENT_CLICKED, indev_act);

                    if(indev_reset_check(&i->proc)) return;

                    lv_group_send_data(g, LV_KEY_ENTER);

                    if(indev_reset_check(&i->proc)) return;
                }
                else
                {
                    lv_obj_clear_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*/
            // 如果焦点对象可编辑且当前处于导航模式,则在ENTER释放时切换到编辑模式
            else if(!i->proc.long_pr_sent)
            {
                LV_LOG_INFO("entering edit mode");
                lv_group_set_editing(g, true); /*Set edit mode*/ // 设置编辑模式
            }
        }

        i->proc.pr_timestamp = 0;// 重置按下时间戳
        i->proc.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->proc)) 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->proc)) 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->proc)) 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->proc)) return;
                }
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值