1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/event.cpp 
   3 // Purpose:     Event classes 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  28 #include "wx/evtloop.h" 
  35     #include "wx/stopwatch.h" 
  36     #include "wx/module.h" 
  39         #include "wx/window.h" 
  40         #include "wx/control.h" 
  42         #include "wx/spinbutt.h" 
  43         #include "wx/textctrl.h" 
  44         #include "wx/validate.h" 
  48 #include "wx/thread.h" 
  51     #include "wx/scopedptr.h" 
  53     wxDECLARE_SCOPED_PTR(wxEvent
, wxEventPtr
) 
  54     wxDEFINE_SCOPED_PTR(wxEvent
, wxEventPtr
) 
  57 // ---------------------------------------------------------------------------- 
  59 // ---------------------------------------------------------------------------- 
  62     IMPLEMENT_DYNAMIC_CLASS(wxEvtHandler
, wxObject
) 
  63     IMPLEMENT_ABSTRACT_CLASS(wxEvent
, wxObject
) 
  64     IMPLEMENT_DYNAMIC_CLASS(wxIdleEvent
, wxEvent
) 
  68     IMPLEMENT_DYNAMIC_CLASS(wxCommandEvent
, wxEvent
) 
  69     IMPLEMENT_DYNAMIC_CLASS(wxThreadEvent
, wxCommandEvent
) 
  70     IMPLEMENT_DYNAMIC_CLASS(wxNotifyEvent
, wxCommandEvent
) 
  71     IMPLEMENT_DYNAMIC_CLASS(wxScrollEvent
, wxCommandEvent
) 
  72     IMPLEMENT_DYNAMIC_CLASS(wxScrollWinEvent
, wxEvent
) 
  73     IMPLEMENT_DYNAMIC_CLASS(wxMouseEvent
, wxEvent
) 
  74     IMPLEMENT_DYNAMIC_CLASS(wxKeyEvent
, wxEvent
) 
  75     IMPLEMENT_DYNAMIC_CLASS(wxSizeEvent
, wxEvent
) 
  76     IMPLEMENT_DYNAMIC_CLASS(wxPaintEvent
, wxEvent
) 
  77     IMPLEMENT_DYNAMIC_CLASS(wxNcPaintEvent
, wxEvent
) 
  78     IMPLEMENT_DYNAMIC_CLASS(wxEraseEvent
, wxEvent
) 
  79     IMPLEMENT_DYNAMIC_CLASS(wxMoveEvent
, wxEvent
) 
  80     IMPLEMENT_DYNAMIC_CLASS(wxFocusEvent
, wxEvent
) 
  81     IMPLEMENT_DYNAMIC_CLASS(wxChildFocusEvent
, wxCommandEvent
) 
  82     IMPLEMENT_DYNAMIC_CLASS(wxCloseEvent
, wxEvent
) 
  83     IMPLEMENT_DYNAMIC_CLASS(wxShowEvent
, wxEvent
) 
  84     IMPLEMENT_DYNAMIC_CLASS(wxMaximizeEvent
, wxEvent
) 
  85     IMPLEMENT_DYNAMIC_CLASS(wxIconizeEvent
, wxEvent
) 
  86     IMPLEMENT_DYNAMIC_CLASS(wxMenuEvent
, wxEvent
) 
  87     IMPLEMENT_DYNAMIC_CLASS(wxJoystickEvent
, wxEvent
) 
  88     IMPLEMENT_DYNAMIC_CLASS(wxDropFilesEvent
, wxEvent
) 
  89     IMPLEMENT_DYNAMIC_CLASS(wxActivateEvent
, wxEvent
) 
  90     IMPLEMENT_DYNAMIC_CLASS(wxInitDialogEvent
, wxEvent
) 
  91     IMPLEMENT_DYNAMIC_CLASS(wxSetCursorEvent
, wxEvent
) 
  92     IMPLEMENT_DYNAMIC_CLASS(wxSysColourChangedEvent
, wxEvent
) 
  93     IMPLEMENT_DYNAMIC_CLASS(wxDisplayChangedEvent
, wxEvent
) 
  94     IMPLEMENT_DYNAMIC_CLASS(wxUpdateUIEvent
, wxCommandEvent
) 
  95     IMPLEMENT_DYNAMIC_CLASS(wxNavigationKeyEvent
, wxEvent
) 
  96     IMPLEMENT_DYNAMIC_CLASS(wxPaletteChangedEvent
, wxEvent
) 
  97     IMPLEMENT_DYNAMIC_CLASS(wxQueryNewPaletteEvent
, wxEvent
) 
  98     IMPLEMENT_DYNAMIC_CLASS(wxWindowCreateEvent
, wxEvent
) 
  99     IMPLEMENT_DYNAMIC_CLASS(wxWindowDestroyEvent
, wxEvent
) 
 100     IMPLEMENT_DYNAMIC_CLASS(wxHelpEvent
, wxCommandEvent
) 
 101     IMPLEMENT_DYNAMIC_CLASS(wxContextMenuEvent
, wxCommandEvent
) 
 102     IMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureChangedEvent
, wxEvent
) 
 103     IMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureLostEvent
, wxEvent
) 
 104     IMPLEMENT_DYNAMIC_CLASS(wxClipboardTextEvent
, wxCommandEvent
) 
 109 const wxEventTable 
*wxEvtHandler::GetEventTable() const 
 110     { return &wxEvtHandler::sm_eventTable
; } 
 112 const wxEventTable 
wxEvtHandler::sm_eventTable 
= 
 113     { (const wxEventTable 
*)NULL
, &wxEvtHandler::sm_eventTableEntries
[0] }; 
 115 wxEventHashTable 
&wxEvtHandler::GetEventHashTable() const 
 116     { return wxEvtHandler::sm_eventHashTable
; } 
 118 wxEventHashTable 
wxEvtHandler::sm_eventHashTable(wxEvtHandler::sm_eventTable
); 
 120 const wxEventTableEntry 
wxEvtHandler::sm_eventTableEntries
[] = 
 121     { DECLARE_EVENT_TABLE_TERMINATOR() }; 
 124 // wxUSE_MEMORY_TRACING considers memory freed from the static objects dtors 
 125 // leaked, so we need to manually clean up all event tables before checking for 
 126 // the memory leaks when using it, however this breaks re-initializing the 
 127 // library (i.e. repeated calls to wxInitialize/wxUninitialize) because the 
 128 // event tables won't be rebuilt the next time, so disable this by default 
 129 #if wxUSE_MEMORY_TRACING 
 131 class wxEventTableEntryModule
: public wxModule
 
 134     wxEventTableEntryModule() { } 
 135     virtual bool OnInit() { return true; } 
 136     virtual void OnExit() { wxEventHashTable::ClearAll(); } 
 138     DECLARE_DYNAMIC_CLASS(wxEventTableEntryModule
) 
 141 IMPLEMENT_DYNAMIC_CLASS(wxEventTableEntryModule
, wxModule
) 
 143 #endif // wxUSE_MEMORY_TRACING 
 145 // ---------------------------------------------------------------------------- 
 147 // ---------------------------------------------------------------------------- 
 149 // common event types are defined here, other event types are defined by the 
 150 // components which use them 
 152 const wxEventType wxEVT_FIRST 
= 10000; 
 153 const wxEventType wxEVT_USER_FIRST 
