X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/75a29298fa900b388cd380649700dc39c9631178..d3a0a0eeab1965fcf85d15123c32a8f3a1900351:/src/common/event.cpp diff --git a/src/common/event.cpp b/src/common/event.cpp index 5c65c985af..e04611b837 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: event.cpp +// Name: src/common/event.cpp // Purpose: Event classes // Author: Julian Smart // Modified by: @@ -17,17 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) && !defined(__EMX__) -// Some older compilers (such as EMX) cannot handle -// #pragma interface/implementation correctly, iff -// #pragma implementation is used in _two_ translation -// units (as created by e.g. event.cpp compiled for -// libwx_base and event.cpp compiled for libwx_gui_core). -// So we must not use those pragmas for those compilers in -// such files. - #pragma implementation "event.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -35,29 +24,23 @@ #pragma hdrstop #endif +#include "wx/event.h" + #ifndef WX_PRECOMP - #include "wx/defs.h" - #include "wx/app.h" #include "wx/list.h" + #include "wx/app.h" + #include "wx/utils.h" + #include "wx/stopwatch.h" + #include "wx/module.h" #if wxUSE_GUI #include "wx/control.h" - #include "wx/utils.h" #include "wx/dc.h" #include "wx/textctrl.h" + #include "wx/validate.h" #endif // wxUSE_GUI #endif -#include "wx/event.h" -#include "wx/module.h" - -#if wxUSE_GUI - #include "wx/validate.h" -#if wxUSE_STOPWATCH - #include "wx/stopwatch.h" -#endif -#endif // wxUSE_GUI - // ---------------------------------------------------------------------------- // wxWin macros // ---------------------------------------------------------------------------- @@ -103,6 +86,8 @@ IMPLEMENT_DYNAMIC_CLASS(wxHelpEvent, wxCommandEvent) IMPLEMENT_DYNAMIC_CLASS(wxContextMenuEvent, wxCommandEvent) IMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureChangedEvent, wxEvent) + IMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureLostEvent, wxEvent) + IMPLEMENT_DYNAMIC_CLASS(wxClipboardTextEvent, wxCommandEvent) #endif // wxUSE_GUI #if wxUSE_BASE @@ -162,6 +147,7 @@ const wxEventType wxEVT_USER_FIRST = wxEVT_FIRST + 2000; DEFINE_EVENT_TYPE(wxEVT_NULL) DEFINE_EVENT_TYPE(wxEVT_IDLE) DEFINE_EVENT_TYPE(wxEVT_SOCKET) +DEFINE_EVENT_TYPE(wxEVT_TIMER) #endif // !WXWIN_COMPATIBILITY_EVENT_TYPES @@ -188,9 +174,6 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_RCLICKED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOOL_ENTER) DEFINE_EVENT_TYPE(wxEVT_COMMAND_SPINCTRL_UPDATED) -// Sockets and timers send events, too -DEFINE_EVENT_TYPE(wxEVT_TIMER) - // Mouse event types DEFINE_EVENT_TYPE(wxEVT_LEFT_DOWN) DEFINE_EVENT_TYPE(wxEVT_LEFT_UP) @@ -245,7 +228,7 @@ DEFINE_EVENT_TYPE(wxEVT_SCROLL_PAGEUP) DEFINE_EVENT_TYPE(wxEVT_SCROLL_PAGEDOWN) DEFINE_EVENT_TYPE(wxEVT_SCROLL_THUMBTRACK) DEFINE_EVENT_TYPE(wxEVT_SCROLL_THUMBRELEASE) -DEFINE_EVENT_TYPE(wxEVT_SCROLL_ENDSCROLL) +DEFINE_EVENT_TYPE(wxEVT_SCROLL_CHANGED) // Scroll events from wxWindow DEFINE_EVENT_TYPE(wxEVT_SCROLLWIN_TOP) @@ -265,6 +248,7 @@ DEFINE_EVENT_TYPE(wxEVT_MOVING) DEFINE_EVENT_TYPE(wxEVT_CLOSE_WINDOW) DEFINE_EVENT_TYPE(wxEVT_END_SESSION) DEFINE_EVENT_TYPE(wxEVT_QUERY_END_SESSION) +DEFINE_EVENT_TYPE(wxEVT_HIBERNATE) DEFINE_EVENT_TYPE(wxEVT_ACTIVATE_APP) DEFINE_EVENT_TYPE(wxEVT_POWER) DEFINE_EVENT_TYPE(wxEVT_ACTIVATE) @@ -274,6 +258,7 @@ DEFINE_EVENT_TYPE(wxEVT_SHOW) DEFINE_EVENT_TYPE(wxEVT_ICONIZE) DEFINE_EVENT_TYPE(wxEVT_MAXIMIZE) DEFINE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_CHANGED) +DEFINE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_LOST) DEFINE_EVENT_TYPE(wxEVT_PAINT) DEFINE_EVENT_TYPE(wxEVT_ERASE_BACKGROUND) DEFINE_EVENT_TYPE(wxEVT_NC_PAINT) @@ -298,6 +283,11 @@ DEFINE_EVENT_TYPE(wxEVT_COMPARE_ITEM) DEFINE_EVENT_TYPE(wxEVT_INIT_DIALOG) DEFINE_EVENT_TYPE(wxEVT_UPDATE_UI) +// Clipboard events +DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_COPY) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_CUT) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_PASTE) + // Generic command events // Note: a click is a higher-level event than button down/up DEFINE_EVENT_TYPE(wxEVT_COMMAND_LEFT_CLICK) @@ -360,7 +350,7 @@ wxEvent::wxEvent(int theId, wxEventType commandType ) } wxEvent::wxEvent(const wxEvent &src) - : wxObject() + : wxObject(src) , m_eventObject(src.m_eventObject) , m_eventType(src.m_eventType) , m_timeStamp(src.m_timeStamp) @@ -381,11 +371,13 @@ wxEvent::wxEvent(const wxEvent &src) * */ +#ifdef __VISUALC__ + // 'this' : used in base member initializer list (for m_commandString) + #pragma warning(disable:4355) +#endif + wxCommandEvent::wxCommandEvent(wxEventType commandType, int theId) : wxEvent(theId, commandType) -#if WXWIN_COMPATIBILITY_2_4 - , m_commandString(this) -#endif { m_clientData = (char *) NULL; m_clientObject = (wxClientData *) NULL; @@ -397,16 +389,22 @@ wxCommandEvent::wxCommandEvent(wxEventType commandType, int theId) m_propagationLevel = wxEVENT_PROPAGATE_MAX; } +#ifdef __VISUALC__ + #pragma warning(default:4355) +#endif + wxString wxCommandEvent::GetString() const { if(m_eventType != wxEVT_COMMAND_TEXT_UPDATED || !m_eventObject) return m_cmdString; else { +#if wxUSE_TEXTCTRL wxTextCtrl *txt = wxDynamicCast(m_eventObject, wxTextCtrl); if(txt) return txt->GetValue(); else +#endif // wxUSE_TEXTCTRL return m_cmdString; } } @@ -536,6 +534,7 @@ wxMouseEvent::wxMouseEvent(wxEventType commandType) m_wheelRotation = 0; m_wheelDelta = 0; m_linesPerAction = 0; + m_wheelAxis = 0; } void wxMouseEvent::Assign(const wxMouseEvent& event) @@ -557,6 +556,7 @@ void wxMouseEvent::Assign(const wxMouseEvent& event) m_wheelRotation = event.m_wheelRotation; m_wheelDelta = event.m_wheelDelta; m_linesPerAction = event.m_linesPerAction; + m_wheelAxis = event.m_wheelAxis; } // return true if was a button dclick event @@ -736,10 +736,12 @@ wxKeyEvent::wxKeyEvent(const wxKeyEvent& evt) #endif } +#if WXWIN_COMPATIBILITY_2_6 long wxKeyEvent::KeyCode() const { return m_keyCode; } +#endif // WXWIN_COMPATIBILITY_2_6 wxWindowCreateEvent::wxWindowCreateEvent(wxWindow *win) { @@ -759,6 +761,23 @@ wxChildFocusEvent::wxChildFocusEvent(wxWindow *win) SetEventObject(win); } +// ---------------------------------------------------------------------------- +// wxHelpEvent +// ---------------------------------------------------------------------------- + +/* static */ +wxHelpEvent::Origin wxHelpEvent::GuessOrigin(Origin origin) +{ + if ( origin == Origin_Unknown ) + { + // assume that the event comes from the help button if it's not from + // keyboard and that pressing F1 always results in the help event + origin = wxGetKeyState(WXK_F1) ? Origin_Keyboard : Origin_HelpButton; + } + + return origin; +} + #endif // wxUSE_GUI @@ -989,6 +1008,7 @@ wxEvtHandler::wxEvtHandler() m_eventsLocker = new wxCriticalSection; # endif #endif + // no client data (yet) m_clientData = NULL; m_clientDataType = wxClientData_None; @@ -1022,6 +1042,8 @@ wxEvtHandler::~wxEvtHandler() delete m_dynamicEvents; }; + if (m_pendingEvents) + m_pendingEvents->DeleteContents(true); delete m_pendingEvents; #if wxUSE_THREADS @@ -1032,8 +1054,10 @@ wxEvtHandler::~wxEvtHandler() // Remove us from wxPendingEvents if necessary. if(wxPendingEventsLocker) wxENTER_CRIT_SECT(*wxPendingEventsLocker); - if ( wxPendingEvents ) { - wxPendingEvents->DeleteObject(this); + if ( wxPendingEvents ) + { + // Delete all occurences of this from the list of pending events + while (wxPendingEvents->DeleteObject(this)) { } // Do nothing } if(wxPendingEventsLocker) wxLEAVE_CRIT_SECT(*wxPendingEventsLocker); @@ -1063,7 +1087,7 @@ void wxEvtHandler::ClearEventLocker() delete m_eventsLocker; m_eventsLocker = NULL; #endif -}; +} #endif // wxUSE_THREADS @@ -1078,22 +1102,14 @@ void wxEvtHandler::AddPendingEvent(wxEvent& event) wxCHECK_RET( eventCopy, _T("events of this type aren't supposed to be posted") ); -#if defined(__VISAGECPP__) - wxENTER_CRIT_SECT( m_eventsLocker); -#else - wxENTER_CRIT_SECT( *m_eventsLocker); -#endif + wxENTER_CRIT_SECT( Lock() ); if ( !m_pendingEvents ) m_pendingEvents = new wxList; m_pendingEvents->Append(eventCopy); -#if defined(__VISAGECPP__) - wxLEAVE_CRIT_SECT( m_eventsLocker); -#else - wxLEAVE_CRIT_SECT( *m_eventsLocker); -#endif + wxLEAVE_CRIT_SECT( Lock() ); // 2) Add this event handler to list of event handlers that // have pending events. @@ -1106,63 +1122,50 @@ void wxEvtHandler::AddPendingEvent(wxEvent& event) wxLEAVE_CRIT_SECT(*wxPendingEventsLocker); - // 3) Inform the system that new pending events are somwehere, + // 3) Inform the system that new pending events are somewhere, // and that these should be processed in idle time. wxWakeUpIdle(); } void wxEvtHandler::ProcessPendingEvents() { - // this method is only called by wxApp if this handler does have pending - // events + // this method is only called by wxApp if this handler does have + // pending events wxCHECK_RET( m_pendingEvents, wxT("Please call wxApp::ProcessPendingEvents() instead") ); - -#if defined(__VISAGECPP__) - wxENTER_CRIT_SECT( m_eventsLocker); -#else - wxENTER_CRIT_SECT( *m_eventsLocker); -#endif - - // remember last event to process during this iteration - wxList::compatibility_iterator lastPendingNode = m_pendingEvents->GetLast(); - - wxList::compatibility_iterator node = m_pendingEvents->GetFirst(); - while ( node ) + + wxENTER_CRIT_SECT( Lock() ); + + // we leave the loop once we have processed all events that were present at + // the start of ProcessPendingEvents because otherwise we could get into + // infinite loop if the pending event handler execution resulted in another + // event being posted + size_t n = m_pendingEvents->size(); + for ( wxList::compatibility_iterator node = m_pendingEvents->GetFirst(); + node; + node = m_pendingEvents->GetFirst() ) { wxEvent *event = (wxEvent *)node->GetData(); + + // It's importan we remove event from list before processing it. + // Else a nested event loop, for example from a modal dialog, might + // process the same event again. + m_pendingEvents->Erase(node); - // In ProcessEvent, new events might get added and - // we can safely leave the crtical section here. -#if defined(__VISAGECPP__) - wxLEAVE_CRIT_SECT( m_eventsLocker); -#else - wxLEAVE_CRIT_SECT( *m_eventsLocker); -#endif + wxLEAVE_CRIT_SECT( Lock() ); + ProcessEvent(*event); + delete event; -#if defined(__VISAGECPP__) - wxENTER_CRIT_SECT( m_eventsLocker); -#else - wxENTER_CRIT_SECT( *m_eventsLocker); -#endif - // leave the loop once we have processed all events that were present - // at the start of ProcessPendingEvents because otherwise we could get - // into infinite loop if the pending event handler execution resulted - // in another event being posted - if ( node == lastPendingNode ) - break; + wxENTER_CRIT_SECT( Lock() ); - node = m_pendingEvents->GetFirst(); + if ( --n == 0 ) + break; } -#if defined(__VISAGECPP__) - wxLEAVE_CRIT_SECT( m_eventsLocker); -#else - wxLEAVE_CRIT_SECT( *m_eventsLocker); -#endif + wxLEAVE_CRIT_SECT( Lock() ); } /* @@ -1363,6 +1366,10 @@ bool wxEvtHandler::SearchDynamicEventTable( wxEvent& event ) wxDynamicEventTableEntry *entry = (wxDynamicEventTableEntry*)node->GetData(); #endif // WXWIN_COMPATIBILITY_EVENT_TYPES/!WXWIN_COMPATIBILITY_EVENT_TYPES + // get next node before (maybe) calling the event handler as it could + // call Disconnect() invalidating the current node + node = node->GetNext(); + if ((event.GetEventType() == entry->m_eventType) && (entry->m_fn != 0)) { wxEvtHandler *handler = @@ -1377,12 +1384,10 @@ bool wxEvtHandler::SearchDynamicEventTable( wxEvent& event ) return true; } } - - node = node->GetNext(); } return false; -}; +} void wxEvtHandler::DoSetClientObject( wxClientData *data ) { @@ -1452,4 +1457,38 @@ wxWindow* wxFindFocusDescendant(wxWindow* ancestor) return focusWin; } +// ---------------------------------------------------------------------------- +// wxEventBlocker +// ---------------------------------------------------------------------------- + +wxEventBlocker::wxEventBlocker(wxWindow *win, wxEventType type) +{ + wxCHECK_RET(win, wxT("Null window given to wxEventBlocker")); + + m_window = win; + + Block(type); + m_window->PushEventHandler(this); +} + +wxEventBlocker::~wxEventBlocker() +{ + wxEvtHandler *popped = m_window->PopEventHandler(false); + wxCHECK_RET(popped == this, + wxT("Don't push other event handlers into a window managed by wxEventBlocker!")); +} + +bool wxEventBlocker::ProcessEvent(wxEvent& event) +{ + // should this event be blocked? + for ( size_t i = 0; i < m_eventsToBlock.size(); i++ ) + { + wxEventType t = (wxEventType)m_eventsToBlock[i]; + if ( t == wxEVT_ANY || t == event.GetEventType() ) + return true; // yes, it should: mark this event as processed + } + + return false; +} + #endif // wxUSE_GUI