Kaydet (Commit) 12dcf5e6 authored tarafından Michael Meeks's avatar Michael Meeks

slideshow: cleanup main-loop usage, post-yield listeners, etc.

    This removes several attempts at reducing jitter in slideshow
animations. Now we have high-resolution (ie. not clamped to 10ms)
timers on Windows and a cleaner and simpler main-loop, we should
be able to use generic timer code-paths for all of this.

    This also allows us to further cleanup and simplify the main-loop
removing the now redundent post-yield handler concept. If there is a
short enough timeout, we will take just 1ms of delay before executing
a short timer anyway.

    Also removed some lingering comments from an old attempt to boost
priorities which broken audio playback.

    Tested: tdf#32861 - still works, audio still plays, no new jitter
            in animations that I tested.

Change-Id: Iadc5e2a48828a18a599a86a8df14cb2b75dd425e
Reviewed-on: https://gerrit.libreoffice.org/19947Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarMichael Meeks <michael.meeks@collabora.com>
üst ea6857f8
...@@ -460,8 +460,6 @@ public: ...@@ -460,8 +460,6 @@ public:
@see Quit, Reschedule, Yield, EndYield, GetSolarMutex, @see Quit, Reschedule, Yield, EndYield, GetSolarMutex,
GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex, GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex,
EnableNoYieldMode, DisableNoYieldMode, AddPostYieldListener,
RemovePostYieldListener
*/ */
static void Execute(); static void Execute();
...@@ -469,8 +467,6 @@ public: ...@@ -469,8 +467,6 @@ public:
@see Execute, Reschedule, Yield, EndYield, GetSolarMutex, @see Execute, Reschedule, Yield, EndYield, GetSolarMutex,
GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex, GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex,
EnableNoYieldMode, DisableNoYieldMode, AddPostYieldListener,
RemovePostYieldListener
*/ */
static void Quit(); static void Quit();
...@@ -482,8 +478,6 @@ public: ...@@ -482,8 +478,6 @@ public:
@see Execute, Quit, Yield, EndYield, GetSolarMutex, @see Execute, Quit, Yield, EndYield, GetSolarMutex,
GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex, GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex,
EnableNoYieldMode, DisableNoYieldMode, AddPostYieldListener,
RemovePostYieldListener
*/ */
static void Reschedule( bool bAllEvents = false ); static void Reschedule( bool bAllEvents = false );
...@@ -491,8 +485,6 @@ public: ...@@ -491,8 +485,6 @@ public:
@see Execute, Quit, Reschedule, EndYield, GetSolarMutex, @see Execute, Quit, Reschedule, EndYield, GetSolarMutex,
GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex, GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex,
EnableNoYieldMode, DisableNoYieldMode, AddPostYieldListener,
RemovePostYieldListener
*/ */
static void Yield(); static void Yield();
...@@ -500,8 +492,6 @@ public: ...@@ -500,8 +492,6 @@ public:
@see Execute, Quit, Reschedule, Yield, GetSolarMutex, @see Execute, Quit, Reschedule, Yield, GetSolarMutex,
GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex, GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex,
EnableNoYieldMode, DisableNoYieldMode, AddPostYieldListener,
RemovePostYieldListener
*/ */
static void EndYield(); static void EndYield();
...@@ -520,8 +510,6 @@ public: ...@@ -520,8 +510,6 @@ public:
@see Execute, Quit, Reschedule, Yield, EndYield, @see Execute, Quit, Reschedule, Yield, EndYield,
GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex, GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex,
EnableNoYieldMode, DisableNoYieldMode, AddPostYieldListener,
RemovePostYieldListener
*/ */
static comphelper::SolarMutex& GetSolarMutex(); static comphelper::SolarMutex& GetSolarMutex();
...@@ -531,8 +519,6 @@ public: ...@@ -531,8 +519,6 @@ public:
@see Execute, Quit, Reschedule, Yield, EndYield, GetSolarMutex, @see Execute, Quit, Reschedule, Yield, EndYield, GetSolarMutex,
ReleaseSolarMutex, AcquireSolarMutex, ReleaseSolarMutex, AcquireSolarMutex,
EnableNoYieldMode, DisableNoYieldMode, AddPostYieldListener,
RemovePostYieldListener
*/ */
static oslThreadIdentifier GetMainThreadIdentifier(); static oslThreadIdentifier GetMainThreadIdentifier();
...@@ -545,8 +531,6 @@ public: ...@@ -545,8 +531,6 @@ public:
@see Execute, Quit, Reschedule, Yield, EndYield, GetSolarMutex, @see Execute, Quit, Reschedule, Yield, EndYield, GetSolarMutex,
GetMainThreadIdentifier, AcquireSolarMutex, GetMainThreadIdentifier, AcquireSolarMutex,
EnableNoYieldMode, DisableNoYieldMode, AddPostYieldListener,
RemovePostYieldListener
*/ */
static sal_uLong ReleaseSolarMutex(); static sal_uLong ReleaseSolarMutex();
...@@ -557,59 +541,9 @@ public: ...@@ -557,59 +541,9 @@ public:
@see Execute, Quit, Reschedule, Yield, EndYield, GetSolarMutex, @see Execute, Quit, Reschedule, Yield, EndYield, GetSolarMutex,
GetMainThreadIdentifier, ReleaseSolarMutex, GetMainThreadIdentifier, ReleaseSolarMutex,
EnableNoYieldMode, DisableNoYieldMode, AddPostYieldListener,
RemovePostYieldListener
*/ */
static void AcquireSolarMutex( sal_uLong nCount ); static void AcquireSolarMutex( sal_uLong nCount );
/** @brief Enables "no yield" mode
"No yield" mode prevents Yield() from waiting for events.
@remarks This was originally implemented in OOo bug 98792 to improve
Impress slideshows.
@see DisableNoYieldMode, Execute, Quit, Reschedule, Yield, EndYield, GetSolarMutex,
GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex,
DisableNoYield, AddPostYieldListener, RemovePostYieldListener
*/
static void EnableNoYieldMode();
/** @brief Disables "no yield" mode
"No yield" mode prevents Yield() from waiting for events.
@remarks This was originally implemented in OOo bug 98792 to improve
Impress slideshows.
@see EnableNoYieldMode, Execute, Quit, Reschedule, Yield, EndYield, GetSolarMutex,
GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex,
EnableNoYield, AddPostYieldListener, RemovePostYieldListener
*/
static void DisableNoYieldMode();
/** Add a listener for yield events
@param i_rListener Listener to add
@see Execute, Quit, Reschedule, Yield, EndYield, GetSolarMutex,
GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex,
EnableNoYieldMode, DisableNoYieldMode, RemovePostYieldListener
*/
static void AddPostYieldListener( const Link<LinkParamNone*,void>& i_rListener );
/** Remove listener for yield events
@param i_rListener Listener to remove
@see Execute, Quit, Reschedule, Yield, EndYield, GetSolarMutex,
GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex,
AddPostYieldListener, EnableNoYieldMode, DisableNoYieldMode
*/
static void RemovePostYieldListener( const Link<LinkParamNone*,void>& i_rListener );
/** Queries whether the application is in "main", i.e. not yet in /** Queries whether the application is in "main", i.e. not yet in
the event loop the event loop
......
...@@ -746,9 +746,6 @@ void SAL_CALL SlideshowImpl::disposing() ...@@ -746,9 +746,6 @@ void SAL_CALL SlideshowImpl::disposing()
setActiveXToolbarsVisible( true ); setActiveXToolbarsVisible( true );
Application::DisableNoYieldMode();
Application::RemovePostYieldListener(LINK(this, SlideshowImpl, PostYieldListener));
mbDisposed = true; mbDisposed = true;
} }
...@@ -1788,22 +1785,6 @@ IMPL_LINK_NOARG_TYPED(SlideshowImpl, updateHdl, Timer *, void) ...@@ -1788,22 +1785,6 @@ IMPL_LINK_NOARG_TYPED(SlideshowImpl, updateHdl, Timer *, void)
updateSlideShow(); updateSlideShow();
} }
IMPL_LINK_NOARG_TYPED(SlideshowImpl, PostYieldListener, LinkParamNone*, void)
{
// prevent me from deletion when recursing (App::Reschedule does)
const rtl::Reference<SlideshowImpl> this_(this);
Application::DisableNoYieldMode();
Application::RemovePostYieldListener(LINK(this, SlideshowImpl, PostYieldListener));
Application::Reschedule(true); // fix for fdo#32861 - process
// *all* outstanding events after
// yield is done.
if (mbDisposed)
return;
Application::Reschedule(true);
updateSlideShow();
}
sal_Int32 SlideshowImpl::updateSlideShow() sal_Int32 SlideshowImpl::updateSlideShow()
{ {
// prevent me from deletion when recursing (App::EnableYieldMode does) // prevent me from deletion when recursing (App::EnableYieldMode does)
...@@ -1815,26 +1796,13 @@ sal_Int32 SlideshowImpl::updateSlideShow() ...@@ -1815,26 +1796,13 @@ sal_Int32 SlideshowImpl::updateSlideShow()
try try
{ {
// TODO(Q3): Evaluate under various systems and setups,
// whether this is really necessary. Under WinXP and Matrox
// G550, the frame rates were much more steadier with this
// tweak, although.
// currently no solution, because this kills sound (at least on Windows)
double fUpdate = 0.0; double fUpdate = 0.0;
if( !xShow->update(fUpdate) ) if( !xShow->update(fUpdate) )
fUpdate = -1.0; fUpdate = -1.0;
if (mxShow.is() && (fUpdate >= 0.0)) if (mxShow.is() && (fUpdate >= 0.0))
{ {
if (::basegfx::fTools::equalZero(fUpdate)) if (!::basegfx::fTools::equalZero(fUpdate))
{
// Use post yield listener for short update intervalls.
Application::EnableNoYieldMode();
Application::AddPostYieldListener(LINK(this, SlideshowImpl, PostYieldListener));
}
else
{ {
// Avoid busy loop when the previous call to update() // Avoid busy loop when the previous call to update()
// returns a small positive number but not 0 (which is // returns a small positive number but not 0 (which is
...@@ -1851,14 +1819,11 @@ sal_Int32 SlideshowImpl::updateSlideShow() ...@@ -1851,14 +1819,11 @@ sal_Int32 SlideshowImpl::updateSlideShow()
// too high (only then conversion to milliseconds and long // too high (only then conversion to milliseconds and long
// integer may lead to zero value.) // integer may lead to zero value.)
OSL_ASSERT(static_cast<sal_uLong>(fUpdate * 1000.0) > 0); OSL_ASSERT(static_cast<sal_uLong>(fUpdate * 1000.0) > 0);
Application::DisableNoYieldMode();
Application::RemovePostYieldListener(LINK(this, SlideshowImpl, PostYieldListener));
// Use a timer for the asynchronous callback.
maUpdateTimer.SetTimeout(static_cast<sal_uLong>(fUpdate * 1000.0));
maUpdateTimer.Start();
} }
// Use our high resolution timers for the asynchronous callback.
maUpdateTimer.SetTimeout(static_cast<sal_uLong>(fUpdate * 1000.0));
maUpdateTimer.Start();
} }
} }
catch( Exception& ) catch( Exception& )
......
...@@ -275,7 +275,6 @@ private: ...@@ -275,7 +275,6 @@ private:
void setActiveXToolbarsVisible( bool bVisible ); void setActiveXToolbarsVisible( bool bVisible );
DECL_LINK_TYPED( updateHdl, Timer *, void ); DECL_LINK_TYPED( updateHdl, Timer *, void );
DECL_LINK_TYPED( PostYieldListener, LinkParamNone*, void );
DECL_LINK_TYPED( ReadyForNextInputHdl, Timer *, void ); DECL_LINK_TYPED( ReadyForNextInputHdl, Timer *, void );
DECL_LINK_TYPED( endPresentationHdl, void*, void ); DECL_LINK_TYPED( endPresentationHdl, void*, void );
DECL_LINK_TYPED( ContextMenuSelectHdl, Menu *, bool ); DECL_LINK_TYPED( ContextMenuSelectHdl, Menu *, bool );
...@@ -311,7 +310,7 @@ private: ...@@ -311,7 +310,7 @@ private:
static void setAutoSaveState( bool bOn ); static void setAutoSaveState( bool bOn );
void gotoPreviousSlide (const bool bSkipAllMainSequenceEffects); void gotoPreviousSlide (const bool bSkipAllMainSequenceEffects);
/** Called by PostYieldListener and updateHdl handlers this method is /** Called by our maUpdateTimer's updateHdl handler this method is
responsible to call the slideshow update() method and, depending on responsible to call the slideshow update() method and, depending on
its return value, wait for a certain amount of time before another its return value, wait for a certain amount of time before another
call to update() is scheduled. call to update() is scheduled.
......
...@@ -105,11 +105,6 @@ public: ...@@ -105,11 +105,6 @@ public:
typedef std::vector<Link<VclWindowEvent&,bool> > SVAppKeyListeners; typedef std::vector<Link<VclWindowEvent&,bool> > SVAppKeyListeners;
struct SVAppPostYieldListeners : public vcl::DeletionNotifier
{
std::vector<Link<LinkParamNone*,void>> m_aListeners;
};
struct ImplSVAppData struct ImplSVAppData
{ {
enum ImeStatusWindowMode enum ImeStatusWindowMode
...@@ -134,7 +129,6 @@ struct ImplSVAppData ...@@ -134,7 +129,6 @@ struct ImplSVAppData
VclPtr<ImplWheelWindow> mpWheelWindow; // WheelWindow VclPtr<ImplWheelWindow> mpWheelWindow; // WheelWindow
ImplHotKey* mpFirstHotKey; // HotKey-Verwaltung ImplHotKey* mpFirstHotKey; // HotKey-Verwaltung
ImplEventHook* mpFirstEventHook; // Event-Hooks ImplEventHook* mpFirstEventHook; // Event-Hooks
SVAppPostYieldListeners* mpPostYieldListeners; // post yield listeners
sal_uInt64 mnLastInputTime; // GetLastInputTime() sal_uInt64 mnLastInputTime; // GetLastInputTime()
sal_uInt16 mnDispatchLevel; // DispatchLevel sal_uInt16 mnDispatchLevel; // DispatchLevel
sal_uInt16 mnModalMode; // ModalMode Count sal_uInt16 mnModalMode; // ModalMode Count
...@@ -146,8 +140,6 @@ struct ImplSVAppData ...@@ -146,8 +140,6 @@ struct ImplSVAppData
bool mbInAppExecute; // is Application::Execute() on stack bool mbInAppExecute; // is Application::Execute() on stack
bool mbAppQuit; // is Application::Quit() called bool mbAppQuit; // is Application::Quit() called
bool mbSettingsInit; // true: Settings are initialized bool mbSettingsInit; // true: Settings are initialized
bool mbNoYield; // Application::Yield will not wait for events if the queue is empty
// essentially that makes it the same as Application::Reschedule
Application::DialogCancelMode meDialogCancel; // true: All Dialog::Execute() calls will be terminated immediately with return false Application::DialogCancelMode meDialogCancel; // true: All Dialog::Execute() calls will be terminated immediately with return false
/** Controls whether showing any IME status window is toggled on or off. /** Controls whether showing any IME status window is toggled on or off.
......
...@@ -492,7 +492,7 @@ inline void ImplYield(bool i_bWait, bool i_bAllEvents, sal_uLong const nReleased ...@@ -492,7 +492,7 @@ inline void ImplYield(bool i_bWait, bool i_bAllEvents, sal_uLong const nReleased
// do not wait for events either if the app decided that it is too busy for timers // do not wait for events either if the app decided that it is too busy for timers
// (feature added for the slideshow) // (feature added for the slideshow)
pSVData->mpDefInst->DoYield( pSVData->mpDefInst->DoYield(
i_bWait && !pSVData->maAppData.mbAppQuit && !pSVData->maAppData.mbNoYield, i_bWait && !pSVData->maAppData.mbAppQuit,
i_bAllEvents, nReleased); i_bAllEvents, nReleased);
pSVData->maAppData.mnDispatchLevel--; pSVData->maAppData.mnDispatchLevel--;
...@@ -501,31 +501,6 @@ inline void ImplYield(bool i_bWait, bool i_bAllEvents, sal_uLong const nReleased ...@@ -501,31 +501,6 @@ inline void ImplYield(bool i_bWait, bool i_bAllEvents, sal_uLong const nReleased
// flush lazy deleted objects // flush lazy deleted objects
if( pSVData->maAppData.mnDispatchLevel == 0 ) if( pSVData->maAppData.mnDispatchLevel == 0 )
vcl::LazyDelete::flush(); vcl::LazyDelete::flush();
// the system timer events will not necessarily come in non waiting mode
// e.g. on OS X; need to trigger timer checks manually
if( pSVData->maAppData.mbNoYield )
{
//Process all timers
Scheduler::ProcessTaskScheduling(true);
}
// call post yield listeners
if( pSVData->maAppData.mpPostYieldListeners )
{
vcl::DeletionListener aDel( pSVData->maAppData.mpPostYieldListeners );
auto& rYieldListeners = pSVData->maAppData.mpPostYieldListeners->m_aListeners;
// Copy the list, because this can be destroyed when calling a Link...
std::vector<Link<LinkParamNone*,void>> aCopy( rYieldListeners );
for( Link<LinkParamNone*,void>& rLink : aCopy )
{
if (aDel.isDeleted()) break;
// check this hasn't been removed in some re-enterancy scenario fdo#47368
if( std::find(rYieldListeners.begin(), rYieldListeners.end(), rLink) != rYieldListeners.end() )
rLink.Call( nullptr );
}
}
} }
void Application::Reschedule( bool i_bAllEvents ) void Application::Reschedule( bool i_bAllEvents )
...@@ -1096,39 +1071,6 @@ void Application::RemoveIdleHdl( const Link<Application*,void>& rLink ) ...@@ -1096,39 +1071,6 @@ void Application::RemoveIdleHdl( const Link<Application*,void>& rLink )
pSVData->maAppData.mpIdleMgr->RemoveIdleHdl( rLink ); pSVData->maAppData.mpIdleMgr->RemoveIdleHdl( rLink );
} }
void Application::EnableNoYieldMode()
{
ImplSVData* pSVData = ImplGetSVData();
pSVData->maAppData.mbNoYield = true;
}
void Application::DisableNoYieldMode()
{
ImplSVData* pSVData = ImplGetSVData();
pSVData->maAppData.mbNoYield = false;
}
void Application::AddPostYieldListener( const Link<LinkParamNone*,void>& i_rListener )
{
ImplSVData* pSVData = ImplGetSVData();
if( ! pSVData->maAppData.mpPostYieldListeners )
pSVData->maAppData.mpPostYieldListeners = new SVAppPostYieldListeners();
// ensure uniqueness
auto& rYieldListeners = pSVData->maAppData.mpPostYieldListeners->m_aListeners;
if (std::find(rYieldListeners.begin(), rYieldListeners.end(), i_rListener) == rYieldListeners.end())
rYieldListeners.push_back( i_rListener );
}
void Application::RemovePostYieldListener( const Link<LinkParamNone*,void>& i_rListener )
{
ImplSVData* pSVData = ImplGetSVData();
if( pSVData->maAppData.mpPostYieldListeners )
{
auto& rYieldListeners = pSVData->maAppData.mpPostYieldListeners->m_aListeners;
rYieldListeners.erase( std::remove(rYieldListeners.begin(), rYieldListeners.end(), i_rListener ), rYieldListeners.end() );
}
}
WorkWindow* Application::GetAppWindow() WorkWindow* Application::GetAppWindow()
{ {
return ImplGetSVData()->maWinData.mpAppWin; return ImplGetSVData()->maWinData.mpAppWin;
......
...@@ -508,11 +508,6 @@ void DeInitVCL() ...@@ -508,11 +508,6 @@ void DeInitVCL()
delete pSVData->maAppData.mpKeyListeners; delete pSVData->maAppData.mpKeyListeners;
pSVData->maAppData.mpKeyListeners = nullptr; pSVData->maAppData.mpKeyListeners = nullptr;
} }
if ( pSVData->maAppData.mpPostYieldListeners )
{
delete pSVData->maAppData.mpPostYieldListeners;
pSVData->maAppData.mpPostYieldListeners = nullptr;
}
if ( pSVData->maAppData.mpFirstHotKey ) if ( pSVData->maAppData.mpFirstHotKey )
ImplFreeHotKeyData(); ImplFreeHotKeyData();
......
...@@ -849,7 +849,7 @@ atk_object_wrapper_new( const ::com::sun::star::uno::Reference< ::com::sun::star ...@@ -849,7 +849,7 @@ atk_object_wrapper_new( const ::com::sun::star::uno::Reference< ::com::sun::star
uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster(xContext, uno::UNO_QUERY); uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster(xContext, uno::UNO_QUERY);
if( xBroadcaster.is() ) if( xBroadcaster.is() )
xBroadcaster->addAccessibleEventListener( static_cast< accessibility::XAccessibleEventListener * > ( new AtkListener(pWrap) ) ); xBroadcaster->addAccessibleEventListener( static_cast< accessibility::XAccessibleEventListener * > ( new AtkListener(pWrap) ) );
else else
OSL_ASSERT( false ); OSL_ASSERT( false );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment