From 79c626c585d5531fc966b60ff8fb65c0002560de Mon Sep 17 00:00:00 2001 From: Benign X <1341398182@qq.com> Date: Fri, 6 Mar 2026 11:30:27 +0800 Subject: [PATCH] chore(gdb): add LVGroup wrapper with focus tracking and dump group command --- scripts/gdb/lvglgdb/__init__.py | 2 + scripts/gdb/lvglgdb/cmds/__init__.py | 3 +- scripts/gdb/lvglgdb/cmds/core/__init__.py | 2 + scripts/gdb/lvglgdb/cmds/core/lv_group.py | 16 ++++ scripts/gdb/lvglgdb/lvgl/__init__.py | 2 + scripts/gdb/lvglgdb/lvgl/core/__init__.py | 2 + scripts/gdb/lvglgdb/lvgl/core/lv_global.py | 6 ++ scripts/gdb/lvglgdb/lvgl/core/lv_group.py | 88 ++++++++++++++++++++++ 8 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 scripts/gdb/lvglgdb/cmds/core/lv_group.py create mode 100644 scripts/gdb/lvglgdb/lvgl/core/lv_group.py diff --git a/scripts/gdb/lvglgdb/__init__.py b/scripts/gdb/lvglgdb/__init__.py index c11da65be5..f91b017aa0 100644 --- a/scripts/gdb/lvglgdb/__init__.py +++ b/scripts/gdb/lvglgdb/__init__.py @@ -40,6 +40,7 @@ from .lvgl import ( LVFsDrv, LVIndev, INDEV_TYPE_NAMES, + LVGroup, ) from . import cmds as cmds @@ -83,4 +84,5 @@ __all__ = [ "LVFsDrv", "LVIndev", "INDEV_TYPE_NAMES", + "LVGroup", ] diff --git a/scripts/gdb/lvglgdb/cmds/__init__.py b/scripts/gdb/lvglgdb/cmds/__init__.py index 65a056115d..fa1bfd80f8 100644 --- a/scripts/gdb/lvglgdb/cmds/__init__.py +++ b/scripts/gdb/lvglgdb/cmds/__init__.py @@ -1,6 +1,6 @@ import gdb -from .core import DumpObj, DumpIndev +from .core import DumpObj, DumpIndev, DumpGroup from .display import DumpDisplayBuf from .draw import InfoDrawUnit, DumpDrawTask from .misc import ( @@ -39,6 +39,7 @@ DumpTimer() DumpImageDecoder() DumpFsDrv() DumpIndev() +DumpGroup() DumpDrawTask() # Infos diff --git a/scripts/gdb/lvglgdb/cmds/core/__init__.py b/scripts/gdb/lvglgdb/cmds/core/__init__.py index b0cac928c0..1fd0ca0bbf 100644 --- a/scripts/gdb/lvglgdb/cmds/core/__init__.py +++ b/scripts/gdb/lvglgdb/cmds/core/__init__.py @@ -1,7 +1,9 @@ from .lv_obj import DumpObj from .lv_indev import DumpIndev +from .lv_group import DumpGroup __all__ = [ "DumpObj", "DumpIndev", + "DumpGroup", ] diff --git a/scripts/gdb/lvglgdb/cmds/core/lv_group.py b/scripts/gdb/lvglgdb/cmds/core/lv_group.py new file mode 100644 index 0000000000..825910e3b2 --- /dev/null +++ b/scripts/gdb/lvglgdb/cmds/core/lv_group.py @@ -0,0 +1,16 @@ +import gdb + +from lvglgdb.lvgl import curr_inst +from lvglgdb.lvgl.core.lv_group import LVGroup + + +class DumpGroup(gdb.Command): + """dump all focus groups""" + + def __init__(self): + super(DumpGroup, self).__init__( + "dump group", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION + ) + + def invoke(self, args, from_tty): + LVGroup.print_entries(curr_inst().groups()) diff --git a/scripts/gdb/lvglgdb/lvgl/__init__.py b/scripts/gdb/lvglgdb/lvgl/__init__.py index 1e3a9ce19c..118077d513 100644 --- a/scripts/gdb/lvglgdb/lvgl/__init__.py +++ b/scripts/gdb/lvglgdb/lvgl/__init__.py @@ -6,6 +6,7 @@ from .core import ( dump_obj_styles, LVIndev, INDEV_TYPE_NAMES, + LVGroup, ) from .display import LVDisplay from .draw import ( @@ -94,4 +95,5 @@ __all__ = [ "LVFsDrv", "LVIndev", "INDEV_TYPE_NAMES", + "LVGroup", ] diff --git a/scripts/gdb/lvglgdb/lvgl/core/__init__.py b/scripts/gdb/lvglgdb/lvgl/core/__init__.py index 19d69b6301..5034f1c6b2 100644 --- a/scripts/gdb/lvglgdb/lvgl/core/__init__.py +++ b/scripts/gdb/lvglgdb/lvgl/core/__init__.py @@ -1,6 +1,7 @@ from .lv_obj import LVObject, ObjStyle, dump_obj_info, dump_obj_styles from .lv_global import curr_inst from .lv_indev import LVIndev, INDEV_TYPE_NAMES +from .lv_group import LVGroup __all__ = [ "LVObject", @@ -10,4 +11,5 @@ __all__ = [ "dump_obj_styles", "LVIndev", "INDEV_TYPE_NAMES", + "LVGroup", ] diff --git a/scripts/gdb/lvglgdb/lvgl/core/lv_global.py b/scripts/gdb/lvglgdb/lvgl/core/lv_global.py index b224d7682d..82231748cf 100644 --- a/scripts/gdb/lvglgdb/lvgl/core/lv_global.py +++ b/scripts/gdb/lvglgdb/lvgl/core/lv_global.py @@ -73,6 +73,12 @@ class LVGL: for timer in LVList(self.lv_global.timer_state.timer_ll, "lv_timer_t"): yield LVTimer(timer) + def groups(self): + from .lv_group import LVGroup + + for group in LVList(self.lv_global.group_ll, "lv_group_t"): + yield LVGroup(group) + def indevs(self): from .lv_indev import LVIndev diff --git a/scripts/gdb/lvglgdb/lvgl/core/lv_group.py b/scripts/gdb/lvglgdb/lvgl/core/lv_group.py new file mode 100644 index 0000000000..a0345f91c6 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/core/lv_group.py @@ -0,0 +1,88 @@ +from prettytable import PrettyTable + +from lvglgdb.value import Value, ValueInput +from ..misc.lv_ll import LVList + + +class LVGroup(Value): + """LVGL focus group wrapper""" + + def __init__(self, group: ValueInput): + super().__init__(Value.normalize(group, "lv_group_t")) + + @property + def frozen(self) -> bool: + return bool(int(self.super_value("frozen"))) + + @property + def editing(self) -> bool: + return bool(int(self.super_value("editing"))) + + @property + def wrap(self) -> bool: + return bool(int(self.super_value("wrap"))) + + @property + def obj_focus(self) -> Value: + focus_pp = self.super_value("obj_focus") + if not int(focus_pp): + return None + return focus_pp.dereference() + + @property + def focus_cb(self) -> Value: + return self.super_value("focus_cb") + + @property + def edge_cb(self) -> Value: + return self.super_value("edge_cb") + + @property + def user_data(self) -> Value: + return self.super_value("user_data") + + @property + def refocus_policy(self) -> bool: + return bool(int(self.super_value("refocus_policy"))) + + @property + def obj_count(self) -> int: + return LVList(self.obj_ll, "lv_obj_t").len + + def __iter__(self): + from .lv_obj import LVObject + + for obj_ptr in LVList(self.obj_ll, "lv_obj_t"): + yield LVObject(obj_ptr) + + @staticmethod + def print_entries(groups): + """Print focus groups as a PrettyTable.""" + table = PrettyTable() + table.field_names = ["#", "objects", "frozen", "editing", "wrap", "focused"] + table.align = "l" + + for i, group in enumerate(groups): + focus = group.obj_focus + if focus: + from .lv_obj import LVObject + + focus_obj = LVObject(focus) + focus_str = f"{focus_obj.class_name}@{int(focus):x}" + else: + focus_str = "(none)" + table.add_row( + [ + i, + group.obj_count, + group.frozen, + group.editing, + group.wrap, + focus_str, + ] + ) + + if not table.rows: + print("No focus groups.") + else: + print(table)