Skip to content

Commit 3249490

Browse files
committed
fix(gui): the node should unlinked before destroying widget
1 parent 2f3e409 commit 3249490

4 files changed

Lines changed: 59 additions & 51 deletions

File tree

include/LCUI/gui/widget_base.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,8 @@ LCUI_API int Widget_RemoveStatus(LCUI_Widget w, const char *status_name);
449449
/** 打印部件树 */
450450
LCUI_API void Widget_PrintTree(LCUI_Widget w);
451451

452+
LCUI_API void LCUIWidget_ClearTrash(void);
453+
452454
LCUI_API void LCUIWidget_InitBase(void);
453455

454456
LCUI_API void LCUIWidget_FreeRoot(void);

include/LCUI/gui/widget_task.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,6 @@ LCUI_API void Widget_AddTask(LCUI_Widget widget, int task_type);
4242
/** 处理部件中当前积累的任务 */
4343
LCUI_API int Widget_Update(LCUI_Widget w);
4444

45-
/** 将部件标记为垃圾,等待销毁 */
46-
LCUI_API void Widget_AddToTrash(LCUI_Widget w);
47-
4845
/** 为子级部件添加任务 */
4946
LCUI_API void Widget_AddTaskForChildren(LCUI_Widget widget, int task);
5047

src/gui/widget_base.c

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,21 @@
3232
#include <stdlib.h>
3333
#include <errno.h>
3434
#include <string.h>
35+
#include <assert.h>
3536
#include <LCUI_Build.h>
3637
#include <LCUI/LCUI.h>
3738
#include <LCUI/gui/widget.h>
3839
#include <LCUI/gui/metrics.h>
3940

4041
static struct LCUI_WidgetModule {
41-
LCUI_Widget root; /**< 根级部件 */
4242
Dict *ids; /**< 各种部件的ID索引 */
43-
LCUI_Mutex mutex; /**< 互斥锁 */
4443
DictType dt_ids; /**< 部件ID映射表的类型模板 */
4544
DictType dt_attributes; /**< 部件属性表的类型模板 */
45+
46+
LCUI_Widget root; /**< 根级部件 */
47+
LCUI_Mutex mutex; /**< 互斥锁 */
48+
49+
LinkedList trash; /**< 待删除的部件列表 */
4650
} LCUIWidget;
4751

4852
#define StrList_Destroy freestrs
@@ -103,6 +107,32 @@ static void Widget_UpdateStatus(LCUI_Widget widget)
103107
}
104108
}
105109