= wxEVT_FIRST 
+ 2000; 
 155 DEFINE_EVENT_TYPE(wxEVT_NULL
) 
 156 wxDEFINE_EVENT( wxEVT_IDLE
, wxIdleEvent 
); 
 162 wxDEFINE_EVENT( wxEVT_COMMAND_BUTTON_CLICKED
, wxCommandEvent 
); 
 163 wxDEFINE_EVENT( wxEVT_COMMAND_CHECKBOX_CLICKED
, wxCommandEvent 
); 
 164 wxDEFINE_EVENT( wxEVT_COMMAND_CHOICE_SELECTED
, wxCommandEvent 
); 
 165 wxDEFINE_EVENT( wxEVT_COMMAND_LISTBOX_SELECTED
, wxCommandEvent 
); 
 166 wxDEFINE_EVENT( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
, wxCommandEvent 
); 
 167 wxDEFINE_EVENT( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
, wxCommandEvent 
); 
 168 wxDEFINE_EVENT( wxEVT_COMMAND_MENU_SELECTED
, wxCommandEvent 
); 
 169 wxDEFINE_EVENT( wxEVT_COMMAND_SLIDER_UPDATED
, wxCommandEvent 
); 
 170 wxDEFINE_EVENT( wxEVT_COMMAND_RADIOBOX_SELECTED
, wxCommandEvent 
); 
 171 wxDEFINE_EVENT( wxEVT_COMMAND_RADIOBUTTON_SELECTED
, wxCommandEvent 
); 
 172 wxDEFINE_EVENT( wxEVT_COMMAND_SCROLLBAR_UPDATED
, wxCommandEvent 
); 
 173 wxDEFINE_EVENT( wxEVT_COMMAND_VLBOX_SELECTED
, wxCommandEvent 
); 
 174 wxDEFINE_EVENT( wxEVT_COMMAND_COMBOBOX_SELECTED
, wxCommandEvent 
); 
 175 wxDEFINE_EVENT( wxEVT_COMMAND_TOOL_RCLICKED
, wxCommandEvent 
); 
 176 wxDEFINE_EVENT( wxEVT_COMMAND_TOOL_ENTER
, wxCommandEvent 
); 
 177 wxDEFINE_EVENT( wxEVT_COMMAND_SPINCTRL_UPDATED
, wxCommandEvent 
); 
 178 wxDEFINE_EVENT( wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED
, wxCommandEvent 
); 
 179 wxDEFINE_EVENT( wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED
, wxCommandEvent 
); 
 180 wxDEFINE_EVENT( wxEVT_COMMAND_COMBOBOX_DROPDOWN
, wxCommandEvent
); 
 181 wxDEFINE_EVENT( wxEVT_COMMAND_COMBOBOX_CLOSEUP
, wxCommandEvent
); 
 184 wxDEFINE_EVENT( wxEVT_LEFT_DOWN
, wxMouseEvent 
); 
 185 wxDEFINE_EVENT( wxEVT_LEFT_UP
, wxMouseEvent 
); 
 186 wxDEFINE_EVENT( wxEVT_MIDDLE_DOWN
, wxMouseEvent 
); 
 187 wxDEFINE_EVENT( wxEVT_MIDDLE_UP
, wxMouseEvent 
); 
 188 wxDEFINE_EVENT( wxEVT_RIGHT_DOWN
, wxMouseEvent 
); 
 189 wxDEFINE_EVENT( wxEVT_RIGHT_UP
, wxMouseEvent 
); 
 190 wxDEFINE_EVENT( wxEVT_MOTION
, wxMouseEvent 
); 
 191 wxDEFINE_EVENT( wxEVT_ENTER_WINDOW
, wxMouseEvent 
); 
 192 wxDEFINE_EVENT( wxEVT_LEAVE_WINDOW
, wxMouseEvent 
); 
 193 wxDEFINE_EVENT( wxEVT_LEFT_DCLICK
, wxMouseEvent 
); 
 194 wxDEFINE_EVENT( wxEVT_MIDDLE_DCLICK
, wxMouseEvent 
); 
 195 wxDEFINE_EVENT( wxEVT_RIGHT_DCLICK
, wxMouseEvent 
); 
 196 wxDEFINE_EVENT( wxEVT_SET_FOCUS
, wxFocusEvent 
); 
 197 wxDEFINE_EVENT( wxEVT_KILL_FOCUS
, wxFocusEvent 
); 
 198 wxDEFINE_EVENT( wxEVT_CHILD_FOCUS
, wxChildFocusEvent 
); 
 199 wxDEFINE_EVENT( wxEVT_MOUSEWHEEL
, wxMouseEvent 
); 
 200 wxDEFINE_EVENT( wxEVT_AUX1_DOWN
, wxMouseEvent 
); 
 201 wxDEFINE_EVENT( wxEVT_AUX1_UP
, wxMouseEvent 
); 
 202 wxDEFINE_EVENT( wxEVT_AUX1_DCLICK
, wxMouseEvent 
); 
 203 wxDEFINE_EVENT( wxEVT_AUX2_DOWN
, wxMouseEvent 
); 
 204 wxDEFINE_EVENT( wxEVT_AUX2_UP
, wxMouseEvent 
); 
 205 wxDEFINE_EVENT( wxEVT_AUX2_DCLICK
, wxMouseEvent 
); 
 207 // Character input event type 
 208 wxDEFINE_EVENT( wxEVT_CHAR
, wxKeyEvent 
); 
 209 wxDEFINE_EVENT( wxEVT_CHAR_HOOK
, wxKeyEvent 
); 
 210 wxDEFINE_EVENT( wxEVT_NAVIGATION_KEY
, wxNavigationKeyEvent 
); 
 211 wxDEFINE_EVENT( wxEVT_KEY_DOWN
, wxKeyEvent 
); 
 212 wxDEFINE_EVENT( wxEVT_KEY_UP
, wxKeyEvent 
); 
 214 wxDEFINE_EVENT( wxEVT_HOTKEY
, wxKeyEvent 
); 
 218 wxDEFINE_EVENT( wxEVT_SET_CURSOR
, wxSetCursorEvent 
); 
 220 // wxScrollbar and wxSlider event identifiers 
 221 wxDEFINE_EVENT( wxEVT_SCROLL_TOP
, wxScrollEvent 
); 
 222 wxDEFINE_EVENT( wxEVT_SCROLL_BOTTOM
, wxScrollEvent 
); 
 223 wxDEFINE_EVENT( wxEVT_SCROLL_LINEUP
, wxScrollEvent 
); 
 224 wxDEFINE_EVENT( wxEVT_SCROLL_LINEDOWN
, wxScrollEvent 
); 
 225 wxDEFINE_EVENT( wxEVT_SCROLL_PAGEUP
, wxScrollEvent 
); 
 226 wxDEFINE_EVENT( wxEVT_SCROLL_PAGEDOWN
, wxScrollEvent 
); 
 227 wxDEFINE_EVENT( wxEVT_SCROLL_THUMBTRACK
, wxScrollEvent 
); 
 228 wxDEFINE_EVENT( wxEVT_SCROLL_THUMBRELEASE
, wxScrollEvent 
); 
 229 wxDEFINE_EVENT( wxEVT_SCROLL_CHANGED
, wxScrollEvent 
); 
 231 // Due to a bug in older wx versions, wxSpinEvents were being sent with type of 
 232 // wxEVT_SCROLL_LINEUP, wxEVT_SCROLL_LINEDOWN and wxEVT_SCROLL_THUMBTRACK. But 
 233 // with the type-safe events in place, these event types are associated with 
 234 // wxScrollEvent. To allow handling of spin events, new event types have been 
 235 // defined in spinbutt.h/spinnbuttcmn.cpp. To maintain backward compatibility 
 236 // the spin event types are being initialized with the scroll event types. 
 240 wxDEFINE_EVENT_ALIAS( wxEVT_SPIN_UP
,   wxSpinEvent
, wxEVT_SCROLL_LINEUP 
); 
 241 wxDEFINE_EVENT_ALIAS( wxEVT_SPIN_DOWN
, wxSpinEvent
, wxEVT_SCROLL_LINEDOWN 
); 
 242 wxDEFINE_EVENT_ALIAS( wxEVT_SPIN
,      wxSpinEvent
, wxEVT_SCROLL_THUMBTRACK 
); 
 244 #endif // wxUSE_SPINBTN 
 246 // Scroll events from wxWindow 
 247 wxDEFINE_EVENT( wxEVT_SCROLLWIN_TOP
, wxScrollWinEvent 
); 
 248 wxDEFINE_EVENT( wxEVT_SCROLLWIN_BOTTOM
, wxScrollWinEvent 
); 
 249 wxDEFINE_EVENT( wxEVT_SCROLLWIN_LINEUP
, wxScrollWinEvent 
); 
 250 wxDEFINE_EVENT( wxEVT_SCROLLWIN_LINEDOWN
, wxScrollWinEvent 
); 
 251 wxDEFINE_EVENT( wxEVT_SCROLLWIN_PAGEUP
, wxScrollWinEvent 
); 
 252 wxDEFINE_EVENT( wxEVT_SCROLLWIN_PAGEDOWN
, wxScrollWinEvent 
); 
 253 wxDEFINE_EVENT( wxEVT_SCROLLWIN_THUMBTRACK
, wxScrollWinEvent 
); 
 254 wxDEFINE_EVENT( wxEVT_SCROLLWIN_THUMBRELEASE
, wxScrollWinEvent 
); 
 257 wxDEFINE_EVENT( wxEVT_SIZE
, wxSizeEvent 
); 
 258 wxDEFINE_EVENT( wxEVT_SIZING
, wxSizeEvent 
); 
 259 wxDEFINE_EVENT( wxEVT_MOVE
, wxMoveEvent 
); 
 260 wxDEFINE_EVENT( wxEVT_MOVING
, wxMoveEvent 
); 
 261 wxDEFINE_EVENT( wxEVT_MOVE_START
, wxMoveEvent 
); 
 262 wxDEFINE_EVENT( wxEVT_MOVE_END
, wxMoveEvent 
); 
 263 wxDEFINE_EVENT( wxEVT_CLOSE_WINDOW
, wxCloseEvent 
); 
 264 wxDEFINE_EVENT( wxEVT_END_SESSION
, wxCloseEvent 
); 
 265 wxDEFINE_EVENT( wxEVT_QUERY_END_SESSION
, wxCloseEvent 
); 
 266 wxDEFINE_EVENT( wxEVT_HIBERNATE
, wxActivateEvent 
); 
 267 wxDEFINE_EVENT( wxEVT_ACTIVATE_APP
, wxActivateEvent 
); 
 268 wxDEFINE_EVENT( wxEVT_ACTIVATE
, wxActivateEvent 
); 
 269 wxDEFINE_EVENT( wxEVT_CREATE
, wxWindowCreateEvent 
); 
 270 wxDEFINE_EVENT( wxEVT_DESTROY
, wxWindowDestroyEvent 
); 
 271 wxDEFINE_EVENT( wxEVT_SHOW
, wxShowEvent 
); 
 272 wxDEFINE_EVENT( wxEVT_ICONIZE
, wxIconizeEvent 
); 
 273 wxDEFINE_EVENT( wxEVT_MAXIMIZE
, wxMaximizeEvent 
); 
 274 wxDEFINE_EVENT( wxEVT_MOUSE_CAPTURE_CHANGED
, wxMouseCaptureChangedEvent 
); 
 275 wxDEFINE_EVENT( wxEVT_MOUSE_CAPTURE_LOST
, wxMouseCaptureLostEvent 
); 
 276 wxDEFINE_EVENT( wxEVT_PAINT
, wxPaintEvent 
); 
 277 wxDEFINE_EVENT( wxEVT_ERASE_BACKGROUND
, wxEraseEvent 
); 
 278 wxDEFINE_EVENT( wxEVT_NC_PAINT
, wxNcPaintEvent 
); 
 279 wxDEFINE_EVENT( wxEVT_MENU_OPEN
, wxMenuEvent 
); 
 280 wxDEFINE_EVENT( wxEVT_MENU_CLOSE
, wxMenuEvent 
); 
 281 wxDEFINE_EVENT( wxEVT_MENU_HIGHLIGHT
, wxMenuEvent 
); 
 282 wxDEFINE_EVENT( wxEVT_CONTEXT_MENU
, wxContextMenuEvent 
); 
 283 wxDEFINE_EVENT( wxEVT_SYS_COLOUR_CHANGED
, wxSysColourChangedEvent 
); 
 284 wxDEFINE_EVENT( wxEVT_DISPLAY_CHANGED
, wxDisplayChangedEvent 
); 
 285 wxDEFINE_EVENT( wxEVT_QUERY_NEW_PALETTE
, wxQueryNewPaletteEvent 
); 
 286 wxDEFINE_EVENT( wxEVT_PALETTE_CHANGED
, wxPaletteChangedEvent 
); 
 287 wxDEFINE_EVENT( wxEVT_JOY_BUTTON_DOWN
, wxJoystickEvent 
); 
 288 wxDEFINE_EVENT( wxEVT_JOY_BUTTON_UP
, wxJoystickEvent 
); 
 289 wxDEFINE_EVENT( wxEVT_JOY_MOVE
, wxJoystickEvent 
); 
 290 wxDEFINE_EVENT( wxEVT_JOY_ZMOVE
, wxJoystickEvent 
); 
 291 wxDEFINE_EVENT( wxEVT_DROP_FILES
, wxDropFilesEvent 
); 
 292 wxDEFINE_EVENT( wxEVT_INIT_DIALOG
, wxInitDialogEvent 
); 
 293 wxDEFINE_EVENT( wxEVT_UPDATE_UI
, wxUpdateUIEvent 
); 
 296 wxDEFINE_EVENT( wxEVT_COMMAND_TEXT_COPY
, wxClipboardTextEvent 
); 
 297 wxDEFINE_EVENT( wxEVT_COMMAND_TEXT_CUT
, wxClipboardTextEvent 
); 
 298 wxDEFINE_EVENT( wxEVT_COMMAND_TEXT_PASTE
, wxClipboardTextEvent 
); 
 300 // Generic command events 
 301 // Note: a click is a higher-level event than button down/up 
 302 wxDEFINE_EVENT( wxEVT_COMMAND_LEFT_CLICK
, wxCommandEvent 
); 
 303 wxDEFINE_EVENT( wxEVT_COMMAND_LEFT_DCLICK
, wxCommandEvent 
); 
 304 wxDEFINE_EVENT( wxEVT_COMMAND_RIGHT_CLICK
, wxCommandEvent 
); 
 305 wxDEFINE_EVENT( wxEVT_COMMAND_RIGHT_DCLICK
, wxCommandEvent 
); 
 306 wxDEFINE_EVENT( wxEVT_COMMAND_SET_FOCUS
, wxCommandEvent 
); 
 307 wxDEFINE_EVENT( wxEVT_COMMAND_KILL_FOCUS
, wxCommandEvent 
); 
 308 wxDEFINE_EVENT( wxEVT_COMMAND_ENTER
, wxCommandEvent 
); 
 311 wxDEFINE_EVENT( wxEVT_HELP
, wxHelpEvent 
); 
 312 wxDEFINE_EVENT( wxEVT_DETAILED_HELP
, wxHelpEvent 
); 
 315 wxDEFINE_EVENT( wxEVT_COMMAND_THREAD
, wxThreadEvent 
); 
 321 wxIdleMode 
