Don't create wrong wxAppTraits during wxApp construction
Creating wxAppTraits before the object of the user-defined class deriving from wxApp is fully constructed may result in creating a wrong traits object if the user class overrides CreateTraits() because the correct, i.e. user-defined, version isn't used if it's called from wx code. This had already happened before and was worked around back inbc334f39ec(Fixes Bug [ 930200 ] Async does not work, 2004-04-27), but recently happened again after the changes of94e4818caa(Warn on startup when not using comctl32.dll v6 in wxMSW, 2022-11-28). To prevent it from happening in the future, add WXAppConstructed() that must be called after fully constructing wxApp (and forgetting to do it would result in an assert, so doesn't risk to go unnoticed) and which resets m_traits if it has been wrongly created. It would, perhaps, be even better if we avoided creating the wrong traits in the first place, but for now this at least fixes the latest problem and ensures it doesn't reoccur. Closes #23315.
This commit is contained in:
parent
b4256aa4e2
commit
2be5f429c1
9 changed files with 48 additions and 6 deletions
|
|
@ -476,6 +476,10 @@ public:
|
|||
wxCmdLineArgsArray argv;
|
||||
|
||||
protected:
|
||||
// This function must be called at the end of wxApp ctor to indicate that
|
||||
// wx part of the object is fully constructed.
|
||||
void WXAppConstructed();
|
||||
|
||||
// delete all objects in wxPendingDelete list
|
||||
//
|
||||
// called from ProcessPendingEvents()
|
||||
|
|
@ -531,6 +535,11 @@ protected:
|
|||
// flag modified by Suspend/ResumeProcessingOfPendingEvents()
|
||||
bool m_bDoPendingEventProcessing = true;
|
||||
|
||||
private:
|
||||
// flag set to true at the end of wxApp ctor, call WXAppConstructed() to
|
||||
// set it
|
||||
bool m_fullyConstructed = false;
|
||||
|
||||
friend class WXDLLIMPEXP_FWD_BASE wxEvtHandler;
|
||||
|
||||
// the application object is a singleton anyhow, there is no sense in
|
||||
|
|
@ -541,8 +550,11 @@ protected:
|
|||
#if defined(__UNIX__) && !defined(__WINDOWS__)
|
||||
#include "wx/unix/app.h"
|
||||
#else
|
||||
// this has to be a class and not a typedef as we forward declare it
|
||||
class wxAppConsole : public wxAppConsoleBase { };
|
||||
class wxAppConsole : public wxAppConsoleBase
|
||||
{
|
||||
public:
|
||||
wxAppConsole() { WXAppConstructed(); }
|
||||
};
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -138,10 +138,6 @@ wxAppConsoleBase::wxAppConsoleBase()
|
|||
|
||||
#ifdef __WXDEBUG__
|
||||
SetTraceMasks();
|
||||
// SetTraceMasks call can cause an apptraits to be
|
||||
// created, but since we are still in the constructor the wrong kind will
|
||||
// be created for GUI apps. Destroy it so it can be created again later.
|
||||
wxDELETE(m_traits);
|
||||
#endif
|
||||
|
||||
wxEvtHandler::AddFilter(this);
|
||||
|
|
@ -162,8 +158,29 @@ wxAppConsoleBase::~wxAppConsoleBase()
|
|||
// initialization/cleanup
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void wxAppConsoleBase::WXAppConstructed()
|
||||
{
|
||||
// Note that we can (and will) be called multiple times for the GUI apps as
|
||||
// wxAppConsole ctor has to call this function itself too in case it's
|
||||
// actually a console app, so don't assert that it's currently false.
|
||||
m_fullyConstructed = true;
|
||||
|
||||
// We're called at the end of wxApp ctor execution, i.e. before the
|
||||
// user-defined wxApp-derived class was fully constructed, so its possibly
|
||||
// overridden CreateTraits() couldn't have been called yet, which means
|
||||
// that if we have already initialized our m_traits, we did it wrongly, and
|
||||
// need to reset it.
|
||||
if ( m_traits )
|
||||
{
|
||||
delete m_traits;
|
||||
m_traits = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool wxAppConsoleBase::Initialize(int& WXUNUSED(argc), wxChar **WXUNUSED(argv))
|
||||
{
|
||||
wxASSERT_MSG( m_fullyConstructed, "Forgot to call WXAppConstructed()?" );
|
||||
|
||||
#if defined(__WINDOWS__)
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler);
|
|||
|
||||
wxApp::wxApp()
|
||||
{
|
||||
WXAppConstructed();
|
||||
}
|
||||
|
||||
wxApp::~wxApp()
|
||||
|
|
|
|||
|
|
@ -308,6 +308,8 @@ wxApp::wxApp()
|
|||
{
|
||||
m_isInAssert = false;
|
||||
m_idleSourceId = 0;
|
||||
|
||||
WXAppConstructed();
|
||||
}
|
||||
|
||||
wxApp::~wxApp()
|
||||
|
|
|
|||
|
|
@ -817,6 +817,8 @@ if you believe not using the manifest should remain supported.
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
WXAppConstructed();
|
||||
}
|
||||
|
||||
wxApp::~wxApp()
|
||||
|
|
|
|||
|
|
@ -379,6 +379,8 @@ wxApp::wxApp()
|
|||
m_macCurrentEvent = nullptr ;
|
||||
m_macCurrentEventHandlerCallRef = nullptr ;
|
||||
m_macPool = sm_isEmbedded ? nullptr : new wxMacAutoreleasePool();
|
||||
|
||||
WXAppConstructed();
|
||||
}
|
||||
|
||||
wxApp::~wxApp()
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler);
|
|||
wxApp::wxApp()
|
||||
{
|
||||
m_qtArgc = 0;
|
||||
|
||||
WXAppConstructed();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ private:
|
|||
wxAppConsole::wxAppConsole()
|
||||
{
|
||||
m_signalWakeUpPipe = nullptr;
|
||||
|
||||
WXAppConstructed();
|
||||
}
|
||||
|
||||
wxAppConsole::~wxAppConsole()
|
||||
|
|
|
|||
|
|
@ -217,6 +217,8 @@ wxApp::wxApp()
|
|||
#if !wxUSE_NANOX
|
||||
m_visualInfo = nullptr;
|
||||
#endif
|
||||
|
||||
WXAppConstructed();
|
||||
}
|
||||
|
||||
wxApp::~wxApp()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue