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
; 
 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
; 
 474 wxEvtHandler::wxEvtHandler() 
 476     m_nextHandler 
= (wxEvtHandler 
*) NULL
; 
 477     m_previousHandler 
= (wxEvtHandler 
*) NULL
; 
 479     m_dynamicEvents 
= (wxList 
*) NULL
; 
 482     m_eventsLocker 
= new wxCriticalSection(); 
 484     m_pendingEvents 
= (wxList 
*) NULL
; 
 487 wxEvtHandler::~wxEvtHandler() 
 489     // Takes itself out of the list of handlers 
 490     if (m_previousHandler
) 
 491         m_previousHandler
->m_nextHandler 
= m_nextHandler
; 
 494         m_nextHandler
->m_previousHandler 
= m_previousHandler
; 
 498         wxNode 
*node 
= m_dynamicEvents
->First(); 
 501             wxEventTableEntry 
*entry 
= (wxEventTableEntry
*)node
->Data(); 
 502             if (entry
->m_callbackUserData
) delete entry
->m_callbackUserData
; 
 506         delete m_dynamicEvents
; 
 511       delete m_pendingEvents
; 
 513     delete m_eventsLocker
; 
 520 extern bool g_isIdle
; 
 522 extern void wxapp_install_idle_handler(); 
 525 bool wxEvtHandler::ProcessThreadEvent(wxEvent
& event
) 
 528     wxCriticalSectionLocker 
locker(*m_eventsLocker
); 
 530     // check that we are really in a child thread 
 531     wxASSERT( !wxThread::IsMain() ); 
 533     if (m_pendingEvents 
== NULL
) 
 534       m_pendingEvents 
= new wxList(); 
 536     event_main 
= (wxEvent 
*)event
.Clone(); 
 538     m_pendingEvents
->Append(event_main
); 
 540     wxPendingEventsLocker
->Enter(); 
 541     wxPendingEvents
->Append(this); 
 542     wxPendingEventsLocker
->Leave(); 
 545 //    if (g_isIdle) wxapp_install_idle_handler(); 
 551 void wxEvtHandler::ProcessPendingEvents() 
 553     wxCriticalSectionLocker 
locker(*m_eventsLocker
); 
 554     wxNode 
