summaryrefslogtreecommitdiffstats
path: root/vcl/unx
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@suse.com>2011-10-25 16:17:40 +0100
committerMichael Meeks <michael.meeks@suse.com>2011-10-25 16:25:28 +0100
commit232c6f1309bb73cc6516c58da749f64ce3668932 (patch)
tree7ce0bba07256dbf394783186ad6d879dbc289dfc /vcl/unx
parentinitial cut at 'last working' feature to help windows builders (diff)
downloadcore-232c6f1309bb73cc6516c58da749f64ce3668932.tar.gz
core-232c6f1309bb73cc6516c58da749f64ce3668932.zip
gtk3: cleanup timeout source, to avoid annoying warnings with old glibs
Diffstat (limited to 'vcl/unx')
-rw-r--r--vcl/unx/gtk/app/gtkdata.cxx162
-rw-r--r--vcl/unx/gtk/app/gtkinst.cxx30
2 files changed, 131 insertions, 61 deletions
diff --git a/vcl/unx/gtk/app/gtkdata.cxx b/vcl/unx/gtk/app/gtkdata.cxx
index b50f85978692..4599ec4ee317 100644
--- a/vcl/unx/gtk/app/gtkdata.cxx
+++ b/vcl/unx/gtk/app/gtkdata.cxx
@@ -778,8 +778,125 @@ 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_source_get_current_time( (GSource *) pTSource, &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 = (SalGtkTimeoutSource *)pSource;
+
+ GTimeVal aTimeNow;
+ g_source_get_current_time( pSource, &aTimeNow );
+
+ return sal_gtk_timeout_expired( pTSource, nTimeoutMS, &aTimeNow );
+ }
+
+ static gboolean sal_gtk_timeout_check( GSource *pSource )
+ {
+ SalGtkTimeoutSource *pTSource = (SalGtkTimeoutSource *)pSource;
+
+ GTimeVal aTimeNow;
+ g_source_get_current_time( pSource, &aTimeNow );
+
+ if( pTSource->aFireTime.tv_sec > aTimeNow.tv_sec )
+ return FALSE;
+ if( pTSource->aFireTime.tv_sec < aTimeNow.tv_sec )
+ return TRUE;
+ if( pTSource->aFireTime.tv_usec < aTimeNow.tv_usec )
+ return FALSE;
+ return TRUE;
+ }
+
+ static gboolean sal_gtk_timeout_dispatch( GSource *pSource, GSourceFunc, gpointer )
+ {
+ SalGtkTimeoutSource *pTSource = (SalGtkTimeoutSource *)pSource;
+
+ if( !pTSource->pInstance )
+ return FALSE;
+
+ SalData *pSalData = GetSalData();
+
+ osl::SolarGuard aGuard( pSalData->m_pInstance->GetYieldMutex() );
+
+ sal_gtk_timeout_defer( pTSource );
+
+ ImplSVData* pSVData = ImplGetSVData();
+ if( pSVData->mpSalTimer )
+ pSVData->mpSalTimer->CallCallback();
+
+ return TRUE;
+ }
+
+ static GSourceFuncs sal_gtk_timeout_funcs =
+ {
+ sal_gtk_timeout_prepare,
+ sal_gtk_timeout_check,
+ sal_gtk_timeout_dispatch,
+ NULL, NULL, NULL
+ };
+}
+
+static SalGtkTimeoutSource *
+create_sal_gtk_timeout( GtkSalTimer *pTimer )
+{
+ GSource *pSource = g_source_new( &sal_gtk_timeout_funcs, sizeof( SalGtkTimeoutSource ) );
+ SalGtkTimeoutSource *pTSource = (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,
+ NULL, NULL );
+ g_source_attach( pSource, g_main_context_default() );
+
+ sal_gtk_timeout_defer( pTSource );
+
+ return pTSource;
+}
+
GtkSalTimer::GtkSalTimer()
- : m_pTimeout( 0 )
+ : m_pTimeout( NULL )
{
}
@@ -794,54 +911,27 @@ bool GtkSalTimer::Expired()
{
if( !m_pTimeout )
return false;
- GSourceFuncs *pKlass = m_pTimeout->source_funcs;
- gint timeout = 0;
- if( pKlass && pKlass->prepare )
- return !!pKlass->prepare( m_pTimeout, &timeout );
- else
- return false;
-}
-
-extern "C"
-{
- gboolean call_timeoutFn( gpointer pData )
- {
- GtkSalTimer *pTimer = (GtkSalTimer *)pData;
- SalData *pSalData = GetSalData();
-
- osl::SolarGuard aGuard( pSalData->m_pInstance->GetYieldMutex() );
-
- pTimer->Start( pTimer->m_nTimeoutMS );
-
- ImplSVData* pSVData = ImplGetSVData();
- if( pSVData->mpSalTimer )
- pSVData->mpSalTimer->CallCallback();
- return FALSE;
- }
+ gint nDummy = 0;
+ GTimeVal aTimeNow;
+ g_get_current_time( &aTimeNow );
+ return !!sal_gtk_timeout_expired( m_pTimeout, &nDummy, &aTimeNow);
}
void GtkSalTimer::Start( sal_uLong nMS )
{
m_nTimeoutMS = nMS; // for restarting
Stop();
-
- m_pTimeout = g_timeout_source_new (m_nTimeoutMS);
- // #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, call_timeoutFn,
- (gpointer) this, NULL);
- g_source_attach (m_pTimeout, g_main_context_default ());
+ m_pTimeout = create_sal_gtk_timeout( this );
}
void GtkSalTimer::Stop()
{
if( m_pTimeout )
{
- g_source_destroy( m_pTimeout );
- g_source_unref( m_pTimeout );
+ g_source_destroy( (GSource *)m_pTimeout );
+ g_source_unref( (GSource *)m_pTimeout );
+ m_pTimeout = NULL;
}
}
diff --git a/vcl/unx/gtk/app/gtkinst.cxx b/vcl/unx/gtk/app/gtkinst.cxx
index 9049419906cf..1f9f1b1f77a6 100644
--- a/vcl/unx/gtk/app/gtkinst.cxx
+++ b/vcl/unx/gtk/app/gtkinst.cxx
@@ -584,32 +584,12 @@ void GtkInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
bool GtkInstance::IsTimerExpired()
{
- gint nPriority;
- bool bRet = false;
- GMainContext *pCtx = g_main_context_default();
+ for( std::vector<GtkSalTimer *>::iterator it = m_aTimers.begin();
+ it != m_aTimers.end(); ++it )
+ if( (*it)->Expired() )
+ return true;
- if( !g_main_context_acquire( pCtx ) )
- return false; // some other thread is waiting still ...
-
- // FIXME: we need to re-work this to do our own timeouts to avoid
- // warnings from older glib's about poll_waiting etc.
-
- // sets GMainContext's time_is_fresh to FALSE
- if( g_main_context_prepare( pCtx, &nPriority ) )
- {
- for( std::vector<GtkSalTimer *>::iterator it = m_aTimers.begin();
- it != m_aTimers.end(); ++it )
- {
- if( (*it)->Expired() )
- {
- bRet = true;
- break;
- }
- }
- }
- g_main_context_release( pCtx );
-
- return bRet;
+ return false;
}
bool GtkInstance::AnyInput( sal_uInt16 nType )