]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/x11/evtloop.cpp
Fixed wxscintilla compilation for wxDFB.
[wxWidgets.git] / src / x11 / evtloop.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/x11/evtloop.cpp
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
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#include "wx/evtloop.h"
24
25#ifndef WX_PRECOMP
26 #include "wx/hash.h"
27 #include "wx/app.h"
28 #include "wx/window.h"
29 #include "wx/module.h"
30#endif
31
32#include "wx/private/fdiodispatcher.h"
33#include "wx/unix/private.h"
34#include "wx/x11/private.h"
35#include "wx/generic/private/timer.h"
36
37#if wxUSE_THREADS
38 #include "wx/thread.h"
39#endif
40
41#include <X11/Xlib.h>
42#include <sys/time.h>
43#include <unistd.h>
44
45#ifdef HAVE_SYS_SELECT_H
46# include <sys/select.h>
47#endif
48
49// ----------------------------------------------------------------------------
50// wxEventLoopImpl
51// ----------------------------------------------------------------------------
52
53class WXDLLEXPORT wxEventLoopImpl
54{
55public:
56 // ctor
57 wxEventLoopImpl() { SetExitCode(0); m_keepGoing = false; }
58
59 // process an XEvent, return true if it was processed
60 bool ProcessEvent(XEvent* event);
61
62 // generate an idle message, return true if more idle time requested
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:
70 // preprocess an event, return true if processed (i.e. no further
71 // dispatching required)
72 bool PreProcessEvent(XEvent* event);
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
88bool wxEventLoopImpl::ProcessEvent(XEvent *event)
89{
90 // give us the chance to preprocess the message first
91 if ( PreProcessEvent(event) )
92 return true;
93
94 // if it wasn't done, dispatch it to the corresponding window
95 if (wxTheApp)
96 return wxTheApp->ProcessXEvent((WXEvent*) event);
97
98 return false;
99}
100
101bool wxEventLoopImpl::PreProcessEvent(XEvent *WXUNUSED(event))
102{
103 return false;
104}
105
106// ----------------------------------------------------------------------------
107// wxEventLoopImpl idle event processing
108// ----------------------------------------------------------------------------
109
110bool wxEventLoopImpl::SendIdleEvent()
111{
112 return wxTheApp->ProcessIdle();
113}
114
115// ============================================================================
116// wxEventLoop implementation
117// ============================================================================
118
119// ----------------------------------------------------------------------------
120// wxEventLoop running and exiting
121// ----------------------------------------------------------------------------
122
123wxGUIEventLoop::~wxGUIEventLoop()
124{
125 wxASSERT_MSG( !m_impl, wxT("should have been deleted in Run()") );
126}
127
128int wxGUIEventLoop::Run()
129{
130 // event loops are not recursive, you need to create another loop!
131 wxCHECK_MSG( !IsRunning(), -1, wxT("can't reenter a message loop") );
132
133 m_impl = new wxEventLoopImpl;
134
135 wxEventLoopActivator activate(this);
136
137 m_impl->m_keepGoing = true;
138 while ( m_impl->m_keepGoing )
139 {
140 // generate and process idle events for as long as we don't have
141 // anything else to do
142 while ( ! Pending() )
143 {
144#if wxUSE_TIMER
145 wxGenericTimerImpl::NotifyTimers(); // TODO: is this the correct place for it?
146#endif
147 if (!m_impl->SendIdleEvent())
148 {
149 // Break out of while loop
150 break;
151 }
152 }
153
154 // a message came or no more idle processing to do, sit in Dispatch()
155 // waiting for the next message
156 if ( !Dispatch() )
157 {
158 break;
159 }
160 }
161
162 OnExit();
163
164 int exitcode = m_impl->GetExitCode();
165 wxDELETE(m_impl);
166
167 return exitcode;
168}
169
170void wxGUIEventLoop::Exit(int rc)
171{
172 wxCHECK_RET( IsRunning(), wxT("can't call Exit() if not running") );
173
174 m_impl->SetExitCode(rc);
175 m_impl->m_keepGoing = false;
176}
177
178// ----------------------------------------------------------------------------
179// wxEventLoop message processing dispatching
180// ----------------------------------------------------------------------------
181
182bool wxGUIEventLoop::Pending() const
183{
184 XFlush( wxGlobalDisplay() );
185 return (XPending( wxGlobalDisplay() ) > 0);
186}
187
188bool wxGUIEventLoop::Dispatch()
189{
190 // see comment in wxEventLoopManual::ProcessEvents()
191 if ( wxTheApp )
192 wxTheApp->ProcessPendingEvents();
193
194 XEvent event;
195
196 // TODO allowing for threads, as per e.g. wxMSW
197
198 // This now waits until either an X event is received,
199 // or the select times out. So we should now process
200 // wxTimers in a reasonably timely fashion. However it
201 // does also mean that idle processing will happen more
202 // often, so we should probably limit idle processing to
203 // not be repeated more than every N milliseconds.
204
205 if (XPending( wxGlobalDisplay() ) == 0)
206 {
207#if wxUSE_NANOX
208 GR_TIMEOUT timeout = 10; // Milliseconds
209 // Wait for next event, or timeout
210 GrGetNextEventTimeout(& event, timeout);
211
212 // Fall through to ProcessEvent.
213 // we'll assume that ProcessEvent will just ignore
214 // the event if there was a timeout and no event.
215
216#else
217 struct timeval tv;
218 tv.tv_sec=0;
219 tv.tv_usec=10000; // TODO make this configurable
220 int fd = ConnectionNumber( wxGlobalDisplay() );
221
222 fd_set readset;
223 fd_set writeset;
224 wxFD_ZERO(&readset);
225 wxFD_ZERO(&writeset);
226 wxFD_SET(fd, &readset);
227
228 if (select( fd+1, &readset, &writeset, NULL, &tv ) != 0)
229 {
230 // An X11 event was pending, get it
231 if (wxFD_ISSET( fd, &readset ))
232 XNextEvent( wxGlobalDisplay(), &event );
233 }
234#endif
235 }
236 else
237 {
238 XNextEvent( wxGlobalDisplay(), &event );
239 }
240
241#if wxUSE_SOCKETS
242 // handle any pending socket events:
243 wxFDIODispatcher::DispatchPending();
244#endif
245
246 (void) m_impl->ProcessEvent( &event );
247 return true;
248}
249
250bool wxGUIEventLoop::YieldFor(long eventsToProcess)
251{
252 // Sometimes only 2 yields seem
253 // to do the trick, e.g. in the
254 // progress dialog
255 int i;
256 for (i = 0; i < 2; i++)
257 {
258 m_isInsideYield = true;
259 m_eventsToProcessInsideYield = eventsToProcess;
260
261 // Call dispatch at least once so that sockets
262 // can be tested
263 wxTheApp->Dispatch();
264
265 // TODO: implement event filtering using the eventsToProcess mask
266 while (wxTheApp && wxTheApp->Pending())
267 wxTheApp->Dispatch();
268
269#if wxUSE_TIMER
270 wxGenericTimerImpl::NotifyTimers();
271#endif
272 ProcessIdle();
273
274 m_isInsideYield = false;
275 }
276
277 return true;
278}