110+
void LCUIWidget_ClearTrash(void)
111+
{
112+
LinkedListNode *node;
113+
node = LCUIWidget.trash.head.next;
114+
while (node) {
115+
LinkedListNode *next = node->next;
116+
LinkedList_Unlink(&LCUIWidget.trash, node);
117+
Widget_ExecDestroy(node->data);
118+
node = next;
119+
}
120+
}
121+
122+
static void Widget_AddToTrash(LCUI_Widget w)
123+
{
124+
LCUI_WidgetEventRec e = { 0 };
125+
e.type = LCUI_WEVENT_UNLINK;
126+
w->state = LCUI_WSTATE_DELETED;
127+
Widget_TriggerEvent(w, &e, NULL);
128+
if (!w->parent) {
129+
return;
130+
}
131+
Widget_Unlink(w);
132+
LinkedList_AppendNode(&LCUIWidget.trash, &w->node);
133+
Widget_PostSurfaceEvent(w, LCUI_WEVENT_UNLINK, TRUE);
134+
}
135+
106136
int Widget_Unlink(LCUI_Widget widget)
107137
{
108138
LCUI_Widget child;
@@ -223,44 +253,47 @@ int Widget_Prepend(LCUI_Widget parent, LCUI_Widget widget)
223253

224254
int Widget_Unwrap(LCUI_Widget widget)
225255
{
226-
int i;
256+
size_t len;
227257
LCUI_Widget child;
228-
LinkedList *list, *list_show;
258+
LinkedList *children, *children_show;
229259
LinkedListNode *target, *node, *prev, *snode;
230260

231261
if (!widget->parent) {
232262
return -1;
233263
}
234-
list = &widget->parent->children;
235-
list_show = &widget->parent->children_show;
236-
if (widget->children.length > 0) {
264+
children = &widget->parent->children;
265+
children_show = &widget->parent->children_show;
266+
len = widget->children.length;
267+
if (len > 0) {
237268
node = LinkedList_GetNode(&widget->children, 0);
238269
Widget_RemoveStatus(node->data, "first-child");
239270
node = LinkedList_GetNodeAtTail(&widget->children, 0);
240271
Widget_RemoveStatus(node->data, "last-child");
241272
}
242273
node = &widget->node;
243-
i = widget->children.length;
244274
target = node->prev;
245275
node = widget->children.tail.prev;
246-
while (i-- > 0) {
276+
while (len > 0) {
277+
assert(node != NULL);
278+
assert(node->data != NULL);
247279
prev = node->prev;
248280
child = node->data;
249281
snode = &child->node_show;
250282
LinkedList_Unlink(&widget->children, node);
251283
LinkedList_Unlink(&widget->children_show, snode);
252284
child->parent = widget->parent;
253-
LinkedList_Link(list, target, node);
254-
LinkedList_AppendNode(list_show, snode);
285+
LinkedList_Link(children, target, node);
286+
LinkedList_AppendNode(children_show, snode);
255287
Widget_AddTaskForChildren(child, LCUI_WTASK_REFRESH_STYLE);
256288
Widget_UpdateTaskStatus(child);
257289
node = prev;
290+
--len;
258291
}
259292
if (widget->index == 0) {
260293
Widget_AddStatus(target->next->data, "first-child");
261294
}
262-
if (widget->index == list->length - 1) {
263-
node = LinkedList_GetNodeAtTail(list, 0);
295+
if (widget->index == children->length - 1) {
296+
node = LinkedList_GetNodeAtTail(children, 0);
264297
Widget_AddStatus(node->data, "last-child");
265298
}
266299
Widget_Destroy(widget);
@@ -325,6 +358,11 @@ static void Widget_OnDestroy(void *arg)
325358
void Widget_ExecDestroy(LCUI_Widget widget)
326359
{
327360
LCUI_WidgetEventRec e = { LCUI_WEVENT_DESTROY, 0 };
361+
362+
if (widget->parent) {
363+
Widget_UpdateLayout(widget->parent);
364+
Widget_Unlink(widget);
365+
}
328366
Widget_TriggerEvent(widget, &e, NULL);
329367
Widget_ReleaseMouseCapture(widget);
330368
Widget_ReleaseTouchCapture(widget, -1);
@@ -340,9 +378,6 @@ void Widget_ExecDestroy(LCUI_Widget widget)
340378
StyleSheet_Delete(widget->inherited_style);
341379
StyleSheet_Delete(widget->custom_style);
342380
StyleSheet_Delete(widget->style);
343-
if (widget->parent) {
344-
Widget_UpdateLayout(widget->parent);
345-
}
346381
if (widget->title) {
347382
free(widget->title);
348383
widget->title = NULL;
@@ -361,6 +396,7 @@ void Widget_Destroy(LCUI_Widget w)
361396
while (root->parent) {
362397
root = root->parent;
363398
}
399+
/* If this widget is not mounted in the root widget tree */
364400
if (root != LCUIWidget.root) {
365401
LCUI_WidgetEventRec e = { 0 };
366402
e.type = LCUI_WEVENT_UNLINK;
@@ -372,8 +408,9 @@ void Widget_Destroy(LCUI_Widget w)
372408
if (w->parent) {
373409
LCUI_Widget child;
374410
LinkedListNode *node;
375-
node = &w->node;
376-
node = node->next;
411+
412+
/* Update the index of the siblings behind it */
413+
node = w->node.next;
377414
while (node) {
378415
child = node->data;
379416
child->index -= 1;
@@ -1727,6 +1764,7 @@ static void OnClearWidgetList(void *privdata, void *data)
17271764

17281765
void LCUIWidget_InitBase(void)
17291766
{
1767+
LinkedList_Init(&LCUIWidget.trash);
17301768
LCUIMutex_Init(&LCUIWidget.mutex);
17311769
LCUIWidget.root = LCUIWidget_New("root");
17321770
LCUIWidget.dt_ids = DictType_StringCopyKey;

src/gui/widget_task.c

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@
3737

3838
/** 部件任务模块数据 */
3939
static struct WidgetTaskModule {
40-
LinkedList trash; /**< 待删除的部件列表 */
4140
LCUI_WidgetFunction handlers[LCUI_WTASK_TOTAL_NUM]; /**< 任务处理器 */
42-
unsigned int update_count; /**< 刷新次数 */
41+
unsigned int update_count; /**< 刷新次数 */
4342
} self;
4443

4544
static void HandleRefreshStyle(LCUI_Widget w)
@@ -139,42 +138,14 @@ static void MapTaskHandler(void)
139138
SetHandler(PROPS, Widget_UpdateProps);
140139
}
141140

142-
static void LCUIWidget_ClearTrash(void)
143-
{
144-
LinkedListNode *node;
145-
node = self.trash.head.next;
146-
while (node) {
147-
LinkedListNode *next = node->next;
148-
LinkedList_Unlink(&self.trash, node);
149-
Widget_ExecDestroy(node->data);
150-
node = next;
151-
}
152-
}
153-
154141
void LCUIWidget_InitTasks(void)
155142
{
156143
MapTaskHandler();
157-
LinkedList_Init(&self.trash);
158144
}
159145

160146
void LCUIWidget_FreeTasks(void)
161147
{
162-
LCUIWidget_ClearTrash();
163-
}
164148

165-
void Widget_AddToTrash(LCUI_Widget w)
166-
{
167-
LCUI_WidgetEventRec e = { 0 };
168-
e.type = LCUI_WEVENT_UNLINK;
169-
w->state = LCUI_WSTATE_DELETED;
170-
Widget_TriggerEvent(w, &e, NULL);
171-
if (!w->parent) {
172-
return;
173-
}
174-
LinkedList_Unlink(&w->parent->children, &w->node);
175-
LinkedList_Unlink(&w->parent->children_show, &w->node_show);
176-
LinkedList_AppendNode(&self.trash, &w->node);
177-
Widget_PostSurfaceEvent(w, LCUI_WEVENT_UNLINK, TRUE);
178149
}
179150

180151
int Widget_Update(LCUI_Widget w)

0 commit comments

Comments
 (0)