Enhance focus behavior for touchless interface

Hi there,

I am working on interface for device controlled only by buttons.
Currently I am looking for a solution for a list.

What I have

The list should contain items with embedded controls like switches, sliders and drop down lists.

However I would like to highlight entire Container (or only the container).

something like this:

image

The list is constructed from Page
every entry is made from Container
inside the container there is a Label and Control element (Switch, slider, dropdown, button …)

The control element is inside the group and it is working fine.

Current implementation

I am using user data to store focus_parent and focus_child, so the parent can check if the child is focused.

I have added code to lv_obj.c / lv_obj_get_style

if (obj->user_data.child_focus)
{
	lv_obj_t * cf = obj->user_data.child_focus;
	//focus if child is focused
	if(cf->group_p) {
		if (lv_group_get_focused(cf->group_p) == cf)
		{
			style_act = lv_group_mod_style(cf->group_p, style_act);
		}
	}
}

And the child can invalidate the parent to force it to repaint it.
In lv_group.c / lv_group_set_editing and focus_next_core

lv_obj_t * p = (*group->obj_focus)->user_data.parent_focus;
if (p) lv_obj_invalidate(p);

I just assign the parent/child pointers to user data during element creation

//create container
c = lv_cont_create(page, NULL);

//create label
lv_obj_t * l = lv_label_create(c, NULL);
lv_label_set_text(l, text);

//create slider
lv_obj_t * slider = lv_slider_create(c, NULL); 
lv_group_add_obj(group, slider);

//assign reference for parent and child focus
c->user_data.child_focus = slider;
slider->user_data.parent_focus = c;

The problem
This is working nice, however when I use dropdown as control element, the program fails with segmentation fault, because of the infinite recursion, but I am not sure why.

I do not understand fully the (re)drawing procedures, so I can be missing something trivial. How does changing the element style might lead to this behavior? I think that it might be related to calculating the redrawing area.

style_act = lv_group_mod_style(cf->group_p, style_act);

I am sure that problem is caused by this line, because when I remove all code causing the parent invalidation it is still happening.

Except the modifications above the lvgl code is untouched.
Maybe I am missing some easier solution to this problem?

Thank you for your advise

So I have solved the issue.

image

As I said, I do not fully understand the redrawing procedure.
The group->style_tmp is supposed to be used only once.
When the lv_group_mod_style function modify the style to be in focus or edit mode the edited style is kept in the group->style_tmp.

My modification caused that the group->style_tmp was reused when the child of the container was focused, therefore the style of the container was modified together with the actual control element.

The problem was when the styles have different size modifiers (eg paddings). Redrawing area was different when it was calculated only for container and the same container with child. The system was unable to settle on the final redrawing area and it will try to recalculate it.

I have added the condition for the lv_obj_get_style. It wan’t apply the focus style to the child if the parent_focus is used. Now the group->style_tmp will be used only once.

//do not apply the focus if using parant_focus
if (!obj->user_data.parent_focus)
{
	if(obj->group_p) {
		if(lv_group_get_focused(obj->group_p) == obj)
		{
			style_act = lv_group_mod_style(obj->group_p, style_act);
		}
	}
}

I will try to make the changes less ugly, and I someone will be interested in this behavior I will make PR.