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" 
  34     #include "wx/stopwatch.h" 
  35     #include "wx/module.h" 
  38         #include "wx/window.h" 
  39         #include "wx/control.h" 
  41         #include "wx/textctrl.h" 
  42         #include "wx/validate.h" 
  46 #include "wx/thread.h" 
  49     #include "wx/ptr_scpd.h" 
  51     wxDECLARE_SCOPED_PTR(wxEvent
, wxEventPtr
) 
  52     wxDEFINE_SCOPED_PTR(wxEvent
, wxEventPtr
) 
  55 // ---------------------------------------------------------------------------- 
  57 // ---------------------------------------------------------------------------- 
  60     IMPLEMENT_DYNAMIC_CLASS(wxEvtHandler
, wxObject
) 
  61     IMPLEMENT_ABSTRACT_CLASS(wxEvent
, wxObject
) 
  62     IMPLEMENT_DYNAMIC_CLASS(wxIdleEvent
, wxEvent
) 
  66     IMPLEMENT_DYNAMIC_CLASS(wxCommandEvent
, wxEvent
) 
  67     IMPLEMENT_DYNAMIC_CLASS(wxNotifyEvent
, wxCommandEvent
) 
  68     IMPLEMENT_DYNAMIC_CLASS(wxScrollEvent
, wxCommandEvent
) 
  69     IMPLEMENT_DYNAMIC_CLASS(wxScrollWinEvent
, wxEvent
) 
  70     IMPLEMENT_DYNAMIC_CLASS(wxMouseEvent
, wxEvent
) 
  71     IMPLEMENT_DYNAMIC_CLASS(wxKeyEvent
, wxEvent
) 
  72     IMPLEMENT_DYNAMIC_CLASS(wxSizeEvent
, wxEvent
) 
  73     IMPLEMENT_DYNAMIC_CLASS(wxPaintEvent
, wxEvent
) 
  74     IMPLEMENT_DYNAMIC_CLASS(wxNcPaintEvent
, wxEvent
) 
  75     IMPLEMENT_DYNAMIC_CLASS(wxEraseEvent
, wxEvent
) 
  76     IMPLEMENT_DYNAMIC_CLASS(wxMoveEvent
, wxEvent
) 
  77     IMPLEMENT_DYNAMIC_CLASS(wxFocusEvent
, wxEvent
) 
  78     IMPLEMENT_DYNAMIC_CLASS(wxChildFocusEvent
, wxCommandEvent
) 
  79     IMPLEMENT_DYNAMIC_CLASS(wxCloseEvent
, wxEvent
) 
  80     IMPLEMENT_DYNAMIC_CLASS(wxShowEvent
, wxEvent
) 
  81     IMPLEMENT_DYNAMIC_CLASS(wxMaximizeEvent
, wxEvent
) 
  82     IMPLEMENT_DYNAMIC_CLASS(wxIconizeEvent
, wxEvent
) 
  83     IMPLEMENT_DYNAMIC_CLASS(wxMenuEvent
, wxEvent
) 
  84     IMPLEMENT_DYNAMIC_CLASS(wxJoystickEvent
, wxEvent
) 
  85     IMPLEMENT_DYNAMIC_CLASS(wxDropFilesEvent
, wxEvent
) 
  86     IMPLEMENT_DYNAMIC_CLASS(wxActivateEvent
, wxEvent
) 
  87     IMPLEMENT_DYNAMIC_CLASS(wxInitDialogEvent
, wxEvent
) 
  88     IMPLEMENT_DYNAMIC_CLASS(wxSetCursorEvent
, wxEvent
) 
  89     IMPLEMENT_DYNAMIC_CLASS(wxSysColourChangedEvent
, wxEvent
) 
  90     IMPLEMENT_DYNAMIC_CLASS(wxDisplayChangedEvent
, wxEvent
) 
  91     IMPLEMENT_DYNAMIC_CLASS(wxUpdateUIEvent
, wxCommandEvent
) 
  92     IMPLEMENT_DYNAMIC_CLASS(wxNavigationKeyEvent
, wxEvent
) 
  93     IMPLEMENT_DYNAMIC_CLASS(wxPaletteChangedEvent
, wxEvent
) 
  94     IMPLEMENT_DYNAMIC_CLASS(wxQueryNewPaletteEvent
, wxEvent
) 
  95     IMPLEMENT_DYNAMIC_CLASS(wxWindowCreateEvent
, wxEvent
) 
  96     IMPLEMENT_DYNAMIC_CLASS(wxWindowDestroyEvent
, wxEvent
) 
  97     IMPLEMENT_DYNAMIC_CLASS(wxHelpEvent
, wxCommandEvent
) 
  98     IMPLEMENT_DYNAMIC_CLASS(wxContextMenuEvent
, wxCommandEvent
) 
  99     IMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureChangedEvent
, wxEvent
) 
 100     IMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureLostEvent
, wxEvent
) 
 101     IMPLEMENT_DYNAMIC_CLASS(wxClipboardTextEvent
, wxCommandEvent
) 
 106 const wxEventTable 
*wxEvtHandler::GetEventTable() const 
 107     { return &wxEvtHandler::sm_eventTable
; } 
 109 const wxEventTable 
wxEvtHandler::sm_eventTable 
= 
 110     { (const wxEventTable 
*)NULL
, &wxEvtHandler::sm_eventTableEntries
[0] }; 
 112 wxEventHashTable 
&wxEvtHandler::GetEventHashTable() const 
 113     { return wxEvtHandler::sm_eventHashTable
; } 
 115 wxEventHashTable 
wxEvtHandler::sm_eventHashTable(wxEvtHandler::sm_eventTable
); 
 117 const wxEventTableEntry 
wxEvtHandler::sm_eventTableEntries
[] = 
 118     { DECLARE_EVENT_TABLE_ENTRY(wxEVT_NULL
, 0, 0, (wxObjectEventFunction
)NULL
, NULL
) }; 
 121 // wxUSE_MEMORY_TRACING considers memory freed from the static objects dtors 
 122 // leaked, so we need to manually clean up all event tables before checking for 
 123 // the memory leaks when using it, however this breaks re-initializing the 
 124 // library (i.e. repeated calls to wxInitialize/wxUninitialize) because the 
 125 // event tables won't be rebuilt the next time, so disable this by default 
 126 #if defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING 
 128 class wxEventTableEntryModule
: public wxModule
 
 131     wxEventTableEntryModule() { } 
 132     virtual bool OnInit() { return true; } 
 133     virtual void OnExit() { wxEventHashTable::ClearAll(); } 
 135     DECLARE_DYNAMIC_CLASS(wxEventTableEntryModule
) 
 138 IMPLEMENT_DYNAMIC_CLASS(wxEventTableEntryModule
, wxModule
) 
 140 #endif // __WXDEBUG__ && wxUSE_MEMORY_TRACING 
 142 // ---------------------------------------------------------------------------- 
 144 // ---------------------------------------------------------------------------- 
 146 // List containing event handlers with pending events (each handler can occur 
 147 // at most once here) 
 148 wxList 