*node 
= m_pendingEvents
->First(); 
 557     while (node 
!= NULL
) { 
 558       event 
= (wxEvent 
*)node
->Data(); 
 559       ProcessEvent(*event
); 
 561       node 
= m_pendingEvents
->First(); 
 570 bool wxEvtHandler::ProcessEvent(wxEvent
& event
) 
 572     // check that our flag corresponds to reality 
 573     wxASSERT( m_isWindow 
== IsKindOf(CLASSINFO(wxWindow
)) ); 
 575     // An event handler can be enabled or disabled 
 576     if ( GetEvtHandlerEnabled() ) 
 579         // Check whether we are in a child thread. 
 580         if (!wxThread::IsMain()) 
 581           return ProcessThreadEvent(event
); 
 583         // Handle per-instance dynamic event tables first 
 585         if ( m_dynamicEvents 
&& SearchDynamicEventTable(event
) ) 
 588         // Then static per-class event tables 
 590         const wxEventTable 
*table 
= GetEventTable(); 
 592         // Try the associated validator first, if this is a window. 
 593         // Problem: if the event handler of the window has been replaced, 
 594         // this wxEvtHandler may no longer be a window. 
 595         // Therefore validators won't be processed if the handler 
 596         // has been replaced with SetEventHandler. 
 597         // THIS CAN BE CURED if PushEventHandler is used instead of 
 598         // SetEventHandler, and then processing will be passed down the 
 599         // chain of event handlers. 
 602             wxWindow 
*win 
= (wxWindow 
*)this; 
 604             // Can only use the validator of the window which 
 605             // is receiving the event 
 606             if ( win 
== event
.GetEventObject() ) 
 608                 wxValidator 
*validator 
= win
->GetValidator(); 
 609                 if ( validator 
&& validator
->ProcessEvent(event
) ) 
 616         // Search upwards through the inheritance hierarchy 
 619             if ( SearchEventTable((wxEventTable
&)*table
, event
) ) 
 621             table 
= table
->baseTable
; 
 625     // Try going down the event handler chain 
 626     if ( GetNextHandler() ) 
 628         if ( GetNextHandler()->ProcessEvent(event
) ) 
 632     // Carry on up the parent-child hierarchy, 
 633     // but only if event is a command event: it wouldn't 
 634     // make sense for a parent to receive a child's size event, for example 
 635     if ( m_isWindow 
&& event
.IsCommandEvent() ) 
 637         wxWindow 
*win 
= (wxWindow 
*)this; 
 638         wxWindow 
*parent 
= win
->GetParent(); 
 639         if (parent 
&& !parent
->IsBeingDeleted()) 
 640             return parent
->GetEventHandler()->ProcessEvent(event
); 
 643     // Last try - application object. 
 644     if ( wxTheApp 
&& (this != wxTheApp
) ) 
 646         // Special case: don't pass wxEVT_IDLE to wxApp, since it'll always 
 647         // swallow it. wxEVT_IDLE is sent explicitly to wxApp so it will be 
 648         // processed appropriately via SearchEventTable. 
 649         if ( event
.GetEventType() != wxEVT_IDLE 
) 
 651             if ( wxTheApp
->ProcessEvent(event
) ) 
 659 bool wxEvtHandler::SearchEventTable(wxEventTable
& table
, wxEvent
& event
) 
 662     int commandId 
= event
.GetId(); 
 664     // BC++ doesn't like while (table.entries[i].m_fn) 
 667     while (table
.entries
[i
].m_fn 
!= 0) 
 669     while (table
.entries
[i
].m_fn 
!= 0L) 
 672         if ((event
.GetEventType() == table
.entries
[i
].m_eventType
) && 
 673                 (table
.entries
[i
].m_id 
== -1 || // Match, if event spec says any id will do (id == -1) 
 674                  (table
.entries
[i
].m_lastId 
== -1 && commandId 
== table
.entries
[i
].m_id
) || 
 675                  (table
.entries
[i
].m_lastId 
!= -1 && 
 676                   (commandId 
>= table
.entries
[i
].m_id 
&& commandId 
<= table
.entries
[i
].m_lastId
)))) 
 679             event
.m_callbackUserData 
= table
.entries
[i
].m_callbackUserData
; 
 681             (this->*((wxEventFunction
) (table
.entries
[i
].m_fn
)))(event
); 
 683             if ( event
.GetSkipped() ) 
 692 void wxEvtHandler::Connect( int id
, int lastId
, 
 693                             wxEventType eventType
, 
 694                             wxObjectEventFunction func
, 
 697     wxEventTableEntry 
*entry 
= new wxEventTableEntry
; 
 699     entry
->m_lastId 
= lastId
; 
 700     entry
->m_eventType 
= eventType
; 
 702     entry
->m_callbackUserData 
= userData
; 
 704     if (!m_dynamicEvents
) 
 705         m_dynamicEvents 
= new wxList
; 
 707     m_dynamicEvents
->Append( (wxObject
*) entry 
); 
 710 bool wxEvtHandler::SearchDynamicEventTable( wxEvent
& event 
) 
 712     wxCHECK_MSG( m_dynamicEvents
, FALSE
, 
 713                  _T("caller should check that we have dynamic events") ); 
 715     int commandId 
= event
.GetId(); 
 717     wxNode 
*node 
= m_dynamicEvents
->First(); 
 720         wxEventTableEntry 
*entry 
= (wxEventTableEntry
*)node
->Data(); 
 724             // Match, if event spec says any id will do (id == -1) 
 725             if ( (event
.GetEventType() == entry
->m_eventType
) && 
 726                  (entry
->m_id 
== -1 || 
 727                   (entry
->m_lastId 
== -1 && commandId 
== entry
->m_id
) || 
 728                   (entry
->m_lastId 
!= -1 && 
 729                   (commandId 
>= entry
->m_id 
&& commandId 
<= entry
->m_lastId
))) ) 
 732                 event
.m_callbackUserData 
= entry
->m_callbackUserData
; 
 734                 (this->*((wxEventFunction
) (entry
->m_fn
)))(event
); 
 736                 if (event
.GetSkipped()) 
 747 #if WXWIN_COMPATIBILITY 
 748 bool wxEvtHandler::OnClose() 
 750     if (GetNextHandler()) 
 751         return GetNextHandler()->OnClose(); 
 755 #endif // WXWIN_COMPATIBILITY 
 757 // Find a window with the focus, that is also a descendant of the given window. 
 758 // This is used to determine the window to initially send commands to. 
 759 wxWindow
* wxFindFocusDescendant(wxWindow
* ancestor
) 
 761     // Process events starting with the window with the focus, if any. 
 762     wxWindow
* focusWin 
= wxWindow::FindFocus(); 
 763     wxWindow
* win 
= focusWin
; 
 765     // Check if this is a descendant of this frame. 
 766     // If not, win will be set to NULL. 
 772             win 
= win
->GetParent(); 
 774     if (win 
== (wxWindow
*) NULL
) 
 775         focusWin 
= (wxWindow
*) NULL
;