From 99eba63796143bf75704e387b2ab4c49369ebd7c Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Mon, 27 Aug 2018 11:50:35 +0200 Subject: [PATCH] use Cocoa fix for nested modal loops for system dialogs also --- src/osx/carbon/colordlgosx.mm | 4 ++-- src/osx/carbon/fontdlg.cpp | 4 ++-- src/osx/carbon/fontdlgosx.mm | 4 ++-- src/osx/cocoa/dialog.mm | 26 ++++++++++++++++++++++++++ src/osx/cocoa/dirdlg.mm | 5 +++++ src/osx/cocoa/evtloop.mm | 17 ----------------- src/osx/cocoa/filedlg.mm | 5 +++++ src/osx/cocoa/msgdlg.mm | 5 +++++ src/osx/cocoa/printdlg.mm | 9 +++++++++ src/osx/dialog_osx.cpp | 32 +++++++++++++++++++++++++------- 10 files changed, 81 insertions(+), 30 deletions(-) diff --git a/src/osx/carbon/colordlgosx.mm b/src/osx/carbon/colordlgosx.mm index 6a63af1197..92d6e03df7 100644 --- a/src/osx/carbon/colordlgosx.mm +++ b/src/osx/carbon/colordlgosx.mm @@ -140,7 +140,7 @@ int wxColourDialog::ShowModal() // // Start the color panel modal loop // - wxDialog::OSXBeginModalDialog(); + OSXBeginModalDialog(); NSModalSession session = [NSApp beginModalSessionForWindow:theColorPanel]; for (;;) { @@ -151,7 +151,7 @@ int wxColourDialog::ShowModal() break; } [NSApp endModalSession:session]; - wxDialog::OSXEndModalDialog(); + OSXEndModalDialog(); //free up the memory for the delegates - we don't need them anymore [theColorPanel setDelegate:nil]; diff --git a/src/osx/carbon/fontdlg.cpp b/src/osx/carbon/fontdlg.cpp index a6dadb57ef..470189ce73 100644 --- a/src/osx/carbon/fontdlg.cpp +++ b/src/osx/carbon/fontdlg.cpp @@ -86,9 +86,9 @@ int wxFontDialog::ShowModal() { WX_HOOK_MODAL_DIALOG(); - wxDialog::OSXBeginModalDialog(); + OSXBeginModalDialog(); int retval = RunMixedFontDialog(this); - wxDialog::OSXEndModalDialog(); + OSXEndModalDialog(); return retval ; } diff --git a/src/osx/carbon/fontdlgosx.mm b/src/osx/carbon/fontdlgosx.mm index 7168b5a484..b61908f0c4 100644 --- a/src/osx/carbon/fontdlgosx.mm +++ b/src/osx/carbon/fontdlgosx.mm @@ -532,7 +532,7 @@ int wxFontDialog::ShowModal() // the color panel until the color panel closes, switching // back to the font panel modal loop once it does close. // - wxDialog::OSXBeginModalDialog(); + OSXBeginModalDialog(); do { // @@ -571,7 +571,7 @@ int wxFontDialog::ShowModal() //out of its modal loop because the color panel was //opened) return the font panel modal loop }while([theFPDelegate isClosed] == NO); - wxDialog::OSXEndModalDialog(); + OSXEndModalDialog(); //free up the memory for the delegates - we don't need them anymore [theFPDelegate release]; diff --git a/src/osx/cocoa/dialog.mm b/src/osx/cocoa/dialog.mm index 8b1e48f1b4..d34fa5cb0b 100644 --- a/src/osx/cocoa/dialog.mm +++ b/src/osx/cocoa/dialog.mm @@ -44,3 +44,29 @@ void wxDialog::EndWindowModal() [NSApp endSheet: GetWXWindow()]; [GetWXWindow() orderOut:GetWXWindow()]; } + +bool wxDialog::OSXGetWorksWhenModal() +{ + bool worksWhenModal = false; + + NSWindow* nswindow = IsModal() ? GetWXWindow() : nil; + if ( nswindow != nil ) + { + if ( [nswindow isKindOfClass:[NSPanel class]] && [(NSPanel*)nswindow worksWhenModal] == YES ) + { + [(NSPanel*)nswindow setWorksWhenModal:NO]; + worksWhenModal = true; + } + } + return worksWhenModal; +} + +void wxDialog::OSXSetWorksWhenModal(bool worksWhenModal) +{ + NSWindow* nswindow = IsModal() ? GetWXWindow() : nil; + if ( nswindow != nil ) + { + if ( [nswindow isKindOfClass:[NSPanel class]] && [(NSPanel*)nswindow worksWhenModal] == YES ) + [(NSPanel*)nswindow setWorksWhenModal:worksWhenModal]; + } +} diff --git a/src/osx/cocoa/dirdlg.mm b/src/osx/cocoa/dirdlg.mm index f9ae000edb..c46c515a58 100644 --- a/src/osx/cocoa/dirdlg.mm +++ b/src/osx/cocoa/dirdlg.mm @@ -116,9 +116,14 @@ int wxDirDialog::ShowModal() m_path.clear(); int returnCode = -1; + + OSXBeginModalDialog(); returnCode = (NSInteger)[oPanel runModalForDirectory:dir.AsNSString() file:nil types:nil]; ModalFinishedCallback(oPanel, returnCode); + + OSXEndModalDialog(); + return GetReturnCode(); } diff --git a/src/osx/cocoa/evtloop.mm b/src/osx/cocoa/evtloop.mm index 558cbb2d4b..26169f86ab 100644 --- a/src/osx/cocoa/evtloop.mm +++ b/src/osx/cocoa/evtloop.mm @@ -436,26 +436,9 @@ void wxModalEventLoop::OSXDoRun() #if OSX_USE_MODAL_SESSION if ( m_modalWindow ) { - bool restoreWorksWhenModal = false; - wxDialog* const parentDialog = wxDynamicCast(wxGetTopLevelParent(m_modalWindow->GetParent()), wxDialog); - NSWindow* parentWindow = parentDialog && parentDialog->IsModal() ? parentDialog->GetWXWindow() : nil; - if ( parentWindow != nil ) - { - if ( [parentWindow isKindOfClass:[NSPanel class]] && [(NSPanel*)parentWindow worksWhenModal] == YES ) - { - [(NSPanel*)parentWindow setWorksWhenModal:NO]; - restoreWorksWhenModal = true; - } - } - BeginModalSession(m_modalWindow); wxCFEventLoop::OSXDoRun(); EndModalSession(); - - if ( restoreWorksWhenModal ) - { - [(NSPanel*)parentWindow setWorksWhenModal:YES]; - } } else #endif diff --git a/src/osx/cocoa/filedlg.mm b/src/osx/cocoa/filedlg.mm index fe69dfbd56..24fdc457f7 100644 --- a/src/osx/cocoa/filedlg.mm +++ b/src/osx/cocoa/filedlg.mm @@ -559,6 +559,8 @@ int wxFileDialog::ShowModal() wxGCC_WARNING_SUPPRESS(deprecated-declarations) + OSXBeginModalDialog(); + if ( HasFlag(wxFD_SAVE) ) { NSSavePanel* sPanel = [NSSavePanel savePanel]; @@ -627,6 +629,9 @@ int wxFileDialog::ShowModal() ModalFinishedCallback(oPanel, returnCode); } + + OSXEndModalDialog(); + wxGCC_WARNING_RESTORE(deprecated-declarations) diff --git a/src/osx/cocoa/msgdlg.mm b/src/osx/cocoa/msgdlg.mm index 1de7e7aa7a..ffaf9438ca 100644 --- a/src/osx/cocoa/msgdlg.mm +++ b/src/osx/cocoa/msgdlg.mm @@ -168,8 +168,13 @@ int wxMessageDialog::ShowModal() { NSAlert* alert = (NSAlert*)ConstructNSAlert(); + OSXBeginModalDialog(); + int button = -1; button = [alert runModal]; + + OSXEndModalDialog(); + ModalFinishedCallback(alert, button); [alert release]; } diff --git a/src/osx/cocoa/printdlg.mm b/src/osx/cocoa/printdlg.mm index 2b1c88a6ab..f873c4ce27 100644 --- a/src/osx/cocoa/printdlg.mm +++ b/src/osx/cocoa/printdlg.mm @@ -72,12 +72,16 @@ int wxMacPrintDialog::ShowModal() [dict setValue:[NSNumber numberWithInt:m_printDialogData.GetMinPage()] forKey:@"com_apple_print_PrintSettings_PMFirstPage"]; [dict setValue:[NSNumber numberWithInt:m_printDialogData.GetMaxPage()] forKey:@"com_apple_print_PrintSettings_PMLastPage"]; + OSXBeginModalDialog(); + if ( (NSInteger)[panel runModalWithPrintInfo:printInfo] == NSOKButton ) { result = wxID_OK; m_printDialogData.GetPrintData().ConvertFromNative(); ((wxOSXPrintData*)m_printDialogData.GetPrintData().GetNativeData())->TransferTo( &m_printDialogData ); } + + OSXEndModalDialog(); return result; } @@ -93,6 +97,9 @@ int wxMacPageSetupDialog::ShowModal() NSPageLayout *pageLayout = [NSPageLayout pageLayout]; NSPrintInfo* printInfo = ((wxOSXCocoaPrintData*)m_pageSetupData.GetPrintData().GetNativeData())->GetNSPrintInfo(); + + OSXBeginModalDialog(); + if ( [pageLayout runModalWithPrintInfo:printInfo] == NSOKButton ) { result = wxID_OK; @@ -100,6 +107,8 @@ int wxMacPageSetupDialog::ShowModal() m_pageSetupData.SetPaperSize( m_pageSetupData.GetPrintData().GetPaperSize() ); } + OSXEndModalDialog(); + return result; } diff --git a/src/osx/dialog_osx.cpp b/src/osx/dialog_osx.cpp index 750e6a2059..aeef9e0f1a 100644 --- a/src/osx/dialog_osx.cpp +++ b/src/osx/dialog_osx.cpp @@ -23,21 +23,39 @@ #include "wx/osx/private.h" -static int s_openDialogs = 0; +wxVector wxDialog::s_modalStack; +#if wxOSX_USE_COCOA +wxVector wxDialog::s_modalWorksStack; +#endif + bool wxDialog::OSXHasModalDialogsOpen() { - return s_openDialogs > 0; + return s_modalStack.size() > 0; } void wxDialog::OSXBeginModalDialog() { - s_openDialogs++; +#if wxOSX_USE_COCOA + // turning off worksWhenModal on 'parent' + if ( s_modalStack.size() > 0 ) + s_modalStack.back()->OSXSetWorksWhenModal(false); + s_modalWorksStack.push_back(OSXGetWorksWhenModal()); +#endif + + s_modalStack.push_back(this); } void wxDialog::OSXEndModalDialog() { - wxASSERT_MSG( s_openDialogs > 0, "incorrect internal modal dialog count"); - s_openDialogs--; + wxASSERT_MSG( s_modalStack.back() == this, "incorrect internal modal dialog stack"); + s_modalStack.pop_back(); +#if wxOSX_USE_COCOA + s_modalWorksStack.pop_back(); + + // restore worksWhenModal + if ( s_modalStack.size() > 0 ) + s_modalStack.back()->OSXSetWorksWhenModal(s_modalWorksStack.back()); +#endif } void wxDialog::Init() @@ -146,9 +164,9 @@ int wxDialog::ShowModal() wxModalEventLoop modalLoop(this); m_eventLoop = &modalLoop; - wxDialog::OSXBeginModalDialog(); + OSXBeginModalDialog(); modalLoop.Run(); - wxDialog::OSXEndModalDialog(); + OSXEndModalDialog(); m_eventLoop = NULL;