1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-14 06:42:58 +08:00

fix(btnmatrix) improve focusing if used in groups

This commit is contained in:
Gabor Kiss-Vamosi 2021-05-03 11:14:25 +02:00
parent 3c39c39c9d
commit e1e45b1de3
5 changed files with 50 additions and 16 deletions

View File

@ -83,7 +83,7 @@ lv_res_t lv_event_send(lv_obj_t * obj, lv_event_code_t event_code, void * param)
lv_res_t lv_obj_event_base(const lv_obj_class_t * class_p, lv_event_t * e)
{
const lv_obj_class_t * base;
if(class_p == NULL) base = e->target->class_p;
if(class_p == NULL) base = e->current_target->class_p;
else base = class_p->base_class;
/*Find a base in which Call the ancestor's event handler_cb is set*/

View File

@ -11,6 +11,7 @@
#include "lv_group.h"
#include "../misc/lv_gc.h"
#include "../core/lv_obj.h"
#include "../core/lv_indev.h"
/*********************
* DEFINES
@ -26,6 +27,7 @@
static void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *),
void * (*move)(const lv_ll_t *, const void *));
static void lv_group_refocus(lv_group_t * g);
static lv_indev_t * get_indev(const lv_group_t * g);
/**********************
* STATIC VARIABLES
@ -70,7 +72,7 @@ void lv_group_del(lv_group_t * group)
{
/*Defocus the currently focused object*/
if(group->obj_focus != NULL) {
lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, NULL);
lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group));
lv_obj_invalidate(*group->obj_focus);
}
@ -150,7 +152,7 @@ void lv_group_remove_obj(lv_obj_t * obj)
/*If this is the only object in the group then focus to nothing.*/
if(_lv_ll_get_head(&g->obj_ll) == g->obj_focus && _lv_ll_get_tail(&g->obj_ll) == g->obj_focus) {
lv_event_send(*g->obj_focus, LV_EVENT_DEFOCUSED, NULL);
lv_event_send(*g->obj_focus, LV_EVENT_DEFOCUSED, get_indev(g));
}
/*If there more objects in the group then focus to the next/prev object*/
else {
@ -182,7 +184,7 @@ void lv_group_remove_all_objs(lv_group_t * group)
{
/*Defocus the currently focused object*/
if(group->obj_focus != NULL) {
lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, NULL);
lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group));
lv_obj_invalidate(*group->obj_focus);
group->obj_focus = NULL;
}
@ -213,7 +215,7 @@ void lv_group_focus_obj(lv_obj_t * obj)
_LV_LL_READ(&g->obj_ll, i) {
if(*i == obj) {
if(g->obj_focus != NULL) {
lv_res_t res = lv_event_send(*g->obj_focus, LV_EVENT_DEFOCUSED, NULL);
lv_res_t res = lv_event_send(*g->obj_focus, LV_EVENT_DEFOCUSED, get_indev(g));
if(res != LV_RES_OK) return;
lv_obj_invalidate(*g->obj_focus);
}
@ -222,7 +224,7 @@ void lv_group_focus_obj(lv_obj_t * obj)
if(g->obj_focus != NULL) {
if(g->focus_cb) g->focus_cb(g);
lv_res_t res = lv_event_send(*g->obj_focus, LV_EVENT_FOCUSED, NULL);
lv_res_t res = lv_event_send(*g->obj_focus, LV_EVENT_FOCUSED, get_indev(g));
if(res != LV_RES_OK) return;
lv_obj_invalidate(*g->obj_focus);
}
@ -243,10 +245,8 @@ void lv_group_focus_prev(lv_group_t * group)
void lv_group_focus_freeze(lv_group_t * group, bool en)
{
if(en == false)
group->frozen = 0;
else
group->frozen = 1;
if(en == false) group->frozen = 0;
else group->frozen = 1;
}
lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c)
@ -278,7 +278,7 @@ void lv_group_set_editing(lv_group_t * group, bool edit)
lv_obj_t * focused = lv_group_get_focused(group);
if(focused) {
lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_FOCUSED, NULL);
lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_FOCUSED, get_indev(group));
if(res != LV_RES_OK) return;
lv_obj_invalidate(focused);
@ -387,14 +387,14 @@ static void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *)
if(obj_next == group->obj_focus) return; /*There's only one visible object and it's already focused*/
if(group->obj_focus) {
lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, NULL);
lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_DEFOCUSED, get_indev(group));
if(res != LV_RES_OK) return;
lv_obj_invalidate(*group->obj_focus);
}
group->obj_focus = obj_next;
lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_FOCUSED, NULL);
lv_res_t res = lv_event_send(*group->obj_focus, LV_EVENT_FOCUSED, get_indev(group));
if(res != LV_RES_OK) return;
lv_obj_invalidate(*group->obj_focus);
@ -402,3 +402,33 @@ static void focus_next_core(lv_group_t * group, void * (*begin)(const lv_ll_t *)
if(group->focus_cb) group->focus_cb(group);
}
/**
* Find an indev preferably with KEYPAD or ENCOEDR type that uses the given group.
* In other words, find an indev, that is related to the given group.
* In the worst case simply return the latest indev
* @param g a group the find in the indevs
* @return the suggested indev
*/
static lv_indev_t * get_indev(const lv_group_t * g)
{
lv_indev_t * indev_encoder = NULL;
lv_indev_t * indev_group = NULL;
lv_indev_t * indev = lv_indev_get_next(NULL);
while(indev) {
lv_indev_type_t indev_type = lv_indev_get_type(indev);
if(indev->group == g) {
/*Prefer KEYPAD*/
if(indev_type == LV_INDEV_TYPE_KEYPAD) return indev;
if(indev_type == LV_INDEV_TYPE_ENCODER) indev_encoder = indev;
indev_group = indev;
}
indev = lv_indev_get_next(indev);
}
if(indev_encoder) return indev_encoder;
if(indev_group) return indev_group;
/*In lack of a better option use the first input device. (It can be NULL if there is no input device)*/
return lv_indev_get_next(NULL);
}

