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
) 
  63     IMPLEMENT_DYNAMIC_CLASS(wxWindowCreateEvent
, wxEvent
) 
  64     IMPLEMENT_DYNAMIC_CLASS(wxWindowDestroyEvent
, wxEvent
) 
  66     const wxEventTable 
*wxEvtHandler::GetEventTable() const 
  67         { return &wxEvtHandler::sm_eventTable
; } 
  69     const wxEventTable 
wxEvtHandler::sm_eventTable 
= 
  70         { (const wxEventTable 
*)NULL
, &wxEvtHandler::sm_eventTableEntries
[0] }; 
  72     const wxEventTableEntry 
wxEvtHandler::sm_eventTableEntries
[] = 
  73         { { 0, 0, 0, (wxObjectEventFunction
) NULL
, (wxObject
*) NULL 
} }; 
  75 #endif // !USE_SHARED_LIBRARY 
  78 /* To put pending event handlers */ 
  79 extern wxList 
*wxPendingEvents
; 
  80 extern wxCriticalSection 
*wxPendingEventsLocker
; 
  84  * General wxWindows events, covering 
  85  * all interesting things that might happen (button clicking, resizing, 
  86  * setting text in widgets, etc.). 
  88  * For each completely new event type, derive a new event class. 
  92 wxEvent::wxEvent(int theId
) 
  94     m_eventType 
= wxEVT_NULL
; 
  95     m_eventObject 
= (wxObject 
*) NULL
; 
  99     m_callbackUserData 
= (wxObject 
*) NULL
; 
 100     m_isCommandEvent 
= FALSE
; 
 103 void wxEvent::CopyObject(wxObject
& object_dest
) const 
 105     wxEvent 
*obj 
= (wxEvent 
*)&object_dest
;  
 106     wxObject::CopyObject(object_dest
); 
 108     obj
->m_eventType 
= m_eventType
; 
 109     obj
->m_eventObject 
= m_eventObject
; 
 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
, 
 168     m_eventType 
= 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
; 
 332 void wxKeyEvent::CopyObject(wxObject
& obj_d
) const 
 334     wxKeyEvent 
*obj 
= (wxKeyEvent 
*)&obj_d
; 
 335     wxEvent::CopyObject(obj_d
); 
 337     obj
->m_shiftDown   
= m_shiftDown
; 
 338     obj
->m_controlDown 
= m_controlDown
; 
 339     obj
->m_metaDown    
= m_metaDown
; 
 340     obj
->m_altDown     
= m_altDown
; 
 341     obj
->m_keyCode     
= m_keyCode
; 
 349 void wxSizeEvent::CopyObject(wxObject
& obj_d
) const 
 351     wxSizeEvent 
*obj 
= (wxSizeEvent 
*)&obj_d
; 
 352     wxEvent::CopyObject(obj_d
); 
 354     obj
->m_size 
= m_size
; 
 357 void wxMoveEvent::CopyObject(wxObject
& obj_d
) const 
 359     wxMoveEvent 
*obj 
= (wxMoveEvent 
*)&obj_d
; 
 360     wxEvent::CopyObject(obj_d
); 
 365 void wxEraseEvent::CopyObject(wxObject
& obj_d
) const 
 367     wxEraseEvent 
*obj 
= (wxEraseEvent 
*)&obj_d
; 
 368     wxEvent::CopyObject(obj_d
); 
 373 void wxActivateEvent::CopyObject(wxObject
& obj_d
) const 
 375     wxActivateEvent 
*obj 
= (wxActivateEvent 
*)&obj_d
; 
 376     wxEvent::CopyObject(obj_d
); 
 378     obj
->m_active 
= m_active
; 
 381 void wxMenuEvent::CopyObject(wxObject
& obj_d
) const 
 383     wxMenuEvent 
*obj 
= (wxMenuEvent 
*)&obj_d
; 
 384     wxEvent::CopyObject(obj_d
); 
 386     obj
->m_menuId 
= m_menuId
; 
 389 void wxCloseEvent::CopyObject(wxObject
& obj_d
) const 
 391     wxCloseEvent 
*obj 
= (wxCloseEvent 
*)&obj_d
; 
 392     wxEvent::CopyObject(obj_d
); 
 394     obj
