From f38f68999028a8ff8d3cd0b1cf4a0fc94af805b0 Mon Sep 17 00:00:00 2001
From: Vadim Zeitlin <vadim@wxwidgets.org>
Date: Sun, 19 Dec 2004 23:59:28 +0000
Subject: [PATCH] added wxEXEC_NODISABLE

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@31081 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/changes.txt           |  1 +
 docs/latex/wx/function.tex |  9 ++++++---
 include/wx/utils.h         |  7 ++++++-
 src/msw/utilsexc.cpp       | 17 ++++++++++++-----
 src/unix/utilsunx.cpp      | 10 +++++++---
 5 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/docs/changes.txt b/docs/changes.txt
index 04e981bdcd..e054637af0 100644
--- a/docs/changes.txt
+++ b/docs/changes.txt
@@ -12,6 +12,7 @@ All:
 - classes in the manual are now cross-referenced (Zbigniew Zagórski)
 - Norwegian (Bokmål) translation added (Hans F. Nordhaug)
 - wxDynamicLibrary::HasSymbol() added
+- added wxEXEC_NODISABLE flag to be used with wxExecute(wxEXEC_SYNC)
 - added wxTextInputStream::operator>>(wchar_t) for compilers which support this
 - added wxURI, a class for dealing with Uniform Resource Identifiers
 - changed wxURL to inherit from wxURI and provide assignment and comparison
diff --git a/docs/latex/wx/function.tex b/docs/latex/wx/function.tex
index 9abdc11976..bc1030da8a 100644
--- a/docs/latex/wx/function.tex
+++ b/docs/latex/wx/function.tex
@@ -553,9 +553,12 @@ In the case of synchronous execution, the return value is the exit code of
 the process (which terminates by the moment the function returns) and will be
 $-1$ if the process couldn't be started and typically 0 if the process
 terminated successfully. Also, while waiting for the process to
-terminate, wxExecute will call \helpref{wxYield}{wxyield}. The caller
-should ensure that this can cause no recursion, in the simplest case by
-calling \helpref{wxEnableTopLevelWindows(false)}{wxenabletoplevelwindows}.
+terminate, wxExecute will call \helpref{wxYield}{wxyield}. Because of this, by
+default this function disables all application windows to avoid unexpected
+reentrancies which could result from the users interaction with the program
+while the child process is running. If you are sure that it is safe to not
+disable the program windows, you may pass \texttt{wxEXEC\_NODISABLE} flag to
+prevent this automatic disabling from happening.
 
 For asynchronous execution, however, the return value is the process id and
 zero value indicates that the command could not be executed. As an added
diff --git a/include/wx/utils.h b/include/wx/utils.h
index a7aba4285c..2450c08a9b 100644
--- a/include/wx/utils.h
+++ b/include/wx/utils.h
@@ -173,7 +173,12 @@ enum
 
     // under Unix, if the process is the group leader then passing wxKILL_CHILDREN to wxKill
     // kills all children as well as pid
-    wxEXEC_MAKE_GROUP_LEADER = 4
+    wxEXEC_MAKE_GROUP_LEADER = 4,
+
+    // by default synchronous execution disables all program windows to avoid
+    // that the user interacts with the program while the child process is
+    // running, you can use this flag to prevent this from happening
+    wxEXEC_NODISABLE = 8
 };
 
 // Execute another program.
diff --git a/src/msw/utilsexc.cpp b/src/msw/utilsexc.cpp
index 8899b5e0f1..5ba14aad62 100644
--- a/src/msw/utilsexc.cpp
+++ b/src/msw/utilsexc.cpp
@@ -888,11 +888,17 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler)
         return pi.dwProcessId;
     }
 
-    wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
-    wxCHECK_MSG( traits, -1, _T("no wxAppTraits in wxExecute()?") );
+    wxAppTraits *traits = NULL;
+    void *cookie wxDUMMY_INITIALIZE(NULL);
+    if ( !(flags & wxEXEC_NODISABLE) )
+    {
+        if ( wxTheApp )
+            traits = wxTheApp->GetTraits();
+        wxCHECK_MSG( traits, -1, _T("no wxAppTraits in wxExecute()?") );
 
-    // disable all app windows while waiting for the child process to finish
-    void *cookie = traits->BeforeChildWaitLoop();
+        // disable all app windows while waiting for the child process to finish
+        cookie = traits->BeforeChildWaitLoop();
+    }
 
     // wait until the child process terminates
     while ( data->state )
@@ -910,7 +916,8 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler)
         traits->AlwaysYield();
     }
 
-    traits->AfterChildWaitLoop(cookie);
+    if ( traits )
+        traits->AfterChildWaitLoop(cookie);
 
     DWORD dwExitCode = data->dwExitCode;
     delete data;
diff --git a/src/unix/utilsunx.cpp b/src/unix/utilsunx.cpp
index 35a7529461..89dd3e65a8 100644
--- a/src/unix/utilsunx.cpp
+++ b/src/unix/utilsunx.cpp
@@ -1133,10 +1133,12 @@ int wxGUIAppTraits::WaitForChild(wxExecuteData& execData)
 {
     wxEndProcessData *endProcData = new wxEndProcessData;
 
+    const int flags = execData.flags;
+
     // wxAddProcessCallback is now (with DARWIN) allowed to call the
     // callback function directly if the process terminates before
     // the callback can be added to the run loop. Set up the endProcData.
-    if ( execData.flags & wxEXEC_SYNC )
+    if ( flags & wxEXEC_SYNC )
     {
         // we may have process for capturing the program output, but it's
         // not used in wxEndProcessData in the case of sync execution
@@ -1167,10 +1169,11 @@ int wxGUIAppTraits::WaitForChild(wxExecuteData& execData)
     execData.pipeEndProcDetect.Close();
 #endif // defined(__DARWIN__) && (defined(__WXMAC__) || defined(__WXCOCOA__))
 
-    if ( execData.flags & wxEXEC_SYNC )
+    if ( flags & wxEXEC_SYNC )
     {
         wxBusyCursor bc;
-        wxWindowDisabler wd;
+        wxWindowDisabler *wd = flags & wxEXEC_NODISABLE ? NULL
+                                                        : new wxWindowDisabler;
 
         // endProcData->pid will be set to 0 from GTK_EndProcessDetector when the
         // process terminates
@@ -1204,6 +1207,7 @@ int wxGUIAppTraits::WaitForChild(wxExecuteData& execData)
 
         int exitcode = endProcData->exitcode;
 
+        delete wd;
         delete endProcData;
 
         return exitcode;
-- 
2.50.0

