1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Event classes 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart and Markus Holzem 
   9 // Licence:       wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13     #pragma implementation "event.h" 
  16 // For compilers that support precompilation, includes "wx.h". 
  17 #include "wx/wxprec.h" 
  25     #include "wx/control.h" 
  32 #include "wx/validate.h" 
  34 #if !USE_SHARED_LIBRARY 
  35     IMPLEMENT_DYNAMIC_CLASS(wxEvtHandler
, wxObject
) 
  36     IMPLEMENT_ABSTRACT_CLASS(wxEvent
, wxObject
) 
  37     IMPLEMENT_DYNAMIC_CLASS(wxCommandEvent
, wxEvent
) 
  38     IMPLEMENT_DYNAMIC_CLASS(wxNotifyEvent
, wxCommandEvent
) 
  39     IMPLEMENT_DYNAMIC_CLASS(wxScrollEvent
, wxCommandEvent
) 
  40     IMPLEMENT_DYNAMIC_CLASS(wxScrollWinEvent
, wxEvent
) 
  41     IMPLEMENT_DYNAMIC_CLASS(wxMouseEvent
, wxEvent
) 
  42     IMPLEMENT_DYNAMIC_CLASS(wxKeyEvent
, wxEvent
) 
  43     IMPLEMENT_DYNAMIC_CLASS(wxSizeEvent
, wxEvent
) 
  44     IMPLEMENT_DYNAMIC_CLASS(wxPaintEvent
, wxEvent
) 
  45     IMPLEMENT_DYNAMIC_CLASS(wxEraseEvent
, wxEvent
) 
  46     IMPLEMENT_DYNAMIC_CLASS(wxMoveEvent
, wxEvent
) 
  47     IMPLEMENT_DYNAMIC_CLASS(wxFocusEvent
, wxEvent
) 
  48     IMPLEMENT_DYNAMIC_CLASS(wxCloseEvent
, wxEvent
) 
  49     IMPLEMENT_DYNAMIC_CLASS(wxShowEvent
, wxEvent
) 
  50     IMPLEMENT_DYNAMIC_CLASS(wxMaximizeEvent
, wxEvent
) 
  51     IMPLEMENT_DYNAMIC_CLASS(wxIconizeEvent
, wxEvent
) 
  52     IMPLEMENT_DYNAMIC_CLASS(wxMenuEvent
, wxEvent
) 
  53     IMPLEMENT_DYNAMIC_CLASS(wxJoystickEvent
, wxEvent
) 
  54     IMPLEMENT_DYNAMIC_CLASS(wxDropFilesEvent
, wxEvent
) 
  55     IMPLEMENT_DYNAMIC_CLASS(wxActivateEvent
, wxEvent
) 
  56     IMPLEMENT_DYNAMIC_CLASS(wxInitDialogEvent
, wxEvent
) 
  57     IMPLEMENT_DYNAMIC_CLASS(wxSysColourChangedEvent
, wxEvent
) 
  58     IMPLEMENT_DYNAMIC_CLASS(wxIdleEvent
, wxEvent
) 
  59     IMPLEMENT_DYNAMIC_CLASS(wxUpdateUIEvent
, wxCommandEvent
) 
  60     IMPLEMENT_DYNAMIC_CLASS(wxNavigationKeyEvent
, wxCommandEvent
) 
  61     IMPLEMENT_DYNAMIC_CLASS(wxPaletteChangedEvent
, wxEvent
) 
  62     IMPLEMENT_DYNAMIC_CLASS(wxQueryNewPaletteEvent
, wxEvent
) 
  64     const wxEventTable 
*wxEvtHandler::GetEventTable() const 
  65         { return &wxEvtHandler::sm_eventTable
; } 
  67     const wxEventTable 
wxEvtHandler::sm_eventTable 
= 
  68         { (const wxEventTable 
*)NULL
, &wxEvtHandler::sm_eventTableEntries
[0] }; 
  70     const wxEventTableEntry 
wxEvtHandler::sm_eventTableEntries
[] = 
  71         { { 0, 0, 0, (wxObjectEventFunction
) NULL
, (wxObject
*) NULL 
} }; 
  73 #endif // !USE_SHARED_LIBRARY 
  76 /* To put pending event handlers */ 
  77 extern wxList 
*wxPendingEvents
; 
  78 extern wxCriticalSection 