->m_loggingOff 
= m_loggingOff
; 
 395     obj
->m_veto 
= m_veto
; 
 396 #if WXWIN_COMPATIBILITY 
 397     obj
->m_force 
= m_force
; 
 399     obj
->m_canVeto 
= m_canVeto
; 
 402 void wxShowEvent::CopyObject(wxObject
& obj_d
) const 
 404     wxShowEvent 
*obj 
= (wxShowEvent 
*)&obj_d
; 
 405     wxEvent::CopyObject(obj_d
); 
 407     obj
->m_show 
= m_show
; 
 410 void wxJoystickEvent::CopyObject(wxObject
& obj_d
) const 
 412     wxJoystickEvent 
*obj 
= (wxJoystickEvent 
*)&obj_d
; 
 413     wxEvent::CopyObject(obj_d
); 
 416     obj
->m_zPosition 
= m_zPosition
; 
 417     obj
->m_buttonChange 
= m_buttonChange
; 
 418     obj
->m_buttonState 
= m_buttonState
; 
 419     obj
->m_joyStick 
= m_joyStick
; 
 422 void wxDropFilesEvent::CopyObject(wxObject
& obj_d
) const 
 424     wxDropFilesEvent 
*obj 
= (wxDropFilesEvent 
*)&obj_d
; 
 425     wxEvent::CopyObject(obj_d
); 
 427     obj
->m_noFiles 
= m_noFiles
; 
 429     // TODO: Problem with obj->m_files. It should be deallocated by the 
 430     // destructor of the event.  
 433 void wxIdleEvent::CopyObject(wxObject
& obj_d
) const 
 435     wxIdleEvent 
*obj 
= (wxIdleEvent 
*)&obj_d
; 
 436     wxEvent::CopyObject(obj_d
); 
 438     obj
->m_requestMore 
= m_requestMore
; 
 441 void wxUpdateUIEvent::CopyObject(wxObject 
&obj_d
) const 
 443     wxUpdateUIEvent 
*obj 
= (wxUpdateUIEvent 
*)&obj_d
; 
 444     wxEvent::CopyObject(obj_d
); 
 446     obj
->m_checked 
= m_checked
; 
 447     obj
->m_enabled 
= m_enabled
; 
 448     obj
->m_text 
= m_text
; 
 449     obj
->m_setText 
= m_setText
; 
 450     obj
->m_setChecked 
= m_setChecked
; 
 451     obj
->m_setEnabled 
= m_setEnabled
; 
 454 void wxPaletteChangedEvent::CopyObject(wxObject 
&obj_d
) const 
 456     wxPaletteChangedEvent 
*obj 
= (wxPaletteChangedEvent 
*)&obj_d
; 
 457     wxEvent::CopyObject(obj_d
); 
 459     obj
->m_changedWindow 
= m_changedWindow
; 
 462 void wxQueryNewPaletteEvent::CopyObject(wxObject
& obj_d
) const 
 464     wxQueryNewPaletteEvent 
*obj 
= (wxQueryNewPaletteEvent 
*)&obj_d
; 
 465     wxEvent::CopyObject(obj_d
); 
 467     obj
->m_paletteRealized 
= m_paletteRealized
; 
 470 wxWindowCreateEvent::wxWindowCreateEvent(wxWindow 
*win
) 
 471                    : wxEvent(wxEVT_CREATE
) 
 476 wxWindowDestroyEvent::wxWindowDestroyEvent(wxWindow 
*win
) 
 477                     : wxEvent(wxEVT_DESTROY
) 
 486 wxEvtHandler::wxEvtHandler() 
 488     m_nextHandler 
= (wxEvtHandler 
*) NULL
; 
 489     m_previousHandler 
= (wxEvtHandler 
*) NULL
; 
 491     m_dynamicEvents 
= (wxList 
*) NULL
; 
 494     m_eventsLocker 
= new wxCriticalSection(); 
 496     m_pendingEvents 
= (wxList 
*) NULL
; 
 499 wxEvtHandler::~wxEvtHandler() 
 501     // Takes itself out of the list of handlers 
 502     if (m_previousHandler
) 
 503         m_previousHandler
->m_nextHandler 
= m_nextHandler
; 
 506         m_nextHandler
->m_previousHandler 
= m_previousHandler
; 
 510         wxNode 
