@@ -320,6 +320,9 @@ static void unregister_custom_widget(twin_widget_t *widget)
320320 custom_widget_map_t * * prev = & custom_widget_map ;
321321 custom_widget_map_t * entry = custom_widget_map ;
322322
323+ if (!widget )
324+ return ;
325+
323326 while (entry ) {
324327 if (entry -> widget == widget ) {
325328 * prev = entry -> next ;
@@ -334,6 +337,26 @@ static void unregister_custom_widget(twin_widget_t *widget)
334337static twin_dispatch_result_t custom_widget_dispatch (twin_widget_t * widget ,
335338 twin_event_t * event )
336339{
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+
337360 /* First call the base widget dispatch to handle standard widget behavior */
338361 twin_dispatch_result_t result = _twin_widget_dispatch (widget , event );
339362 if (result == TwinDispatchDone )
@@ -396,6 +419,9 @@ void twin_custom_widget_destroy(twin_custom_widget_t *custom)
396419 return ;
397420
398421 if (custom -> widget ) {
422+ /* Unregister from dispatch map (idempotent if already done during
423+ * TwinEventDestroy)
424+ */
399425 unregister_custom_widget (custom -> widget );
400426 /* Note: widget destruction should be handled by the parent/container */
401427 }
0 commit comments