* Added threads event propagation. Should compile on GTK (tested).

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1986 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Guilhem Lavaux
1999-03-27 18:50:54 +00:00
parent eedcfe5eb9
commit 7214297d16
14 changed files with 223 additions and 5 deletions

View File

@@ -19,6 +19,9 @@
#include "wx/defs.h"
#include "wx/object.h"
#include "wx/gdicmn.h"
#if wxUSE_THREADS
#include "wx/thread.h"
#endif
/*
* Event types
@@ -347,7 +350,7 @@ public:
// 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); }
@@ -1170,6 +1173,10 @@ public:
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);
@@ -1196,10 +1203,14 @@ protected:
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

View File

@@ -115,6 +115,9 @@ class wxApp: public wxEvtHandler
static void CleanUp();
bool ProcessIdle();
#if wxUSE_THREADS
void ProcessPendingEvents();
#endif
void DeletePendingObjects();
bool m_initialized;

View File

@@ -115,6 +115,9 @@ class wxApp: public wxEvtHandler
static void CleanUp();
bool ProcessIdle();
#if wxUSE_THREADS
void ProcessPendingEvents();
#endif
void DeletePendingObjects();
bool m_initialized;

View File

@@ -141,6 +141,9 @@ public:
void DeletePendingObjects();
bool ProcessIdle();
#if wxUSE_THREADS
void ProcessPendingEvents();
#endif
// Motif-specific
inline WXAppContext GetAppContext() const { return m_appContext; }

View File

@@ -144,6 +144,9 @@ public:
virtual bool ProcessMessage(WXMSG* pMsg);
void DeletePendingObjects();
bool ProcessIdle();
#if wxUSE_THREADS
void ProcessPendingEvents();
#endif
int GetComCtl32Version() const;
public:

View File

@@ -78,6 +78,12 @@
#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,
@@ -283,6 +289,10 @@ wxEvtHandler::wxEvtHandler()
m_enabled = TRUE;
m_dynamicEvents = (wxList *) NULL;
m_isWindow = FALSE;
#if wxUSE_THREADS
m_eventsLocker = new wxCriticalSection();
#endif
m_pendingEvents = (wxList *) NULL;
}
wxEvtHandler::~wxEvtHandler()
@@ -306,8 +316,54 @@ 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
*/
@@ -320,6 +376,11 @@ bool wxEvtHandler::ProcessEvent(wxEvent& event)
// 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) )

View File

@@ -46,6 +46,10 @@ wxApp *wxTheApp = (wxApp *) 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] =
@@ -283,6 +287,10 @@ void wxApp::OnIdle( wxIdleEvent &event )
inOnIdle = TRUE;
/* Resend in the main thread events which have been prepared in other
threads */
ProcessPendingEvents();
/* 'Garbage' collection of windows deleted with Close(). */
DeletePendingObjects();
@@ -366,6 +374,25 @@ void wxApp::Dispatch()
{
}
#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();

View File

@@ -38,6 +38,12 @@ wxList wxTopLevelWindows;
/* 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;

View File

@@ -46,6 +46,10 @@ wxApp *wxTheApp = (wxApp *) 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] =
@@ -283,6 +287,10 @@ void wxApp::OnIdle( wxIdleEvent &event )
inOnIdle = TRUE;
/* Resend in the main thread events which have been prepared in other
threads */
ProcessPendingEvents();
/* 'Garbage' collection of windows deleted with Close(). */
DeletePendingObjects();
@@ -366,6 +374,25 @@ void wxApp::Dispatch()
{
}
#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();

View File

@@ -38,6 +38,12 @@ wxList wxTopLevelWindows;
/* 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;

View File

@@ -49,6 +49,10 @@
extern char *wxBuffer;
extern wxList wxPendingDelete;
#if wxUSE_THREADS
extern wxList wxPendingEvents;
extern wxList wxPendingEventsLocker;
#endif
wxApp *wxTheApp = NULL;
@@ -411,6 +415,11 @@ void wxApp::OnIdle(wxIdleEvent& event)
// '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() )
@@ -483,6 +492,24 @@ void wxApp::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
wxLog* wxApp::CreateLogTarget()
{
return new wxLogGui;

View File

@@ -27,6 +27,12 @@ wxList wxTopLevelWindows;
// 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

View File

@@ -92,6 +92,10 @@ extern char *wxBuffer;
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;
@@ -893,7 +897,13 @@ int wxApp::MainLoop()
{
}
DoMessage();
// If they are pending events, we must process them.
#if wxUSE_THREADS
ProcessPendingEvents();
#endif
}
return s_currentMsg.wParam;
@@ -909,6 +919,25 @@ bool wxApp::ProcessIdle()
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;

View File

@@ -37,6 +37,12 @@ wxList wxTopLevelWindows;
// 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;