@@ -667,8 +667,8 @@ void MCPlatformSetSystemProperty(MCPlatformSystemProperty p_property, MCPlatform
667667 bool is_done;
668668};
669669
670- static MCModalSession * s_modal_sessions = nil ;
671- static uindex_t s_modal_session_count = 0 ;
670+ static MCAutoArray< MCModalSession> s_modal_sessions;
671+ static MCAutoArray<MCModalSession> s_modal_sessions_pending_cleanup ;
672672static uindex_t s_modal_session_run_depth = 0 ;
673673
674674struct MCCallback
@@ -787,7 +787,7 @@ bool MCPlatformWaitForEvent(double p_duration, bool p_blocking)
787787 s_in_blocking_wait = true ;
788788
789789 bool t_modal;
790- t_modal = s_modal_session_count > 0 ;
790+ t_modal = s_modal_sessions. Size () > 0 ;
791791
792792 NSAutoreleasePool *t_pool;
793793 t_pool = [[NSAutoreleasePool alloc ] init ];
@@ -802,11 +802,14 @@ bool MCPlatformWaitForEvent(double p_duration, bool p_blocking)
802802 // the modal session, e.g. when losing window focus).
803803 // Check the modal run depth to prevent re-entering a modal session that
804804 // is already being run.
805- if (s_modal_session_run_depth < s_modal_session_count && s_modal_sessions[s_modal_session_run_depth].session != nil )
805+ if (s_modal_session_run_depth < s_modal_sessions. Size () && s_modal_sessions[s_modal_session_run_depth].session != nil )
806806 {
807807 s_modal_session_run_depth++;
808808 [NSApp runModalSession: s_modal_sessions[s_modal_session_run_depth - 1 ].session];
809809 s_modal_session_run_depth--;
810+
811+ // clean up modal sessions
812+ MCMacPlatformCleanupModalSessions ();
810813 }
811814
812815 t_event = nil ;
@@ -873,38 +876,59 @@ void MCMacPlatformBeginModalSession(MCMacPlatformWindow *p_window)
873876 // current mouse window.
874877 MCMacPlatformSyncMouseBeforeDragging ();
875878
876- /* UNCHECKED */ MCMemoryResizeArray (s_modal_session_count + 1 , s_modal_sessions, s_modal_session_count) ;
879+ MCModalSession t_session ;
877880
878- s_modal_sessions[s_modal_session_count - 1 ] . is_done = false ;
879- s_modal_sessions[s_modal_session_count - 1 ] . window = p_window;
881+ t_session. is_done = false ;
882+ t_session. window = p_window;
880883 p_window -> Retain ();
881884 // IM-2015-01-30: [[ Bug 14140 ]] lock the window frame to prevent it from being centered on the screen.
882885 p_window->SetFrameLocked (true );
883- s_modal_sessions[s_modal_session_count - 1 ] . session = [NSApp beginModalSessionForWindow: (NSWindow *)(p_window -> GetHandle ())];
886+
887+ t_session.session = [NSApp beginModalSessionForWindow: (NSWindow *)(p_window -> GetHandle ())];
888+ /* UNCHECKED */ s_modal_sessions.Push (t_session);
889+
884890 p_window->SetFrameLocked (false );
885891}
886892
887893void MCMacPlatformEndModalSession (MCMacPlatformWindow *p_window)
888894{
889895 uindex_t t_index;
890- for (t_index = 0 ; t_index < s_modal_session_count ; t_index++)
896+ for (t_index = 0 ; t_index < s_modal_sessions. Size () ; t_index++)
891897 if (s_modal_sessions[t_index] . window == p_window)
892898 break ;
893899
894- if (t_index == s_modal_session_count )
900+ if (t_index == s_modal_sessions. Size () )
895901 return ;
896902
897903 s_modal_sessions[t_index] . is_done = true ;
898904
899- for (uindex_t t_final_index = s_modal_session_count; t_final_index > 0 ; t_final_index--)
905+ /* Pop all modal sessions which are now complete. All those which are
906+ * get pushed onto a list to be destroyed later. */
907+ while (s_modal_sessions.Size () > 0 )
900908 {
901- if (!s_modal_sessions[t_final_index - 1 ] . is_done)
909+ if (!s_modal_sessions[s_modal_sessions. Size () - 1 ] . is_done)
902910 return ;
903911
904- [NSApp endModalSession: s_modal_sessions[t_final_index - 1 ] . session];
905- [s_modal_sessions[t_final_index - 1 ] . window -> GetHandle () orderOut: nil ];
906- s_modal_sessions[t_final_index - 1 ] . window -> Release ();
907- s_modal_session_count -= 1 ;
912+ MCModalSession t_session;
913+ /* UNCHECKED */ s_modal_sessions.Pop (t_session);
914+ /* UNCHECKED */ s_modal_sessions_pending_cleanup.Push (t_session);
915+
916+ [NSApp endModalSession: t_session.session];
917+ }
918+ }
919+
920+ /* Process all modal sessions which are pending destruction. This
921+ * ensures that windows don't get hidden and destroyed at the wrong
922+ * time (e.g. within a nested modal session!). */
923+ void MCMacPlatformCleanupModalSessions (void )
924+ {
925+ while (s_modal_sessions_pending_cleanup.Size () > 0 )
926+ {
927+ MCModalSession t_session;
928+ /* UNCHECKED */ s_modal_sessions_pending_cleanup.Pop (t_session);
929+
930+ [t_session.window->GetHandle () orderOut: nil ];
931+ t_session.window ->Release ();
908932 }
909933}
910934
0 commit comments