[lvgl] Fix setting triggers on display (#15364)

This commit is contained in:
Clyde Stubbs
2026-04-07 08:48:14 +10:00
committed by GitHub
parent ce0d360790
commit c98bb9060f
4 changed files with 114 additions and 72 deletions
+15 -5
View File
@@ -2,7 +2,7 @@ import importlib
from pathlib import Path
import pkgutil
from esphome.automation import build_automation, validate_automation
from esphome.automation import Trigger, build_automation, validate_automation
import esphome.codegen as cg
from esphome.components.const import (
CONF_BYTE_ORDER,
@@ -34,7 +34,6 @@ from esphome.const import (
CONF_ID,
CONF_LAMBDA,
CONF_LOG_LEVEL,
CONF_ON_BOOT,
CONF_ON_IDLE,
CONF_PAGES,
CONF_ROTATION,
@@ -59,7 +58,7 @@ from .encoders import (
from .gradient import GRADIENT_SCHEMA, gradients_to_code
from .keypads import KEYPADS_CONFIG, keypads_to_code
from .lv_validation import lv_bool, lv_images_used
from .lvcode import LvContext, LvglComponent, lvgl_static
from .lvcode import LvContext, LvglComponent, lv_event_t_ptr, lvgl_static
from .schemas import (
DISP_BG_SCHEMA,
FULL_STYLE_SCHEMA,
@@ -71,7 +70,7 @@ from .schemas import (
)
from .styles import styles_to_code, theme_to_code
from .touchscreens import touchscreen_schema, touchscreens_to_code
from .trigger import add_on_boot_triggers, generate_align_tos, generate_triggers
from .trigger import generate_align_tos, generate_triggers
from .types import (
IdleTrigger,
PlainTrigger,
@@ -79,6 +78,7 @@ from .types import (
lv_font_t,
lv_group_t,
lv_lambda_t,
lv_obj_t_ptr,
lv_style_t,
lvgl_ns,
)
@@ -398,7 +398,6 @@ async def to_code(configs):
f"set_{trigger_name.removeprefix('on_')}_trigger",
)(trigger_var)
)
await add_on_boot_triggers(config.get(CONF_ON_BOOT, ()))
# This must be done after all widgets are created
for comp in helpers.lvgl_components_required:
@@ -502,6 +501,17 @@ LVGL_SCHEMA = cv.All(
cv.polling_component_schema("1s")
.extend(
{
**{
cv.Optional(event): validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
Trigger.template(lv_obj_t_ptr, lv_event_t_ptr)
),
}
)
for event in df.LV_SCREEN_EVENT_TRIGGERS
+ df.LV_DISPLAY_EVENT_TRIGGERS
},
cv.GenerateID(CONF_ID): cv.declare_id(LvglComponent),
cv.GenerateID(CONF_ALIGN_TO_LAMBDA_ID): cv.declare_id(lv_lambda_t),
cv.GenerateID(df.CONF_DISPLAYS): display_schema,
+22 -14
View File
@@ -276,10 +276,6 @@ LV_EVENT_MAP = {
"DRAW_POST_BEGIN": "DRAW_POST_BEGIN",
"DRAW_POST_END": "DRAW_POST_END",
"DRAW_TASK_ADD": "DRAW_TASK_ADDED",
"FLUSH_FINISH": "FLUSH_FINISH",
"FLUSH_START": "FLUSH_START",
"FLUSH_WAIT_FINISH": "FLUSH_WAIT_FINISH",
"FLUSH_WAIT_START": "FLUSH_WAIT_START",
"FOCUS": "FOCUSED",
"GESTURE": "GESTURE",
"GET_SELF_SIZE": "GET_SELF_SIZE",
@@ -300,18 +296,8 @@ LV_EVENT_MAP = {
"READY": "READY",
"REFRESH": "REFRESH",
"REFR_EXT_DRAW_SIZE": "REFR_EXT_DRAW_SIZE",
"REFR_READY": "REFR_READY",
"REFR_REQUEST": "REFR_REQUEST",
"REFR_START": "REFR_START",
"RELEASE": "RELEASED",
"RENDER_READY": "RENDER_READY",
"RENDER_START": "RENDER_START",
"RESOLUTION_CHANGE": "RESOLUTION_CHANGED",
"ROTARY": "ROTARY",
"SCREEN_LOAD": "SCREEN_LOADED",
"SCREEN_LOAD_START": "SCREEN_LOAD_START",
"SCREEN_UNLOAD": "SCREEN_UNLOADED",
"SCREEN_UNLOAD_START": "SCREEN_UNLOAD_START",
"SCROLL": "SCROLL",
"SCROLL_BEGIN": "SCROLL_BEGIN",
"SCROLL_END": "SCROLL_END",
@@ -322,12 +308,34 @@ LV_EVENT_MAP = {
"STATE_CHANGE": "STATE_CHANGED",
"STYLE_CHANGE": "STYLE_CHANGED",
"TRIPLE_CLICK": "TRIPLE_CLICKED",
}
LV_SCREEN_EVENT_MAP = {
"SCREEN_LOAD": "SCREEN_LOADED",
"SCREEN_LOAD_START": "SCREEN_LOAD_START",
"SCREEN_UNLOAD": "SCREEN_UNLOADED",
"SCREEN_UNLOAD_START": "SCREEN_UNLOAD_START",
}
LV_DISPLAY_EVENT_MAP = {
"FLUSH_FINISH": "FLUSH_FINISH",
"FLUSH_START": "FLUSH_START",
"FLUSH_WAIT_FINISH": "FLUSH_WAIT_FINISH",
"FLUSH_WAIT_START": "FLUSH_WAIT_START",
"REFR_READY": "REFR_READY",
"REFR_REQUEST": "REFR_REQUEST",
"REFR_START": "REFR_START",
"RENDER_READY": "RENDER_READY",
"RENDER_START": "RENDER_START",
"RESOLUTION_CHANGE": "RESOLUTION_CHANGED",
"UPDATE_LAYOUT_COMPLETE": "UPDATE_LAYOUT_COMPLETED",
"VSYNC": "VSYNC",
"VSYNC_REQUEST": "VSYNC_REQUEST",
}
LV_EVENT_TRIGGERS = tuple(f"on_{x.lower()}" for x in LV_EVENT_MAP)
LV_DISPLAY_EVENT_TRIGGERS = tuple(f"on_{x.lower()}" for x in LV_DISPLAY_EVENT_MAP)
LV_SCREEN_EVENT_TRIGGERS = tuple(f"on_{x.lower()}" for x in LV_SCREEN_EVENT_MAP)
SWIPE_TRIGGERS = tuple(
f"on_swipe_{x.lower()}" for x in DIRECTIONS.choices + ("up", "down")
)
+39 -15
View File
@@ -8,16 +8,21 @@ from esphome.const import (
CONF_X,
CONF_Y,
)
from esphome.cpp_generator import new_Pvariable
from esphome.cpp_generator import MockObj, new_Pvariable
from esphome.cpp_helpers import register_component
from esphome.cpp_types import nullptr
from .defines import (
CONF_ALIGN,
CONF_ALIGN_TO,
CONF_ALIGN_TO_LAMBDA_ID,
DIRECTIONS,
LV_DISPLAY_EVENT_MAP,
LV_DISPLAY_EVENT_TRIGGERS,
LV_EVENT_MAP,
LV_EVENT_TRIGGERS,
LV_SCREEN_EVENT_MAP,
LV_SCREEN_EVENT_TRIGGERS,
SWIPE_TRIGGERS,
literal,
)
@@ -30,6 +35,7 @@ from .lvcode import (
lv,
lv_add,
lv_event_t_ptr,
lv_expr,
lvgl_static,
)
from .types import LV_EVENT
@@ -49,25 +55,24 @@ async def generate_triggers():
Must be done after all widgets completed
"""
all_triggers = (
LV_EVENT_TRIGGERS + LV_DISPLAY_EVENT_TRIGGERS + LV_SCREEN_EVENT_TRIGGERS
)
for w in widget_map.values():
config = w.config
if isinstance(w.type, LvScrActType):
w = get_screen_active(w.var)
if w.config:
if config:
for event, conf in {
event: conf
for event, conf in w.config.items()
if event in LV_EVENT_TRIGGERS
event: conf for event, conf in config.items() if event in all_triggers
}.items():
conf = conf[0]
w.add_flag("LV_OBJ_FLAG_CLICKABLE")
event = literal("LV_EVENT_" + LV_EVENT_MAP[event[3:].upper()])
await add_trigger(conf, w, event)
for event, conf in {
event: conf
for event, conf in w.config.items()
if event in SWIPE_TRIGGERS
event: conf for event, conf in config.items() if event in SWIPE_TRIGGERS
}.items():
conf = conf[0]
dir = event[9:].upper()
@@ -77,11 +82,9 @@ async def generate_triggers():
selected = literal(
f"lv_indev_get_gesture_dir(lv_indev_active()) == {dir}"
)
await add_trigger(
conf, w, literal("LV_EVENT_GESTURE"), is_selected=selected
)
await add_trigger(conf, w, "GESTURE", is_selected=selected)
for conf in w.config.get(CONF_ON_VALUE, ()):
for conf in config.get(CONF_ON_VALUE, ()):
await add_trigger(
conf,
w,
@@ -90,7 +93,7 @@ async def generate_triggers():
UPDATE_EVENT,
)
await add_on_boot_triggers(w.config.get(CONF_ON_BOOT, ()))
await add_on_boot_triggers(config.get(CONF_ON_BOOT, ()))
async def generate_align_tos(config: dict):
@@ -119,6 +122,17 @@ async def generate_align_tos(config: dict):
await register_component(var, {})
TRIGGER_MAP = LV_EVENT_MAP | LV_DISPLAY_EVENT_MAP | LV_SCREEN_EVENT_MAP
DISPLAY_TRIGGERS = set(LV_DISPLAY_EVENT_TRIGGERS)
def _get_event_literal(trigger: str | MockObj) -> MockObj:
if isinstance(trigger, MockObj):
return trigger
trigger = trigger.removeprefix("on_")
return literal("LV_EVENT_" + TRIGGER_MAP[trigger.upper()])
async def add_trigger(conf, w, *events, is_selected=None):
is_selected = is_selected or w.is_selected()
tid = conf[CONF_TRIGGER_ID]
@@ -129,4 +143,14 @@ async def add_trigger(conf, w, *events, is_selected=None):
async with LambdaContext(EVENT_ARG, where=tid) as context:
with LvConditional(is_selected):
lv_add(trigger.trigger(*value, literal("event")))
lv_add(lvgl_static.add_event_cb(w.obj, await context.get_lambda(), *events))
callback = await context.get_lambda()
event_literals = [_get_event_literal(event) for event in events]
if isinstance(events[0], str) and events[0] in DISPLAY_TRIGGERS:
assert len(events) == 1
lv.display_add_event_cb(
lv_expr.obj_get_display(w.obj), callback, event_literals[0], nullptr
)
else:
lv_add(
lvgl_static.add_event_cb(w.obj, await context.get_lambda(), *event_literals)
)
+38 -38
View File
@@ -49,6 +49,44 @@ lvgl:
id: meter_arc_indicator
start_value: 0
end_value: 180
on_invalidate_area:
logger.log: Invalidate area
on_resolution_change:
logger.log: Resolution changed
on_color_format_change:
logger.log: Color format changed
on_refr_request:
logger.log: Refresh request
on_refr_start:
logger.log: Refresh start
on_refr_ready:
logger.log: Refresh ready
on_render_start:
logger.log: Render start
on_render_ready:
logger.log: Render ready
on_flush_start:
logger.log: Flush start
on_flush_finish:
logger.log: Flush finish
on_flush_wait_start:
logger.log: Flush wait start
on_flush_wait_finish:
logger.log: Flush wait finish
on_update_layout_complete:
logger.log: Update layout complete
on_vsync:
logger.log: Vsync
on_vsync_request:
logger.log: Vsync request
on_screen_load_start:
logger.log: Screen load start
on_screen_load:
logger.log: Screen loaded
on_screen_unload:
logger.log: Screen unloaded
on_screen_unload_start:
logger.log: Screen unload start
bg_color: light_blue
bottom_layer:
widgets:
@@ -660,14 +698,6 @@ lvgl:
logger.log: Child created
on_child_delete:
logger.log: Child deleted
on_screen_unload_start:
logger.log: Screen unload start
on_screen_load_start:
logger.log: Screen load start
on_screen_load:
logger.log: Screen loaded
on_screen_unload:
logger.log: Screen unloaded
on_size_change:
logger.log: Size changed
on_style_change:
@@ -676,36 +706,6 @@ lvgl:
logger.log: Layout changed
on_get_self_size:
logger.log: Get self size
on_invalidate_area:
logger.log: Invalidate area
on_resolution_change:
logger.log: Resolution changed
on_color_format_change:
logger.log: Color format changed
on_refr_request:
logger.log: Refresh request
on_refr_start:
logger.log: Refresh start
on_refr_ready:
logger.log: Refresh ready
on_render_start:
logger.log: Render start
on_render_ready:
logger.log: Render ready
on_flush_start:
logger.log: Flush start
on_flush_finish:
logger.log: Flush finish
on_flush_wait_start:
logger.log: Flush wait start
on_flush_wait_finish:
logger.log: Flush wait finish
on_update_layout_complete:
logger.log: Update layout complete
on_vsync:
logger.log: Vsync
on_vsync_request:
logger.log: Vsync request
- led:
id: lv_led
color: 0x00FF00