the app doesn't exit any more if a dialog is shown (and destroyed) while
the flow of control is still in OnInit() git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@16523 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
62b77e42be
commit
1cbee0b42c
@ -137,7 +137,8 @@ otherwise.
|
||||
|
||||
\wxheading{See also}
|
||||
|
||||
\helpref{wxApp::SetExitOnFrameDelete}{wxappsetexitonframedelete}
|
||||
\helpref{wxApp::SetExitOnFrameDelete}{wxappsetexitonframedelete},\\
|
||||
\helpref{wxApp shutdown overview}{wxappshutdownoverview}
|
||||
|
||||
\membersection{wxApp::GetTopWindow}\label{wxappgettopwindow}
|
||||
|
||||
@ -550,6 +551,11 @@ top-level frame is deleted.
|
||||
\docparam{flag}{If TRUE (the default), the application will exit when the top-level frame is
|
||||
deleted. If FALSE, the application will continue to run.}
|
||||
|
||||
\wxheading{See also}
|
||||
|
||||
\helpref{wxApp::GetExitOnFrameDelete}{wxappgetexitonframedelete},\\
|
||||
\helpref{wxApp shutdown overview}{wxappshutdownoverview}
|
||||
|
||||
\membersection{wxApp::SetTopWindow}\label{wxappsettopwindow}
|
||||
|
||||
\func{void}{SetTopWindow}{\param{wxWindow* }{window}}
|
||||
|
@ -22,7 +22,8 @@ is to explicitly delete child frames in the top-level frame's \helpref{wxCloseEv
|
||||
handler.
|
||||
|
||||
In emergencies the \helpref{wxExit}{wxexit} function can be called to kill the
|
||||
application.
|
||||
application however normally the applications shuts down automatically,
|
||||
\helpref{see below}{wxappshutdownoverview}.
|
||||
|
||||
An example of defining an application follows:
|
||||
|
||||
@ -55,11 +56,25 @@ construction time.
|
||||
You can also use DECLARE\_APP(appClass) in a header file to declare the wxGetApp function which returns
|
||||
a reference to the application object.
|
||||
|
||||
\subsection{Application shutdown}
|
||||
\subsection{Application shutdown}\label{wxappshutdownoverview}
|
||||
|
||||
\helpref{OnExit}{wxapponexit} is called when the application exits but {\it before}
|
||||
wxWindows cleans its internal structures. Your should delete all wxWindows object that
|
||||
your created by the time OnExit finishes. In particular, do {\bf not} destroy them
|
||||
The application normally shuts down when the last of its top level windows is
|
||||
closed. This is normally the expected behaviour and means that it is enough to
|
||||
call \helpref{Close()}{wxwindowclose} in response to the {\tt "Exit"} menu
|
||||
command if your program has a single top level window. If this behaviour is not
|
||||
desirable \helpref{wxApp::SetExitOnFrameDelete}{wxappsetexitonframedelete} can
|
||||
be called to change it. Note that starting from wxWindows 2.3.3 such logic
|
||||
doesn't apply for the windows shown before the program enters the main loop: in
|
||||
other words, you can safely show a dialog from
|
||||
\helpref{wxApp::OnInit}{wxapponinit} and not be afraid that your application
|
||||
terminates when this dialog -- which is the last top level window for the
|
||||
moment -- is closed.
|
||||
|
||||
|
||||
Another aspect of the application shutdown is the \helpref{OnExit}{wxapponexit}
|
||||
which is called when the application exits but {\it before} wxWindows cleans up
|
||||
its internal structures. Your should delete all wxWindows object that your
|
||||
created by the time OnExit finishes. In particular, do {\bf not} destroy them
|
||||
from application class' destructor!
|
||||
|
||||
For example, this code may crash:
|
||||
|
@ -128,7 +128,7 @@ public:
|
||||
//
|
||||
// Override: rarely in GUI applications, always in console ones.
|
||||
#if wxUSE_GUI
|
||||
virtual int OnRun() { return MainLoop(); };
|
||||
virtual int OnRun();
|
||||
#else // !GUI
|
||||
virtual int OnRun() = 0;
|
||||
#endif // wxUSE_GUI
|
||||
@ -236,11 +236,13 @@ public:
|
||||
|
||||
// control the exit behaviour: by default, the program will exit the
|
||||
// main loop (and so, usually, terminate) when the last top-level
|
||||
// program window is deleted. Beware that if you disabel this (with
|
||||
// SetExitOnFrameDelete(FALSE)), you'll have to call ExitMainLoop()
|
||||
// explicitly from somewhere.
|
||||
void SetExitOnFrameDelete(bool flag) { m_exitOnFrameDelete = flag; }
|
||||
bool GetExitOnFrameDelete() const { return m_exitOnFrameDelete; }
|
||||
// program window is deleted. Beware that if you disable this behaviour
|
||||
// (with SetExitOnFrameDelete(FALSE)), you'll have to call
|
||||
// ExitMainLoop() explicitly from somewhere.
|
||||
void SetExitOnFrameDelete(bool flag)
|
||||
{ m_exitOnFrameDelete = flag ? Yes : No; }
|
||||
bool GetExitOnFrameDelete() const
|
||||
{ return m_exitOnFrameDelete == Yes; }
|
||||
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
@ -392,8 +394,16 @@ protected:
|
||||
// the main top level window - may be NULL
|
||||
wxWindow *m_topWindow;
|
||||
|
||||
// if TRUE, exit the main loop when the last top level window is deleted
|
||||
bool m_exitOnFrameDelete;
|
||||
// if Yes, exit the main loop when the last top level window is deleted, if
|
||||
// No don't do it and if Later -- only do it once we reach our OnRun()
|
||||
//
|
||||
// the explanation for using this strange scheme is given in appcmn.cpp
|
||||
enum
|
||||
{
|
||||
Later = -1,
|
||||
No,
|
||||
Yes
|
||||
} m_exitOnFrameDelete;
|
||||
|
||||
// TRUE if the apps whats to use the best visual on systems where
|
||||
// more than one are available (Sun, SGI, XFree86 4.0 ?)
|
||||
|
@ -135,16 +135,21 @@ protected:
|
||||
virtual void DoClientToScreen(int *x, int *y) const;
|
||||
virtual void DoScreenToClient(int *x, int *y) const;
|
||||
|
||||
// test whether this window makes part of the frame
|
||||
// (menubar, toolbar and statusbar are excluded from automatic layout)
|
||||
virtual bool IsOneOfBars(const wxWindow *WXUNUSED(win)) const
|
||||
{ return FALSE; }
|
||||
|
||||
// check if we should exit the program after deleting another top level
|
||||
// window (this is used in common dtor and wxMSW code)
|
||||
static bool IsLastBeforeExit();
|
||||
|
||||
// send the iconize event, return TRUE if processed
|
||||
bool SendIconizeEvent(bool iconized = TRUE);
|
||||
|
||||
// the frame icon
|
||||
wxIconBundle m_icons;
|
||||
|
||||
// test whether this window makes part of the frame
|
||||
// (menubar, toolbar and statusbar are excluded from automatic layout)
|
||||
virtual bool IsOneOfBars(const wxWindow *WXUNUSED(win)) const { return FALSE; }
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
|
@ -84,8 +84,21 @@ wxAppBase::wxAppBase()
|
||||
#if wxUSE_GUI
|
||||
m_topWindow = (wxWindow *)NULL;
|
||||
m_useBestVisual = FALSE;
|
||||
m_exitOnFrameDelete = TRUE;
|
||||
m_isActive = TRUE;
|
||||
|
||||
// We don't want to exit the app if the user code shows a dialog from its
|
||||
// OnInit() -- but this is what would happen if we set m_exitOnFrameDelete
|
||||
// to Yes initially as this dialog would be the last top level window.
|
||||
// OTOH, if we set it to No initially we'll have to overwrite it with Yes
|
||||
// when we enter our OnRun() because we do want the default behaviour from
|
||||
// then on. But this would be a problem if the user code calls
|
||||
// SetExitOnFrameDelete(FALSE) from OnInit().
|
||||
//
|
||||
// So we use the special "Later" value which is such that
|
||||
// GetExitOnFrameDelete() returns FALSE for it but which we know we can
|
||||
// safely (i.e. without losing the effect of the users SetExitOnFrameDelete
|
||||
// call) overwrite in OnRun()
|
||||
m_exitOnFrameDelete = Later;
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
@ -113,6 +126,19 @@ bool wxAppBase::OnInitGui()
|
||||
}
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
int wxAppBase::OnRun()
|
||||
{
|
||||
// see the comment in ctor: if the initial value hasn't been changed, use
|
||||
// the default Yes from now on
|
||||
if ( m_exitOnFrameDelete == Later )
|
||||
{
|
||||
m_exitOnFrameDelete = Yes;
|
||||
}
|
||||
//else: it has been changed, assume the user knows what he is doing
|
||||
|
||||
return MainLoop();
|
||||
}
|
||||
|
||||
int wxAppBase::OnExit()
|
||||
{
|
||||
#if wxUSE_CONFIG
|
||||
|
@ -60,7 +60,19 @@ wxTopLevelWindowBase::wxTopLevelWindowBase()
|
||||
|
||||
wxTopLevelWindowBase::~wxTopLevelWindowBase()
|
||||
{
|
||||
// this destructor is required for Darwin
|
||||
// don't let wxTheApp keep any stale pointers to us
|
||||
if ( wxTheApp && wxTheApp->GetTopWindow() == this )
|
||||
wxTheApp->SetTopWindow(NULL);
|
||||
|
||||
bool shouldExit = IsLastBeforeExit();
|
||||
|
||||
wxTopLevelWindows.DeleteObject(this);
|
||||
|
||||
if ( shouldExit )
|
||||
{
|
||||
// then do it
|
||||
wxTheApp->ExitMainLoop();
|
||||
}
|
||||
}
|
||||
|
||||
bool wxTopLevelWindowBase::Destroy()
|
||||
@ -73,6 +85,19 @@ bool wxTopLevelWindowBase::Destroy()
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool wxTopLevelWindowBase::IsLastBeforeExit()
|
||||
{
|
||||
// we exit the application if there are no more top level windows left
|
||||
// normally but wxApp can prevent this from happening
|
||||
return (wxTopLevelWindows.GetCount() == 1) &&
|
||||
wxTheApp && wxTheApp->GetExitOnFrameDelete();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxTopLevelWindow geometry
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxSize wxTopLevelWindowBase::GetMaxSize() const
|
||||
{
|
||||
wxSize size( GetMaxWidth(), GetMaxHeight() );
|
||||
|
@ -483,7 +483,7 @@ wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
|
||||
wxASSERT_MSG( FALSE, _T("Window still grabbed"));
|
||||
RemoveGrab();
|
||||
}
|
||||
|
||||
|
||||
m_isBeingDeleted = TRUE;
|
||||
|
||||
// it may also be GtkScrolledWindow in the case of an MDI child
|
||||
@ -491,17 +491,6 @@ wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
|
||||
{
|
||||
gtk_window_set_focus( GTK_WINDOW(m_widget), NULL );
|
||||
}
|
||||
|
||||
wxTopLevelWindows.DeleteObject( this );
|
||||
|
||||
if (wxTheApp->GetTopWindow() == this)
|
||||
wxTheApp->SetTopWindow( (wxWindow*) NULL );
|
||||
|
||||
if ((wxTopLevelWindows.Number() == 0) &&
|
||||
(wxTheApp->GetExitOnFrameDelete()))
|
||||
{
|
||||
wxTheApp->ExitMainLoop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -522,11 +511,11 @@ static void wx_win_hints_set_layer(GtkWidget *window, int layer)
|
||||
XEvent xev;
|
||||
GdkWindowPrivate *priv;
|
||||
gint prev_error;
|
||||
|
||||
|
||||
prev_error = gdk_error_warnings;
|
||||
gdk_error_warnings = 0;
|
||||
priv = (GdkWindowPrivate*)(GTK_WIDGET(window)->window);
|
||||
|
||||
|
||||
if (GTK_WIDGET_MAPPED(window))
|
||||
{
|
||||
xev.type = ClientMessage;
|
||||
@ -536,14 +525,14 @@ static void wx_win_hints_set_layer(GtkWidget *window, int layer)
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = (long)layer;
|
||||
xev.xclient.data.l[1] = gdk_time_get();
|
||||
|
||||
|
||||
XSendEvent(GDK_DISPLAY(), GDK_ROOT_WINDOW(), False,
|
||||
SubstructureNotifyMask, (XEvent*) &xev);
|
||||
}
|
||||
else
|
||||
{
|
||||
long data[1];
|
||||
|
||||
|
||||
data[0] = layer;
|
||||
XChangeProperty(GDK_DISPLAY(), priv->xwindow, gs_XA_WIN_LAYER,
|
||||
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
|
||||
@ -574,14 +563,14 @@ bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
|
||||
|
||||
int screen_width,screen_height;
|
||||
wxDisplaySize( &screen_width, &screen_height );
|
||||
|
||||
|
||||
gint client_x, client_y, root_x, root_y;
|
||||
gint width, height;
|
||||
|
||||
gdk_window_get_origin (m_widget->window, &root_x, &root_y);
|
||||
gdk_window_get_geometry (m_widget->window, &client_x, &client_y,
|
||||
&width, &height, NULL);
|
||||
|
||||
|
||||
wx_win_hints_set_layer( m_widget, WIN_LAYER_ABOVE_DOCK );
|
||||
|
||||
gdk_window_move_resize (m_widget->window, -client_x, -client_y,
|
||||
@ -590,7 +579,7 @@ bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
|
||||
else
|
||||
{
|
||||
wx_win_hints_set_layer( m_widget, WIN_LAYER_NORMAL );
|
||||
|
||||
|
||||
SetSize( m_fsSaveFrame.x, m_fsSaveFrame.y, m_fsSaveFrame.width, m_fsSaveFrame.height );
|
||||
}
|
||||
|
||||
@ -778,7 +767,7 @@ void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
|
||||
// Gtk-WARNING **: gtk_widget_size_allocate():
|
||||
// attempt to allocate widget with width 65535 and height 600
|
||||
// but I don't have time to track them all now..
|
||||
//
|
||||
//
|
||||
// Really we need to encapulate all this height/width business and
|
||||
// stop any old method from ripping at the members directly and
|
||||
// scattering -1's without regard for who might resolve them later.
|
||||
|
@ -483,7 +483,7 @@ wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
|
||||
wxASSERT_MSG( FALSE, _T("Window still grabbed"));
|
||||
RemoveGrab();
|
||||
}
|
||||
|
||||
|
||||
m_isBeingDeleted = TRUE;
|
||||
|
||||
// it may also be GtkScrolledWindow in the case of an MDI child
|
||||
@ -491,17 +491,6 @@ wxTopLevelWindowGTK::~wxTopLevelWindowGTK()
|
||||
{
|
||||
gtk_window_set_focus( GTK_WINDOW(m_widget), NULL );
|
||||
}
|
||||
|
||||
wxTopLevelWindows.DeleteObject( this );
|
||||
|
||||
if (wxTheApp->GetTopWindow() == this)
|
||||
wxTheApp->SetTopWindow( (wxWindow*) NULL );
|
||||
|
||||
if ((wxTopLevelWindows.Number() == 0) &&
|
||||
(wxTheApp->GetExitOnFrameDelete()))
|
||||
{
|
||||
wxTheApp->ExitMainLoop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -522,11 +511,11 @@ static void wx_win_hints_set_layer(GtkWidget *window, int layer)
|
||||
XEvent xev;
|
||||
GdkWindowPrivate *priv;
|
||||
gint prev_error;
|
||||
|
||||
|
||||
prev_error = gdk_error_warnings;
|
||||
gdk_error_warnings = 0;
|
||||
priv = (GdkWindowPrivate*)(GTK_WIDGET(window)->window);
|
||||
|
||||
|
||||
if (GTK_WIDGET_MAPPED(window))
|
||||
{
|
||||
xev.type = ClientMessage;
|
||||
@ -536,14 +525,14 @@ static void wx_win_hints_set_layer(GtkWidget *window, int layer)
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = (long)layer;
|
||||
xev.xclient.data.l[1] = gdk_time_get();
|
||||
|
||||
|
||||
XSendEvent(GDK_DISPLAY(), GDK_ROOT_WINDOW(), False,
|
||||
SubstructureNotifyMask, (XEvent*) &xev);
|
||||
}
|
||||
else
|
||||
{
|
||||
long data[1];
|
||||
|
||||
|
||||
data[0] = layer;
|
||||
XChangeProperty(GDK_DISPLAY(), priv->xwindow, gs_XA_WIN_LAYER,
|
||||
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
|
||||
@ -574,14 +563,14 @@ bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
|
||||
|
||||
int screen_width,screen_height;
|
||||
wxDisplaySize( &screen_width, &screen_height );
|
||||
|
||||
|
||||
gint client_x, client_y, root_x, root_y;
|
||||
gint width, height;
|
||||
|
||||
gdk_window_get_origin (m_widget->window, &root_x, &root_y);
|
||||
gdk_window_get_geometry (m_widget->window, &client_x, &client_y,
|
||||
&width, &height, NULL);
|
||||
|
||||
|
||||
wx_win_hints_set_layer( m_widget, WIN_LAYER_ABOVE_DOCK );
|
||||
|
||||
gdk_window_move_resize (m_widget->window, -client_x, -client_y,
|
||||
@ -590,7 +579,7 @@ bool wxTopLevelWindowGTK::ShowFullScreen(bool show, long style )
|
||||
else
|
||||
{
|
||||
wx_win_hints_set_layer( m_widget, WIN_LAYER_NORMAL );
|
||||
|
||||
|
||||
SetSize( m_fsSaveFrame.x, m_fsSaveFrame.y, m_fsSaveFrame.width, m_fsSaveFrame.height );
|
||||
}
|
||||
|
||||
@ -778,7 +767,7 @@ void wxTopLevelWindowGTK::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
|
||||
// Gtk-WARNING **: gtk_widget_size_allocate():
|
||||
// attempt to allocate widget with width 65535 and height 600
|
||||
// but I don't have time to track them all now..
|
||||
//
|
||||
//
|
||||
// Really we need to encapulate all this height/width business and
|
||||
// stop any old method from ripping at the members directly and
|
||||
// scattering -1's without regard for who might resolve them later.
|
||||
|
@ -701,22 +701,8 @@ int wxEntry(WXHINSTANCE hInstance,
|
||||
wxLog::SetTimestamp(NULL);
|
||||
#endif
|
||||
|
||||
int retValue = 0;
|
||||
|
||||
// it is common to create a modal dialog in OnInit() (to ask/notify the
|
||||
// user about something) but it wouldn't work if we don't change the
|
||||
// "exit on delete last frame" flag here as when this dialog is
|
||||
// deleted, the app would terminate (it was the last top level window
|
||||
// as the main frame wasn't created yet!), so disable this behaviour
|
||||
// temproarily
|
||||
bool exitOnLastFrameDelete = wxTheApp->GetExitOnFrameDelete();
|
||||
wxTheApp->SetExitOnFrameDelete(FALSE);
|
||||
|
||||
// init the app
|
||||
retValue = wxEntryInitGui() && wxTheApp->OnInit() ? 0 : -1;
|
||||
|
||||
// restore the old flag value
|
||||
wxTheApp->SetExitOnFrameDelete(exitOnLastFrameDelete);
|
||||
int retValue = wxEntryInitGui() && wxTheApp->OnInit() ? 0 : -1;
|
||||
|
||||
if ( retValue == 0 )
|
||||
{
|
||||
@ -986,8 +972,8 @@ bool wxApp::ProcessIdle()
|
||||
|
||||
void wxApp::ExitMainLoop()
|
||||
{
|
||||
// VZ: why not ::PostQuitMessage()?
|
||||
m_keepGoing = FALSE;
|
||||
// this will set m_keepGoing to FALSE a bit later
|
||||
::PostQuitMessage(0);
|
||||
}
|
||||
|
||||
bool wxApp::Pending()
|
||||
|
@ -454,12 +454,12 @@ wxTopLevelWindowMSW::~wxTopLevelWindowMSW()
|
||||
if ( this == ms_hiddenParent )
|
||||
{
|
||||
// stop [infinite] recursion which would otherwise happen when we do
|
||||
// "delete ms_hiddenParent" below
|
||||
// "delete ms_hiddenParent" below -- and we're not interested in doing
|
||||
// anything of the rest below for that window because the rest of
|
||||
// wxWindows doesn't even know about it
|
||||
return;
|
||||
}
|
||||
|
||||
wxTopLevelWindows.DeleteObject(this);
|
||||
|
||||
if ( wxModelessWindows.Find(this) )
|
||||
wxModelessWindows.DeleteObject(this);
|
||||
|
||||
@ -476,21 +476,15 @@ wxTopLevelWindowMSW::~wxTopLevelWindowMSW()
|
||||
}
|
||||
}
|
||||
|
||||
// If this is the last top-level window, exit.
|
||||
if ( wxTheApp && (wxTopLevelWindows.Number() == 0) )
|
||||
// if this is the last top-level window, we're going to exit and we should
|
||||
// delete ms_hiddenParent now to avoid leaking it
|
||||
if ( IsLastBeforeExit() )
|
||||
{
|
||||
if ( ms_hiddenParent )
|
||||
{
|
||||
delete ms_hiddenParent;
|
||||
ms_hiddenParent = NULL;
|
||||
}
|
||||
|
||||
wxTheApp->SetTopWindow(NULL);
|
||||
|
||||
if ( wxTheApp->GetExitOnFrameDelete() )
|
||||
{
|
||||
::PostQuitMessage(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user