wxIdleEvent::sm_idleMode 
= wxIDLE_PROCESS_ALL
; 
 323 // ============================================================================ 
 325 // ============================================================================ 
 327 // ---------------------------------------------------------------------------- 
 328 // event initialization 
 329 // ---------------------------------------------------------------------------- 
 334     static int s_lastUsedEventType 
= wxEVT_FIRST
; 
 336     return s_lastUsedEventType
++; 
 338 // ---------------------------------------------------------------------------- 
 340 // ---------------------------------------------------------------------------- 
 342 wxEventFunctor::~wxEventFunctor() 
 346 // ---------------------------------------------------------------------------- 
 348 // ---------------------------------------------------------------------------- 
 351  * General wxWidgets events, covering all interesting things that might happen 
 352  * (button clicking, resizing, setting text in widgets, etc.). 
 354  * For each completely new event type, derive a new event class. 
 358 wxEvent::wxEvent(int theId
, wxEventType commandType
) 
 360     m_eventType 
= commandType
; 
 361     m_eventObject 
= NULL
; 
 365     m_callbackUserData 
= NULL
; 
 366     m_isCommandEvent 
= false; 
 367     m_propagationLevel 
= wxEVENT_PROPAGATE_NONE
; 
 368     m_wasProcessed 
= false; 
 369     m_processHereOnly 
