mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-28 05:26:18 +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,
|
create_cache_iterator,
|
||||||
LVRedBlackTree,
|
LVRedBlackTree,
|
||||||
LVArray,
|
LVArray,
|
||||||
|
LVEvent,
|
||||||
|
LVEventDsc,
|
||||||
|
LVEventList,
|
||||||
|
event_code_name,
|
||||||
|
EVENT_CODE_NAMES,
|
||||||
)
|
)
|
||||||
from . import cmds as cmds
|
from . import cmds as cmds
|
||||||
|
|
||||||
@@ -61,4 +66,9 @@ __all__ = [
|
|||||||
"LVImageHeaderCache",
|
"LVImageHeaderCache",
|
||||||
"create_cache_iterator",
|
"create_cache_iterator",
|
||||||
"LVArray",
|
"LVArray",
|
||||||
|
"LVEvent",
|
||||||
|
"LVEventDsc",
|
||||||
|
"LVEventList",
|
||||||
|
"event_code_name",
|
||||||
|
"EVENT_CODE_NAMES",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ from .misc import (
|
|||||||
LVImageHeaderCache,
|
LVImageHeaderCache,
|
||||||
create_cache_iterator,
|
create_cache_iterator,
|
||||||
LVArray,
|
LVArray,
|
||||||
|
LVEvent,
|
||||||
|
LVEventDsc,
|
||||||
|
LVEventList,
|
||||||
|
event_code_name,
|
||||||
|
EVENT_CODE_NAMES,
|
||||||
)
|
)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
@@ -66,4 +71,9 @@ __all__ = [
|
|||||||
"LVImageHeaderCache",
|
"LVImageHeaderCache",
|
||||||
"create_cache_iterator",
|
"create_cache_iterator",
|
||||||
"LVArray",
|
"LVArray",
|
||||||
|
"LVEvent",
|
||||||
|
"LVEventDsc",
|
||||||
|
"LVEventList",
|
||||||
|
"event_code_name",
|
||||||
|
"EVENT_CODE_NAMES",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -59,6 +59,16 @@ class LVObject(Value):
|
|||||||
def child_count(self):
|
def child_count(self):
|
||||||
return self.spec_attr.child_cnt if self.spec_attr else 0
|
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
|
@property
|
||||||
def children(self):
|
def children(self):
|
||||||
if not self.spec_attr:
|
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_cache import LVImageCache
|
||||||
from .lv_image_header_cache import LVImageHeaderCache
|
from .lv_image_header_cache import LVImageHeaderCache
|
||||||
from .lv_array import LVArray
|
from .lv_array import LVArray
|
||||||
|
from .lv_event import (
|
||||||
|
LVEvent,
|
||||||
|
LVEventDsc,
|
||||||
|
LVEventList,
|
||||||
|
event_code_name,
|
||||||
|
EVENT_CODE_NAMES,
|
||||||
|
)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"LVList",
|
"LVList",
|
||||||
@@ -39,4 +46,9 @@ __all__ = [
|
|||||||
"LVImageHeaderCache",
|
"LVImageHeaderCache",
|
||||||
"create_cache_iterator",
|
"create_cache_iterator",
|
||||||
"LVArray",
|
"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