]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk1/evtloop.cpp
wxMessageBox off the main thread lost result code.
[wxWidgets.git] / src / gtk1 / evtloop.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/gtk1/evtloop.cpp
3// Purpose: implements wxEventLoop for GTK+
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 10.07.01
7// Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#include "wx/evtloop.h"
27#include "wx/private/eventloopsourcesmanager.h"
28#include "wx/apptrait.h"
29
30#ifndef WX_PRECOMP
31 #include "wx/app.h"
32 #include "wx/log.h"
33#endif // WX_PRECOMP
34
35#include <gtk/gtk.h>
36
37// ----------------------------------------------------------------------------
38// wxEventLoopImpl
39// ----------------------------------------------------------------------------
40
41class WXDLLEXPORT wxEventLoopImpl
42{
43public:
44 // ctor
45 wxEventLoopImpl() { SetExitCode(0); }
46
47 // set/get the exit code
48 void SetExitCode(int exitcode) { m_exitcode = exitcode; }
49 int GetExitCode() const { return m_exitcode; }
50
51private:
52 // the exit code of the event loop
53 int m_exitcode;
54};
55
56// ============================================================================
57// wxGUIEventLoop implementation
58// ============================================================================
59
60// ----------------------------------------------------------------------------
61// wxGUIEventLoop running and exiting
62// ----------------------------------------------------------------------------
63
64wxGUIEventLoop::~wxGUIEventLoop()
65{
66 wxASSERT_MSG( !m_impl, wxT("should have been deleted in Run()") );
67}
68
69int wxGUIEventLoop::DoRun()
70{
71 m_impl = new wxEventLoopImpl;
72
73 guint loopLevel = gtk_main_level();
74
75 // This is placed inside of a loop to take into account nested
76 // event loops. For example, inside this event loop, we may recieve
77 // Exit() for a different event loop (which we are currently inside of)
78 // That Exit() will cause this gtk_main() to exit so we need to re-enter it.
79#if 0
80 // changed by JJ
81 // this code was intended to support nested event loops. However,
82 // exiting a dialog will result in a application hang (because
83 // gtk_main_quit is called when closing the dialog????)
84 // So for the moment this code is disabled and nested event loops
85 // probably fail for wxGTK1
86 while ( !m_shouldExit )
87 {
88#endif
89 gtk_main();
90#if 0
91 }
92
93 // Force the enclosing event loop to also exit to see if it is done
94 // in case that event loop ended inside of this one. If it is not time
95 // yet for that event loop to exit, it will be executed again due to
96 // the while() loop on m_shouldExit().
97 //
98 // This is unnecessary if we are the top level loop, i.e. loop of level 0.
99 if ( loopLevel )
100 {
101 gtk_main_quit();
102 }
103#endif
104
105 OnExit();
106
107 int exitcode = m_impl->GetExitCode();
108 wxDELETE(m_impl);
109
110 return exitcode;
111}
112
113void wxGUIEventLoop::ScheduleExit(int rc)
114{
115 wxCHECK_RET( IsInsideRun(), wxT("can't call ScheduleExit() if not started") );
116
117 m_impl->SetExitCode(rc);
118
119 m_shouldExit = true;
120
121 gtk_main_quit();
122}
123
124// ----------------------------------------------------------------------------
125// wxEventLoop message processing dispatching
126// ----------------------------------------------------------------------------
127
128bool wxGUIEventLoop::Pending() const
129{
130 if (wxTheApp)
131 {
132 // We need to remove idle callbacks or gtk_events_pending will
133 // never return false.
134 wxTheApp->RemoveIdleTag();
135 }
136
137 return gtk_events_pending();
138}
139
140bool wxGUIEventLoop::Dispatch()
141{
142 wxCHECK_MSG( IsRunning(), false, wxT("can't call Dispatch() if not running") );
143
144 gtk_main_iteration();
145
146 return true;
147}
148
149//-----------------------------------------------------------------------------
150// wxYield
151//-----------------------------------------------------------------------------
152
153bool wxGUIEventLoop::YieldFor(long eventsToProcess)
154{
155#if wxUSE_THREADS
156 if ( !wxThread::IsMain() )
157 {
158 // can't call gtk_main_iteration() from other threads like this
159 return true;
160 }
161#endif // wxUSE_THREADS
162
163 m_isInsideYield = true;
164 m_eventsToProcessInsideYield = eventsToProcess;
165
166 // We need to remove idle callbacks or the loop will
167 // never finish.
168 wxTheApp->RemoveIdleTag();
169
170#if wxUSE_LOG
171 // disable log flushing from here because a call to wxYield() shouldn't
172 // normally result in message boxes popping up &c
173 wxLog::Suspend();
174#endif
175
176 // TODO: implement event filtering using the eventsToProcess mask
177 while (gtk_events_pending())
178 gtk_main_iteration();
179
180 // It's necessary to call ProcessIdle() to update the frames sizes which
181 // might have been changed (it also will update other things set from
182 // OnUpdateUI() which is a nice (and desired) side effect). But we
183 // call ProcessIdle() only once since this is not meant for longish
184 // background jobs (controlled by wxIdleEvent::RequestMore() and the
185 // return value of Processidle().
186 ProcessIdle();
187
188#if wxUSE_LOG
189 // let the logs be flashed again
190 wxLog::Resume();
191#endif
192
193 m_isInsideYield = false;
194
195 return true;
196}
197
198class wxGUIEventLoopSourcesManager : public wxEventLoopSourcesManagerBase
199{
200 public:
201 wxEventLoopSource *
202 AddSourceForFD(int WXUNUSED(fd),
203 wxEventLoopSourceHandler* WXUNUSED(handler),
204 int WXUNUSED(flags))
205 {
206 wxFAIL_MSG("Monitoring FDs in the main loop is not implemented in wxGTK1");
207
208 return NULL;
209 }
210};
211
212wxEventLoopSourcesManagerBase* wxGUIAppTraits::GetEventLoopSourcesManager()
213{
214 static wxGUIEventLoopSourcesManager s_eventLoopSourcesManager;
215
216 return &s_eventLoopSourcesManager;
217}