]> git.saurik.com Git - wxWidgets.git/blob - src/unix/evtloopunix.cpp
Workaround for #15404: wxRichTextCtrl: caret does not disappear when focus is lost...
[wxWidgets.git] / src / unix / evtloopunix.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/unix/evtloopunix.cpp
3 // Purpose: wxEventLoop implementation
4 // Author: Lukasz Michalski (lm@zork.pl)
5 // Created: 2007-05-07
6 // Copyright: (c) 2006 Zork Lukasz Michalski
7 // (c) 2009, 2013 Vadim Zeitlin <vadim@wxwidgets.org>
8 // (c) 2013 Rob Bresalier
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 #if wxUSE_CONSOLE_EVENTLOOP
24
25 #include "wx/evtloop.h"
26
27 #ifndef WX_PRECOMP
28 #include "wx/app.h"
29 #include "wx/log.h"
30 #endif
31
32 #include "wx/apptrait.h"
33 #include "wx/scopedptr.h"
34 #include "wx/thread.h"
35 #include "wx/module.h"
36 #include "wx/unix/private/timer.h"
37 #include "wx/unix/private/epolldispatcher.h"
38 #include "wx/unix/private/wakeuppipe.h"
39 #include "wx/private/selectdispatcher.h"
40 #include "wx/private/eventloopsourcesmanager.h"
41 #include "wx/private/fdioeventloopsourcehandler.h"
42 #include "wx/private/eventloopsourcesmanager.h"
43
44 #if wxUSE_EVENTLOOP_SOURCE
45 #include "wx/evtloopsrc.h"
46 #endif // wxUSE_EVENTLOOP_SOURCE
47
48 // ===========================================================================
49 // wxEventLoop implementation
50 // ===========================================================================
51
52 //-----------------------------------------------------------------------------
53 // initialization
54 //-----------------------------------------------------------------------------
55
56 wxConsoleEventLoop::wxConsoleEventLoop()
57 {
58 // Be pessimistic initially and assume that we failed to initialize.
59 m_dispatcher = NULL;
60 m_wakeupPipe = NULL;
61 m_wakeupSource = NULL;
62
63 // Create the pipe.
64 wxScopedPtr<wxWakeUpPipeMT> wakeupPipe(new wxWakeUpPipeMT);
65 const int pipeFD = wakeupPipe->GetReadFd();
66 if ( pipeFD == wxPipe::INVALID_FD )
67 return;
68
69 // And start monitoring it in our event loop.
70 m_wakeupSource = wxEventLoopBase::AddSourceForFD
71 (
72 pipeFD,
73 wakeupPipe.get(),
74 wxFDIO_INPUT
75 );
76
77 if ( !m_wakeupSource )
78 return;
79
80 // This is a bit ugly but we know that AddSourceForFD() used the currently
81 // active dispatcher to register this source, so use the same one for our
82 // other operations. Of course, currently the dispatcher returned by
83 // wxFDIODispatcher::Get() is always the same one anyhow so it doesn't
84 // really matter, but if we started returning different things later, it
85 // would.
86 m_dispatcher = wxFDIODispatcher::Get();
87
88 m_wakeupPipe = wakeupPipe.release();
89 }
90
91 wxConsoleEventLoop::~wxConsoleEventLoop()
92 {
93 if ( m_wakeupPipe )
94 {
95 delete m_wakeupSource;
96
97 delete m_wakeupPipe;
98 }
99 }
100
101 //-----------------------------------------------------------------------------
102 // adding & removing sources
103 //-----------------------------------------------------------------------------
104
105 #if wxUSE_EVENTLOOP_SOURCE
106
107 class wxConsoleEventLoopSourcesManager : public wxEventLoopSourcesManagerBase
108 {
109 public:
110 wxEventLoopSource* AddSourceForFD( int fd,
111 wxEventLoopSourceHandler *handler,
112 int flags)
113 {
114 wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" );
115
116 wxLogTrace(wxTRACE_EVT_SOURCE,
117 "Adding event loop source for fd=%d", fd);
118
119 // we need a bridge to wxFDIODispatcher
120 //
121 // TODO: refactor the code so that only wxEventLoopSourceHandler is used
122 wxScopedPtr<wxFDIOHandler>
123 fdioHandler(new wxFDIOEventLoopSourceHandler(handler));
124
125 if ( !wxFDIODispatcher::Get()->RegisterFD(fd, fdioHandler.get(), flags) )
126 return NULL;
127
128 return new wxUnixEventLoopSource(wxFDIODispatcher::Get(), fdioHandler.release(),
129 fd, handler, flags);
130 }
131 };
132
133 wxEventLoopSourcesManagerBase* wxAppTraits::GetEventLoopSourcesManager()
134 {
135 static wxConsoleEventLoopSourcesManager s_eventLoopSourcesManager;
136
137 return &s_eventLoopSourcesManager;
138 }
139
140 wxUnixEventLoopSource::~wxUnixEventLoopSource()
141 {
142 wxLogTrace(wxTRACE_EVT_SOURCE,
143 "Removing event loop source for fd=%d", m_fd);
144
145 m_dispatcher->UnregisterFD(m_fd);
146
147 delete m_fdioHandler;
148 }
149
150 #endif // wxUSE_EVENTLOOP_SOURCE
151
152 //-----------------------------------------------------------------------------
153 // events dispatch and loop handling
154 //-----------------------------------------------------------------------------
155
156 bool wxConsoleEventLoop::Pending() const
157 {
158 if ( m_dispatcher->HasPending() )
159 return true;
160
161 #if wxUSE_TIMER
162 wxUsecClock_t nextTimer;
163 if ( wxTimerScheduler::Get().GetNext(&nextTimer) &&
164 !wxMilliClockToLong(nextTimer) )
165 return true;
166 #endif // wxUSE_TIMER
167
168 return false;
169 }
170
171 bool wxConsoleEventLoop::Dispatch()
172 {
173 DispatchTimeout(static_cast<unsigned long>(
174 wxFDIODispatcher::TIMEOUT_INFINITE));
175
176 return true;
177 }
178
179 int wxConsoleEventLoop::DispatchTimeout(unsigned long timeout)
180 {
181 #if wxUSE_TIMER
182 // check if we need to decrease the timeout to account for a timer
183 wxUsecClock_t nextTimer;
184 if ( wxTimerScheduler::Get().GetNext(&nextTimer) )
185 {
186 unsigned long timeUntilNextTimer = wxMilliClockToLong(nextTimer / 1000);
187 if ( timeUntilNextTimer < timeout )
188 timeout = timeUntilNextTimer;
189 }
190 #endif // wxUSE_TIMER
191
192 bool hadEvent = m_dispatcher->Dispatch(timeout) > 0;
193
194 #if wxUSE_TIMER
195 if ( wxTimerScheduler::Get().NotifyExpired() )
196 hadEvent = true;
197 #endif // wxUSE_TIMER
198
199 return hadEvent ? 1 : -1;
200 }
201
202 void wxConsoleEventLoop::WakeUp()
203 {
204 m_wakeupPipe->WakeUp();
205 }
206
207 void wxConsoleEventLoop::OnNextIteration()
208 {
209 // call the signal handlers for any signals we caught recently
210 wxTheApp->CheckSignal();
211 }
212
213
214 wxEventLoopBase *wxConsoleAppTraits::CreateEventLoop()
215 {
216 return new wxEventLoop();
217 }
218
219 #endif // wxUSE_CONSOLE_EVENTLOOP