*node 
= m_dynamicEvents
->First(); 
 513             wxEventTableEntry 
*entry 
= (wxEventTableEntry
*)node
->Data(); 
 514             if (entry
->m_callbackUserData
) delete entry
->m_callbackUserData
; 
 518         delete m_dynamicEvents
; 
 523       delete m_pendingEvents
; 
 525     delete m_eventsLocker
; 
 532 extern bool g_isIdle
; 
 533 extern void wxapp_install_idle_handler(); 
 536 bool wxEvtHandler::ProcessThreadEvent(wxEvent
& event
) 
 539     wxCriticalSectionLocker 
locker(*m_eventsLocker
); 
 541     // check that we are really in a child thread 
 542     wxASSERT( !wxThread::IsMain() ); 
 544     if (m_pendingEvents 
== NULL
) 
 545       m_pendingEvents 
= new wxList(); 
 547     event_main 
= (wxEvent 
*)event
.Clone(); 
 549     m_pendingEvents
->Append(event_main
); 
 551     wxPendingEventsLocker
->Enter(); 
 552     wxPendingEvents
->Append(this); 
 553     wxPendingEventsLocker
->Leave(); 
 557 //        wxapp_install_idle_handler(); 
 563 void wxEvtHandler::ProcessPendingEvents() 
 565     wxCriticalSectionLocker 
locker(*m_eventsLocker
); 
 566     wxNode 
