diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2016-11-13 06:13:22 +0100 |
---|---|---|
committer | Jan-Marek Glogowski <glogow@fbihome.de> | 2017-07-13 12:10:25 +0200 |
commit | 3e20ce802ee2ab49c4f2a98880f6e999657686bb (patch) | |
tree | 36371101121e00c047e7b99755c55bb3336ea620 | |
parent | 1fedc1c38a141bf071c707fda6a3ae1a5bf8fd41 (diff) |
GTK+ simplifiy system timer implementation
Instead of implementing an own GSource, this implements the glib
based system timer using the g_timeout_source_new() function.
It removes the vector of GtkSalTimer and changes the remaining
timer to be single-shot, just like the Windows and KDE platforms.
The ownership handling is a little bit strange and should generally
be changed to use std::shared_ptr as the result of CreateSalTimer
for all backends.
Change-Id: Iea40a6284bdc5c121235af5a6079a92a679391ca
-rw-r--r-- | vcl/inc/unx/gtk/gtkdata.hxx | 4 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/gtkinst.hxx | 4 | ||||
-rw-r--r-- | vcl/unx/gtk/gtkdata.cxx | 148 | ||||
-rw-r--r-- | vcl/unx/gtk/gtkinst.cxx | 25 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkdata.cxx | 148 |
5 files changed, 70 insertions, 259 deletions
diff --git a/vcl/inc/unx/gtk/gtkdata.hxx b/vcl/inc/unx/gtk/gtkdata.hxx index 2582314eb003..052fc071dcc0 100644 --- a/vcl/inc/unx/gtk/gtkdata.hxx +++ b/vcl/inc/unx/gtk/gtkdata.hxx @@ -81,15 +81,13 @@ inline void widget_set_can_default(GtkWidget *widget, gboolean can_default) class GtkSalTimer : public SalTimer { - struct SalGtkTimeoutSource *m_pTimeout; + GSource *m_pTimeout; public: GtkSalTimer(); virtual ~GtkSalTimer() override; virtual void Start( sal_uLong nMS ) override; virtual void Stop() override; bool Expired(); - - sal_uLong m_nTimeoutMS; }; class GtkData : public SalGenericData diff --git a/vcl/inc/unx/gtk/gtkinst.hxx b/vcl/inc/unx/gtk/gtkinst.hxx index 4c86a3d62867..ff8271b514a4 100644 --- a/vcl/inc/unx/gtk/gtkinst.hxx +++ b/vcl/inc/unx/gtk/gtkinst.hxx @@ -233,12 +233,12 @@ public: const cairo_font_options_t* GetLastSeenCairoFontOptions(); void ResetLastSeenCairoFontOptions(); - void RemoveTimer (SalTimer *pTimer); + void RemoveTimer(); std::shared_ptr<vcl::unx::GtkPrintWrapper> const & getPrintWrapper() const; private: - std::vector<GtkSalTimer *> m_aTimers; + GtkSalTimer* m_pTimer; #if GTK_CHECK_VERSION(3,0,0) std::unordered_map< GdkAtom, css::uno::Reference<css::uno::XInterface> > m_aClipboards; #endif diff --git a/vcl/unx/gtk/gtkdata.cxx b/vcl/unx/gtk/gtkdata.cxx index e5278f157698..76c9fed0e733 100644 --- a/vcl/unx/gtk/gtkdata.cxx +++ b/vcl/unx/gtk/gtkdata.cxx @@ -652,161 +652,71 @@ bool GtkData::ErrorTrapPop( bool bIgnoreError ) return gdk_error_trap_pop () != 0; } -extern "C" { - - struct SalGtkTimeoutSource { - GSource aParent; - GTimeVal aFireTime; - GtkSalTimer *pInstance; - }; - - static void sal_gtk_timeout_defer( SalGtkTimeoutSource *pTSource ) - { - g_get_current_time( &pTSource->aFireTime ); - g_time_val_add( &pTSource->aFireTime, pTSource->pInstance->m_nTimeoutMS * 1000 ); - } - - static gboolean sal_gtk_timeout_expired( SalGtkTimeoutSource *pTSource, - gint *nTimeoutMS, GTimeVal *pTimeNow ) - { - glong nDeltaSec = pTSource->aFireTime.tv_sec - pTimeNow->tv_sec; - glong nDeltaUSec = pTSource->aFireTime.tv_usec - pTimeNow->tv_usec; - if( nDeltaSec < 0 || ( nDeltaSec == 0 && nDeltaUSec < 0) ) - { - *nTimeoutMS = 0; - return TRUE; - } - if( nDeltaUSec < 0 ) - { - nDeltaUSec += 1000000; - nDeltaSec -= 1; - } - // if the clock changes backwards we need to cope ... - if( (unsigned long) nDeltaSec > 1 + ( pTSource->pInstance->m_nTimeoutMS / 1000 ) ) - { - sal_gtk_timeout_defer( pTSource ); - return TRUE; - } - - *nTimeoutMS = MIN( G_MAXINT, ( nDeltaSec * 1000 + (nDeltaUSec + 999) / 1000 ) ); - - return *nTimeoutMS == 0; - } - - static gboolean sal_gtk_timeout_prepare( GSource *pSource, gint *nTimeoutMS ) - { - SalGtkTimeoutSource *pTSource = reinterpret_cast<SalGtkTimeoutSource *>(pSource); - - GTimeVal aTimeNow; - g_get_current_time( &aTimeNow ); - - return sal_gtk_timeout_expired( pTSource, nTimeoutMS, &aTimeNow ); - } - - static gboolean sal_gtk_timeout_check( GSource *pSource ) - { - SalGtkTimeoutSource *pTSource = reinterpret_cast<SalGtkTimeoutSource *>(pSource); - - GTimeVal aTimeNow; - g_get_current_time( &aTimeNow ); - - return ( pTSource->aFireTime.tv_sec < aTimeNow.tv_sec || - ( pTSource->aFireTime.tv_sec == aTimeNow.tv_sec && - pTSource->aFireTime.tv_usec < aTimeNow.tv_usec ) ); - } +#if !GLIB_CHECK_VERSION(2,32,0) +#define G_SOURCE_REMOVE FALSE +#endif - static gboolean sal_gtk_timeout_dispatch( GSource *pSource, GSourceFunc, gpointer ) +extern "C" { + static gboolean sal_gtk_timeout_function( gpointer ) { - SalGtkTimeoutSource *pTSource = reinterpret_cast<SalGtkTimeoutSource *>(pSource); - - if( !pTSource->pInstance ) - return FALSE; - GtkData *pSalData = static_cast< GtkData* >( GetSalData()); - osl::Guard< comphelper::SolarMutex > aGuard( pSalData->m_pInstance->GetYieldMutex() ); - sal_gtk_timeout_defer( pTSource ); - ImplSVData* pSVData = ImplGetSVData(); if( pSVData->maSchedCtx.mpSalTimer ) pSVData->maSchedCtx.mpSalTimer->CallCallback(); - - return TRUE; + return G_SOURCE_REMOVE; } - - static GSourceFuncs sal_gtk_timeout_funcs = - { - sal_gtk_timeout_prepare, - sal_gtk_timeout_check, - sal_gtk_timeout_dispatch, - nullptr, nullptr, nullptr - }; -} - -static SalGtkTimeoutSource * -create_sal_gtk_timeout( GtkSalTimer *pTimer ) -{ - GSource *pSource = g_source_new( &sal_gtk_timeout_funcs, sizeof( SalGtkTimeoutSource ) ); - SalGtkTimeoutSource *pTSource = reinterpret_cast<SalGtkTimeoutSource *>(pSource); - pTSource->pInstance = pTimer; - - // #i36226# timers should be executed with lower priority - // than XEvents like in generic plugin - g_source_set_priority( pSource, G_PRIORITY_LOW ); - g_source_set_can_recurse( pSource, TRUE ); - g_source_set_callback( pSource, - /* unused dummy */ g_idle_remove_by_data, - nullptr, nullptr ); - g_source_attach( pSource, g_main_context_default() ); -#ifdef DBG_UTIL - g_source_set_name( pSource, "VCL timeout source" ); -#endif - - sal_gtk_timeout_defer( pTSource ); - - return pTSource; } GtkSalTimer::GtkSalTimer() : m_pTimeout(nullptr) - , m_nTimeoutMS(0) { } GtkSalTimer::~GtkSalTimer() { GtkInstance *pInstance = static_cast<GtkInstance *>(GetSalData()->m_pInstance); - pInstance->RemoveTimer( this ); + pInstance->RemoveTimer(); Stop(); } bool GtkSalTimer::Expired() { - if( !m_pTimeout ) + if( !m_pTimeout || g_source_is_destroyed( m_pTimeout ) ) return false; - - gint nDummy = 0; - GTimeVal aTimeNow; - g_get_current_time( &aTimeNow ); - return !!sal_gtk_timeout_expired( m_pTimeout, &nDummy, &aTimeNow); + return (g_get_monotonic_time() > g_source_get_ready_time( m_pTimeout )); } void GtkSalTimer::Start( sal_uLong nMS ) { // glib is not 64bit safe in this regard. - assert( nMS <= G_MAXINT ); - m_nTimeoutMS = nMS; // for restarting - Stop(); // FIXME: ideally re-use an existing m_pTimeout - m_pTimeout = create_sal_gtk_timeout( this ); + if ( nMS > G_MAXINT ) + nMS = G_MAXINT; + + Stop(); + assert( nullptr == m_pTimeout ); + + m_pTimeout = g_timeout_source_new ( nMS ); + // #i36226# timers should be executed with lower priority + // than XEvents like in generic plugin + g_source_set_priority( m_pTimeout, G_PRIORITY_LOW ); + g_source_set_can_recurse( m_pTimeout, TRUE ); + g_source_set_callback( m_pTimeout, + sal_gtk_timeout_function, + this, nullptr ); + g_source_attach( m_pTimeout, g_main_context_default() ); +#ifdef DBG_UTIL + g_source_set_name( m_pTimeout, "VCL timeout source" ); +#endif } void GtkSalTimer::Stop() { if( m_pTimeout ) { - g_source_destroy( &m_pTimeout->aParent ); - g_source_unref( &m_pTimeout->aParent ); + g_source_destroy( m_pTimeout ); + g_source_unref( m_pTimeout ); m_pTimeout = nullptr; } } diff --git a/vcl/unx/gtk/gtkinst.cxx b/vcl/unx/gtk/gtkinst.cxx index 034b634a0f79..caaa2af2499f 100644 --- a/vcl/unx/gtk/gtkinst.cxx +++ b/vcl/unx/gtk/gtkinst.cxx @@ -156,6 +156,7 @@ GtkInstance::GtkInstance( SalYieldMutex* pMutex ) #else : X11SalInstance( pMutex ) #endif + , m_pTimer(nullptr) , bNeedsInit(true) , m_pLastCairoFontOptions(nullptr) { @@ -194,8 +195,7 @@ void GtkInstance::EnsureInit() GtkInstance::~GtkInstance() { - while( !m_aTimers.empty() ) - delete *m_aTimers.begin(); + assert( nullptr == m_pTimer ); DeInitAtkBridge(); ResetLastSeenCairoFontOptions(); } @@ -397,18 +397,16 @@ void GtkInstance::DestroyMenuItem( SalMenuItem* ) {} SalTimer* GtkInstance::CreateSalTimer() { EnsureInit(); - GtkSalTimer *pTimer = new GtkSalTimer(); - m_aTimers.push_back( pTimer ); - return pTimer; + assert( nullptr == m_pTimer ); + if ( nullptr == m_pTimer ) + m_pTimer = new GtkSalTimer(); + return m_pTimer; } -void GtkInstance::RemoveTimer (SalTimer *pTimer) +void GtkInstance::RemoveTimer() { EnsureInit(); - std::vector<GtkSalTimer *>::iterator it; - it = std::find( m_aTimers.begin(), m_aTimers.end(), pTimer ); - if( it != m_aTimers.end() ) - m_aTimers.erase( it ); + m_pTimer = nullptr; } bool GtkInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong const nReleased) @@ -422,12 +420,7 @@ bool GtkInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong co bool GtkInstance::IsTimerExpired() { EnsureInit(); - for( std::vector<GtkSalTimer *>::iterator it = m_aTimers.begin(); - it != m_aTimers.end(); ++it ) - if( (*it)->Expired() ) - return true; - - return false; + return (m_pTimer && m_pTimer->Expired()); } bool GtkInstance::AnyInput( VclInputFlags nType ) diff --git a/vcl/unx/gtk3/gtk3gtkdata.cxx b/vcl/unx/gtk3/gtk3gtkdata.cxx index 3e074489bfd5..57cc1084460f 100644 --- a/vcl/unx/gtk3/gtk3gtkdata.cxx +++ b/vcl/unx/gtk3/gtk3gtkdata.cxx @@ -614,161 +614,71 @@ bool GtkData::ErrorTrapPop( bool bIgnoreError ) return gdk_error_trap_pop () != 0; } -extern "C" { - - struct SalGtkTimeoutSource { - GSource aParent; - GTimeVal aFireTime; - GtkSalTimer *pInstance; - }; - - static void sal_gtk_timeout_defer( SalGtkTimeoutSource *pTSource ) - { - g_get_current_time( &pTSource->aFireTime ); - g_time_val_add( &pTSource->aFireTime, pTSource->pInstance->m_nTimeoutMS * 1000 ); - } - - static gboolean sal_gtk_timeout_expired( SalGtkTimeoutSource *pTSource, - gint *nTimeoutMS, GTimeVal *pTimeNow ) - { - glong nDeltaSec = pTSource->aFireTime.tv_sec - pTimeNow->tv_sec; - glong nDeltaUSec = pTSource->aFireTime.tv_usec - pTimeNow->tv_usec; - if( nDeltaSec < 0 || ( nDeltaSec == 0 && nDeltaUSec < 0) ) - { - *nTimeoutMS = 0; - return TRUE; - } - if( nDeltaUSec < 0 ) - { - nDeltaUSec += 1000000; - nDeltaSec -= 1; - } - // if the clock changes backwards we need to cope ... - if( (unsigned long) nDeltaSec > 1 + ( pTSource->pInstance->m_nTimeoutMS / 1000 ) ) - { - sal_gtk_timeout_defer( pTSource ); - return TRUE; - } - - *nTimeoutMS = MIN( G_MAXINT, ( nDeltaSec * 1000 + (nDeltaUSec + 999) / 1000 ) ); - - return *nTimeoutMS == 0; - } - - static gboolean sal_gtk_timeout_prepare( GSource *pSource, gint *nTimeoutMS ) - { - SalGtkTimeoutSource *pTSource = reinterpret_cast<SalGtkTimeoutSource *>(pSource); - - GTimeVal aTimeNow; - g_get_current_time( &aTimeNow ); - - return sal_gtk_timeout_expired( pTSource, nTimeoutMS, &aTimeNow ); - } - - static gboolean sal_gtk_timeout_check( GSource *pSource ) - { - SalGtkTimeoutSource *pTSource = reinterpret_cast<SalGtkTimeoutSource *>(pSource); - - GTimeVal aTimeNow; - g_get_current_time( &aTimeNow ); - - return ( pTSource->aFireTime.tv_sec < aTimeNow.tv_sec || - ( pTSource->aFireTime.tv_sec == aTimeNow.tv_sec && - pTSource->aFireTime.tv_usec < aTimeNow.tv_usec ) ); - } +#if !GLIB_CHECK_VERSION(2,32,0) +#define G_SOURCE_REMOVE FALSE +#endif - static gboolean sal_gtk_timeout_dispatch( GSource *pSource, GSourceFunc, gpointer ) +extern "C" { + static gboolean sal_gtk_timeout_function( gpointer ) { - SalGtkTimeoutSource *pTSource = reinterpret_cast<SalGtkTimeoutSource *>(pSource); - - if( !pTSource->pInstance ) - return FALSE; - GtkData *pSalData = static_cast< GtkData* >( GetSalData()); - osl::Guard< comphelper::SolarMutex > aGuard( pSalData->m_pInstance->GetYieldMutex() ); - sal_gtk_timeout_defer( pTSource ); - ImplSVData* pSVData = ImplGetSVData(); if( pSVData->maSchedCtx.mpSalTimer ) pSVData->maSchedCtx.mpSalTimer->CallCallback(); - - return TRUE; + return G_SOURCE_REMOVE; } - - static GSourceFuncs sal_gtk_timeout_funcs = - { - sal_gtk_timeout_prepare, - sal_gtk_timeout_check, - sal_gtk_timeout_dispatch, - nullptr, nullptr, nullptr - }; -} - -static SalGtkTimeoutSource * -create_sal_gtk_timeout( GtkSalTimer *pTimer ) -{ - GSource *pSource = g_source_new( &sal_gtk_timeout_funcs, sizeof( SalGtkTimeoutSource ) ); - SalGtkTimeoutSource *pTSource = reinterpret_cast<SalGtkTimeoutSource *>(pSource); - pTSource->pInstance = pTimer; - - // #i36226# timers should be executed with lower priority - // than XEvents like in generic plugin - g_source_set_priority( pSource, G_PRIORITY_LOW ); - g_source_set_can_recurse( pSource, TRUE ); - g_source_set_callback( pSource, - /* unused dummy */ g_idle_remove_by_data, - nullptr, nullptr ); - g_source_attach( pSource, g_main_context_default() ); -#ifdef DBG_UTIL - g_source_set_name( pSource, "VCL timeout source" ); -#endif - - sal_gtk_timeout_defer( pTSource ); - - return pTSource; } GtkSalTimer::GtkSalTimer() : m_pTimeout(nullptr) - , m_nTimeoutMS(0) { } GtkSalTimer::~GtkSalTimer() { GtkInstance *pInstance = static_cast<GtkInstance *>(GetSalData()->m_pInstance); - pInstance->RemoveTimer( this ); + pInstance->RemoveTimer(); Stop(); } bool GtkSalTimer::Expired() { - if( !m_pTimeout ) + if( !m_pTimeout || g_source_is_destroyed( m_pTimeout ) ) return false; - - gint nDummy = 0; - GTimeVal aTimeNow; - g_get_current_time( &aTimeNow ); - return !!sal_gtk_timeout_expired( m_pTimeout, &nDummy, &aTimeNow); + return (g_get_monotonic_time() > g_source_get_ready_time( m_pTimeout )); } void GtkSalTimer::Start( sal_uLong nMS ) { // glib is not 64bit safe in this regard. - assert( nMS <= G_MAXINT ); - m_nTimeoutMS = nMS; // for restarting - Stop(); // FIXME: ideally re-use an existing m_pTimeout - m_pTimeout = create_sal_gtk_timeout( this ); + if ( nMS > G_MAXINT ) + nMS = G_MAXINT; + + Stop(); + assert( nullptr == m_pTimeout ); + + m_pTimeout = g_timeout_source_new ( nMS ); + // #i36226# timers should be executed with lower priority + // than XEvents like in generic plugin + g_source_set_priority( m_pTimeout, G_PRIORITY_LOW ); + g_source_set_can_recurse( m_pTimeout, TRUE ); + g_source_set_callback( m_pTimeout, + sal_gtk_timeout_function, + this, nullptr ); + g_source_attach( m_pTimeout, g_main_context_default() ); +#ifdef DBG_UTIL + g_source_set_name( m_pTimeout, "VCL timeout source" ); +#endif } void GtkSalTimer::Stop() { if( m_pTimeout ) { - g_source_destroy( &m_pTimeout->aParent ); - g_source_unref( &m_pTimeout->aParent ); + g_source_destroy( m_pTimeout ); + g_source_unref( m_pTimeout ); m_pTimeout = nullptr; } } |