From 691ce778008d92b336b18783213ceeb00531c498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Hor=C3=ADnek?= Date: Mon, 25 May 2020 15:51:20 +0200 Subject: [PATCH] Modified version for encoder input proc. Now you can also pass buttons LEFT/RIGHT to emulate the encoder, good for joysticks or small keypads. All other keys are passed trought. --- src/lv_core/lv_indev.c | 244 ++++++++++++++++++++++++-------------- src/lv_hal/lv_hal_indev.c | 5 + 2 files changed, 157 insertions(+), 92 deletions(-) diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index 6b0e23aba..b48343a26 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -607,8 +607,158 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) indev_obj_act = lv_group_get_focused(g); if(indev_obj_act == NULL) return; - /*Process the steps first. They are valid only with released button*/ - if(data->state == LV_INDEV_STATE_REL) { + /*Process the steps they are valid only with released button*/ + if(data->state != LV_INDEV_STATE_REL) { + data->enc_diff = 0; + } + + /*Refresh the focused object. It might change due to 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_PR && last_state == LV_INDEV_STATE_REL) { + + i->proc.pr_timestamp = lv_tick_get(); + + if (data->key == LV_KEY_ENTER) { + bool editable = false; + indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_GET_EDITABLE, &editable); + + if(lv_group_get_editing(g) == true || editable == false) { + indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_PRESSED, NULL); + if(indev_reset_check(&i->proc)) return; + + lv_event_send(indev_obj_act, LV_EVENT_PRESSED, NULL); + 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*/ + lv_group_send_data(g, LV_KEY_ESC); + + lv_event_send(indev_obj_act, LV_EVENT_CANCEL, NULL); + if(indev_reset_check(&i->proc)) return; + } + /*Just send other keys to the object (e.g. 'A' or `LV_GROUP_KEY_RIGHT`)*/ + else { + lv_group_send_data(g, data->key); + } + } + /*Pressing*/ + else if(data->state == LV_INDEV_STATE_PR && last_state == LV_INDEV_STATE_PR) { + /* Long press*/ + if(i->proc.long_pr_sent == 0 && lv_tick_elaps(i->proc.pr_timestamp) > i->driver.long_press_time) { + + i->proc.long_pr_sent = 1; + i->proc.longpr_rep_timestamp = lv_tick_get(); + + if (data->key == LV_KEY_ENTER) { + bool editable = false; + indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_GET_EDITABLE, &editable); + + /*On enter long press toggle edit mode.*/ + if(editable) { + /*Don't leave edit mode if there is only one object (nowhere to navigate)*/ + if(_lv_ll_is_empty(&g->obj_ll) == false) { + lv_group_set_editing(g, lv_group_get_editing(g) ? false : true); /*Toggle edit mode on long press*/ + } + } + /*If not editable then just send a long press signal*/ + else { + indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_LONG_PRESS, NULL); + if(indev_reset_check(&i->proc)) return; + lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, NULL); + 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 && lv_tick_elaps(i->proc.longpr_rep_timestamp) > i->driver.long_press_rep_time) { + + i->proc.longpr_rep_timestamp = lv_tick_get(); + + if(data->key == LV_KEY_ENTER) { + indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_LONG_PRESS_REP, NULL); + if(indev_reset_check(&i->proc)) return; + lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED_REPEAT, NULL); + 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_REL && last_state == LV_INDEV_STATE_PR) { + + if (data->key == LV_KEY_ENTER) { + bool editable = false; + indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_GET_EDITABLE, &editable); + + /*The button was released on a non-editable object. Just send enter*/ + if(editable == false) { + indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_RELEASED, NULL); + if(indev_reset_check(&i->proc)) return; + + if(i->proc.long_pr_sent == 0) lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, NULL); + if(indev_reset_check(&i->proc)) return; + + lv_event_send(indev_obj_act, LV_EVENT_CLICKED, NULL); + if(indev_reset_check(&i->proc)) return; + + lv_event_send(indev_obj_act, LV_EVENT_RELEASED, NULL); + if(indev_reset_check(&i->proc)) return; + } + /*An object is being edited and the button is released. */ + else if(g->editing) { + /*Ignore long pressed enter release because it comes from mode switch*/ + if(!i->proc.long_pr_sent || _lv_ll_is_empty(&g->obj_ll)) { + indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_RELEASED, NULL); + if(indev_reset_check(&i->proc)) return; + + lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, NULL); + if(indev_reset_check(&i->proc)) return; + + lv_event_send(indev_obj_act, LV_EVENT_CLICKED, NULL); + if(indev_reset_check(&i->proc)) return; + + lv_event_send(indev_obj_act, LV_EVENT_RELEASED, NULL); + if(indev_reset_check(&i->proc)) return; + + lv_group_send_data(g, LV_KEY_ENTER); + } + } + /*If the focused object is editable and now in navigate mode then on enter switch edit + mode*/ + else if(editable && !g->editing && !i->proc.long_pr_sent) { + 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)) { int32_t s; @@ -631,96 +781,6 @@ static void indev_encoder_proc(lv_indev_t * i, lv_indev_data_t * data) } } - /*Refresh the focused object. It might change due to 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_PR && last_state == LV_INDEV_STATE_REL) { - bool editable = false; - indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_GET_EDITABLE, &editable); - - i->proc.pr_timestamp = lv_tick_get(); - if(lv_group_get_editing(g) == true || editable == false) { - indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_PRESSED, NULL); - if(indev_reset_check(&i->proc)) return; - - lv_event_send(indev_obj_act, LV_EVENT_PRESSED, NULL); - if(indev_reset_check(&i->proc)) return; - } - } - /*Pressing*/ - 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) { - bool editable = false; - indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_GET_EDITABLE, &editable); - - /*On enter long press toggle edit mode.*/ - if(editable) { - /*Don't leave edit mode if there is only one object (nowhere to navigate)*/ - if(_lv_ll_is_empty(&g->obj_ll) == false) { - lv_group_set_editing(g, lv_group_get_editing(g) ? false : true); /*Toggle edit mode on long press*/ - } - } - /*If not editable then just send a long press signal*/ - else { - indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_LONG_PRESS, NULL); - if(indev_reset_check(&i->proc)) return; - lv_event_send(indev_obj_act, LV_EVENT_LONG_PRESSED, NULL); - if(indev_reset_check(&i->proc)) return; - } - i->proc.long_pr_sent = 1; - } - } - /*Release happened*/ - else if(data->state == LV_INDEV_STATE_REL && last_state == LV_INDEV_STATE_PR) { - - bool editable = false; - indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_GET_EDITABLE, &editable); - - /*The button was released on a non-editable object. Just send enter*/ - if(editable == false) { - indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_RELEASED, NULL); - if(indev_reset_check(&i->proc)) return; - - if(i->proc.long_pr_sent == 0) lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, NULL); - if(indev_reset_check(&i->proc)) return; - - lv_event_send(indev_obj_act, LV_EVENT_CLICKED, NULL); - if(indev_reset_check(&i->proc)) return; - - lv_event_send(indev_obj_act, LV_EVENT_RELEASED, NULL); - if(indev_reset_check(&i->proc)) return; - } - /*An object is being edited and the button is released. */ - else if(g->editing) { - /*Ignore long pressed enter release because it comes from mode switch*/ - if(!i->proc.long_pr_sent || _lv_ll_is_empty(&g->obj_ll)) { - indev_obj_act->signal_cb(indev_obj_act, LV_SIGNAL_RELEASED, NULL); - if(indev_reset_check(&i->proc)) return; - - lv_event_send(indev_obj_act, LV_EVENT_SHORT_CLICKED, NULL); - if(indev_reset_check(&i->proc)) return; - - lv_event_send(indev_obj_act, LV_EVENT_CLICKED, NULL); - if(indev_reset_check(&i->proc)) return; - - lv_event_send(indev_obj_act, LV_EVENT_RELEASED, NULL); - if(indev_reset_check(&i->proc)) return; - - lv_group_send_data(g, LV_KEY_ENTER); - } - } - /*If the focused object is editable and now in navigate mode then on enter switch edit - mode*/ - else if(editable && !g->editing && !i->proc.long_pr_sent) { - lv_group_set_editing(g, true); /*Set edit mode*/ - } - - i->proc.pr_timestamp = 0; - i->proc.long_pr_sent = 0; - } - indev_obj_act = NULL; #else (void)data; /*Unused*/ (void)i; /*Unused*/ diff --git a/src/lv_hal/lv_hal_indev.c b/src/lv_hal/lv_hal_indev.c index 0dd328a5c..b99b57beb 100644 --- a/src/lv_hal/lv_hal_indev.c +++ b/src/lv_hal/lv_hal_indev.c @@ -143,6 +143,11 @@ bool _lv_indev_read(lv_indev_t * indev, lv_indev_data_t * data) else if(indev->driver.type == LV_INDEV_TYPE_KEYPAD) { data->key = indev->proc.types.keypad.last_key; } + /*For compatibility assume that used button was enter (encoder push) */ + else if(indev->driver.type == LV_INDEV_TYPE_ENCODER) { + data->key = LV_KEY_ENTER; + data->enc_diff = 0; + } if(indev->driver.read_cb) { LV_LOG_TRACE("idnev read started");