= false; 
 372 wxEvent::wxEvent(const wxEvent
& src
) 
 374     , m_eventObject(src
.m_eventObject
) 
 375     , m_eventType(src
.m_eventType
) 
 376     , m_timeStamp(src
.m_timeStamp
) 
 378     , m_callbackUserData(src
.m_callbackUserData
) 
 379     , m_propagationLevel(src
.m_propagationLevel
) 
 380     , m_skipped(src
.m_skipped
) 
 381     , m_isCommandEvent(src
.m_isCommandEvent
) 
 382     , m_wasProcessed(false) 
 383     , m_processHereOnly(false) 
 387 wxEvent
& wxEvent::operator=(const wxEvent
& src
) 
 389     wxObject::operator=(src
); 
 391     m_eventObject 
= src
.m_eventObject
; 
 392     m_eventType 
= src
.m_eventType
; 
 393     m_timeStamp 
= src
.m_timeStamp
; 
 395     m_callbackUserData 
= src
.m_callbackUserData
; 
 396     m_propagationLevel 
= src
.m_propagationLevel
; 
 397     m_skipped 
= src
.m_skipped
; 
 398     m_isCommandEvent 
= src
.m_isCommandEvent
; 
 400     // don't change m_wasProcessed nor m_processHereOnly 
 409 // ---------------------------------------------------------------------------- 
 411 // ---------------------------------------------------------------------------- 
 414     // 'this' : used in base member initializer list (for m_commandString) 
 415     #pragma warning(disable:4355) 
 418 wxCommandEvent::wxCommandEvent(wxEventType commandType
, int theId
) 
 419               : wxEvent(theId
, commandType
) 
 422     m_clientObject 
= NULL
; 
 425     m_isCommandEvent 
= true; 
 427     // the command events are propagated upwards by default 
 428     m_propagationLevel 
= wxEVENT_PROPAGATE_MAX
; 
 432     #pragma warning(default:4355) 
 435 wxString 
wxCommandEvent::GetString() const 
 437     if (m_eventType 
!= wxEVT_COMMAND_TEXT_UPDATED 
|| !m_eventObject
) 
 444         wxTextCtrl 
*txt 
= wxDynamicCast(m_eventObject
, wxTextCtrl
); 
 446             return txt
->GetValue(); 
 448 #endif // wxUSE_TEXTCTRL 
 453 // ---------------------------------------------------------------------------- 
 455 // ---------------------------------------------------------------------------- 
 458 wxLongLong 
wxUpdateUIEvent::sm_lastUpdate 
= 0; 
 461 long wxUpdateUIEvent::sm_updateInterval 
= 0; 
 463 wxUpdateUIMode 
wxUpdateUIEvent::sm_updateMode 
= wxUPDATE_UI_PROCESS_ALL
; 
 466 bool wxUpdateUIEvent::CanUpdate(wxWindowBase 
*win
) 
 468     // Don't update if we've switched global updating off 
 469     // and this window doesn't support updates. 
 471        (GetMode() == wxUPDATE_UI_PROCESS_SPECIFIED 
&& 
 472        ((win
->GetExtraStyle() & wxWS_EX_PROCESS_UI_UPDATES
) == 0))) 
 475     if (sm_updateInterval 
== -1) 
 478     if (sm_updateInterval 
== 0) 
 481 #if wxUSE_STOPWATCH && wxUSE_LONGLONG 
 482     wxLongLong now 
= wxGetLocalTimeMillis(); 
 483     if (now 
> (sm_lastUpdate 
+ sm_updateInterval
)) 
 490     // If we don't have wxStopWatch or wxLongLong, we 
 491     // should err on the safe side and update now anyway. 
 496 // Reset the update time to provide a delay until the next 
 497 // time we should update 
 498 void wxUpdateUIEvent::ResetUpdateTime() 
 500 #if wxUSE_STOPWATCH && wxUSE_LONGLONG 
 501     if (sm_updateInterval 
> 0) 
 503         wxLongLong now 
