Rewrite wxExecute() implementation under Unix.
[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 // RCS-ID: $Id$
8 // Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #include "wx/evtloop.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 while ( !m_shouldExit )
79 {
80 gtk_main();
81 }
82
83 // Force the enclosing event loop to also exit to see if it is done
84 // in case that event loop ended inside of this one. If it is not time
85 // yet for that event loop to exit, it will be executed again due to
86 // the while() loop on m_shouldExit().
87 //
88 // This is unnecessary if we are the top level loop, i.e. loop of level 0.
89 if ( loopLevel )
90 {
91 gtk_main_quit();
92 }
93
94 OnExit();
95
96 int exitcode = m_impl->GetExitCode();
97 wxDELETE(m_impl);
98
99 return exitcode;
100 }
101
102 void wxGUIEventLoop::ScheduleExit(int rc)
103 {
104 wxCHECK_RET( IsInsideRun(), wxT("can't call ScheduleExit() if not started") );
105
106 m_impl->SetExitCode(rc);
107
108 m_shouldExit = true;
109
110 gtk_main_quit();
111 }
112
113 // ----------------------------------------------------------------------------
114 // wxEventLoop message processing dispatching
115 // ----------------------------------------------------------------------------
116
117 bool wxGUIEventLoop::Pending() const
118 {
119 if (wxTheApp)
120 {
121 // We need to remove idle callbacks or gtk_events_pending will
122 // never return false.
123 wxTheApp->RemoveIdleTag();
124 }
125
126 return gtk_events_pending();
127 }
128
129 bool wxGUIEventLoop::Dispatch()
130 {
131 wxCHECK_MSG( IsRunning(), false, wxT("can't call Dispatch() if not running") );
132
133 gtk_main_iteration();
134
135 return true;
136 }
137
138 //-----------------------------------------------------------------------------
139 // wxYield
140 //-----------------------------------------------------------------------------
141
142 bool wxGUIEventLoop::YieldFor(long eventsToProcess)
143 {
144 #if wxUSE_THREADS
145 if ( !wxThread::IsMain() )
146 {
147 // can't call gtk_main_iteration() from other threads like this
148 return true;
149 }
150 #endif // wxUSE_THREADS
151
152 m_isInsideYield = true;
153 m_eventsToProcessInsideYield = eventsToProcess;
154
155 // We need to remove idle callbacks or the loop will
156 // never finish.
157 wxTheApp->RemoveIdleTag();
158
159 #if wxUSE_LOG
160 // disable log flushing from here because a call to wxYield() shouldn't
161 // normally result in message boxes popping up &c
162 wxLog::Suspend();
163 #endif
164
165 // TODO: implement event filtering using the eventsToProcess mask
166 while (gtk_events_pending())
167 gtk_main_iteration();
168
169 // It's necessary to call ProcessIdle() to update the frames sizes which
170 // might have been changed (it also will update other things set from
171 // OnUpdateUI() which is a nice (and desired) side effect). But we
172 // call ProcessIdle() only once since this is not meant for longish
173 // background jobs (controlled by wxIdleEvent::RequestMore() and the
174 // return value of Processidle().
175 ProcessIdle();
176
177 #if wxUSE_LOG
178 // let the logs be flashed again
179 wxLog::Resume();
180 #endif
181
182 m_isInsideYield = false;
183
184 return true;
185 }