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