*wxPendingEventsLocker
; 
  82  * General wxWindows events, covering 
  83  * all interesting things that might happen (button clicking, resizing, 
  84  * setting text in widgets, etc.). 
  86  * For each completely new event type, derive a new event class. 
  90 wxEvent::wxEvent(int theId
) 
  92     m_eventType 
= wxEVT_NULL
; 
  93     m_eventObject 
= (wxObject 
*) NULL
; 
  94     m_eventHandle 
= (char *) NULL
; 
  98     m_callbackUserData 
= (wxObject 
*) NULL
; 
  99     m_isCommandEvent 
= FALSE
; 
 102 void wxEvent::CopyObject(wxObject
& object_dest
) const 
 104     wxEvent 
*obj 
= (wxEvent 
*)&object_dest
;  
 105     wxObject::CopyObject(object_dest
); 
 107     obj
->m_eventType 
= m_eventType
; 
 108     obj
->m_eventObject 
= m_eventObject
; 
 109     obj
->m_eventHandle 
= m_eventHandle
; 
 110     obj
->m_timeStamp 
= m_timeStamp
; 
 112     obj
->m_skipped 
= m_skipped
; 
 113     obj
->m_callbackUserData 
= m_callbackUserData
; 
 114     obj
->m_isCommandEvent 
= m_isCommandEvent
; 
 122 wxCommandEvent::wxCommandEvent(wxEventType commandType
, int theId
) 
 124     m_eventType 
= commandType
; 
 125     m_clientData 
= (char *) NULL
; 
 126     m_clientObject 
= (wxClientData 
*) NULL
; 
 130     m_commandString 
= (wxChar 
*) NULL
; 
 131     m_isCommandEvent 
= TRUE
; 
 134 void wxCommandEvent::CopyObject(wxObject
& obj_d
) const 
 136     wxCommandEvent 
*obj 
= (wxCommandEvent 
*)&obj_d
;  
 138     wxEvent::CopyObject(obj_d
); 
 140     obj
->m_clientData   
= m_clientData
; 
 141     obj
->m_clientObject 
= m_clientObject
; 
 142     obj
->m_extraLong    
= m_extraLong
; 
 143     obj
