Add wxEventFilter and related functionality.
Allow defining event filters to globally pre-process all application events without having to override wxApp::FilterEvent(). git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@69794 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -359,6 +359,7 @@ ALL_BASE_HEADERS = \
|
||||
wx/dynload.h \
|
||||
wx/encconv.h \
|
||||
wx/event.h \
|
||||
wx/eventfilter.h \
|
||||
wx/evtloop.h \
|
||||
wx/except.h \
|
||||
wx/features.h \
|
||||
@@ -537,6 +538,7 @@ ALL_PORTS_BASE_HEADERS = \
|
||||
wx/dynload.h \
|
||||
wx/encconv.h \
|
||||
wx/event.h \
|
||||
wx/eventfilter.h \
|
||||
wx/evtloop.h \
|
||||
wx/except.h \
|
||||
wx/features.h \
|
||||
|
@@ -447,6 +447,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
|
||||
wx/dynload.h
|
||||
wx/encconv.h
|
||||
wx/event.h
|
||||
wx/eventfilter.h
|
||||
wx/evtloop.h
|
||||
wx/except.h
|
||||
wx/features.h
|
||||
|
@@ -1231,6 +1231,10 @@ SOURCE=..\..\include\wx\event.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\wx\eventfilter.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\wx\evtloop.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@@ -1347,6 +1347,9 @@
|
||||
<File
|
||||
RelativePath="..\..\include\wx\event.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\wx\eventfilter.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\wx\evtloop.h">
|
||||
</File>
|
||||
|
@@ -1817,6 +1817,10 @@
|
||||
RelativePath="..\..\include\wx\event.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\wx\eventfilter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\wx\evtloop.h"
|
||||
>
|
||||
|
@@ -1813,6 +1813,10 @@
|
||||
RelativePath="..\..\include\wx\event.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\wx\eventfilter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\wx\evtloop.h"
|
||||
>
|
||||
|
@@ -457,6 +457,7 @@ All:
|
||||
|
||||
- Fix parsing of negated long options in wxCmdLineParser (roed_bis).
|
||||
- Fix crash in wxArray::insert() overload taking iterator range (wsu).
|
||||
- Added wxEventFilter class and wxEvtHandler::{Add,Remove}Filter().
|
||||
|
||||
All (GUI):
|
||||
|
||||
|
@@ -18,6 +18,7 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "wx/event.h" // for the base class
|
||||
#include "wx/eventfilter.h" // (and another one)
|
||||
#include "wx/build.h"
|
||||
#include "wx/cmdargs.h" // for wxCmdLineArgsArray used by wxApp::argv
|
||||
#include "wx/init.h" // we must declare wxEntry()
|
||||
@@ -70,7 +71,8 @@ extern WXDLLIMPEXP_DATA_BASE(wxList) wxPendingDelete;
|
||||
// wxAppConsoleBase: wxApp for non-GUI applications
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class WXDLLIMPEXP_BASE wxAppConsoleBase : public wxEvtHandler
|
||||
class WXDLLIMPEXP_BASE wxAppConsoleBase : public wxEvtHandler,
|
||||
public wxEventFilter
|
||||
{
|
||||
public:
|
||||
// ctor and dtor
|
||||
@@ -238,13 +240,8 @@ public:
|
||||
// event processing functions
|
||||
// --------------------------
|
||||
|
||||
// this method allows to filter all the events processed by the program, so
|
||||
// you should try to return quickly from it to avoid slowing down the
|
||||
// program to the crawl
|
||||
//
|
||||
// return value should be -1 to continue with the normal event processing,
|
||||
// or TRUE or FALSE to stop further processing and pretend that the event
|
||||
// had been already processed or won't be processed at all, respectively
|
||||
// Implement the inherited wxEventFilter method but just return -1 from it
|
||||
// to indicate that default processing should take place.
|
||||
virtual int FilterEvent(wxEvent& event);
|
||||
|
||||
// return true if we're running event loop, i.e. if the events can
|
||||
|
@@ -39,6 +39,7 @@
|
||||
|
||||
class WXDLLIMPEXP_FWD_BASE wxList;
|
||||
class WXDLLIMPEXP_FWD_BASE wxEvent;
|
||||
class WXDLLIMPEXP_FWD_BASE wxEventFilter;
|
||||
#if wxUSE_GUI
|
||||
class WXDLLIMPEXP_FWD_CORE wxDC;
|
||||
class WXDLLIMPEXP_FWD_CORE wxMenu;
|
||||
@@ -3013,6 +3014,19 @@ public:
|
||||
bool IsUnlinked() const;
|
||||
|
||||
|
||||
// Global event filters
|
||||
// --------------------
|
||||
|
||||
// Add an event filter whose FilterEvent() method will be called for each
|
||||
// and every event processed by wxWidgets. The filters are called in LIFO
|
||||
// order and wxApp is registered as an event filter by default. The pointer
|
||||
// must remain valid until it's removed with RemoveFilter() and is not
|
||||
// deleted by wxEvtHandler.
|
||||
static void AddFilter(wxEventFilter* filter);
|
||||
|
||||
// Remove a filter previously installed with AddFilter().
|
||||
static void RemoveFilter(wxEventFilter* filter);
|
||||
|
||||
|
||||
// Event queuing and processing
|
||||
// ----------------------------
|
||||
@@ -3360,6 +3374,9 @@ private:
|
||||
// try to process events in all handlers chained to this one
|
||||
bool DoTryChain(wxEvent& event);
|
||||
|
||||
// Head of the event filter linked list.
|
||||
static wxEventFilter* ms_filterList;
|
||||
|
||||
DECLARE_DYNAMIC_CLASS_NO_COPY(wxEvtHandler)
|
||||
};
|
||||
|
||||
|
72
include/wx/eventfilter.h
Normal file
72
include/wx/eventfilter.h
Normal file
@@ -0,0 +1,72 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/eventfilter.h
|
||||
// Purpose: wxEventFilter class declaration.
|
||||
// Author: Vadim Zeitlin
|
||||
// Created: 2011-11-21
|
||||
// RCS-ID: $Id: wxhead.h,v 1.12 2010-04-22 12:44:51 zeitlin Exp $
|
||||
// Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
|
||||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WX_EVENTFILTER_H_
|
||||
#define _WX_EVENTFILTER_H_
|
||||
|
||||
#include "wx/defs.h"
|
||||
|
||||
class WXDLLIMPEXP_FWD_BASE wxEvent;
|
||||
class WXDLLIMPEXP_FWD_BASE wxEvtHandler;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxEventFilter is used with wxEvtHandler::AddFilter() and ProcessEvent().
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxEventFilter
|
||||
{
|
||||
public:
|
||||
// Possible return values for FilterEvent().
|
||||
//
|
||||
// Notice that the values of these enum elements are fixed due to backwards
|
||||
// compatibility constraints.
|
||||
enum
|
||||
{
|
||||
// Process event as usual.
|
||||
Event_Skip = -1,
|
||||
|
||||
// Don't process the event normally at all.
|
||||
Event_Ignore = 0,
|
||||
|
||||
// Event was already handled, don't process it normally.
|
||||
Event_Processed = 1
|
||||
};
|
||||
|
||||
wxEventFilter()
|
||||
{
|
||||
m_next = NULL;
|
||||
}
|
||||
|
||||
virtual ~wxEventFilter()
|
||||
{
|
||||
wxASSERT_MSG( !m_next, "Forgot to call wxEvtHandler::RemoveFilter()?" );
|
||||
}
|
||||
|
||||
// This method allows to filter all the events processed by the program, so
|
||||
// you should try to return quickly from it to avoid slowing down the
|
||||
// program to the crawl.
|
||||
//
|
||||
// Return value should be -1 to continue with the normal event processing,
|
||||
// or true or false to stop further processing and pretend that the event
|
||||
// had been already processed or won't be processed at all, respectively.
|
||||
virtual int FilterEvent(wxEvent& event) = 0;
|
||||
|
||||
private:
|
||||
// Objects of this class are made to be stored in a linked list in
|
||||
// wxEvtHandler so put the next node ponter directly in the class itself.
|
||||
wxEventFilter* m_next;
|
||||
|
||||
// And provide access to it for wxEvtHandler [only].
|
||||
friend class wxEvtHandler;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxEventFilter);
|
||||
};
|
||||
|
||||
#endif // _WX_EVENTFILTER_H_
|
@@ -37,7 +37,8 @@
|
||||
|
||||
@see @ref overview_app, wxApp, wxAppTraits, wxEventLoopBase
|
||||
*/
|
||||
class wxAppConsole : public wxEvtHandler
|
||||
class wxAppConsole : public wxEvtHandler,
|
||||
public wxEventFilter
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
@@ -81,13 +82,14 @@ public:
|
||||
virtual void ExitMainLoop();
|
||||
|
||||
/**
|
||||
This function is called before processing any event and allows the application
|
||||
to preempt the processing of some events.
|
||||
Overridden wxEventFilter method.
|
||||
|
||||
If this method returns -1 the event is processed normally, otherwise either
|
||||
@true or @false should be returned and the event processing stops immediately
|
||||
considering that the event had been already processed (for the former return
|
||||
value) or that it is not going to be processed at all (for the latter one).
|
||||
This function is called before processing any event and allows the application
|
||||
to preempt the processing of some events, see wxEventFilter
|
||||
documentation for more information.
|
||||
|
||||
wxApp implementation of this method always return -1 indicating that
|
||||
the event should be processed normally.
|
||||
*/
|
||||
virtual int FilterEvent(wxEvent& event);
|
||||
|
||||
|
@@ -1088,6 +1088,40 @@ public:
|
||||
|
||||
//@}
|
||||
|
||||
/**
|
||||
@name Global event filters.
|
||||
|
||||
Methods for working with the global list of event filters.
|
||||
|
||||
Event filters can be defined to pre-process all the events that happen
|
||||
in an application, see wxEventFilter documentation for more information.
|
||||
*/
|
||||
//@{
|
||||
|
||||
/**
|
||||
Add an event filter whose FilterEvent() method will be called for each
|
||||
and every event processed by wxWidgets.
|
||||
|
||||
The filters are called in LIFO order and wxApp is registered as an
|
||||
event filter by default. The pointer must remain valid until it's
|
||||
removed with RemoveFilter() and is not deleted by wxEvtHandler.
|
||||
|
||||
@since 2.9.3
|
||||
*/
|
||||
static void AddFilter(wxEventFilter* filter);
|
||||
|
||||
/**
|
||||
Remove a filter previously installed with AddFilter().
|
||||
|
||||
It's an error to remove a filter that hadn't been previously added or
|
||||
was already removed.
|
||||
|
||||
@since 2.9.3
|
||||
*/
|
||||
static void RemoveFilter(wxEventFilter* filter);
|
||||
|
||||
//@}
|
||||
|
||||
protected:
|
||||
/**
|
||||
Method called by ProcessEvent() before examining this object event
|
||||
|
139
interface/wx/eventfilter.h
Normal file
139
interface/wx/eventfilter.h
Normal file
@@ -0,0 +1,139 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: interface/wx/eventfilter.h
|
||||
// Purpose: wxEventFilter class documentation
|
||||
// Author: Vadim Zeitlin
|
||||
// Created: 2011-11-21
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
|
||||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
A global event filter for pre-processing all the events generated in the
|
||||
program.
|
||||
|
||||
This is a very simple class which just provides FilterEvent() virtual
|
||||
method to be called by wxEvtHandler before starting process of any event.
|
||||
Thus, inheriting from this class and overriding FilterEvent() allows to
|
||||
capture and possibly handle or ignore all the events happening in the
|
||||
program. Of course, having event filters adds additional overhead to every
|
||||
event processing and so should not be used lightly and your FilterEvent()
|
||||
code should try to return as quickly as possible, especially for the events
|
||||
it is not interested in.
|
||||
|
||||
An example of using this class:
|
||||
@code
|
||||
// This class allows to determine the last time the user has worked with
|
||||
// this application:
|
||||
class LastActivityTimeDetector : public wxEventFilter
|
||||
{
|
||||
public:
|
||||
LastActivityTimeDetector()
|
||||
{
|
||||
wxEvtHandler::AddFilter(this);
|
||||
|
||||
m_last = wxDateTime::Now();
|
||||
}
|
||||
|
||||
virtual ~LastActivityTimeDetector()
|
||||
{
|
||||
wxEvtHandler::RemoveFilter(this);
|
||||
}
|
||||
|
||||
virtual int FilterEvent(wxEvent& event)
|
||||
{
|
||||
// Update the last user activity
|
||||
const wxEventType t = event.GetEventType();
|
||||
if ( t == wxEVT_KEY_DOWN || t == wxEVT_MOTION ||
|
||||
t == wxEVT_LEFT_DOWN ||
|
||||
t == wxEVT_RIGHT_DOWN ||
|
||||
t == wxEVT_MIDDLE_DOWN )
|
||||
{
|
||||
m_last = wxDateTime::Now();
|
||||
}
|
||||
|
||||
// Continue processing the event normally as well.
|
||||
return Event_Skip;
|
||||
}
|
||||
|
||||
// This function could be called periodically from some timer to
|
||||
// do something (e.g. hide sensitive data or log out from remote
|
||||
// server) if the user has been inactive for some time period.
|
||||
bool IsInactiveFor(const wxTimeSpan& diff) const
|
||||
{
|
||||
return wxDateTime::Now() - diff > m_last;
|
||||
}
|
||||
|
||||
private:
|
||||
wxDateTime m_last;
|
||||
};
|
||||
@endcode
|
||||
|
||||
Notice that wxApp derives from wxEventFilter and is registered as an event
|
||||
filter during its creation so you may also override FilterEvent() method in
|
||||
your wxApp-derived class and, in fact, this is often the most convenient
|
||||
way to do it. However creating a new class deriving directly from
|
||||
wxEventFilter allows to isolate the event filtering code in its own
|
||||
separate class and also to have several independent filters, if necessary.
|
||||
|
||||
@category{events}
|
||||
|
||||
@since 2.9.3
|
||||
*/
|
||||
class wxEventFilter
|
||||
{
|
||||
public:
|
||||
/// Possible return values for FilterEvent().
|
||||
enum
|
||||
{
|
||||
/// Process event as usual.
|
||||
Event_Skip = -1,
|
||||
|
||||
/// Don't process the event normally at all.
|
||||
Event_Ignore = 0,
|
||||
|
||||
/// Event was already handled, don't process it normally.
|
||||
Event_Processed = 1
|
||||
};
|
||||
|
||||
/**
|
||||
Default constructor.
|
||||
|
||||
Constructor does not register this filter using
|
||||
wxEvtHandler::AddFilter(), it's your responsibility to do it when
|
||||
necessary.
|
||||
|
||||
Notice that the objects of this class can't be copied.
|
||||
*/
|
||||
wxEventFilter();
|
||||
|
||||
/**
|
||||
Destructor.
|
||||
|
||||
You must call wxEvtHandler::RemoveFilter() before destroying this
|
||||
object (possibly from the derived class destructor), failure to do this
|
||||
is indicated by an assert unless assertions are disabled.
|
||||
*/
|
||||
virtual ~wxEventFilter();
|
||||
|
||||
/**
|
||||
Override this method to implement event pre-processing.
|
||||
|
||||
This method allows to filter all the events processed by the program,
|
||||
so you should try to return quickly from it to avoid slowing down the
|
||||
program to the crawl.
|
||||
|
||||
Although the return type of this method is @c int, this is only due to
|
||||
backwards compatibility concerns and the actual return value must be
|
||||
one of the @c Event_XXX constants defined above:
|
||||
- Event_Skip to continue processing the event normally (this should
|
||||
be used in most cases).
|
||||
- Event_Ignore to not process this event at all (this can be used
|
||||
to suppress some events).
|
||||
- Event_Processed to not process this event normally but indicate
|
||||
that it was already processed by the event filter and so no default
|
||||
processing should take place neither (this should only be used if
|
||||
the filter really did process the event).
|
||||
*/
|
||||
virtual int FilterEvent(wxEvent& event) = 0;
|
||||
};
|
@@ -150,10 +150,14 @@ wxAppConsoleBase::wxAppConsoleBase()
|
||||
wxDELETE(m_traits);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
wxEvtHandler::AddFilter(this);
|
||||
}
|
||||
|
||||
wxAppConsoleBase::~wxAppConsoleBase()
|
||||
{
|
||||
wxEvtHandler::RemoveFilter(this);
|
||||
|
||||
// we're being destroyed and using this object from now on may not work or
|
||||
// even crash so don't leave dangling pointers to it
|
||||
ms_appInstance = NULL;
|
||||
@@ -401,7 +405,7 @@ bool wxAppConsoleBase::IsMainLoopRunning()
|
||||
int wxAppConsoleBase::FilterEvent(wxEvent& WXUNUSED(event))
|
||||
{
|
||||
// process the events normally by default
|
||||
return -1;
|
||||
return Event_Skip;
|
||||
}
|
||||
|
||||
void wxAppConsoleBase::DelayPendingEventHandler(wxEvtHandler* toDelay)
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#endif
|
||||
|
||||
#include "wx/event.h"
|
||||
#include "wx/eventfilter.h"
|
||||
#include "wx/evtloop.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
@@ -1132,6 +1133,43 @@ bool wxEvtHandler::IsUnlinked() const
|
||||
m_nextHandler == NULL;
|
||||
}
|
||||
|
||||
wxEventFilter* wxEvtHandler::ms_filterList = NULL;
|
||||
|
||||
/* static */ void wxEvtHandler::AddFilter(wxEventFilter* filter)
|
||||
{
|
||||
wxCHECK_RET( filter, "NULL filter" );
|
||||
|
||||
filter->m_next = ms_filterList;
|
||||
ms_filterList = filter;
|
||||
}
|
||||
|
||||
/* static */ void wxEvtHandler::RemoveFilter(wxEventFilter* filter)
|
||||
{
|
||||
wxEventFilter* prev = NULL;
|
||||
for ( wxEventFilter* f = ms_filterList; f; f = f->m_next )
|
||||
{
|
||||
if ( f == filter )
|
||||
{
|
||||
// Set the previous list element or the list head to the next
|
||||
// element.
|
||||
if ( prev )
|
||||
prev->m_next = f->m_next;
|
||||
else
|
||||
ms_filterList = f->m_next;
|
||||
|
||||
// Also reset the next pointer in the filter itself just to avoid
|
||||
// having possibly dangling pointers, even though it's not strictly
|
||||
// necessary.
|
||||
f->m_next = NULL;
|
||||
|
||||
// Skip the assert below.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wxFAIL_MSG( "Filter not found" );
|
||||
}
|
||||
|
||||
#if wxUSE_THREADS
|
||||
|
||||
bool wxEvtHandler::ProcessThreadEvent(const wxEvent& event)
|
||||
@@ -1360,23 +1398,24 @@ bool wxEvtHandler::TryAfter(wxEvent& event)
|
||||
|
||||
bool wxEvtHandler::ProcessEvent(wxEvent& event)
|
||||
{
|
||||
// The very first thing we do is to allow the application to hook into
|
||||
// event processing in order to globally pre-process all events.
|
||||
// The very first thing we do is to allow any registered filters to hook
|
||||
// into event processing in order to globally pre-process all events.
|
||||
//
|
||||
// Note that we should only do it if we're the first event handler called
|
||||
// to avoid calling FilterEvent() multiple times as the event goes through
|
||||
// the event handler chain and possibly upwards the window hierarchy.
|
||||
if ( !event.WasProcessed() )
|
||||
{
|
||||
if ( wxTheApp )
|
||||
for ( wxEventFilter* f = ms_filterList; f; f = f->m_next )
|
||||
{
|
||||
int rc = wxTheApp->FilterEvent(event);
|
||||
if ( rc != -1 )
|
||||
int rc = f->FilterEvent(event);
|
||||
if ( rc != wxEventFilter::Event_Skip )
|
||||
{
|
||||
wxASSERT_MSG( rc == 1 || rc == 0,
|
||||
"unexpected wxApp::FilterEvent return value" );
|
||||
wxASSERT_MSG( rc == wxEventFilter::Event_Ignore ||
|
||||
rc == wxEventFilter::Event_Processed,
|
||||
"unexpected FilterEvent() return value" );
|
||||
|
||||
return rc != 0;
|
||||
return rc != wxEventFilter::Event_Ignore;
|
||||
}
|
||||
//else: proceed normally
|
||||
}
|
||||
|
@@ -226,6 +226,7 @@ wx/dynlib.h
|
||||
wx/dynload.h
|
||||
wx/encconv.h
|
||||
wx/event.h
|
||||
wx/eventfilter.h
|
||||
wx/evtloop.h
|
||||
wx/except.h
|
||||
wx/features.h
|
||||
|
@@ -128,6 +128,7 @@ wx/dynlib.h
|
||||
wx/dynload.h
|
||||
wx/encconv.h
|
||||
wx/event.h
|
||||
wx/eventfilter.h
|
||||
wx/evtloop.h
|
||||
wx/except.h
|
||||
wx/features.h
|
||||
|
@@ -152,6 +152,7 @@ wx/dynlib.h
|
||||
wx/dynload.h
|
||||
wx/encconv.h
|
||||
wx/event.h
|
||||
wx/eventfilter.h
|
||||
wx/evtloop.h
|
||||
wx/except.h
|
||||
wx/features.h
|
||||
|
Reference in New Issue
Block a user