diff --git a/docs/latex/wx/window.tex b/docs/latex/wx/window.tex index 77e76e7270..106ff9e65d 100644 --- a/docs/latex/wx/window.tex +++ b/docs/latex/wx/window.tex @@ -2068,6 +2068,10 @@ for them is found. Using this style allows to prevent them from being propagated beyond this window. Notice that wxDialog has this style on by default for the reasons explained in the \helpref{event processing overview}{eventprocessing}.} +\twocolitem{\windowstyle{wxWS\_EX\_TRANSIENT}}{This can be used to prevent a +window from being used as an implicit parent for the dialogs which were +created without a parent. It is useful for the windows which can disappear at +any moment as creating childs of such windows results in fatal problems.} \end{twocollist} \membersection{wxWindow::SetFocus}\label{wxwindowsetfocus} diff --git a/include/wx/defs.h b/include/wx/defs.h index 91b788c8f8..39578aaa31 100644 --- a/include/wx/defs.h +++ b/include/wx/defs.h @@ -784,6 +784,12 @@ enum wxBorder // flag on by default. #define wxWS_EX_BLOCK_EVENTS 0x00000002 +// don't use this window as an implicit parent for the other windows: this must +// be used with transient windows as otherwise there is the risk of creating a +// dialog/frame with this window as a parent which would lead to a crash if the +// parent is destroyed before the child +#define wxWS_EX_TRANSIENT 0x00000004 + /* * wxFrame/wxDialog style flags */ diff --git a/src/generic/logg.cpp b/src/generic/logg.cpp index a0ff4d3672..155628d827 100644 --- a/src/generic/logg.cpp +++ b/src/generic/logg.cpp @@ -245,9 +245,6 @@ void wxLogGui::Flush() wxString title; title.Printf(titleFormat, appName.c_str()); - // this is the best we can do here - wxWindow *parent = wxTheApp->GetTopWindow(); - size_t nMsgCount = m_aMessages.Count(); // avoid showing other log dialogs until we're done with the dialog we're @@ -263,7 +260,7 @@ void wxLogGui::Flush() { #if wxUSE_LOG_DIALOG - wxLogDialog dlg(parent, + wxLogDialog dlg(NULL, m_aMessages, m_aSeverity, m_aTimes, title, style); @@ -295,7 +292,7 @@ void wxLogGui::Flush() // situation without it if ( !!str ) { - wxMessageBox(str, title, wxOK | style, parent); + wxMessageBox(str, title, wxOK | style); // no undisplayed messages whatsoever Clear(); diff --git a/src/generic/progdlgg.cpp b/src/generic/progdlgg.cpp index 94109c5660..33a8d648fc 100644 --- a/src/generic/progdlgg.cpp +++ b/src/generic/progdlgg.cpp @@ -89,6 +89,9 @@ wxProgressDialog::wxProgressDialog(wxString const &title, int style) : wxDialog(parent, -1, title) { + // we may disappear at any moment, let the others know about it + SetExtraStyle(GetExtraStyle() | wxWS_EX_TRANSIENT); + m_windowStyle |= style; bool hasAbortButton = (style & wxPD_CAN_ABORT) != 0; diff --git a/src/gtk/dialog.cpp b/src/gtk/dialog.cpp index e948cddd10..68a991a371 100644 --- a/src/gtk/dialog.cpp +++ b/src/gtk/dialog.cpp @@ -198,7 +198,10 @@ int wxDialog::ShowModal() if ( !GetParent() && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT) ) { wxWindow *parent = wxTheApp->GetTopWindow(); - if ( parent && parent != this && parent->IsBeingDeleted() ) + if ( parent && + parent != this && + parent->IsBeingDeleted() && + !(parent->GetExtraStyle() & wxWS_EX_TRANSIENT) ) { m_parent = parent; gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(parent->m_widget) ); diff --git a/src/gtk1/dialog.cpp b/src/gtk1/dialog.cpp index e948cddd10..68a991a371 100644 --- a/src/gtk1/dialog.cpp +++ b/src/gtk1/dialog.cpp @@ -198,7 +198,10 @@ int wxDialog::ShowModal() if ( !GetParent() && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT) ) { wxWindow *parent = wxTheApp->GetTopWindow(); - if ( parent && parent != this && parent->IsBeingDeleted() ) + if ( parent && + parent != this && + parent->IsBeingDeleted() && + !(parent->GetExtraStyle() & wxWS_EX_TRANSIENT) ) { m_parent = parent; gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(parent->m_widget) ); diff --git a/src/msw/toplevel.cpp b/src/msw/toplevel.cpp index 4482e103d9..a7b917f9f1 100644 --- a/src/msw/toplevel.cpp +++ b/src/msw/toplevel.cpp @@ -196,11 +196,18 @@ bool wxTopLevelWindowMSW::CreateDialog(const wxChar *dlgTemplate, { parent = wxTheApp->GetTopWindow(); - // but don't use the window which is currently hidden as then the - // dialog would be hidden as well - if ( parent && !parent->IsShown() ) + if ( parent ) { - parent = NULL; + // don't use transient windows as parents, this is dangerous as it + // can lead to a crash if the parent is destroyed before the child + // + // also don't use the window which is currently hidden as then the + // dialog would be hidden as well + if ( (parent->GetExtraStyle() & wxWS_EX_TRANSIENT) || + !parent->IsShown() ) + { + parent = NULL; + } } }