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:
@@ -32,6 +32,7 @@ class WXDLLIMPEXP_FWD_BASE wxMessageOutput;
|
|||||||
|
|
||||||
#if wxUSE_GUI
|
#if wxUSE_GUI
|
||||||
struct WXDLLIMPEXP_FWD_CORE wxVideoMode;
|
struct WXDLLIMPEXP_FWD_CORE wxVideoMode;
|
||||||
|
class WXDLLIMPEXP_FWD_CORE wxWindow;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -254,6 +255,13 @@ public:
|
|||||||
// (already) be dispatched
|
// (already) be dispatched
|
||||||
static bool IsMainLoopRunning();
|
static bool IsMainLoopRunning();
|
||||||
|
|
||||||
|
// temporary suspends processing of the pending events
|
||||||
|
virtual void SuspendProcessingOfPendingEvents();
|
||||||
|
|
||||||
|
// resume processing of the pending events previously stopped because of a
|
||||||
|
// call to SuspendProcessingOfPendingEvents()
|
||||||
|
virtual void ResumeProcessingOfPendingEvents();
|
||||||
|
|
||||||
// process all events in the wxHandlersWithPendingEvents list -- it is necessary
|
// process all events in the wxHandlersWithPendingEvents list -- it is necessary
|
||||||
// to call this function to process posted events. This happens during each
|
// to call this function to process posted events. This happens during each
|
||||||
// event loop iteration in GUI mode but if there is no main loop, it may be
|
// event loop iteration in GUI mode but if there is no main loop, it may be
|
||||||
@@ -263,9 +271,6 @@ public:
|
|||||||
// check if there are pending events on global pending event list
|
// check if there are pending events on global pending event list
|
||||||
bool HasPendingEvents() const;
|
bool HasPendingEvents() const;
|
||||||
|
|
||||||
// doesn't do anything in this class, just a hook for GUI wxApp
|
|
||||||
virtual bool Yield(bool WXUNUSED(onlyIfNeeded) = false) { return true; }
|
|
||||||
|
|
||||||
// make sure that idle events are sent again
|
// make sure that idle events are sent again
|
||||||
virtual void WakeUpIdle();
|
virtual void WakeUpIdle();
|
||||||
|
|
||||||
@@ -300,6 +305,30 @@ public:
|
|||||||
virtual bool OnExceptionInMainLoop();
|
virtual bool OnExceptionInMainLoop();
|
||||||
#endif // wxUSE_EXCEPTIONS
|
#endif // wxUSE_EXCEPTIONS
|
||||||
|
|
||||||
|
// Yield-related hooks
|
||||||
|
// -------------------
|
||||||
|
|
||||||
|
// process all currently pending events right now
|
||||||
|
//
|
||||||
|
// it is an error to call Yield() recursively unless the value of
|
||||||
|
// onlyIfNeeded is true
|
||||||
|
//
|
||||||
|
// WARNING: this function is dangerous as it can lead to unexpected
|
||||||
|
// reentrancies (i.e. when called from an event handler it
|
||||||
|
// may result in calling the same event handler again), use
|
||||||
|
// with _extreme_ care or, better, don't use at all!
|
||||||
|
// NOTE: in wxConsoleBase it doesn't do anything, just a hook for GUI wxApp
|
||||||
|
bool Yield(bool onlyIfNeeded = false)
|
||||||
|
{ return DoYield(onlyIfNeeded, wxEVT_CATEGORY_ALL); }
|
||||||
|
bool YieldFor(long eventsToProcess)
|
||||||
|
{ return DoYield(true, eventsToProcess); }
|
||||||
|
virtual bool IsYielding() const
|
||||||
|
{ return false; }
|
||||||
|
virtual bool IsEventAllowedInsideYield(wxEventCategory WXUNUSED(cat)) const
|
||||||
|
{ return true; }
|
||||||
|
// no SafeYield hooks since it uses wxWindow which is not available when wxUSE_GUI=0
|
||||||
|
|
||||||
|
|
||||||
// debugging support
|
// debugging support
|
||||||
// -----------------
|
// -----------------
|
||||||
|
|
||||||
@@ -366,6 +395,9 @@ protected:
|
|||||||
// for the first time
|
// for the first time
|
||||||
virtual wxAppTraits *CreateTraits();
|
virtual wxAppTraits *CreateTraits();
|
||||||
|
|
||||||
|
// the real yield function hook:
|
||||||
|
virtual bool DoYield(bool WXUNUSED(onlyIfNeeded), long WXUNUSED(eventsToProcess))
|
||||||
|
{ return true; }
|
||||||
|
|
||||||
// function used for dynamic wxApp creation
|
// function used for dynamic wxApp creation
|
||||||
static wxAppInitializerFunction ms_appInitFn;
|
static wxAppInitializerFunction ms_appInitFn;
|
||||||
@@ -392,6 +424,15 @@ protected:
|
|||||||
// been started yet or has already terminated)
|
// been started yet or has already terminated)
|
||||||
wxEventLoopBase *m_mainLoop;
|
wxEventLoopBase *m_mainLoop;
|
||||||
|
|
||||||
|
// the array of the handlers with pending events which needs to be processed
|
||||||
|
// inside ProcessPendingEvents()
|
||||||
|
// wxEvtHandlerArray m_handlersWithPendingEvents; FIXME: enable this and remove global lists
|
||||||
|
|
||||||
|
// helper array used by ProcessPendingEvents()
|
||||||
|
// wxEvtHandlerArray m_handlersWithPendingDelayedEvents; FIXME: enable this and remove global lists
|
||||||
|
|
||||||
|
friend class WXDLLIMPEXP_BASE wxEvtHandler;
|
||||||
|
|
||||||
// the application object is a singleton anyhow, there is no sense in
|
// the application object is a singleton anyhow, there is no sense in
|
||||||
// copying it
|
// copying it
|
||||||
DECLARE_NO_COPY_CLASS(wxAppConsoleBase)
|
DECLARE_NO_COPY_CLASS(wxAppConsoleBase)
|
||||||
@@ -451,23 +492,19 @@ public:
|
|||||||
// the worker functions - usually not used directly by the user code
|
// the worker functions - usually not used directly by the user code
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
|
// safer alternatives to Yield(), using wxWindowDisabler
|
||||||
|
virtual bool SafeYield(wxWindow *win, bool onlyIfNeeded);
|
||||||
// process all currently pending events right now
|
virtual bool SafeYieldFor(wxWindow *win, long eventsToProcess);
|
||||||
//
|
|
||||||
// it is an error to call Yield() recursively unless the value of
|
|
||||||
// onlyIfNeeded is true
|
|
||||||
//
|
|
||||||
// WARNING: this function is dangerous as it can lead to unexpected
|
|
||||||
// reentrancies (i.e. when called from an event handler it
|
|
||||||
// may result in calling the same event handler again), use
|
|
||||||
// with _extreme_ care or, better, don't use at all!
|
|
||||||
virtual bool Yield(bool onlyIfNeeded = false) = 0;
|
|
||||||
|
|
||||||
// returns true if the main thread is inside a Yield() call
|
// returns true if the main thread is inside a Yield() call
|
||||||
bool IsYielding() const
|
virtual bool IsYielding() const
|
||||||
{ return m_isInsideYield; }
|
{ return m_isInsideYield; }
|
||||||
|
|
||||||
|
// returns true if events of the given event category should be immediately
|
||||||
|
// processed inside a wxApp::Yield() call or rather should be queued for
|
||||||
|
// later processing by the main event loop
|
||||||
|
virtual bool IsEventAllowedInsideYield(wxEventCategory cat) const;
|
||||||
|
|
||||||
// this virtual function is called in the GUI mode when the application
|
// this virtual function is called in the GUI mode when the application
|
||||||
// becomes idle and normally just sends wxIdleEvent to all interested
|
// becomes idle and normally just sends wxIdleEvent to all interested
|
||||||
// parties
|
// parties
|
||||||
@@ -590,7 +627,9 @@ protected:
|
|||||||
// does any of our windows have focus?
|
// does any of our windows have focus?
|
||||||
bool m_isActive;
|
bool m_isActive;
|
||||||
|
|
||||||
|
// Yield() helpers:
|
||||||
bool m_isInsideYield;
|
bool m_isInsideYield;
|
||||||
|
long m_eventsToProcessInsideYield;
|
||||||
|
|
||||||
DECLARE_NO_COPY_CLASS(wxAppBase)
|
DECLARE_NO_COPY_CLASS(wxAppBase)
|
||||||
};
|
};
|
||||||
@@ -660,7 +699,7 @@ protected:
|
|||||||
// Force an exit from main loop
|
// Force an exit from main loop
|
||||||
WXDLLIMPEXP_BASE void wxExit();
|
WXDLLIMPEXP_BASE void wxExit();
|
||||||
|
|
||||||
// avoid redeclaring this function here if it had been already declated by
|
// avoid redeclaring this function here if it had been already declared by
|
||||||
// wx/utils.h, this results in warnings from g++ with -Wredundant-decls
|
// wx/utils.h, this results in warnings from g++ with -Wredundant-decls
|
||||||
#ifndef wx_YIELD_DECLARED
|
#ifndef wx_YIELD_DECLARED
|
||||||
#define wx_YIELD_DECLARED
|
#define wx_YIELD_DECLARED
|
||||||
|
@@ -57,7 +57,7 @@ public:
|
|||||||
// Implement wxAppBase pure virtuals
|
// Implement wxAppBase pure virtuals
|
||||||
virtual void Exit();
|
virtual void Exit();
|
||||||
|
|
||||||
virtual bool Yield(bool onlyIfNeeded = FALSE);
|
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||||
virtual void WakeUpIdle();
|
virtual void WakeUpIdle();
|
||||||
|
|
||||||
virtual bool Initialize(int& argc, wxChar **argv);
|
virtual bool Initialize(int& argc, wxChar **argv);
|
||||||
|
@@ -32,7 +32,6 @@ public:
|
|||||||
virtual void CleanUp();
|
virtual void CleanUp();
|
||||||
|
|
||||||
virtual void WakeUpIdle();
|
virtual void WakeUpIdle();
|
||||||
virtual bool Yield(bool onlyIfNeeded = false);
|
|
||||||
|
|
||||||
virtual wxVideoMode GetDisplayMode() const;
|
virtual wxVideoMode GetDisplayMode() const;
|
||||||
virtual bool SetDisplayMode(const wxVideoMode& mode);
|
virtual bool SetDisplayMode(const wxVideoMode& mode);
|
||||||
@@ -40,6 +39,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
wxVideoMode m_videoMode;
|
wxVideoMode m_videoMode;
|
||||||
|
|
||||||
|
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||||
|
|
||||||
DECLARE_DYNAMIC_CLASS(wxApp)
|
DECLARE_DYNAMIC_CLASS(wxApp)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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_DROPDOWN_CLICKED, wxCommandEvent)
|
||||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_COMMAND_TOOL_ENTER, 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
|
// Mouse event types
|
||||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_LEFT_DOWN, wxMouseEvent)
|
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_LEFT_DOWN, wxMouseEvent)
|
||||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_LEFT_UP, 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
|
// still, any new code using it should include wx/textctrl.h explicitly
|
||||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEvent)
|
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEvent)
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxEvent(-derived) classes
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
// the predefined constants for the number of times we propagate event
|
// the predefined constants for the number of times we propagate event
|
||||||
// upwards window child-parent chain
|
// upwards window child-parent chain
|
||||||
enum Propagation_state
|
enum wxEventPropagation
|
||||||
{
|
{
|
||||||
// don't propagate it at all
|
// don't propagate it at all
|
||||||
wxEVENT_PROPAGATE_NONE = 0,
|
wxEVENT_PROPAGATE_NONE = 0,
|
||||||
@@ -729,6 +737,58 @@ enum Propagation_state
|
|||||||
wxEVENT_PROPAGATE_MAX = INT_MAX
|
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
|
* wxWidgets events, covering all interesting things that might happen
|
||||||
* (button clicking, resizing, setting text in widgets, etc.).
|
* (button clicking, resizing, setting text in widgets, etc.).
|
||||||
@@ -748,10 +808,13 @@ public:
|
|||||||
|
|
||||||
void SetEventType(wxEventType typ) { m_eventType = typ; }
|
void SetEventType(wxEventType typ) { m_eventType = typ; }
|
||||||
wxEventType GetEventType() const { return m_eventType; }
|
wxEventType GetEventType() const { return m_eventType; }
|
||||||
|
|
||||||
wxObject *GetEventObject() const { return m_eventObject; }
|
wxObject *GetEventObject() const { return m_eventObject; }
|
||||||
void SetEventObject(wxObject *obj) { m_eventObject = obj; }
|
void SetEventObject(wxObject *obj) { m_eventObject = obj; }
|
||||||
|
|
||||||
long GetTimestamp() const { return m_timeStamp; }
|
long GetTimestamp() const { return m_timeStamp; }
|
||||||
void SetTimestamp(long ts = 0) { m_timeStamp = ts; }
|
void SetTimestamp(long ts = 0) { m_timeStamp = ts; }
|
||||||
|
|
||||||
int GetId() const { return m_id; }
|
int GetId() const { return m_id; }
|
||||||
void SetId(int Id) { m_id = 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)
|
// for them wouldn't work (it needs to do a copy of the event)
|
||||||
virtual wxEvent *Clone() const = 0;
|
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
|
// Implementation only: this test is explicitly anti OO and this function
|
||||||
// exists only for optimization purposes.
|
// exists only for optimization purposes.
|
||||||
bool IsCommandEvent() const { return m_isCommandEvent; }
|
bool IsCommandEvent() const { return m_isCommandEvent; }
|
||||||
@@ -818,9 +887,6 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
// the propagation level: while it is positive, we propagate the event to
|
// the propagation level: while it is positive, we propagate the event to
|
||||||
// the parent window (if any)
|
// 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;
|
int m_propagationLevel;
|
||||||
|
|
||||||
bool m_skipped;
|
bool m_skipped;
|
||||||
@@ -956,6 +1022,7 @@ public:
|
|||||||
int GetInt() const { return m_commandInt; }
|
int GetInt() const { return m_commandInt; }
|
||||||
|
|
||||||
virtual wxEvent *Clone() const { return new wxCommandEvent(*this); }
|
virtual wxEvent *Clone() const { return new wxCommandEvent(*this); }
|
||||||
|
virtual wxEventCategory GetEventCategory() const { return wxEVT_CATEGORY_USER_INPUT; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
wxString m_cmdString; // String event argument
|
wxString m_cmdString; // String event argument
|
||||||
@@ -999,6 +1066,36 @@ private:
|
|||||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxNotifyEvent)
|
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
|
// Scroll event class, derived form wxCommandEvent. wxScrollEvents are
|
||||||
// sent by wxSlider and wxScrollBar.
|
// sent by wxSlider and wxScrollBar.
|
||||||
/*
|
/*
|
||||||
@@ -1067,6 +1164,8 @@ private:
|
|||||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxScrollWinEvent)
|
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxScrollWinEvent)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Mouse event class
|
// Mouse event class
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1247,6 +1346,7 @@ public:
|
|||||||
bool IsPageScroll() const { return ((unsigned int)m_linesPerAction == UINT_MAX); }
|
bool IsPageScroll() const { return ((unsigned int)m_linesPerAction == UINT_MAX); }
|
||||||
|
|
||||||
virtual wxEvent *Clone() const { return new wxMouseEvent(*this); }
|
virtual wxEvent *Clone() const { return new wxMouseEvent(*this); }
|
||||||
|
virtual wxEventCategory GetEventCategory() const { return wxEVT_CATEGORY_USER_INPUT; }
|
||||||
|
|
||||||
wxMouseEvent& operator=(const wxMouseEvent& event)
|
wxMouseEvent& operator=(const wxMouseEvent& event)
|
||||||
{
|
{
|
||||||
@@ -1370,6 +1470,7 @@ public:
|
|||||||
wxCoord GetY() const { return m_y; }
|
wxCoord GetY() const { return m_y; }
|
||||||
|
|
||||||
virtual wxEvent *Clone() const { return new wxKeyEvent(*this); }
|
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
|
// we do need to copy wxKeyEvent sometimes (in wxTreeCtrl code, for
|
||||||
// example)
|
// example)
|
||||||
@@ -2537,6 +2638,7 @@ private:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// event handler and related classes
|
// event handler and related classes
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -3217,6 +3319,8 @@ private:
|
|||||||
DECLARE_DYNAMIC_CLASS_NO_COPY(wxEvtHandler)
|
DECLARE_DYNAMIC_CLASS_NO_COPY(wxEvtHandler)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
WX_DEFINE_EXPORTED_ARRAY_PTR(wxEvtHandler*, wxEvtHandlerArray);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxEventConnectionRef represents all connections between two event handlers
|
// wxEventConnectionRef represents all connections between two event handlers
|
||||||
// and enables automatic disconnect when an event handler sink goes out of
|
// 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::*wxCommandEventFunction)(wxCommandEvent&);
|
||||||
|
typedef void (wxEvtHandler::*wxThreadEventFunction)(wxThreadEvent&);
|
||||||
typedef void (wxEvtHandler::*wxScrollEventFunction)(wxScrollEvent&);
|
typedef void (wxEvtHandler::*wxScrollEventFunction)(wxScrollEvent&);
|
||||||
typedef void (wxEvtHandler::*wxScrollWinEventFunction)(wxScrollWinEvent&);
|
typedef void (wxEvtHandler::*wxScrollWinEventFunction)(wxScrollWinEvent&);
|
||||||
typedef void (wxEvtHandler::*wxSizeEventFunction)(wxSizeEvent&);
|
typedef void (wxEvtHandler::*wxSizeEventFunction)(wxSizeEvent&);
|
||||||
@@ -3361,6 +3466,8 @@ typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&
|
|||||||
|
|
||||||
#define wxCommandEventHandler(func) \
|
#define wxCommandEventHandler(func) \
|
||||||
wxEVENT_HANDLER_CAST(wxCommandEventFunction, func)
|
wxEVENT_HANDLER_CAST(wxCommandEventFunction, func)
|
||||||
|
#define wxThreadEventHandler(func) \
|
||||||
|
wxEVENT_HANDLER_CAST(wxThreadEventFunction, func)
|
||||||
#define wxScrollEventHandler(func) \
|
#define wxScrollEventHandler(func) \
|
||||||
wxEVENT_HANDLER_CAST(wxScrollEventFunction, func)
|
wxEVENT_HANDLER_CAST(wxScrollEventFunction, func)
|
||||||
#define wxScrollWinEventHandler(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_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))
|
#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
|
// Global data
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -3848,10 +3958,16 @@ typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&
|
|||||||
//
|
//
|
||||||
// notice that each event handler should occur at most once in this list
|
// notice that each event handler should occur at most once in this list
|
||||||
extern WXDLLIMPEXP_BASE wxList *wxHandlersWithPendingEvents;
|
extern WXDLLIMPEXP_BASE wxList *wxHandlersWithPendingEvents;
|
||||||
|
extern WXDLLIMPEXP_BASE wxList *wxHandlersWithPendingDelayedEvents;
|
||||||
#if wxUSE_THREADS
|
#if wxUSE_THREADS
|
||||||
|
// this critical section protectes both the lists above
|
||||||
extern WXDLLIMPEXP_BASE wxCriticalSection *wxHandlersWithPendingEventsLocker;
|
extern WXDLLIMPEXP_BASE wxCriticalSection *wxHandlersWithPendingEventsLocker;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// old list names:
|
||||||
|
#define wxPendingEvents wxHandlersWithPendingEvents
|
||||||
|
#define wxPendingEventsLocker wxHandlersWithPendingEventsLocker
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Helper functions
|
// Helper functions
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// Name: wx/gtk/app.h
|
// Name: wx/gtk/app.h
|
||||||
// Purpose:
|
// Purpose: wxApp definition for wxGTK
|
||||||
// Author: Robert Roebling
|
// Author: Robert Roebling
|
||||||
// Id: $Id$
|
// Id: $Id$
|
||||||
// Copyright: (c) 1998 Robert Roebling, Julian Smart
|
// Copyright: (c) 1998 Robert Roebling, Julian Smart
|
||||||
@@ -40,7 +40,6 @@ public:
|
|||||||
virtual bool OnInitGui();
|
virtual bool OnInitGui();
|
||||||
|
|
||||||
// override base class (pure) virtuals
|
// override base class (pure) virtuals
|
||||||
virtual bool Yield(bool onlyIfNeeded = FALSE);
|
|
||||||
virtual void WakeUpIdle();
|
virtual void WakeUpIdle();
|
||||||
|
|
||||||
virtual bool Initialize(int& argc, wxChar **argv);
|
virtual bool Initialize(int& argc, wxChar **argv);
|
||||||
@@ -79,6 +78,10 @@ public:
|
|||||||
bool EventsPending();
|
bool EventsPending();
|
||||||
bool DoIdle();
|
bool DoIdle();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// true if we're inside an assert modal dialog
|
// true if we're inside an assert modal dialog
|
||||||
#ifdef __WXDEBUG__
|
#ifdef __WXDEBUG__
|
||||||
|
@@ -38,7 +38,6 @@ public:
|
|||||||
virtual bool OnInitGui();
|
virtual bool OnInitGui();
|
||||||
|
|
||||||
// override base class (pure) virtuals
|
// override base class (pure) virtuals
|
||||||
virtual bool Yield(bool onlyIfNeeded = FALSE);
|
|
||||||
virtual void WakeUpIdle();
|
virtual void WakeUpIdle();
|
||||||
|
|
||||||
virtual bool Initialize(int& argc, wxChar **argv);
|
virtual bool Initialize(int& argc, wxChar **argv);
|
||||||
@@ -71,6 +70,8 @@ private:
|
|||||||
bool m_isInAssert;
|
bool m_isInAssert;
|
||||||
#endif // __WXDEBUG__
|
#endif // __WXDEBUG__
|
||||||
|
|
||||||
|
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||||
|
|
||||||
DECLARE_DYNAMIC_CLASS(wxApp)
|
DECLARE_DYNAMIC_CLASS(wxApp)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1277,4 +1277,15 @@ public:
|
|||||||
(list).clear(); \
|
(list).clear(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// append all element of one list to another one
|
||||||
|
#define WX_APPEND_LIST(list, other) \
|
||||||
|
{ \
|
||||||
|
wxList::compatibility_iterator node = other->GetFirst(); \
|
||||||
|
while ( node ) \
|
||||||
|
{ \
|
||||||
|
(list)->push_back(node->GetData()); \
|
||||||
|
node = node->GetNext(); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
#endif // _WX_LISTH__
|
#endif // _WX_LISTH__
|
||||||
|
@@ -44,7 +44,6 @@ public:
|
|||||||
|
|
||||||
virtual void Exit();
|
virtual void Exit();
|
||||||
virtual void WakeUpIdle();
|
virtual void WakeUpIdle();
|
||||||
virtual bool Yield(bool onlyIfNeeded = FALSE);
|
|
||||||
|
|
||||||
virtual wxVideoMode GetDisplayMode() const { return m_displayMode; }
|
virtual wxVideoMode GetDisplayMode() const { return m_displayMode; }
|
||||||
virtual bool SetDisplayMode(const wxVideoMode& mode);
|
virtual bool SetDisplayMode(const wxVideoMode& mode);
|
||||||
@@ -52,6 +51,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
DECLARE_DYNAMIC_CLASS(wxApp)
|
DECLARE_DYNAMIC_CLASS(wxApp)
|
||||||
|
|
||||||
|
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||||
|
|
||||||
wxVideoMode m_displayMode;
|
wxVideoMode m_displayMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -53,7 +53,6 @@ public:
|
|||||||
|
|
||||||
virtual void Exit();
|
virtual void Exit();
|
||||||
|
|
||||||
virtual bool Yield(bool onlyIfNeeded = false);
|
|
||||||
virtual void WakeUpIdle(); // implemented in motif/evtloop.cpp
|
virtual void WakeUpIdle(); // implemented in motif/evtloop.cpp
|
||||||
|
|
||||||
// implementation from now on
|
// implementation from now on
|
||||||
@@ -66,6 +65,7 @@ public:
|
|||||||
// Implementation
|
// Implementation
|
||||||
virtual bool Initialize(int& argc, wxChar **argv);
|
virtual bool Initialize(int& argc, wxChar **argv);
|
||||||
virtual void CleanUp();
|
virtual void CleanUp();
|
||||||
|
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||||
|
|
||||||
// Motif-specific
|
// Motif-specific
|
||||||
WXAppContext GetAppContext() const { return m_appContext; }
|
WXAppContext GetAppContext() const { return m_appContext; }
|
||||||
|
@@ -33,7 +33,6 @@ public:
|
|||||||
virtual bool Initialize(int& argc, wxChar **argv);
|
virtual bool Initialize(int& argc, wxChar **argv);
|
||||||
virtual void CleanUp();
|
virtual void CleanUp();
|
||||||
|
|
||||||
virtual bool Yield(bool onlyIfNeeded = false);
|
|
||||||
virtual void WakeUpIdle();
|
virtual void WakeUpIdle();
|
||||||
|
|
||||||
virtual void SetPrintMode(int mode) { m_printMode = mode; }
|
virtual void SetPrintMode(int mode) { m_printMode = mode; }
|
||||||
@@ -79,6 +78,8 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
int m_printMode; // wxPRINT_WINDOWS, wxPRINT_POSTSCRIPT
|
int m_printMode; // wxPRINT_WINDOWS, wxPRINT_POSTSCRIPT
|
||||||
|
|
||||||
|
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// unregister any window classes registered by GetRegisteredClassName()
|
// unregister any window classes registered by GetRegisteredClassName()
|
||||||
static void UnregisterWindowClasses();
|
static void UnregisterWindowClasses();
|
||||||
|
@@ -75,7 +75,6 @@ public:
|
|||||||
|
|
||||||
virtual bool OnInitGui(void);
|
virtual bool OnInitGui(void);
|
||||||
|
|
||||||
virtual bool Yield(bool onlyIfNeeded = false);
|
|
||||||
virtual void WakeUpIdle(void);
|
virtual void WakeUpIdle(void);
|
||||||
|
|
||||||
virtual void SetPrintMode(int mode) { m_nPrintMode = mode; }
|
virtual void SetPrintMode(int mode) { m_nPrintMode = mode; }
|
||||||
@@ -111,6 +110,8 @@ public:
|
|||||||
// Implementation
|
// Implementation
|
||||||
static bool RegisterWindowClasses(HAB vHab);
|
static bool RegisterWindowClasses(HAB vHab);
|
||||||
|
|
||||||
|
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int m_nCmdShow;
|
int m_nCmdShow;
|
||||||
HMQ m_hMq;
|
HMQ m_hMq;
|
||||||
|
@@ -38,7 +38,6 @@ class WXDLLIMPEXP_CORE wxApp: public wxAppBase
|
|||||||
wxApp();
|
wxApp();
|
||||||
virtual ~wxApp() {}
|
virtual ~wxApp() {}
|
||||||
|
|
||||||
virtual bool Yield(bool onlyIfNeeded = FALSE);
|
|
||||||
virtual void WakeUpIdle();
|
virtual void WakeUpIdle();
|
||||||
|
|
||||||
virtual void SetPrintMode(int mode) { m_printMode = mode; }
|
virtual void SetPrintMode(int mode) { m_printMode = mode; }
|
||||||
@@ -67,6 +66,7 @@ public:
|
|||||||
// Implementation
|
// Implementation
|
||||||
virtual bool Initialize(int& argc, wxChar **argv);
|
virtual bool Initialize(int& argc, wxChar **argv);
|
||||||
virtual void CleanUp();
|
virtual void CleanUp();
|
||||||
|
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||||
|
|
||||||
// the installed application event handler
|
// the installed application event handler
|
||||||
WXEVENTHANDLERREF MacGetEventHandler() { return m_macEventHandler ; }
|
WXEVENTHANDLERREF MacGetEventHandler() { return m_macEventHandler ; }
|
||||||
|
@@ -35,7 +35,6 @@ public:
|
|||||||
virtual bool Initialize(int& argc, wxChar **argv);
|
virtual bool Initialize(int& argc, wxChar **argv);
|
||||||
virtual void CleanUp();
|
virtual void CleanUp();
|
||||||
|
|
||||||
virtual bool Yield(bool onlyIfNeeded = false);
|
|
||||||
virtual void WakeUpIdle();
|
virtual void WakeUpIdle();
|
||||||
|
|
||||||
virtual void SetPrintMode(int mode) { m_printMode = mode; }
|
virtual void SetPrintMode(int mode) { m_printMode = mode; }
|
||||||
@@ -52,6 +51,8 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
int m_printMode; // wxPRINT_WINDOWS, wxPRINT_POSTSCRIPT
|
int m_printMode; // wxPRINT_WINDOWS, wxPRINT_POSTSCRIPT
|
||||||
|
|
||||||
|
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Implementation
|
// Implementation
|
||||||
static bool RegisterWindowClasses();
|
static bool RegisterWindowClasses();
|
||||||
|
@@ -382,6 +382,7 @@ public:
|
|||||||
void *GetClientData() const { return m_clientData; }
|
void *GetClientData() const { return m_clientData; }
|
||||||
|
|
||||||
virtual wxEvent *Clone() const { return new wxSocketEvent(*this); }
|
virtual wxEvent *Clone() const { return new wxSocketEvent(*this); }
|
||||||
|
virtual wxEventCategory GetEventCategory() const { return wxEVT_CATEGORY_SOCKET; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wxSocketNotify m_event;
|
wxSocketNotify m_event;
|
||||||
|
@@ -172,6 +172,7 @@ public:
|
|||||||
|
|
||||||
// implement the base class pure virtual
|
// implement the base class pure virtual
|
||||||
virtual wxEvent *Clone() const { return new wxTimerEvent(*this); }
|
virtual wxEvent *Clone() const { return new wxTimerEvent(*this); }
|
||||||
|
virtual wxEventCategory GetEventCategory() const { return wxEVT_CATEGORY_TIMER; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxTimer* m_timer;
|
wxTimer* m_timer;
|
||||||
|
@@ -45,7 +45,6 @@ public:
|
|||||||
|
|
||||||
virtual void Exit();
|
virtual void Exit();
|
||||||
|
|
||||||
virtual bool Yield(bool onlyIfNeeded = FALSE);
|
|
||||||
virtual void WakeUpIdle();
|
virtual void WakeUpIdle();
|
||||||
|
|
||||||
virtual bool OnInitGui();
|
virtual bool OnInitGui();
|
||||||
@@ -64,6 +63,7 @@ public:
|
|||||||
// Implementation
|
// Implementation
|
||||||
virtual bool Initialize(int& argc, wxChar **argv);
|
virtual bool Initialize(int& argc, wxChar **argv);
|
||||||
virtual void CleanUp();
|
virtual void CleanUp();
|
||||||
|
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||||
|
|
||||||
WXWindow GetTopLevelWidget() const { return m_topLevelWidget; }
|
WXWindow GetTopLevelWidget() const { return m_topLevelWidget; }
|
||||||
WXColormap GetMainColormap(WXDisplay* display);
|
WXColormap GetMainColormap(WXDisplay* display);
|
||||||
|
@@ -162,7 +162,26 @@ public:
|
|||||||
@a onlyIfNeeded parameter is @true, the method will just silently
|
@a onlyIfNeeded parameter is @true, the method will just silently
|
||||||
return @false instead.
|
return @false instead.
|
||||||
*/
|
*/
|
||||||
virtual bool Yield(bool onlyIfNeeded = false);
|
bool Yield(bool onlyIfNeeded = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Works like Yield() with @e onlyIfNeeded == @true, except that it allows
|
||||||
|
the caller to specify a mask of the ::wxEventCategory values which
|
||||||
|
indicates which events should be processed and which should instead
|
||||||
|
be "delayed" (i.e. processed by the main loop later).
|
||||||
|
|
||||||
|
Note that this is a safer alternative to Yield() since it ensures that
|
||||||
|
only the events you're interested to are processed; i.e. helps to avoid
|
||||||
|
unwanted reentrancies.
|
||||||
|
*/
|
||||||
|
bool YieldFor(long eventsToProcess);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns @true if the given event category is allowed inside
|
||||||
|
a YieldFor() call (i.e. compares the given category against the
|
||||||
|
last mask passed to YieldFor()).
|
||||||
|
*/
|
||||||
|
virtual bool IsEventAllowedInsideYield(wxEventCategory cat) const;
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
@@ -180,7 +199,7 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the one and only global application object.
|
Returns the one and only global application object.
|
||||||
Usually wxTheApp is used instead.
|
Usually ::wxTheApp is used instead.
|
||||||
|
|
||||||
@see SetInstance()
|
@see SetInstance()
|
||||||
*/
|
*/
|
||||||
@@ -621,6 +640,25 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual bool IsActive() const;
|
virtual bool IsActive() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function is similar to wxYield(), except that it disables the user
|
||||||
|
input to all program windows before calling wxAppConsole::Yield and re-enables it
|
||||||
|
again afterwards. If @a win is not @NULL, this window will remain enabled,
|
||||||
|
allowing the implementation of some limited user interaction.
|
||||||
|
Returns the result of the call to wxAppConsole::Yield.
|
||||||
|
|
||||||
|
@see wxSafeYield
|
||||||
|
*/
|
||||||
|
virtual bool SafeYield(wxWindow *win, bool onlyIfNeeded);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Works like SafeYield() with @e onlyIfNeeded == @true except that
|
||||||
|
it allows the caller to specify a mask of events to be processed.
|
||||||
|
|
||||||
|
See wxAppConsole::YieldFor for more info.
|
||||||
|
*/
|
||||||
|
virtual bool SafeYieldFor(wxWindow *win, long eventsToProcess);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Windows-only function for processing a message. This function is called
|
Windows-only function for processing a message. This function is called
|
||||||
from the main message loop, checking for windows that may wish to process it.
|
from the main message loop, checking for windows that may wish to process it.
|
||||||
@@ -857,22 +895,18 @@ void wxUninitialize();
|
|||||||
void wxWakeUpIdle();
|
void wxWakeUpIdle();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Calls wxApp::Yield.
|
Calls wxAppConsole::Yield.
|
||||||
|
|
||||||
@deprecated
|
@deprecated
|
||||||
This function is kept only for backwards compatibility. Please use
|
This function is kept only for backwards compatibility. Please use
|
||||||
the wxApp::Yield method instead in any new code.
|
the wxAppConsole::Yield method instead in any new code.
|
||||||
|
|
||||||
@header{wx/app.h}
|
@header{wx/app.h}
|
||||||
*/
|
*/
|
||||||
bool wxYield();
|
bool wxYield();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This function is similar to wxYield(), except that it disables the user
|
Calls wxApp::SafeYield.
|
||||||
input to all program windows before calling wxYield() and re-enables it
|
|
||||||
again afterwards. If @a win is not @NULL, this window will remain enabled,
|
|
||||||
allowing the implementation of some limited user interaction.
|
|
||||||
Returns the result of the call to ::wxYield.
|
|
||||||
|
|
||||||
@header{wx/app.h}
|
@header{wx/app.h}
|
||||||
*/
|
*/
|
||||||
|
@@ -7,6 +7,64 @@
|
|||||||
// Licence: wxWindows license
|
// Licence: wxWindows license
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
The predefined constants for the number of times we propagate event
|
||||||
|
upwards window child-parent chain.
|
||||||
|
*/
|
||||||
|
enum wxEventPropagation
|
||||||
|
{
|
||||||
|
/// don't propagate it at all
|
||||||
|
wxEVENT_PROPAGATE_NONE = 0,
|
||||||
|
|
||||||
|
/// propagate it until it is processed
|
||||||
|
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,
|
||||||
|
|
||||||
|
/**
|
||||||
|
This mask is used in wxApp::Yield to specify that 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
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@class wxEvent
|
@class wxEvent
|
||||||
@@ -87,6 +145,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
wxEventType GetEventType() const;
|
wxEventType GetEventType() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns a generic category for this event.
|
||||||
|
|
||||||
|
This function is used to selectively process events in wxApp::Yield.
|
||||||
|
*/
|
||||||
|
virtual wxEventCategory GetEventCategory() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the identifier associated with this event, such as a button command id.
|
Returns the identifier associated with this event, such as a button command id.
|
||||||
*/
|
*/
|
||||||
@@ -2463,18 +2528,45 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@class wxThreadEvent
|
||||||
|
|
||||||
|
This class adds some simple functionalities to wxCommandEvent coinceived
|
||||||
|
for inter-threads communications.
|
||||||
|
|
||||||
enum wxHelpEventOrigin
|
@library{wxcore}
|
||||||
|
@category{events}
|
||||||
|
|
||||||
|
@see @ref overview_thread, wxApp::YieldFor
|
||||||
|
*/
|
||||||
|
class wxThreadEvent : public wxCommandEvent
|
||||||
{
|
{
|
||||||
wxHE_ORIGIN_UNKNOWN = -1,
|
public:
|
||||||
wxHE_ORIGIN_KEYBOARD,
|
/**
|
||||||
|
Constructor.
|
||||||
|
|
||||||
/** event generated by wxContextHelp or from the [?] button on
|
Initializes the event type to @c wxEVT_THREAD (but you can change it
|
||||||
the title bar (Windows). */
|
using wxEvent::SetEventType.
|
||||||
wxHE_ORIGIN_HELPBUTTON
|
*/
|
||||||
|
wxThreadEvent(int id = wxID_ANY);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Clones this event making sure that all internal members which use
|
||||||
|
COW (only @c m_commandString for now; see @ref overview_refcount)
|
||||||
|
are unshared (see wxObject::UnShare).
|
||||||
|
*/
|
||||||
|
virtual wxEvent *Clone() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns @c wxEVT_CATEGORY_THREAD.
|
||||||
|
|
||||||
|
This is important to avoid that calling wxApp::Yield() thread events
|
||||||
|
gets processed when this is unwanted:
|
||||||
|
*/
|
||||||
|
virtual wxEventCategory GetEventCategory() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@class wxHelpEvent
|
@class wxHelpEvent
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// Name: clipboard.cpp
|
// Name: clipboard.cpp
|
||||||
// Purpose: clipbaord wxWidgets sample
|
// Purpose: clipboard wxWidgets sample
|
||||||
// Author: Robert Roebling
|
// Author: Robert Roebling
|
||||||
// RCS-ID: $Id: minimal.cpp 53461 2008-05-05 23:30:33Z VZ $
|
// RCS-ID: $Id: minimal.cpp 53461 2008-05-05 23:30:33Z VZ $
|
||||||
// Copyright: (c) Robert Roebling
|
// Copyright: (c) Robert Roebling
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define USE_ASYNCHRONOUS_CLIPBOARD_REQUEST 1
|
#define USE_ASYNCHRONOUS_CLIPBOARD_REQUEST 0
|
||||||
|
|
||||||
class MyApp : public wxApp
|
class MyApp : public wxApp
|
||||||
{
|
{
|
||||||
@@ -198,6 +198,7 @@ void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
|
|||||||
|
|
||||||
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
|
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
|
||||||
{
|
{
|
||||||
|
wxMessageBox("Clipboard sample", "About clipboard", wxOK|wxICON_INFORMATION, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -105,7 +105,7 @@ private:
|
|||||||
void OnResumeThread(wxCommandEvent& event);
|
void OnResumeThread(wxCommandEvent& event);
|
||||||
|
|
||||||
void OnStartWorker(wxCommandEvent& event);
|
void OnStartWorker(wxCommandEvent& event);
|
||||||
void OnWorkerEvent(wxCommandEvent& event);
|
void OnWorkerEvent(wxThreadEvent& event);
|
||||||
void OnUpdateWorker(wxUpdateUIEvent& event);
|
void OnUpdateWorker(wxUpdateUIEvent& event);
|
||||||
|
|
||||||
void OnExecMain(wxCommandEvent& event);
|
void OnExecMain(wxCommandEvent& event);
|
||||||
@@ -169,7 +169,7 @@ enum
|
|||||||
|
|
||||||
THREAD_SHOWCPUS,
|
THREAD_SHOWCPUS,
|
||||||
|
|
||||||
WORKER_EVENT // this one gets sent from the worker thread
|
WORKER_EVENT = wxID_HIGHEST+1 // this one gets sent from the worker thread
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -292,8 +292,22 @@ void MyWorkerThread::OnExit()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define TEST_YIELD_RACE_CONDITION 1
|
||||||
|
|
||||||
void *MyWorkerThread::Entry()
|
void *MyWorkerThread::Entry()
|
||||||
{
|
{
|
||||||
|
#if TEST_YIELD_RACE_CONDITION
|
||||||
|
if ( TestDestroy() )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
wxThreadEvent event( WORKER_EVENT );
|
||||||
|
|
||||||
|
event.SetInt( 50 );
|
||||||
|
wxQueueEvent( m_frame, new wxThreadEvent(event) );
|
||||||
|
|
||||||
|
event.SetInt(-1);
|
||||||
|
wxQueueEvent( m_frame, new wxThreadEvent(event) );
|
||||||
|
#else
|
||||||
for ( m_count = 0; !m_frame->Cancelled() && (m_count < 100); m_count++ )
|
for ( m_count = 0; !m_frame->Cancelled() && (m_count < 100); m_count++ )
|
||||||
{
|
{
|
||||||
// check if we were asked to exit
|
// check if we were asked to exit
|
||||||
@@ -301,18 +315,19 @@ void *MyWorkerThread::Entry()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
// create any type of command event here
|
// create any type of command event here
|
||||||
wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, WORKER_EVENT );
|
wxThreadEvent event( WORKER_EVENT );
|
||||||
event.SetInt( m_count );
|
event.SetInt( m_count );
|
||||||
|
|
||||||
// send in a thread-safe way
|
// send in a thread-safe way
|
||||||
wxQueueEvent( m_frame, new wxCommandEvent(event) );
|
wxQueueEvent( m_frame, new wxThreadEvent(event) );
|
||||||
|
|
||||||
wxMilliSleep(200);
|
wxMilliSleep(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, WORKER_EVENT );
|
wxThreadEvent event( WORKER_EVENT );
|
||||||
event.SetInt(-1); // that's all
|
event.SetInt(-1); // that's all
|
||||||
wxQueueEvent( m_frame, new wxCommandEvent(event) );
|
wxQueueEvent( m_frame, new wxThreadEvent(event) );
|
||||||
|
#endif
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -360,7 +375,8 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
|||||||
|
|
||||||
EVT_UPDATE_UI(THREAD_START_WORKER, MyFrame::OnUpdateWorker)
|
EVT_UPDATE_UI(THREAD_START_WORKER, MyFrame::OnUpdateWorker)
|
||||||
EVT_MENU(THREAD_START_WORKER, MyFrame::OnStartWorker)
|
EVT_MENU(THREAD_START_WORKER, MyFrame::OnStartWorker)
|
||||||
EVT_MENU(WORKER_EVENT, MyFrame::OnWorkerEvent)
|
|
||||||
|
EVT_THREAD(WORKER_EVENT, MyFrame::OnWorkerEvent)
|
||||||
|
|
||||||
EVT_IDLE(MyFrame::OnIdle)
|
EVT_IDLE(MyFrame::OnIdle)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
@@ -442,7 +458,6 @@ MyFrame::MyFrame(wxFrame *frame, const wxString& title,
|
|||||||
|
|
||||||
m_txtctrl = new wxTextCtrl(this, wxID_ANY, _T(""), wxPoint(0, 0), wxSize(0, 0),
|
m_txtctrl = new wxTextCtrl(this, wxID_ANY, _T(""), wxPoint(0, 0), wxSize(0, 0),
|
||||||
wxTE_MULTILINE | wxTE_READONLY);
|
wxTE_MULTILINE | wxTE_READONLY);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MyFrame::~MyFrame()
|
MyFrame::~MyFrame()
|
||||||
@@ -758,7 +773,7 @@ void MyFrame::OnStartWorker(wxCommandEvent& WXUNUSED(event))
|
|||||||
thread->Run();
|
thread->Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyFrame::OnWorkerEvent(wxCommandEvent& event)
|
void MyFrame::OnWorkerEvent(wxThreadEvent& event)
|
||||||
{
|
{
|
||||||
int n = event.GetInt();
|
int n = event.GetInt();
|
||||||
if ( n == -1 )
|
if ( n == -1 )
|
||||||
|
@@ -295,7 +295,7 @@ void wxApp::Exit()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Yield to other processes
|
// Yield to other processes
|
||||||
bool wxApp::Yield(bool onlyIfNeeded)
|
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||||
{
|
{
|
||||||
#if wxUSE_LOG
|
#if wxUSE_LOG
|
||||||
// disable log flushing from here because a call to wxYield() shouldn't
|
// disable log flushing from here because a call to wxYield() shouldn't
|
||||||
@@ -314,10 +314,13 @@ bool wxApp::Yield(bool onlyIfNeeded)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_isInsideYield = true;
|
m_isInsideYield = true;
|
||||||
|
m_eventsToProcessInsideYield = eventsToProcess;
|
||||||
|
|
||||||
// Run the event loop until it is out of events
|
// Run the event loop until it is out of events
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
|
// TODO: implement event filtering using the eventsToProcess mask
|
||||||
|
|
||||||
wxAutoNSAutoreleasePool pool;
|
wxAutoNSAutoreleasePool pool;
|
||||||
/* NOTE: It may be better to use something like
|
/* NOTE: It may be better to use something like
|
||||||
NSEventTrackingRunLoopMode since we don't necessarily want all
|
NSEventTrackingRunLoopMode since we don't necessarily want all
|
||||||
|
@@ -164,6 +164,7 @@ bool wxAppConsoleBase::Initialize(int& WXUNUSED(argc), wxChar **argv)
|
|||||||
|
|
||||||
#if wxUSE_THREADS
|
#if wxUSE_THREADS
|
||||||
wxHandlersWithPendingEventsLocker = new wxCriticalSection;
|
wxHandlersWithPendingEventsLocker = new wxCriticalSection;
|
||||||
|
wxHandlersWithPendingDelayedEvents = new wxList;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __WXPALMOS__
|
#ifndef __WXPALMOS__
|
||||||
@@ -193,6 +194,9 @@ void wxAppConsoleBase::CleanUp()
|
|||||||
delete wxHandlersWithPendingEvents;
|
delete wxHandlersWithPendingEvents;
|
||||||
wxHandlersWithPendingEvents = NULL;
|
wxHandlersWithPendingEvents = NULL;
|
||||||
|
|
||||||
|
delete wxHandlersWithPendingDelayedEvents;
|
||||||
|
wxHandlersWithPendingDelayedEvents = NULL;
|
||||||
|
|
||||||
#if wxUSE_THREADS
|
#if wxUSE_THREADS
|
||||||
delete wxHandlersWithPendingEventsLocker;
|
delete wxHandlersWithPendingEventsLocker;
|
||||||
wxHandlersWithPendingEventsLocker = NULL;
|
wxHandlersWithPendingEventsLocker = NULL;
|
||||||
@@ -336,6 +340,16 @@ bool wxAppConsoleBase::HasPendingEvents() const
|
|||||||
return has;
|
return has;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxAppConsoleBase::SuspendProcessingOfPendingEvents()
|
||||||
|
{
|
||||||
|
wxENTER_CRIT_SECT( *wxHandlersWithPendingEventsLocker );
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxAppConsoleBase::ResumeProcessingOfPendingEvents()
|
||||||
|
{
|
||||||
|
wxLEAVE_CRIT_SECT( *wxHandlersWithPendingEventsLocker );
|
||||||
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
bool wxAppConsoleBase::IsMainLoopRunning()
|
bool wxAppConsoleBase::IsMainLoopRunning()
|
||||||
{
|
{
|
||||||
@@ -353,6 +367,9 @@ void wxAppConsoleBase::ProcessPendingEvents()
|
|||||||
|
|
||||||
wxENTER_CRIT_SECT( *wxHandlersWithPendingEventsLocker );
|
wxENTER_CRIT_SECT( *wxHandlersWithPendingEventsLocker );
|
||||||
|
|
||||||
|
wxCHECK_RET( wxHandlersWithPendingDelayedEvents->IsEmpty(),
|
||||||
|
"this helper list should be empty" );
|
||||||
|
|
||||||
if (wxHandlersWithPendingEvents)
|
if (wxHandlersWithPendingEvents)
|
||||||
{
|
{
|
||||||
// iterate until the list becomes empty: the handlers remove themselves
|
// iterate until the list becomes empty: the handlers remove themselves
|
||||||
@@ -360,7 +377,7 @@ void wxAppConsoleBase::ProcessPendingEvents()
|
|||||||
wxList::compatibility_iterator node = wxHandlersWithPendingEvents->GetFirst();
|
wxList::compatibility_iterator node = wxHandlersWithPendingEvents->GetFirst();
|
||||||
while (node)
|
while (node)
|
||||||
{
|
{
|
||||||
// In ProcessPendingEvents(), new handlers might be add
|
// In ProcessPendingEvents(), new handlers might be added
|
||||||
// and we can safely leave the critical section here.
|
// and we can safely leave the critical section here.
|
||||||
wxLEAVE_CRIT_SECT( *wxHandlersWithPendingEventsLocker );
|
wxLEAVE_CRIT_SECT( *wxHandlersWithPendingEventsLocker );
|
||||||
|
|
||||||
@@ -374,6 +391,20 @@ void wxAppConsoleBase::ProcessPendingEvents()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now the wxHandlersWithPendingEvents is surely empty; however some event
|
||||||
|
// handlers may have moved themselves into wxHandlersWithPendingDelayedEvents
|
||||||
|
// because of a selective wxYield call in progress.
|
||||||
|
// Now we need to move them back to wxHandlersWithPendingEvents so the next
|
||||||
|
// call to this function has the chance of processing them:
|
||||||
|
if (!wxHandlersWithPendingDelayedEvents->IsEmpty())
|
||||||
|
{
|
||||||
|
if (!wxHandlersWithPendingEvents)
|
||||||
|
wxHandlersWithPendingEvents = new wxList;
|
||||||
|
|
||||||
|
WX_APPEND_LIST(wxHandlersWithPendingEvents, wxHandlersWithPendingDelayedEvents);
|
||||||
|
wxHandlersWithPendingDelayedEvents->Clear();
|
||||||
|
}
|
||||||
|
|
||||||
wxLEAVE_CRIT_SECT( *wxHandlersWithPendingEventsLocker );
|
wxLEAVE_CRIT_SECT( *wxHandlersWithPendingEventsLocker );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -79,6 +79,7 @@ wxAppBase::wxAppBase()
|
|||||||
m_isActive = true;
|
m_isActive = true;
|
||||||
|
|
||||||
m_isInsideYield = false;
|
m_isInsideYield = false;
|
||||||
|
m_eventsToProcessInsideYield = wxEVT_CATEGORY_ALL;
|
||||||
|
|
||||||
// We don't want to exit the app if the user code shows a dialog from its
|
// We don't want to exit the app if the user code shows a dialog from its
|
||||||
// OnInit() -- but this is what would happen if we set m_exitOnFrameDelete
|
// OnInit() -- but this is what would happen if we set m_exitOnFrameDelete
|
||||||
@@ -325,6 +326,26 @@ void wxAppBase::SetActive(bool active, wxWindow * WXUNUSED(lastFocus))
|
|||||||
(void)ProcessEvent(event);
|
(void)ProcessEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wxAppBase::IsEventAllowedInsideYield(wxEventCategory cat) const
|
||||||
|
{
|
||||||
|
return m_eventsToProcessInsideYield & cat;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxAppBase::SafeYield(wxWindow *win, bool onlyIfNeeded)
|
||||||
|
{
|
||||||
|
wxWindowDisabler wd(win);
|
||||||
|
|
||||||
|
return Yield(onlyIfNeeded);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxAppBase::SafeYieldFor(wxWindow *win, long eventsToProcess)
|
||||||
|
{
|
||||||
|
wxWindowDisabler wd(win);
|
||||||
|
|
||||||
|
return YieldFor(eventsToProcess);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// idle handling
|
// idle handling
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@@ -65,6 +65,7 @@
|
|||||||
|
|
||||||
#if wxUSE_GUI
|
#if wxUSE_GUI
|
||||||
IMPLEMENT_DYNAMIC_CLASS(wxCommandEvent, wxEvent)
|
IMPLEMENT_DYNAMIC_CLASS(wxCommandEvent, wxEvent)
|
||||||
|
IMPLEMENT_DYNAMIC_CLASS(wxThreadEvent, wxEvent)
|
||||||
IMPLEMENT_DYNAMIC_CLASS(wxNotifyEvent, wxCommandEvent)
|
IMPLEMENT_DYNAMIC_CLASS(wxNotifyEvent, wxCommandEvent)
|
||||||
IMPLEMENT_DYNAMIC_CLASS(wxScrollEvent, wxCommandEvent)
|
IMPLEMENT_DYNAMIC_CLASS(wxScrollEvent, wxCommandEvent)
|
||||||
IMPLEMENT_DYNAMIC_CLASS(wxScrollWinEvent, wxEvent)
|
IMPLEMENT_DYNAMIC_CLASS(wxScrollWinEvent, wxEvent)
|
||||||
@@ -147,6 +148,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxEventTableEntryModule, wxModule)
|
|||||||
// List containing event handlers with pending events (each handler can occur
|
// List containing event handlers with pending events (each handler can occur
|
||||||
// at most once here)
|
// at most once here)
|
||||||
wxList *wxHandlersWithPendingEvents = NULL;
|
wxList *wxHandlersWithPendingEvents = NULL;
|
||||||
|
wxList *wxHandlersWithPendingDelayedEvents = NULL;
|
||||||
|
|
||||||
#if wxUSE_THREADS
|
#if wxUSE_THREADS
|
||||||
// protects wxHandlersWithPendingEvents list
|
// protects wxHandlersWithPendingEvents list
|
||||||
@@ -316,6 +318,9 @@ wxDEFINE_EVENT( wxEVT_COMMAND_ENTER, wxCommandEvent )
|
|||||||
wxDEFINE_EVENT( wxEVT_HELP, wxHelpEvent )
|
wxDEFINE_EVENT( wxEVT_HELP, wxHelpEvent )
|
||||||
wxDEFINE_EVENT( wxEVT_DETAILED_HELP, wxHelpEvent )
|
wxDEFINE_EVENT( wxEVT_DETAILED_HELP, wxHelpEvent )
|
||||||
|
|
||||||
|
// Thread event
|
||||||
|
DEFINE_EVENT_TYPE(wxEVT_COMMAND_THREAD)
|
||||||
|
|
||||||
#endif // wxUSE_GUI
|
#endif // wxUSE_GUI
|
||||||
|
|
||||||
#if wxUSE_BASE
|
#if wxUSE_BASE
|
||||||
@@ -350,15 +355,14 @@ wxEventFunctor::~wxEventFunctor()
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* General wxWidgets events, covering
|
* General wxWidgets events, covering all interesting things that might happen
|
||||||
* all interesting things that might happen (button clicking, resizing,
|
* (button clicking, resizing, setting text in widgets, etc.).
|
||||||
* setting text in widgets, etc.).
|
|
||||||
*
|
*
|
||||||
* For each completely new event type, derive a new event class.
|
* For each completely new event type, derive a new event class.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
wxEvent::wxEvent(int theId, wxEventType commandType )
|
wxEvent::wxEvent(int theId, wxEventType commandType)
|
||||||
{
|
{
|
||||||
m_eventType = commandType;
|
m_eventType = commandType;
|
||||||
m_eventObject = NULL;
|
m_eventObject = NULL;
|
||||||
@@ -1103,6 +1107,14 @@ wxEvtHandler::~wxEvtHandler()
|
|||||||
}
|
}
|
||||||
//else: we weren't in this list at all, it's ok
|
//else: we weren't in this list at all, it's ok
|
||||||
|
|
||||||
|
if ( wxHandlersWithPendingDelayedEvents->DeleteObject(this) )
|
||||||
|
{
|
||||||
|
// check that we were present only once in the list
|
||||||
|
wxASSERT_MSG( !wxHandlersWithPendingDelayedEvents->Find(this),
|
||||||
|
"Handler occurs twice in wxHandlersWithPendingDelayedEvents list" );
|
||||||
|
}
|
||||||
|
//else: we weren't in this list at all, it's ok
|
||||||
|
|
||||||
#if wxUSE_THREADS
|
#if wxUSE_THREADS
|
||||||
if (wxHandlersWithPendingEventsLocker)
|
if (wxHandlersWithPendingEventsLocker)
|
||||||
wxLEAVE_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
|
wxLEAVE_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
|
||||||
@@ -1188,6 +1200,10 @@ void wxEvtHandler::QueueEvent(wxEvent *event)
|
|||||||
|
|
||||||
void wxEvtHandler::ProcessPendingEvents()
|
void wxEvtHandler::ProcessPendingEvents()
|
||||||
{
|
{
|
||||||
|
// we need to process only a single pending event in this call because
|
||||||
|
// each call to ProcessEvent() could result in the destruction of this
|
||||||
|
// same event handler (see the comment at the end of this function)
|
||||||
|
|
||||||
wxENTER_CRIT_SECT( m_pendingEventsLock );
|
wxENTER_CRIT_SECT( m_pendingEventsLock );
|
||||||
|
|
||||||
// this method is only called by wxApp if this handler does have
|
// this method is only called by wxApp if this handler does have
|
||||||
@@ -1196,7 +1212,40 @@ void wxEvtHandler::ProcessPendingEvents()
|
|||||||
"should have pending events if called" );
|
"should have pending events if called" );
|
||||||
|
|
||||||
wxList::compatibility_iterator node = m_pendingEvents->GetFirst();
|
wxList::compatibility_iterator node = m_pendingEvents->GetFirst();
|
||||||
wxEventPtr event(static_cast<wxEvent *>(node->GetData()));
|
wxEvent* pEvent = static_cast<wxEvent *>(node->GetData());
|
||||||
|
|
||||||
|
// find the first event which can be processed now:
|
||||||
|
if (wxTheApp && wxTheApp->IsYielding())
|
||||||
|
{
|
||||||
|
while (node && pEvent && !wxTheApp->IsEventAllowedInsideYield(pEvent->GetEventCategory()))
|
||||||
|
{
|
||||||
|
node = node->GetNext();
|
||||||
|
pEvent = node ? static_cast<wxEvent *>(node->GetData()) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
{
|
||||||
|
// all our events are NOT processable now... signal this:
|
||||||
|
#if wxUSE_THREADS
|
||||||
|
if (wxHandlersWithPendingEventsLocker)
|
||||||
|
wxENTER_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
|
||||||
|
#endif
|
||||||
|
// move us from the list of handlers with processable pending events
|
||||||
|
// to the list of handlers with pending events which needs to be processed later
|
||||||
|
wxHandlersWithPendingEvents->DeleteObject(this);
|
||||||
|
if ( !wxHandlersWithPendingDelayedEvents->Find(this) )
|
||||||
|
wxHandlersWithPendingDelayedEvents->Append(this);
|
||||||
|
#if wxUSE_THREADS
|
||||||
|
if (wxHandlersWithPendingEventsLocker)
|
||||||
|
wxLEAVE_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
|
||||||
|
#endif
|
||||||
|
wxLEAVE_CRIT_SECT( m_pendingEventsLock );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wxEventPtr event(pEvent);
|
||||||
|
|
||||||
// it's important we remove event from list before processing it, else a
|
// 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
|
// nested event loop, for example from a modal dialog, might process the
|
||||||
@@ -1306,6 +1355,27 @@ bool wxEvtHandler::ProcessEvent(wxEvent& event)
|
|||||||
{
|
{
|
||||||
if ( wxTheApp )
|
if ( wxTheApp )
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
CANNOT ENABLE: ProcessEvent() must always immediately process the event!
|
||||||
|
|
||||||
|
if (wxTheApp->IsYielding() &&
|
||||||
|
!wxTheApp->IsEventAllowedInsideYield(event.GetEventCategory()))
|
||||||
|
{
|
||||||
|
wxEvent* queuedEv = event.Clone();
|
||||||
|
|
||||||
|
// queue this event rather than processing it now
|
||||||
|
QueueEvent(queuedEv);
|
||||||
|
// the wxWakeUpIdle call shouldn't probably be done
|
||||||
|
// in this context (there's wxYield in the call stack)
|
||||||
|
|
||||||
|
return true;
|
||||||
|
// it's not completely true that the event was processed;
|
||||||
|
// but we cannot even say it was skipped or discarded...
|
||||||
|
}
|
||||||
|
//else: either we're not inside a wxYield() call or if we are,
|
||||||
|
// we can process this event immediately.
|
||||||
|
*/
|
||||||
|
|
||||||
int rc = wxTheApp->FilterEvent(event);
|
int rc = wxTheApp->FilterEvent(event);
|
||||||
if ( rc != -1 )
|
if ( rc != -1 )
|
||||||
{
|
{
|
||||||
|
@@ -63,6 +63,7 @@ public:
|
|||||||
wxDummyConsoleApp() { }
|
wxDummyConsoleApp() { }
|
||||||
|
|
||||||
virtual int OnRun() { wxFAIL_MSG( _T("unreachable code") ); return 0; }
|
virtual int OnRun() { wxFAIL_MSG( _T("unreachable code") ); return 0; }
|
||||||
|
virtual bool DoYield(bool, long) { return true; }
|
||||||
|
|
||||||
DECLARE_NO_COPY_CLASS(wxDummyConsoleApp)
|
DECLARE_NO_COPY_CLASS(wxDummyConsoleApp)
|
||||||
};
|
};
|
||||||
|
@@ -163,8 +163,7 @@ void wxApp::WakeUpIdle()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||||
bool wxApp::Yield(bool onlyIfNeeded)
|
|
||||||
{
|
{
|
||||||
#if wxUSE_THREADS
|
#if wxUSE_THREADS
|
||||||
if ( !wxThread::IsMain() )
|
if ( !wxThread::IsMain() )
|
||||||
@@ -182,6 +181,7 @@ bool wxApp::Yield(bool onlyIfNeeded)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_isInsideYield = true;
|
m_isInsideYield = true;
|
||||||
|
m_eventsToProcessInsideYield = eventsToProcess;
|
||||||
|
|
||||||
#if wxUSE_LOG
|
#if wxUSE_LOG
|
||||||
wxLog::Suspend();
|
wxLog::Suspend();
|
||||||
|
@@ -204,6 +204,8 @@ wxIDirectFBEventBufferPtr wxGUIEventLoop::GetDirectFBEventBuffer()
|
|||||||
|
|
||||||
void wxGUIEventLoop::Yield()
|
void wxGUIEventLoop::Yield()
|
||||||
{
|
{
|
||||||
|
// TODO: implement event filtering using the eventsToProcess mask
|
||||||
|
|
||||||
// process all pending events:
|
// process all pending events:
|
||||||
while ( Pending() )
|
while ( Pending() )
|
||||||
Dispatch();
|
Dispatch();
|
||||||
|
@@ -401,7 +401,7 @@ wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip)
|
|||||||
m_msg->SetLabel(_("Done."));
|
m_msg->SetLabel(_("Done."));
|
||||||
}
|
}
|
||||||
|
|
||||||
wxYieldIfNeeded();
|
wxTheApp->YieldFor(wxEVT_CATEGORY_UI);
|
||||||
|
|
||||||
(void)ShowModal();
|
(void)ShowModal();
|
||||||
}
|
}
|
||||||
@@ -451,7 +451,7 @@ bool wxProgressDialog::DoAfterUpdate(bool *skip)
|
|||||||
{
|
{
|
||||||
// we have to yield because not only we want to update the display but
|
// we have to yield because not only we want to update the display but
|
||||||
// also to process the clicks on the cancel and skip buttons
|
// also to process the clicks on the cancel and skip buttons
|
||||||
wxYieldIfNeeded();
|
wxTheApp->YieldFor(wxEVT_CATEGORY_UI|wxEVT_CATEGORY_USER_INPUT);
|
||||||
|
|
||||||
Update();
|
Update();
|
||||||
|
|
||||||
@@ -670,7 +670,7 @@ void wxProgressDialog::UpdateMessage(const wxString &newmsg)
|
|||||||
|
|
||||||
Fit(); // adapt to the new label size
|
Fit(); // adapt to the new label size
|
||||||
|
|
||||||
wxYieldIfNeeded() ;
|
wxTheApp->YieldFor(wxEVT_CATEGORY_UI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
110
src/gtk/app.cpp
110
src/gtk/app.cpp
@@ -49,12 +49,13 @@
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
static GtkWidget *gs_RootWindow = NULL;
|
static GtkWidget *gs_RootWindow = NULL;
|
||||||
|
static wxArrayPtrVoid g_arrGdkEvents;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// wxYield
|
// wxYield
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool wxApp::Yield(bool onlyIfNeeded)
|
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||||
{
|
{
|
||||||
if ( m_isInsideYield )
|
if ( m_isInsideYield )
|
||||||
{
|
{
|
||||||
@@ -75,6 +76,7 @@ bool wxApp::Yield(bool onlyIfNeeded)
|
|||||||
#endif // wxUSE_THREADS
|
#endif // wxUSE_THREADS
|
||||||
|
|
||||||
m_isInsideYield = true;
|
m_isInsideYield = true;
|
||||||
|
m_eventsToProcessInsideYield = eventsToProcess;
|
||||||
|
|
||||||
#if wxUSE_LOG
|
#if wxUSE_LOG
|
||||||
// disable log flushing from here because a call to wxYield() shouldn't
|
// disable log flushing from here because a call to wxYield() shouldn't
|
||||||
@@ -82,16 +84,116 @@ bool wxApp::Yield(bool onlyIfNeeded)
|
|||||||
wxLog::Suspend();
|
wxLog::Suspend();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (EventsPending())
|
// NOTE: gtk_main_iteration() doesn't allow us to filter events, so we
|
||||||
gtk_main_iteration();
|
// rather use gtk_main_do_event() after filtering the events at
|
||||||
|
// GDK level
|
||||||
|
|
||||||
|
GdkDisplay* disp = gtk_widget_get_display(gs_RootWindow);
|
||||||
|
|
||||||
|
// gdk_display_get_event() will transform X11 events into GDK events
|
||||||
|
// and will queue all of them in the display (private) structure;
|
||||||
|
// finally it will "unqueue" the last one and return it to us
|
||||||
|
GdkEvent* event = gdk_display_get_event(disp);
|
||||||
|
while (event)
|
||||||
|
{
|
||||||
|
// categorize the GDK event according to wxEventCategory.
|
||||||
|
// See http://library.gnome.org/devel/gdk/unstable/gdk-Events.html#GdkEventType
|
||||||
|
// for more info.
|
||||||
|
|
||||||
|
wxEventCategory cat = wxEVT_CATEGORY_UNKNOWN;
|
||||||
|
switch (event->type)
|
||||||
|
{
|
||||||
|
case GDK_SELECTION_REQUEST:
|
||||||
|
case GDK_SELECTION_NOTIFY:
|
||||||
|
case GDK_SELECTION_CLEAR:
|
||||||
|
case GDK_OWNER_CHANGE:
|
||||||
|
cat = wxEVT_CATEGORY_CLIPBOARD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case GDK_KEY_PRESS:
|
||||||
|
case GDK_KEY_RELEASE:
|
||||||
|
case GDK_BUTTON_PRESS:
|
||||||
|
case GDK_2BUTTON_PRESS:
|
||||||
|
case GDK_3BUTTON_PRESS:
|
||||||
|
case GDK_BUTTON_RELEASE:
|
||||||
|
case GDK_SCROLL: // generated from mouse buttons
|
||||||
|
case GDK_CLIENT_EVENT:
|
||||||
|
cat = wxEVT_CATEGORY_USER_INPUT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case GDK_PROXIMITY_IN:
|
||||||
|
case GDK_PROXIMITY_OUT:
|
||||||
|
|
||||||
|
case GDK_MOTION_NOTIFY:
|
||||||
|
case GDK_ENTER_NOTIFY:
|
||||||
|
case GDK_LEAVE_NOTIFY:
|
||||||
|
case GDK_VISIBILITY_NOTIFY:
|
||||||
|
case GDK_PROPERTY_NOTIFY:
|
||||||
|
|
||||||
|
case GDK_FOCUS_CHANGE:
|
||||||
|
case GDK_CONFIGURE:
|
||||||
|
case GDK_WINDOW_STATE:
|
||||||
|
case GDK_SETTING:
|
||||||
|
case GDK_DELETE:
|
||||||
|
case GDK_DESTROY:
|
||||||
|
|
||||||
|
case GDK_EXPOSE:
|
||||||
|
case GDK_NO_EXPOSE:
|
||||||
|
case GDK_MAP:
|
||||||
|
case GDK_UNMAP:
|
||||||
|
//case GDK_DAMAGE:
|
||||||
|
|
||||||
|
case GDK_DRAG_ENTER:
|
||||||
|
case GDK_DRAG_LEAVE:
|
||||||
|
case GDK_DRAG_MOTION:
|
||||||
|
case GDK_DRAG_STATUS:
|
||||||
|
case GDK_DROP_START:
|
||||||
|
case GDK_DROP_FINISHED:
|
||||||
|
case GDK_GRAB_BROKEN:
|
||||||
|
cat = wxEVT_CATEGORY_UI;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
cat = wxEVT_CATEGORY_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventsToProcess & cat)
|
||||||
|
gtk_main_do_event(event); // process it now
|
||||||
|
else
|
||||||
|
g_arrGdkEvents.Add(event); // process it later
|
||||||
|
|
||||||
|
// get next event
|
||||||
|
event = gdk_display_get_event(disp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventsToProcess != wxEVT_CATEGORY_CLIPBOARD)
|
||||||
|
{
|
||||||
// It's necessary to call ProcessIdle() to update the frames sizes which
|
// It's necessary to call ProcessIdle() to update the frames sizes which
|
||||||
// might have been changed (it also will update other things set from
|
// might have been changed (it also will update other things set from
|
||||||
// OnUpdateUI() which is a nice (and desired) side effect). But we
|
// OnUpdateUI() which is a nice (and desired) side effect). But we
|
||||||
// call ProcessIdle() only once since this is not meant for longish
|
// call ProcessIdle() only once since this is not meant for longish
|
||||||
// background jobs (controlled by wxIdleEvent::RequestMore() and the
|
// background jobs (controlled by wxIdleEvent::RequestMore() and the
|
||||||
// return value of Processidle().
|
// return value of Processidle().
|
||||||
ProcessIdle();
|
ProcessIdle(); // ProcessIdle() also calls ProcessPendingEvents()
|
||||||
|
}
|
||||||
|
//else: if we are inside ~wxClipboardSync() and we call ProcessIdle() and
|
||||||
|
// the user app contains an UI update handler which calls wxClipboard::IsSupported,
|
||||||
|
// then we fall into a never-ending loop...
|
||||||
|
|
||||||
|
// put all unprocessed GDK events back in the queue
|
||||||
|
for (size_t i=0; i<g_arrGdkEvents.GetCount(); i++)
|
||||||
|
{
|
||||||
|
GdkEvent* ev = (GdkEvent*)g_arrGdkEvents[i];
|
||||||
|
|
||||||
|
// NOTE: gdk_display_put_event makes a copy of the event passed to it
|
||||||
|
gdk_display_put_event(disp, ev);
|
||||||
|
gdk_event_free(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_arrGdkEvents.Clear();
|
||||||
|
|
||||||
#if wxUSE_LOG
|
#if wxUSE_LOG
|
||||||
// let the logs be flashed again
|
// let the logs be flashed again
|
||||||
|
@@ -73,8 +73,8 @@ public:
|
|||||||
|
|
||||||
~wxClipboardSync()
|
~wxClipboardSync()
|
||||||
{
|
{
|
||||||
while ( ms_clipboard )
|
while (ms_clipboard)
|
||||||
gtk_main_iteration();
|
wxTheApp->YieldFor(wxEVT_CATEGORY_CLIPBOARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this method must be called by GTK+ callbacks to indicate that we got the
|
// this method must be called by GTK+ callbacks to indicate that we got the
|
||||||
@@ -438,7 +438,7 @@ wxClipboard::wxClipboard()
|
|||||||
g_signal_connect (m_targetsWidget, "selection_received",
|
g_signal_connect (m_targetsWidget, "selection_received",
|
||||||
G_CALLBACK (targets_selection_received), this);
|
G_CALLBACK (targets_selection_received), this);
|
||||||
|
|
||||||
// we use m_targetsWidgetAsync to query what formats asynchronously
|
// we use m_targetsWidgetAsync to query what formats are available asynchronously
|
||||||
m_targetsWidgetAsync = gtk_window_new( GTK_WINDOW_POPUP );
|
m_targetsWidgetAsync = gtk_window_new( GTK_WINDOW_POPUP );
|
||||||
gtk_widget_realize( m_targetsWidgetAsync );
|
gtk_widget_realize( m_targetsWidgetAsync );
|
||||||
|
|
||||||
|
@@ -103,7 +103,7 @@ static wxMutex gs_idleTagsMutex;
|
|||||||
// wxYield
|
// wxYield
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool wxApp::Yield(bool onlyIfNeeded)
|
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||||
{
|
{
|
||||||
if ( m_isInsideYield )
|
if ( m_isInsideYield )
|
||||||
{
|
{
|
||||||
@@ -124,6 +124,7 @@ bool wxApp::Yield(bool onlyIfNeeded)
|
|||||||
#endif // wxUSE_THREADS
|
#endif // wxUSE_THREADS
|
||||||
|
|
||||||
m_isInsideYield = true;
|
m_isInsideYield = true;
|
||||||
|
m_eventsToProcessInsideYield = eventsToProcess;
|
||||||
|
|
||||||
// We need to remove idle callbacks or the loop will
|
// We need to remove idle callbacks or the loop will
|
||||||
// never finish.
|
// never finish.
|
||||||
@@ -135,6 +136,7 @@ bool wxApp::Yield(bool onlyIfNeeded)
|
|||||||
wxLog::Suspend();
|
wxLog::Suspend();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// TODO: implement event filtering using the eventsToProcess mask
|
||||||
while (gtk_events_pending())
|
while (gtk_events_pending())
|
||||||
gtk_main_iteration();
|
gtk_main_iteration();
|
||||||
|
|
||||||
|
@@ -48,7 +48,7 @@ void wxApp::Exit()
|
|||||||
// wxYield
|
// wxYield
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool wxApp::Yield(bool onlyIfNeeded)
|
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||||
{
|
{
|
||||||
if ( m_isInsideYield )
|
if ( m_isInsideYield )
|
||||||
{
|
{
|
||||||
@@ -69,12 +69,15 @@ bool wxApp::Yield(bool onlyIfNeeded)
|
|||||||
#endif // wxUSE_THREADS
|
#endif // wxUSE_THREADS
|
||||||
|
|
||||||
m_isInsideYield = true;
|
m_isInsideYield = true;
|
||||||
|
m_eventsToProcessInsideYield = eventsToProcess;
|
||||||
|
|
||||||
wxLog::Suspend();
|
wxLog::Suspend();
|
||||||
|
|
||||||
wxEventLoopBase * const eventLoop = wxEventLoop::GetActive();
|
wxEventLoopBase * const eventLoop = wxEventLoop::GetActive();
|
||||||
if ( eventLoop )
|
if ( eventLoop )
|
||||||
{
|
{
|
||||||
|
// TODO: implement event filtering using the eventsToProcess mask
|
||||||
|
|
||||||
while (eventLoop->Pending())
|
while (eventLoop->Pending())
|
||||||
eventLoop->Dispatch();
|
eventLoop->Dispatch();
|
||||||
}
|
}
|
||||||
|
@@ -470,7 +470,7 @@ void wxApp::SetTopLevelRealizedWidget(WXDisplay* display, WXWidget widget)
|
|||||||
|
|
||||||
// Yield to other processes
|
// Yield to other processes
|
||||||
|
|
||||||
bool wxApp::Yield(bool onlyIfNeeded)
|
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||||
{
|
{
|
||||||
if ( m_isInsideYield )
|
if ( m_isInsideYield )
|
||||||
{
|
{
|
||||||
@@ -483,9 +483,11 @@ bool wxApp::Yield(bool onlyIfNeeded)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_isInsideYield = true;
|
m_isInsideYield = true;
|
||||||
|
m_eventsToProcessInsideYield = eventsToProcess;
|
||||||
|
|
||||||
wxEventLoopGuarantor dummyLoopIfNeeded;
|
wxEventLoopGuarantor dummyLoopIfNeeded;
|
||||||
while (wxTheApp && wxTheApp->Pending())
|
while (wxTheApp && wxTheApp->Pending())
|
||||||
|
// TODO: implement event filtering using the eventsToProcess mask
|
||||||
wxTheApp->Dispatch();
|
wxTheApp->Dispatch();
|
||||||
|
|
||||||
m_isInsideYield = false;
|
m_isInsideYield = false;
|
||||||
|
105
src/msw/app.cpp
105
src/msw/app.cpp
@@ -1015,7 +1015,14 @@ int wxApp::GetShell32Version()
|
|||||||
// Yield to incoming messages
|
// Yield to incoming messages
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool wxApp::Yield(bool onlyIfNeeded)
|
WX_DECLARE_OBJARRAY(MSG, wxMSGArray);
|
||||||
|
|
||||||
|
#include <wx/arrimpl.cpp>
|
||||||
|
WX_DEFINE_OBJARRAY(wxMSGArray);
|
||||||
|
|
||||||
|
static wxMSGArray g_arrMSG;
|
||||||
|
|
||||||
|
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||||
{
|
{
|
||||||
if ( m_isInsideYield )
|
if ( m_isInsideYield )
|
||||||
{
|
{
|
||||||
@@ -1029,8 +1036,9 @@ bool wxApp::Yield(bool onlyIfNeeded)
|
|||||||
|
|
||||||
// set the flag and don't forget to reset it before returning
|
// set the flag and don't forget to reset it before returning
|
||||||
m_isInsideYield = true;
|
m_isInsideYield = true;
|
||||||
wxON_BLOCK_EXIT_SET(m_isInsideYield, false);
|
m_eventsToProcessInsideYield = eventsToProcess;
|
||||||
|
|
||||||
|
wxON_BLOCK_EXIT_SET(m_isInsideYield, false);
|
||||||
|
|
||||||
#if wxUSE_LOG
|
#if wxUSE_LOG
|
||||||
// disable log flushing from here because a call to wxYield() shouldn't
|
// disable log flushing from here because a call to wxYield() shouldn't
|
||||||
@@ -1041,7 +1049,6 @@ bool wxApp::Yield(bool onlyIfNeeded)
|
|||||||
wxON_BLOCK_EXIT0(wxLog::Resume);
|
wxON_BLOCK_EXIT0(wxLog::Resume);
|
||||||
#endif // wxUSE_LOG
|
#endif // wxUSE_LOG
|
||||||
|
|
||||||
|
|
||||||
// we don't want to process WM_QUIT from here - it should be processed in
|
// we don't want to process WM_QUIT from here - it should be processed in
|
||||||
// the main event loop in order to stop it
|
// the main event loop in order to stop it
|
||||||
wxEventLoopGuarantor dummyLoopIfNeeded;
|
wxEventLoopGuarantor dummyLoopIfNeeded;
|
||||||
@@ -1053,13 +1060,105 @@ bool wxApp::Yield(bool onlyIfNeeded)
|
|||||||
wxMutexGuiLeaveOrEnter();
|
wxMutexGuiLeaveOrEnter();
|
||||||
#endif // wxUSE_THREADS
|
#endif // wxUSE_THREADS
|
||||||
|
|
||||||
|
wxEventCategory cat;
|
||||||
|
switch (msg.message)
|
||||||
|
{
|
||||||
|
case WM_NCMOUSEMOVE:
|
||||||
|
case WM_NCLBUTTONDOWN:
|
||||||
|
case WM_NCLBUTTONUP:
|
||||||
|
case WM_NCLBUTTONDBLCLK:
|
||||||
|
case WM_NCRBUTTONDOWN:
|
||||||
|
case WM_NCRBUTTONUP:
|
||||||
|
case WM_NCRBUTTONDBLCLK:
|
||||||
|
case WM_NCMBUTTONDOWN:
|
||||||
|
case WM_NCMBUTTONUP:
|
||||||
|
case WM_NCMBUTTONDBLCLK:
|
||||||
|
|
||||||
|
case WM_KEYFIRST:
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
case WM_KEYUP:
|
||||||
|
case WM_CHAR:
|
||||||
|
case WM_DEADCHAR:
|
||||||
|
case WM_SYSKEYDOWN:
|
||||||
|
case WM_SYSKEYUP:
|
||||||
|
case WM_SYSCHAR:
|
||||||
|
case WM_SYSDEADCHAR:
|
||||||
|
case WM_KEYLAST:
|
||||||
|
case WM_HOTKEY:
|
||||||
|
case WM_IME_STARTCOMPOSITION:
|
||||||
|
case WM_IME_ENDCOMPOSITION:
|
||||||
|
case WM_IME_COMPOSITION:
|
||||||
|
case WM_IME_KEYLAST:
|
||||||
|
case WM_COMMAND:
|
||||||
|
case WM_SYSCOMMAND:
|
||||||
|
|
||||||
|
case WM_IME_SETCONTEXT:
|
||||||
|
case WM_IME_NOTIFY:
|
||||||
|
case WM_IME_CONTROL:
|
||||||
|
case WM_IME_COMPOSITIONFULL:
|
||||||
|
case WM_IME_SELECT:
|
||||||
|
case WM_IME_CHAR:
|
||||||
|
case WM_IME_KEYDOWN:
|
||||||
|
case WM_IME_KEYUP:
|
||||||
|
|
||||||
|
case WM_MOUSEHOVER:
|
||||||
|
case WM_NCMOUSELEAVE:
|
||||||
|
case WM_MOUSELEAVE:
|
||||||
|
|
||||||
|
case WM_CUT:
|
||||||
|
case WM_COPY:
|
||||||
|
case WM_PASTE:
|
||||||
|
case WM_CLEAR:
|
||||||
|
case WM_UNDO:
|
||||||
|
|
||||||
|
case WM_MOUSEFIRST:
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
case WM_LBUTTONDBLCLK:
|
||||||
|
case WM_RBUTTONDOWN:
|
||||||
|
case WM_RBUTTONUP:
|
||||||
|
case WM_RBUTTONDBLCLK:
|
||||||
|
case WM_MBUTTONDOWN:
|
||||||
|
case WM_MBUTTONUP:
|
||||||
|
case WM_MBUTTONDBLCLK:
|
||||||
|
case WM_MOUSELAST:
|
||||||
|
case WM_MOUSEWHEEL:
|
||||||
|
cat = wxEVT_CATEGORY_USER_INPUT;
|
||||||
|
|
||||||
|
case WM_TIMER:
|
||||||
|
cat = wxEVT_CATEGORY_TIMER;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// there are too many of these types of messages to handle them in this switch
|
||||||
|
cat = wxEVT_CATEGORY_UI;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cat & eventsToProcess)
|
||||||
|
{
|
||||||
if ( !wxTheApp->Dispatch() )
|
if ( !wxTheApp->Dispatch() )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// remove the message and store it
|
||||||
|
PeekMessage(&msg, (HWND)0, 0, 0, PM_REMOVE)
|
||||||
|
g_arrMSG.Add(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if there are pending events, we must process them.
|
// if there are pending events, we must process them.
|
||||||
ProcessPendingEvents();
|
ProcessPendingEvents();
|
||||||
|
|
||||||
|
// put back unprocessed events in the queue
|
||||||
|
DWORD id = GetCurrentThreadId();
|
||||||
|
for (size_t i=0; i<g_arrMSG.GetCount(); i++)
|
||||||
|
{
|
||||||
|
PostThreadMessage(id, g_arrMSG[i].message, g_arrMSG[i].wParam, g_arrMSG[i].lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_arrMSG.Clear();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -360,6 +360,11 @@ void wxGUIEventLoop::WakeUp()
|
|||||||
|
|
||||||
#else // !wxUSE_GUI
|
#else // !wxUSE_GUI
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// wxConsoleEventLoop implementation
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
#if wxUSE_CONSOLE_EVENTLOOP
|
#if wxUSE_CONSOLE_EVENTLOOP
|
||||||
|
|
||||||
void wxConsoleEventLoop::WakeUp()
|
void wxConsoleEventLoop::WakeUp()
|
||||||
|
@@ -507,7 +507,7 @@ void wxApp::OnQueryEndSession( wxCloseEvent& rEvent )
|
|||||||
//
|
//
|
||||||
// Yield to incoming messages
|
// Yield to incoming messages
|
||||||
//
|
//
|
||||||
bool wxApp::Yield(bool onlyIfNeeded)
|
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||||
{
|
{
|
||||||
if ( m_isInsideYield )
|
if ( m_isInsideYield )
|
||||||
{
|
{
|
||||||
@@ -529,6 +529,7 @@ bool wxApp::Yield(bool onlyIfNeeded)
|
|||||||
wxLog::Suspend();
|
wxLog::Suspend();
|
||||||
|
|
||||||
m_isInsideYield = true;
|
m_isInsideYield = true;
|
||||||
|
m_eventsToProcessInsideYield = eventsToProcess;
|
||||||
|
|
||||||
//
|
//
|
||||||
// We want to go back to the main message loop
|
// We want to go back to the main message loop
|
||||||
@@ -537,6 +538,8 @@ bool wxApp::Yield(bool onlyIfNeeded)
|
|||||||
wxEventLoopGuarantor dummyLoopIfNeeded;
|
wxEventLoopGuarantor dummyLoopIfNeeded;
|
||||||
while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
|
while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
|
||||||
{
|
{
|
||||||
|
// TODO: implement event filtering using the eventsToProcess mask
|
||||||
|
|
||||||
#if wxUSE_THREADS
|
#if wxUSE_THREADS
|
||||||
wxMutexGuiLeaveOrEnter();
|
wxMutexGuiLeaveOrEnter();
|
||||||
#endif // wxUSE_THREADS
|
#endif // wxUSE_THREADS
|
||||||
|
@@ -1119,7 +1119,7 @@ void wxCYield()
|
|||||||
|
|
||||||
// Yield to other processes
|
// Yield to other processes
|
||||||
|
|
||||||
bool wxApp::Yield(bool onlyIfNeeded)
|
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||||
{
|
{
|
||||||
#if wxUSE_THREADS
|
#if wxUSE_THREADS
|
||||||
// Yielding from a non-gui thread needs to bail out, otherwise we end up
|
// Yielding from a non-gui thread needs to bail out, otherwise we end up
|
||||||
@@ -1141,6 +1141,7 @@ bool wxApp::Yield(bool onlyIfNeeded)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_isInsideYield = true;
|
m_isInsideYield = true;
|
||||||
|
m_eventsToProcessInsideYield = eventsToProcess;
|
||||||
|
|
||||||
#if wxUSE_LOG
|
#if wxUSE_LOG
|
||||||
// disable log flushing from here because a call to wxYield() shouldn't
|
// disable log flushing from here because a call to wxYield() shouldn't
|
||||||
|
@@ -287,7 +287,7 @@ int wxApp::GetComCtl32Version()
|
|||||||
|
|
||||||
// Yield to incoming messages
|
// Yield to incoming messages
|
||||||
|
|
||||||
bool wxApp::Yield(bool onlyIfNeeded)
|
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -769,7 +769,7 @@ void wxApp::Exit()
|
|||||||
|
|
||||||
// Yield to other processes
|
// Yield to other processes
|
||||||
|
|
||||||
bool wxApp::Yield(bool onlyIfNeeded)
|
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||||
{
|
{
|
||||||
// Sometimes only 2 yields seem
|
// Sometimes only 2 yields seem
|
||||||
// to do the trick, e.g. in the
|
// to do the trick, e.g. in the
|
||||||
@@ -788,6 +788,7 @@ bool wxApp::Yield(bool onlyIfNeeded)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_isInsideYield = true;
|
m_isInsideYield = true;
|
||||||
|
m_eventsToProcessInsideYield = eventsToProcess;
|
||||||
|
|
||||||
// Make sure we have an event loop object,
|
// Make sure we have an event loop object,
|
||||||
// or Pending/Dispatch will fail
|
// or Pending/Dispatch will fail
|
||||||
@@ -797,6 +798,7 @@ bool wxApp::Yield(bool onlyIfNeeded)
|
|||||||
// can be tested
|
// can be tested
|
||||||
wxTheApp->Dispatch();
|
wxTheApp->Dispatch();
|
||||||
|
|
||||||
|
// TODO: implement event filtering using the eventsToProcess mask
|
||||||
while (wxTheApp && wxTheApp->Pending())
|
while (wxTheApp && wxTheApp->Pending())
|
||||||
wxTheApp->Dispatch();
|
wxTheApp->Dispatch();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user