X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ad81651f00edc6f489d9b6a0839d316a964fd521..90c0f5a958242295e950cbd1eedbae8f5309442d:/src/os2/timer.cpp diff --git a/src/os2/timer.cpp b/src/os2/timer.cpp index 05784150e4..cb2d9518cc 100644 --- a/src/os2/timer.cpp +++ b/src/os2/timer.cpp @@ -31,31 +31,73 @@ #include #include + +// ---------------------------------------------------------------------------- +// private globals +// ---------------------------------------------------------------------------- + +// define a hash containing all the timers: it is indexed by timer id and +// contains the corresponding timer +WX_DECLARE_HASH_MAP(unsigned long, wxTimer *, wxIntegerHash, wxIntegerEqual, + wxTimerMap); + +// instead of using a global here, wrap it in a static function as otherwise it +// could have been used before being initialized if a timer object were created +// globally +static wxTimerMap& TimerMap() +{ + static wxTimerMap s_timerMap; + + return s_timerMap; +} + // ---------------------------------------------------------------------------- // private functions // ---------------------------------------------------------------------------- -wxList wxTimerList(wxKEY_INTEGER); +// timer callback used for all timers ULONG wxTimerProc(HWND hwnd, ULONG, int nIdTimer, ULONG); // ---------------------------------------------------------------------------- // macros // ---------------------------------------------------------------------------- -IMPLEMENT_ABSTRACT_CLASS(wxTimer, wxObject) +IMPLEMENT_ABSTRACT_CLASS(wxTimer, wxEvtHandler) -wxTimer::wxTimer() +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxTimer class +// ---------------------------------------------------------------------------- + +void wxTimer::Init() { m_ulId = 0; } wxTimer::~wxTimer() { - Stop(); - - wxTimerList.DeleteObject(this); + wxTimer::Stop(); } +void wxTimer::Notify() +{ + // + // The base class version generates an event if it has owner - which it + // should because otherwise nobody can process timer events, but it does + // not use the OS's ID, which OS/2 must have to figure out which timer fired + // + wxCHECK_RET( m_owner, _T("wxTimer::Notify() should be overridden.") ); + + wxTimerEvent vEvent( m_idTimer + ,m_milli + ); + + (void)m_owner->ProcessEvent(vEvent); +} // end of wxTimer::Notify + bool wxTimer::Start( int nMilliseconds , bool bOneShot @@ -67,22 +109,42 @@ bool wxTimer::Start( wxCHECK_MSG( m_milli > 0L, FALSE, wxT("invalid value for timer") ); - wxTimerList.DeleteObject(this); + wxWindow* pWin = NULL; - // - // Create a windowless timer - // - m_ulId = ::WinStartTimer( m_Hab - ,NULL - ,(m_ulId ? m_ulId : 1L) - ,(ULONG)nMilliseconds - ); + if (m_owner) + { + pWin = (wxWindow*)m_owner; + m_ulId = ::WinStartTimer( m_Hab + ,pWin->GetHWND() + ,m_idTimer + ,(ULONG)nMilliseconds + ); + } + else + m_ulId = ::WinStartTimer( m_Hab + ,NULLHANDLE + ,0 + ,(ULONG)nMilliseconds + ); if (m_ulId > 0L) { - wxTimerList.Append( m_ulId - ,this - ); - return(TRUE); + // check that SetTimer() didn't reuse an existing id: according to + // the MSDN this can happen and this would be catastrophic to us as + // we rely on ids uniquely identifying the timers because we use + // them as keys in the hash + if ( TimerMap().find(m_ulId) != TimerMap().end() ) + { + wxLogError(_("Timer creation failed.")); + + ::WinStopTimer(m_Hab, pWin?(pWin->GetHWND()):NULL, m_ulId); + m_ulId = 0; + + return false; + } + + TimerMap()[m_ulId] = this; + + return true; } else { @@ -96,8 +158,16 @@ void wxTimer::Stop() { if ( m_ulId ) { - ::WinStopTimer(m_Hab, NULL, m_ulId); - wxTimerList.DeleteObject(this); + if (m_owner) + { + wxWindow* pWin = (wxWindow*)m_owner; + + ::WinStopTimer(m_Hab, pWin->GetHWND(), m_ulId); + } + else + ::WinStopTimer(m_Hab, NULLHANDLE, m_ulId); + + TimerMap().erase(m_ulId); } m_ulId = 0L; } @@ -129,11 +199,11 @@ ULONG wxTimerProc( , ULONG ) { - wxNode* pNode = wxTimerList.Find((ULONG)nIdTimer); - - wxCHECK_MSG(pNode, 0, wxT("bogus timer id in wxTimerProc") ); + wxTimerMap::iterator node = TimerMap().find((ULONG)nIdTimer); - wxProcessTimer(*(wxTimer *)pNode->Data()); + wxCHECK_MSG(node != TimerMap().end(), 0, + wxT("bogus timer id in wxTimerProc") ); + wxProcessTimer(*(node->second)); return 0; }