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