second part of #10320: move wxApp event handling functions to wxEventLoopBase (in particular move Yield() functions); add backward compatible redirections to wxApp; update docs; remove global lists wxPendingEvents and wxPendingEventsLocker
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58911 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
145bbf1fdf
commit
dde19c2180
@ -261,6 +261,8 @@ Deprecated methods and their replacements
|
||||
- wxDos2UnixFilename, wxUnix2DosFilename, wxStripExtension, wxGetTempFileName,
|
||||
wxExpandPath, wxContractPath, wxRealPath, wxCopyAbsolutePath, wxSplitPath
|
||||
were deprecated in favour of wxFileName methods. See docs for more info.
|
||||
- global wxPendingEvents and wxPendingEventsLocker objects were removed; now you may use
|
||||
wxEventLoopBase::SuspendProcessingOfPendingEvents instead of locking wxPendingEventsLocker.
|
||||
|
||||
Major new features in this release
|
||||
----------------------------------
|
||||
@ -472,6 +474,9 @@ All (GUI):
|
||||
- Added wxIMAGE_OPTION_PNG_FILTER and many wxIMAGE_OPTION_PNG_COMPRESSION_* options
|
||||
to wxImage and wxPNGHandler to allow for custom compression levels when saving PNGs
|
||||
- Added GetValue(), GetRange(), GetMessage() functions to wxProgressDialog
|
||||
- Moved yield functions to wxEventLoopBase and implemented for wxMSW and wxGTK
|
||||
a selective wxEventLoopBase::YieldFor() function.
|
||||
Added also wxEventLoopBase::IsYielding to help cure re-entrancy problems with Yield().
|
||||
|
||||
wxGTK:
|
||||
|
||||
|
119
include/wx/app.h
119
include/wx/app.h
@ -221,6 +221,10 @@ public:
|
||||
// had been already processed or won't be processed at all, respectively
|
||||
virtual int FilterEvent(wxEvent& event);
|
||||
|
||||
// return true if we're running event loop, i.e. if the events can
|
||||
// (already) be dispatched
|
||||
static bool IsMainLoopRunning();
|
||||
|
||||
#if wxUSE_EXCEPTIONS
|
||||
// execute the functor to handle the given event
|
||||
//
|
||||
@ -246,87 +250,34 @@ public:
|
||||
// exit, if you need to really handle the exceptions you need to override
|
||||
// OnExceptionInMainLoop()
|
||||
virtual void OnUnhandledException();
|
||||
#endif // wxUSE_EXCEPTIONS
|
||||
|
||||
// event processing functions
|
||||
// --------------------------
|
||||
|
||||
// return true if we're running event loop, i.e. if the events can
|
||||
// (already) be dispatched
|
||||
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
|
||||
// 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
|
||||
// also called directly.
|
||||
virtual void ProcessPendingEvents();
|
||||
|
||||
// check if there are pending events on global pending event list
|
||||
bool HasPendingEvents() const;
|
||||
|
||||
// make sure that idle events are sent again
|
||||
virtual void WakeUpIdle();
|
||||
|
||||
// execute the main GUI loop, the function returns when the loop ends
|
||||
virtual int MainLoop();
|
||||
|
||||
// exit the main GUI loop during the next iteration (i.e. it does not
|
||||
// stop the program immediately!)
|
||||
virtual void ExitMainLoop();
|
||||
|
||||
// returns true if there are unprocessed events in the event queue
|
||||
virtual bool Pending();
|
||||
|
||||
// process the first event in the event queue (blocks until an event
|
||||
// appears if there are none currently, use Pending() if this is not
|
||||
// wanted), returns false if the event loop should stop and true
|
||||
// otherwise
|
||||
virtual bool Dispatch();
|
||||
|
||||
// this virtual function is called when the application
|
||||
// becomes idle and normally just sends wxIdleEvent to all interested
|
||||
// parties
|
||||
//
|
||||
// it should return true if more idle events are needed, false if not
|
||||
virtual bool ProcessIdle();
|
||||
|
||||
#if wxUSE_EXCEPTIONS
|
||||
// Function called if an uncaught exception is caught inside the main
|
||||
// event loop: it may return true to continue running the event loop or
|
||||
// false to stop it (in the latter case it may rethrow the exception as
|
||||
// well)
|
||||
virtual bool OnExceptionInMainLoop();
|
||||
|
||||
#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
|
||||
// wxEventLoop redirections
|
||||
// ------------------------
|
||||
|
||||
virtual void SuspendProcessingOfPendingEvents();
|
||||
virtual void ResumeProcessingOfPendingEvents();
|
||||
virtual void ProcessPendingEvents();
|
||||
bool HasPendingEvents() const;
|
||||
|
||||
virtual bool Pending();
|
||||
virtual bool Dispatch();
|
||||
|
||||
virtual int MainLoop();
|
||||
virtual void ExitMainLoop();
|
||||
|
||||
bool Yield(bool onlyIfNeeded = false);
|
||||
|
||||
virtual void WakeUpIdle();
|
||||
virtual bool ProcessIdle();
|
||||
|
||||
|
||||
// debugging support
|
||||
@ -395,10 +346,6 @@ protected:
|
||||
// for the first time
|
||||
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
|
||||
static wxAppInitializerFunction ms_appInitFn;
|
||||
|
||||
@ -424,13 +371,6 @@ protected:
|
||||
// been started yet or has already terminated)
|
||||
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_FWD_BASE wxEvtHandler;
|
||||
|
||||
// the application object is a singleton anyhow, there is no sense in
|
||||
@ -496,15 +436,6 @@ public:
|
||||
virtual bool SafeYield(wxWindow *win, bool onlyIfNeeded);
|
||||
virtual bool SafeYieldFor(wxWindow *win, long eventsToProcess);
|
||||
|
||||
// returns true if the main thread is inside a Yield() call
|
||||
virtual bool IsYielding() const
|
||||
{ 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
|
||||
// becomes idle and normally just sends wxIdleEvent to all interested
|
||||
// parties
|
||||
@ -627,10 +558,6 @@ protected:
|
||||
// does any of our windows have focus?
|
||||
bool m_isActive;
|
||||
|
||||
// Yield() helpers:
|
||||
bool m_isInsideYield;
|
||||
long m_eventsToProcessInsideYield;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxAppBase);
|
||||
};
|
||||
|
||||
|
@ -57,7 +57,6 @@ public:
|
||||
// Implement wxAppBase pure virtuals
|
||||
virtual void Exit();
|
||||
|
||||
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||
virtual void WakeUpIdle();
|
||||
|
||||
virtual bool Initialize(int& argc, wxChar **argv);
|
||||
|
@ -26,6 +26,7 @@ public:
|
||||
virtual bool Dispatch();
|
||||
virtual int DispatchTimeout(unsigned long timeout);
|
||||
virtual void WakeUp() { }
|
||||
virtual bool YieldFor(long eventsToProcess);
|
||||
|
||||
protected:
|
||||
int m_exitcode;
|
||||
|
@ -39,8 +39,6 @@ public:
|
||||
private:
|
||||
wxVideoMode m_videoMode;
|
||||
|
||||
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||
|
||||
DECLARE_DYNAMIC_CLASS(wxApp)
|
||||
};
|
||||
|
||||
|
@ -25,14 +25,12 @@ class WXDLLIMPEXP_CORE wxGUIEventLoop : public wxConsoleEventLoop
|
||||
public:
|
||||
wxGUIEventLoop();
|
||||
|
||||
virtual bool YieldFor(long eventsToProcess);
|
||||
|
||||
// returns DirectFB event buffer used by wx
|
||||
static wxIDirectFBEventBufferPtr GetDirectFBEventBuffer();
|
||||
|
||||
private:
|
||||
// wxYield implementation: iterate the loop as long as there are any
|
||||
// pending events
|
||||
void Yield();
|
||||
|
||||
static void InitBuffer();
|
||||
static void CleanUp();
|
||||
|
||||
|
@ -772,7 +772,7 @@ enum wxEventPropagation
|
||||
};
|
||||
|
||||
// The different categories for a wxEvent; see wxEvent::GetEventCategory.
|
||||
// NOTE: they are used as OR-combinable flags by wxApp::Yield
|
||||
// NOTE: they are used as OR-combinable flags by wxEventLoopBase::YieldFor
|
||||
enum wxEventCategory
|
||||
{
|
||||
// this is the category for those events which are generated to update
|
||||
@ -802,10 +802,10 @@ enum wxEventCategory
|
||||
|
||||
// implementation only
|
||||
|
||||
// used in the implementations of DoYield()
|
||||
// used in the implementations of wxEventLoopBase::YieldFor
|
||||
wxEVT_CATEGORY_UNKNOWN = 32,
|
||||
|
||||
// a special category used as an argument to wxApp::Yield() to indicate that
|
||||
// a special category used as an argument to wxEventLoopBase::YieldFor 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,
|
||||
@ -817,7 +817,7 @@ enum wxEventCategory
|
||||
// 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:
|
||||
// used in wxEventLoopBase::YieldFor 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
|
||||
@ -864,7 +864,7 @@ 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
|
||||
// this function is used to selectively process events in wxEventLoopBase::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
|
||||
@ -1120,7 +1120,7 @@ public:
|
||||
return ev;
|
||||
}
|
||||
|
||||
// this is important to avoid that calling wxApp::Yield() thread events
|
||||
// this is important to avoid that calling wxEventLoopBase::YieldFor thread events
|
||||
// gets processed when this is unwanted:
|
||||
virtual wxEventCategory GetEventCategory() const
|
||||
{ return wxEVT_CATEGORY_THREAD; }
|
||||
@ -3985,24 +3985,6 @@ typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&
|
||||
// Thread events
|
||||
#define EVT_THREAD(id, func) wx__DECLARE_EVT1(wxEVT_COMMAND_THREAD, id, wxThreadEventHandler(func))
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Global data
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// list containing event handlers with pending events for them
|
||||
//
|
||||
// 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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -14,6 +14,36 @@
|
||||
|
||||
#include "wx/utils.h"
|
||||
|
||||
|
||||
/*
|
||||
NOTE ABOUT wxEventLoopBase::YieldFor LOGIC
|
||||
------------------------------------------
|
||||
|
||||
The YieldFor() function helps to avoid re-entrancy problems and problems
|
||||
caused by out-of-order event processing
|
||||
(see "wxYield-like problems" and "wxProgressDialog+threading BUG" wx-dev threads).
|
||||
|
||||
The logic behind YieldFor() is simple: it analyzes the queue of the native
|
||||
events generated by the underlying GUI toolkit and picks out and processes
|
||||
only those matching the given mask.
|
||||
|
||||
It's important to note that YieldFor() is used to selectively process the
|
||||
events generated by the NATIVE toolkit.
|
||||
Events syntethized by wxWidgets code or by user code are instead selectively
|
||||
processed thanks to the logic built into wxEvtHandler::ProcessPendingEvents().
|
||||
In fact, when wxEvtHandler::ProcessPendingEvents gets called from inside a
|
||||
YieldFor() call, wxEventLoopBase::IsEventAllowedInsideYield is used to decide
|
||||
if the pending events for that event handler can be processed.
|
||||
If all the pending events associated with that event handler result as "not processable",
|
||||
the event handler "delays" itself calling wxEventLoopBase::DelayPendingEventHandler
|
||||
(so it's moved: m_handlersWithPendingEvents => m_handlersWithPendingDelayedEvents).
|
||||
Last, wxEventLoopBase::ProcessPendingEvents() before exiting moves the delayed
|
||||
event handlers back into the list of handlers with pending events
|
||||
(m_handlersWithPendingDelayedEvents => m_handlersWithPendingEvents) so that
|
||||
a later call to ProcessPendingEvents() (possibly outside the YieldFor() call)
|
||||
will process all pending events as usual.
|
||||
*/
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxEventLoopBase: interface for wxEventLoop
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -22,7 +52,7 @@ class WXDLLIMPEXP_BASE wxEventLoopBase
|
||||
{
|
||||
public:
|
||||
// trivial, but needed (because of wxEventLoopBase) ctor
|
||||
wxEventLoopBase() { }
|
||||
wxEventLoopBase();
|
||||
|
||||
// dtor
|
||||
virtual ~wxEventLoopBase() { }
|
||||
@ -32,9 +62,18 @@ public:
|
||||
virtual bool IsOk() const { return true; }
|
||||
|
||||
|
||||
// dispatch&processing
|
||||
// -------------------
|
||||
|
||||
// start the event loop, return the exit code when it is finished
|
||||
virtual int Run() = 0;
|
||||
|
||||
// is this event loop running now?
|
||||
//
|
||||
// notice that even if this event loop hasn't terminated yet but has just
|
||||
// spawned a nested (e.g. modal) event loop, this would return false
|
||||
bool IsRunning() const;
|
||||
|
||||
// exit from the loop with the given exit code
|
||||
virtual void Exit(int rc = 0) = 0;
|
||||
|
||||
@ -49,6 +88,86 @@ public:
|
||||
// exit the loop or -1 if timeout expired
|
||||
virtual int DispatchTimeout(unsigned long timeout) = 0;
|
||||
|
||||
// implement this to wake up the loop: usually done by posting a dummy event
|
||||
// to it (can be called from non main thread)
|
||||
virtual void WakeUp() = 0;
|
||||
|
||||
|
||||
// pending events
|
||||
// --------------
|
||||
|
||||
// process all events in the wxHandlersWithPendingEvents list -- it is necessary
|
||||
// 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
|
||||
// also called directly.
|
||||
virtual void ProcessPendingEvents();
|
||||
|
||||
// check if there are pending events on global pending event list
|
||||
bool HasPendingEvents() const;
|
||||
|
||||
// temporary suspends processing of the pending events
|
||||
void SuspendProcessingOfPendingEvents();
|
||||
|
||||
// resume processing of the pending events previously stopped because of a
|
||||
// call to SuspendProcessingOfPendingEvents()
|
||||
void ResumeProcessingOfPendingEvents();
|
||||
|
||||
// called by ~wxEvtHandler to (eventually) remove the handler from the list of
|
||||
// the handlers with pending events
|
||||
void RemovePendingEventHandler(wxEvtHandler* toRemove);
|
||||
|
||||
// adds an event handler to the list of the handlers with pending events
|
||||
void AppendPendingEventHandler(wxEvtHandler* toAppend);
|
||||
|
||||
// moves the event handler from the list of the handlers with pending events
|
||||
//to the list of the handlers with _delayed_ pending events
|
||||
void DelayPendingEventHandler(wxEvtHandler* toDelay);
|
||||
|
||||
|
||||
// idle handling
|
||||
// -------------
|
||||
|
||||
// make sure that idle events are sent again
|
||||
virtual void WakeUpIdle();
|
||||
|
||||
// this virtual function is called when the application
|
||||
// becomes idle and normally just sends wxIdleEvent to all interested
|
||||
// parties
|
||||
//
|
||||
// it should return true if more idle events are needed, false if not
|
||||
virtual bool ProcessIdle();
|
||||
|
||||
|
||||
// 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!
|
||||
bool Yield(bool onlyIfNeeded = false);
|
||||
virtual bool YieldFor(long eventsToProcess) = 0;
|
||||
|
||||
// returns true if the main thread is inside a Yield() call
|
||||
virtual bool IsYielding() const
|
||||
{ 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
|
||||
{ return (m_eventsToProcessInsideYield & cat) != 0; }
|
||||
|
||||
// no SafeYield hooks since it uses wxWindow which is not available when wxUSE_GUI=0
|
||||
|
||||
|
||||
// active loop
|
||||
// -----------
|
||||
|
||||
// return currently active (running) event loop, may be NULL
|
||||
static wxEventLoopBase *GetActive() { return ms_activeLoop; }
|
||||
@ -56,15 +175,6 @@ public:
|
||||
// set currently active (running) event loop
|
||||
static void SetActive(wxEventLoopBase* loop) { ms_activeLoop = loop; }
|
||||
|
||||
// is this event loop running now?
|
||||
//
|
||||
// notice that even if this event loop hasn't terminated yet but has just
|
||||
// spawned a nested (e.g. modal) event loop, this would return false
|
||||
bool IsRunning() const;
|
||||
|
||||
// implement this to wake up the loop: usually done by posting a dummy event
|
||||
// to it (can be called from non main thread)
|
||||
virtual void WakeUp() = 0;
|
||||
|
||||
protected:
|
||||
// this function should be called before the event loop terminates, whether
|
||||
@ -72,10 +182,25 @@ protected:
|
||||
// an exception thrown from inside the loop)
|
||||
virtual void OnExit() { }
|
||||
|
||||
|
||||
// the pointer to currently active loop
|
||||
static wxEventLoopBase *ms_activeLoop;
|
||||
|
||||
// the array of the handlers with pending events which needs to be processed
|
||||
// inside ProcessPendingEvents()
|
||||
wxEvtHandlerArray m_handlersWithPendingEvents;
|
||||
|
||||
// helper array used by ProcessPendingEvents()
|
||||
wxEvtHandlerArray m_handlersWithPendingDelayedEvents;
|
||||
|
||||
#if wxUSE_THREADS
|
||||
// this critical section protects both the lists above
|
||||
wxCriticalSection m_handlersWithPendingEventsLocker;
|
||||
#endif
|
||||
|
||||
// Yield() helpers:
|
||||
bool m_isInsideYield;
|
||||
long m_eventsToProcessInsideYield;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxEventLoopBase);
|
||||
};
|
||||
|
||||
@ -161,6 +286,7 @@ public:
|
||||
}
|
||||
}
|
||||
virtual void WakeUp() { }
|
||||
virtual bool YieldFor(long eventsToProcess);
|
||||
|
||||
protected:
|
||||
// the pointer to the port specific implementation class
|
||||
|
@ -78,10 +78,6 @@ public:
|
||||
bool EventsPending();
|
||||
bool DoIdle();
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||
|
||||
private:
|
||||
// true if we're inside an assert modal dialog
|
||||
#ifdef __WXDEBUG__
|
||||
|
@ -26,11 +26,16 @@ public:
|
||||
virtual bool Dispatch();
|
||||
virtual int DispatchTimeout(unsigned long timeout);
|
||||
virtual void WakeUp();
|
||||
virtual bool YieldFor(long eventsToProcess);
|
||||
|
||||
protected:
|
||||
|
||||
// the exit code of this event loop
|
||||
int m_exitcode;
|
||||
|
||||
// used to temporarily store events in DoYield()
|
||||
wxArrayPtrVoid m_arrGdkEvents;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxGUIEventLoop);
|
||||
};
|
||||
|
||||
|
@ -70,8 +70,6 @@ private:
|
||||
bool m_isInAssert;
|
||||
#endif // __WXDEBUG__
|
||||
|
||||
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||
|
||||
DECLARE_DYNAMIC_CLASS(wxApp)
|
||||
};
|
||||
|
||||
|
@ -51,8 +51,6 @@ public:
|
||||
private:
|
||||
DECLARE_DYNAMIC_CLASS(wxApp)
|
||||
|
||||
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||
|
||||
wxVideoMode m_displayMode;
|
||||
};
|
||||
|
||||
|
@ -65,7 +65,6 @@ public:
|
||||
// Implementation
|
||||
virtual bool Initialize(int& argc, wxChar **argv);
|
||||
virtual void CleanUp();
|
||||
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||
|
||||
// Motif-specific
|
||||
WXAppContext GetAppContext() const { return m_appContext; }
|
||||
|
@ -78,8 +78,6 @@ public:
|
||||
protected:
|
||||
int m_printMode; // wxPRINT_WINDOWS, wxPRINT_POSTSCRIPT
|
||||
|
||||
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||
|
||||
public:
|
||||
// unregister any window classes registered by GetRegisteredClassName()
|
||||
static void UnregisterWindowClasses();
|
||||
|
@ -40,6 +40,8 @@ protected:
|
||||
|
||||
#if wxUSE_GUI
|
||||
|
||||
WX_DECLARE_OBJARRAY(MSG, wxMSGArray);
|
||||
|
||||
class WXDLLIMPEXP_CORE wxGUIEventLoop : public wxMSWEventLoopBase
|
||||
{
|
||||
public:
|
||||
@ -72,6 +74,7 @@ public:
|
||||
virtual bool Dispatch();
|
||||
virtual int DispatchTimeout(unsigned long timeout);
|
||||
virtual void WakeUp();
|
||||
virtual bool YieldFor(long eventsToProcess);
|
||||
|
||||
protected:
|
||||
virtual void OnNextIteration();
|
||||
@ -81,6 +84,8 @@ private:
|
||||
// non NULL)
|
||||
static bool IsChildOfCriticalWindow(wxWindowMSW *win);
|
||||
|
||||
// array of messages used for temporary storage by YieldFor()
|
||||
wxMSGArray m_arrMSG;
|
||||
|
||||
// critical window or NULL
|
||||
static wxWindowMSW *ms_winCritical;
|
||||
|
@ -110,8 +110,6 @@ public:
|
||||
// Implementation
|
||||
static bool RegisterWindowClasses(HAB vHab);
|
||||
|
||||
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||
|
||||
public:
|
||||
int m_nCmdShow;
|
||||
HMQ m_hMq;
|
||||
|
@ -66,7 +66,6 @@ public:
|
||||
// Implementation
|
||||
virtual bool Initialize(int& argc, wxChar **argv);
|
||||
virtual void CleanUp();
|
||||
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||
|
||||
// the installed application event handler
|
||||
WXEVENTHANDLERREF MacGetEventHandler() { return m_macEventHandler ; }
|
||||
|
@ -26,6 +26,7 @@ public:
|
||||
virtual int DispatchTimeout(unsigned long timeout);
|
||||
|
||||
virtual void WakeUp();
|
||||
virtual bool YieldFor(long eventsToProcess);
|
||||
|
||||
private:
|
||||
// dispatch an event and release it
|
||||
|
@ -22,6 +22,7 @@ public:
|
||||
virtual int DispatchTimeout(unsigned long timeout);
|
||||
|
||||
virtual void WakeUp();
|
||||
virtual bool YieldFor(long eventsToProcess);
|
||||
|
||||
private:
|
||||
double m_sleepTime;
|
||||
|
@ -51,8 +51,6 @@ public:
|
||||
protected:
|
||||
int m_printMode; // wxPRINT_WINDOWS, wxPRINT_POSTSCRIPT
|
||||
|
||||
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||
|
||||
public:
|
||||
// Implementation
|
||||
static bool RegisterWindowClasses();
|
||||
|
@ -28,6 +28,7 @@ public:
|
||||
virtual bool Dispatch();
|
||||
virtual int DispatchTimeout(unsigned long timeout);
|
||||
virtual bool IsRunning() const;
|
||||
virtual bool YieldFor(long eventsToProcess);
|
||||
|
||||
// MSW-specific methods
|
||||
// --------------------
|
||||
|
@ -37,6 +37,7 @@ public:
|
||||
virtual int DispatchTimeout(unsigned long timeout);
|
||||
virtual void WakeUp();
|
||||
virtual bool IsOk() const { return m_dispatcher != NULL; }
|
||||
virtual bool YieldFor(long WXUNUSED(eventsToProcess)) { return true; }
|
||||
|
||||
protected:
|
||||
virtual void OnNextIteration();
|
||||
|
@ -63,7 +63,6 @@ public:
|
||||
// Implementation
|
||||
virtual bool Initialize(int& argc, wxChar **argv);
|
||||
virtual void CleanUp();
|
||||
virtual bool DoYield(bool onlyIfNeeded, long eventsToProcess);
|
||||
|
||||
WXWindow GetTopLevelWidget() const { return m_topLevelWidget; }
|
||||
WXColormap GetMainColormap(WXDisplay* display);
|
||||
|
@ -57,31 +57,26 @@ public:
|
||||
|
||||
/**
|
||||
@name Event-handling
|
||||
|
||||
Note that you should look at wxEvtLoopBase for more event-processing
|
||||
documentation.
|
||||
*/
|
||||
//@{
|
||||
|
||||
/**
|
||||
Dispatches the next event in the windowing system event queue.
|
||||
Blocks until an event appears if there are none currently
|
||||
(use Pending() if this is not wanted).
|
||||
Called by wxWidgets on creation of the application. Override this if you wish
|
||||
to provide your own (environment-dependent) main loop.
|
||||
|
||||
This can be used for programming event loops, e.g.
|
||||
|
||||
@code
|
||||
while (app.Pending())
|
||||
Dispatch();
|
||||
@endcode
|
||||
|
||||
@return @false if the event loop should stop and @true otherwise.
|
||||
|
||||
@see Pending(), wxEventLoopBase
|
||||
@return 0 under X, and the wParam of the WM_QUIT message under Windows.
|
||||
*/
|
||||
virtual bool Dispatch();
|
||||
virtual int MainLoop();
|
||||
|
||||
/**
|
||||
Call this to explicitly exit the main message (event) loop.
|
||||
You should normally exit the main loop (and the application) by deleting
|
||||
the top window.
|
||||
|
||||
This function simply calls wxEvtLoopBase::Exit() on the active loop.
|
||||
*/
|
||||
virtual void ExitMainLoop();
|
||||
|
||||
@ -108,81 +103,6 @@ public:
|
||||
wxEventFunction func,
|
||||
wxEvent& event) const;
|
||||
|
||||
/**
|
||||
Returns @true if called from inside Yield().
|
||||
*/
|
||||
virtual bool IsYielding() const;
|
||||
|
||||
/**
|
||||
Process all pending events; it is necessary 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 also called directly.
|
||||
*/
|
||||
virtual void ProcessPendingEvents();
|
||||
|
||||
/**
|
||||
Called by wxWidgets on creation of the application. Override this if you wish
|
||||
to provide your own (environment-dependent) main loop.
|
||||
|
||||
@return 0 under X, and the wParam of the WM_QUIT message under Windows.
|
||||
*/
|
||||
virtual int MainLoop();
|
||||
|
||||
/**
|
||||
Returns @true if unprocessed events are in the window system event queue.
|
||||
|
||||
@see Dispatch()
|
||||
*/
|
||||
virtual bool Pending();
|
||||
|
||||
/**
|
||||
Yields control to pending messages in the windowing system.
|
||||
|
||||
This can be useful, for example, when a time-consuming process writes to a
|
||||
text window. Without an occasional yield, the text window will not be updated
|
||||
properly, and on systems with cooperative multitasking, such as Windows 3.1
|
||||
other processes will not respond.
|
||||
|
||||
Caution should be exercised, however, since yielding may allow the
|
||||
user to perform actions which are not compatible with the current task.
|
||||
Disabling menu items or whole menus during processing can avoid unwanted
|
||||
reentrance of code: see ::wxSafeYield for a better function.
|
||||
You can avoid unwanted reentrancies also using IsYielding().
|
||||
|
||||
Note that Yield() will not flush the message logs. This is intentional as
|
||||
calling Yield() is usually done to quickly update the screen and popping up
|
||||
a message box dialog may be undesirable. If you do wish to flush the log
|
||||
messages immediately (otherwise it will be done during the next idle loop
|
||||
iteration), call wxLog::FlushActive.
|
||||
|
||||
Calling Yield() recursively is normally an error and an assert failure is
|
||||
raised in debug build if such situation is detected. However if the
|
||||
@a onlyIfNeeded parameter is @true, the method will just silently
|
||||
return @false instead.
|
||||
*/
|
||||
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;
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
|
@ -23,7 +23,7 @@ enum wxEventPropagation
|
||||
/**
|
||||
The different categories for a wxEvent; see wxEvent::GetEventCategory.
|
||||
|
||||
@note They are used as OR-combinable flags by wxApp::Yield.
|
||||
@note They are used as OR-combinable flags by wxEventLoopBase::YieldFor.
|
||||
*/
|
||||
enum wxEventCategory
|
||||
{
|
||||
@ -58,8 +58,8 @@ enum wxEventCategory
|
||||
wxEVT_CATEGORY_THREAD = 16,
|
||||
|
||||
/**
|
||||
This mask is used in wxApp::Yield to specify that all event categories should
|
||||
be processed.
|
||||
This mask is used in wxEventLoopBase::YieldFor to specify that all event
|
||||
categories should be processed.
|
||||
*/
|
||||
wxEVT_CATEGORY_ALL =
|
||||
wxEVT_CATEGORY_UI|wxEVT_CATEGORY_USER_INPUT|wxEVT_CATEGORY_SOCKET| \
|
||||
@ -148,7 +148,7 @@ public:
|
||||
/**
|
||||
Returns a generic category for this event.
|
||||
|
||||
This function is used to selectively process events in wxApp::Yield.
|
||||
This function is used to selectively process events in wxEventLoopBase::YieldFor.
|
||||
*/
|
||||
virtual wxEventCategory GetEventCategory() const;
|
||||
|
||||
@ -2537,7 +2537,7 @@ public:
|
||||
@library{wxcore}
|
||||
@category{events}
|
||||
|
||||
@see @ref overview_thread, wxApp::YieldFor
|
||||
@see @ref overview_thread, wxEventLoopBase::YieldFor
|
||||
*/
|
||||
class wxThreadEvent : public wxCommandEvent
|
||||
{
|
||||
@ -2558,7 +2558,7 @@ public:
|
||||
Returns @c wxEVT_CATEGORY_THREAD.
|
||||
|
||||
This is important to avoid unwanted processing of thread events
|
||||
when calling wxApp::YieldFor().
|
||||
when calling wxEventLoopBase::YieldFor().
|
||||
*/
|
||||
virtual wxEventCategory GetEventCategory() const;
|
||||
};
|
||||
|
@ -18,7 +18,7 @@
|
||||
@library{wxbase}
|
||||
@category{appmanagement}
|
||||
|
||||
@see wxApp
|
||||
@see wxApp, wxEventLoopActivator
|
||||
*/
|
||||
class wxEventLoopBase
|
||||
{
|
||||
@ -42,10 +42,9 @@ public:
|
||||
|
||||
|
||||
/**
|
||||
Use this to check whether the event loop was successfully created
|
||||
before using it
|
||||
*/
|
||||
virtual bool IsOk() const;
|
||||
@name Dispatch and processing
|
||||
*/
|
||||
//@{
|
||||
|
||||
/**
|
||||
Start the event loop, return the exit code when it is finished.
|
||||
@ -60,6 +59,21 @@ public:
|
||||
*/
|
||||
virtual int Run() = 0;
|
||||
|
||||
/**
|
||||
Return true if this event loop is currently running.
|
||||
|
||||
Notice that even if this event loop hasn't terminated yet but has just
|
||||
spawned a nested (e.g. modal) event loop, this method would return
|
||||
@false.
|
||||
*/
|
||||
bool IsRunning() const;
|
||||
|
||||
/**
|
||||
Use this to check whether the event loop was successfully created
|
||||
before using it
|
||||
*/
|
||||
virtual bool IsOk() const;
|
||||
|
||||
/**
|
||||
Exit from the loop with the given exit code.
|
||||
*/
|
||||
@ -73,13 +87,21 @@ public:
|
||||
virtual bool Pending() const = 0;
|
||||
|
||||
/**
|
||||
Dispatch a single event.
|
||||
Dispatches the next event in the windowing system event queue.
|
||||
Blocks until an event appears if there are none currently
|
||||
(use Pending() if this is not wanted).
|
||||
|
||||
If there are currently no events in the queue, blocks until an event
|
||||
becomes available.
|
||||
This can be used for programming event loops, e.g.
|
||||
|
||||
@return @false only if the event loop should terminate.
|
||||
*/
|
||||
@code
|
||||
while (evtloop->Pending())
|
||||
evtloop->Dispatch();
|
||||
@endcode
|
||||
|
||||
@return @false if the event loop should stop and @true otherwise.
|
||||
|
||||
@see Pending(), wxEventLoopBase
|
||||
*/
|
||||
virtual bool Dispatch() = 0;
|
||||
|
||||
/**
|
||||
@ -100,21 +122,139 @@ public:
|
||||
*/
|
||||
virtual int DispatchTimeout(unsigned long timeout) = 0;
|
||||
|
||||
/**
|
||||
Return true if this event loop is currently running.
|
||||
|
||||
Notice that even if this event loop hasn't terminated yet but has just
|
||||
spawned a nested (e.g. modal) event loop, this method would return
|
||||
@false.
|
||||
*/
|
||||
bool IsRunning() const;
|
||||
|
||||
/**
|
||||
Called by wxWidgets to wake up the event loop even if it is currently
|
||||
blocked inside Dispatch().
|
||||
*/
|
||||
virtual void WakeUp() = 0;
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
/**
|
||||
@name Pending events
|
||||
*/
|
||||
//@{
|
||||
|
||||
/**
|
||||
Process all pending events; it is necessary to call this function to
|
||||
process posted events.
|
||||
|
||||
This happens during each event loop iteration in GUI mode but
|
||||
it may be also called directly.
|
||||
*/
|
||||
virtual void ProcessPendingEvents();
|
||||
|
||||
/**
|
||||
Returns @true if there are pending events on the internal pending event list.
|
||||
*/
|
||||
bool HasPendingEvents() const;
|
||||
|
||||
/**
|
||||
Temporary suspends processing of the pending events.
|
||||
|
||||
@see ResumeProcessingOfPendingEvents()
|
||||
*/
|
||||
void SuspendProcessingOfPendingEvents();
|
||||
|
||||
/**
|
||||
Resume processing of the pending events previously stopped because of a
|
||||
call to SuspendProcessingOfPendingEvents().
|
||||
*/
|
||||
void ResumeProcessingOfPendingEvents();
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
/**
|
||||
@name Idle handling
|
||||
*/
|
||||
//@{
|
||||
|
||||
/**
|
||||
Makes sure that idle events are sent again.
|
||||
*/
|
||||
virtual void WakeUpIdle();
|
||||
|
||||
/**
|
||||
This virtual function is called when the application becomes idle and
|
||||
normally just sends wxIdleEvent to all interested parties.
|
||||
|
||||
It should return @true if more idle events are needed, @false if not.
|
||||
*/
|
||||
virtual bool ProcessIdle();
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
/**
|
||||
@name Yield-related hooks
|
||||
*/
|
||||
//@{
|
||||
|
||||
/**
|
||||
Returns @true if called from inside Yield().
|
||||
*/
|
||||
virtual bool IsYielding() const;
|
||||
|
||||
/**
|
||||
Yields control to pending messages in the windowing system.
|
||||
|
||||
This can be useful, for example, when a time-consuming process writes to a
|
||||
text window. Without an occasional yield, the text window will not be updated
|
||||
properly, and on systems with cooperative multitasking, such as Windows 3.1
|
||||
other processes will not respond.
|
||||
|
||||
Caution should be exercised, however, since yielding may allow the
|
||||
user to perform actions which are not compatible with the current task.
|
||||
Disabling menu items or whole menus during processing can avoid unwanted
|
||||
reentrance of code: see ::wxSafeYield for a better function.
|
||||
You can avoid unwanted reentrancies also using IsYielding().
|
||||
|
||||
Note that Yield() will not flush the message logs. This is intentional as
|
||||
calling Yield() is usually done to quickly update the screen and popping up
|
||||
a message box dialog may be undesirable. If you do wish to flush the log
|
||||
messages immediately (otherwise it will be done during the next idle loop
|
||||
iteration), call wxLog::FlushActive.
|
||||
|
||||
Calling Yield() recursively is normally an error and an assert failure is
|
||||
raised in debug build if such situation is detected. However if the
|
||||
@a onlyIfNeeded parameter is @true, the method will just silently
|
||||
return @false instead.
|
||||
*/
|
||||
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 will be processed; i.e. this method
|
||||
helps to avoid unwanted reentrancies.
|
||||
|
||||
Note that currently only wxMSW and wxGTK do support selective yield of
|
||||
native events coming from the underlying GUI toolkit.
|
||||
wxWidgets events posted using wxEvtHandler::AddPendingEvent or
|
||||
wxEvtHandler::QueueEvent are instead selectively processed by all ports.
|
||||
|
||||
@see wxEvent::GetEventCategory
|
||||
*/
|
||||
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()).
|
||||
|
||||
@see wxEvent::GetEventCategory
|
||||
*/
|
||||
virtual bool IsEventAllowedInsideYield(wxEventCategory cat) const;
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
This function is called before the event loop terminates, whether this
|
||||
|
@ -162,11 +162,6 @@ bool wxAppConsoleBase::Initialize(int& WXUNUSED(argc), wxChar **argv)
|
||||
GetTraits()->SetLocale();
|
||||
#endif // wxUSE_INTL
|
||||
|
||||
#if wxUSE_THREADS
|
||||
wxHandlersWithPendingEventsLocker = new wxCriticalSection;
|
||||
wxHandlersWithPendingDelayedEvents = new wxList;
|
||||
#endif
|
||||
|
||||
#ifndef __WXPALMOS__
|
||||
if ( m_appName.empty() && argv && argv[0] )
|
||||
{
|
||||
@ -190,17 +185,6 @@ void wxAppConsoleBase::CleanUp()
|
||||
delete m_mainLoop;
|
||||
m_mainLoop = NULL;
|
||||
}
|
||||
|
||||
delete wxHandlersWithPendingEvents;
|
||||
wxHandlersWithPendingEvents = NULL;
|
||||
|
||||
delete wxHandlersWithPendingDelayedEvents;
|
||||
wxHandlersWithPendingDelayedEvents = NULL;
|
||||
|
||||
#if wxUSE_THREADS
|
||||
delete wxHandlersWithPendingEventsLocker;
|
||||
wxHandlersWithPendingEventsLocker = NULL;
|
||||
#endif // wxUSE_THREADS
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -291,7 +275,7 @@ wxAppTraits *wxAppConsoleBase::GetTraitsIfExists()
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// event processing
|
||||
// wxEventLoop redirection
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int wxAppConsoleBase::MainLoop()
|
||||
@ -331,81 +315,37 @@ bool wxAppConsoleBase::Dispatch()
|
||||
|
||||
bool wxAppConsoleBase::HasPendingEvents() const
|
||||
{
|
||||
wxENTER_CRIT_SECT( *wxHandlersWithPendingEventsLocker );
|
||||
wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
|
||||
|
||||
bool has = wxHandlersWithPendingEvents && !wxHandlersWithPendingEvents->IsEmpty();
|
||||
|
||||
wxLEAVE_CRIT_SECT( *wxHandlersWithPendingEventsLocker );
|
||||
|
||||
return has;
|
||||
return loop && loop->HasPendingEvents();
|
||||
}
|
||||
|
||||
void wxAppConsoleBase::SuspendProcessingOfPendingEvents()
|
||||
{
|
||||
wxENTER_CRIT_SECT( *wxHandlersWithPendingEventsLocker );
|
||||
wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
|
||||
|
||||
if (loop) loop->SuspendProcessingOfPendingEvents();
|
||||
}
|
||||
|
||||
void wxAppConsoleBase::ResumeProcessingOfPendingEvents()
|
||||
{
|
||||
wxLEAVE_CRIT_SECT( *wxHandlersWithPendingEventsLocker );
|
||||
}
|
||||
wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
|
||||
|
||||
/* static */
|
||||
bool wxAppConsoleBase::IsMainLoopRunning()
|
||||
{
|
||||
const wxAppConsole * const app = GetInstance();
|
||||
|
||||
return app && app->m_mainLoop != NULL;
|
||||
if (loop) loop->ResumeProcessingOfPendingEvents();
|
||||
}
|
||||
|
||||
void wxAppConsoleBase::ProcessPendingEvents()
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
if ( !wxHandlersWithPendingEventsLocker )
|
||||
return;
|
||||
#endif
|
||||
wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
|
||||
|
||||
wxENTER_CRIT_SECT( *wxHandlersWithPendingEventsLocker );
|
||||
if (loop) loop->ProcessPendingEvents();
|
||||
}
|
||||
|
||||
wxCHECK_RET( wxHandlersWithPendingDelayedEvents->IsEmpty(),
|
||||
"this helper list should be empty" );
|
||||
bool wxAppConsoleBase::Yield(bool onlyIfNeeded)
|
||||
{
|
||||
wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
|
||||
|
||||
if (wxHandlersWithPendingEvents)
|
||||
{
|
||||
// iterate until the list becomes empty: the handlers remove themselves
|
||||
// from it when they don't have any more pending events
|
||||
wxList::compatibility_iterator node = wxHandlersWithPendingEvents->GetFirst();
|
||||
while (node)
|
||||
{
|
||||
// In ProcessPendingEvents(), new handlers might be added
|
||||
// and we can safely leave the critical section here.
|
||||
wxLEAVE_CRIT_SECT( *wxHandlersWithPendingEventsLocker );
|
||||
|
||||
wxEvtHandler *handler = (wxEvtHandler *)node->GetData();
|
||||
handler->ProcessPendingEvents();
|
||||
|
||||
wxENTER_CRIT_SECT( *wxHandlersWithPendingEventsLocker );
|
||||
|
||||
// restart as the iterators could have been invalidated
|
||||
node = wxHandlersWithPendingEvents->GetFirst();
|
||||
}
|
||||
}
|
||||
|
||||
// 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 );
|
||||
return loop && loop->Yield(onlyIfNeeded);
|
||||
}
|
||||
|
||||
void wxAppConsoleBase::WakeUpIdle()
|
||||
@ -416,14 +356,21 @@ void wxAppConsoleBase::WakeUpIdle()
|
||||
|
||||
bool wxAppConsoleBase::ProcessIdle()
|
||||
{
|
||||
// process pending wx events before sending idle events
|
||||
ProcessPendingEvents();
|
||||
wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
|
||||
|
||||
wxIdleEvent event;
|
||||
return loop && loop->ProcessIdle();
|
||||
}
|
||||
|
||||
event.SetEventObject(this);
|
||||
ProcessEvent(event);
|
||||
return event.MoreRequested();
|
||||
// ----------------------------------------------------------------------------
|
||||
// events
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* static */
|
||||
bool wxAppConsoleBase::IsMainLoopRunning()
|
||||
{
|
||||
const wxAppConsole * const app = GetInstance();
|
||||
|
||||
return app && app->m_mainLoop != NULL;
|
||||
}
|
||||
|
||||
int wxAppConsoleBase::FilterEvent(wxEvent& WXUNUSED(event))
|
||||
@ -603,7 +550,6 @@ bool wxAppConsoleBase::CheckBuildOptions(const char *optionsSignature,
|
||||
// normally wxLogFatalError doesn't return
|
||||
return false;
|
||||
}
|
||||
#undef wxCMP
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "wx/msgout.h"
|
||||
#include "wx/thread.h"
|
||||
#include "wx/vidmode.h"
|
||||
#include "wx/evtloop.h"
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
#if wxUSE_STACKWALKER
|
||||
@ -78,9 +79,6 @@ wxAppBase::wxAppBase()
|
||||
|
||||
m_isActive = true;
|
||||
|
||||
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
|
||||
// OnInit() -- but this is what would happen if we set m_exitOnFrameDelete
|
||||
// to Yes initially as this dialog would be the last top level window.
|
||||
@ -326,23 +324,22 @@ void wxAppBase::SetActive(bool active, wxWindow * WXUNUSED(lastFocus))
|
||||
(void)ProcessEvent(event);
|
||||
}
|
||||
|
||||
bool wxAppBase::IsEventAllowedInsideYield(wxEventCategory cat) const
|
||||
{
|
||||
return (m_eventsToProcessInsideYield & cat) != 0;
|
||||
}
|
||||
|
||||
bool wxAppBase::SafeYield(wxWindow *win, bool onlyIfNeeded)
|
||||
{
|
||||
wxWindowDisabler wd(win);
|
||||
|
||||
return Yield(onlyIfNeeded);
|
||||
wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
|
||||
|
||||
return loop && loop->Yield(onlyIfNeeded);
|
||||
}
|
||||
|
||||
bool wxAppBase::SafeYieldFor(wxWindow *win, long eventsToProcess)
|
||||
{
|
||||
wxWindowDisabler wd(win);
|
||||
|
||||
return YieldFor(eventsToProcess);
|
||||
wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
|
||||
|
||||
return loop && loop->YieldFor(eventsToProcess);
|
||||
}
|
||||
|
||||
|
||||
|
@ -145,16 +145,6 @@ IMPLEMENT_DYNAMIC_CLASS(wxEventTableEntryModule, wxModule)
|
||||
// global variables
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// List containing event handlers with pending events (each handler can occur
|
||||
// at most once here)
|
||||
wxList *wxHandlersWithPendingEvents = NULL;
|
||||
wxList *wxHandlersWithPendingDelayedEvents = NULL;
|
||||
|
||||
#if wxUSE_THREADS
|
||||
// protects wxHandlersWithPendingEvents list
|
||||
wxCriticalSection *wxHandlersWithPendingEventsLocker = NULL;
|
||||
#endif
|
||||
|
||||
// common event types are defined here, other event types are defined by the
|
||||
// components which use them
|
||||
|
||||
@ -1037,10 +1027,6 @@ void wxEventHashTable::GrowEventTypeTable()
|
||||
// wxEvtHandler
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Event handler
|
||||
*/
|
||||
|
||||
wxEvtHandler::wxEvtHandler()
|
||||
{
|
||||
m_nextHandler = NULL;
|
||||
@ -1085,41 +1071,16 @@ wxEvtHandler::~wxEvtHandler()
|
||||
delete entry;
|
||||
}
|
||||
delete m_dynamicEvents;
|
||||
};
|
||||
}
|
||||
|
||||
if (m_pendingEvents)
|
||||
m_pendingEvents->DeleteContents(true);
|
||||
delete m_pendingEvents;
|
||||
|
||||
// Remove us from wxHandlersWithPendingEvents if necessary.
|
||||
if ( wxHandlersWithPendingEvents )
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
if (wxHandlersWithPendingEventsLocker)
|
||||
wxENTER_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
|
||||
#endif
|
||||
|
||||
if ( wxHandlersWithPendingEvents->DeleteObject(this) )
|
||||
{
|
||||
// check that we were present only once in the list
|
||||
wxASSERT_MSG( !wxHandlersWithPendingEvents->Find(this),
|
||||
"Handler occurs twice in wxHandlersWithPendingEvents list" );
|
||||
}
|
||||
//else: we weren't in this list at all, it's ok
|
||||
|
||||
if ( 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 (wxHandlersWithPendingEventsLocker)
|
||||
wxLEAVE_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
|
||||
#endif
|
||||
}
|
||||
// Remove us from the list of the pending events if necessary.
|
||||
wxEventLoopBase *loop = wxEventLoopBase::GetActive();
|
||||
if (loop)
|
||||
loop->RemovePendingEventHandler(this);
|
||||
|
||||
// we only delete object data, not untyped
|
||||
if ( m_clientDataType == wxClientData_Object )
|
||||
@ -1165,6 +1126,15 @@ void wxEvtHandler::QueueEvent(wxEvent *event)
|
||||
{
|
||||
wxCHECK_RET( event, "NULL event can't be posted" );
|
||||
|
||||
wxEventLoopBase* loop = wxEventLoopBase::GetActive();
|
||||
if (!loop)
|
||||
{
|
||||
// we need an event loop which manages the list of event handlers with
|
||||
// pending events... cannot proceed without it!
|
||||
wxLogDebug("No event loop is running!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 1) Add this event to our list of pending events
|
||||
wxENTER_CRIT_SECT( m_pendingEventsLock );
|
||||
|
||||
@ -1176,14 +1146,7 @@ void wxEvtHandler::QueueEvent(wxEvent *event)
|
||||
// 2) Add this event handler to list of event handlers that
|
||||
// have pending events.
|
||||
|
||||
wxENTER_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
|
||||
|
||||
if ( !wxHandlersWithPendingEvents )
|
||||
wxHandlersWithPendingEvents = new wxList;
|
||||
if ( !wxHandlersWithPendingEvents->Find(this) )
|
||||
wxHandlersWithPendingEvents->Append(this);
|
||||
|
||||
wxLEAVE_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
|
||||
loop->AppendPendingEventHandler(this);
|
||||
|
||||
// only release m_pendingEventsLock now because otherwise there is a race
|
||||
// condition as described in the ticket #9093: we could process the event
|
||||
@ -1200,6 +1163,15 @@ void wxEvtHandler::QueueEvent(wxEvent *event)
|
||||
|
||||
void wxEvtHandler::ProcessPendingEvents()
|
||||
{
|
||||
wxEventLoopBase* loop = wxEventLoopBase::GetActive();
|
||||
if (!loop)
|
||||
{
|
||||
// we need an event loop which manages the list of event handlers with
|
||||
// pending events... cannot proceed without it!
|
||||
wxLogDebug("No event loop is running!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 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)
|
||||
@ -1215,9 +1187,10 @@ void wxEvtHandler::ProcessPendingEvents()
|
||||
wxEvent* pEvent = static_cast<wxEvent *>(node->GetData());
|
||||
|
||||
// find the first event which can be processed now:
|
||||
if (wxTheApp && wxTheApp->IsYielding())
|
||||
wxEventLoopBase* evtLoop = wxEventLoopBase::GetActive();
|
||||
if (evtLoop && evtLoop->IsYielding())
|
||||
{
|
||||
while (node && pEvent && !wxTheApp->IsEventAllowedInsideYield(pEvent->GetEventCategory()))
|
||||
while (node && pEvent && !evtLoop->IsEventAllowedInsideYield(pEvent->GetEventCategory()))
|
||||
{
|
||||
node = node->GetNext();
|
||||
pEvent = node ? static_cast<wxEvent *>(node->GetData()) : NULL;
|
||||
@ -1226,19 +1199,11 @@ void wxEvtHandler::ProcessPendingEvents()
|
||||
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
|
||||
loop->DelayPendingEventHandler(this);
|
||||
|
||||
// see the comment at the beginning of evtloop.h header for the
|
||||
// logic behind YieldFor() and behind DelayPendingEventHandler()
|
||||
|
||||
wxLEAVE_CRIT_SECT( m_pendingEventsLock );
|
||||
|
||||
return;
|
||||
@ -1252,19 +1217,11 @@ void wxEvtHandler::ProcessPendingEvents()
|
||||
// same event again.
|
||||
m_pendingEvents->Erase(node);
|
||||
|
||||
// if there are no more pending events left, we don't need to stay in this
|
||||
// list
|
||||
if ( m_pendingEvents->IsEmpty() )
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
if (wxHandlersWithPendingEventsLocker)
|
||||
wxENTER_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
|
||||
#endif
|
||||
wxHandlersWithPendingEvents->DeleteObject(this);
|
||||
#if wxUSE_THREADS
|
||||
if (wxHandlersWithPendingEventsLocker)
|
||||
wxLEAVE_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
|
||||
#endif
|
||||
// if there are no more pending events left, we don't need to
|
||||
// stay in this list
|
||||
loop->RemovePendingEventHandler(this);
|
||||
}
|
||||
|
||||
wxLEAVE_CRIT_SECT( m_pendingEventsLock );
|
||||
|
@ -36,6 +36,154 @@
|
||||
|
||||
wxEventLoopBase *wxEventLoopBase::ms_activeLoop = NULL;
|
||||
|
||||
wxEventLoopBase::wxEventLoopBase()
|
||||
{
|
||||
m_isInsideYield = false;
|
||||
m_eventsToProcessInsideYield = wxEVT_CATEGORY_ALL;
|
||||
}
|
||||
|
||||
void wxEventLoopBase::DelayPendingEventHandler(wxEvtHandler* toDelay)
|
||||
{
|
||||
wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||
|
||||
// move the handler from the list of handlers with processable pending events
|
||||
// to the list of handlers with pending events which needs to be processed later
|
||||
m_handlersWithPendingEvents.Remove(toDelay);
|
||||
|
||||
if (m_handlersWithPendingDelayedEvents.Index(toDelay) == wxNOT_FOUND)
|
||||
m_handlersWithPendingDelayedEvents.Add(toDelay);
|
||||
|
||||
wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||
}
|
||||
|
||||
void wxEventLoopBase::RemovePendingEventHandler(wxEvtHandler* toRemove)
|
||||
{
|
||||
wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||
|
||||
if (m_handlersWithPendingEvents.Index(toRemove) != wxNOT_FOUND)
|
||||
{
|
||||
m_handlersWithPendingEvents.Remove(toRemove);
|
||||
|
||||
// check that the handler was present only once in the list
|
||||
wxASSERT_MSG( m_handlersWithPendingEvents.Index(toRemove) == wxNOT_FOUND,
|
||||
"Handler occurs twice in the m_handlersWithPendingEvents list!" );
|
||||
}
|
||||
//else: it wasn't in this list at all, it's ok
|
||||
|
||||
if (m_handlersWithPendingDelayedEvents.Index(toRemove) != wxNOT_FOUND)
|
||||
{
|
||||
m_handlersWithPendingDelayedEvents.Remove(toRemove);
|
||||
|
||||
// check that the handler was present only once in the list
|
||||
wxASSERT_MSG( m_handlersWithPendingDelayedEvents.Index(toRemove) == wxNOT_FOUND,
|
||||
"Handler occurs twice in m_handlersWithPendingDelayedEvents list!" );
|
||||
}
|
||||
//else: it wasn't in this list at all, it's ok
|
||||
|
||||
wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||
}
|
||||
|
||||
void wxEventLoopBase::AppendPendingEventHandler(wxEvtHandler* toAppend)
|
||||
{
|
||||
wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||
|
||||
if ( m_handlersWithPendingEvents.Index(toAppend) == wxNOT_FOUND )
|
||||
m_handlersWithPendingEvents.Add(toAppend);
|
||||
|
||||
wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||
}
|
||||
|
||||
bool wxEventLoopBase::HasPendingEvents() const
|
||||
{
|
||||
wxENTER_CRIT_SECT(const_cast<wxEventLoopBase*>(this)->m_handlersWithPendingEventsLocker);
|
||||
|
||||
bool has = !m_handlersWithPendingEvents.IsEmpty();
|
||||
|
||||
wxLEAVE_CRIT_SECT(const_cast<wxEventLoopBase*>(this)->m_handlersWithPendingEventsLocker);
|
||||
|
||||
return has;
|
||||
}
|
||||
|
||||
void wxEventLoopBase::SuspendProcessingOfPendingEvents()
|
||||
{
|
||||
wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||
}
|
||||
|
||||
void wxEventLoopBase::ResumeProcessingOfPendingEvents()
|
||||
{
|
||||
wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||
}
|
||||
|
||||
void wxEventLoopBase::ProcessPendingEvents()
|
||||
{
|
||||
wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||
|
||||
wxCHECK_RET( m_handlersWithPendingDelayedEvents.IsEmpty(),
|
||||
"this helper list should be empty" );
|
||||
|
||||
// iterate until the list becomes empty: the handlers remove themselves
|
||||
// from it when they don't have any more pending events
|
||||
while (!m_handlersWithPendingEvents.IsEmpty())
|
||||
{
|
||||
// In ProcessPendingEvents(), new handlers might be added
|
||||
// and we can safely leave the critical section here.
|
||||
wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||
|
||||
// NOTE: we always call ProcessPendingEvents() on the first event handler
|
||||
// with pending events because handlers auto-remove themselves
|
||||
// from this list (see RemovePendingEventHandler) if they have no
|
||||
// more pending events.
|
||||
m_handlersWithPendingEvents[0]->ProcessPendingEvents();
|
||||
|
||||
wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||
}
|
||||
|
||||
// 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 (!m_handlersWithPendingDelayedEvents.IsEmpty())
|
||||
{
|
||||
WX_APPEND_ARRAY(m_handlersWithPendingEvents, m_handlersWithPendingDelayedEvents);
|
||||
m_handlersWithPendingDelayedEvents.Clear();
|
||||
}
|
||||
|
||||
wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||
}
|
||||
|
||||
void wxEventLoopBase::WakeUpIdle()
|
||||
{
|
||||
WakeUp();
|
||||
}
|
||||
|
||||
bool wxEventLoopBase::ProcessIdle()
|
||||
{
|
||||
// process pending wx events before sending idle events
|
||||
ProcessPendingEvents();
|
||||
|
||||
wxIdleEvent event;
|
||||
|
||||
event.SetEventObject(wxTheApp);
|
||||
wxTheApp->ProcessEvent(event);
|
||||
return event.MoreRequested();
|
||||
}
|
||||
|
||||
bool wxEventLoopBase::Yield(bool onlyIfNeeded)
|
||||
{
|
||||
if ( m_isInsideYield )
|
||||
{
|
||||
if ( !onlyIfNeeded )
|
||||
{
|
||||
wxFAIL_MSG( wxT("wxYield called recursively" ) );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return YieldFor(wxEVT_CATEGORY_ALL);
|
||||
}
|
||||
|
||||
// wxEventLoopManual is unused in the other ports
|
||||
#if defined(__WXMSW__) || defined(__WXMAC__) || defined(__WXDFB__) || (defined(__UNIX__) && wxUSE_BASE)
|
||||
|
||||
|
@ -162,46 +162,3 @@ void wxApp::WakeUpIdle()
|
||||
wxMutexGuiLeave();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
if ( !wxThread::IsMain() )
|
||||
return true; // can't process events from other threads
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
if ( m_isInsideYield )
|
||||
{
|
||||
if ( !onlyIfNeeded )
|
||||
{
|
||||
wxFAIL_MSG( wxT("wxYield called recursively" ) );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_isInsideYield = true;
|
||||
m_eventsToProcessInsideYield = eventsToProcess;
|
||||
|
||||
#if wxUSE_LOG
|
||||
wxLog::Suspend();
|
||||
#endif // wxUSE_LOG
|
||||
|
||||
wxEventLoop * const
|
||||
loop = static_cast<wxEventLoop *>(wxEventLoop::GetActive());
|
||||
if ( loop )
|
||||
loop->Yield();
|
||||
|
||||
// it's necessary to call ProcessIdle() to update the frames sizes which
|
||||
// might have been changed (it also will update other things set from
|
||||
// OnUpdateUI() which is a nice (and desired) side effect)
|
||||
while ( ProcessIdle() ) {}
|
||||
|
||||
#if wxUSE_LOG
|
||||
wxLog::Resume();
|
||||
#endif // wxUSE_LOG
|
||||
|
||||
m_isInsideYield = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -202,8 +202,20 @@ wxIDirectFBEventBufferPtr wxGUIEventLoop::GetDirectFBEventBuffer()
|
||||
// events dispatch and loop handling
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void wxGUIEventLoop::Yield()
|
||||
bool wxGUIEventLoop::YieldFor(long eventsToProcess)
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
if ( !wxThread::IsMain() )
|
||||
return true; // can't process events from other threads
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
m_isInsideYield = true;
|
||||
m_eventsToProcessInsideYield = eventsToProcess;
|
||||
|
||||
#if wxUSE_LOG
|
||||
wxLog::Suspend();
|
||||
#endif // wxUSE_LOG
|
||||
|
||||
// TODO: implement event filtering using the eventsToProcess mask
|
||||
|
||||
// process all pending events:
|
||||
@ -212,4 +224,17 @@ void wxGUIEventLoop::Yield()
|
||||
|
||||
// handle timers, sockets etc.
|
||||
OnNextIteration();
|
||||
|
||||
// it's necessary to call ProcessIdle() to update the frames sizes which
|
||||
// might have been changed (it also will update other things set from
|
||||
// OnUpdateUI() which is a nice (and desired) side effect)
|
||||
while ( ProcessIdle() ) {}
|
||||
|
||||
#if wxUSE_LOG
|
||||
wxLog::Resume();
|
||||
#endif // wxUSE_LOG
|
||||
|
||||
m_isInsideYield = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -42,6 +42,7 @@
|
||||
#endif
|
||||
|
||||
#include "wx/progdlg.h"
|
||||
#include "wx/evtloop.h"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// macros
|
||||
@ -402,7 +403,7 @@ wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip)
|
||||
m_msg->SetLabel(_("Done."));
|
||||
}
|
||||
|
||||
wxTheApp->YieldFor(wxEVT_CATEGORY_UI);
|
||||
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI);
|
||||
|
||||
(void)ShowModal();
|
||||
}
|
||||
@ -452,7 +453,7 @@ bool wxProgressDialog::DoAfterUpdate(bool *skip)
|
||||
{
|
||||
// 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
|
||||
wxTheApp->YieldFor(wxEVT_CATEGORY_UI|wxEVT_CATEGORY_USER_INPUT);
|
||||
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI|wxEVT_CATEGORY_USER_INPUT);
|
||||
|
||||
Update();
|
||||
|
||||
@ -671,7 +672,7 @@ void wxProgressDialog::UpdateMessage(const wxString &newmsg)
|
||||
|
||||
Fit(); // adapt to the new label size
|
||||
|
||||
wxTheApp->YieldFor(wxEVT_CATEGORY_UI);
|
||||
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI);
|
||||
}
|
||||
}
|
||||
|
||||
|
171
src/gtk/app.cpp
171
src/gtk/app.cpp
@ -44,167 +44,6 @@
|
||||
wxFORCE_LINK_MODULE(gnome_vfs)
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// global data
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static GtkWidget *gs_RootWindow = NULL;
|
||||
static wxArrayPtrVoid g_arrGdkEvents;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxYield
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||
{
|
||||
if ( m_isInsideYield )
|
||||
{
|
||||
if ( !onlyIfNeeded )
|
||||
{
|
||||
wxFAIL_MSG( wxT("wxYield called recursively" ) );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if wxUSE_THREADS
|
||||
if ( !wxThread::IsMain() )
|
||||
{
|
||||
// can't call gtk_main_iteration() from other threads like this
|
||||
return true;
|
||||
}
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
m_isInsideYield = true;
|
||||
m_eventsToProcessInsideYield = eventsToProcess;
|
||||
|
||||
#if wxUSE_LOG
|
||||
// disable log flushing from here because a call to wxYield() shouldn't
|
||||
// normally result in message boxes popping up &c
|
||||
wxLog::Suspend();
|
||||
#endif
|
||||
|
||||
// NOTE: gtk_main_iteration() doesn't allow us to filter events, so we
|
||||
// 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
|
||||
// might have been changed (it also will update other things set from
|
||||
// OnUpdateUI() which is a nice (and desired) side effect). But we
|
||||
// call ProcessIdle() only once since this is not meant for longish
|
||||
// background jobs (controlled by wxIdleEvent::RequestMore() and the
|
||||
// return value of 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
|
||||
// let the logs be flashed again
|
||||
wxLog::Resume();
|
||||
#endif
|
||||
|
||||
m_isInsideYield = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// local functions
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -324,12 +163,14 @@ bool wxApp::DoIdle()
|
||||
|
||||
GtkWidget* wxGetRootWindow()
|
||||
{
|
||||
if (gs_RootWindow == NULL)
|
||||
static GtkWidget *s_RootWindow = NULL;
|
||||
|
||||
if (s_RootWindow == NULL)
|
||||
{
|
||||
gs_RootWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL );
|
||||
gtk_widget_realize( gs_RootWindow );
|
||||
s_RootWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL );
|
||||
gtk_widget_realize( s_RootWindow );
|
||||
}
|
||||
return gs_RootWindow;
|
||||
return s_RootWindow;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "wx/scopedarray.h"
|
||||
#include "wx/scopeguard.h"
|
||||
#include "wx/evtloop.h"
|
||||
|
||||
#include "wx/gtk/private.h"
|
||||
|
||||
@ -75,7 +76,7 @@ public:
|
||||
~wxClipboardSync()
|
||||
{
|
||||
while (ms_clipboard)
|
||||
wxTheApp->YieldFor(wxEVT_CATEGORY_CLIPBOARD);
|
||||
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_CLIPBOARD);
|
||||
}
|
||||
|
||||
// this method must be called by GTK+ callbacks to indicate that we got the
|
||||
|
@ -36,6 +36,8 @@
|
||||
// wxEventLoop implementation
|
||||
// ============================================================================
|
||||
|
||||
extern GtkWidget *wxGetRootWindow();
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxEventLoop running and exiting
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -126,4 +128,146 @@ int wxGUIEventLoop::DispatchTimeout(unsigned long timeout)
|
||||
return !quit;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// YieldFor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool wxGUIEventLoop::YieldFor(long eventsToProcess)
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
if ( !wxThread::IsMain() )
|
||||
{
|
||||
// can't call gtk_main_iteration() from other threads like this
|
||||
return true;
|
||||
}
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
m_isInsideYield = true;
|
||||
m_eventsToProcessInsideYield = eventsToProcess;
|
||||
|
||||
#if wxUSE_LOG
|
||||
// disable log flushing from here because a call to wxYield() shouldn't
|
||||
// normally result in message boxes popping up &c
|
||||
wxLog::Suspend();
|
||||
#endif
|
||||
|
||||
// NOTE: gtk_main_iteration() doesn't allow us to filter events, so we
|
||||
// rather use gtk_main_do_event() after filtering the events at
|
||||
// GDK level
|
||||
|
||||
GdkDisplay* disp = gtk_widget_get_display(wxGetRootWindow());
|
||||
|
||||
// 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
|
||||
m_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
|
||||
// might have been changed (it also will update other things set from
|
||||
// OnUpdateUI() which is a nice (and desired) side effect). But we
|
||||
// call ProcessIdle() only once since this is not meant for longish
|
||||
// background jobs (controlled by wxIdleEvent::RequestMore() and the
|
||||
// return value of 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<m_arrGdkEvents.GetCount(); i++)
|
||||
{
|
||||
GdkEvent* ev = (GdkEvent*)m_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);
|
||||
}
|
||||
|
||||
m_arrGdkEvents.Clear();
|
||||
|
||||
#if wxUSE_LOG
|
||||
// let the logs be flashed again
|
||||
wxLog::Resume();
|
||||
#endif
|
||||
|
||||
m_isInsideYield = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -99,64 +99,6 @@ void wxapp_install_idle_handler();
|
||||
static wxMutex gs_idleTagsMutex;
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxYield
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||
{
|
||||
if ( m_isInsideYield )
|
||||
{
|
||||
if ( !onlyIfNeeded )
|
||||
{
|
||||
wxFAIL_MSG( wxT("wxYield called recursively" ) );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if wxUSE_THREADS
|
||||
if ( !wxThread::IsMain() )
|
||||
{
|
||||
// can't call gtk_main_iteration() from other threads like this
|
||||
return true;
|
||||
}
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
m_isInsideYield = true;
|
||||
m_eventsToProcessInsideYield = eventsToProcess;
|
||||
|
||||
// We need to remove idle callbacks or the loop will
|
||||
// never finish.
|
||||
wxTheApp->RemoveIdleTag();
|
||||
|
||||
#if wxUSE_LOG
|
||||
// disable log flushing from here because a call to wxYield() shouldn't
|
||||
// normally result in message boxes popping up &c
|
||||
wxLog::Suspend();
|
||||
#endif
|
||||
|
||||
// TODO: implement event filtering using the eventsToProcess mask
|
||||
while (gtk_events_pending())
|
||||
gtk_main_iteration();
|
||||
|
||||
// It's necessary to call ProcessIdle() to update the frames sizes which
|
||||
// might have been changed (it also will update other things set from
|
||||
// OnUpdateUI() which is a nice (and desired) side effect). But we
|
||||
// call ProcessIdle() only once since this is not meant for longish
|
||||
// background jobs (controlled by wxIdleEvent::RequestMore() and the
|
||||
// return value of Processidle().
|
||||
ProcessIdle();
|
||||
|
||||
#if wxUSE_LOG
|
||||
// let the logs be flashed again
|
||||
wxLog::Resume();
|
||||
#endif
|
||||
|
||||
m_isInsideYield = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxWakeUpIdle
|
||||
|
@ -117,3 +117,52 @@ bool wxGUIEventLoop::Dispatch()
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxYield
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool wxGUIEventLoop::YieldFor(long eventsToProcess)
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
if ( !wxThread::IsMain() )
|
||||
{
|
||||
// can't call gtk_main_iteration() from other threads like this
|
||||
return true;
|
||||
}
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
m_isInsideYield = true;
|
||||
m_eventsToProcessInsideYield = eventsToProcess;
|
||||
|
||||
// We need to remove idle callbacks or the loop will
|
||||
// never finish.
|
||||
wxTheApp->RemoveIdleTag();
|
||||
|
||||
#if wxUSE_LOG
|
||||
// disable log flushing from here because a call to wxYield() shouldn't
|
||||
// normally result in message boxes popping up &c
|
||||
wxLog::Suspend();
|
||||
#endif
|
||||
|
||||
// TODO: implement event filtering using the eventsToProcess mask
|
||||
while (gtk_events_pending())
|
||||
gtk_main_iteration();
|
||||
|
||||
// It's necessary to call ProcessIdle() to update the frames sizes which
|
||||
// might have been changed (it also will update other things set from
|
||||
// OnUpdateUI() which is a nice (and desired) side effect). But we
|
||||
// call ProcessIdle() only once since this is not meant for longish
|
||||
// background jobs (controlled by wxIdleEvent::RequestMore() and the
|
||||
// return value of Processidle().
|
||||
ProcessIdle();
|
||||
|
||||
#if wxUSE_LOG
|
||||
// let the logs be flashed again
|
||||
wxLog::Resume();
|
||||
#endif
|
||||
|
||||
m_isInsideYield = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -44,56 +44,6 @@ void wxApp::Exit()
|
||||
exit(0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxYield
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||
{
|
||||
if ( m_isInsideYield )
|
||||
{
|
||||
if ( !onlyIfNeeded )
|
||||
{
|
||||
wxFAIL_MSG( wxT("wxYield called recursively" ) );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if wxUSE_THREADS
|
||||
if ( !wxThread::IsMain() )
|
||||
{
|
||||
// can't process events from other threads, MGL is thread-unsafe
|
||||
return true;
|
||||
}
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
m_isInsideYield = true;
|
||||
m_eventsToProcessInsideYield = eventsToProcess;
|
||||
|
||||
wxLog::Suspend();
|
||||
|
||||
wxEventLoopBase * const eventLoop = wxEventLoop::GetActive();
|
||||
if ( eventLoop )
|
||||
{
|
||||
// TODO: implement event filtering using the eventsToProcess mask
|
||||
|
||||
while (eventLoop->Pending())
|
||||
eventLoop->Dispatch();
|
||||
}
|
||||
|
||||
/* it's necessary to call ProcessIdle() to update the frames sizes which
|
||||
might have been changed (it also will update other things set from
|
||||
OnUpdateUI() which is a nice (and desired) side effect) */
|
||||
while (wxTheApp->ProcessIdle()) { }
|
||||
|
||||
wxLog::Resume();
|
||||
|
||||
m_isInsideYield = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxWakeUpIdle
|
||||
|
@ -184,3 +184,39 @@ bool wxGUIEventLoop::Dispatch()
|
||||
return m_impl->GetKeepLooping();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// wxYield
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool wxGUIEventLoop::YieldFor(long eventsToProcess)
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
if ( !wxThread::IsMain() )
|
||||
{
|
||||
// can't process events from other threads, MGL is thread-unsafe
|
||||
return true;
|
||||
}
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
m_isInsideYield = true;
|
||||
m_eventsToProcessInsideYield = eventsToProcess;
|
||||
|
||||
wxLog::Suspend();
|
||||
|
||||
// TODO: implement event filtering using the eventsToProcess mask
|
||||
|
||||
while (Pending())
|
||||
Dispatch();
|
||||
|
||||
/* it's necessary to call ProcessIdle() to update the frames sizes which
|
||||
might have been changed (it also will update other things set from
|
||||
OnUpdateUI() which is a nice (and desired) side effect) */
|
||||
while (wxTheApp->ProcessIdle()) { }
|
||||
|
||||
wxLog::Resume();
|
||||
|
||||
m_isInsideYield = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -468,32 +468,6 @@ void wxApp::SetTopLevelRealizedWidget(WXDisplay* display, WXWidget widget)
|
||||
.m_topLevelRealizedWidget = (Widget)widget;
|
||||
}
|
||||
|
||||
// Yield to other processes
|
||||
|
||||
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||
{
|
||||
if ( m_isInsideYield )
|
||||
{
|
||||
if ( !onlyIfNeeded )
|
||||
{
|
||||
wxFAIL_MSG( wxT("wxYield called recursively" ) );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_isInsideYield = true;
|
||||
m_eventsToProcessInsideYield = eventsToProcess;
|
||||
|
||||
wxEventLoopGuarantor dummyLoopIfNeeded;
|
||||
while (wxTheApp && wxTheApp->Pending())
|
||||
// TODO: implement event filtering using the eventsToProcess mask
|
||||
wxTheApp->Dispatch();
|
||||
|
||||
m_isInsideYield = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// accessors for C modules
|
||||
|
@ -137,6 +137,20 @@ void wxGUIEventLoop::Exit(int rc)
|
||||
::wxBreakDispatch();
|
||||
}
|
||||
|
||||
bool wxGUIEventLoop::YieldFor(ong eventsToProcess)
|
||||
{
|
||||
m_isInsideYield = true;
|
||||
m_eventsToProcessInsideYield = eventsToProcess;
|
||||
|
||||
while (wxTheApp && wxTheApp->Pending())
|
||||
// TODO: implement event filtering using the eventsToProcess mask
|
||||
wxTheApp->Dispatch();
|
||||
|
||||
m_isInsideYield = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxEventLoop message processing dispatching
|
||||
// ----------------------------------------------------------------------------
|
||||
|
171
src/msw/app.cpp
171
src/msw/app.cpp
@ -1011,177 +1011,6 @@ int wxApp::GetShell32Version()
|
||||
|
||||
#endif // !__WXWINCE__
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Yield to incoming messages
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
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 ( !onlyIfNeeded )
|
||||
{
|
||||
wxFAIL_MSG( wxT("wxYield called recursively" ) );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// set the flag and don't forget to reset it before returning
|
||||
m_isInsideYield = true;
|
||||
m_eventsToProcessInsideYield = eventsToProcess;
|
||||
|
||||
wxON_BLOCK_EXIT_SET(m_isInsideYield, false);
|
||||
|
||||
#if wxUSE_LOG
|
||||
// disable log flushing from here because a call to wxYield() shouldn't
|
||||
// normally result in message boxes popping up &c
|
||||
wxLog::Suspend();
|
||||
|
||||
// ensure the logs will be flashed again when we exit
|
||||
wxON_BLOCK_EXIT0(wxLog::Resume);
|
||||
#endif // wxUSE_LOG
|
||||
|
||||
// we don't want to process WM_QUIT from here - it should be processed in
|
||||
// the main event loop in order to stop it
|
||||
wxEventLoopGuarantor dummyLoopIfNeeded;
|
||||
MSG msg;
|
||||
while ( PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) &&
|
||||
msg.message != WM_QUIT )
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
wxMutexGuiLeaveOrEnter();
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
if (msg.message == WM_PAINT)
|
||||
{
|
||||
// WM_PAINT messages are the last ones of the queue...
|
||||
break;
|
||||
}
|
||||
|
||||
// choose a wxEventCategory for this Windows message
|
||||
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_KEYDOWN:
|
||||
case WM_KEYUP:
|
||||
case WM_CHAR:
|
||||
case WM_DEADCHAR:
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_SYSKEYUP:
|
||||
case WM_SYSCHAR:
|
||||
case WM_SYSDEADCHAR:
|
||||
#ifdef WM_UNICHAR
|
||||
case WM_UNICHAR:
|
||||
#endif
|
||||
case WM_HOTKEY:
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
case WM_IME_ENDCOMPOSITION:
|
||||
case WM_IME_COMPOSITION:
|
||||
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:
|
||||
#ifdef WM_NCMOUSELEAVE
|
||||
case WM_NCMOUSELEAVE:
|
||||
#endif
|
||||
case WM_MOUSELEAVE:
|
||||
|
||||
case WM_CUT:
|
||||
case WM_COPY:
|
||||
case WM_PASTE:
|
||||
case WM_CLEAR:
|
||||
case WM_UNDO:
|
||||
|
||||
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_MOUSEWHEEL:
|
||||
cat = wxEVT_CATEGORY_USER_INPUT;
|
||||
break;
|
||||
|
||||
case WM_TIMER:
|
||||
cat = wxEVT_CATEGORY_TIMER;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (msg.message < WM_USER)
|
||||
{
|
||||
// 0;WM_USER-1 is the range of message IDs reserved for use
|
||||
// by the system.
|
||||
|
||||
// there are too many of these types of messages to handle
|
||||
// them in this switch
|
||||
cat = wxEVT_CATEGORY_UI;
|
||||
}
|
||||
else
|
||||
cat = wxEVT_CATEGORY_UNKNOWN;
|
||||
}
|
||||
|
||||
// should we process this event now?
|
||||
if (cat & eventsToProcess)
|
||||
{
|
||||
if ( !wxTheApp->Dispatch() )
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove the message and store it
|
||||
::GetMessage(&msg, NULL, 0, 0);
|
||||
g_arrMSG.Add(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// if there are pending events, we must process them.
|
||||
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;
|
||||
}
|
||||
|
||||
#if wxUSE_EXCEPTIONS
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "wx/thread.h"
|
||||
#include "wx/except.h"
|
||||
#include "wx/msw/private.h"
|
||||
#include "wx/scopeguard.h"
|
||||
|
||||
#if wxUSE_GUI
|
||||
#include "wx/tooltip.h"
|
||||
@ -358,6 +359,164 @@ void wxGUIEventLoop::WakeUp()
|
||||
::PostMessage(NULL, WM_NULL, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Yield to incoming messages
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include <wx/arrimpl.cpp>
|
||||
WX_DEFINE_OBJARRAY(wxMSGArray);
|
||||
|
||||
bool wxGUIEventLoop::YieldFor(long eventsToProcess)
|
||||
{
|
||||
// set the flag and don't forget to reset it before returning
|
||||
m_isInsideYield = true;
|
||||
m_eventsToProcessInsideYield = eventsToProcess;
|
||||
|
||||
wxON_BLOCK_EXIT_SET(m_isInsideYield, false);
|
||||
|
||||
#if wxUSE_LOG
|
||||
// disable log flushing from here because a call to wxYield() shouldn't
|
||||
// normally result in message boxes popping up &c
|
||||
wxLog::Suspend();
|
||||
|
||||
// ensure the logs will be flashed again when we exit
|
||||
wxON_BLOCK_EXIT0(wxLog::Resume);
|
||||
#endif // wxUSE_LOG
|
||||
|
||||
// we don't want to process WM_QUIT from here - it should be processed in
|
||||
// the main event loop in order to stop it
|
||||
MSG msg;
|
||||
while ( PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) &&
|
||||
msg.message != WM_QUIT )
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
wxMutexGuiLeaveOrEnter();
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
if (msg.message == WM_PAINT)
|
||||
{
|
||||
// WM_PAINT messages are the last ones of the queue...
|
||||
break;
|
||||
}
|
||||
|
||||
// choose a wxEventCategory for this Windows message
|
||||
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_KEYDOWN:
|
||||
case WM_KEYUP:
|
||||
case WM_CHAR:
|
||||
case WM_DEADCHAR:
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_SYSKEYUP:
|
||||
case WM_SYSCHAR:
|
||||
case WM_SYSDEADCHAR:
|
||||
#ifdef WM_UNICHAR
|
||||
case WM_UNICHAR:
|
||||
#endif
|
||||
case WM_HOTKEY:
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
case WM_IME_ENDCOMPOSITION:
|
||||
case WM_IME_COMPOSITION:
|
||||
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:
|
||||
#ifdef WM_NCMOUSELEAVE
|
||||
case WM_NCMOUSELEAVE:
|
||||
#endif
|
||||
case WM_MOUSELEAVE:
|
||||
|
||||
case WM_CUT:
|
||||
case WM_COPY:
|
||||
case WM_PASTE:
|
||||
case WM_CLEAR:
|
||||
case WM_UNDO:
|
||||
|
||||
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_MOUSEWHEEL:
|
||||
cat = wxEVT_CATEGORY_USER_INPUT;
|
||||
break;
|
||||
|
||||
case WM_TIMER:
|
||||
cat = wxEVT_CATEGORY_TIMER;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (msg.message < WM_USER)
|
||||
{
|
||||
// 0;WM_USER-1 is the range of message IDs reserved for use
|
||||
// by the system.
|
||||
|
||||
// there are too many of these types of messages to handle
|
||||
// them in this switch
|
||||
cat = wxEVT_CATEGORY_UI;
|
||||
}
|
||||
else
|
||||
cat = wxEVT_CATEGORY_UNKNOWN;
|
||||
}
|
||||
|
||||
// should we process this event now?
|
||||
if (cat & eventsToProcess)
|
||||
{
|
||||
if ( !wxTheApp->Dispatch() )
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove the message and store it
|
||||
::GetMessage(&msg, NULL, 0, 0);
|
||||
m_arrMSG.Add(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// if there are pending events, we must process them.
|
||||
ProcessPendingEvents();
|
||||
|
||||
// put back unprocessed events in the queue
|
||||
DWORD id = GetCurrentThreadId();
|
||||
for (size_t i=0; i<m_arrMSG.GetCount(); i++)
|
||||
{
|
||||
PostThreadMessage(id, m_arrMSG[i].message,
|
||||
m_arrMSG[i].wParam, m_arrMSG[i].lParam);
|
||||
}
|
||||
|
||||
m_arrMSG.Clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#else // !wxUSE_GUI
|
||||
|
||||
|
||||
|
@ -504,66 +504,6 @@ void wxApp::OnQueryEndSession( wxCloseEvent& rEvent )
|
||||
}
|
||||
} // end of wxApp::OnQueryEndSession
|
||||
|
||||
//
|
||||
// Yield to incoming messages
|
||||
//
|
||||
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||
{
|
||||
if ( m_isInsideYield )
|
||||
{
|
||||
if ( !onlyIfNeeded )
|
||||
{
|
||||
wxFAIL_MSG( _T("wxYield() called recursively") );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
HAB vHab = 0;
|
||||
QMSG vMsg;
|
||||
|
||||
//
|
||||
// Disable log flushing from here because a call to wxYield() shouldn't
|
||||
// normally result in message boxes popping up &c
|
||||
//
|
||||
wxLog::Suspend();
|
||||
|
||||
m_isInsideYield = true;
|
||||
m_eventsToProcessInsideYield = eventsToProcess;
|
||||
|
||||
//
|
||||
// We want to go back to the main message loop
|
||||
// if we see a WM_QUIT. (?)
|
||||
//
|
||||
wxEventLoopGuarantor dummyLoopIfNeeded;
|
||||
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
|
||||
wxMutexGuiLeaveOrEnter();
|
||||
#endif // wxUSE_THREADS
|
||||
if (!wxTheApp->Dispatch())
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// If they are pending events, we must process them.
|
||||
//
|
||||
if (wxTheApp)
|
||||
wxTheApp->ProcessPendingEvents();
|
||||
|
||||
HandleSockets();
|
||||
|
||||
//
|
||||
// Let the logs be flashed again
|
||||
//
|
||||
wxLog::Resume();
|
||||
m_isInsideYield = false;
|
||||
|
||||
return true;
|
||||
} // end of wxYield
|
||||
|
||||
int wxApp::AddSocketHandler(int handle, int mask,
|
||||
void (*callback)(void*), void * gsock)
|
||||
{
|
||||
|
@ -365,3 +365,52 @@ bool wxGUIEventLoop::Dispatch()
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Yield to incoming messages
|
||||
//
|
||||
bool wxGUIEventLoop::YieldFor(long eventsToProcess)
|
||||
{
|
||||
HAB vHab = 0;
|
||||
QMSG vMsg;
|
||||
|
||||
//
|
||||
// Disable log flushing from here because a call to wxYield() shouldn't
|
||||
// normally result in message boxes popping up &c
|
||||
//
|
||||
wxLog::Suspend();
|
||||
|
||||
m_isInsideYield = true;
|
||||
m_eventsToProcessInsideYield = eventsToProcess;
|
||||
|
||||
//
|
||||
// We want to go back to the main message loop
|
||||
// if we see a 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
|
||||
wxMutexGuiLeaveOrEnter();
|
||||
#endif // wxUSE_THREADS
|
||||
if (!wxTheApp->Dispatch())
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// If they are pending events, we must process them.
|
||||
//
|
||||
if (wxTheApp)
|
||||
wxTheApp->ProcessPendingEvents();
|
||||
|
||||
HandleSockets();
|
||||
|
||||
//
|
||||
// Let the logs be flashed again
|
||||
//
|
||||
wxLog::Resume();
|
||||
m_isInsideYield = false;
|
||||
|
||||
return true;
|
||||
} // end of wxYield
|
||||
|
@ -285,13 +285,6 @@ int wxApp::GetComCtl32Version()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Yield to incoming messages
|
||||
|
||||
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#if wxUSE_EXCEPTIONS
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -144,3 +144,8 @@ void wxGUIEventLoop::WakeUp()
|
||||
return;
|
||||
}
|
||||
|
||||
bool wxGUIEventLoop::YieldFor(long eventsToProcess)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -767,52 +767,6 @@ void wxApp::Exit()
|
||||
wxAppConsole::Exit();
|
||||
}
|
||||
|
||||
// Yield to other processes
|
||||
|
||||
bool wxApp::DoYield(bool onlyIfNeeded, long eventsToProcess)
|
||||
{
|
||||
// Sometimes only 2 yields seem
|
||||
// to do the trick, e.g. in the
|
||||
// progress dialog
|
||||
int i;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if ( m_isInsideYield )
|
||||
{
|
||||
if ( !onlyIfNeeded )
|
||||
{
|
||||
wxFAIL_MSG( wxT("wxYield called recursively" ) );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_isInsideYield = true;
|
||||
m_eventsToProcessInsideYield = eventsToProcess;
|
||||
|
||||
// Make sure we have an event loop object,
|
||||
// or Pending/Dispatch will fail
|
||||
wxEventLoopGuarantor dummyLoopIfNeeded;
|
||||
|
||||
// Call dispatch at least once so that sockets
|
||||
// can be tested
|
||||
wxTheApp->Dispatch();
|
||||
|
||||
// TODO: implement event filtering using the eventsToProcess mask
|
||||
while (wxTheApp && wxTheApp->Pending())
|
||||
wxTheApp->Dispatch();
|
||||
|
||||
#if wxUSE_TIMER
|
||||
wxGenericTimerImpl::NotifyTimers();
|
||||
#endif
|
||||
ProcessIdle();
|
||||
|
||||
m_isInsideYield = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
|
||||
void wxApp::OnAssert(const wxChar *file, int line, const wxChar* cond, const wxChar *msg)
|
||||
|
@ -243,3 +243,33 @@ bool wxGUIEventLoop::Dispatch()
|
||||
(void) m_impl->ProcessEvent( &event );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxGUIEventLoop::YieldFor(long eventsToProcess)
|
||||
{
|
||||
// Sometimes only 2 yields seem
|
||||
// to do the trick, e.g. in the
|
||||
// progress dialog
|
||||
int i;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
m_isInsideYield = true;
|
||||
m_eventsToProcessInsideYield = eventsToProcess;
|
||||
|
||||
// Call dispatch at least once so that sockets
|
||||
// can be tested
|
||||
wxTheApp->Dispatch();
|
||||
|
||||
// TODO: implement event filtering using the eventsToProcess mask
|
||||
while (wxTheApp && wxTheApp->Pending())
|
||||
wxTheApp->Dispatch();
|
||||
|
||||
#if wxUSE_TIMER
|
||||
wxGenericTimerImpl::NotifyTimers();
|
||||
#endif
|
||||
ProcessIdle();
|
||||
|
||||
m_isInsideYield = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user