mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-09 20:27:41 +08:00
chore(gdb): add event subsystem wrappers with LVEvent, LVEventDsc, LVEventList and gen_event_consts
This commit is contained in:
@@ -29,6 +29,11 @@ from .lvgl import (
|
||||
create_cache_iterator,
|
||||
LVRedBlackTree,
|
||||
LVArray,
|
||||
LVEvent,
|
||||
LVEventDsc,
|
||||
LVEventList,
|
||||
event_code_name,
|
||||
EVENT_CODE_NAMES,
|
||||
)
|
||||
from . import cmds as cmds
|
||||
|
||||
@@ -61,4 +66,9 @@ __all__ = [
|
||||
"LVImageHeaderCache",
|
||||
"create_cache_iterator",
|
||||
"LVArray",
|
||||
"LVEvent",
|
||||
"LVEventDsc",
|
||||
"LVEventList",
|
||||
"event_code_name",
|
||||
"EVENT_CODE_NAMES",
|
||||
]
|
||||
|
||||
@@ -30,6 +30,11 @@ from .misc import (
|
||||
LVImageHeaderCache,
|
||||
create_cache_iterator,
|
||||
LVArray,
|
||||
LVEvent,
|
||||
LVEventDsc,
|
||||
LVEventList,
|
||||
event_code_name,
|
||||
EVENT_CODE_NAMES,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
@@ -66,4 +71,9 @@ __all__ = [
|
||||
"LVImageHeaderCache",
|
||||
"create_cache_iterator",
|
||||
"LVArray",
|
||||
"LVEvent",
|
||||
"LVEventDsc",
|
||||
"LVEventList",
|
||||
"event_code_name",
|
||||
"EVENT_CODE_NAMES",
|
||||
]
|
||||
|
||||
@@ -59,6 +59,16 @@ class LVObject(Value):
|
||||
def child_count(self):
|
||||
return self.spec_attr.child_cnt if self.spec_attr else 0
|
||||
|
||||
@property
|
||||
def event_list(self):
|
||||
"""Get event list from obj->spec_attr->event_list."""
|
||||
from ..misc.lv_event import LVEventList
|
||||
|
||||
spec = self.spec_attr
|
||||
if not spec or not int(spec):
|
||||
return None
|
||||
return LVEventList(spec.event_list)
|
||||
|
||||
@property
|
||||
def children(self):
|
||||
if not self.spec_attr:
|
||||
|
||||
@@ -16,6 +16,13 @@ from .lv_cache_iter_factory import create_cache_iterator
|
||||
from .lv_image_cache import LVImageCache
|
||||
from .lv_image_header_cache import LVImageHeaderCache
|
||||
from .lv_array import LVArray
|
||||
from .lv_event import (
|
||||
LVEvent,
|
||||
LVEventDsc,
|
||||
LVEventList,
|
||||
event_code_name,
|
||||
EVENT_CODE_NAMES,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"LVList",
|
||||
@@ -39,4 +46,9 @@ __all__ = [
|
||||
"LVImageHeaderCache",
|
||||
"create_cache_iterator",
|
||||
"LVArray",
|
||||
"LVEvent",
|
||||
"LVEventDsc",
|
||||
"LVEventList",
|
||||
"event_code_name",
|
||||
"EVENT_CODE_NAMES",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
import gdb
|
||||
|
||||
from lvglgdb.value import Value, ValueInput
|
||||
from .lv_event_consts import EVENT_CODE_NAMES
|
||||
from .lv_array import LVArray
|
||||
|
||||
|
||||
def event_code_name(code: int) -> str:
|
||||
"""Map event code integer to human-readable name."""
|
||||
return EVENT_CODE_NAMES.get(code, f"UNKNOWN({code})")
|
||||
|
||||
|
||||
class LVEvent(Value):
|
||||
"""LVGL event wrapper"""
|
||||
|
||||
def __init__(self, event: ValueInput):
|
||||
super().__init__(Value.normalize(event, "lv_event_t"))
|
||||
|
||||
@property
|
||||
def code(self) -> int:
|
||||
return int(self.super_value("code"))
|
||||
|
||||
@property
|
||||
def code_name(self) -> str:
|
||||
return event_code_name(self.code)
|
||||
|
||||
@property
|
||||
def current_target(self) -> Value:
|
||||
return self.super_value("current_target")
|
||||
|
||||
@property
|
||||
def original_target(self) -> Value:
|
||||
return self.super_value("original_target")
|
||||
|
||||
@property
|
||||
def param(self) -> Value:
|
||||
return self.super_value("param")
|
||||
|
||||
@property
|
||||
def prev(self):
|
||||
p = self.super_value("prev")
|
||||
return LVEvent(p) if int(p) else None
|
||||
|
||||
@property
|
||||
def deleted(self) -> bool:
|
||||
return bool(int(self.super_value("deleted")))
|
||||
|
||||
@property
|
||||
def stop_processing(self) -> bool:
|
||||
return bool(int(self.super_value("stop_processing")))
|
||||
|
||||
def print_info(self):
|
||||
print(f"Event: code={self.code_name}({self.code})")
|
||||
print(f" current_target={self.current_target}")
|
||||
print(f" original_target={self.original_target}")
|
||||
print(f" deleted={self.deleted} stop_processing={self.stop_processing}")
|
||||
|
||||
|
||||
class LVEventDsc(Value):
|
||||
"""LVGL event descriptor wrapper"""
|
||||
|
||||
def __init__(self, dsc: ValueInput):
|
||||
super().__init__(Value.normalize(dsc, "lv_event_dsc_t"))
|
||||
|
||||
@property
|
||||
def cb(self) -> Value:
|
||||
return self.super_value("cb")
|
||||
|
||||
@property
|
||||
def user_data(self) -> Value:
|
||||
return self.super_value("user_data")
|
||||
|
||||
@property
|
||||
def filter(self) -> int:
|
||||
return int(self.super_value("filter"))
|
||||
|
||||
@property
|
||||
def filter_code(self) -> int:
|
||||
"""Event code with flag bits masked off."""
|
||||
return self.filter & ~(0x8000 | 0x10000)
|
||||
|
||||
@property
|
||||
def filter_name(self) -> str:
|
||||
return event_code_name(self.filter_code)
|
||||
|
||||
@property
|
||||
def is_preprocess(self) -> bool:
|
||||
return bool(self.filter & 0x8000)
|
||||
|
||||
@property
|
||||
def is_marked_deleting(self) -> bool:
|
||||
return bool(self.filter & 0x10000)
|
||||
|
||||
def print_info(self):
|
||||
cb_str = self.cb.format_string(symbols=True, address=True)
|
||||
flags = []
|
||||
if self.is_preprocess:
|
||||
flags.append("PRE")
|
||||
if self.is_marked_deleting:
|
||||
flags.append("DEL")
|
||||
flag_str = f" [{','.join(flags)}]" if flags else ""
|
||||
print(f" cb={cb_str} filter={self.filter_name}({self.filter_code}){flag_str}")
|
||||
|
||||
|
||||
class LVEventList(Value):
|
||||
"""LVGL event list wrapper (lv_event_list_t contains lv_array_t)"""
|
||||
|
||||
def __init__(self, event_list: ValueInput):
|
||||
super().__init__(Value.normalize(event_list, "lv_event_list_t"))
|
||||
|
||||
@property
|
||||
def array(self) -> LVArray:
|
||||
"""Array stores lv_event_dsc_t* pointers (not inline structs)."""
|
||||
dsc_ptr_type = gdb.lookup_type("lv_event_dsc_t").pointer()
|
||||
return LVArray(self.super_value("array"), dsc_ptr_type)
|
||||
|
||||
@property
|
||||
def is_traversing(self) -> bool:
|
||||
return bool(int(self.super_value("is_traversing")))
|
||||
|
||||
@property
|
||||
def has_marked_deleting(self) -> bool:
|
||||
return bool(int(self.super_value("has_marked_deleting")))
|
||||
|
||||
def __iter__(self):
|
||||
"""Yield LVEventDsc for each pointer stored in the array."""
|
||||
for dsc_ptr in self.array:
|
||||
yield LVEventDsc(dsc_ptr)
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self.array)
|
||||
|
||||
@staticmethod
|
||||
def print_entries(event_dscs):
|
||||
"""Print event descriptors as a PrettyTable."""
|
||||
from prettytable import PrettyTable
|
||||
|
||||
table = PrettyTable()
|
||||
table.field_names = ["#", "callback", "filter", "flags", "user_data"]
|
||||
table.align = "l"
|
||||
|
||||
count = 0
|
||||
for i, dsc in enumerate(event_dscs):
|
||||
cb_str = dsc.cb.format_string(symbols=True, address=True)
|
||||
flags = []
|
||||
if dsc.is_preprocess:
|
||||
flags.append("PRE")
|
||||
if dsc.is_marked_deleting:
|
||||
flags.append("DEL")
|
||||
table.add_row(
|
||||
[i, cb_str, dsc.filter_name, ",".join(flags) or "-", dsc.user_data]
|
||||
)
|
||||
count += 1
|
||||
|
||||
if count == 0:
|
||||
print("No event descriptors.")
|
||||
else:
|
||||
print(table)
|
||||
@@ -0,0 +1,83 @@
|
||||
"""
|
||||
Auto-generated event constants from LVGL headers.
|
||||
|
||||
Do not edit manually. Regenerate with:
|
||||
python3 scripts/gen_event_consts.py
|
||||
"""
|
||||
|
||||
EVENT_CODE_NAMES = {
|
||||
0: "ALL",
|
||||
1: "PRESSED",
|
||||
2: "PRESSING",
|
||||
3: "PRESS_LOST",
|
||||
4: "SHORT_CLICKED",
|
||||
5: "SINGLE_CLICKED",
|
||||
6: "DOUBLE_CLICKED",
|
||||
7: "TRIPLE_CLICKED",
|
||||
8: "LONG_PRESSED",
|
||||
9: "LONG_PRESSED_REPEAT",
|
||||
10: "CLICKED",
|
||||
11: "RELEASED",
|
||||
12: "SCROLL_BEGIN",
|
||||
13: "SCROLL_THROW_BEGIN",
|
||||
14: "SCROLL_END",
|
||||
15: "SCROLL",
|
||||
16: "GESTURE",
|
||||
17: "KEY",
|
||||
18: "ROTARY",
|
||||
19: "FOCUSED",
|
||||
20: "DEFOCUSED",
|
||||
21: "LEAVE",
|
||||
22: "HIT_TEST",
|
||||
23: "INDEV_RESET",
|
||||
24: "HOVER_OVER",
|
||||
25: "HOVER_LEAVE",
|
||||
26: "COVER_CHECK",
|
||||
27: "REFR_EXT_DRAW_SIZE",
|
||||
28: "DRAW_MAIN_BEGIN",
|
||||
29: "DRAW_MAIN",
|
||||
30: "DRAW_MAIN_END",
|
||||
31: "DRAW_POST_BEGIN",
|
||||
32: "DRAW_POST",
|
||||
33: "DRAW_POST_END",
|
||||
34: "DRAW_TASK_ADDED",
|
||||
35: "VALUE_CHANGED",
|
||||
36: "INSERT",
|
||||
37: "REFRESH",
|
||||
38: "READY",
|
||||
39: "CANCEL",
|
||||
40: "STATE_CHANGED",
|
||||
41: "CREATE",
|
||||
42: "DELETE",
|
||||
43: "CHILD_CHANGED",
|
||||
44: "CHILD_CREATED",
|
||||
45: "CHILD_DELETED",
|
||||
46: "SCREEN_UNLOAD_START",
|
||||
47: "SCREEN_LOAD_START",
|
||||
48: "SCREEN_LOADED",
|
||||
49: "SCREEN_UNLOADED",
|
||||
50: "SIZE_CHANGED",
|
||||
51: "STYLE_CHANGED",
|
||||
52: "LAYOUT_CHANGED",
|
||||
53: "GET_SELF_SIZE",
|
||||
54: "INVALIDATE_AREA",
|
||||
55: "RESOLUTION_CHANGED",
|
||||
56: "COLOR_FORMAT_CHANGED",
|
||||
57: "REFR_REQUEST",
|
||||
58: "REFR_START",
|
||||
59: "REFR_READY",
|
||||
60: "RENDER_START",
|
||||
61: "RENDER_READY",
|
||||
62: "FLUSH_START",
|
||||
63: "FLUSH_FINISH",
|
||||
64: "FLUSH_WAIT_START",
|
||||
65: "FLUSH_WAIT_FINISH",
|
||||
66: "SYNC_START",
|
||||
67: "SYNC_FINISH",
|
||||
68: "SYNC_WAIT_START",
|
||||
69: "SYNC_WAIT_FINISH",
|
||||
70: "UPDATE_LAYOUT_COMPLETED",
|
||||
71: "VSYNC",
|
||||
72: "VSYNC_REQUEST",
|
||||
73: "TRANSLATION_LANGUAGE_CHANGED",
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate event constant tables from LVGL header files.
|
||||
|
||||
Parses lv_event.h for the lv_event_code_t enum.
|
||||
|
||||
Usage:
|
||||
python3 scripts/gen_event_consts.py
|
||||
"""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
SCRIPT_DIR = Path(__file__).parent
|
||||
GDB_ROOT = SCRIPT_DIR.parent
|
||||
LVGL_SRC = GDB_ROOT.parent.parent / "src"
|
||||
OUTPUT = GDB_ROOT / "lvglgdb" / "lvgl" / "misc" / "lv_event_consts.py"
|
||||
|
||||
EVENT_H = LVGL_SRC / "misc" / "lv_event.h"
|
||||
|
||||
|
||||
def parse_event_codes(path: Path) -> dict[int, str]:
|
||||
"""Parse lv_event_code_t enum from lv_event.h."""
|
||||
text = path.read_text()
|
||||
|
||||
m = re.search(r"typedef\s+enum\s*\{(.*?)\}\s*lv_event_code_t", text, re.DOTALL)
|
||||
if not m:
|
||||
raise RuntimeError("Cannot find lv_event_code_t enum")
|
||||
|
||||
codes = {}
|
||||
current_val = 0
|
||||
for line in m.group(1).splitlines():
|
||||
line = line.strip().rstrip(",")
|
||||
if (
|
||||
not line
|
||||
or line.startswith("/*")
|
||||
or line.startswith("//")
|
||||
or line.startswith("*")
|
||||
or line.startswith("#")
|
||||
):
|
||||
continue
|
||||
|
||||
# Match: LV_EVENT_XXX = value
|
||||
match = re.match(r"(LV_EVENT_\w+)\s*=\s*(0x[\da-fA-F]+|\d+)", line)
|
||||
if match:
|
||||
name = match.group(1)
|
||||
current_val = int(match.group(2), 0)
|
||||
else:
|
||||
match = re.match(r"(LV_EVENT_\w+)", line)
|
||||
if not match:
|
||||
continue
|
||||
name = match.group(1)
|
||||
|
||||
# Skip meta entries
|
||||
if name in ("LV_EVENT_LAST", "LV_EVENT_PREPROCESS", "LV_EVENT_MARKED_DELETING"):
|
||||
current_val += 1
|
||||
continue
|
||||
|
||||
short = name.removeprefix("LV_EVENT_")
|
||||
codes[current_val] = short
|
||||
current_val += 1
|
||||
|
||||
return codes
|
||||
|
||||
|
||||
def generate(codes: dict[int, str]) -> str:
|
||||
"""Generate Python source for the event constants module."""
|
||||
lines = [
|
||||
'"""',
|
||||
"Auto-generated event constants from LVGL headers.",
|
||||
"",
|
||||
"Do not edit manually. Regenerate with:",
|
||||
" python3 scripts/gen_event_consts.py",
|
||||
'"""',
|
||||
"",
|
||||
]
|
||||
|
||||
lines.append("EVENT_CODE_NAMES = {")
|
||||
for k in sorted(codes):
|
||||
lines.append(f' {k}: "{codes[k]}",')
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
codes = parse_event_codes(EVENT_H)
|
||||
src = generate(codes)
|
||||
OUTPUT.write_text(src)
|
||||
print(f"Generated {OUTPUT} ({len(codes)} event codes)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user