]> git.saurik.com Git - wxWidgets.git/blame - src/x11/evtloop.cpp
Rewrite wxExecute() implementation under Unix.
[wxWidgets.git] / src / x11 / evtloop.cpp
CommitLineData
1b0fb34b 1///////////////////////////////////////////////////////////////////////////////
32d4c30a 2// Name: src/x11/evtloop.cpp
1b0fb34b
JS
3// Purpose: implements wxEventLoop for X11
4// Author: Julian Smart
5// Modified by:
6// Created: 01.06.01
7// RCS-ID: $Id$
8// Copyright: (c) 2002 Julian Smart
526954c5 9// Licence: wxWindows licence
1b0fb34b
JS
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
32d4c30a
WS
20// for compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
670f9935
WS
23#include "wx/evtloop.h"
24
32d4c30a
WS
25#ifndef WX_PRECOMP
26 #include "wx/hash.h"
670f9935 27 #include "wx/app.h"
cdccdfab 28 #include "wx/window.h"
02761f6c 29 #include "wx/module.h"
32d4c30a
WS
30#endif
31
4eba3923 32#include "wx/private/fdiodispatcher.h"
17a1ebd1 33#include "wx/unix/private.h"
1b0fb34b 34#include "wx/x11/private.h"
c2ca375c 35#include "wx/generic/private/timer.h"
1b0fb34b 36
32d4c30a
WS
37#if wxUSE_THREADS
38 #include "wx/thread.h"
39#endif
40
8193abb6 41#include <X11/Xlib.h>
1016f0de
JS
42#include <sys/time.h>
43#include <unistd.h>
44
bc023abb
MW
45#ifdef HAVE_SYS_SELECT_H
46# include <sys/select.h>
47#endif
48
1b0fb34b
JS
49// ----------------------------------------------------------------------------
50// wxEventLoopImpl
51// ----------------------------------------------------------------------------
52
53class WXDLLEXPORT wxEventLoopImpl
54{
55public:
56 // ctor
32d4c30a 57 wxEventLoopImpl() { SetExitCode(0); m_keepGoing = false; }
1b0fb34b 58
32d4c30a 59 // process an XEvent, return true if it was processed
086fd560 60 bool ProcessEvent(XEvent* event);
1b0fb34b 61
32d4c30a 62 // generate an idle message, return true if more idle time requested
1b0fb34b
JS
63 bool SendIdleEvent();
64
65 // set/get the exit code
66 void SetExitCode(int exitcode) { m_exitcode = exitcode; }
67 int GetExitCode() const { return m_exitcode; }
68
69public:
32d4c30a 70 // preprocess an event, return true if processed (i.e. no further
1b0fb34b 71 // dispatching required)
7266b672 72 bool PreProcessEvent(XEvent* event);
1b0fb34b
JS
73
74 // the exit code of the event loop
75 int m_exitcode;
76
77 bool m_keepGoing;
78};
79
80// ============================================================================
81// wxEventLoopImpl implementation
82// ============================================================================
83
84// ----------------------------------------------------------------------------
85// wxEventLoopImpl message processing
86// ----------------------------------------------------------------------------
87
086fd560 88bool wxEventLoopImpl::ProcessEvent(XEvent *event)
1b0fb34b
JS
89{
90 // give us the chance to preprocess the message first
086fd560 91 if ( PreProcessEvent(event) )
32d4c30a 92 return true;
3754265e 93
086fd560
JS
94 // if it wasn't done, dispatch it to the corresponding window
95 if (wxTheApp)
96 return wxTheApp->ProcessXEvent((WXEvent*) event);
97
32d4c30a 98 return false;
1b0fb34b
JS
99}
100
89954433 101bool wxEventLoopImpl::PreProcessEvent(XEvent *WXUNUSED(event))
1b0fb34b 102{
32d4c30a 103 return false;
1b0fb34b
JS
104}
105
106// ----------------------------------------------------------------------------
107// wxEventLoopImpl idle event processing
108// ----------------------------------------------------------------------------
109
110bool wxEventLoopImpl::SendIdleEvent()
111{
e39af974 112 return wxTheApp->ProcessIdle();
1b0fb34b
JS
113}
114
115// ============================================================================
116// wxEventLoop implementation
117// ============================================================================
118
1b0fb34b
JS
119// ----------------------------------------------------------------------------
120// wxEventLoop running and exiting
121// ----------------------------------------------------------------------------
122
b46b1d59 123wxGUIEventLoop::~wxGUIEventLoop()
1b0fb34b 124{
9a83f860 125 wxASSERT_MSG( !m_impl, wxT("should have been deleted in Run()") );
1b0fb34b
JS
126}
127
c738d187 128int wxGUIEventLoop::DoRun()
1b0fb34b 129{
1b0fb34b 130 m_impl = new wxEventLoopImpl;
3754265e 131
32d4c30a 132 m_impl->m_keepGoing = true;
1b0fb34b
JS
133 while ( m_impl->m_keepGoing )
134 {
1b0fb34b
JS
135 // generate and process idle events for as long as we don't have
136 // anything else to do
137 while ( ! Pending() )
138 {
b555c37c 139#if wxUSE_TIMER
c2ca375c 140 wxGenericTimerImpl::NotifyTimers(); // TODO: is this the correct place for it?
b555c37c 141#endif
1b0fb34b
JS
142 if (!m_impl->SendIdleEvent())
143 {
1b0fb34b
JS
144 // Break out of while loop
145 break;
146 }
147 }
148
149 // a message came or no more idle processing to do, sit in Dispatch()
150 // waiting for the next message
151 if ( !Dispatch() )
152 {
153 break;
154 }
155 }
156
16d17da6
VZ
157 OnExit();
158
1b0fb34b 159 int exitcode = m_impl->GetExitCode();
5276b0a5 160 wxDELETE(m_impl);
1b0fb34b 161
1b0fb34b
JS
162 return exitcode;
163}
164
d3ad22bd 165void wxGUIEventLoop::ScheduleExit(int rc)
1b0fb34b 166{
2c032a5d
VZ
167 if ( m_impl )
168 {
169 m_impl->SetExitCode(rc);
170 m_impl->m_keepGoing = false;
171 }
1b0fb34b
JS
172}
173
174// ----------------------------------------------------------------------------
175// wxEventLoop message processing dispatching
176// ----------------------------------------------------------------------------
177
b46b1d59 178bool wxGUIEventLoop::Pending() const
1b0fb34b 179{
2b5f62a0
VZ
180 XFlush( wxGlobalDisplay() );
181 return (XPending( wxGlobalDisplay() ) > 0);
1b0fb34b
JS
182}
183
b46b1d59 184bool wxGUIEventLoop::Dispatch()
1b0fb34b 185{
1c991946
VZ
186 // see comment in wxEventLoopManual::ProcessEvents()
187 if ( wxTheApp )
188 wxTheApp->ProcessPendingEvents();
189
1b0fb34b
JS
190 XEvent event;
191
192 // TODO allowing for threads, as per e.g. wxMSW
193
1016f0de
JS
194 // This now waits until either an X event is received,
195 // or the select times out. So we should now process
196 // wxTimers in a reasonably timely fashion. However it
197 // does also mean that idle processing will happen more
198 // often, so we should probably limit idle processing to
199 // not be repeated more than every N milliseconds.
3754265e 200
2b5f62a0 201 if (XPending( wxGlobalDisplay() ) == 0)
1016f0de 202 {
868741e9
JS
203#if wxUSE_NANOX
204 GR_TIMEOUT timeout = 10; // Milliseconds
205 // Wait for next event, or timeout
206 GrGetNextEventTimeout(& event, timeout);
207
208 // Fall through to ProcessEvent.
209 // we'll assume that ProcessEvent will just ignore
210 // the event if there was a timeout and no event.
3754265e 211
868741e9 212#else
1016f0de
JS
213 struct timeval tv;
214 tv.tv_sec=0;
215 tv.tv_usec=10000; // TODO make this configurable
2b5f62a0 216 int fd = ConnectionNumber( wxGlobalDisplay() );
3754265e 217
1016f0de 218 fd_set readset;
52127426 219 fd_set writeset;
17a1ebd1
VZ
220 wxFD_ZERO(&readset);
221 wxFD_ZERO(&writeset);
17a1ebd1 222 wxFD_SET(fd, &readset);
52127426 223
6b44a335 224 if (select( fd+1, &readset, &writeset, NULL, &tv ) != 0)
1016f0de 225 {
6b44a335 226 // An X11 event was pending, get it
17a1ebd1 227 if (wxFD_ISSET( fd, &readset ))
2b5f62a0 228 XNextEvent( wxGlobalDisplay(), &event );
b46b1d59 229 }
868741e9 230#endif
3754265e 231 }
2b5f62a0 232 else
1016f0de 233 {
2b5f62a0 234 XNextEvent( wxGlobalDisplay(), &event );
1016f0de 235 }
3754265e 236
6b44a335
VS
237#if wxUSE_SOCKETS
238 // handle any pending socket events:
4eba3923 239 wxFDIODispatcher::DispatchPending();
6b44a335 240#endif
3754265e 241
2b5f62a0 242 (void) m_impl->ProcessEvent( &event );
32d4c30a 243 return true;
1b0fb34b 244}
dde19c21
FM
245
246bool wxGUIEventLoop::YieldFor(long eventsToProcess)
247{
248 // Sometimes only 2 yields seem
249 // to do the trick, e.g. in the
250 // progress dialog
251 int i;
252 for (i = 0; i < 2; i++)
253 {
254 m_isInsideYield = true;
255 m_eventsToProcessInsideYield = eventsToProcess;
256
257 // Call dispatch at least once so that sockets
258 // can be tested
259 wxTheApp->Dispatch();
260
261 // TODO: implement event filtering using the eventsToProcess mask
262 while (wxTheApp && wxTheApp->Pending())
263 wxTheApp->Dispatch();
264
265#if wxUSE_TIMER
266 wxGenericTimerImpl::NotifyTimers();
267#endif
268 ProcessIdle();
269
270 m_isInsideYield = false;
271 }
272
273 return true;
274}