->m_commandInt   
= m_commandInt
; 
 150 wxScrollEvent::wxScrollEvent(wxEventType commandType
, 
 154              : wxCommandEvent(commandType
, id
) 
 156     m_extraLong 
= orient
; 
 164 wxScrollWinEvent::wxScrollWinEvent(wxEventType commandType
, 
 167              : wxEvent(commandType
) 
 169     m_extraLong 
= orient
; 
 178 wxMouseEvent::wxMouseEvent(wxEventType commandType
) 
 180     m_eventType 
= commandType
; 
 183     m_controlDown 
= FALSE
; 
 187     m_middleDown 
= FALSE
; 
 192 void wxMouseEvent::CopyObject(wxObject
& obj_d
) const 
 194     wxMouseEvent 
*obj 
= (wxMouseEvent 
*)&obj_d
; 
 196     wxEvent::CopyObject(obj_d
); 
 198     obj
->m_metaDown 
= m_metaDown
; 
 199     obj
->m_altDown 
= m_altDown
; 
 200     obj
->m_controlDown 
= m_controlDown
; 
 201     obj
->m_shiftDown 
= m_shiftDown
; 
 202     obj
->m_leftDown 
= m_leftDown
; 
 203     obj
->m_rightDown 
= m_rightDown
; 
 204     obj
->m_middleDown 
= m_middleDown
; 
 209 // True if was a button dclick event (1 = left, 2 = middle, 3 = right) 
 210 // or any button dclick event (but = -1) 
 211 bool wxMouseEvent::ButtonDClick(int but
) const 
 216             return (LeftDClick() || MiddleDClick() || RightDClick()); 
 220             return MiddleDClick(); 
 222             return RightDClick(); 
 224             wxFAIL_MSG(_T("invalid parameter in wxMouseEvent::ButtonDClick")); 
 230 // True if was a button down event (1 = left, 2 = middle, 3 = right) 
 231 // or any button down event (but = -1) 
 232 bool wxMouseEvent::ButtonDown(int but
) const 
 237             return (LeftDown() || MiddleDown() || RightDown()); 
 245             wxFAIL_MSG(_T("invalid parameter in wxMouseEvent::ButtonDown")); 
 251 // True if was a button up event (1 = left, 2 = middle, 3 = right) 
 252 // or any button up event (but = -1) 
 253 bool wxMouseEvent::ButtonUp(int but
) const 
 257             return (LeftUp() || MiddleUp() || RightUp()); 
 265             wxFAIL_MSG(_T("invalid parameter in wxMouseEvent::ButtonUp")); 
 271 // True if the given button is currently changing state 
 272 bool wxMouseEvent::Button(int but
) const 
 276             return (ButtonUp(-1) || ButtonDown(-1) || ButtonDClick(-1)) ; 
 278             return (LeftDown() || LeftUp() || LeftDClick()); 
 280             return (MiddleDown() || MiddleUp() || MiddleDClick()); 
 282             return (RightDown() || RightUp() || RightDClick()); 
 284             wxFAIL_MSG(_T("invalid parameter in wxMouseEvent::Button")); 
 290 bool wxMouseEvent::ButtonIsDown(int but
) const 
 294             return (LeftIsDown() || MiddleIsDown() || RightIsDown()); 
 298             return MiddleIsDown(); 
 300             return RightIsDown(); 
 302             wxFAIL_MSG(_T("invalid parameter in wxMouseEvent::ButtonIsDown")); 
 308 // Find the logical position of the event given the DC 
 309 wxPoint 
wxMouseEvent::GetLogicalPosition(const wxDC
& dc
) const 
 311     wxPoint 
pt(dc
.DeviceToLogicalX(m_x
), dc
.DeviceToLogicalY(m_y
)); 
 321 wxKeyEvent::wxKeyEvent(wxEventType type
) 
 325     m_controlDown 
= FALSE
; 
 331 void wxKeyEvent::CopyObject(wxObject
& obj_d
) const 
 333     wxKeyEvent 
*obj 
= (wxKeyEvent 
*)&obj_d
; 
 334     wxEvent::CopyObject(obj_d
); 
 336     obj
->m_shiftDown   
= m_shiftDown
; 
 337     obj
->m_controlDown 
= m_controlDown
; 
 338     obj
->m_metaDown    
= m_metaDown
; 
 339     obj
->m_altDown     
= m_altDown
; 
 340     obj
->m_keyCode     
= m_keyCode
; 
 348 void wxSizeEvent::CopyObject(wxObject
& obj_d
) const 
 350     wxSizeEvent 
*obj 
= (wxSizeEvent 
*)&obj_d
; 
 351     wxEvent::CopyObject(obj_d
); 
 353     obj
->m_size 
= m_size
; 
 356 void wxMoveEvent::CopyObject(wxObject
& obj_d
) const 
 358     wxMoveEvent 
*obj 
= (wxMoveEvent 
*)&obj_d
; 
 359     wxEvent::CopyObject(obj_d
); 
 364 void wxEraseEvent::CopyObject(wxObject
& obj_d
) const 
 366     wxEraseEvent 
*obj 
= (wxEraseEvent 
*)&obj_d
; 
 367     wxEvent::CopyObject(obj_d
); 
 372 void wxActivateEvent::CopyObject(wxObject
& obj_d
) const 
 374     wxActivateEvent 
*obj 
= (wxActivateEvent 
*)&obj_d
; 
 375     wxEvent::CopyObject(obj_d
); 
 377     obj
->m_active 
= m_active
; 
 380 void wxMenuEvent::CopyObject(wxObject
& obj_d
) const 
 382     wxMenuEvent 
*obj 
= (wxMenuEvent 
*)&obj_d
; 
 383     wxEvent::CopyObject(obj_d
); 
 385     obj
->m_menuId 
= m_menuId
; 
 388 void wxCloseEvent::CopyObject(wxObject
& obj_d
) const 
 390     wxCloseEvent 
*obj 
= (wxCloseEvent 
*)&obj_d
; 
 391     wxEvent::CopyObject(obj_d
); 
 393     obj
->m_loggingOff 
= m_loggingOff
; 
 394     obj
->m_veto 
= m_veto
; 
 395 #if WXWIN_COMPATIBILITY 
 396     obj
->m_force 
= m_force
; 
 398     obj
->m_canVeto 
= m_canVeto
; 
 401 void wxShowEvent::CopyObject(wxObject
& obj_d
) const 
 403     wxShowEvent 
*obj 
= (wxShowEvent 
*)&obj_d
; 
 404     wxEvent::CopyObject(obj_d
); 
 406     obj
->m_show 
= m_show
; 
 414 wxEvtHandler::wxEvtHandler() 
 416     m_nextHandler 
= (wxEvtHandler 
*) NULL
; 
 417     m_previousHandler 
= (wxEvtHandler 
*) NULL
; 
 419     m_dynamicEvents 
= (wxList 
*) NULL
; 
 422     m_eventsLocker 
= new wxCriticalSection(); 
 424     m_pendingEvents 
= (wxList 
*) NULL
; 
 427 wxEvtHandler::~wxEvtHandler() 
 429     // Takes itself out of the list of handlers 
 430     if (m_previousHandler
) 
 431         m_previousHandler
->m_nextHandler 
= m_nextHandler
; 
 434         m_nextHandler
->m_previousHandler 
= m_previousHandler
; 
 438         wxNode 
*node 
= m_dynamicEvents
->First(); 
 441             wxEventTableEntry 
*entry 
= (wxEventTableEntry
*)node
->Data(); 
 442             if (entry
->m_callbackUserData
) delete entry
->m_callbackUserData
; 
 446         delete m_dynamicEvents
; 
 451       delete m_pendingEvents
; 
 453     delete m_eventsLocker
; 
 460 extern bool g_isIdle
; 
 462 extern void wxapp_install_idle_handler(); 
 465 bool wxEvtHandler::ProcessThreadEvent(wxEvent
& event
) 
 468     wxCriticalSectionLocker 
locker(*m_eventsLocker
); 
 471     // check that we are really in a child thread 
 472     wxASSERT( !wxThread::IsMain() ); 
 474     if (m_pendingEvents 
== NULL
) 
 475       m_pendingEvents 
= new wxList(); 
 477     event_main 
= (wxEvent 
*)event
.Clone(); 
 479     m_pendingEvents
->Append(event_main
); 
 481     wxPendingEventsLocker
->Enter(); 
 482     wxPendingEvents
->Append(this); 
 483     wxPendingEventsLocker
->Leave(); 
 486     if (g_isIdle
) wxapp_install_idle_handler(); 
 492 void wxEvtHandler::ProcessPendingEvents() 
 494     wxCriticalSectionLocker 
locker(*m_eventsLocker
); 
 495     wxNode 
*node 
= m_pendingEvents
->First(); 
 498     while (node 
!= NULL
) { 
 499       event 
= (wxEvent 
*)node
->Data(); 
 500       ProcessEvent(*event
); 
 502       node 
= m_pendingEvents
->First(); 
 511 bool wxEvtHandler::ProcessEvent(wxEvent
& event
) 
 513     // check that our flag corresponds to reality 
 514     wxASSERT( m_isWindow 
== IsKindOf(CLASSINFO(wxWindow
)) ); 
 516     // An event handler can be enabled or disabled 
 517     if ( GetEvtHandlerEnabled() ) 
 520         // Check whether we are in a child thread. 
 521         if (!wxThread::IsMain()) 
 522           return ProcessThreadEvent(event
); 
 524         // Handle per-instance dynamic event tables first 
 526         if ( m_dynamicEvents 
&& SearchDynamicEventTable(event
) ) 
 529         // Then static per-class event tables 
 531         const wxEventTable 
*table 
= GetEventTable(); 
 533         // Try the associated validator first, if this is a window. 
 534         // Problem: if the event handler of the window has been replaced, 
 535         // this wxEvtHandler may no longer be a window. 
 536         // Therefore validators won't be processed if the handler 
 537         // has been replaced with SetEventHandler. 
 538         // THIS CAN BE CURED if PushEventHandler is used instead of 
 539         // SetEventHandler, and then processing will be passed down the 
 540         // chain of event handlers. 
 543             wxWindow 
*win 
= (wxWindow 
*)this; 
 545             // Can only use the validator of the window which 
 546             // is receiving the event 
 547             if ( win 
== event
.GetEventObject() ) 
 549                 wxValidator 
*validator 
= win
->GetValidator(); 
 550                 if ( validator 
&& validator
->ProcessEvent(event
) ) 
 557         // Search upwards through the inheritance hierarchy 
 560             if ( SearchEventTable((wxEventTable
&)*table
, event
) ) 
 562             table 
= table
->baseTable
; 
 566     // Try going down the event handler chain 
 567     if ( GetNextHandler() ) 
 569         if ( GetNextHandler()->ProcessEvent(event
) ) 
 573     // Carry on up the parent-child hierarchy, 
 574     // but only if event is a command event: it wouldn't 
 575     // make sense for a parent to receive a child's size event, for example 
 576     if ( m_isWindow 
&& event
.IsCommandEvent() ) 
 578         wxWindow 
*win 
= (wxWindow 
*)this; 
 579         wxWindow 
*parent 
= win
->GetParent(); 
 580         if (parent 
&& !parent
->IsBeingDeleted()) 
 581             return parent
->GetEventHandler()->ProcessEvent(event
); 
 584     // Last try - application object. 
 585     if ( wxTheApp 
&& (this != wxTheApp
) ) 
 587         // Special case: don't pass wxEVT_IDLE to wxApp, since it'll always 
 588         // swallow it. wxEVT_IDLE is sent explicitly to wxApp so it will be 
 589         // processed appropriately via SearchEventTable. 
 590         if ( event
.GetEventType() != wxEVT_IDLE 
) 
 592             if ( wxTheApp
->ProcessEvent(event
) ) 
 600 bool wxEvtHandler::SearchEventTable(wxEventTable
& table
, wxEvent
& event
) 
 603     int commandId 
= event
.GetId(); 
 605     // BC++ doesn't like while (table.entries[i].m_fn) 
 608     while (table
.entries
[i
].m_fn 
!= 0) 
 610     while (table
.entries
[i
].m_fn 
!= 0L) 
 613         if ((event
.GetEventType() == table
.entries
[i
].m_eventType
) && 
 614                 (table
.entries
[i
].m_id 
== -1 || // Match, if event spec says any id will do (id == -1) 
 615                  (table
.entries
[i
].m_lastId 
== -1 && commandId 
== table
.entries
[i
].m_id
) || 
 616                  (table
.entries
[i
].m_lastId 
!= -1 && 
 617                   (commandId 
>= table
.entries
[i
].m_id 
&& commandId 
<= table
.entries
[i
].m_lastId
)))) 
 620             event
.m_callbackUserData 
= table
.entries
[i
].m_callbackUserData
; 
 622             (this->*((wxEventFunction
) (table
.entries
[i
].m_fn
)))(event
); 
 624             if ( event
.GetSkipped() ) 
 633 void wxEvtHandler::Connect( int id
, int lastId
, 
 634                             wxEventType eventType
, 
 635                             wxObjectEventFunction func
, 
 638     wxEventTableEntry 
*entry 
= new wxEventTableEntry
; 
 640     entry
->m_lastId 
= lastId
; 
 641     entry
->m_eventType 
= eventType
; 
 643     entry
->m_callbackUserData 
= userData
; 
 645     if (!m_dynamicEvents
) 
 646         m_dynamicEvents 
= new wxList
; 
 648     m_dynamicEvents
->Append( (wxObject
*) entry 
); 
 651 bool wxEvtHandler::SearchDynamicEventTable( wxEvent
& event 
) 
 653     wxCHECK_MSG( m_dynamicEvents
, FALSE
, 
 654                  _T("caller should check that we have dynamic events") ); 
 656     int commandId 
= event
.GetId(); 
 658     wxNode 
*node 
= m_dynamicEvents
->First(); 
 661         wxEventTableEntry 
*entry 
= (wxEventTableEntry
*)node
->Data(); 
 665             // Match, if event spec says any id will do (id == -1) 
 666             if ( (event
.GetEventType() == entry
->m_eventType
) && 
 667                  (entry
->m_id 
== -1 || 
 668                   (entry
->m_lastId 
== -1 && commandId 
== entry
->m_id
) || 
 669                   (entry
->m_lastId 
!= -1 && 
 670                   (commandId 
>= entry
->m_id 
&& commandId 
<= entry
->m_lastId
))) ) 
 673                 event
.m_callbackUserData 
= entry
->m_callbackUserData
; 
 675                 (this->*((wxEventFunction
) (entry
->m_fn
)))(event
); 
 677                 if (event
.GetSkipped()) 
 688 #if WXWIN_COMPATIBILITY 
 689 bool wxEvtHandler::OnClose() 
 691     if (GetNextHandler()) 
 692         return GetNextHandler()->OnClose(); 
 696 #endif // WXWIN_COMPATIBILITY 
 698 // Find a window with the focus, that is also a descendant of the given window. 
 699 // This is used to determine the window to initially send commands to. 
 700 wxWindow
* wxFindFocusDescendant(wxWindow
* ancestor
) 
 702     // Process events starting with the window with the focus, if any. 
 703     wxWindow
* focusWin 
= wxWindow::FindFocus(); 
 704     wxWindow
* win 
= focusWin
; 
 706     // Check if this is a descendant of this frame. 
 707     // If not, win will be set to NULL. 
 713             win 
= win
->GetParent(); 
 715     if (win 
== (wxWindow
*) NULL
) 
 716         focusWin 
= (wxWindow
*) NULL
;