@@ -667,8 +667,9 @@ 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;
672+ static uindex_t s_modal_session_run_depth = 0 ;
672673
673674struct MCCallback
674675{
@@ -786,7 +787,7 @@ bool MCPlatformWaitForEvent(double p_duration, bool p_blocking)
786787 s_in_blocking_wait = true ;
787788
788789 bool t_modal;
789- t_modal = s_modal_session_count > 0 ;
790+ t_modal = s_modal_sessions. Size () > 0 ;
790791
791792 NSAutoreleasePool *t_pool;
792793 t_pool = [[NSAutoreleasePool alloc ] init ];
@@ -805,8 +806,17 @@ bool MCPlatformWaitForEvent(double p_duration, bool p_blocking)
805806 // Run the modal session, if it has been created yet (it might not if this
806807 // wait was triggered by reacting to an event caused as part of creating
807808 // the modal session, e.g. when losing window focus).
808- if (s_modal_sessions[s_modal_session_count - 1 ].session != nil )
809- [NSApp runModalSession: s_modal_sessions[s_modal_session_count - 1 ] . session];
809+ // Check the modal run depth to prevent re-entering a modal session that
810+ // is already being run.
811+ if (s_modal_session_run_depth < s_modal_sessions.Size () && s_modal_sessions[s_modal_session_run_depth].session != nil )
812+ {
813+ s_modal_session_run_depth++;
814+ [NSApp runModalSession: s_modal_sessions[s_modal_session_run_depth - 1 ].session];
815+ s_modal_session_run_depth--;
816+
817+ // clean up modal sessions
818+ MCMacPlatformCleanupModalSessions ();
819+ }
810820
811821 t_event = nil ;
812822 }
@@ -842,38 +852,59 @@ void MCMacPlatformBeginModalSession(MCMacPlatformWindow *p_window)
842852 // current mouse window.
843853 MCMacPlatformSyncMouseBeforeDragging ();
844854
845- /* UNCHECKED */ MCMemoryResizeArray (s_modal_session_count + 1 , s_modal_sessions, s_modal_session_count) ;
855+ MCModalSession t_session ;
846856
847- s_modal_sessions[s_modal_session_count - 1 ] . is_done = false ;
848- s_modal_sessions[s_modal_session_count - 1 ] . window = p_window;
857+ t_session. is_done = false ;
858+ t_session. window = p_window;
849859 p_window -> Retain ();
850860 // IM-2015-01-30: [[ Bug 14140 ]] lock the window frame to prevent it from being centered on the screen.
851861 p_window->SetFrameLocked (true );
852- s_modal_sessions[s_modal_session_count - 1 ] . session = [NSApp beginModalSessionForWindow: (NSWindow *)(p_window -> GetHandle ())];
862+
863+ t_session.session = [NSApp beginModalSessionForWindow: (NSWindow *)(p_window -> GetHandle ())];
864+ /* UNCHECKED */ s_modal_sessions.Push (t_session);
865+
853866 p_window->SetFrameLocked (false );
854867}
855868
856869void MCMacPlatformEndModalSession (MCMacPlatformWindow *p_window)
857870{
858871 uindex_t t_index;
859- for (t_index = 0 ; t_index < s_modal_session_count ; t_index++)
872+ for (t_index = 0 ; t_index < s_modal_sessions. Size () ; t_index++)
860873 if (s_modal_sessions[t_index] . window == p_window)
861874 break ;
862875
863- if (t_index == s_modal_session_count )
876+ if (t_index == s_modal_sessions. Size () )
864877 return ;
865878
866879 s_modal_sessions[t_index] . is_done = true ;
867880
868- for (uindex_t t_final_index = s_modal_session_count; t_final_index > 0 ; t_final_index--)
881+ /* Pop all modal sessions which are now complete. All those which are
882+ * get pushed onto a list to be destroyed later. */
883+ while (s_modal_sessions.Size () > 0 )
869884 {
870- if (!s_modal_sessions[t_final_index - 1 ] . is_done)
885+ if (!s_modal_sessions[s_modal_sessions. Size () - 1 ] . is_done)
871886 return ;
872887
873- [NSApp endModalSession: s_modal_sessions[t_final_index - 1 ] . session];
874- [s_modal_sessions[t_final_index - 1 ] . window -> GetHandle () orderOut: nil ];
875- s_modal_sessions[t_final_index - 1 ] . window -> Release ();
876- s_modal_session_count -= 1 ;
888+ MCModalSession t_session;
889+ /* UNCHECKED */ s_modal_sessions.Pop (t_session);
890+ /* UNCHECKED */ s_modal_sessions_pending_cleanup.Push (t_session);
891+
892+ [NSApp endModalSession: t_session.session];
893+ }
894+ }
895+
896+ /* Process all modal sessions which are pending destruction. This
897+ * ensures that windows don't get hidden and destroyed at the wrong
898+ * time (e.g. within a nested modal session!). */
899+ void MCMacPlatformCleanupModalSessions (void )
900+ {
901+ while (s_modal_sessions_pending_cleanup.Size () > 0 )
902+ {
903+ MCModalSession t_session;
904+ /* UNCHECKED */ s_modal_sessions_pending_cleanup.Pop (t_session);
905+
906+ [t_session.window->GetHandle () orderOut: nil ];
907+ t_session.window ->Release ();
877908 }
878909}
879910
0 commit comments