@@ -320,6 +320,9 @@ static void unregister_custom_widget(twin_widget_t *widget)
320
320
custom_widget_map_t * * prev = & custom_widget_map ;
321
321
custom_widget_map_t * entry = custom_widget_map ;
322
322
323
+ if (!widget )
324
+ return ;
325
+
323
326
while (entry ) {
324
327
if (entry -> widget == widget ) {
325
328
* prev = entry -> next ;
@@ -334,6 +337,26 @@ static void unregister_custom_widget(twin_widget_t *widget)
334
337
static twin_dispatch_result_t custom_widget_dispatch (twin_widget_t * widget ,
335
338
twin_event_t * event )
336
339
{
340
+ /* Handle destroy events specially to ensure proper cleanup order */
341
+ if (event -> kind == TwinEventDestroy ) {
342
+ /* Find and call user dispatch first if it exists */
343
+ custom_widget_map_t * entry = custom_widget_map ;
344
+ while (entry ) {
345
+ if (entry -> widget == widget ) {
346
+ if (entry -> user_dispatch )
347
+ entry -> user_dispatch (widget , event );
348
+ break ;
349
+ }
350
+ entry = entry -> next ;
351
+ }
352
+
353
+ /* Unregister from custom widget map before base destruction */
354
+ unregister_custom_widget (widget );
355
+
356
+ /* Now call base widget dispatch to complete destruction */
357
+ return _twin_widget_dispatch (widget , event );
358
+ }
359
+
337
360
/* First call the base widget dispatch to handle standard widget behavior */
338
361
twin_dispatch_result_t result = _twin_widget_dispatch (widget , event );
339
362
if (result == TwinDispatchDone )
@@ -396,6 +419,9 @@ void twin_custom_widget_destroy(twin_custom_widget_t *custom)
396
419
return ;
397
420
398
421
if (custom -> widget ) {
422
+ /* Unregister from dispatch map (idempotent if already done during
423
+ * TwinEventDestroy)
424
+ */
399
425
unregister_custom_widget (custom -> widget );
400
426
/* Note: widget destruction should be handled by the parent/container */
401
427
}
0 commit comments