#ifndef WX_PRECOMP
#include "wx/list.h"
+ #include "wx/log.h"
#include "wx/app.h"
#include "wx/utils.h"
#include "wx/stopwatch.h"
#include "wx/window.h"
#include "wx/control.h"
#include "wx/dc.h"
+ #include "wx/spinbutt.h"
#include "wx/textctrl.h"
#include "wx/validate.h"
#endif // wxUSE_GUI
#include "wx/thread.h"
#if wxUSE_BASE
- #include "wx/ptr_scpd.h"
+ #include "wx/scopedptr.h"
wxDECLARE_SCOPED_PTR(wxEvent, wxEventPtr)
wxDEFINE_SCOPED_PTR(wxEvent, wxEventPtr)
#if wxUSE_GUI
IMPLEMENT_DYNAMIC_CLASS(wxCommandEvent, wxEvent)
+ IMPLEMENT_DYNAMIC_CLASS(wxThreadEvent, wxCommandEvent)
IMPLEMENT_DYNAMIC_CLASS(wxNotifyEvent, wxCommandEvent)
IMPLEMENT_DYNAMIC_CLASS(wxScrollEvent, wxCommandEvent)
IMPLEMENT_DYNAMIC_CLASS(wxScrollWinEvent, wxEvent)
wxEventHashTable wxEvtHandler::sm_eventHashTable(wxEvtHandler::sm_eventTable);
const wxEventTableEntry wxEvtHandler::sm_eventTableEntries[] =
- { DECLARE_EVENT_TABLE_ENTRY(wxEVT_NULL, 0, 0, (wxObjectEventFunction)NULL, NULL) };
+ { DECLARE_EVENT_TABLE_TERMINATOR() };
// wxUSE_MEMORY_TRACING considers memory freed from the static objects dtors
// global variables
// ----------------------------------------------------------------------------
-// List containing event handlers with pending events (each handler can occur
-// at most once here)
-wxList *wxPendingEvents = NULL;
-
-#if wxUSE_THREADS
- // protects wxPendingEvents list
- wxCriticalSection *wxPendingEventsLocker = NULL;
-#endif
-
// common event types are defined here, other event types are defined by the
// components which use them
const wxEventType wxEVT_USER_FIRST = wxEVT_FIRST + 2000;
DEFINE_EVENT_TYPE(wxEVT_NULL)
-DEFINE_EVENT_TYPE(wxEVT_IDLE)
-DEFINE_EVENT_TYPE(wxEVT_SOCKET)
-DEFINE_EVENT_TYPE(wxEVT_TIMER)
+wxDEFINE_EVENT( wxEVT_IDLE, wxIdleEvent );
#endif // wxUSE_BASE
#if wxUSE_GUI
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_BUTTON_CLICKED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_CHECKBOX_CLICKED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_CHOICE_SELECTED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LISTBOX_SELECTED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_MENU_SELECTED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_SLIDER_UPDATED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_RADIOBOX_SELECTED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_RADIOBUTTON_SELECTED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_SCROLLBAR_UPDATED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_VLBOX_SELECTED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_COMBOBOX_SELECTED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_RCLICKED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_ENTER)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_SPINCTRL_UPDATED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED)
+wxDEFINE_EVENT( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_MENU_SELECTED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_SLIDER_UPDATED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_SCROLLBAR_UPDATED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_VLBOX_SELECTED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_TOOL_RCLICKED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_TOOL_ENTER, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED, wxCommandEvent );
// Mouse event types
-DEFINE_EVENT_TYPE(wxEVT_LEFT_DOWN)
-DEFINE_EVENT_TYPE(wxEVT_LEFT_UP)
-DEFINE_EVENT_TYPE(wxEVT_MIDDLE_DOWN)
-DEFINE_EVENT_TYPE(wxEVT_MIDDLE_UP)
-DEFINE_EVENT_TYPE(wxEVT_RIGHT_DOWN)
-DEFINE_EVENT_TYPE(wxEVT_RIGHT_UP)
-DEFINE_EVENT_TYPE(wxEVT_MOTION)
-DEFINE_EVENT_TYPE(wxEVT_ENTER_WINDOW)
-DEFINE_EVENT_TYPE(wxEVT_LEAVE_WINDOW)
-DEFINE_EVENT_TYPE(wxEVT_LEFT_DCLICK)
-DEFINE_EVENT_TYPE(wxEVT_MIDDLE_DCLICK)
-DEFINE_EVENT_TYPE(wxEVT_RIGHT_DCLICK)
-DEFINE_EVENT_TYPE(wxEVT_SET_FOCUS)
-DEFINE_EVENT_TYPE(wxEVT_KILL_FOCUS)
-DEFINE_EVENT_TYPE(wxEVT_CHILD_FOCUS)
-DEFINE_EVENT_TYPE(wxEVT_MOUSEWHEEL)
-DEFINE_EVENT_TYPE(wxEVT_AUX1_DOWN)
-DEFINE_EVENT_TYPE(wxEVT_AUX1_UP)
-DEFINE_EVENT_TYPE(wxEVT_AUX1_DCLICK)
-DEFINE_EVENT_TYPE(wxEVT_AUX2_DOWN)
-DEFINE_EVENT_TYPE(wxEVT_AUX2_UP)
-DEFINE_EVENT_TYPE(wxEVT_AUX2_DCLICK)
-
-// Non-client mouse events
-DEFINE_EVENT_TYPE(wxEVT_NC_LEFT_DOWN)
-DEFINE_EVENT_TYPE(wxEVT_NC_LEFT_UP)
-DEFINE_EVENT_TYPE(wxEVT_NC_MIDDLE_DOWN)
-DEFINE_EVENT_TYPE(wxEVT_NC_MIDDLE_UP)
-DEFINE_EVENT_TYPE(wxEVT_NC_RIGHT_DOWN)
-DEFINE_EVENT_TYPE(wxEVT_NC_RIGHT_UP)
-DEFINE_EVENT_TYPE(wxEVT_NC_MOTION)
-DEFINE_EVENT_TYPE(wxEVT_NC_ENTER_WINDOW)
-DEFINE_EVENT_TYPE(wxEVT_NC_LEAVE_WINDOW)
-DEFINE_EVENT_TYPE(wxEVT_NC_LEFT_DCLICK)
-DEFINE_EVENT_TYPE(wxEVT_NC_MIDDLE_DCLICK)
-DEFINE_EVENT_TYPE(wxEVT_NC_RIGHT_DCLICK)
+wxDEFINE_EVENT( wxEVT_LEFT_DOWN, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_LEFT_UP, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_MIDDLE_DOWN, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_MIDDLE_UP, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_RIGHT_DOWN, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_RIGHT_UP, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_MOTION, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_ENTER_WINDOW, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_LEAVE_WINDOW, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_LEFT_DCLICK, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_MIDDLE_DCLICK, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_RIGHT_DCLICK, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_SET_FOCUS, wxFocusEvent );
+wxDEFINE_EVENT( wxEVT_KILL_FOCUS, wxFocusEvent );
+wxDEFINE_EVENT( wxEVT_CHILD_FOCUS, wxChildFocusEvent );
+wxDEFINE_EVENT( wxEVT_MOUSEWHEEL, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_AUX1_DOWN, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_AUX1_UP, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_AUX1_DCLICK, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_AUX2_DOWN, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_AUX2_UP, wxMouseEvent );
+wxDEFINE_EVENT( wxEVT_AUX2_DCLICK, wxMouseEvent );
// Character input event type
-DEFINE_EVENT_TYPE(wxEVT_CHAR)
-DEFINE_EVENT_TYPE(wxEVT_CHAR_HOOK)
-DEFINE_EVENT_TYPE(wxEVT_NAVIGATION_KEY)
-DEFINE_EVENT_TYPE(wxEVT_KEY_DOWN)
-DEFINE_EVENT_TYPE(wxEVT_KEY_UP)
+wxDEFINE_EVENT( wxEVT_CHAR, wxKeyEvent );
+wxDEFINE_EVENT( wxEVT_CHAR_HOOK, wxKeyEvent );
+wxDEFINE_EVENT( wxEVT_NAVIGATION_KEY, wxNavigationKeyEvent );
+wxDEFINE_EVENT( wxEVT_KEY_DOWN, wxKeyEvent );
+wxDEFINE_EVENT( wxEVT_KEY_UP, wxKeyEvent );
#if wxUSE_HOTKEY
-DEFINE_EVENT_TYPE(wxEVT_HOTKEY)
+wxDEFINE_EVENT( wxEVT_HOTKEY, wxKeyEvent );
#endif
// Set cursor event
-DEFINE_EVENT_TYPE(wxEVT_SET_CURSOR)
+wxDEFINE_EVENT( wxEVT_SET_CURSOR, wxSetCursorEvent );
// wxScrollbar and wxSlider event identifiers
-DEFINE_EVENT_TYPE(wxEVT_SCROLL_TOP)
-DEFINE_EVENT_TYPE(wxEVT_SCROLL_BOTTOM)
-DEFINE_EVENT_TYPE(wxEVT_SCROLL_LINEUP)
-DEFINE_EVENT_TYPE(wxEVT_SCROLL_LINEDOWN)
-DEFINE_EVENT_TYPE(wxEVT_SCROLL_PAGEUP)
-DEFINE_EVENT_TYPE(wxEVT_SCROLL_PAGEDOWN)
-DEFINE_EVENT_TYPE(wxEVT_SCROLL_THUMBTRACK)
-DEFINE_EVENT_TYPE(wxEVT_SCROLL_THUMBRELEASE)
-DEFINE_EVENT_TYPE(wxEVT_SCROLL_CHANGED)
+wxDEFINE_EVENT( wxEVT_SCROLL_TOP, wxScrollEvent );
+wxDEFINE_EVENT( wxEVT_SCROLL_BOTTOM, wxScrollEvent );
+wxDEFINE_EVENT( wxEVT_SCROLL_LINEUP, wxScrollEvent );
+wxDEFINE_EVENT( wxEVT_SCROLL_LINEDOWN, wxScrollEvent );
+wxDEFINE_EVENT( wxEVT_SCROLL_PAGEUP, wxScrollEvent );
+wxDEFINE_EVENT( wxEVT_SCROLL_PAGEDOWN, wxScrollEvent );
+wxDEFINE_EVENT( wxEVT_SCROLL_THUMBTRACK, wxScrollEvent );
+wxDEFINE_EVENT( wxEVT_SCROLL_THUMBRELEASE, wxScrollEvent );
+wxDEFINE_EVENT( wxEVT_SCROLL_CHANGED, wxScrollEvent );
+
+// Due to a bug in older wx versions, wxSpinEvents were being sent with type of
+// wxEVT_SCROLL_LINEUP, wxEVT_SCROLL_LINEDOWN and wxEVT_SCROLL_THUMBTRACK. But
+// with the type-safe events in place, these event types are associated with
+// wxScrollEvent. To allow handling of spin events, new event types have been
+// defined in spinbutt.h/spinnbuttcmn.cpp. To maintain backward compatibility
+// the spin event types are being initialized with the scroll event types.
+
+#if wxUSE_SPINBTN
+
+wxDEFINE_EVENT_ALIAS( wxEVT_SPIN_UP, wxSpinEvent, wxEVT_SCROLL_LINEUP );
+wxDEFINE_EVENT_ALIAS( wxEVT_SPIN_DOWN, wxSpinEvent, wxEVT_SCROLL_LINEDOWN );
+wxDEFINE_EVENT_ALIAS( wxEVT_SPIN, wxSpinEvent, wxEVT_SCROLL_THUMBTRACK );
+
+#endif // wxUSE_SPINBTN
// Scroll events from wxWindow
-DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_TOP)
-DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_BOTTOM)
-DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_LINEUP)
-DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_LINEDOWN)
-DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_PAGEUP)
-DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_PAGEDOWN)
-DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_THUMBTRACK)
-DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_THUMBRELEASE)
+wxDEFINE_EVENT( wxEVT_SCROLLWIN_TOP, wxScrollWinEvent );
+wxDEFINE_EVENT( wxEVT_SCROLLWIN_BOTTOM, wxScrollWinEvent );
+wxDEFINE_EVENT( wxEVT_SCROLLWIN_LINEUP, wxScrollWinEvent );
+wxDEFINE_EVENT( wxEVT_SCROLLWIN_LINEDOWN, wxScrollWinEvent );
+wxDEFINE_EVENT( wxEVT_SCROLLWIN_PAGEUP, wxScrollWinEvent );
+wxDEFINE_EVENT( wxEVT_SCROLLWIN_PAGEDOWN, wxScrollWinEvent );
+wxDEFINE_EVENT( wxEVT_SCROLLWIN_THUMBTRACK, wxScrollWinEvent );
+wxDEFINE_EVENT( wxEVT_SCROLLWIN_THUMBRELEASE, wxScrollWinEvent );
// System events
-DEFINE_EVENT_TYPE(wxEVT_SIZE)
-DEFINE_EVENT_TYPE(wxEVT_SIZING)
-DEFINE_EVENT_TYPE(wxEVT_MOVE)
-DEFINE_EVENT_TYPE(wxEVT_MOVING)
-DEFINE_EVENT_TYPE(wxEVT_MOVE_START)
-DEFINE_EVENT_TYPE(wxEVT_MOVE_END)
-DEFINE_EVENT_TYPE(wxEVT_CLOSE_WINDOW)
-DEFINE_EVENT_TYPE(wxEVT_END_SESSION)
-DEFINE_EVENT_TYPE(wxEVT_QUERY_END_SESSION)
-DEFINE_EVENT_TYPE(wxEVT_HIBERNATE)
-DEFINE_EVENT_TYPE(wxEVT_ACTIVATE_APP)
-DEFINE_EVENT_TYPE(wxEVT_ACTIVATE)
-DEFINE_EVENT_TYPE(wxEVT_CREATE)
-DEFINE_EVENT_TYPE(wxEVT_DESTROY)
-DEFINE_EVENT_TYPE(wxEVT_SHOW)
-DEFINE_EVENT_TYPE(wxEVT_ICONIZE)
-DEFINE_EVENT_TYPE(wxEVT_MAXIMIZE)
-DEFINE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_CHANGED)
-DEFINE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_LOST)
-DEFINE_EVENT_TYPE(wxEVT_PAINT)
-DEFINE_EVENT_TYPE(wxEVT_ERASE_BACKGROUND)
-DEFINE_EVENT_TYPE(wxEVT_NC_PAINT)
-DEFINE_EVENT_TYPE(wxEVT_PAINT_ICON)
-DEFINE_EVENT_TYPE(wxEVT_MENU_OPEN)
-DEFINE_EVENT_TYPE(wxEVT_MENU_CLOSE)
-DEFINE_EVENT_TYPE(wxEVT_MENU_HIGHLIGHT)
-DEFINE_EVENT_TYPE(wxEVT_CONTEXT_MENU)
-DEFINE_EVENT_TYPE(wxEVT_SYS_COLOUR_CHANGED)
-DEFINE_EVENT_TYPE(wxEVT_DISPLAY_CHANGED)
-DEFINE_EVENT_TYPE(wxEVT_SETTING_CHANGED)
-DEFINE_EVENT_TYPE(wxEVT_QUERY_NEW_PALETTE)
-DEFINE_EVENT_TYPE(wxEVT_PALETTE_CHANGED)
-DEFINE_EVENT_TYPE(wxEVT_JOY_BUTTON_DOWN)
-DEFINE_EVENT_TYPE(wxEVT_JOY_BUTTON_UP)
-DEFINE_EVENT_TYPE(wxEVT_JOY_MOVE)
-DEFINE_EVENT_TYPE(wxEVT_JOY_ZMOVE)
-DEFINE_EVENT_TYPE(wxEVT_DROP_FILES)
-DEFINE_EVENT_TYPE(wxEVT_DRAW_ITEM)
-DEFINE_EVENT_TYPE(wxEVT_MEASURE_ITEM)
-DEFINE_EVENT_TYPE(wxEVT_COMPARE_ITEM)
-DEFINE_EVENT_TYPE(wxEVT_INIT_DIALOG)
-DEFINE_EVENT_TYPE(wxEVT_UPDATE_UI)
+wxDEFINE_EVENT( wxEVT_SIZE, wxSizeEvent );
+wxDEFINE_EVENT( wxEVT_SIZING, wxSizeEvent );
+wxDEFINE_EVENT( wxEVT_MOVE, wxMoveEvent );
+wxDEFINE_EVENT( wxEVT_MOVING, wxMoveEvent );
+wxDEFINE_EVENT( wxEVT_MOVE_START, wxMoveEvent );
+wxDEFINE_EVENT( wxEVT_MOVE_END, wxMoveEvent );
+wxDEFINE_EVENT( wxEVT_CLOSE_WINDOW, wxCloseEvent );
+wxDEFINE_EVENT( wxEVT_END_SESSION, wxCloseEvent );
+wxDEFINE_EVENT( wxEVT_QUERY_END_SESSION, wxCloseEvent );
+wxDEFINE_EVENT( wxEVT_HIBERNATE, wxActivateEvent );
+wxDEFINE_EVENT( wxEVT_ACTIVATE_APP, wxActivateEvent );
+wxDEFINE_EVENT( wxEVT_ACTIVATE, wxActivateEvent );
+wxDEFINE_EVENT( wxEVT_CREATE, wxWindowCreateEvent );
+wxDEFINE_EVENT( wxEVT_DESTROY, wxWindowDestroyEvent );
+wxDEFINE_EVENT( wxEVT_SHOW, wxShowEvent );
+wxDEFINE_EVENT( wxEVT_ICONIZE, wxIconizeEvent );
+wxDEFINE_EVENT( wxEVT_MAXIMIZE, wxMaximizeEvent );
+wxDEFINE_EVENT( wxEVT_MOUSE_CAPTURE_CHANGED, wxMouseCaptureChangedEvent );
+wxDEFINE_EVENT( wxEVT_MOUSE_CAPTURE_LOST, wxMouseCaptureLostEvent );
+wxDEFINE_EVENT( wxEVT_PAINT, wxPaintEvent );
+wxDEFINE_EVENT( wxEVT_ERASE_BACKGROUND, wxEraseEvent );
+wxDEFINE_EVENT( wxEVT_NC_PAINT, wxNcPaintEvent );
+wxDEFINE_EVENT( wxEVT_MENU_OPEN, wxMenuEvent );
+wxDEFINE_EVENT( wxEVT_MENU_CLOSE, wxMenuEvent );
+wxDEFINE_EVENT( wxEVT_MENU_HIGHLIGHT, wxMenuEvent );
+wxDEFINE_EVENT( wxEVT_CONTEXT_MENU, wxContextMenuEvent );
+wxDEFINE_EVENT( wxEVT_SYS_COLOUR_CHANGED, wxSysColourChangedEvent );
+wxDEFINE_EVENT( wxEVT_DISPLAY_CHANGED, wxDisplayChangedEvent );
+wxDEFINE_EVENT( wxEVT_QUERY_NEW_PALETTE, wxQueryNewPaletteEvent );
+wxDEFINE_EVENT( wxEVT_PALETTE_CHANGED, wxPaletteChangedEvent );
+wxDEFINE_EVENT( wxEVT_JOY_BUTTON_DOWN, wxJoystickEvent );
+wxDEFINE_EVENT( wxEVT_JOY_BUTTON_UP, wxJoystickEvent );
+wxDEFINE_EVENT( wxEVT_JOY_MOVE, wxJoystickEvent );
+wxDEFINE_EVENT( wxEVT_JOY_ZMOVE, wxJoystickEvent );
+wxDEFINE_EVENT( wxEVT_DROP_FILES, wxDropFilesEvent );
+wxDEFINE_EVENT( wxEVT_INIT_DIALOG, wxInitDialogEvent );
+wxDEFINE_EVENT( wxEVT_UPDATE_UI, wxUpdateUIEvent );
// Clipboard events
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_COPY)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_CUT)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_PASTE)
+wxDEFINE_EVENT( wxEVT_COMMAND_TEXT_COPY, wxClipboardTextEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_TEXT_CUT, wxClipboardTextEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_TEXT_PASTE, wxClipboardTextEvent );
// Generic command events
// Note: a click is a higher-level event than button down/up
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LEFT_CLICK)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_LEFT_DCLICK)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_RIGHT_CLICK)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_RIGHT_DCLICK)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_SET_FOCUS)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_KILL_FOCUS)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_ENTER)
+wxDEFINE_EVENT( wxEVT_COMMAND_LEFT_CLICK, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_LEFT_DCLICK, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_RIGHT_CLICK, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_RIGHT_DCLICK, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_SET_FOCUS, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_KILL_FOCUS, wxCommandEvent );
+wxDEFINE_EVENT( wxEVT_COMMAND_ENTER, wxCommandEvent );
// Help events
-DEFINE_EVENT_TYPE(wxEVT_HELP)
-DEFINE_EVENT_TYPE(wxEVT_DETAILED_HELP)
+wxDEFINE_EVENT( wxEVT_HELP, wxHelpEvent );
+wxDEFINE_EVENT( wxEVT_DETAILED_HELP, wxHelpEvent );
+
+// Thread event
+wxDEFINE_EVENT( wxEVT_COMMAND_THREAD, wxThreadEvent );
#endif // wxUSE_GUI
return s_lastUsedEventType++;
}
+// ----------------------------------------------------------------------------
+// wxEventFunctor
+// ----------------------------------------------------------------------------
+
+wxEventFunctor::~wxEventFunctor()
+{
+}
// ----------------------------------------------------------------------------
// wxEvent
// ----------------------------------------------------------------------------
/*
- * General wxWidgets events, covering
- * all interesting things that might happen (button clicking, resizing,
- * setting text in widgets, etc.).
+ * General wxWidgets events, covering all interesting things that might happen
+ * (button clicking, resizing, setting text in widgets, etc.).
*
* For each completely new event type, derive a new event class.
*
*/
-wxEvent::wxEvent(int theId, wxEventType commandType )
+wxEvent::wxEvent(int theId, wxEventType commandType)
{
m_eventType = commandType;
- m_eventObject = (wxObject *) NULL;
+ m_eventObject = NULL;
m_timeStamp = 0;
m_id = theId;
m_skipped = false;
- m_callbackUserData = (wxObject *) NULL;
+ m_callbackUserData = NULL;
m_isCommandEvent = false;
m_propagationLevel = wxEVENT_PROPAGATE_NONE;
+ m_wasProcessed = false;
}
wxEvent::wxEvent(const wxEvent& src)
, m_propagationLevel(src.m_propagationLevel)
, m_skipped(src.m_skipped)
, m_isCommandEvent(src.m_isCommandEvent)
+ , m_wasProcessed(false)
{
}
m_skipped = src.m_skipped;
m_isCommandEvent = src.m_isCommandEvent;
+ // don't change m_wasProcessed
+
return *this;
}
wxCommandEvent::wxCommandEvent(wxEventType commandType, int theId)
: wxEvent(theId, commandType)
{
- m_clientData = (char *) NULL;
- m_clientObject = (wxClientData *) NULL;
+ m_clientData = NULL;
+ m_clientObject = NULL;
m_extraLong = 0;
m_commandInt = 0;
m_isCommandEvent = true;
{
m_eventType = type;
m_keyCode = 0;
- m_scanCode = 0;
#if wxUSE_UNICODE
m_uniChar = 0;
#endif
m_y = evt.m_y;
m_keyCode = evt.m_keyCode;
-
- m_scanCode = evt.m_scanCode;
m_rawCode = evt.m_rawCode;
m_rawFlags = evt.m_rawFlags;
const size_t count = eventEntryTable.GetCount();
for (size_t n = 0; n < count; n++)
{
- if ( wxEvtHandler::
- ProcessEventIfMatches(*eventEntryTable[n], self, event) )
- {
+ const wxEventTableEntry& entry = *eventEntryTable[n];
+ if ( wxEvtHandler::ProcessEventIfMatchesId(entry, self, event) )
return true;
- }
}
}
// wxEvtHandler
// ----------------------------------------------------------------------------
-/*
- * Event handler
- */
-
wxEvtHandler::wxEvtHandler()
{
- m_nextHandler = (wxEvtHandler *) NULL;
- m_previousHandler = (wxEvtHandler *) NULL;
+ m_nextHandler = NULL;
+ m_previousHandler = NULL;
m_enabled = true;
- m_dynamicEvents = (wxList *) NULL;
- m_pendingEvents = (wxList *) NULL;
+ m_dynamicEvents = NULL;
+ m_pendingEvents = NULL;
// no client data (yet)
m_clientData = NULL;
wxEvtHandler::~wxEvtHandler()
{
- // Takes itself out of the list of handlers
- if (m_previousHandler)
- m_previousHandler->m_nextHandler = m_nextHandler;
-
- if (m_nextHandler)
- m_nextHandler->m_previousHandler = m_previousHandler;
+ Unlink();
if (m_dynamicEvents)
{
wxDynamicEventTableEntry *entry = (wxDynamicEventTableEntry*)*it;
// Remove ourselves from sink destructor notifications
- // (this has usually been been done, in wxTrackable destructor)
- wxEvtHandler *eventSink = entry->m_eventSink;
+ // (this has usually been done, in wxTrackable destructor)
+ wxEvtHandler *eventSink = entry->m_fn->GetEvtHandler();
if ( eventSink )
{
wxEventConnectionRef * const
}
}
- if (entry->m_callbackUserData)
- delete entry->m_callbackUserData;
+ delete entry->m_callbackUserData;
delete entry;
}
delete m_dynamicEvents;
- };
+ }
if (m_pendingEvents)
m_pendingEvents->DeleteContents(true);
delete m_pendingEvents;
- // Remove us from wxPendingEvents if necessary.
- if ( wxPendingEvents )
- {
-#if wxUSE_THREADS
- if (wxPendingEventsLocker)
- wxENTER_CRIT_SECT(*wxPendingEventsLocker);
-#endif
-
- if ( wxPendingEvents->DeleteObject(this) )
- {
- // check that we were present only once in the list
- wxASSERT_MSG( !wxPendingEvents->Find(this),
- "Handler occurs twice in wxPendingEvents list" );
- }
- //else: we weren't in this list at all, it's ok
-
-#if wxUSE_THREADS
- if (wxPendingEventsLocker)
- wxLEAVE_CRIT_SECT(*wxPendingEventsLocker);
-#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 )
delete m_clientObject;
}
+void wxEvtHandler::Unlink()
+{
+ // this event handler must take itself out of the chain of handlers:
+
+ if (m_previousHandler)
+ m_previousHandler->SetNextHandler(m_nextHandler);
+
+ if (m_nextHandler)
+ m_nextHandler->SetPreviousHandler(m_previousHandler);
+
+ m_nextHandler = NULL;
+ m_previousHandler = NULL;
+}
+
+bool wxEvtHandler::IsUnlinked() const
+{
+ return m_previousHandler == NULL &&
+ m_nextHandler == NULL;
+}
+
#if wxUSE_THREADS
bool wxEvtHandler::ProcessThreadEvent(const 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 );
// 2) Add this event handler to list of event handlers that
// have pending events.
- wxENTER_CRIT_SECT(*wxPendingEventsLocker);
-
- if ( !wxPendingEvents )
- wxPendingEvents = new wxList;
- if ( !wxPendingEvents->Find(this) )
- wxPendingEvents->Append(this);
-
- wxLEAVE_CRIT_SECT(*wxPendingEventsLocker);
+ 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
// just added to m_pendingEvents in our ProcessPendingEvents() below before
- // we had time to append this pointer to wxPendingEvents list; thus
+ // we had time to append this pointer to wxHandlersWithPendingEvents list; thus
// breaking the invariant that a handler should be in the list iff it has
// any pending events to process
wxLEAVE_CRIT_SECT( m_pendingEventsLock );
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)
+
wxENTER_CRIT_SECT( m_pendingEventsLock );
// this method is only called by wxApp if this handler does have
"should have pending events if called" );
wxList::compatibility_iterator node = m_pendingEvents->GetFirst();
- wxEventPtr event(static_cast<wxEvent *>(node->GetData()));
+ wxEvent* pEvent = static_cast<wxEvent *>(node->GetData());
+
+ // find the first event which can be processed now:
+ wxEventLoopBase* evtLoop = wxEventLoopBase::GetActive();
+ if (evtLoop && evtLoop->IsYielding())
+ {
+ while (node && pEvent && !evtLoop->IsEventAllowedInsideYield(pEvent->GetEventCategory()))
+ {
+ node = node->GetNext();
+ pEvent = node ? static_cast<wxEvent *>(node->GetData()) : NULL;
+ }
+
+ if (!node)
+ {
+ // all our events are NOT processable now... signal this:
+ 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;
+ }
+ }
+
+ wxEventPtr event(pEvent);
// it's important we remove event from list before processing it, else a
// nested event loop, for example from a modal dialog, might process the
// 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 (wxPendingEventsLocker)
- wxENTER_CRIT_SECT(*wxPendingEventsLocker);
-#endif
- wxPendingEvents->DeleteObject(this);
-#if wxUSE_THREADS
- if (wxPendingEventsLocker)
- wxLEAVE_CRIT_SECT(*wxPendingEventsLocker);
-#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 );
* Event table stuff
*/
/* static */ bool
-wxEvtHandler::ProcessEventIfMatches(const wxEventTableEntryBase& entry,
- wxEvtHandler *handler,
- wxEvent& event)
+wxEvtHandler::ProcessEventIfMatchesId(const wxEventTableEntryBase& entry,
+ wxEvtHandler *handler,
+ wxEvent& event)
{
int tableId1 = entry.m_id,
tableId2 = entry.m_lastId;
// call the handler via wxApp method which allows the user to catch
// any exceptions which may be thrown by any handler in the program
// in one place
- wxTheApp->HandleEvent(handler, (wxEventFunction)entry.m_fn, event);
+ wxTheApp->CallEventHandler(handler, *entry.m_fn, event);
}
else
#endif // wxUSE_EXCEPTIONS
{
- // no need for an extra virtual function call
- (handler->*((wxEventFunction) (entry.m_fn)))(event);
+ (*entry.m_fn)(handler, event);
}
if (!event.GetSkipped())
bool wxEvtHandler::ProcessEvent(wxEvent& event)
{
// allow the application to hook into event processing
- if ( wxTheApp )
+ //
+ // 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() )
{
- int rc = wxTheApp->FilterEvent(event);
- if ( rc != -1 )
+ if ( wxTheApp )
{
- wxASSERT_MSG( rc == 1 || rc == 0,
- _T("unexpected wxApp::FilterEvent return value") );
+ int rc = wxTheApp->FilterEvent(event);
+ if ( rc != -1 )
+ {
+ wxASSERT_MSG( rc == 1 || rc == 0,
+ "unexpected wxApp::FilterEvent return value" );
- return rc != 0;
+ return rc != 0;
+ }
+ //else: proceed normally
}
- //else: proceed normally
}
if ( ProcessEventHere(event) )
return true;
+ // pass the event to the next handler, notice that we shouldn't call
+ // TryParent() even if it doesn't handle the event as the last handler in
+ // the chain will do it
+ if ( GetNextHandler() )
+ return GetNextHandler()->ProcessEvent(event);
+
// propagate the event upwards the window chain and/or to the application
// object if it wasn't processed at this level
return TryParent(event);
bool wxEvtHandler::ProcessEventHere(wxEvent& event)
{
- // An event handler can be enabled or disabled
- if ( GetEvtHandlerEnabled() )
- {
- // if we have a validator, it has higher priority than our own event
- // table
- if ( TryValidator(event) )
- return true;
+ // If the event handler is disabled it doesn't process any events
+ if ( !GetEvtHandlerEnabled() )
+ return false;
- // Handle per-instance dynamic event tables first
- if ( m_dynamicEvents && SearchDynamicEventTable(event) )
- return true;
+ // If we have a validator, it has higher priority than our own event
+ // handlers
+ if ( TryValidator(event) )
+ return true;
- // Then static per-class event tables
- if ( GetEventHashTable().HandleEvent(event, this) )
- return true;
- }
+ // Handle per-instance dynamic event tables first
+ if ( m_dynamicEvents && SearchDynamicEventTable(event) )
+ return true;
- // Try going down the event handler chain
- if ( GetNextHandler() && GetNextHandler()->ProcessEventHere(event) )
+ // Then static per-class event tables
+ if ( GetEventHashTable().HandleEvent(event, this) )
return true;
// We don't have a handler for this event.
const wxEventTableEntry& entry = table.entries[i];
if ( eventType == entry.m_eventType )
{
- if ( ProcessEventIfMatches(entry, this, event) )
+ if ( ProcessEventIfMatchesId(entry, this, event) )
return true;
}
}
return false;
}
-void wxEvtHandler::Connect( int id, int lastId,
- wxEventType eventType,
- wxObjectEventFunction func,
- wxObject *userData,
- wxEvtHandler* eventSink )
+void wxEvtHandler::DoConnect(int id,
+ int lastId,
+ wxEventType eventType,
+ wxEventFunctor *func,
+ wxObject *userData)
{
wxDynamicEventTableEntry *entry =
- new wxDynamicEventTableEntry(eventType, id, lastId, func, userData, eventSink);
+ new wxDynamicEventTableEntry(eventType, id, lastId, func, userData);
if (!m_dynamicEvents)
m_dynamicEvents = new wxList;
m_dynamicEvents->Insert( (wxObject*) entry );
// Make sure we get to know when a sink is destroyed
+ wxEvtHandler *eventSink = func->GetEvtHandler();
if ( eventSink && eventSink != this )
{
wxEventConnectionRef *evtConnRef = FindRefInTrackerList(eventSink);
}
}
-bool wxEvtHandler::Disconnect( int id, int lastId, wxEventType eventType,
- wxObjectEventFunction func,
- wxObject *userData,
- wxEvtHandler* eventSink )
+bool
+wxEvtHandler::DoDisconnect(int id,
+ int lastId,
+ wxEventType eventType,
+ const wxEventFunctor& func,
+ wxObject *userData)
{
if (!m_dynamicEvents)
return false;
// Remove connection from tracker node (wxEventConnectionRef)
+ wxEvtHandler *eventSink = func.GetEvtHandler();
if ( eventSink && eventSink != this )
{
wxEventConnectionRef *evtConnRef = FindRefInTrackerList(eventSink);
if ((entry->m_id == id) &&
((entry->m_lastId == lastId) || (lastId == wxID_ANY)) &&
((entry->m_eventType == eventType) || (eventType == wxEVT_NULL)) &&
- ((entry->m_fn == func) || (func == (wxObjectEventFunction)NULL)) &&
- ((entry->m_eventSink == eventSink) || (eventSink == (wxEvtHandler*)NULL)) &&
- ((entry->m_callbackUserData == userData) || (userData == (wxObject*)NULL)))
+ entry->m_fn->Matches(func) &&
+ ((entry->m_callbackUserData == userData) || !userData))
{
- if (entry->m_callbackUserData)
- delete entry->m_callbackUserData;
+ delete entry->m_callbackUserData;
m_dynamicEvents->Erase( node );
delete entry;
return true;
// call Disconnect() invalidating the current node
node = node->GetNext();
- if ((event.GetEventType() == entry->m_eventType) && (entry->m_fn != 0))
+ if ( event.GetEventType() == entry->m_eventType )
{
- wxEvtHandler *handler = entry->m_eventSink ? entry->m_eventSink
- : this;
- if ( ProcessEventIfMatches(*entry, handler, event) )
+ wxEvtHandler *handler = entry->m_fn->GetEvtHandler();
+ if ( !handler )
+ handler = this;
+ if ( ProcessEventIfMatchesId(*entry, handler, event) )
return true;
}
}
wxDynamicEventTableEntry *entry = (wxDynamicEventTableEntry*)node->GetData();
node_nxt = node->GetNext();
- if ( entry->m_eventSink==sink )
+ if ( entry->m_fn->GetEvtHandler() == sink )
{
- if (entry->m_callbackUserData)
- delete entry->m_callbackUserData;
+ delete entry->m_callbackUserData;
m_dynamicEvents->Erase( node );
delete entry;
}
else
win = win->GetParent();
}
- if (win == (wxWindow*) NULL)
- focusWin = (wxWindow*) NULL;
+ if (win == NULL)
+ focusWin = NULL;
return focusWin;
}
}
#endif // wxUSE_GUI
+