X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7ce2fb71397346ceaba2ea49b73df72c3cdcafb4..c363ead1e206e599d6564ac939ac7342d165e0e3:/src/common/event.cpp?ds=sidebyside diff --git a/src/common/event.cpp b/src/common/event.cpp index 7b33c11e77..3a32fb3719 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -145,11 +145,11 @@ IMPLEMENT_DYNAMIC_CLASS(wxEventTableEntryModule, wxModule) // List containing event handlers with pending events (each handler can occur // at most once here) -wxList *wxPendingEvents = NULL; +wxList *wxHandlersWithPendingEvents = NULL; #if wxUSE_THREADS - // protects wxPendingEvents list - wxCriticalSection *wxPendingEventsLocker = NULL; + // protects wxHandlersWithPendingEvents list + wxCriticalSection *wxHandlersWithPendingEventsLocker = NULL; #endif // common event types are defined here, other event types are defined by the @@ -561,7 +561,10 @@ wxMouseEvent::wxMouseEvent(wxEventType commandType) void wxMouseEvent::Assign(const wxMouseEvent& event) { wxEvent::operator=(event); - wxMouseState::operator=(event); + + // Borland C++ 5.82 doesn't compile an explicit call to an implicitly + // defined operator=() so need to do it this way: + *static_cast(this) = event; m_x = event.m_x; m_y = event.m_y; @@ -1086,25 +1089,25 @@ wxEvtHandler::~wxEvtHandler() m_pendingEvents->DeleteContents(true); delete m_pendingEvents; - // Remove us from wxPendingEvents if necessary. - if ( wxPendingEvents ) + // Remove us from wxHandlersWithPendingEvents if necessary. + if ( wxHandlersWithPendingEvents ) { #if wxUSE_THREADS - if (wxPendingEventsLocker) - wxENTER_CRIT_SECT(*wxPendingEventsLocker); + if (wxHandlersWithPendingEventsLocker) + wxENTER_CRIT_SECT(*wxHandlersWithPendingEventsLocker); #endif - if ( wxPendingEvents->DeleteObject(this) ) + if ( wxHandlersWithPendingEvents->DeleteObject(this) ) { // check that we were present only once in the list - wxASSERT_MSG( !wxPendingEvents->Find(this), - "Handler occurs twice in wxPendingEvents list" ); + wxASSERT_MSG( !wxHandlersWithPendingEvents->Find(this), + "Handler occurs twice in wxHandlersWithPendingEvents list" ); } //else: we weren't in this list at all, it's ok #if wxUSE_THREADS - if (wxPendingEventsLocker) - wxLEAVE_CRIT_SECT(*wxPendingEventsLocker); + if (wxHandlersWithPendingEventsLocker) + wxLEAVE_CRIT_SECT(*wxHandlersWithPendingEventsLocker); #endif } @@ -1140,19 +1143,25 @@ void wxEvtHandler::QueueEvent(wxEvent *event) m_pendingEvents->Append(event); - wxLEAVE_CRIT_SECT( m_pendingEventsLock ); - // 2) Add this event handler to list of event handlers that // have pending events. - wxENTER_CRIT_SECT(*wxPendingEventsLocker); + wxENTER_CRIT_SECT(*wxHandlersWithPendingEventsLocker); - if ( !wxPendingEvents ) - wxPendingEvents = new wxList; - if ( !wxPendingEvents->Find(this) ) - wxPendingEvents->Append(this); + if ( !wxHandlersWithPendingEvents ) + wxHandlersWithPendingEvents = new wxList; + if ( !wxHandlersWithPendingEvents->Find(this) ) + wxHandlersWithPendingEvents->Append(this); - wxLEAVE_CRIT_SECT(*wxPendingEventsLocker); + wxLEAVE_CRIT_SECT(*wxHandlersWithPendingEventsLocker); + + // only release m_pendingEventsLock now because otherwise there is a race + // condition as described in the ticket #9093: we could process the event + // just added to m_pendingEvents in our ProcessPendingEvents() below before + // we had time to append this pointer to wxHandlersWithPendingEvents list; thus + // breaking the invariant that a handler should be in the list iff it has + // any pending events to process + wxLEAVE_CRIT_SECT( m_pendingEventsLock ); // 3) Inform the system that new pending events are somewhere, // and that these should be processed in idle time. @@ -1169,7 +1178,7 @@ void wxEvtHandler::ProcessPendingEvents() "should have pending events if called" ); wxList::compatibility_iterator node = m_pendingEvents->GetFirst(); - wxEventPtr event(wx_static_cast(wxEvent *, node->GetData())); + wxEventPtr event(static_cast(node->GetData())); // it's important we remove event from list before processing it, else a // nested event loop, for example from a modal dialog, might process the @@ -1181,13 +1190,13 @@ void wxEvtHandler::ProcessPendingEvents() if ( m_pendingEvents->IsEmpty() ) { #if wxUSE_THREADS - if (wxPendingEventsLocker) - wxENTER_CRIT_SECT(*wxPendingEventsLocker); + if (wxHandlersWithPendingEventsLocker) + wxENTER_CRIT_SECT(*wxHandlersWithPendingEventsLocker); #endif - wxPendingEvents->DeleteObject(this); + wxHandlersWithPendingEvents->DeleteObject(this); #if wxUSE_THREADS - if (wxPendingEventsLocker) - wxLEAVE_CRIT_SECT(*wxPendingEventsLocker); + if (wxHandlersWithPendingEventsLocker) + wxLEAVE_CRIT_SECT(*wxHandlersWithPendingEventsLocker); #endif } @@ -1289,7 +1298,7 @@ bool wxEvtHandler::ProcessEvent(wxEvent& event) return true; // propagate the event upwards the window chain and/or to the application - // object if it wasn't processed at this level + // object if it wasn't processed at this level return TryParent(event); } @@ -1374,7 +1383,7 @@ bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event) } void wxEvtHandler::Connect( int id, int lastId, - int eventType, + wxEventType eventType, wxObjectEventFunction func, wxObject *userData, wxEvtHandler* eventSink ) @@ -1395,7 +1404,7 @@ void wxEvtHandler::Connect( int id, int lastId, if ( evtConnRef ) evtConnRef->IncRef( ); else - evtConnRef = new wxEventConnectionRef(this, eventSink); + new wxEventConnectionRef(this, eventSink); } }