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:
@@ -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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user