1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/x11/evtloop.cpp 
   3 // Purpose:     implements wxEventLoop for X11 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) 2002 Julian Smart 
   9 // License:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // for compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  23 #include "wx/evtloop.h" 
  28     #include "wx/window.h" 
  29     #include "wx/module.h" 
  32 #include "wx/private/fdiodispatcher.h" 
  33 #include "wx/unix/private.h" 
  34 #include "wx/x11/private.h" 
  35 #include "wx/generic/private/timer.h" 
  38     #include "wx/thread.h" 
  45 #ifdef HAVE_SYS_SELECT_H 
  46 #   include <sys/select.h> 
  49 // ---------------------------------------------------------------------------- 
  51 // ---------------------------------------------------------------------------- 
  53 class WXDLLEXPORT wxEventLoopImpl
 
  57     wxEventLoopImpl() { SetExitCode(0); m_keepGoing 
= false; } 
  59     // process an XEvent, return true if it was processed 
  60     bool ProcessEvent(XEvent
* event
); 
  62     // generate an idle message, return true if more idle time requested 
  65     // set/get the exit code 
  66     void SetExitCode(int exitcode
) { m_exitcode 
= exitcode
; } 
  67     int GetExitCode() const { return m_exitcode
; } 
  70     // preprocess an event, return true if processed (i.e. no further 
  71     // dispatching required) 
  72     bool PreProcessEvent(XEvent
* event
); 
  74     // the exit code of the event loop 
  80 // ============================================================================ 
  81 // wxEventLoopImpl implementation 
  82 // ============================================================================ 
  84 // ---------------------------------------------------------------------------- 
  85 // wxEventLoopImpl message processing 
  86 // ---------------------------------------------------------------------------- 
  88 bool wxEventLoopImpl::ProcessEvent(XEvent 
*event
) 
  90     // give us the chance to preprocess the message first 
  91     if ( PreProcessEvent(event
) ) 
  94     // if it wasn't done, dispatch it to the corresponding window 
  96         return wxTheApp
->ProcessXEvent((WXEvent
*) event
); 
 101 bool wxEventLoopImpl::PreProcessEvent(XEvent 
*WXUNUSED(event
)) 
 106 // ---------------------------------------------------------------------------- 
 107 // wxEventLoopImpl idle event processing 
 108 // ---------------------------------------------------------------------------- 
 110 bool wxEventLoopImpl::SendIdleEvent() 
 112     return wxTheApp
->ProcessIdle(); 
 115 // ============================================================================ 
 116 // wxEventLoop implementation 
 117 // ============================================================================ 
 119 // ---------------------------------------------------------------------------- 
 120 // wxEventLoop running and exiting 
 121 // ---------------------------------------------------------------------------- 
 123 wxGUIEventLoop::~wxGUIEventLoop() 
 125     wxASSERT_MSG( !m_impl
, _T("should have been deleted in Run()") ); 
 128 int wxGUIEventLoop::Run() 
 130     // event loops are not recursive, you need to create another loop! 
 131     wxCHECK_MSG( !IsRunning(), -1, _T("can't reenter a message loop") ); 
 133     m_impl 
= new wxEventLoopImpl
; 
 135     wxEventLoopActivator 
activate(this); 
 137     m_impl
->m_keepGoing 
= true; 
 138     while ( m_impl
->m_keepGoing 
) 
 140         // generate and process idle events for as long as we don't have 
 141         // anything else to do 
 142         while ( ! Pending() ) 
 145             wxGenericTimerImpl::NotifyTimers(); // TODO: is this the correct place for it? 
 147             if (!m_impl
->SendIdleEvent()) 
 149                 // Break out of while loop 
 154         // a message came or no more idle processing to do, sit in Dispatch() 
 155         // waiting for the next message 
 164     int exitcode 
= m_impl
->GetExitCode(); 
 171 void wxGUIEventLoop::Exit(int rc
) 
 173     wxCHECK_RET( IsRunning(), _T("can't call Exit() if not running") ); 
 175     m_impl
->SetExitCode(rc
); 
 176     m_impl
->m_keepGoing 
= false; 
 179 // ---------------------------------------------------------------------------- 
 180 // wxEventLoop message processing dispatching 
 181 // ---------------------------------------------------------------------------- 
 183 bool wxGUIEventLoop::Pending() const 
 185     XFlush( wxGlobalDisplay() ); 
 186     return (XPending( wxGlobalDisplay() ) > 0); 
 189 bool wxGUIEventLoop::Dispatch() 
 193     // TODO allowing for threads, as per e.g. wxMSW 
 195     // This now waits until either an X event is received, 
 196     // or the select times out. So we should now process 
 197     // wxTimers in a reasonably timely fashion. However it 
 198     // does also mean that idle processing will happen more 
 199     // often, so we should probably limit idle processing to 
 200     // not be repeated more than every N milliseconds. 
 202     if (XPending( wxGlobalDisplay() ) == 0) 
 205         GR_TIMEOUT timeout 
= 10; // Milliseconds 
 206         // Wait for next event, or timeout 
 207         GrGetNextEventTimeout(& event
, timeout
); 
 209         // Fall through to ProcessEvent. 
 210         // we'll assume that ProcessEvent will just ignore 
 211         // the event if there was a timeout and no event. 
 216         tv
.tv_usec
=10000; // TODO make this configurable 
 217         int fd 
= ConnectionNumber( wxGlobalDisplay() ); 
 222         wxFD_ZERO(&writeset
); 
 223         wxFD_SET(fd
, &readset
); 
 225         if (select( fd
+1, &readset
, &writeset
, NULL
, &tv 
) != 0) 
 227             // An X11 event was pending, get it 
 228             if (wxFD_ISSET( fd
, &readset 
)) 
 229                 XNextEvent( wxGlobalDisplay(), &event 
); 
 235         XNextEvent( wxGlobalDisplay(), &event 
); 
 239     // handle any pending socket events: 
 240     wxFDIODispatcher::DispatchPending(); 
 243     (void) m_impl
->ProcessEvent( &event 
);