*wxPendingEvents 
= NULL
; 
 151     // protects wxPendingEvents list 
 152     wxCriticalSection 
*wxPendingEventsLocker 
= NULL
; 
 155 // common event types are defined here, other event types are defined by the 
 156 // components which use them 
 158 const wxEventType wxEVT_FIRST 
= 10000; 
 159 const wxEventType wxEVT_USER_FIRST 
= wxEVT_FIRST 
+ 2000; 
 161 DEFINE_EVENT_TYPE(wxEVT_NULL
) 
 162 DEFINE_EVENT_TYPE(wxEVT_IDLE
) 
 163 DEFINE_EVENT_TYPE(wxEVT_SOCKET
) 
 164 DEFINE_EVENT_TYPE(wxEVT_TIMER
) 
 170 DEFINE_EVENT_TYPE(wxEVT_COMMAND_BUTTON_CLICKED
) 
 171 DEFINE_EVENT_TYPE(wxEVT_COMMAND_CHECKBOX_CLICKED
) 
 172 DEFINE_EVENT_TYPE(wxEVT_COMMAND_CHOICE_SELECTED
) 
 173 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LISTBOX_SELECTED
) 
 174 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
) 
 175 DEFINE_EVENT_TYPE(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
) 
 176 DEFINE_EVENT_TYPE(wxEVT_COMMAND_MENU_SELECTED
) 
 177 DEFINE_EVENT_TYPE(wxEVT_COMMAND_SLIDER_UPDATED
) 
 178 DEFINE_EVENT_TYPE(wxEVT_COMMAND_RADIOBOX_SELECTED
) 
 179 DEFINE_EVENT_TYPE(wxEVT_COMMAND_RADIOBUTTON_SELECTED
) 
 180 DEFINE_EVENT_TYPE(wxEVT_COMMAND_SCROLLBAR_UPDATED
) 
 181 DEFINE_EVENT_TYPE(wxEVT_COMMAND_VLBOX_SELECTED
) 
 182 DEFINE_EVENT_TYPE(wxEVT_COMMAND_COMBOBOX_SELECTED
) 
 183 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_RCLICKED
) 
 184 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_ENTER
) 
 185 DEFINE_EVENT_TYPE(wxEVT_COMMAND_SPINCTRL_UPDATED
) 
 186 DEFINE_EVENT_TYPE(wxEVT_COMMAND_SPINCTRLDOUBLE_UPDATED
) 
 187 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED
) 
 190 DEFINE_EVENT_TYPE(wxEVT_LEFT_DOWN
) 
 191 DEFINE_EVENT_TYPE(wxEVT_LEFT_UP
) 
 192 DEFINE_EVENT_TYPE(wxEVT_MIDDLE_DOWN
) 
 193 DEFINE_EVENT_TYPE(wxEVT_MIDDLE_UP
) 
 194 DEFINE_EVENT_TYPE(wxEVT_RIGHT_DOWN
) 
 195 DEFINE_EVENT_TYPE(wxEVT_RIGHT_UP
) 
 196 DEFINE_EVENT_TYPE(wxEVT_MOTION
) 
 197 DEFINE_EVENT_TYPE(wxEVT_ENTER_WINDOW
) 
 198 DEFINE_EVENT_TYPE(wxEVT_LEAVE_WINDOW
) 
 199 DEFINE_EVENT_TYPE(wxEVT_LEFT_DCLICK
) 
 200 DEFINE_EVENT_TYPE(wxEVT_MIDDLE_DCLICK
) 
 201 DEFINE_EVENT_TYPE(wxEVT_RIGHT_DCLICK
) 
 202 DEFINE_EVENT_TYPE(wxEVT_SET_FOCUS
) 
 203 DEFINE_EVENT_TYPE(wxEVT_KILL_FOCUS
) 
 204 DEFINE_EVENT_TYPE(wxEVT_CHILD_FOCUS
) 
 205 DEFINE_EVENT_TYPE(wxEVT_MOUSEWHEEL
) 
 206 DEFINE_EVENT_TYPE(wxEVT_AUX1_DOWN
) 
 207 DEFINE_EVENT_TYPE(wxEVT_AUX1_UP
) 
 208 DEFINE_EVENT_TYPE(wxEVT_AUX1_DCLICK
) 
 209 DEFINE_EVENT_TYPE(wxEVT_AUX2_DOWN
) 
 210 DEFINE_EVENT_TYPE(wxEVT_AUX2_UP
) 
 211 DEFINE_EVENT_TYPE(wxEVT_AUX2_DCLICK
) 
 213 // Non-client mouse events 
 214 DEFINE_EVENT_TYPE(wxEVT_NC_LEFT_DOWN
) 
 215 DEFINE_EVENT_TYPE(wxEVT_NC_LEFT_UP
) 
 216 DEFINE_EVENT_TYPE(wxEVT_NC_MIDDLE_DOWN
) 
 217 DEFINE_EVENT_TYPE(wxEVT_NC_MIDDLE_UP
) 
 218 DEFINE_EVENT_TYPE(wxEVT_NC_RIGHT_DOWN
) 
 219 DEFINE_EVENT_TYPE(wxEVT_NC_RIGHT_UP
) 
 220 DEFINE_EVENT_TYPE(wxEVT_NC_MOTION
) 
 221 DEFINE_EVENT_TYPE(wxEVT_NC_ENTER_WINDOW
) 
 222 DEFINE_EVENT_TYPE(wxEVT_NC_LEAVE_WINDOW
) 
 223 DEFINE_EVENT_TYPE(wxEVT_NC_LEFT_DCLICK
) 
 224 DEFINE_EVENT_TYPE(wxEVT_NC_MIDDLE_DCLICK
) 
 225 DEFINE_EVENT_TYPE(wxEVT_NC_RIGHT_DCLICK
) 
 227 // Character input event type 
 228 DEFINE_EVENT_TYPE(wxEVT_CHAR
) 
 229 DEFINE_EVENT_TYPE(wxEVT_CHAR_HOOK
) 
 230 DEFINE_EVENT_TYPE(wxEVT_NAVIGATION_KEY
) 
 231 DEFINE_EVENT_TYPE(wxEVT_KEY_DOWN
) 
 232 DEFINE_EVENT_TYPE(wxEVT_KEY_UP
) 
 234 DEFINE_EVENT_TYPE(wxEVT_HOTKEY
) 
 238 DEFINE_EVENT_TYPE(wxEVT_SET_CURSOR
) 
 240 // wxScrollbar and wxSlider event identifiers 
 241 DEFINE_EVENT_TYPE(wxEVT_SCROLL_TOP
) 
 242 DEFINE_EVENT_TYPE(wxEVT_SCROLL_BOTTOM
) 
 243 DEFINE_EVENT_TYPE(wxEVT_SCROLL_LINEUP
) 
 244 DEFINE_EVENT_TYPE(wxEVT_SCROLL_LINEDOWN
) 
 245 DEFINE_EVENT_TYPE(wxEVT_SCROLL_PAGEUP
) 
 246 DEFINE_EVENT_TYPE(wxEVT_SCROLL_PAGEDOWN
) 
 247 DEFINE_EVENT_TYPE(wxEVT_SCROLL_THUMBTRACK
) 
 248 DEFINE_EVENT_TYPE(wxEVT_SCROLL_THUMBRELEASE
) 
 249 DEFINE_EVENT_TYPE(wxEVT_SCROLL_CHANGED
) 
 251 // Scroll events from wxWindow 
 252 DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_TOP
) 
 253 DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_BOTTOM
) 
 254 DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_LINEUP
) 
 255 DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_LINEDOWN
) 
 256 DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_PAGEUP
) 
 257 DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_PAGEDOWN
) 
 258 DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_THUMBTRACK
) 
 259 DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_THUMBRELEASE
) 
 262 DEFINE_EVENT_TYPE(wxEVT_SIZE
) 
 263 DEFINE_EVENT_TYPE(wxEVT_SIZING
) 
 264 DEFINE_EVENT_TYPE(wxEVT_MOVE
) 
 265 DEFINE_EVENT_TYPE(wxEVT_MOVING
) 
 266 DEFINE_EVENT_TYPE(wxEVT_MOVE_START
) 
 267 DEFINE_EVENT_TYPE(wxEVT_MOVE_END
) 
 268 DEFINE_EVENT_TYPE(wxEVT_CLOSE_WINDOW
) 
 269 DEFINE_EVENT_TYPE(wxEVT_END_SESSION
) 
 270 DEFINE_EVENT_TYPE(wxEVT_QUERY_END_SESSION
) 
 271 DEFINE_EVENT_TYPE(wxEVT_HIBERNATE
) 
 272 DEFINE_EVENT_TYPE(wxEVT_ACTIVATE_APP
) 
 273 DEFINE_EVENT_TYPE(wxEVT_ACTIVATE
) 
 274 DEFINE_EVENT_TYPE(wxEVT_CREATE
) 
 275 DEFINE_EVENT_TYPE(wxEVT_DESTROY
) 
 276 DEFINE_EVENT_TYPE(wxEVT_SHOW
) 
 277 DEFINE_EVENT_TYPE(wxEVT_ICONIZE
) 
 278 DEFINE_EVENT_TYPE(wxEVT_MAXIMIZE
) 
 279 DEFINE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_CHANGED
) 
 280 DEFINE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_LOST
) 
 281 DEFINE_EVENT_TYPE(wxEVT_PAINT
) 
 282 DEFINE_EVENT_TYPE(wxEVT_ERASE_BACKGROUND
) 
 283 DEFINE_EVENT_TYPE(wxEVT_NC_PAINT
) 
 284 DEFINE_EVENT_TYPE(wxEVT_PAINT_ICON
) 
 285 DEFINE_EVENT_TYPE(wxEVT_MENU_OPEN
) 
 286 DEFINE_EVENT_TYPE(wxEVT_MENU_CLOSE
) 
 287 DEFINE_EVENT_TYPE(wxEVT_MENU_HIGHLIGHT
) 
 288 DEFINE_EVENT_TYPE(wxEVT_CONTEXT_MENU
) 
 289 DEFINE_EVENT_TYPE(wxEVT_SYS_COLOUR_CHANGED
) 
 290 DEFINE_EVENT_TYPE(wxEVT_DISPLAY_CHANGED
) 
 291 DEFINE_EVENT_TYPE(wxEVT_SETTING_CHANGED
) 
 292 DEFINE_EVENT_TYPE(wxEVT_QUERY_NEW_PALETTE
) 
 293 DEFINE_EVENT_TYPE(wxEVT_PALETTE_CHANGED
) 
 294 DEFINE_EVENT_TYPE(wxEVT_JOY_BUTTON_DOWN
) 
 295 DEFINE_EVENT_TYPE(wxEVT_JOY_BUTTON_UP
) 
 296 DEFINE_EVENT_TYPE(wxEVT_JOY_MOVE
) 
 297 DEFINE_EVENT_TYPE(wxEVT_JOY_ZMOVE
) 
 298 DEFINE_EVENT_TYPE(wxEVT_DROP_FILES
) 
 299 DEFINE_EVENT_TYPE(wxEVT_DRAW_ITEM
) 
 300 DEFINE_EVENT_TYPE(wxEVT_MEASURE_ITEM
) 
 301 DEFINE_EVENT_TYPE(wxEVT_COMPARE_ITEM
) 
 302 DEFINE_EVENT_TYPE(wxEVT_INIT_DIALOG
) 
 303 DEFINE_EVENT_TYPE(wxEVT_UPDATE_UI
) 
 306 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_COPY
) 
 307 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_CUT
) 
 308 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_PASTE
) 
 310 // Generic command events 
 311 // Note: a click is a higher-level event than button down/up 
 312 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LEFT_CLICK
) 
 313 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LEFT_DCLICK
) 
 314 DEFINE_EVENT_TYPE(wxEVT_COMMAND_RIGHT_CLICK
) 
 315 DEFINE_EVENT_TYPE(wxEVT_COMMAND_RIGHT_DCLICK
) 
 316 DEFINE_EVENT_TYPE(wxEVT_COMMAND_SET_FOCUS
) 
 317 DEFINE_EVENT_TYPE(wxEVT_COMMAND_KILL_FOCUS
) 
 318 DEFINE_EVENT_TYPE(wxEVT_COMMAND_ENTER
) 
 321 DEFINE_EVENT_TYPE(wxEVT_HELP
) 
 322 DEFINE_EVENT_TYPE(wxEVT_DETAILED_HELP
) 
 328 wxIdleMode 
