X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8cd6a9ad50c00a94e62558a3b55e814028d81100..1a9a6eed360bc9a263f2ea7c0d470953397de531:/include/wx/event.h diff --git a/include/wx/event.h b/include/wx/event.h index bbd046aada..9fc7828003 100644 --- a/include/wx/event.h +++ b/include/wx/event.h @@ -38,7 +38,24 @@ class WXDLLIMPEXP_FWD_BASE wxList; class WXDLLIMPEXP_FWD_CORE wxWindowBase; #endif // wxUSE_GUI -class WXDLLIMPEXP_FWD_BASE wxEvtHandler; +// We operate with pointer to members of wxEvtHandler (such functions are used +// as event handlers in the event tables or as arguments to Connect()) but by +// default MSVC uses a restricted (but more efficient) representation of +// pointers to members which can't deal with multiple base classes. To avoid +// mysterious (as the compiler is not good enough to detect this and give a +// sensible error message) errors in the user code as soon as it defines +// classes inheriting from both wxEvtHandler (possibly indirectly, e.g. via +// wxWindow) and something else (including our own wxTrackable but not limited +// to it), we use the special MSVC keyword telling the compiler to use a more +// general pointer to member representation for the classes inheriting from +// wxEvtHandler. +#ifdef __VISUALC__ + #define wxMSVC_FWD_MULTIPLE_BASES __multiple_inheritance +#else + #define wxMSVC_FWD_MULTIPLE_BASES +#endif + +class WXDLLIMPEXP_FWD_BASE wxMSVC_FWD_MULTIPLE_BASES wxEvtHandler; class wxEventConnectionRef; // ---------------------------------------------------------------------------- @@ -2098,10 +2115,16 @@ private: // event handler and related classes // ============================================================================ -// for backwards compatibility and to prevent eVC 4 for ARM from crashing with -// internal compiler error when compiling wx, we define wxObjectEventFunction -// as a wxObject method even though it can only be a wxEvtHandler one -typedef void (wxObject::*wxObjectEventFunction)(wxEvent&); +typedef void (wxEvtHandler::*wxEventFunction)(wxEvent&); + +// We had some trouble (specifically with eVC for ARM WinCE build) with using +// wxEventFunction in the past so we had introduced wxObjectEventFunction which +// used to be a typedef for a member of wxObject and not wxEvtHandler to work +// around this but as eVC is not really supported any longer we now only keep +// this for backwards compatibility and, despite its name, this is a typedef +// for wxEvtHandler member now -- but if we have the same problem with another +// compiler we can restore its old definition for it. +typedef wxEventFunction wxObjectEventFunction; // struct containing the members common to static and dynamic event tables // entries @@ -2260,9 +2283,7 @@ protected: // ---------------------------------------------------------------------------- class WXDLLIMPEXP_BASE wxEvtHandler : public wxObject -#if wxUSE_WEAKREF , public wxTrackable -#endif { public: wxEvtHandler(); @@ -2276,7 +2297,9 @@ public: void SetEvtHandlerEnabled(bool enabled) { m_enabled = enabled; } bool GetEvtHandlerEnabled() const { return m_enabled; } - // process an event right now + // Process an event right now: this can only be called from the main + // thread, use QueueEvent() for scheduling the events for + // processing from other threads. virtual bool ProcessEvent(wxEvent& event); // Process an event by calling ProcessEvent and handling any exceptions @@ -2285,8 +2308,25 @@ public: // wouldn't correctly propagate to wxEventLoop. bool SafelyProcessEvent(wxEvent& event); - // add an event to be processed later - virtual void AddPendingEvent(const wxEvent& event); + // Schedule the given event to be processed later. It takes ownership of + // the event pointer, i.e. it will be deleted later. This is safe to call + // from multiple threads although you still need to ensure that wxString + // fields of the event object are deep copies and not use the same string + // buffer as other wxString objects in this thread. + virtual void QueueEvent(wxEvent *event); + + // Add an event to be processed later: notice that this function is not + // safe to call from threads other than main, use QueueEvent() + virtual void AddPendingEvent(const wxEvent& event) + { + // notice that the thread-safety problem comes from the fact that + // Clone() doesn't make deep copies of wxString fields of wxEvent + // object and so the same wxString could be used from both threads when + // the event object is destroyed in this one -- QueueEvent() avoids + // this problem as the event pointer is not used any more in this + // thread at all after it is called. + QueueEvent(event.Clone()); + } void ProcessPendingEvents(); @@ -2362,9 +2402,7 @@ public: // Avoid problems at exit by cleaning up static hash table gracefully void ClearEventHashTable() { GetEventHashTable().Clear(); } -#if wxUSE_WEAKREF void OnSinkDestroyed( wxEvtHandler *sink ); -#endif private: static const wxEventTableEntry sm_eventTableEntries[]; @@ -2431,16 +2469,13 @@ protected: virtual void DoSetClientData( void *data ); virtual void *DoGetClientData() const; -#if wxUSE_WEAKREF // Search tracker objects for event connection with this sink wxEventConnectionRef *FindRefInTrackerList(wxEvtHandler *eventSink); -#endif private: DECLARE_DYNAMIC_CLASS_NO_COPY(wxEvtHandler) }; -#if wxUSE_WEAKREF // ---------------------------------------------------------------------------- // wxEventConnectionRef represents all connections between two event handlers // and enables automatic disconnect when an event handler sink goes out of @@ -2489,17 +2524,28 @@ private: DECLARE_NO_ASSIGN_CLASS(wxEventConnectionRef) }; -#endif // wxUSE_WEAKREF -// Post a message to the given eventhandler which will be processed during the -// next event loop iteration +// Post a message to the given event handler which will be processed during the +// next event loop iteration. +// +// Notice that this one is not thread-safe, use wxQueueEvent() inline void wxPostEvent(wxEvtHandler *dest, const wxEvent& event) { - wxCHECK_RET( dest, wxT("need an object to post event to in wxPostEvent") ); + wxCHECK_RET( dest, "need an object to post event to" ); dest->AddPendingEvent(event); } +// Wrapper around wxEvtHandler::QueueEvent(): adds an event for later +// processing, unlike wxPostEvent it is safe to use from different thread even +// for events with wxString members +inline void wxQueueEvent(wxEvtHandler *dest, wxEvent *event) +{ + wxCHECK_RET( dest, "need an object to queue event for" ); + + dest->QueueEvent(event); +} + typedef void (wxEvtHandler::*wxEventFunction)(wxEvent&); typedef void (wxEvtHandler::*wxIdleEventFunction)(wxIdleEvent&);