Skip to content

Commit c4daf8a

Browse files
committed
fix(buttonmatrix): skip buttons outside clip area in draw_main
draw_main iterates all buttons unconditionally, performing style resolution and draw dispatch even for buttons outside the clip area. Add an lv_area_is_on() check to skip buttons that don't intersect the layer's clip area. The test area is extended by the same margin used in invalidate_button_area (row/col gap with dpi/10 minimum) to account for outline and shadow rendering outside the base button area. The popover flag additionally extends the test area upward by the button's height. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
1 parent 8dc2006 commit c4daf8a

1 file changed

Lines changed: 27 additions & 0 deletions

File tree

src/widgets/buttonmatrix/lv_buttonmatrix.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,19 @@ static void draw_main(lv_event_t * e)
653653
int32_t pleft = lv_obj_get_style_pad_left(obj, LV_PART_MAIN);
654654
int32_t pright = lv_obj_get_style_pad_right(obj, LV_PART_MAIN);
655655

656+
/*Clip margin for the early skip check below. Buttons can render outside
657+
*their base area due to outline/shadow, so extend the test area by the
658+
*same margin used in invalidate_button_area (row/col gap, dpi/10 min).*/
659+
int32_t clip_margin;
660+
{
661+
int32_t row_gap = lv_obj_get_style_pad_row(obj, LV_PART_MAIN);
662+
int32_t col_gap = lv_obj_get_style_pad_column(obj, LV_PART_MAIN);
663+
int32_t dpi_margin = lv_display_get_dpi(lv_obj_get_display(obj)) / 10;
664+
row_gap = LV_MAX(row_gap, dpi_margin);
665+
col_gap = LV_MAX(col_gap, dpi_margin);
666+
clip_margin = LV_MAX(row_gap, col_gap);
667+
}
668+
656669
#if LV_USE_ARABIC_PERSIAN_CHARS
657670
char txt_ap[256];
658671
#endif
@@ -685,6 +698,20 @@ static void draw_main(lv_event_t * e)
685698
btn_area.x2 += area_obj.x1;
686699
btn_area.y2 += area_obj.y1;
687700

701+
/*Skip buttons outside the clip area. Extend the test area by
702+
*clip_margin (shadow/outline) and popover height when applicable.*/
703+
{
704+
lv_area_t clip_test = btn_area;
705+
clip_test.x1 -= clip_margin;
706+
clip_test.y1 -= clip_margin;
707+
clip_test.x2 += clip_margin;
708+
clip_test.y2 += clip_margin;
709+
if(btnm->ctrl_bits[btn_i] & LV_BUTTONMATRIX_CTRL_POPOVER) {
710+
clip_test.y1 -= lv_area_get_height(&btn_area);
711+
}
712+
if(!lv_area_is_on(&clip_test, &layer->_clip_area)) continue;
713+
}
714+
688715
/*Set up the draw descriptors*/
689716
if(btn_state == LV_STATE_DEFAULT) {
690717
lv_memcpy(&draw_rect_dsc_act, &draw_rect_dsc_def, sizeof(lv_draw_rect_dsc_t));

0 commit comments

Comments
 (0)