wxIdleEvent::sm_idleMode 
= wxIDLE_PROCESS_ALL
; 
 330 // ============================================================================ 
 332 // ============================================================================ 
 334 // ---------------------------------------------------------------------------- 
 335 // event initialization 
 336 // ---------------------------------------------------------------------------- 
 341     static int s_lastUsedEventType 
= wxEVT_FIRST
; 
 343     return s_lastUsedEventType
++; 
 346 // ---------------------------------------------------------------------------- 
 348 // ---------------------------------------------------------------------------- 
 351  * General wxWidgets events, covering 
 352  * all interesting things that might happen (button clicking, resizing, 
 353  * setting text in widgets, etc.). 
 355  * For each completely new event type, derive a new event class. 
 359 wxEvent::wxEvent(int theId
, wxEventType commandType 
) 
 361     m_eventType 
= commandType
; 
 362     m_eventObject 
= (wxObject 
*) NULL
; 
 366     m_callbackUserData 
= (wxObject 
*) NULL
; 
 367     m_isCommandEvent 
= false; 
 368     m_propagationLevel 
= wxEVENT_PROPAGATE_NONE
; 
 371 wxEvent::wxEvent(const wxEvent
& src
) 
 373     , m_eventObject(src
.m_eventObject
) 
 374     , m_eventType(src
.m_eventType
) 
 375     , m_timeStamp(src
.m_timeStamp
) 
 377     , m_callbackUserData(src
.m_callbackUserData
) 
 378     , m_propagationLevel(src
.m_propagationLevel
) 
 379     , m_skipped(src
.m_skipped
) 
 380     , m_isCommandEvent(src
.m_isCommandEvent
) 
 384 wxEvent
