check in the 'selective yield' patch (see ticket #10320):

- implements YieldFor() with event filtering for wxMSW and wxGTK,
  adds TODO markers in other ports;
- replaces wxYield() in GTK's clipboard code with a wxTheApp->YieldFor() call, thus fixing possible reentrancies 
(and modifies clipboard sample to test synchronous IsSupported calls)
- replaces wxYieldIfNeeded() calls in wxProgressDialog with wxTheApp->YieldFor() calls, so that it processes only 
UI/user-input events, thus fixing the race condition visible in the "thread" sample
- documents the new functions


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58654 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Francesco Montorsi
2009-02-04 17:42:28 +00:00
parent a721fd82b7
commit d48b06bd90
39 changed files with 777 additions and 111 deletions

View File

@@ -574,6 +574,9 @@ wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_COMMAND_TOOL_RCLICKED, wxComman
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED, wxCommandEvent)
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_COMMAND_TOOL_ENTER, wxCommandEvent)
// Thread events
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_COMMAND_THREAD, wxCommandEvent)
// Mouse event types
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_LEFT_DOWN, wxMouseEvent)
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_LEFT_UP, wxMouseEvent)
@@ -718,9 +721,14 @@ wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_DETAILED_HELP, wxHelpEvent)
// still, any new code using it should include wx/textctrl.h explicitly
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEvent)
// ----------------------------------------------------------------------------
// wxEvent(-derived) classes
// ----------------------------------------------------------------------------
// the predefined constants for the number of times we propagate event
// upwards window child-parent chain
enum Propagation_state
enum wxEventPropagation
{
// don't propagate it at all
wxEVENT_PROPAGATE_NONE = 0,
@@ -729,6 +737,58 @@ enum Propagation_state
wxEVENT_PROPAGATE_MAX = INT_MAX
};
// The different categories for a wxEvent; see wxEvent::GetEventCategory.
// NOTE: they are used as OR-combinable flags by wxApp::Yield
enum wxEventCategory
{
// this is the category for those events which are generated to update
// the appearance of the GUI but which (usually) do not comport data
// processing, i.e. which do not provide input or output data
// (e.g. size events, scroll events, etc).
// They are events NOT directly generated by the user's input devices.
wxEVT_CATEGORY_UI = 1,
// this category groups those events which are generated directly from the
// user through input devices like mouse and keyboard and usually result in
// data to be processed from the application.
// (e.g. mouse clicks, key presses, etc)
wxEVT_CATEGORY_USER_INPUT = 2,
// this category is for wxSocketEvent
wxEVT_CATEGORY_SOCKET = 4,
// this category is for wxTimerEvent
wxEVT_CATEGORY_TIMER = 8,
// this category is for any event used to send notifications from the
// secondary threads to the main one or in general for notifications among
// different threads (which may or may not be user-generated)
wxEVT_CATEGORY_THREAD = 16,
// implementation only
// used in the implementations of DoYield()
wxEVT_CATEGORY_UNKNOWN = 32,
// a special category used as an argument to wxApp::Yield() to indicate that
// Yield() should leave all wxEvents on the queue while emptying the native event queue
// (native events will be processed but the wxEvents they generate will be queued)
wxEVT_CATEGORY_CLIPBOARD = 64,
// shortcut masks
// this category groups those events which are emitted in response to
// events of the native toolkit and which typically are not-"delayable".
wxEVT_CATEGORY_NATIVE_EVENTS = wxEVT_CATEGORY_UI|wxEVT_CATEGORY_USER_INPUT,
// used in wxApp::Yield to specify all event categories should be processed:
wxEVT_CATEGORY_ALL =
wxEVT_CATEGORY_UI|wxEVT_CATEGORY_USER_INPUT|wxEVT_CATEGORY_SOCKET| \
wxEVT_CATEGORY_TIMER|wxEVT_CATEGORY_THREAD
};
/*
* wxWidgets events, covering all interesting things that might happen
* (button clicking, resizing, setting text in widgets, etc.).
@@ -748,10 +808,13 @@ public:
void SetEventType(wxEventType typ) { m_eventType = typ; }
wxEventType GetEventType() const { return m_eventType; }
wxObject *GetEventObject() const { return m_eventObject; }
void SetEventObject(wxObject *obj) { m_eventObject = obj; }
long GetTimestamp() const { return m_timeStamp; }
void SetTimestamp(long ts = 0) { m_timeStamp = ts; }
int GetId() const { return m_id; }
void SetId(int Id) { m_id = Id; }
@@ -767,6 +830,12 @@ public:
// for them wouldn't work (it needs to do a copy of the event)
virtual wxEvent *Clone() const = 0;
// this function is used to selectively process events in wxApp::YieldFor
// NOTE: by default it returns wxEVT_CATEGORY_UI just because the major
// part of wxWidgets events belong to that category.
virtual wxEventCategory GetEventCategory() const
{ return wxEVT_CATEGORY_UI; }
// Implementation only: this test is explicitly anti OO and this function
// exists only for optimization purposes.
bool IsCommandEvent() const { return m_isCommandEvent; }
@@ -818,9 +887,6 @@ public:
protected:
// the propagation level: while it is positive, we propagate the event to
// the parent window (if any)
//
// this one doesn't have to be public, we don't have to worry about
// backwards compatibility as it is new
int m_propagationLevel;
bool m_skipped;
@@ -956,6 +1022,7 @@ public:
int GetInt() const { return m_commandInt; }
virtual wxEvent *Clone() const { return new wxCommandEvent(*this); }
virtual wxEventCategory GetEventCategory() const { return wxEVT_CATEGORY_USER_INPUT; }
protected:
wxString m_cmdString; // String event argument
@@ -999,6 +1066,36 @@ private:
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxNotifyEvent)
};
// Thread event
class WXDLLIMPEXP_BASE wxThreadEvent : public wxCommandEvent
{
public:
wxThreadEvent(int id = wxID_ANY)
: wxCommandEvent(wxEVT_COMMAND_THREAD, id)
{ }
virtual wxEvent *Clone() const
{
// make sure our string member (which uses COW aka refcounting) is not
// shared by other string instances:
const_cast<wxThreadEvent*>(this)->SetString(GetString().c_str());
return new wxThreadEvent(*this);
}
// this is important to avoid that calling wxApp::Yield() thread events
// gets processed when this is unwanted:
virtual wxEventCategory GetEventCategory() const
{ return wxEVT_CATEGORY_THREAD; }
private:
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxThreadEvent)
};
// Scroll event class, derived form wxCommandEvent. wxScrollEvents are
// sent by wxSlider and wxScrollBar.
/*
@@ -1067,6 +1164,8 @@ private:
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxScrollWinEvent)
};
// Mouse event class
/*
@@ -1247,6 +1346,7 @@ public:
bool IsPageScroll() const { return ((unsigned int)m_linesPerAction == UINT_MAX); }
virtual wxEvent *Clone() const { return new wxMouseEvent(*this); }
virtual wxEventCategory GetEventCategory() const { return wxEVT_CATEGORY_USER_INPUT; }
wxMouseEvent& operator=(const wxMouseEvent& event)
{
@@ -1370,6 +1470,7 @@ public:
wxCoord GetY() const { return m_y; }
virtual wxEvent *Clone() const { return new wxKeyEvent(*this); }
virtual wxEventCategory GetEventCategory() const { return wxEVT_CATEGORY_USER_INPUT; }
// we do need to copy wxKeyEvent sometimes (in wxTreeCtrl code, for
// example)
@@ -2537,6 +2638,7 @@ private:
*/
// ============================================================================
// event handler and related classes
// ============================================================================
@@ -3217,6 +3319,8 @@ private:
DECLARE_DYNAMIC_CLASS_NO_COPY(wxEvtHandler)
};
WX_DEFINE_EXPORTED_ARRAY_PTR(wxEvtHandler*, wxEvtHandlerArray);
// ----------------------------------------------------------------------------
// wxEventConnectionRef represents all connections between two event handlers
// and enables automatic disconnect when an event handler sink goes out of
@@ -3322,6 +3426,7 @@ protected:
};
typedef void (wxEvtHandler::*wxCommandEventFunction)(wxCommandEvent&);
typedef void (wxEvtHandler::*wxThreadEventFunction)(wxThreadEvent&);
typedef void (wxEvtHandler::*wxScrollEventFunction)(wxScrollEvent&);
typedef void (wxEvtHandler::*wxScrollWinEventFunction)(wxScrollWinEvent&);
typedef void (wxEvtHandler::*wxSizeEventFunction)(wxSizeEvent&);
@@ -3361,6 +3466,8 @@ typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&
#define wxCommandEventHandler(func) \
wxEVENT_HANDLER_CAST(wxCommandEventFunction, func)
#define wxThreadEventHandler(func) \
wxEVENT_HANDLER_CAST(wxThreadEventFunction, func)
#define wxScrollEventHandler(func) \
wxEVENT_HANDLER_CAST(wxScrollEventFunction, func)
#define wxScrollWinEventHandler(func) \
@@ -3840,6 +3947,9 @@ typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&
#define EVT_TEXT_COPY(winid, func) wx__DECLARE_EVT1(wxEVT_COMMAND_TEXT_COPY, winid, wxClipboardTextEventHandler(func))
#define EVT_TEXT_PASTE(winid, func) wx__DECLARE_EVT1(wxEVT_COMMAND_TEXT_PASTE, winid, wxClipboardTextEventHandler(func))
// Thread events
#define EVT_THREAD(id, func) wx__DECLARE_EVT1(wxEVT_COMMAND_THREAD, id, wxThreadEventHandler(func))
// ----------------------------------------------------------------------------
// Global data
// ----------------------------------------------------------------------------
@@ -3848,10 +3958,16 @@ typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&
//
// notice that each event handler should occur at most once in this list
extern WXDLLIMPEXP_BASE wxList *wxHandlersWithPendingEvents;
extern WXDLLIMPEXP_BASE wxList *wxHandlersWithPendingDelayedEvents;
#if wxUSE_THREADS
// this critical section protectes both the lists above
extern WXDLLIMPEXP_BASE wxCriticalSection *wxHandlersWithPendingEventsLocker;
#endif
// old list names:
#define wxPendingEvents wxHandlersWithPendingEvents
#define wxPendingEventsLocker wxHandlersWithPendingEventsLocker
// ----------------------------------------------------------------------------
// Helper functions
// ----------------------------------------------------------------------------