View File

@ -662,7 +662,9 @@ static void lv_obj_event(const lv_obj_class_t * class_p, lv_event_t * e)
bool editing = false;
editing = lv_group_get_editing(lv_obj_get_group(obj));
lv_state_t state = LV_STATE_FOCUSED;
lv_indev_type_t indev_type = lv_indev_get_type(lv_indev_get_act());
lv_indev_t * indev = lv_event_get_param(e);
lv_indev_type_t indev_type = lv_indev_get_type(indev);
if(indev_type == LV_INDEV_TYPE_KEYPAD || indev_type == LV_INDEV_TYPE_ENCODER) state |= LV_STATE_FOCUS_KEY;
if(editing) {
state |= LV_STATE_EDITED;

View File

@ -663,10 +663,12 @@ static void theme_apply(lv_theme_t * th, lv_obj_t * obj)
if(lv_obj_check_type(lv_obj_get_parent(obj), &lv_msgbox_class)) {
lv_obj_add_style(obj, &styles->msgbox_btns_bg, 0);
lv_obj_add_style(obj, &styles->pad_gap, 0);
lv_obj_add_style(obj, &styles->pad_tiny, 0);
lv_obj_add_style(obj, &styles->btn, LV_PART_ITEMS);
lv_obj_add_style(obj, &styles->pressed, LV_PART_ITEMS | LV_STATE_PRESSED);
lv_obj_add_style(obj, &styles->bg_color_primary, LV_PART_ITEMS | LV_STATE_CHECKED);
lv_obj_add_style(obj, &styles->outline_primary, LV_PART_ITEMS | LV_STATE_FOCUS_KEY);
lv_obj_add_style(obj, &styles->bg_color_primary_muted, LV_PART_ITEMS | LV_STATE_FOCUS_KEY);
lv_obj_add_style(obj, &styles->bg_color_secondary_muted, LV_PART_ITEMS | LV_STATE_EDITED);
return;
}
#endif

View File

@ -500,7 +500,7 @@ static void lv_btnmatrix_event(const lv_obj_class_t * class_p, lv_event_t * e)
btnm->btn_id_sel = LV_BTNMATRIX_BTN_NONE;
}
else if(code == LV_EVENT_FOCUSED) {
lv_indev_t * indev = lv_indev_get_act();
lv_indev_t * indev = lv_event_get_param(e);
lv_indev_type_t indev_type = lv_indev_get_type(indev);
/*If not focused by an input device assume the last input device*/