& wxEvent::operator=(const wxEvent
& src
) 
 386     wxObject::operator=(src
); 
 388     m_eventObject 
= src
.m_eventObject
; 
 389     m_eventType 
= src
.m_eventType
; 
 390     m_timeStamp 
= src
.m_timeStamp
; 
 392     m_callbackUserData 
= src
.m_callbackUserData
; 
 393     m_propagationLevel 
= src
.m_propagationLevel
; 
 394     m_skipped 
= src
.m_skipped
; 
 395     m_isCommandEvent 
= src
.m_isCommandEvent
; 
 410     // 'this' : used in base member initializer list (for m_commandString) 
 411     #pragma warning(disable:4355) 
 414 wxCommandEvent::wxCommandEvent(wxEventType commandType
, int theId
) 
 415               : wxEvent(theId
, commandType
) 
 417     m_clientData 
= (char *) NULL
; 
 418     m_clientObject 
= (wxClientData 
*) NULL
; 
 421     m_isCommandEvent 
= true; 
 423     // the command events are propagated upwards by default 
 424     m_propagationLevel 
= wxEVENT_PROPAGATE_MAX
; 
 428     #pragma warning(default:4355) 
 431 wxString 
wxCommandEvent::GetString() const 
 433     if (m_eventType 
!= wxEVT_COMMAND_TEXT_UPDATED 
|| !m_eventObject
) 
 440         wxTextCtrl 
*txt 
= wxDynamicCast(m_eventObject
, wxTextCtrl
); 
 442             return txt
->GetValue(); 
 444 #endif // wxUSE_TEXTCTRL 
 454 wxLongLong 
wxUpdateUIEvent::sm_lastUpdate 
= 0; 
 457 long wxUpdateUIEvent::sm_updateInterval 
= 0; 
 459 wxUpdateUIMode 
wxUpdateUIEvent::sm_updateMode 
= wxUPDATE_UI_PROCESS_ALL
; 
 462 bool wxUpdateUIEvent::CanUpdate(wxWindowBase 
*win
) 
 464     // Don't update if we've switched global updating off 
 465     // and this window doesn't support updates. 
 467        (GetMode() == wxUPDATE_UI_PROCESS_SPECIFIED 
&& 
 468        ((win
->GetExtraStyle() & wxWS_EX_PROCESS_UI_UPDATES
) == 0))) 
 471     if (sm_updateInterval 
== -1) 
 474     if (sm_updateInterval 
== 0) 
 477 #if wxUSE_STOPWATCH && wxUSE_LONGLONG 
 478     wxLongLong now 
= wxGetLocalTimeMillis(); 
 479     if (now 
> (sm_lastUpdate 
+ sm_updateInterval
)) 
 486     // If we don't have wxStopWatch or wxLongLong, we 
 487     // should err on the safe side and update now anyway. 
 492 // Reset the update time to provide a delay until the next 
 493 // time we should update 
 494 void wxUpdateUIEvent::ResetUpdateTime() 
 496 #if wxUSE_STOPWATCH && wxUSE_LONGLONG 
 497     if (sm_updateInterval 
> 0) 
 499         wxLongLong now 
