]> git.saurik.com Git - wxWidgets.git/blob - src/x11/evtloop.cpp
da51dca79ea3ba65a7e75fae9b455c34758dfa9d
[wxWidgets.git] / src / x11 / evtloop.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: 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 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "evtloop.h"
22 #endif
23
24 #include "wx/window.h"
25 #include "wx/app.h"
26 #include "wx/evtloop.h"
27 #include "wx/tooltip.h"
28 #if wxUSE_THREADS
29 #include "wx/thread.h"
30 #endif
31 #include "wx/x11/private.h"
32 #include "X11/Xlib.h"
33
34 // ----------------------------------------------------------------------------
35 // wxEventLoopImpl
36 // ----------------------------------------------------------------------------
37
38 class WXDLLEXPORT wxEventLoopImpl
39 {
40 public:
41 // ctor
42 wxEventLoopImpl() { SetExitCode(0); m_keepGoing = FALSE; }
43
44 // process an XEvent
45 void ProcessEvent(XEvent* event);
46
47 // generate an idle message, return TRUE if more idle time requested
48 bool SendIdleEvent();
49
50 // set/get the exit code
51 void SetExitCode(int exitcode) { m_exitcode = exitcode; }
52 int GetExitCode() const { return m_exitcode; }
53
54 public:
55 // preprocess an event, return TRUE if processed (i.e. no further
56 // dispatching required)
57 bool PreProcessEvent(XEvent* event);
58
59 // the exit code of the event loop
60 int m_exitcode;
61
62 bool m_keepGoing;
63 };
64
65 // ============================================================================
66 // wxEventLoopImpl implementation
67 // ============================================================================
68
69 // ----------------------------------------------------------------------------
70 // wxEventLoopImpl message processing
71 // ----------------------------------------------------------------------------
72
73 void wxEventLoopImpl::ProcessEvent(XEvent *event)
74 {
75 // give us the chance to preprocess the message first
76 if ( !PreProcessEvent(event) )
77 {
78 // if it wasn't done, dispatch it to the corresponding window
79 if (wxTheApp)
80 wxTheApp->ProcessXEvent((WXEvent*) event);
81 }
82 }
83
84 bool wxEventLoopImpl::PreProcessEvent(XEvent *event)
85 {
86 // TODO
87 #if 0
88 HWND hWnd = msg->hwnd;
89 wxWindow *wndThis = wxGetWindowFromHWND((WXHWND)hWnd);
90
91
92 // try translations first; find the youngest window with a translation
93 // table.
94 wxWindow *wnd;
95 for ( wnd = wndThis; wnd; wnd = wnd->GetParent() )
96 {
97 if ( wnd->MSWTranslateMessage((WXMSG *)msg) )
98 return TRUE;
99 }
100
101 // Anyone for a non-translation message? Try youngest descendants first.
102 for ( wnd = wndThis; wnd; wnd = wnd->GetParent() )
103 {
104 if ( wnd->MSWProcessMessage((WXMSG *)msg) )
105 return TRUE;
106 }
107 #endif
108
109 return FALSE;
110 }
111
112 // ----------------------------------------------------------------------------
113 // wxEventLoopImpl idle event processing
114 // ----------------------------------------------------------------------------
115
116 bool wxEventLoopImpl::SendIdleEvent()
117 {
118 wxIdleEvent event;
119 event.SetEventObject(wxTheApp);
120
121 return wxTheApp->ProcessEvent(event) && event.MoreRequested();
122 }
123
124 // ============================================================================
125 // wxEventLoop implementation
126 // ============================================================================
127
128 wxEventLoop *wxEventLoop::ms_activeLoop = NULL;
129
130 // ----------------------------------------------------------------------------
131 // wxEventLoop running and exiting
132 // ----------------------------------------------------------------------------
133
134 wxEventLoop::~wxEventLoop()
135 {
136 wxASSERT_MSG( !m_impl, _T("should have been deleted in Run()") );
137 }
138
139 bool wxEventLoop::IsRunning() const
140 {
141 return m_impl != NULL;
142 }
143
144 int wxEventLoop::Run()
145 {
146 // event loops are not recursive, you need to create another loop!
147 wxCHECK_MSG( !IsRunning(), -1, _T("can't reenter a message loop") );
148
149 m_impl = new wxEventLoopImpl;
150
151 wxEventLoop *oldLoop = ms_activeLoop;
152 ms_activeLoop = this;
153
154 m_impl->m_keepGoing = TRUE;
155 while ( m_impl->m_keepGoing )
156 {
157 #if 0 // wxUSE_THREADS
158 wxMutexGuiLeaveOrEnter();
159 #endif // wxUSE_THREADS
160
161 // generate and process idle events for as long as we don't have
162 // anything else to do
163 while ( ! Pending() )
164 {
165 if (!m_impl->SendIdleEvent())
166 {
167 #if 0 // wxUSE_THREADS
168 // leave the main loop to give other threads a chance to
169 // perform their GUI work
170 wxMutexGuiLeave();
171 wxUsleep(20);
172 wxMutexGuiEnter();
173 #endif
174 // Break out of while loop
175 break;
176 }
177 }
178
179 // a message came or no more idle processing to do, sit in Dispatch()
180 // waiting for the next message
181 if ( !Dispatch() )
182 {
183 break;
184 }
185 }
186
187 int exitcode = m_impl->GetExitCode();
188 delete m_impl;
189 m_impl = NULL;
190
191 ms_activeLoop = oldLoop;
192
193 return exitcode;
194 }
195
196 void wxEventLoop::Exit(int rc)
197 {
198 wxCHECK_RET( IsRunning(), _T("can't call Exit() if not running") );
199
200 m_impl->SetExitCode(rc);
201 m_impl->m_keepGoing = FALSE;
202 }
203
204 // ----------------------------------------------------------------------------
205 // wxEventLoop message processing dispatching
206 // ----------------------------------------------------------------------------
207
208 bool wxEventLoop::Pending() const
209 {
210 XFlush((Display*) wxGetDisplay());
211 return (XPending((Display*) wxGetDisplay()) > 0);
212 }
213
214 bool wxEventLoop::Dispatch()
215 {
216 XEvent event;
217
218 // TODO allowing for threads, as per e.g. wxMSW
219
220 XNextEvent((Display*) wxGetDisplay(), & event);
221 m_impl->ProcessEvent(& event);
222 return TRUE;
223 }
224