------------------------------------------------------------------------ r11938 | mortenmacfly | 2020-01-05 00:41:53 +0900 (Sun, 05 Jan 2020) | 1 line * applied patch #805: Flashing icons in Windows' taskbar while starting C::B. Thanks Miguel Gimenez. ------------------------------------------------------------------------ Index: src/include/compiler.h =================================================================== --- src/include/compiler.h (revision 11937) +++ src/include/compiler.h (revision 11938) @@ -100,12 +100,12 @@ } RegExStruct& operator=(const RegExStruct &obj) { - desc=obj.desc; - lt=obj.lt; - regex=obj.regex; - regexCompiled=false; - filename=obj.filename; - line=obj.line; + desc = obj.desc; + lt = obj.lt; + regex = obj.regex; + regexCompiled = false; + filename = obj.filename; + line = obj.line; memcpy(msg, obj.msg, sizeof(msg)); return *this; @@ -404,6 +404,9 @@ // keeps a copy of current settings (works only the first time it's called) void MirrorCurrentSettings(); + // execute without creating taskbar icon + long Execute(const wxString& cmd, wxArrayString& output); + // set the following members in your class wxString m_Name; wxString m_MasterPath; Index: src/plugins/compilergcc/compilerMINGW.cpp =================================================================== --- src/plugins/compilergcc/compilerMINGW.cpp (revision 11937) +++ src/plugins/compilergcc/compilerMINGW.cpp (revision 11938) @@ -173,7 +173,7 @@ { // Manager::Get()->GetLogManager()->DebugLog(_T("Compiler detection for compiler ID: '") + GetID() + _T("' (parent ID= '") + GetParentID() + _T("')")); - wxArrayString output, errors; + wxArrayString output; wxString sep = wxFileName::GetPathSeparator(); wxString master_path = m_MasterPath; wxString compiler_exe = m_Programs.C; @@ -223,16 +223,7 @@ // Manager::Get()->GetLogManager()->DebugLog(_T("Compiler version detection: Issuing command: ") + gcc_command); - int flags = wxEXEC_SYNC; -#if wxCHECK_VERSION(3, 0, 0) - // Stop event-loop while wxExecute runs, to avoid a deadlock on startup, - // that occurs from time to time on wx3 - flags |= wxEXEC_NOEVENTS; -#else - flags |= wxEXEC_NODISABLE; -#endif - long result = wxExecute(gcc_command + _T(" --version"), output, errors, flags ); - if(result != 0) + if ( Execute(gcc_command + _T(" --version"), output) != 0 ) { // Manager::Get()->GetLogManager()->DebugLog(_T("Compiler version detection: Error executing command.")); } Index: src/sdk/compiler.cpp =================================================================== --- src/sdk/compiler.cpp (revision 11937) +++ src/sdk/compiler.cpp (revision 11938) @@ -20,7 +20,9 @@ #include "compilerfactory.h" #include + #include #include + #include #endif #include "compilercommandgenerator.h" @@ -28,7 +30,6 @@ #include #include - // static wxArrayString Compiler::m_CompilerIDs; // map to guarantee unique IDs @@ -1229,18 +1230,7 @@ long ret = -1; if ( !cmd[0].IsEmpty() ) // should never be empty - { - int flags = wxEXEC_SYNC; - #if wxCHECK_VERSION(3, 0, 0) - // Stop event-loop while wxExecute runs, to avoid a deadlock on startup, - // that occurs from time to time on wx3 - flags |= wxEXEC_NOEVENTS; - #else - flags |= wxEXEC_NODISABLE; - #endif - wxLogNull logNo; // do not warn if execution fails - ret = wxExecute(GetStringFromArray(cmd, wxT(" "), false), cmd, flags); - } + ret = Execute(GetStringFromArray(cmd, wxT(" "), false), cmd); if (ret != 0) // execution failed val = (node->GetAttribute(wxT("default"), wxEmptyString) == wxT("true")); @@ -1284,3 +1274,93 @@ ret = m_Programs.MAKE; return ret; } + +#ifdef __WXMSW__ + +// In MSW calling wxExecute in synchronous mode while the main window is not visible makes +// the system show a C::B icon in the taskbar. When this is made repeatedly (as in compiler +// loading) the result is a stream of flashing icons. +// However, wxExecute in asynchronous mode does not do this. The caveat is that we must wait +// in a loop for the end of the task and extract the command output in a separate step. + +// This auxiliary class is needed for detecting the end of the task and retrieving the ouput. +// OnTerminate() will be called when the task ends with the return code of the task, and then +// the task output can be retrieved (as a stream). + +class ExecProcess : public wxProcess +{ + public: + ExecProcess(cb_unused wxEvtHandler *parent = NULL, cb_unused int id = -1) + { + m_status = 0; + } + + long GetStatus() const {return m_status;} + wxSemaphore &GetSemaphore() {return m_semaphore;} + void OnTerminate(cb_unused int pid, int status) + { + m_status = status; + m_semaphore.Post(); + } + + protected: + long m_status; + wxSemaphore m_semaphore; +}; + +// Emulates wxExecute() in synchronous mode using asynchronous mode + +long Compiler::Execute(const wxString &cmd, wxArrayString &output) +{ + wxLogNull logNo; // do not warn if execution fails + + output.Clear(); + + ExecProcess process; + process.Redirect(); // capture task input/output streams + + // wxExecute in asynchronous mode returns 0 if execution failed. + // Return -1 emulating the behaviour of wxExecute in synchronous mode + if ( !wxExecute(cmd, wxEXEC_ASYNC, &process) ) + return -1; + + // Wait for the end of the task + for (;;) + { + Manager::Yield(); // needed for semaphore update + if (process.GetSemaphore().WaitTimeout(25) == wxSEMA_NO_ERROR) + break; + } + + // Loads the wxArrayString with the task output (returned in a wxInputStream) + wxInputStream *inputStream = process.GetInputStream(); + wxTextInputStream text(*inputStream); +#if wxCHECK_VERSION(3, 0, 0) + while (!text.GetInputStream().Eof()) +#else + while (!inputStream->Eof()) +#endif + { + output.Add(text.ReadLine()); + } + + // Return task exit code emulating the behaviour of wxExecute in synchronous mode + return process.GetStatus(); +} + +#else // __WXMSW__ + +long Compiler::Execute(const wxString &cmd, wxArrayString &output) +{ + wxLogNull logNo; // do not warn if execution fails + int flags = wxEXEC_SYNC; + #if wxCHECK_VERSION(3, 0, 0) + // Stop event-loop while wxExecute runs, to avoid a deadlock on startup, + // that occurs from time to time on wx3 + flags |= wxEXEC_NOEVENTS; + #else + flags |= wxEXEC_NODISABLE; + #endif + return wxExecute(cmd, output, flags); +} +#endif // __WXMSW__