]> git.saurik.com Git - wxWidgets.git/blame - src/common/selectdispatcher.cpp
Return NULL from wxWindow::GetCapture() when the capture is being lost.
[wxWidgets.git] / src / common / selectdispatcher.cpp
CommitLineData
30c45bdd 1///////////////////////////////////////////////////////////////////////////////
b46b1d59 2// Name: src/common/selectdispatcher.cpp
30c45bdd 3// Purpose: implements dispatcher for select() call
b46b1d59 4// Author: Lukasz Michalski and Vadim Zeitlin
30c45bdd 5// Created: December 2006
30c45bdd 6// Copyright: (c) 2006 Lukasz Michalski
526954c5 7// Licence: wxWindows licence
30c45bdd
VZ
8///////////////////////////////////////////////////////////////////////////////
9
10// ============================================================================
11// declarations
12// ============================================================================
13
14// ----------------------------------------------------------------------------
15// headers
16// ----------------------------------------------------------------------------
17
18// for compilers that support precompilation, includes "wx.h".
19#include "wx/wxprec.h"
20
b4715d08
VZ
21#ifdef __BORLANDC__
22 #pragma hdrstop
23#endif
24
a1873279
VZ
25#if wxUSE_SELECT_DISPATCHER
26
30c45bdd 27#include "wx/private/selectdispatcher.h"
30c45bdd 28#include "wx/unix/private.h"
30c45bdd
VZ
29
30#ifndef WX_PRECOMP
31 #include "wx/hash.h"
b5ef33b2
VS
32 #include "wx/log.h"
33 #include "wx/intl.h"
30c45bdd
VZ
34#endif
35
b46b1d59
VZ
36#include <errno.h>
37
30c45bdd
VZ
38#define wxSelectDispatcher_Trace wxT("selectdispatcher")
39
40// ============================================================================
41// implementation
42// ============================================================================
43
44// ----------------------------------------------------------------------------
b46b1d59 45// wxSelectSets
30c45bdd
VZ
46// ----------------------------------------------------------------------------
47
b46b1d59
VZ
48int wxSelectSets::ms_flags[wxSelectSets::Max] =
49{
50 wxFDIO_INPUT,
51 wxFDIO_OUTPUT,
52 wxFDIO_EXCEPTION,
53};
30c45bdd 54
b46b1d59 55const char *wxSelectSets::ms_names[wxSelectSets::Max] =
30c45bdd 56{
b46b1d59
VZ
57 "input",
58 "output",
59 "exceptional",
60};
30c45bdd 61
b46b1d59 62wxSelectSets::Callback wxSelectSets::ms_handlers[wxSelectSets::Max] =
30c45bdd 63{
b46b1d59
VZ
64 &wxFDIOHandler::OnReadWaiting,
65 &wxFDIOHandler::OnWriteWaiting,
66 &wxFDIOHandler::OnExceptionWaiting,
67};
30c45bdd 68
b46b1d59
VZ
69wxSelectSets::wxSelectSets()
70{
71 for ( int n = 0; n < Max; n++ )
30c45bdd 72 {
b46b1d59 73 wxFD_ZERO(&m_fds[n]);
30c45bdd 74 }
b46b1d59 75}
30c45bdd 76
b46b1d59
VZ
77bool wxSelectSets::HasFD(int fd) const
78{
79 for ( int n = 0; n < Max; n++ )
30c45bdd 80 {
fa15eac7 81 if ( wxFD_ISSET(fd, (fd_set*) &m_fds[n]) )
b46b1d59
VZ
82 return true;
83 }
30c45bdd 84
b46b1d59 85 return false;
30c45bdd
VZ
86}
87
b46b1d59 88bool wxSelectSets::SetFD(int fd, int flags)
30c45bdd 89{
9a83f860 90 wxCHECK_MSG( fd >= 0, false, wxT("invalid descriptor") );
30c45bdd 91
b46b1d59 92 for ( int n = 0; n < Max; n++ )
30c45bdd 93 {
b46b1d59
VZ
94 if ( flags & ms_flags[n] )
95 {
96 wxFD_SET(fd, &m_fds[n]);
b46b1d59 97 }
fa15eac7 98 else if ( wxFD_ISSET(fd, (fd_set*) &m_fds[n]) )
b46b1d59
VZ
99 {
100 wxFD_CLR(fd, &m_fds[n]);
b46b1d59 101 }
30c45bdd
VZ
102 }
103
b46b1d59
VZ
104 return true;
105}
30c45bdd 106
b46b1d59
VZ
107int wxSelectSets::Select(int nfds, struct timeval *tv)
108{
109 return select(nfds, &m_fds[Read], &m_fds[Write], &m_fds[Except], tv);
110}
30c45bdd 111
a12698ab 112bool wxSelectSets::Handle(int fd, wxFDIOHandler& handler) const
b46b1d59
VZ
113{
114 for ( int n = 0; n < Max; n++ )
30c45bdd 115 {
fa15eac7 116 if ( wxFD_ISSET(fd, (fd_set*) &m_fds[n]) )
30c45bdd 117 {
b46b1d59 118 wxLogTrace(wxSelectDispatcher_Trace,
9a83f860 119 wxT("Got %s event on fd %d"), ms_names[n], fd);
b46b1d59 120 (handler.*ms_handlers[n])();
2804f77d
VZ
121 // callback can modify sets and destroy handler
122 // this forces that one event can be processed at one time
a12698ab 123 return true;
b46b1d59
VZ
124 }
125 }
a12698ab
VZ
126
127 return false;
30c45bdd
VZ
128}
129
b46b1d59
VZ
130// ----------------------------------------------------------------------------
131// wxSelectDispatcher
132// ----------------------------------------------------------------------------
133
b46b1d59
VZ
134bool wxSelectDispatcher::RegisterFD(int fd, wxFDIOHandler *handler, int flags)
135{
ad8d42f8 136 if ( !wxMappedFDIODispatcher::RegisterFD(fd, handler, flags) )
b46b1d59
VZ
137 return false;
138
139 if ( !m_sets.SetFD(fd, flags) )
140 return false;
141
142 if ( fd > m_maxFD )
143 m_maxFD = fd;
144
2804f77d 145 wxLogTrace(wxSelectDispatcher_Trace,
9a83f860 146 wxT("Registered fd %d: input:%d, output:%d, exceptional:%d"), fd, (flags & wxFDIO_INPUT) == wxFDIO_INPUT, (flags & wxFDIO_OUTPUT), (flags & wxFDIO_EXCEPTION) == wxFDIO_EXCEPTION);
b46b1d59
VZ
147 return true;
148}
149
150bool wxSelectDispatcher::ModifyFD(int fd, wxFDIOHandler *handler, int flags)
151{
ad8d42f8 152 if ( !wxMappedFDIODispatcher::ModifyFD(fd, handler, flags) )
b46b1d59
VZ
153 return false;
154
9a83f860 155 wxASSERT_MSG( fd <= m_maxFD, wxT("logic error: registered fd > m_maxFD?") );
b46b1d59 156
2804f77d 157 wxLogTrace(wxSelectDispatcher_Trace,
9a83f860 158 wxT("Modified fd %d: input:%d, output:%d, exceptional:%d"), fd, (flags & wxFDIO_INPUT) == wxFDIO_INPUT, (flags & wxFDIO_OUTPUT) == wxFDIO_OUTPUT, (flags & wxFDIO_EXCEPTION) == wxFDIO_EXCEPTION);
b46b1d59
VZ
159 return m_sets.SetFD(fd, flags);
160}
161
af57c51a 162bool wxSelectDispatcher::UnregisterFD(int fd)
b46b1d59 163{
af57c51a
VZ
164 m_sets.ClearFD(fd);
165
166 if ( !wxMappedFDIODispatcher::UnregisterFD(fd) )
167 return false;
b46b1d59
VZ
168
169 // remove the handler if we don't need it any more
170 if ( !m_sets.HasFD(fd) )
171 {
172 if ( fd == m_maxFD )
30c45bdd 173 {
b46b1d59
VZ
174 // need to find new max fd
175 m_maxFD = -1;
176 for ( wxFDIOHandlerMap::const_iterator it = m_handlers.begin();
177 it != m_handlers.end();
178 ++it )
30c45bdd 179 {
b46b1d59 180 if ( it->first > m_maxFD )
2804f77d 181 {
b46b1d59 182 m_maxFD = it->first;
2804f77d 183 }
b46b1d59
VZ
184 }
185 }
186 }
187
2804f77d 188 wxLogTrace(wxSelectDispatcher_Trace,
9a83f860 189 wxT("Removed fd %d, current max: %d"), fd, m_maxFD);
ad8d42f8 190 return true;
30c45bdd
VZ
191}
192
a12698ab 193int wxSelectDispatcher::ProcessSets(const wxSelectSets& sets)
30c45bdd 194{
a12698ab 195 int numEvents = 0;
b46b1d59
VZ
196 for ( int fd = 0; fd <= m_maxFD; fd++ )
197 {
198 if ( !sets.HasFD(fd) )
199 continue;
200
201 wxFDIOHandler * const handler = FindHandler(fd);
202 if ( !handler )
203 {
9a83f860 204 wxFAIL_MSG( wxT("NULL handler in wxSelectDispatcher?") );
b46b1d59
VZ
205 continue;
206 }
207
a12698ab
VZ
208 if ( sets.Handle(fd, *handler) )
209 numEvents++;
b46b1d59 210 }
5a557d1e 211
a12698ab 212 return numEvents;
b46b1d59 213}
30c45bdd 214
a12698ab 215int wxSelectDispatcher::DoSelect(wxSelectSets& sets, int timeout) const
30c45bdd 216{
b46b1d59 217 struct timeval tv,
7523de90 218 *ptv;
b46b1d59 219 if ( timeout != TIMEOUT_INFINITE )
30c45bdd
VZ
220 {
221 ptv = &tv;
947d5ad0
VZ
222 tv.tv_sec = timeout / 1000;
223 tv.tv_usec = (timeout % 1000)*1000;
b46b1d59 224 }
7523de90 225 else // no timeout
30c45bdd 226 {
7523de90
VZ
227 ptv = NULL;
228 }
b46b1d59 229
a12698ab 230 int ret = sets.Select(m_maxFD + 1, ptv);
b46b1d59 231
a12698ab
VZ
232 // TODO: we need to restart select() in this case but for now just return
233 // as if timeout expired
234 if ( ret == -1 && errno == EINTR )
235 ret = 0;
236
237 return ret;
238}
239
240bool wxSelectDispatcher::HasPending() const
241{
242 wxSelectSets sets(m_sets);
243 return DoSelect(sets, 0) > 0;
244}
245
246int wxSelectDispatcher::Dispatch(int timeout)
247{
248 wxSelectSets sets(m_sets);
249 switch ( DoSelect(sets, timeout) )
7523de90
VZ
250 {
251 case -1:
a12698ab
VZ
252 wxLogSysError(_("Failed to monitor I/O channels"));
253 return -1;
b46b1d59 254
7523de90
VZ
255 case 0:
256 // timeout expired without anything happening
a12698ab 257 return 0;
b46b1d59 258
7523de90 259 default:
a12698ab 260 return ProcessSets(sets);
b46b1d59 261 }
30c45bdd
VZ
262}
263
a1873279 264#endif // wxUSE_SELECT_DISPATCHER