#if wxUSE_GUI
#include "wx/gdicmn.h"
#include "wx/cursor.h"
+ #include "wx/mousestate.h"
#endif
#include "wx/dynarray.h"
class WXDLLIMPEXP_FWD_CORE wxWindowBase;
#endif // wxUSE_GUI
-class WXDLLIMPEXP_FWD_BASE wxEvtHandler;
+// We operate with pointer to members of wxEvtHandler (such functions are used
+// as event handlers in the event tables or as arguments to Connect()) but by
+// default MSVC uses a restricted (but more efficient) representation of
+// pointers to members which can't deal with multiple base classes. To avoid
+// mysterious (as the compiler is not good enough to detect this and give a
+// sensible error message) errors in the user code as soon as it defines
+// classes inheriting from both wxEvtHandler (possibly indirectly, e.g. via
+// wxWindow) and something else (including our own wxTrackable but not limited
+// to it), we use the special MSVC keyword telling the compiler to use a more
+// general pointer to member representation for the classes inheriting from
+// wxEvtHandler.
+#ifdef __VISUALC__
+ #define wxMSVC_FWD_MULTIPLE_BASES __multiple_inheritance
+#else
+ #define wxMSVC_FWD_MULTIPLE_BASES
+#endif
+
+class WXDLLIMPEXP_FWD_BASE wxMSVC_FWD_MULTIPLE_BASES wxEvtHandler;
class wxEventConnectionRef;
// ----------------------------------------------------------------------------
class WXDLLIMPEXP_BASE wxEvent : public wxObject
{
-private:
- wxEvent& operator=(const wxEvent&);
-
-protected:
- wxEvent(const wxEvent&); // for implementing Clone()
-
public:
wxEvent(int winid = 0, wxEventType commandType = wxEVT_NULL );
// backwards compatibility as it is new
int m_propagationLevel;
-protected:
bool m_skipped;
bool m_isCommandEvent;
+protected:
+ wxEvent(const wxEvent&); // for implementing Clone()
+ wxEvent& operator=(const wxEvent&); // for derived classes operator=()
+
private:
// it needs to access our m_propagationLevel
friend class WXDLLIMPEXP_FWD_BASE wxPropagateOnce;
wxCommandEvent(const wxCommandEvent& event)
: wxEvent(event),
- m_cmdString(event.m_cmdString.c_str()), // "thread-safe"
+ m_cmdString(event.m_cmdString),
m_commandInt(event.m_commandInt),
m_extraLong(event.m_extraLong),
m_clientData(event.m_clientData),
wxMOUSE_BTN_MAX
};
-class WXDLLIMPEXP_CORE wxMouseEvent : public wxEvent
+class WXDLLIMPEXP_CORE wxMouseEvent : public wxEvent,
+ public wxMouseState
{
public:
wxMouseEvent(wxEventType mouseType = wxEVT_NULL);
- wxMouseEvent(const wxMouseEvent& event) : wxEvent(event)
- { Assign(event); }
+ wxMouseEvent(const wxMouseEvent& event)
+ : wxEvent(event),
+ wxMouseState(event)
+ {
+ Assign(event);
+ }
// Was it a button event? (*doesn't* mean: is any button *down*?)
bool IsButton() const { return Button(wxMOUSE_BTN_ANY); }
// Get the button which is changing state (wxMOUSE_BTN_NONE if none)
int GetButton() const;
- // Find state of shift/control keys
- bool ControlDown() const { return m_controlDown; }
- bool MetaDown() const { return m_metaDown; }
- bool AltDown() const { return m_altDown; }
- bool ShiftDown() const { return m_shiftDown; }
- bool CmdDown() const
- {
-#if defined(__WXMAC__) || defined(__WXCOCOA__)
- return MetaDown();
-#else
- return ControlDown();
-#endif
- }
-
// Find which event was just generated
bool LeftDown() const { return (m_eventType == wxEVT_LEFT_DOWN); }
bool MiddleDown() const { return (m_eventType == wxEVT_MIDDLE_DOWN); }
virtual wxEvent *Clone() const { return new wxMouseEvent(*this); }
- wxMouseEvent& operator=(const wxMouseEvent& event) { if (&event != this) Assign(event); return *this; }
+ wxMouseEvent& operator=(const wxMouseEvent& event)
+ {
+ if (&event != this)
+ Assign(event);
+ return *this;
+ }
public:
wxCoord m_x, m_y;
bool m_aux1Down;
bool m_aux2Down;
- bool m_controlDown;
- bool m_shiftDown;
- bool m_altDown;
- bool m_metaDown;
-
int m_clickCount;
int m_wheelAxis;
wxEVT_HOTKEY
*/
-class WXDLLIMPEXP_CORE wxKeyEvent : public wxEvent
+class WXDLLIMPEXP_CORE wxKeyEvent : public wxEvent,
+ public wxKeyboardState
{
public:
wxKeyEvent(wxEventType keyType = wxEVT_NULL);
wxKeyEvent(const wxKeyEvent& evt);
- // can be used check if the key event has exactly the given modifiers:
- // "GetModifiers() = wxMOD_CONTROL" is easier to write than "ControlDown()
- // && !MetaDown() && !AltDown() && !ShiftDown()"
- int GetModifiers() const
- {
- return (m_controlDown ? wxMOD_CONTROL : 0) |
- (m_shiftDown ? wxMOD_SHIFT : 0) |
- (m_metaDown ? wxMOD_META : 0) |
- (m_altDown ? wxMOD_ALT : 0);
- }
-
- // Find state of shift/control keys
- bool ControlDown() const { return m_controlDown; }
- bool ShiftDown() const { return m_shiftDown; }
- bool MetaDown() const { return m_metaDown; }
- bool AltDown() const { return m_altDown; }
-
- // "Cmd" is a pseudo key which is Control for PC and Unix platforms but
- // Apple ("Command") key under Macs: it makes often sense to use it instead
- // of, say, ControlDown() because Cmd key is used for the same thing under
- // Mac as Ctrl elsewhere (but Ctrl still exists, just not used for this
- // purpose under Mac)
- bool CmdDown() const
- {
-#if defined(__WXMAC__) || defined(__WXCOCOA__)
- return MetaDown();
-#else
- return ControlDown();
-#endif
- }
-
- // exclude MetaDown() from HasModifiers() because NumLock under X is often
- // configured as mod2 modifier, yet the key events even when it is pressed
- // should be processed normally, not like Ctrl- or Alt-key
- bool HasModifiers() const { return ControlDown() || AltDown(); }
-
// get the key code: an ASCII7 char or an element of wxKeyCode enum
int GetKeyCode() const { return (int)m_keyCode; }
// example)
wxKeyEvent& operator=(const wxKeyEvent& evt)
{
- if (&evt != this)
+ if ( &evt != this )
{
+ wxEvent::operator=(evt);
+
+ // Borland C++ 5.82 doesn't compile an explicit call to an
+ // implicitly defined operator=() so need to do it this way:
+ *static_cast<wxKeyboardState *>(this) = evt;
+
m_x = evt.m_x;
m_y = evt.m_y;
m_keyCode = evt.m_keyCode;
- m_controlDown = evt.m_controlDown;
- m_shiftDown = evt.m_shiftDown;
- m_altDown = evt.m_altDown;
- m_metaDown = evt.m_metaDown;
m_scanCode = evt.m_scanCode;
m_rawCode = evt.m_rawCode;
m_rawFlags = evt.m_rawFlags;
long m_keyCode;
- // TODO: replace those with a single m_modifiers bitmask of wxMOD_XXX?
- bool m_controlDown;
- bool m_shiftDown;
- bool m_altDown;
- bool m_metaDown;
-
// FIXME: what is this for? relation to m_rawXXX?
bool m_scanCode;
{ m_show = event.m_show; }
void SetShow(bool show) { m_show = show; }
- bool GetShow() const { return m_show; }
+
+ // return true if the window was shown, false if hidden
+ bool IsShown() const { return m_show; }
+
+#if WXWIN_COMPATIBILITY_2_8
+ wxDEPRECATED( bool GetShow() const { return IsShown(); } )
+#endif
virtual wxEvent *Clone() const { return new wxShowEvent(*this); }
: wxEvent(event)
{ m_iconized = event.m_iconized; }
+#if WXWIN_COMPATIBILITY_2_8
+ wxDEPRECATED( bool Iconized() const { return IsIconized(); } )
+#endif
// return true if the frame was iconized, false if restored
- bool Iconized() const { return m_iconized; }
+ bool IsIconized() const { return m_iconized; }
virtual wxEvent *Clone() const { return new wxIconizeEvent(*this); }
// event handler and related classes
// ============================================================================
-// for backwards compatibility and to prevent eVC 4 for ARM from crashing with
-// internal compiler error when compiling wx, we define wxObjectEventFunction
-// as a wxObject method even though it can only be a wxEvtHandler one
-typedef void (wxObject::*wxObjectEventFunction)(wxEvent&);
+typedef void (wxEvtHandler::*wxEventFunction)(wxEvent&);
+
+// We had some trouble (specifically with eVC for ARM WinCE build) with using
+// wxEventFunction in the past so we had introduced wxObjectEventFunction which
+// used to be a typedef for a member of wxObject and not wxEvtHandler to work
+// around this but as eVC is not really supported any longer we now only keep
+// this for backwards compatibility and, despite its name, this is a typedef
+// for wxEvtHandler member now -- but if we have the same problem with another
+// compiler we can restore its old definition for it.
+typedef wxEventFunction wxObjectEventFunction;
// struct containing the members common to static and dynamic event tables
// entries
// ----------------------------------------------------------------------------
class WXDLLIMPEXP_BASE wxEvtHandler : public wxObject
-#if wxUSE_WEAKREF
, public wxTrackable
-#endif
{
public:
wxEvtHandler();
void SetEvtHandlerEnabled(bool enabled) { m_enabled = enabled; }
bool GetEvtHandlerEnabled() const { return m_enabled; }
- // process an event right now
+ // Process an event right now: this can only be called from the main
+ // thread, use QueueEvent() for scheduling the events for
+ // processing from other threads.
virtual bool ProcessEvent(wxEvent& event);
// Process an event by calling ProcessEvent and handling any exceptions
// wouldn't correctly propagate to wxEventLoop.
bool SafelyProcessEvent(wxEvent& event);
- // add an event to be processed later
- virtual void AddPendingEvent(const wxEvent& event);
+ // Schedule the given event to be processed later. It takes ownership of
+ // the event pointer, i.e. it will be deleted later. This is safe to call
+ // from multiple threads although you still need to ensure that wxString
+ // fields of the event object are deep copies and not use the same string
+ // buffer as other wxString objects in this thread.
+ virtual void QueueEvent(wxEvent *event);
+
+ // Add an event to be processed later: notice that this function is not
+ // safe to call from threads other than main, use QueueEvent()
+ virtual void AddPendingEvent(const wxEvent& event)
+ {
+ // notice that the thread-safety problem comes from the fact that
+ // Clone() doesn't make deep copies of wxString fields of wxEvent
+ // object and so the same wxString could be used from both threads when
+ // the event object is destroyed in this one -- QueueEvent() avoids
+ // this problem as the event pointer is not used any more in this
+ // thread at all after it is called.
+ QueueEvent(event.Clone());
+ }
void ProcessPendingEvents();
void SetClientData( void *data ) { DoSetClientData(data); }
void *GetClientData() const { return DoGetClientData(); }
+
+ // implementation from now on
+ // --------------------------
+
// check if the given event table entry matches this event and call the
// handler if it does
//
wxEvtHandler *handler,
wxEvent& event);
- // implementation from now on
virtual bool SearchEventTable(wxEventTable& table, wxEvent& event);
bool SearchDynamicEventTable( wxEvent& event );
// Avoid problems at exit by cleaning up static hash table gracefully
void ClearEventHashTable() { GetEventHashTable().Clear(); }
-#if wxUSE_WEAKREF
void OnSinkDestroyed( wxEvtHandler *sink );
-#endif
+
+
+ // The method processing the event in this event handler (or rather in this
+ // event handler chain as it also tries the next handler and so on), i.e.
+ // it returns true if we processed this event or false if we didn't but
+ // does not call TryParent() in the latter case. It also doesn't call
+ // wxApp::FilterEvent() before processing it, this is supposed to be done
+ // by the public ProcessEvent() only once for every event we handle.
+ //
+ // It is meant to be called from ProcessEvent() only and is not virtual,
+ // additional event handlers can be hooked into the normal event processing
+ // logic using TryValidator() hook.
+ bool ProcessEventHere(wxEvent& event);
+
private:
static const wxEventTableEntry sm_eventTableEntries[];
virtual void DoSetClientData( void *data );
virtual void *DoGetClientData() const;
-#if wxUSE_WEAKREF
// Search tracker objects for event connection with this sink
wxEventConnectionRef *FindRefInTrackerList(wxEvtHandler *eventSink);
-#endif
private:
DECLARE_DYNAMIC_CLASS_NO_COPY(wxEvtHandler)
};
-#if wxUSE_WEAKREF
// ----------------------------------------------------------------------------
// wxEventConnectionRef represents all connections between two event handlers
// and enables automatic disconnect when an event handler sink goes out of
DECLARE_NO_ASSIGN_CLASS(wxEventConnectionRef)
};
-#endif // wxUSE_WEAKREF
-// Post a message to the given eventhandler which will be processed during the
-// next event loop iteration
+// Post a message to the given event handler which will be processed during the
+// next event loop iteration.
+//
+// Notice that this one is not thread-safe, use wxQueueEvent()
inline void wxPostEvent(wxEvtHandler *dest, const wxEvent& event)
{
- wxCHECK_RET( dest, wxT("need an object to post event to in wxPostEvent") );
+ wxCHECK_RET( dest, "need an object to post event to" );
dest->AddPendingEvent(event);
}
+// Wrapper around wxEvtHandler::QueueEvent(): adds an event for later
+// processing, unlike wxPostEvent it is safe to use from different thread even
+// for events with wxString members
+inline void wxQueueEvent(wxEvtHandler *dest, wxEvent *event)
+{
+ wxCHECK_RET( dest, "need an object to queue event for" );
+
+ dest->QueueEvent(event);
+}
+
typedef void (wxEvtHandler::*wxEventFunction)(wxEvent&);
typedef void (wxEvtHandler::*wxIdleEventFunction)(wxIdleEvent&);