]> git.saurik.com Git - wxWidgets.git/blame - src/x11/evtloop.cpp
Don't crash when laying out wxGridBagSizer with only hidden elements.
[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
1b0fb34b 7// Copyright: (c) 2002 Julian Smart
526954c5 8// Licence: wxWindows licence
1b0fb34b
JS
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
32d4c30a
WS
19// for compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
670f9935
WS
22#include "wx/evtloop.h"
23
32d4c30a
WS
24#ifndef WX_PRECOMP
25 #include "wx/hash.h"
670f9935 26 #include "wx/app.h"
cdccdfab 27 #include "wx/window.h"
02761f6c 28 #include "wx/module.h"
32d4c30a
WS
29#endif
30
4eba3923 31#include "wx/private/fdiodispatcher.h"
17a1ebd1 32#include "wx/unix/private.h"
1b0fb34b 33#include "wx/x11/private.h"
c2ca375c 34#include "wx/generic/private/timer.h"
1b0fb34b 35
32d4c30a
WS
36#if wxUSE_THREADS
37 #include "wx/thread.h"
38#endif
39
8193abb6 40#include <X11/Xlib.h>
1016f0de
JS
41#include <sys/time.h>
42#include <unistd.h>
43
bc023abb
MW
44#ifdef HAVE_SYS_SELECT_H
45# include <sys/select.h>
46#endif
47
1b0fb34b
JS
48// ----------------------------------------------------------------------------
49// wxEventLoopImpl
50// ----------------------------------------------------------------------------
51
52class WXDLLEXPORT wxEventLoopImpl
53{
54public:
55 // ctor
32d4c30a 56 wxEventLoopImpl() { SetExitCode(0); m_keepGoing = false; }
1b0fb34b 57
32d4c30a 58 // process an XEvent, return true if it was processed
086fd560 59 bool ProcessEvent(XEvent* event);
1b0fb34b 60
32d4c30a 61 // generate an idle message, return true if more idle time requested
1b0fb34b
JS
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:
32d4c30a 69 // preprocess an event, return true if processed (i.e. no further
1b0fb34b 70 // dispatching required)
7266b672 71 bool PreProcessEvent(XEvent* event);
1b0fb34b
JS
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
086fd560 87bool wxEventLoopImpl::ProcessEvent(XEvent *event)
1b0fb34b
JS
88{
89 // give us the chance to preprocess the message first
086fd560 90 if ( PreProcessEvent(event) )
32d4c30a 91 return true;
3754265e 92
086fd560
JS
93 // if it wasn't done, dispatch it to the corresponding window
94 if (wxTheApp)
95 return wxTheApp->ProcessXEvent((WXEvent*) event);
96
32d4c30a 97 return false;
1b0fb34b
JS
98}
99
89954433 100bool wxEventLoopImpl::PreProcessEvent(XEvent *WXUNUSED(event))
1b0fb34b 101{
32d4c30a 102 return false;
1b0fb34b
JS
103}
104
105// ----------------------------------------------------------------------------
106// wxEventLoopImpl idle event processing
107// ----------------------------------------------------------------------------
108
109bool wxEventLoopImpl::SendIdleEvent()
110{
e39af974 111 return wxTheApp->ProcessIdle();
1b0fb34b
JS
112}
113
114// ============================================================================
115// wxEventLoop implementation
116// ============================================================================
117
1b0fb34b
JS
118// ----------------------------------------------------------------------------
119// wxEventLoop running and exiting
120// ----------------------------------------------------------------------------
121
b46b1d59 122wxGUIEventLoop::~wxGUIEventLoop()
1b0fb34b 123{
9a83f860 124 wxASSERT_MSG( !m_impl, wxT("should have been deleted in Run()") );
1b0fb34b
JS
125}
126
c738d187 127int wxGUIEventLoop::DoRun()
1b0fb34b 128{
1b0fb34b 129 m_impl = new wxEventLoopImpl;
3754265e 130
32d4c30a 131 m_impl->m_keepGoing = true;
1b0fb34b
JS
132 while ( m_impl->m_keepGoing )
133 {
1b0fb34b
JS
134 // generate and process idle events for as long as we don't have
135 // anything else to do
136 while ( ! Pending() )
137 {
b555c37c 138#if wxUSE_TIMER
c2ca375c 139 wxGenericTimerImpl::NotifyTimers(); // TODO: is this the correct place for it?
b555c37c 140#endif
1b0fb34b
JS
141 if (!m_impl->SendIdleEvent())
142 {
1b0fb34b
JS
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
16d17da6
VZ
156 OnExit();
157
1b0fb34b 158 int exitcode = m_impl->GetExitCode();
5276b0a5 159 wxDELETE(m_impl);
1b0fb34b 160
1b0fb34b
JS
161 return exitcode;
162}
163
d3ad22bd 164void wxGUIEventLoop::ScheduleExit(int rc)
1b0fb34b 165{
2c032a5d
VZ
166 if ( m_impl )
167 {
168 m_impl->SetExitCode(rc);
169 m_impl->m_keepGoing = false;
170 }
1b0fb34b
JS
171}
172
173// ----------------------------------------------------------------------------
174// wxEventLoop message processing dispatching
175// ----------------------------------------------------------------------------
176
b46b1d59 177bool wxGUIEventLoop::Pending() const
1b0fb34b 178{
2b5f62a0
VZ
179 XFlush( wxGlobalDisplay() );
180 return (XPending( wxGlobalDisplay() ) > 0);
1b0fb34b
JS
181}
182
b46b1d59 183bool wxGUIEventLoop::Dispatch()
1b0fb34b 184{
1c991946
VZ
185 // see comment in wxEventLoopManual::ProcessEvents()
186 if ( wxTheApp )
187 wxTheApp->ProcessPendingEvents();
188
1b0fb34b
JS
189 XEvent event;
190
191 // TODO allowing for threads, as per e.g. wxMSW
192
1016f0de
JS
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.
3754265e 199
2b5f62a0 200 if (XPending( wxGlobalDisplay() ) == 0)
1016f0de 201 {
868741e9
JS
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.
3754265e 210
868741e9 211#else
1016f0de
JS
212 struct timeval tv;
213 tv.tv_sec=0;
214 tv.tv_usec=10000; // TODO make this configurable
2b5f62a0 215 int fd = ConnectionNumber( wxGlobalDisplay() );
3754265e 216
1016f0de 217 fd_set readset;
52127426 218 fd_set writeset;
17a1ebd1
VZ
219 wxFD_ZERO(&readset);
220 wxFD_ZERO(&writeset);
17a1ebd1 221 wxFD_SET(fd, &readset);
52127426 222
6b44a335 223 if (select( fd+1, &readset, &writeset, NULL, &tv ) != 0)
1016f0de 224 {
6b44a335 225 // An X11 event was pending, get it
17a1ebd1 226 if (wxFD_ISSET( fd, &readset ))
2b5f62a0 227 XNextEvent( wxGlobalDisplay(), &event );
b46b1d59 228 }
868741e9 229#endif
3754265e 230 }
2b5f62a0 231 else
1016f0de 232 {
2b5f62a0 233 XNextEvent( wxGlobalDisplay(), &event );
1016f0de 234 }
3754265e 235
6b44a335
VS
236#if wxUSE_SOCKETS
237 // handle any pending socket events:
4eba3923 238 wxFDIODispatcher::DispatchPending();
6b44a335 239#endif
3754265e 240
2b5f62a0 241 (void) m_impl->ProcessEvent( &event );
32d4c30a 242 return true;
1b0fb34b 243}
dde19c21
FM
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}