#include "wx/defs.h"
#include "wx/object.h"
#include "wx/gdicmn.h"
+#if wxUSE_THREADS
+#include "wx/thread.h"
+#endif
/*
* Event types
// Set/Get listbox/choice selection string
void SetString(const wxString& s) { m_commandString = s; }
- const wxString& GetString() const { return m_commandString; }
+ wxString GetString() const { return m_commandString; }
// Get checkbox value
bool Checked() const { return (m_commandInt != 0); }
virtual bool OnClose();
#endif
+#if wxUSE_THREADS
+ bool ProcessThreadEvent(wxEvent& event);
+ void ProcessPendingEvents();
+#endif
virtual bool ProcessEvent(wxEvent& event);
virtual bool SearchEventTable(wxEventTable& table, wxEvent& event);
virtual const wxEventTable *GetEventTable() const;
protected:
- wxEvtHandler* m_nextHandler;
- wxEvtHandler* m_previousHandler;
- bool m_enabled; // Is event handler enabled?
- wxList* m_dynamicEvents;
+ wxEvtHandler* m_nextHandler;
+ wxEvtHandler* m_previousHandler;
+ bool m_enabled; // Is event handler enabled?
+ wxList* m_dynamicEvents;
+ wxList* m_pendingEvents;
+#if wxUSE_THREADS
+ wxCriticalSection* m_eventsLocker;
+#endif
// optimization: instead of using costly IsKindOf() to decide whether we're
// a window (which is true in 99% of cases), use this flag
static void CleanUp();
bool ProcessIdle();
+#if wxUSE_THREADS
+ void ProcessPendingEvents();
+#endif
void DeletePendingObjects();
bool m_initialized;
static void CleanUp();
bool ProcessIdle();
+#if wxUSE_THREADS
+ void ProcessPendingEvents();
+#endif
void DeletePendingObjects();
bool m_initialized;
void DeletePendingObjects();
bool ProcessIdle();
+#if wxUSE_THREADS
+ void ProcessPendingEvents();
+#endif
// Motif-specific
inline WXAppContext GetAppContext() const { return m_appContext; }
virtual bool ProcessMessage(WXMSG* pMsg);
void DeletePendingObjects();
bool ProcessIdle();
+#if wxUSE_THREADS
+ void ProcessPendingEvents();
+#endif
int GetComCtl32Version() const;
public:
#endif // !USE_SHARED_LIBRARY
+#if wxUSE_THREADS
+/* To put pending event handlers */
+extern wxList wxPendingEvents;
+extern wxCriticalSection wxPendingEventsLocker;
+#endif
+
/*
* General wxWindows events, covering
* all interesting things that might happen (button clicking, resizing,
m_enabled = TRUE;
m_dynamicEvents = (wxList *) NULL;
m_isWindow = FALSE;
+#if wxUSE_THREADS
+ m_eventsLocker = new wxCriticalSection();
+#endif
+ m_pendingEvents = (wxList *) NULL;
}
wxEvtHandler::~wxEvtHandler()
}
delete m_dynamicEvents;
};
+
+ if (m_pendingEvents)
+ delete m_pendingEvents;
+
+#if wxUSE_THREADS
+ delete m_eventsLocker;
+#endif
}
+#if wxUSE_THREADS
+bool wxEvtHandler::ProcessThreadEvent(wxEvent& event)
+{
+ wxEvent *event_main;
+ wxCriticalSectionLocker locker(*m_eventsLocker);
+
+ // check that we are really in a child thread
+ wxASSERT( !wxThread::IsMain() );
+
+ if (m_pendingEvents == NULL)
+ m_pendingEvents = new wxList();
+
+ event_main = (wxEvent *)event.GetClassInfo()->CreateObject();
+ *event_main = event;
+
+ m_pendingEvents->Append(event_main);
+
+ wxPendingEventsLocker.Enter();
+ wxPendingEvents.Append(this);
+ wxPendingEventsLocker.Leave();
+
+ return TRUE;
+}
+
+void wxEvtHandler::ProcessPendingEvents()
+{
+ wxCriticalSectionLocker locker(*m_eventsLocker);
+ wxNode *node = m_pendingEvents->First();
+ wxEvent *event;
+
+ while (node != NULL) {
+ event = (wxEvent *)node->Data();
+ ProcessEvent(*event);
+ delete node;
+ node = m_pendingEvents->First();
+ }
+}
+#endif
+
/*
* Event table stuff
*/
// An event handler can be enabled or disabled
if ( GetEvtHandlerEnabled() )
{
+#if wxUSE_THREADS
+ // Check whether we are in a child thread.
+ if (!wxThread::IsMain())
+ return ProcessThreadEvent(event);
+#endif
// Handle per-instance dynamic event tables first
if ( m_dynamicEvents && SearchDynamicEventTable(event) )
wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL;
extern wxList wxPendingDelete;
+#if wxUSE_THREADS
+extern wxList wxPendingEvents;
+extern wxCriticalSection wxPendingEventsLocker;
+#endif
extern wxResourceCache *wxTheResourceCache;
unsigned char g_palette[64*3] =
inOnIdle = TRUE;
+ /* Resend in the main thread events which have been prepared in other
+ threads */
+ ProcessPendingEvents();
+
/* 'Garbage' collection of windows deleted with Close(). */
DeletePendingObjects();
{
}
+#if wxUSE_THREADS
+void wxApp::ProcessPendingEvents()
+{
+ wxNode *node = wxPendingEvents.First();
+ wxCriticalSectionLocker locker(wxPendingEventsLocker);
+
+ while (node)
+ {
+ wxEvtHandler *handler = (wxEvtHandler *)node->Data();
+
+ handler->ProcessPendingEvents();
+
+ delete node;
+
+ node = wxPendingEvents.First();
+ }
+}
+#endif
+
void wxApp::DeletePendingObjects()
{
wxNode *node = wxPendingDelete.First();
/* List of windows pending deletion */
wxList wxPendingDelete;
+#if wxUSE_THREADS
+/* List of events pending processing */
+wxList wxPendingEvents;
+wxCriticalSection wxPendingEventsLocker;
+#endif
+
/* Current cursor, in order to hang on to
* cursor handle when setting the cursor globally */
wxCursor *g_globalCursor = (wxCursor *) NULL;
wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL;
extern wxList wxPendingDelete;
+#if wxUSE_THREADS
+extern wxList wxPendingEvents;
+extern wxCriticalSection wxPendingEventsLocker;
+#endif
extern wxResourceCache *wxTheResourceCache;
unsigned char g_palette[64*3] =
inOnIdle = TRUE;
+ /* Resend in the main thread events which have been prepared in other
+ threads */
+ ProcessPendingEvents();
+
/* 'Garbage' collection of windows deleted with Close(). */
DeletePendingObjects();
{
}
+#if wxUSE_THREADS
+void wxApp::ProcessPendingEvents()
+{
+ wxNode *node = wxPendingEvents.First();
+ wxCriticalSectionLocker locker(wxPendingEventsLocker);
+
+ while (node)
+ {
+ wxEvtHandler *handler = (wxEvtHandler *)node->Data();
+
+ handler->ProcessPendingEvents();
+
+ delete node;
+
+ node = wxPendingEvents.First();
+ }
+}
+#endif
+
void wxApp::DeletePendingObjects()
{
wxNode *node = wxPendingDelete.First();
/* List of windows pending deletion */
wxList wxPendingDelete;
+#if wxUSE_THREADS
+/* List of events pending processing */
+wxList wxPendingEvents;
+wxCriticalSection wxPendingEventsLocker;
+#endif
+
/* Current cursor, in order to hang on to
* cursor handle when setting the cursor globally */
wxCursor *g_globalCursor = (wxCursor *) NULL;
extern char *wxBuffer;
extern wxList wxPendingDelete;
+#if wxUSE_THREADS
+extern wxList wxPendingEvents;
+extern wxList wxPendingEventsLocker;
+#endif
wxApp *wxTheApp = NULL;
// 'Garbage' collection of windows deleted with Close().
DeletePendingObjects();
+#if wxUSE_THREADS
+ // Flush pending events.
+ ProcessPendingEvents();
+#endif
+
// flush the logged messages if any
wxLog *pLog = wxLog::GetActiveTarget();
if ( pLog != NULL && pLog->HasPendingMessages() )
}
}
+#if wxUSE_THREADS
+void wxApp::ProcessPendingEvents()
+
+ wxNode *node = wxPendingEvents.First();
+ wxCriticalSectionLocker locker(wxPendingEventsLocker);
+
+ while (node)
+ {
+ wxEvtHandler *handler = (wxEvtHandler *)node->Data();
+
+ handler->ProcessPendingEvents();
+
+ delete node;
+ node = wxPendingEvents.First();
+ }
+
+#endif
+
wxLog* wxApp::CreateLogTarget()
{
return new wxLogGui;
// List of windows pending deletion
wxList wxPendingDelete;
+#if wxUSE_THREADS
+// List of events pending propagation
+wxList wxPendingEvents;
+wxCriticalSection wxPendingEventsLocker;
+#endif
+
int wxPageNumber;
// GDI Object Lists
extern char *wxOsVersion;
extern wxList *wxWinHandleList;
extern wxList WXDLLEXPORT wxPendingDelete;
+#if wxUSE_THREADS
+extern wxList wxPendingEvents;
+extern wxCriticalSection wxPendingEventsLocker;
+#endif
extern void wxSetKeyboardHook(bool doIt);
extern wxCursor *g_globalCursor;
{
}
+
DoMessage();
+
+ // If they are pending events, we must process them.
+#if wxUSE_THREADS
+ ProcessPendingEvents();
+#endif
}
return s_currentMsg.wParam;
return event.MoreRequested();
}
+#if wxUSE_THREADS
+void wxApp::ProcessPendingEvents()
+
+ wxNode *node = wxPendingEvents.First();
+ wxCriticalSectionLocker locker(wxPendingEventsLocker);
+
+ while (node)
+ {
+ wxEvtHandler *handler = (wxEvtHandler *)node->Data();
+
+ handler->ProcessPendingEvents();
+
+ delete node;
+ node = wxPendingEvents.First();
+ }
+}
+#endif
+
+
void wxApp::ExitMainLoop()
{
m_keepGoing = FALSE;
// List of windows pending deletion
wxList WXDLLEXPORT wxPendingDelete;
+// List of events pending processing
+#if wxUSE_THREADS
+wxList wxPendingEvents;
+wxCriticalSection wxPendingEventsLocker;
+#endif
+
// Current cursor, in order to hang on to
// cursor handle when setting the cursor globally
wxCursor *g_globalCursor = NULL;