= wxGetLocalTimeMillis(); 
 504         if (now 
> (sm_lastUpdate 
+ sm_updateInterval
)) 
 512 // ---------------------------------------------------------------------------- 
 514 // ---------------------------------------------------------------------------- 
 516 wxScrollEvent::wxScrollEvent(wxEventType commandType
, 
 520     : wxCommandEvent(commandType
, id
) 
 522     m_extraLong 
= orient
; 
 526 // ---------------------------------------------------------------------------- 
 528 // ---------------------------------------------------------------------------- 
 530 wxScrollWinEvent::wxScrollWinEvent(wxEventType commandType
, 
 534     m_eventType 
= commandType
; 
 535     m_extraLong 
= orient
; 
 539 // ---------------------------------------------------------------------------- 
 541 // ---------------------------------------------------------------------------- 
 543 wxMouseEvent::wxMouseEvent(wxEventType commandType
) 
 545     m_eventType 
= commandType
; 
 551     m_middleDown 
= false; 
 560     m_linesPerAction 
= 0; 
 564 void wxMouseEvent::Assign(const wxMouseEvent
& event
) 
 566     wxEvent::operator=(event
); 
 568     // Borland C++ 5.82 doesn't compile an explicit call to an implicitly 
 569     // defined operator=() so need to do it this way: 
 570     *static_cast<wxMouseState 
*>(this) = event
; 
 575     m_leftDown 
= event
.m_leftDown
; 
 576     m_middleDown 
= event
.m_middleDown
; 
 577     m_rightDown 
= event
.m_rightDown
; 
 578     m_aux1Down 
= event
.m_aux1Down
; 
 579     m_aux2Down 
= event
.m_aux2Down
; 
 581     m_wheelRotation 
= event
.m_wheelRotation
; 
 582     m_wheelDelta 
= event
.m_wheelDelta
; 
 583     m_linesPerAction 
= event
.m_linesPerAction
; 
 584     m_wheelAxis 
= event
.m_wheelAxis
; 
 587 // return true if was a button dclick event 
 588 bool wxMouseEvent::ButtonDClick(int but
) const 
 593             wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::ButtonDClick")); 
 596         case wxMOUSE_BTN_ANY
: 
 597             return (LeftDClick() || MiddleDClick() || RightDClick() || 
 598                     Aux1DClick() || Aux2DClick()); 
 600         case wxMOUSE_BTN_LEFT
: 
 603         case wxMOUSE_BTN_MIDDLE
: 
 604             return MiddleDClick(); 
 606         case wxMOUSE_BTN_RIGHT
: 
 607             return RightDClick(); 
 609         case wxMOUSE_BTN_AUX1
: 
 612         case wxMOUSE_BTN_AUX2
: 
 617 // return true if was a button down event 
 618 bool wxMouseEvent::ButtonDown(int but
) const 
 623             wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::ButtonDown")); 
 626         case wxMOUSE_BTN_ANY
: 
 627             return (LeftDown() || MiddleDown() || RightDown() || 
 628                     Aux1Down() || Aux2Down()); 
 630         case wxMOUSE_BTN_LEFT
: 
 633         case wxMOUSE_BTN_MIDDLE
: 
 636         case wxMOUSE_BTN_RIGHT
: 
 639         case wxMOUSE_BTN_AUX1
: 
 642         case wxMOUSE_BTN_AUX2
: 
 647 // return true if was a button up event 
 648 bool wxMouseEvent::ButtonUp(int but
) const 
 653             wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::ButtonUp")); 
 656         case wxMOUSE_BTN_ANY
: 
 657             return (LeftUp() || MiddleUp() || RightUp() || 
 658                     Aux1Up() || Aux2Up()); 
 660         case wxMOUSE_BTN_LEFT
: 
 663         case wxMOUSE_BTN_MIDDLE
: 
 666         case wxMOUSE_BTN_RIGHT
: 
 669         case wxMOUSE_BTN_AUX1
: 
 672         case wxMOUSE_BTN_AUX2
: 
 677 // return true if the given button is currently changing state 
 678 bool wxMouseEvent::Button(int but
) const 
 683             wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::Button")); 
 686         case wxMOUSE_BTN_ANY
: 
 687             return ButtonUp(wxMOUSE_BTN_ANY
) || 
 688                     ButtonDown(wxMOUSE_BTN_ANY
) || 
 689                         ButtonDClick(wxMOUSE_BTN_ANY
); 
 691         case wxMOUSE_BTN_LEFT
: 
 692             return LeftDown() || LeftUp() || LeftDClick(); 
 694         case wxMOUSE_BTN_MIDDLE
: 
 695             return MiddleDown() || MiddleUp() || MiddleDClick(); 
 697         case wxMOUSE_BTN_RIGHT
: 
 698             return RightDown() || RightUp() || RightDClick(); 
 700         case wxMOUSE_BTN_AUX1
: 
 701            return Aux1Down() || Aux1Up() || Aux1DClick(); 
 703         case wxMOUSE_BTN_AUX2
: 
 704            return Aux2Down() || Aux2Up() || Aux2DClick(); 
 708 int wxMouseEvent::GetButton() const 
 710     for ( int i 
= 1; i 
< wxMOUSE_BTN_MAX
; i
++ ) 
 718     return wxMOUSE_BTN_NONE
; 
 721 // Find the logical position of the event given the DC 
 722 wxPoint 
wxMouseEvent::GetLogicalPosition(const wxDC
& dc
) const 
 724     wxPoint 
pt(dc
.DeviceToLogicalX(m_x
), dc
.DeviceToLogicalY(m_y
)); 
 728 // ---------------------------------------------------------------------------- 
 730 // ---------------------------------------------------------------------------- 
 732 wxKeyEvent::wxKeyEvent(wxEventType type
) 
 741 wxKeyEvent::wxKeyEvent(const wxKeyEvent
& evt
) 
 748     m_keyCode 
= evt
.m_keyCode
; 
 749     m_rawCode 
= evt
.m_rawCode
; 
 750     m_rawFlags 
= evt
.m_rawFlags
; 
 753     m_uniChar 
= evt
.m_uniChar
; 
 757 bool wxKeyEvent::IsKeyInCategory(int category
) const 
 759     switch ( GetKeyCode() ) 
 765         case WXK_NUMPAD_LEFT
: 
 766         case WXK_NUMPAD_RIGHT
: 
 768         case WXK_NUMPAD_DOWN
: 
 769             return (category 
& WXK_CATEGORY_ARROW
) != 0; 
 773         case WXK_NUMPAD_PAGEUP
: 
 774         case WXK_NUMPAD_PAGEDOWN
: 
 775             return (category 
& WXK_CATEGORY_PAGING
) != 0; 
 779         case WXK_NUMPAD_HOME
: 
 781             return (category 
& WXK_CATEGORY_JUMP
) != 0; 
 785             return (category 
& WXK_CATEGORY_TAB
) != 0; 
 789         case WXK_NUMPAD_DELETE
: 
 790             return (category 
& WXK_CATEGORY_CUT
) != 0; 
 797 // ---------------------------------------------------------------------------- 
 798 // wxWindowCreateEvent 
 799 // ---------------------------------------------------------------------------- 
 801 wxWindowCreateEvent::wxWindowCreateEvent(wxWindow 
*win
) 
 803     SetEventType(wxEVT_CREATE
); 
 807 // ---------------------------------------------------------------------------- 
 808 // wxWindowDestroyEvent 
 809 // ---------------------------------------------------------------------------- 
 811 wxWindowDestroyEvent::wxWindowDestroyEvent(wxWindow 
*win
) 
 813     SetEventType(wxEVT_DESTROY
); 
 817 // ---------------------------------------------------------------------------- 
 819 // ---------------------------------------------------------------------------- 
 821 wxChildFocusEvent::wxChildFocusEvent(wxWindow 
*win
) 
 822                  : wxCommandEvent(wxEVT_CHILD_FOCUS
) 
 827 // ---------------------------------------------------------------------------- 
 829 // ---------------------------------------------------------------------------- 
 832 wxHelpEvent::Origin 
wxHelpEvent::GuessOrigin(Origin origin
) 
 834     if ( origin 
== Origin_Unknown 
) 
 836         // assume that the event comes from the help button if it's not from 
 837         // keyboard and that pressing F1 always results in the help event 
 838         origin 
= wxGetKeyState(WXK_F1
) ? Origin_Keyboard 
: Origin_HelpButton
; 
 849 // ---------------------------------------------------------------------------- 
 851 // ---------------------------------------------------------------------------- 
 853 static const int EVENT_TYPE_TABLE_INIT_SIZE 
= 31; // Not too big not too small... 
 855 wxEventHashTable
* wxEventHashTable::sm_first 
= NULL
; 
 857 wxEventHashTable::wxEventHashTable(const wxEventTable 
&table
) 
 861     AllocEventTypeTable(EVENT_TYPE_TABLE_INIT_SIZE
); 
 865         m_next
->m_previous 
= this; 
 869 wxEventHashTable::~wxEventHashTable() 
 872         m_next
->m_previous 
= m_previous
; 
 874         m_previous
->m_next 
= m_next
; 
 875     if (sm_first 
== this) 
 881 void wxEventHashTable::Clear() 
 883     for ( size_t i 
= 0; i 
< m_size
; i
++ ) 
 885         EventTypeTablePointer  eTTnode 
= m_eventTypeTable
[i
]; 
 889     delete[] m_eventTypeTable
; 
 890     m_eventTypeTable 
= NULL
; 
 895 #if wxUSE_MEMORY_TRACING 
 898 void wxEventHashTable::ClearAll() 
 900     wxEventHashTable
* table 
= sm_first
; 
 904         table 
= table
->m_next
; 
 908 #endif // wxUSE_MEMORY_TRACING 
 910 bool wxEventHashTable::HandleEvent(wxEvent 
&event
, wxEvtHandler 
*self
) 
 915         m_rebuildHash 
= false; 
 918     if (!m_eventTypeTable
) 
 921     // Find all entries for the given event type. 
 922     wxEventType eventType 
= event
.GetEventType(); 
 923     const EventTypeTablePointer eTTnode 
= m_eventTypeTable
[eventType 
% m_size
]; 
 924     if (eTTnode 
&& eTTnode
->eventType 
== eventType
) 
 926         // Now start the search for an event handler 
 927         // that can handle an event with the given ID. 
 928         const wxEventTableEntryPointerArray
& 
 929             eventEntryTable 
= eTTnode
->eventEntryTable
; 
 931         const size_t count 
= eventEntryTable
.GetCount(); 
 932         for (size_t n 
= 0; n 
< count
; n
++) 
 934             const wxEventTableEntry
& entry 
= *eventEntryTable
[n
]; 
 935             if ( wxEvtHandler::ProcessEventIfMatchesId(entry
, self
, event
) ) 
 943 void wxEventHashTable::InitHashTable() 
 945     // Loop over the event tables and all its base tables. 
 946     const wxEventTable 
*table 
= &m_table
; 
 949         // Retrieve all valid event handler entries 
 950         const wxEventTableEntry 
*entry 
= table
->entries
; 
 951         while (entry
->m_fn 
!= 0) 
 953             // Add the event entry in the Hash. 
 959         table 
= table
->baseTable
; 
 962     // Lets free some memory. 
 964     for(i 
= 0; i 
< m_size
; i
++) 
 966         EventTypeTablePointer  eTTnode 
= m_eventTypeTable
[i
]; 
 969             eTTnode
->eventEntryTable
.Shrink(); 
 974 void wxEventHashTable::AddEntry(const wxEventTableEntry 
&entry
) 
 976     // This might happen 'accidentally' as the app is exiting 
 977     if (!m_eventTypeTable
) 
 980     EventTypeTablePointer 
*peTTnode 
= &m_eventTypeTable
[entry
.m_eventType 
% m_size
]; 
 981     EventTypeTablePointer  eTTnode 
= *peTTnode
; 
 985         if (eTTnode
->eventType 
!= entry
.m_eventType
) 
 988             GrowEventTypeTable(); 
 989             // Try again to add it. 
 996         eTTnode 
= new EventTypeTable
; 
 997         eTTnode
->eventType 
= entry
.m_eventType
; 
1001     // Fill all hash entries between entry.m_id and entry.m_lastId... 
1002     eTTnode
->eventEntryTable
.Add(&entry
); 
1005 void wxEventHashTable::AllocEventTypeTable(size_t size
) 
1007     m_eventTypeTable 
= new EventTypeTablePointer
[size
]; 
1008     memset((void *)m_eventTypeTable
, 0, sizeof(EventTypeTablePointer
)*size
); 
1012 void wxEventHashTable::GrowEventTypeTable() 
1014     size_t oldSize 
= m_size
; 
1015     EventTypeTablePointer 
*oldEventTypeTable 
= m_eventTypeTable
; 
1017     // TODO: Search the most optimal grow sequence 
1018     AllocEventTypeTable(/* GetNextPrime(oldSize) */oldSize
*2+1); 
1020     for ( size_t i 
= 0; i 
< oldSize
; /* */ ) 
1022         EventTypeTablePointer  eTToldNode 
= oldEventTypeTable
[i
]; 
1025             EventTypeTablePointer 
*peTTnode 
= &m_eventTypeTable
[eTToldNode
->eventType 
% m_size
]; 
1026             EventTypeTablePointer  eTTnode 
= *peTTnode
; 
1028             // Check for collision, we don't want any. 
1031                 GrowEventTypeTable(); 
1032                 continue; // Don't increment the counter, 
1033                           // as we still need to add this element. 
1037                 // Get the old value and put it in the new table. 
1038                 *peTTnode 
= oldEventTypeTable
[i
]; 
1045     delete[] oldEventTypeTable
; 
1048 // ---------------------------------------------------------------------------- 
1050 // ---------------------------------------------------------------------------- 
1052 wxEvtHandler::wxEvtHandler() 
1054     m_nextHandler 
= NULL
; 
1055     m_previousHandler 
= NULL
; 
1057     m_dynamicEvents 
= NULL
; 
1058     m_pendingEvents 
= NULL
; 
1060     // no client data (yet) 
1061     m_clientData 
= NULL
; 
1062     m_clientDataType 
= wxClientData_None
; 
1065 wxEvtHandler::~wxEvtHandler() 
1069     if (m_dynamicEvents
) 
1071         for ( wxList::iterator it 
= m_dynamicEvents
->begin(), 
1072                                end 
= m_dynamicEvents
->end(); 
1076             wxDynamicEventTableEntry 
*entry 
= (wxDynamicEventTableEntry
*)*it
; 
1078             // Remove ourselves from sink destructor notifications 
1079             // (this has usually been done, in wxTrackable destructor) 
1080             wxEvtHandler 
*eventSink 
= entry
->m_fn
->GetEvtHandler(); 
1083                 wxEventConnectionRef 
* const 
1084                     evtConnRef 
= FindRefInTrackerList(eventSink
); 
1087                     eventSink
->RemoveNode(evtConnRef
); 
1092             delete entry
->m_callbackUserData
; 
1095         delete m_dynamicEvents
; 
1098     // Remove us from the list of the pending events if necessary. 
1100         wxTheApp
->RemovePendingEventHandler(this); 
1102     DeletePendingEvents(); 
1104     // we only delete object data, not untyped 
1105     if ( m_clientDataType 
== wxClientData_Object 
) 
1106         delete m_clientObject
; 
1109 void wxEvtHandler::Unlink() 
1111     // this event handler must take itself out of the chain of handlers: 
1113     if (m_previousHandler
) 
1114         m_previousHandler
->SetNextHandler(m_nextHandler
); 
1117         m_nextHandler
->SetPreviousHandler(m_previousHandler
); 
1119     m_nextHandler 
= NULL
; 
1120     m_previousHandler 
= NULL
; 
1123 bool wxEvtHandler::IsUnlinked() const 
1125     return m_previousHandler 
== NULL 
&& 
1126            m_nextHandler 
== NULL
; 
1131 bool wxEvtHandler::ProcessThreadEvent(const wxEvent
& event
) 
1133     // check that we are really in a child thread 
1134     wxASSERT_MSG( !wxThread::IsMain(), 
1135                   wxT("use ProcessEvent() in main thread") ); 
1137     AddPendingEvent(event
); 
1142 #endif // wxUSE_THREADS 
1144 void wxEvtHandler::QueueEvent(wxEvent 
*event
) 
1146     wxCHECK_RET( event
, "NULL event can't be posted" ); 
1150         // we need an event loop which manages the list of event handlers with 
1151         // pending events... cannot proceed without it! 
1152         wxLogDebug("No application object! Cannot queue this event!"); 
1154         // anyway delete the given event to avoid memory leaks 
1160     // 1) Add this event to our list of pending events 
1161     wxENTER_CRIT_SECT( m_pendingEventsLock 
); 
1163     if ( !m_pendingEvents 
) 
1164         m_pendingEvents 
= new wxList
; 
1166     m_pendingEvents
->Append(event
); 
1168     // 2) Add this event handler to list of event handlers that 
1169     //    have pending events. 
1171     wxTheApp
->AppendPendingEventHandler(this); 
1173     // only release m_pendingEventsLock now because otherwise there is a race 
1174     // condition as described in the ticket #9093: we could process the event 
1175     // just added to m_pendingEvents in our ProcessPendingEvents() below before 
1176     // we had time to append this pointer to wxHandlersWithPendingEvents list; thus 
1177     // breaking the invariant that a handler should be in the list iff it has 
1178     // any pending events to process 
1179     wxLEAVE_CRIT_SECT( m_pendingEventsLock 
); 
1181     // 3) Inform the system that new pending events are somewhere, 
1182     //    and that these should be processed in idle time. 
1186 void wxEvtHandler::DeletePendingEvents() 
1188     if (m_pendingEvents
) 
1189         m_pendingEvents
->DeleteContents(true); 
1190     wxDELETE(m_pendingEvents
); 
1193 void wxEvtHandler::ProcessPendingEvents() 
1197         // we need an event loop which manages the list of event handlers with 
1198         // pending events... cannot proceed without it! 
1199         wxLogDebug("No application object! Cannot process pending events!"); 
1203     // we need to process only a single pending event in this call because 
1204     // each call to ProcessEvent() could result in the destruction of this 
1205     // same event handler (see the comment at the end of this function) 
1207     wxENTER_CRIT_SECT( m_pendingEventsLock 
); 
1209     // this method is only called by wxApp if this handler does have 
1211     wxCHECK_RET( m_pendingEvents 
&& !m_pendingEvents
->IsEmpty(), 
1212                  "should have pending events if called" ); 
1214     wxList::compatibility_iterator node 
= m_pendingEvents
->GetFirst(); 
1215     wxEvent
* pEvent 
= static_cast<wxEvent 
*>(node
->GetData()); 
1217     // find the first event which can be processed now: 
1218     wxEventLoopBase
* evtLoop 
= wxEventLoopBase::GetActive(); 
1219     if (evtLoop 
&& evtLoop
->IsYielding()) 
1221         while (node 
&& pEvent 
&& !evtLoop
->IsEventAllowedInsideYield(pEvent
->GetEventCategory())) 
1223             node 
= node
->GetNext(); 
1224             pEvent 
= node 
? static_cast<wxEvent 
*>(node
->GetData()) : NULL
; 
1229             // all our events are NOT processable now... signal this: 
1230             wxTheApp
->DelayPendingEventHandler(this); 
1232             // see the comment at the beginning of evtloop.h header for the 
1233             // logic behind YieldFor() and behind DelayPendingEventHandler() 
1235             wxLEAVE_CRIT_SECT( m_pendingEventsLock 
); 
1241     wxEventPtr 
event(pEvent
); 
1243     // it's important we remove event from list before processing it, else a 
1244     // nested event loop, for example from a modal dialog, might process the 
1245     // same event again. 
1246     m_pendingEvents
->Erase(node
); 
1248     if ( m_pendingEvents
->IsEmpty() ) 
1250         // if there are no more pending events left, we don't need to 
1251         // stay in this list 
1252         wxTheApp
->RemovePendingEventHandler(this); 
1255     wxLEAVE_CRIT_SECT( m_pendingEventsLock 
); 
1257     ProcessEvent(*event
); 
1259     // careful: this object could have been deleted by the event handler 
1260     // executed by the above ProcessEvent() call, so we can't access any fields 
1261     // of this object any more 
1265 bool wxEvtHandler::ProcessEventIfMatchesId(const wxEventTableEntryBase
& entry
, 
1266                                            wxEvtHandler 
*handler
, 
1269     int tableId1 
= entry
.m_id
, 
1270         tableId2 
= entry
.m_lastId
; 
1272     // match only if the event type is the same and the id is either -1 in 
1273     // the event table (meaning "any") or the event id matches the id 
1274     // specified in the event table either exactly or by falling into 
1275     // range between first and last 
1276     if ((tableId1 
== wxID_ANY
) || 
1277         (tableId2 
== wxID_ANY 
&& tableId1 
== event
.GetId()) || 
1278         (tableId2 
!= wxID_ANY 
&& 
1279          (event
.GetId() >= tableId1 
&& event
.GetId() <= tableId2
))) 
1282         event
.m_callbackUserData 
= entry
.m_callbackUserData
; 
1284 #if wxUSE_EXCEPTIONS 
1287             // call the handler via wxApp method which allows the user to catch 
1288             // any exceptions which may be thrown by any handler in the program 
1290             wxTheApp
->CallEventHandler(handler
, *entry
.m_fn
, event
); 
1293 #endif // wxUSE_EXCEPTIONS 
1295             (*entry
.m_fn
)(handler
, event
); 
1298         if (!event
.GetSkipped()) 
1305 bool wxEvtHandler::DoTryApp(wxEvent
& event
) 
1307     if ( wxTheApp 
&& (this != wxTheApp
) ) 
1309         // Special case: don't pass wxEVT_IDLE to wxApp, since it'll always 
1310         // swallow it. wxEVT_IDLE is sent explicitly to wxApp so it will be 
1311         // processed appropriately via SearchEventTable. 
1312         if ( event
.GetEventType() != wxEVT_IDLE 
) 
1314             if ( wxTheApp
->ProcessEvent(event
) ) 
1322 bool wxEvtHandler::TryBefore(wxEvent
& event
) 
1324 #if WXWIN_COMPATIBILITY_2_8 
1325     // call the old virtual function to keep the code overriding it working 
1326     return TryValidator(event
); 
1333 bool wxEvtHandler::TryAfter(wxEvent
& event
) 
1335     // We only want to pass the window to the application object once even if 
1336     // there are several chained handlers. Ensure that this is what happens by 
1337     // only calling DoTryApp() if there is no next handler (which would do it). 
1339     // Notice that, unlike simply calling TryAfter() on the last handler in the 
1340     // chain only from ProcessEvent(), this also works with wxWindow object in 
1341     // the middle of the chain: its overridden TryAfter() will still be called 
1342     // and propagate the event upwards the window hierarchy even if it's not 
1343     // the last one in the chain (which, admittedly, shouldn't happen often). 
1344     if ( GetNextHandler() ) 
1345         return GetNextHandler()->TryAfter(event
); 
1347 #if WXWIN_COMPATIBILITY_2_8 
1348     // as above, call the old virtual function for compatibility 
1349     return TryParent(event
); 
1351     return DoTryApp(event
); 
1355 bool wxEvtHandler::ProcessEvent(wxEvent
& event
) 
1357     // The very first thing we do is to allow the application to hook into 
1358     // event processing in order to globally pre-process all events. 
1360     // Note that we should only do it if we're the first event handler called 
1361     // to avoid calling FilterEvent() multiple times as the event goes through 
1362     // the event handler chain and possibly upwards the window hierarchy. 
1363     if ( !event
.WasProcessed() ) 
1367             int rc 
= wxTheApp
->FilterEvent(event
); 
1370                 wxASSERT_MSG( rc 
== 1 || rc 
== 0, 
1371                               "unexpected wxApp::FilterEvent return value" ); 
1375             //else: proceed normally 
1379     // Short circuit the event processing logic if we're requested to process 
1380     // this event in this handler only, see DoTryChain() for more details. 
1381     if ( event
.ShouldProcessHereOnly() ) 
1382         return TryHere(event
); 
1385     // Try to process the event in this handler itself. 
1386     if ( ProcessEventLocally(event
) ) 
1389     // If we still didn't find a handler, propagate the event upwards the 
1390     // window chain and/or to the application object. 
1391     if ( TryAfter(event
) ) 
1395     // No handler found anywhere, bail out. 
1399 bool wxEvtHandler::ProcessEventLocally(wxEvent
& event
) 
1401     // First try the hooks which should be called before our own handlers 
1402     if ( TryBefore(event
) ) 
1405     // Then try this handler itself, notice that we should not call 
1406     // ProcessEvent() on this one as we're already called from it, which 
1407     // explains why we do it here and not in DoTryChain() 
1408     if ( TryHere(event
) ) 
1411     // Finally try the event handlers chained to this one, 
1412     if ( DoTryChain(event
) ) 
1415     // And return false to indicate that we didn't find any handler at this 
1420 bool wxEvtHandler::DoTryChain(wxEvent
& event
) 
1422     for ( wxEvtHandler 
*h 
= GetNextHandler(); h
; h 
= h
->GetNextHandler() ) 
1424         // We need to process this event at the level of this handler only 
1425         // right now, the pre-/post-processing was either already done by 
1426         // ProcessEvent() from which we were called or will be done by it when 
1429         // However we must call ProcessEvent() and not TryHere() because the 
1430         // existing code (including some in wxWidgets itself) expects the 
1431         // overridden ProcessEvent() in its custom event handlers pushed on a 
1432         // window to be called. 
1434         // So we must call ProcessEvent() but it must not do what it usually 
1435         // does. To resolve this paradox we pass a special "process here only" 
1436         // flag to ProcessEvent() via the event object itself. This ensures 
1437         // that if our own, base class, version is called, it will just call 
1438         // TryHere() and won't do anything else, just as we want it to. 
1439         wxEventProcessHereOnly 
processHereOnly(event
); 
1440         if ( h
->ProcessEvent(event
) ) 
1447 bool wxEvtHandler::TryHere(wxEvent
& event
) 
1449     // If the event handler is disabled it doesn't process any events 
1450     if ( !GetEvtHandlerEnabled() ) 
1453     // Handle per-instance dynamic event tables first 
1454     if ( m_dynamicEvents 
&& SearchDynamicEventTable(event
) ) 
1457     // Then static per-class event tables 
1458     if ( GetEventHashTable().HandleEvent(event
, this) ) 
1461     // We don't have a handler for this event. 
1465 bool wxEvtHandler::SafelyProcessEvent(wxEvent
& event
) 
1467 #if wxUSE_EXCEPTIONS 
1471         return ProcessEvent(event
); 
1472 #if wxUSE_EXCEPTIONS 
1476         // notice that we do it in 2 steps to avoid warnings about possibly 
1477         // uninitialized loop variable from some versions of g++ which are not 
1478         // smart enough to figure out that GetActive() doesn't throw and so 
1479         // that loop will always be initialized 
1480         wxEventLoopBase 
*loop 
= NULL
; 
1483             loop 
= wxEventLoopBase::GetActive(); 
1485             if ( !wxTheApp 
|| !wxTheApp
->OnExceptionInMainLoop() ) 
1490             //else: continue running current event loop 
1496             // OnExceptionInMainLoop() threw, possibly rethrowing the same 
1497             // exception again: very good, but we still need Exit() to 
1504 #endif // wxUSE_EXCEPTIONS 
1507 bool wxEvtHandler::SearchEventTable(wxEventTable
& table
, wxEvent
& event
) 
1509     const wxEventType eventType 
= event
.GetEventType(); 
1510     for ( int i 
= 0; table
.entries
[i
].m_fn 
!= 0; i
++ ) 
1512         const wxEventTableEntry
& entry 
= table
.entries
[i
]; 
1513         if ( eventType 
== entry
.m_eventType 
) 
1515             if ( ProcessEventIfMatchesId(entry
, this, event
) ) 
1523 void wxEvtHandler::DoBind(int id
, 
1525                           wxEventType eventType
, 
1526                           wxEventFunctor 
*func
, 
1529     wxDynamicEventTableEntry 
*entry 
= 
1530         new wxDynamicEventTableEntry(eventType
, id
, lastId
, func
, userData
); 
1532     if (!m_dynamicEvents
) 
1533         m_dynamicEvents 
= new wxList
; 
1535     // Insert at the front of the list so most recent additions are found first 
1536     m_dynamicEvents
->Insert( (wxObject
*) entry 
); 
1538     // Make sure we get to know when a sink is destroyed 
1539     wxEvtHandler 
*eventSink 
= func
->GetEvtHandler(); 
1540     if ( eventSink 
&& eventSink 
!= this ) 
1542         wxEventConnectionRef 
*evtConnRef 
= FindRefInTrackerList(eventSink
); 
1544             evtConnRef
->IncRef( ); 
1546             new wxEventConnectionRef(this, eventSink
); 
1551 wxEvtHandler::DoUnbind(int id
, 
1553                        wxEventType eventType
, 
1554                        const wxEventFunctor
& func
, 
1557     if (!m_dynamicEvents
) 
1560     // Remove connection from tracker node (wxEventConnectionRef) 
1561     wxEvtHandler 
*eventSink 
= func
.GetEvtHandler(); 
1562     if ( eventSink 
&& eventSink 
!= this ) 
1564         wxEventConnectionRef 
*evtConnRef 
= FindRefInTrackerList(eventSink
); 
1566             evtConnRef
->DecRef(); 
1569     wxList::compatibility_iterator node 
= m_dynamicEvents
->GetFirst(); 
1572         wxDynamicEventTableEntry 
*entry 
= (wxDynamicEventTableEntry
*)node
->GetData(); 
1574         if ((entry
->m_id 
== id
) && 
1575             ((entry
->m_lastId 
== lastId
) || (lastId 
== wxID_ANY
)) && 
1576             ((entry
->m_eventType 
== eventType
) || (eventType 
== wxEVT_NULL
)) && 
1577             entry
->m_fn
->IsMatching(func
) && 
1578             ((entry
->m_callbackUserData 
== userData
) || !userData
)) 
1580             delete entry
->m_callbackUserData
; 
1581             m_dynamicEvents
->Erase( node 
); 
1585         node 
= node
->GetNext(); 
1590 bool wxEvtHandler::SearchDynamicEventTable( wxEvent
& event 
) 
1592     wxCHECK_MSG( m_dynamicEvents
, false, 
1593                  wxT("caller should check that we have dynamic events") ); 
1595     wxList::compatibility_iterator node 
= m_dynamicEvents
->GetFirst(); 
1598         wxDynamicEventTableEntry 
*entry 
= (wxDynamicEventTableEntry
*)node
->GetData(); 
1600         // get next node before (maybe) calling the event handler as it could 
1601         // call Disconnect() invalidating the current node 
1602         node 
= node
->GetNext(); 
1604         if ( event
.GetEventType() == entry
->m_eventType 
) 
1606             wxEvtHandler 
*handler 
= entry
->m_fn
->GetEvtHandler(); 
1609             if ( ProcessEventIfMatchesId(*entry
, handler
, event
) ) 
1617 void wxEvtHandler::DoSetClientObject( wxClientData 
*data 
) 
1619     wxASSERT_MSG( m_clientDataType 
!= wxClientData_Void
, 
1620                   wxT("can't have both object and void client data") ); 
1622     if ( m_clientObject 
) 
1623         delete m_clientObject
; 
1625     m_clientObject 
= data
; 
1626     m_clientDataType 
= wxClientData_Object
; 
1629 wxClientData 
*wxEvtHandler::DoGetClientObject() const 
1631     // it's not an error to call GetClientObject() on a window which doesn't 
1632     // have client data at all - NULL will be returned 
1633     wxASSERT_MSG( m_clientDataType 
!= wxClientData_Void
, 
1634                   wxT("this window doesn't have object client data") ); 
1636     return m_clientObject
; 
1639 void wxEvtHandler::DoSetClientData( void *data 
) 
1641     wxASSERT_MSG( m_clientDataType 
!= wxClientData_Object
, 
1642                   wxT("can't have both object and void client data") ); 
1644     m_clientData 
= data
; 
1645     m_clientDataType 
= wxClientData_Void
; 
1648 void *wxEvtHandler::DoGetClientData() const 
1650     // it's not an error to call GetClientData() on a window which doesn't have 
1651     // client data at all - NULL will be returned 
1652     wxASSERT_MSG( m_clientDataType 
!= wxClientData_Object
, 
1653                   wxT("this window doesn't have void client data") ); 
1655     return m_clientData
; 
1658 // A helper to find an wxEventConnectionRef object 
1659 wxEventConnectionRef 
* 
1660 wxEvtHandler::FindRefInTrackerList(wxEvtHandler 
*eventSink
) 
1662     for ( wxTrackerNode 
*node 
= eventSink
->GetFirst(); node
; node 
= node
->m_nxt 
) 
1664         // we only want wxEventConnectionRef nodes here 
1665         wxEventConnectionRef 
*evtConnRef 
= node
->ToEventConnection(); 
1666         if ( evtConnRef 
&& evtConnRef
->m_src 
== this ) 
1668             wxASSERT( evtConnRef
->m_sink
==eventSink 
); 
1676 void wxEvtHandler::OnSinkDestroyed( wxEvtHandler 
*sink 
) 
1678     wxASSERT(m_dynamicEvents
); 
1680     // remove all connections with this sink 
1681     wxList::compatibility_iterator node 
= m_dynamicEvents
->GetFirst(), node_nxt
; 
1684         wxDynamicEventTableEntry 
*entry 
= (wxDynamicEventTableEntry
*)node
->GetData(); 
1685         node_nxt 
= node
->GetNext(); 
1687         if ( entry
->m_fn
->GetEvtHandler() == sink 
) 
1689             delete entry
->m_callbackUserData
; 
1690             m_dynamicEvents
->Erase( node 
); 
1697 #endif // wxUSE_BASE 
1701 // Find a window with the focus, that is also a descendant of the given window. 
1702 // This is used to determine the window to initially send commands to. 
1703 wxWindow
* wxFindFocusDescendant(wxWindow
* ancestor
) 
1705     // Process events starting with the window with the focus, if any. 
1706     wxWindow
* focusWin 
= wxWindow::FindFocus(); 
1707     wxWindow
* win 
= focusWin
; 
1709     // Check if this is a descendant of this frame. 
1710     // If not, win will be set to NULL. 
1713         if (win 
== ancestor
) 
1716             win 
= win
->GetParent(); 
1724 // ---------------------------------------------------------------------------- 
1726 // ---------------------------------------------------------------------------- 
1728 wxEventBlocker::wxEventBlocker(wxWindow 
*win
, wxEventType type
) 
1730     wxCHECK_RET(win
, wxT("Null window given to wxEventBlocker")); 
1735     m_window
->PushEventHandler(this); 
1738 wxEventBlocker::~wxEventBlocker() 
1740     wxEvtHandler 
*popped 
= m_window
->PopEventHandler(false); 
1741     wxCHECK_RET(popped 
== this, 
1742         wxT("Don't push other event handlers into a window managed by wxEventBlocker!")); 
1745 bool wxEventBlocker::ProcessEvent(wxEvent
& event
) 
1747     // should this event be blocked? 
1748     for ( size_t i 
= 0; i 
< m_eventsToBlock
.size(); i
++ ) 
1750         wxEventType t 
= (wxEventType
)m_eventsToBlock
[i
]; 
1751         if ( t 
== wxEVT_ANY 
|| t 
== event
.GetEventType() ) 
1752             return true;   // yes, it should: mark this event as processed