From 434ceda91ac9a39540ffed411015f3c33d6535b9 Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Sun, 12 Jul 2026 10:45:52 -0700 Subject: [PATCH] fix: enable adv_hittest on dial arcs so touch respects each ring's own radius MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause of 'only the cool/blue knob drags, regardless of where you tap': LVGL's default arc hit-testing just uses each widget's full bounding square (whichever topmost widget's box contains the touch point wins), not the precise ring geometry. Since cool_arc's 360x360 box is entirely contained within heat_arc's 400x400 box, cool_arc (on top in z-order) claimed every touch inside its own square, including touches physically on heat_arc's outer ring, which sits outside cool_arc's box but still within heat_arc's simple bounding-box test. Confirmed via lv_arc.c: LVGL has a precise ring-based hit test (LV_EVENT_HIT_TEST, respects each widget's own radius and angular span) but it's opt-in via the ADV_HITTEST flag; without it, LVGL falls back to the simple bounding-box test. Verified the adv_hittest: true YAML property generates lv_obj_add_flag(..., LV_OBJ_FLAG_ADV_HITTEST) via an isolated test compile before applying to both arcs. The differing radii (400/360) from the previous fix are still useful for visual separation but were never sufficient on their own — this flag is what actually makes hit-testing respect the radius difference. --- firmware/components/display-classic.yaml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/firmware/components/display-classic.yaml b/firmware/components/display-classic.yaml index 019be54..9889194 100644 --- a/firmware/components/display-classic.yaml +++ b/firmware/components/display-classic.yaml @@ -109,6 +109,12 @@ lvgl: max_value: 90 value: 70 adjustable: true + adv_hittest: true # LVGL's default touch hit-test just uses each widget's full + # bounding square (any topmost widget under the touch point + # wins), which is why the radius difference alone didn't fix + # touch disambiguation. adv_hittest switches to LVGL's precise + # ring-based hit test (see LV_EVENT_HIT_TEST in lv_arc.c), + # which actually respects each arc's own radius. arc_opa: transp # flattened, see dial_bg_arc comment above indicator: arc_color: 0xFF3B30 @@ -129,11 +135,11 @@ lvgl: id: cool_arc align: center y: -20 - width: 360px # smaller radius than heat_arc (400px) so the two rings occupy - height: 360px # different physical pixels — LVGL hit-tests arcs by distance - # from center, and two arcs at the same radius are touch-ambiguous; - # the topmost one (this one, declared last) always wins regardless - # of where along the ring you actually tap + width: 360px # smaller radius than heat_arc (400px) so the two rings are visually + height: 360px # distinct; touch disambiguation itself comes from adv_hittest below, + # not from this size difference alone (a same-radius pair would also + # work correctly with adv_hittest on both, but differing radii keeps + # the two rings visually separable too) start_angle: 315 end_angle: 225 mode: REVERSE @@ -141,6 +147,7 @@ lvgl: max_value: 90 value: 75 adjustable: true + adv_hittest: true # see heat_arc comment above — precise ring-based hit test arc_opa: transp # flattened, see dial_bg_arc comment above indicator: arc_color: 0x0A84FF