= wxGetLocalTimeMillis(); 
 500         if (now 
> (sm_lastUpdate 
+ sm_updateInterval
)) 
 512 wxScrollEvent::wxScrollEvent(wxEventType commandType
, 
 516     : wxCommandEvent(commandType
, id
) 
 518     m_extraLong 
= orient
; 
 526 wxScrollWinEvent::wxScrollWinEvent(wxEventType commandType
, 
 530     m_eventType 
= commandType
; 
 531     m_extraLong 
= orient
; 
 540 wxMouseEvent::wxMouseEvent(wxEventType commandType
) 
 542     m_eventType 
= commandType
; 
 548     m_middleDown 
= false; 
 557     m_linesPerAction 
= 0; 
 561 void wxMouseEvent::Assign(const wxMouseEvent
& event
) 
 563     wxEvent::operator=(event
); 
 565     // Borland C++ 5.82 doesn't compile an explicit call to an implicitly 
 566     // defined operator=() so need to do it this way: 
 567     *static_cast<wxMouseState 
*>(this) = event
; 
 572     m_leftDown 
= event
.m_leftDown
; 
 573     m_middleDown 
= event
.m_middleDown
; 
 574     m_rightDown 
= event
.m_rightDown
; 
 575     m_aux1Down 
= event
.m_aux1Down
; 
 576     m_aux2Down 
= event
.m_aux2Down
; 
 578     m_wheelRotation 
= event
.m_wheelRotation
; 
 579     m_wheelDelta 
= event
.m_wheelDelta
; 
 580     m_linesPerAction 
= event
.m_linesPerAction
; 
 581     m_wheelAxis 
= event
.m_wheelAxis
; 
 584 // return true if was a button dclick event 
 585 bool wxMouseEvent::ButtonDClick(int but
) const 
 590             wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::ButtonDClick")); 
 593         case wxMOUSE_BTN_ANY
: 
 594             return (LeftDClick() || MiddleDClick() || RightDClick() || 
 595                     Aux1DClick() || Aux2DClick()); 
 597         case wxMOUSE_BTN_LEFT
: 
 600         case wxMOUSE_BTN_MIDDLE
: 
 601             return MiddleDClick(); 
 603         case wxMOUSE_BTN_RIGHT
: 
 604             return RightDClick(); 
 606         case wxMOUSE_BTN_AUX1
: 
 609         case wxMOUSE_BTN_AUX2
: 
 614 // return true if was a button down event 
 615 bool wxMouseEvent::ButtonDown(int but
) const 
 620             wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::ButtonDown")); 
 623         case wxMOUSE_BTN_ANY
: 
 624             return (LeftDown() || MiddleDown() || RightDown() || 
 625                     Aux1Down() || Aux2Down()); 
 627         case wxMOUSE_BTN_LEFT
: 
 630         case wxMOUSE_BTN_MIDDLE
: 
 633         case wxMOUSE_BTN_RIGHT
: 
 636         case wxMOUSE_BTN_AUX1
: 
 639         case wxMOUSE_BTN_AUX2
: 
 644 // return true if was a button up event 
 645 bool wxMouseEvent::ButtonUp(int but
) const 
 650             wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::ButtonUp")); 
 653         case wxMOUSE_BTN_ANY
: 
 654             return (LeftUp() || MiddleUp() || RightUp() || 
 655                     Aux1Up() || Aux2Up()); 
 657         case wxMOUSE_BTN_LEFT
: 
 660         case wxMOUSE_BTN_MIDDLE
: 
 663         case wxMOUSE_BTN_RIGHT
: 
 666         case wxMOUSE_BTN_AUX1
: 
 669         case wxMOUSE_BTN_AUX2
: 
 674 // return true if the given button is currently changing state 
 675 bool wxMouseEvent::Button(int but
) const 
 680             wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::Button")); 
 683         case wxMOUSE_BTN_ANY
: 
 684             return ButtonUp(wxMOUSE_BTN_ANY
) || 
 685                     ButtonDown(wxMOUSE_BTN_ANY
) || 
 686                         ButtonDClick(wxMOUSE_BTN_ANY
); 
 688         case wxMOUSE_BTN_LEFT
: 
 689             return LeftDown() || LeftUp() || LeftDClick(); 
 691         case wxMOUSE_BTN_MIDDLE
: 
 692             return MiddleDown() || MiddleUp() || MiddleDClick(); 
 694         case wxMOUSE_BTN_RIGHT
: 
 695             return RightDown() || RightUp() || RightDClick(); 
 697         case wxMOUSE_BTN_AUX1
: 
 698            return Aux1Down() || Aux1Up() || Aux1DClick(); 
 700         case wxMOUSE_BTN_AUX2
: 
 701            return Aux2Down() || Aux2Up() || Aux2DClick(); 
 705 bool wxMouseEvent::ButtonIsDown(int but
) const 
 710             wxFAIL_MSG(wxT("invalid parameter in wxMouseEvent::ButtonIsDown")); 
 713         case wxMOUSE_BTN_ANY
: 
 714             return LeftIsDown() || MiddleIsDown() || RightIsDown() || Aux1Down() || Aux2Down(); 
 716         case wxMOUSE_BTN_LEFT
: 
 719         case wxMOUSE_BTN_MIDDLE
: 
 720             return MiddleIsDown(); 
 722         case wxMOUSE_BTN_RIGHT
: 
 723             return RightIsDown(); 
 725         case wxMOUSE_BTN_AUX1
: 
 728         case wxMOUSE_BTN_AUX2
: 
 733 int wxMouseEvent::GetButton() const 
 735     for ( int i 
= 1; i 
< wxMOUSE_BTN_MAX
; i
++ ) 
 743     return wxMOUSE_BTN_NONE
; 
 746 // Find the logical position of the event given the DC 
 747 wxPoint 
wxMouseEvent::GetLogicalPosition(const wxDC
& dc
) const 
 749     wxPoint 
pt(dc
.DeviceToLogicalX(m_x
), dc
.DeviceToLogicalY(m_y
)); 
 759 wxKeyEvent::wxKeyEvent(wxEventType type
) 
 769 wxKeyEvent::wxKeyEvent(const wxKeyEvent
& evt
) 
 776     m_keyCode 
= evt
.m_keyCode
; 
 778     m_scanCode 
= evt
.m_scanCode
; 
 779     m_rawCode 
= evt
.m_rawCode
; 
 780     m_rawFlags 
= evt
.m_rawFlags
; 
 783     m_uniChar 
= evt
.m_uniChar
; 
 787 wxWindowCreateEvent::wxWindowCreateEvent(wxWindow 
*win
) 
 789     SetEventType(wxEVT_CREATE
); 
 793 wxWindowDestroyEvent::wxWindowDestroyEvent(wxWindow 
*win
) 
 795     SetEventType(wxEVT_DESTROY
); 
 799 wxChildFocusEvent::wxChildFocusEvent(wxWindow 
*win
) 
 800                  : wxCommandEvent(wxEVT_CHILD_FOCUS
) 
 805 // ---------------------------------------------------------------------------- 
 807 // ---------------------------------------------------------------------------- 
 810 wxHelpEvent::Origin 
wxHelpEvent::GuessOrigin(Origin origin
) 
 812     if ( origin 
== Origin_Unknown 
) 
 814         // assume that the event comes from the help button if it's not from 
 815         // keyboard and that pressing F1 always results in the help event 
 816         origin 
= wxGetKeyState(WXK_F1
) ? Origin_Keyboard 
: Origin_HelpButton
; 
 827 // ---------------------------------------------------------------------------- 
 829 // ---------------------------------------------------------------------------- 
 831 static const int EVENT_TYPE_TABLE_INIT_SIZE 
= 31; // Not too big not too small... 
 833 wxEventHashTable
* wxEventHashTable::sm_first 
= NULL
; 
 835 wxEventHashTable::wxEventHashTable(const wxEventTable 
&table
) 
 839     AllocEventTypeTable(EVENT_TYPE_TABLE_INIT_SIZE
); 
 843         m_next
->m_previous 
= this; 
 847 wxEventHashTable::~wxEventHashTable() 
 850         m_next
->m_previous 
= m_previous
; 
 852         m_previous
->m_next 
= m_next
; 
 853     if (sm_first 
== this) 
 859 void wxEventHashTable::Clear() 
 861     for ( size_t i 
= 0; i 
< m_size
; i
++ ) 
 863         EventTypeTablePointer  eTTnode 
= m_eventTypeTable
[i
]; 
 867     delete[] m_eventTypeTable
; 
 868     m_eventTypeTable 
= NULL
; 
 873 #if defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING 
 876 void wxEventHashTable::ClearAll() 
 878     wxEventHashTable
* table 
= sm_first
; 
 882         table 
= table
->m_next
; 
 886 #endif // __WXDEBUG__ && wxUSE_MEMORY_TRACING 
 888 bool wxEventHashTable::HandleEvent(wxEvent 
&event
, wxEvtHandler 
*self
) 
 893         m_rebuildHash 
= false; 
 896     if (!m_eventTypeTable
) 
 899     // Find all entries for the given event type. 
 900     wxEventType eventType 
= event
.GetEventType(); 
 901     const EventTypeTablePointer eTTnode 
= m_eventTypeTable
[eventType 
% m_size
]; 
 902     if (eTTnode 
&& eTTnode
->eventType 
== eventType
) 
 904         // Now start the search for an event handler 
 905         // that can handle an event with the given ID. 
 906         const wxEventTableEntryPointerArray
& 
 907             eventEntryTable 
= eTTnode
->eventEntryTable
; 
 909         const size_t count 
= eventEntryTable
.GetCount(); 
 910         for (size_t n 
= 0; n 
< count
; n
++) 
 913                     ProcessEventIfMatches(*eventEntryTable
[n
], self
, event
) ) 
 923 void wxEventHashTable::InitHashTable() 
 925     // Loop over the event tables and all its base tables. 
 926     const wxEventTable 
*table 
= &m_table
; 
 929         // Retrieve all valid event handler entries 
 930         const wxEventTableEntry 
*entry 
= table
->entries
; 
 931         while (entry
->m_fn 
!= 0) 
 933             // Add the event entry in the Hash. 
 939         table 
= table
->baseTable
; 
 942     // Lets free some memory. 
 944     for(i 
= 0; i 
< m_size
; i
++) 
 946         EventTypeTablePointer  eTTnode 
= m_eventTypeTable
[i
]; 
 949             eTTnode
->eventEntryTable
.Shrink(); 
 954 void wxEventHashTable::AddEntry(const wxEventTableEntry 
&entry
) 
 956     // This might happen 'accidentally' as the app is exiting 
 957     if (!m_eventTypeTable
) 
 960     EventTypeTablePointer 
*peTTnode 
= &m_eventTypeTable
[entry
.m_eventType 
% m_size
]; 
 961     EventTypeTablePointer  eTTnode 
= *peTTnode
; 
 965         if (eTTnode
->eventType 
!= entry
.m_eventType
) 
 968             GrowEventTypeTable(); 
 969             // Try again to add it. 
 976         eTTnode 
= new EventTypeTable
; 
 977         eTTnode
->eventType 
= entry
.m_eventType
; 
 981     // Fill all hash entries between entry.m_id and entry.m_lastId... 
 982     eTTnode
->eventEntryTable
.Add(&entry
); 
 985 void wxEventHashTable::AllocEventTypeTable(size_t size
) 
 987     m_eventTypeTable 
= new EventTypeTablePointer
[size
]; 
 988     memset((void *)m_eventTypeTable
, 0, sizeof(EventTypeTablePointer
)*size
); 
 992 void wxEventHashTable::GrowEventTypeTable() 
 994     size_t oldSize 
= m_size
; 
 995     EventTypeTablePointer 
*oldEventTypeTable 
= m_eventTypeTable
; 
 997     // TODO: Search the most optimal grow sequence 
 998     AllocEventTypeTable(/* GetNextPrime(oldSize) */oldSize
*2+1); 
1000     for ( size_t i 
= 0; i 
< oldSize
; /* */ ) 
1002         EventTypeTablePointer  eTToldNode 
= oldEventTypeTable
[i
]; 
1005             EventTypeTablePointer 
*peTTnode 
= &m_eventTypeTable
[eTToldNode
->eventType 
% m_size
]; 
1006             EventTypeTablePointer  eTTnode 
= *peTTnode
; 
1008             // Check for collision, we don't want any. 
1011                 GrowEventTypeTable(); 
1012                 continue; // Don't increment the counter, 
1013                           // as we still need to add this element. 
1017                 // Get the old value and put it in the new table. 
1018                 *peTTnode 
= oldEventTypeTable
[i
]; 
1025     delete[] oldEventTypeTable
; 
1028 // ---------------------------------------------------------------------------- 
1030 // ---------------------------------------------------------------------------- 
1036 wxEvtHandler::wxEvtHandler() 
1038     m_nextHandler 
= (wxEvtHandler 
*) NULL
; 
1039     m_previousHandler 
= (wxEvtHandler 
*) NULL
; 
1041     m_dynamicEvents 
= (wxList 
*) NULL
; 
1042     m_pendingEvents 
= (wxList 
*) NULL
; 
1044     // no client data (yet) 
1045     m_clientData 
= NULL
; 
1046     m_clientDataType 
= wxClientData_None
; 
1049 wxEvtHandler::~wxEvtHandler() 
1051     // Takes itself out of the list of handlers 
1052     if (m_previousHandler
) 
1053         m_previousHandler
->m_nextHandler 
= m_nextHandler
; 
1056         m_nextHandler
->m_previousHandler 
= m_previousHandler
; 
1058     if (m_dynamicEvents
) 
1060         for ( wxList::iterator it 
= m_dynamicEvents
->begin(), 
1061                                end 
= m_dynamicEvents
->end(); 
1065             wxDynamicEventTableEntry 
*entry 
= (wxDynamicEventTableEntry
*)*it
; 
1067             // Remove ourselves from sink destructor notifications 
1068             // (this has usually been been done, in wxTrackable destructor) 
1069             wxEvtHandler 
*eventSink 
= entry
->m_eventSink
; 
1072                 wxEventConnectionRef 
* const 
1073                     evtConnRef 
= FindRefInTrackerList(eventSink
); 
1076                     eventSink
->RemoveNode(evtConnRef
); 
1081             if (entry
->m_callbackUserData
) 
1082                 delete entry
->m_callbackUserData
; 
1085         delete m_dynamicEvents
; 
1088     if (m_pendingEvents
) 
1089         m_pendingEvents
->DeleteContents(true); 
1090     delete m_pendingEvents
; 
1092     // Remove us from wxPendingEvents if necessary. 
1093     if ( wxPendingEvents 
) 
1096         if (wxPendingEventsLocker
) 
1097             wxENTER_CRIT_SECT(*wxPendingEventsLocker
); 
1100         if ( wxPendingEvents
->DeleteObject(this) ) 
1102             // check that we were present only once in the list 
1103             wxASSERT_MSG( !wxPendingEvents
->Find(this), 
1104                           "Handler occurs twice in wxPendingEvents list" ); 
1106         //else: we weren't in this list at all, it's ok 
1109         if (wxPendingEventsLocker
) 
1110             wxLEAVE_CRIT_SECT(*wxPendingEventsLocker
); 
1114     // we only delete object data, not untyped 
1115     if ( m_clientDataType 
== wxClientData_Object 
) 
1116         delete m_clientObject
; 
1121 bool wxEvtHandler::ProcessThreadEvent(const wxEvent
& event
) 
1123     // check that we are really in a child thread 
1124     wxASSERT_MSG( !wxThread::IsMain(), 
1125                   wxT("use ProcessEvent() in main thread") ); 
1127     AddPendingEvent(event
); 
1132 #endif // wxUSE_THREADS 
1134 void wxEvtHandler::QueueEvent(wxEvent 
*event
) 
1136     wxCHECK_RET( event
, "NULL event can't be posted" ); 
1138     // 1) Add this event to our list of pending events 
1139     wxENTER_CRIT_SECT( m_pendingEventsLock 
); 
1141     if ( !m_pendingEvents 
) 
1142       m_pendingEvents 
= new wxList
; 
1144     m_pendingEvents
->Append(event
); 
1146     // 2) Add this event handler to list of event handlers that 
1147     //    have pending events. 
1149     wxENTER_CRIT_SECT(*wxPendingEventsLocker
); 
1151     if ( !wxPendingEvents 
) 
1152         wxPendingEvents 
= new wxList
; 
1153     if ( !wxPendingEvents
->Find(this) ) 
1154         wxPendingEvents
->Append(this); 
1156     wxLEAVE_CRIT_SECT(*wxPendingEventsLocker
); 
1158     // only release m_pendingEventsLock now because otherwise there is a race 
1159     // condition as described in the ticket #9093: we could process the event 
1160     // just added to m_pendingEvents in our ProcessPendingEvents() below before 
1161     // we had time to append this pointer to wxPendingEvents list; thus 
1162     // breaking the invariant that a handler should be in the list iff it has 
1163     // any pending events to process 
1164     wxLEAVE_CRIT_SECT( m_pendingEventsLock 
); 
1166     // 3) Inform the system that new pending events are somewhere, 
1167     //    and that these should be processed in idle time. 
1171 void wxEvtHandler::ProcessPendingEvents() 
1173     wxENTER_CRIT_SECT( m_pendingEventsLock 
); 
1175     // this method is only called by wxApp if this handler does have 
1177     wxCHECK_RET( m_pendingEvents 
&& !m_pendingEvents
->IsEmpty(), 
1178                  "should have pending events if called" ); 
1180     wxList::compatibility_iterator node 
= m_pendingEvents
->GetFirst(); 
1181     wxEventPtr 
event(static_cast<wxEvent 
*>(node
->GetData())); 
1183     // it's important we remove event from list before processing it, else a 
1184     // nested event loop, for example from a modal dialog, might process the 
1185     // same event again. 
1186     m_pendingEvents
->Erase(node
); 
1188     // if there are no more pending events left, we don't need to stay in this 
1190     if ( m_pendingEvents
->IsEmpty() ) 
1193         if (wxPendingEventsLocker
) 
1194             wxENTER_CRIT_SECT(*wxPendingEventsLocker
); 
1196         wxPendingEvents
->DeleteObject(this); 
1198         if (wxPendingEventsLocker
) 
1199             wxLEAVE_CRIT_SECT(*wxPendingEventsLocker
); 
1203     wxLEAVE_CRIT_SECT( m_pendingEventsLock 
); 
1205     ProcessEvent(*event
); 
1207     // careful: this object could have been deleted by the event handler 
1208     // executed by the above ProcessEvent() call, so we can't access any fields 
1209     // of this object any more 
1216 wxEvtHandler::ProcessEventIfMatches(const wxEventTableEntryBase
& entry
, 
1217                                     wxEvtHandler 
*handler
, 
1220     int tableId1 
= entry
.m_id
, 
1221         tableId2 
= entry
.m_lastId
; 
1223     // match only if the event type is the same and the id is either -1 in 
1224     // the event table (meaning "any") or the event id matches the id 
1225     // specified in the event table either exactly or by falling into 
1226     // range between first and last 
1227     if ((tableId1 
== wxID_ANY
) || 
1228         (tableId2 
== wxID_ANY 
&& tableId1 
== event
.GetId()) || 
1229         (tableId2 
!= wxID_ANY 
&& 
1230          (event
.GetId() >= tableId1 
&& event
.GetId() <= tableId2
))) 
1233         event
.m_callbackUserData 
= entry
.m_callbackUserData
; 
1235 #if wxUSE_EXCEPTIONS 
1238             // call the handler via wxApp method which allows the user to catch 
1239             // any exceptions which may be thrown by any handler in the program 
1241             wxTheApp
->HandleEvent(handler
, (wxEventFunction
)entry
.m_fn
, event
); 
1244 #endif // wxUSE_EXCEPTIONS 
1246             // no need for an extra virtual function call 
1247             (handler
->*((wxEventFunction
) (entry
.m_fn
)))(event
); 
1250         if (!event
.GetSkipped()) 
1257 bool wxEvtHandler::TryParent(wxEvent
& event
) 
1259     if ( GetNextHandler() ) 
1261         // the next handler will pass it to wxTheApp if it doesn't process it, 
1262         // so return from here to avoid doing it again 
1263         return GetNextHandler()->TryParent(event
); 
1266     if ( wxTheApp 
&& (this != wxTheApp
) ) 
1268         // Special case: don't pass wxEVT_IDLE to wxApp, since it'll always 
1269         // swallow it. wxEVT_IDLE is sent explicitly to wxApp so it will be 
1270         // processed appropriately via SearchEventTable. 
1271         if ( event
.GetEventType() != wxEVT_IDLE 
) 
1273             if ( wxTheApp
->ProcessEvent(event
) ) 
1281 bool wxEvtHandler::ProcessEvent(wxEvent
& event
) 
1283     // allow the application to hook into event processing 
1286         int rc 
= wxTheApp
->FilterEvent(event
); 
1289             wxASSERT_MSG( rc 
== 1 || rc 
== 0, 
1290                           _T("unexpected wxApp::FilterEvent return value") ); 
1294         //else: proceed normally 
1297     if ( ProcessEventHere(event
) ) 
1300     // propagate the event upwards the window chain and/or to the application 
1301     // object if it wasn't processed at this level 
1302     return TryParent(event
); 
1305 bool wxEvtHandler::ProcessEventHere(wxEvent
& event
) 
1307     // An event handler can be enabled or disabled 
1308     if ( GetEvtHandlerEnabled() ) 
1310         // if we have a validator, it has higher priority than our own event 
1312         if ( TryValidator(event
) ) 
1315         // Handle per-instance dynamic event tables first 
1316         if ( m_dynamicEvents 
&& SearchDynamicEventTable(event
) ) 
1319         // Then static per-class event tables 
1320         if ( GetEventHashTable().HandleEvent(event
, this) ) 
1324     // Try going down the event handler chain 
1325     if ( GetNextHandler() && GetNextHandler()->ProcessEventHere(event
) ) 
1328     // We don't have a handler for this event. 
1332 bool wxEvtHandler::SafelyProcessEvent(wxEvent
& event
) 
1334 #if wxUSE_EXCEPTIONS 
1338         return ProcessEvent(event
); 
1339 #if wxUSE_EXCEPTIONS 
1343         wxEventLoopBase 
*loop 
= wxEventLoopBase::GetActive(); 
1346             if ( !wxTheApp 
|| !wxTheApp
->OnExceptionInMainLoop() ) 
1351             //else: continue running current event loop 
1357             // OnExceptionInMainLoop() threw, possibly rethrowing the same 
1358             // exception again: very good, but we still need Exit() to 
1365 #endif // wxUSE_EXCEPTIONS 
1369 bool wxEvtHandler::SearchEventTable(wxEventTable
& table
, wxEvent
& event
) 
1371     const wxEventType eventType 
= event
.GetEventType(); 
1372     for ( int i 
= 0; table
.entries
[i
].m_fn 
!= 0; i
++ ) 
1374         const wxEventTableEntry
& entry 
= table
.entries
[i
]; 
1375         if ( eventType 
== entry
.m_eventType 
) 
1377             if ( ProcessEventIfMatches(entry
, this, event
) ) 
1385 void wxEvtHandler::Connect( int id
, int lastId
, 
1386                             wxEventType eventType
, 
1387                             wxObjectEventFunction func
, 
1389                             wxEvtHandler
* eventSink 
) 
1391     wxDynamicEventTableEntry 
*entry 
= 
1392         new wxDynamicEventTableEntry(eventType
, id
, lastId
, func
, userData
, eventSink
); 
1394     if (!m_dynamicEvents
) 
1395         m_dynamicEvents 
= new wxList
; 
1397     // Insert at the front of the list so most recent additions are found first 
1398     m_dynamicEvents
->Insert( (wxObject
*) entry 
); 
1400     // Make sure we get to know when a sink is destroyed 
1401     if ( eventSink 
&& eventSink 
!= this ) 
1403         wxEventConnectionRef 
*evtConnRef 
= FindRefInTrackerList(eventSink
); 
1405             evtConnRef
->IncRef( ); 
1407             new wxEventConnectionRef(this, eventSink
); 
1411 bool wxEvtHandler::Disconnect( int id
, int lastId
, wxEventType eventType
, 
1412                   wxObjectEventFunction func
, 
1414                   wxEvtHandler
* eventSink 
) 
1416     if (!m_dynamicEvents
) 
1419     // Remove connection from tracker node (wxEventConnectionRef) 
1420     if ( eventSink 
&& eventSink 
!= this ) 
1422         wxEventConnectionRef 
*evtConnRef 
= FindRefInTrackerList(eventSink
); 
1424             evtConnRef
->DecRef(); 
1427     wxList::compatibility_iterator node 
= m_dynamicEvents
->GetFirst(); 
1430         wxDynamicEventTableEntry 
*entry 
= (wxDynamicEventTableEntry
*)node
->GetData(); 
1432         if ((entry
->m_id 
== id
) && 
1433             ((entry
->m_lastId 
== lastId
) || (lastId 
== wxID_ANY
)) && 
1434             ((entry
->m_eventType 
== eventType
) || (eventType 
== wxEVT_NULL
)) && 
1435             ((entry
->m_fn 
== func
) || (func 
== (wxObjectEventFunction
)NULL
)) && 
1436             ((entry
->m_eventSink 
== eventSink
) || (eventSink 
== (wxEvtHandler
*)NULL
)) && 
1437             ((entry
->m_callbackUserData 
== userData
) || (userData 
== (wxObject
*)NULL
))) 
1439             if (entry
->m_callbackUserData
) 
1440                 delete entry
->m_callbackUserData
; 
1441             m_dynamicEvents
->Erase( node 
); 
1445         node 
= node
->GetNext(); 
1450 bool wxEvtHandler::SearchDynamicEventTable( wxEvent
& event 
) 
1452     wxCHECK_MSG( m_dynamicEvents
, false, 
1453                  wxT("caller should check that we have dynamic events") ); 
1455     wxList::compatibility_iterator node 
= m_dynamicEvents
->GetFirst(); 
1458         wxDynamicEventTableEntry 
*entry 
= (wxDynamicEventTableEntry
*)node
->GetData(); 
1460         // get next node before (maybe) calling the event handler as it could 
1461         // call Disconnect() invalidating the current node 
1462         node 
= node
->GetNext(); 
1464         if ((event
.GetEventType() == entry
->m_eventType
) && (entry
->m_fn 
!= 0)) 
1466             wxEvtHandler 
*handler 
= entry
->m_eventSink 
? entry
->m_eventSink
 
1468             if ( ProcessEventIfMatches(*entry
, handler
, event
) ) 
1476 void wxEvtHandler::DoSetClientObject( wxClientData 
*data 
) 
1478     wxASSERT_MSG( m_clientDataType 
!= wxClientData_Void
, 
1479                   wxT("can't have both object and void client data") ); 
1481     if ( m_clientObject 
) 
1482         delete m_clientObject
; 
1484     m_clientObject 
= data
; 
1485     m_clientDataType 
= wxClientData_Object
; 
1488 wxClientData 
*wxEvtHandler::DoGetClientObject() const 
1490     // it's not an error to call GetClientObject() on a window which doesn't 
1491     // have client data at all - NULL will be returned 
1492     wxASSERT_MSG( m_clientDataType 
!= wxClientData_Void
, 
1493                   wxT("this window doesn't have object client data") ); 
1495     return m_clientObject
; 
1498 void wxEvtHandler::DoSetClientData( void *data 
) 
1500     wxASSERT_MSG( m_clientDataType 
!= wxClientData_Object
, 
1501                   wxT("can't have both object and void client data") ); 
1503     m_clientData 
= data
; 
1504     m_clientDataType 
= wxClientData_Void
; 
1507 void *wxEvtHandler::DoGetClientData() const 
1509     // it's not an error to call GetClientData() on a window which doesn't have 
1510     // client data at all - NULL will be returned 
1511     wxASSERT_MSG( m_clientDataType 
!= wxClientData_Object
, 
1512                   wxT("this window doesn't have void client data") ); 
1514     return m_clientData
; 
1517 // A helper to find an wxEventConnectionRef object 
1518 wxEventConnectionRef 
* 
1519 wxEvtHandler::FindRefInTrackerList(wxEvtHandler 
*eventSink
) 
1521     for ( wxTrackerNode 
*node 
= eventSink
->GetFirst(); node
; node 
= node
->m_nxt 
) 
1523         // we only want wxEventConnectionRef nodes here 
1524         wxEventConnectionRef 
*evtConnRef 
= node
->ToEventConnection(); 
1525         if ( evtConnRef 
&& evtConnRef
->m_src 
== this ) 
1527             wxASSERT( evtConnRef
->m_sink
==eventSink 
); 
1535 void wxEvtHandler::OnSinkDestroyed( wxEvtHandler 
*sink 
) 
1537     wxASSERT(m_dynamicEvents
); 
1539     // remove all connections with this sink 
1540     wxList::compatibility_iterator node 
= m_dynamicEvents
->GetFirst(), node_nxt
; 
1543         wxDynamicEventTableEntry 
*entry 
= (wxDynamicEventTableEntry
*)node
->GetData(); 
1544         node_nxt 
= node
->GetNext(); 
1546         if ( entry
->m_eventSink
==sink 
) 
1548             if (entry
->m_callbackUserData
) 
1549                 delete entry
->m_callbackUserData
; 
1550             m_dynamicEvents
->Erase( node 
); 
1557 #endif // wxUSE_BASE 
1561 // Find a window with the focus, that is also a descendant of the given window. 
1562 // This is used to determine the window to initially send commands to. 
1563 wxWindow
* wxFindFocusDescendant(wxWindow
* ancestor
) 
1565     // Process events starting with the window with the focus, if any. 
1566     wxWindow
* focusWin 
= wxWindow::FindFocus(); 
1567     wxWindow
* win 
= focusWin
; 
1569     // Check if this is a descendant of this frame. 
1570     // If not, win will be set to NULL. 
1573         if (win 
== ancestor
) 
1576             win 
= win
->GetParent(); 
1578     if (win 
== (wxWindow
*) NULL
) 
1579         focusWin 
= (wxWindow
*) NULL
; 
1584 // ---------------------------------------------------------------------------- 
1586 // ---------------------------------------------------------------------------- 
1588 wxEventBlocker::wxEventBlocker(wxWindow 
*win
, wxEventType type
) 
1590     wxCHECK_RET(win
, wxT("Null window given to wxEventBlocker")); 
1595     m_window
->PushEventHandler(this); 
1598 wxEventBlocker::~wxEventBlocker() 
1600     wxEvtHandler 
*popped 
= m_window
->PopEventHandler(false); 
1601     wxCHECK_RET(popped 
== this, 
1602         wxT("Don't push other event handlers into a window managed by wxEventBlocker!")); 
1605 bool wxEventBlocker::ProcessEvent(wxEvent
& event
) 
1607     // should this event be blocked? 
1608     for ( size_t i 
= 0; i 
< m_eventsToBlock
.size(); i
++ ) 
1610         wxEventType t 
= (wxEventType
)m_eventsToBlock
[i
]; 
1611         if ( t 
== wxEVT_ANY 
|| t 
== event
.GetEventType() ) 
1612             return true;   // yes, it should: mark this event as processed