*node 
= m_pendingEvents
->First(); 
 569     while (node 
!= NULL
) { 
 570       event 
= (wxEvent 
*)node
->Data(); 
 571       ProcessEvent(*event
); 
 573       node 
= m_pendingEvents
->First(); 
 582 bool wxEvtHandler::ProcessEvent(wxEvent
& event
) 
 584     // check that our flag corresponds to reality 
 585     wxASSERT( m_isWindow 
== IsKindOf(CLASSINFO(wxWindow
)) ); 
 587     // An event handler can be enabled or disabled 
 588     if ( GetEvtHandlerEnabled() ) 
 591         // Check whether we are in a child thread. 
 592         if (!wxThread::IsMain()) 
 593           return ProcessThreadEvent(event
); 
 595         // Handle per-instance dynamic event tables first 
 597         if ( m_dynamicEvents 
&& SearchDynamicEventTable(event
) ) 
 600         // Then static per-class event tables 
 602         const wxEventTable 
*table 
= GetEventTable(); 
 604         // Try the associated validator first, if this is a window. 
 605         // Problem: if the event handler of the window has been replaced, 
 606         // this wxEvtHandler may no longer be a window. 
 607         // Therefore validators won't be processed if the handler 
 608         // has been replaced with SetEventHandler. 
 609         // THIS CAN BE CURED if PushEventHandler is used instead of 
 610         // SetEventHandler, and then processing will be passed down the 
 611         // chain of event handlers. 
 614             wxWindow 
*win 
= (wxWindow 
*)this; 
 616             // Can only use the validator of the window which 
 617             // is receiving the event 
 618             if ( win 
== event
.GetEventObject() ) 
 620                 wxValidator 
*validator 
= win
->GetValidator(); 
 621                 if ( validator 
&& validator
->ProcessEvent(event
) ) 
 628         // Search upwards through the inheritance hierarchy 
 631             if ( SearchEventTable((wxEventTable
&)*table
, event
) ) 
 633             table 
= table
->baseTable
; 
 637     // Try going down the event handler chain 
 638     if ( GetNextHandler() ) 
 640         if ( GetNextHandler()->ProcessEvent(event
) ) 
 644     // Carry on up the parent-child hierarchy, 
 645     // but only if event is a command event: it wouldn't 
 646     // make sense for a parent to receive a child's size event, for example 
 647     if ( m_isWindow 
&& event
.IsCommandEvent() ) 
 649         wxWindow 
*win 
= (wxWindow 
*)this; 
 650         wxWindow 
*parent 
= win
->GetParent(); 
 651         if (parent 
&& !parent
->IsBeingDeleted()) 
 652             return parent
->GetEventHandler()->ProcessEvent(event
); 
 655     // Last try - application object. 
 656     if ( wxTheApp 
&& (this != wxTheApp
) ) 
 658         // Special case: don't pass wxEVT_IDLE to wxApp, since it'll always 
 659         // swallow it. wxEVT_IDLE is sent explicitly to wxApp so it will be 
 660         // processed appropriately via SearchEventTable. 
 661         if ( event
.GetEventType() != wxEVT_IDLE 
) 
 663             if ( wxTheApp
->ProcessEvent(event
) ) 
 671 bool wxEvtHandler::SearchEventTable(wxEventTable
& table
, wxEvent
& event
) 
 674     int commandId 
= event
.GetId(); 
 676     // BC++ doesn't like while (table.entries[i].m_fn) 
 679     while (table
.entries
[i
].m_fn 
!= 0) 
 681     while (table
.entries
[i
].m_fn 
!= 0L) 
 684         if ((event
.GetEventType() == table
.entries
[i
].m_eventType
) && 
 685                 (table
.entries
[i
].m_id 
== -1 || // Match, if event spec says any id will do (id == -1) 
 686                  (table
.entries
[i
].m_lastId 
== -1 && commandId 
== table
.entries
[i
].m_id
) || 
 687                  (table
.entries
[i
].m_lastId 
!= -1 && 
 688                   (commandId 
>= table
.entries
[i
].m_id 
&& commandId 
<= table
.entries
[i
].m_lastId
)))) 
 691             event
.m_callbackUserData 
= table
.entries
[i
].m_callbackUserData
; 
 693             (this->*((wxEventFunction
) (table
.entries
[i
].m_fn
)))(event
); 
 695             if ( event
.GetSkipped() ) 
 704 void wxEvtHandler::Connect( int id
, int lastId
, 
 705                             wxEventType eventType
, 
 706                             wxObjectEventFunction func
, 
 709     wxEventTableEntry 
*entry 
= new wxEventTableEntry
; 
 711     entry
->m_lastId 
= lastId
; 
 712     entry
->m_eventType 
= eventType
; 
 714     entry
->m_callbackUserData 
= userData
; 
 716     if (!m_dynamicEvents
) 
 717         m_dynamicEvents 
= new wxList
; 
 719     m_dynamicEvents
->Append( (wxObject
*) entry 
); 
 722 bool wxEvtHandler::SearchDynamicEventTable( wxEvent
& event 
) 
 724     wxCHECK_MSG( m_dynamicEvents
, FALSE
, 
 725                  _T("caller should check that we have dynamic events") ); 
 727     int commandId 
= event
.GetId(); 
 729     wxNode 
*node 
= m_dynamicEvents
->First(); 
 732         wxEventTableEntry 
*entry 
= (wxEventTableEntry
*)node
->Data(); 
 736             // Match, if event spec says any id will do (id == -1) 
 737             if ( (event
.GetEventType() == entry
->m_eventType
) && 
 738                  (entry
->m_id 
== -1 || 
 739                   (entry
->m_lastId 
== -1 && commandId 
== entry
->m_id
) || 
 740                   (entry
->m_lastId 
!= -1 && 
 741                   (commandId 
>= entry
->m_id 
&& commandId 
<= entry
->m_lastId
))) ) 
 744                 event
.m_callbackUserData 
= entry
->m_callbackUserData
; 
 746                 (this->*((wxEventFunction
) (entry
->m_fn
)))(event
); 
 748                 if (event
.GetSkipped()) 
 759 #if WXWIN_COMPATIBILITY 
 760 bool wxEvtHandler::OnClose() 
 762     if (GetNextHandler()) 
 763         return GetNextHandler()->OnClose(); 
 767 #endif // WXWIN_COMPATIBILITY 
 769 // Find a window with the focus, that is also a descendant of the given window. 
 770 // This is used to determine the window to initially send commands to. 
 771 wxWindow
* wxFindFocusDescendant(wxWindow
* ancestor
) 
 773     // Process events starting with the window with the focus, if any. 
 774     wxWindow
* focusWin 
= wxWindow::FindFocus(); 
 775     wxWindow
* win 
= focusWin
; 
 777     // Check if this is a descendant of this frame. 
 778     // If not, win will be set to NULL. 
 784             win 
= win
->GetParent(); 
 786     if (win 
== (wxWindow
*) NULL
) 
 787         focusWin 
= (wxWindow
*) NULL
;