diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2017-10-05 18:19:32 +0200 |
---|---|---|
committer | Jan-Marek Glogowski <glogow@fbihome.de> | 2017-10-06 15:04:56 +0200 |
commit | 0d24dd25e6f506b5f9128d70d7eb21f0bb4dde89 (patch) | |
tree | 37611d945315e5ccbf325c9b0baa86d7a7435b6c | |
parent | 53da556c600fa82ba84bc7fdce6a594b43f2b097 (diff) |
KDE update system loop integration
This updates the system loop integration to be on par with the
other backends. This includes:
1. Process LO user events before other LO events
2. Correctly handle elapsed QTimer events
3. Don't wait-yield in the main thread from a non-main thread
Change-Id: Ia17be032ae39dc4c7bfa44cadd22d85a1b9c4fbd
Reviewed-on: https://gerrit.libreoffice.org/43198
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
-rw-r--r-- | vcl/inc/unx/gendisp.hxx | 2 | ||||
-rw-r--r-- | vcl/inc/unx/saldisp.hxx | 2 | ||||
-rw-r--r-- | vcl/source/app/salusereventlist.cxx | 1 | ||||
-rw-r--r-- | vcl/unx/generic/app/gendisp.cxx | 4 | ||||
-rw-r--r-- | vcl/unx/generic/app/salinst.cxx | 3 | ||||
-rw-r--r-- | vcl/unx/kde4/KDESalDisplay.cxx | 3 | ||||
-rw-r--r-- | vcl/unx/kde4/KDEXLib.cxx | 62 | ||||
-rw-r--r-- | vcl/unx/kde4/KDEXLib.hxx | 19 |
8 files changed, 64 insertions, 32 deletions
diff --git a/vcl/inc/unx/gendisp.hxx b/vcl/inc/unx/gendisp.hxx index 5c8f5113c300..2d5bc12fcadf 100644 --- a/vcl/inc/unx/gendisp.hxx +++ b/vcl/inc/unx/gendisp.hxx @@ -47,7 +47,7 @@ public: void SendInternalEvent( SalFrame* pFrame, void* pData, SalEvent nEvent = SalEvent::UserEvent ); void CancelInternalEvent( SalFrame* pFrame, void* pData, SalEvent nEvent ); - bool DispatchInternalEvent(); + bool DispatchInternalEvent( bool bHandleAllCurrentEvent = false ); bool MouseCaptured( const SalFrame *pFrameData ) const { return m_pCapture == pFrameData; } diff --git a/vcl/inc/unx/saldisp.hxx b/vcl/inc/unx/saldisp.hxx index 8f96e03630b0..54799149e25c 100644 --- a/vcl/inc/unx/saldisp.hxx +++ b/vcl/inc/unx/saldisp.hxx @@ -179,7 +179,7 @@ public: virtual void StartTimer( sal_uLong nMS ); virtual void StopTimer(); - bool CheckTimeout( bool bExecuteTimers = true ); + virtual bool CheckTimeout( bool bExecuteTimers = true ); SalI18N_InputMethod* GetInputMethod() const { return m_pInputMethod; } Display* GetDisplay() const { return m_pDisplay; } diff --git a/vcl/source/app/salusereventlist.cxx b/vcl/source/app/salusereventlist.cxx index 6384d8805be4..8f9d76ed313f 100644 --- a/vcl/source/app/salusereventlist.cxx +++ b/vcl/source/app/salusereventlist.cxx @@ -51,6 +51,7 @@ bool SalUserEventList::DispatchUserEvents( bool bHandleAllCurrentEvents ) { osl::MutexGuard aGuard( m_aUserEventsMutex ); + assert( m_aProcessingUserEvents.empty() ); if( ! m_aUserEvents.empty() ) { if( bHandleAllCurrentEvents ) diff --git a/vcl/unx/generic/app/gendisp.cxx b/vcl/unx/generic/app/gendisp.cxx index 1be8606602e0..c83283a7b0e0 100644 --- a/vcl/unx/generic/app/gendisp.cxx +++ b/vcl/unx/generic/app/gendisp.cxx @@ -47,9 +47,9 @@ void SalGenericDisplay::emitDisplayChanged() pAnyFrame->CallCallback( SalEvent::DisplayChanged, nullptr ); } -bool SalGenericDisplay::DispatchInternalEvent() +bool SalGenericDisplay::DispatchInternalEvent( bool bHandleAllCurrentEvent ) { - return DispatchUserEvents( false ); + return DispatchUserEvents( bHandleAllCurrentEvent ); } void SalGenericDisplay::SendInternalEvent( SalFrame* pFrame, void* pData, SalEvent nEvent ) diff --git a/vcl/unx/generic/app/salinst.cxx b/vcl/unx/generic/app/salinst.cxx index abd29a78c077..0d30e1d17a99 100644 --- a/vcl/unx/generic/app/salinst.cxx +++ b/vcl/unx/generic/app/salinst.cxx @@ -147,7 +147,8 @@ bool X11SalInstance::AnyInput(VclInputFlags nType) if( (nType & VclInputFlags::TIMER) && (mpXLib && mpXLib->CheckTimeout(false)) ) bRet = true; - else if (XPending(pDisplay) ) + + if( !bRet && XPending(pDisplay) ) { PredicateReturn aInput; XEvent aEvent; diff --git a/vcl/unx/kde4/KDESalDisplay.cxx b/vcl/unx/kde4/KDESalDisplay.cxx index 8a2422a3918d..14a753e1c0a1 100644 --- a/vcl/unx/kde4/KDESalDisplay.cxx +++ b/vcl/unx/kde4/KDESalDisplay.cxx @@ -47,9 +47,6 @@ SalKDEDisplay::~SalKDEDisplay() void SalKDEDisplay::Yield() { - if( DispatchInternalEvent() ) - return; - // Prevent blocking from Drag'n'Drop events, which may have already have processed the event if (XEventsQueued( pDisp_, QueuedAfterReading ) == 0) return; diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx index f047ed9fce65..43e055a2c0bb 100644 --- a/vcl/unx/kde4/KDEXLib.cxx +++ b/vcl/unx/kde4/KDEXLib.cxx @@ -53,6 +53,7 @@ KDEXLib::KDEXLib() : m_nFakeCmdLineArgs( 0 ), m_isGlibEventLoopType(false), m_allowKdeDialogs(false), m_timerEventId( -1 ), m_postUserEventId( -1 ) + , m_bTimedOut( false ) { m_timerEventId = QEvent::registerEventType(); m_postUserEventId = QEvent::registerEventType(); @@ -269,22 +270,24 @@ void KDEXLib::socketNotifierActivated( int fd ) bool KDEXLib::Yield( bool bWait, bool bHandleAllCurrentEvents ) { + bool bWasEvent = false; if( !m_isGlibEventLoopType ) { - bool wasEvent = false; if( qApp->thread() == QThread::currentThread()) { // even if we use the LO event loop, still process Qt's events, // otherwise they can remain unhandled for quite a long while - wasEvent = processYield( false, bHandleAllCurrentEvents ); + bWasEvent = processYield( false, bHandleAllCurrentEvents ); } - return SalXLib::Yield(bWait, bHandleAllCurrentEvents) || wasEvent; + return SalXLib::Yield(bWait, bHandleAllCurrentEvents) || bWasEvent; } // if we are the main thread (which is where the event processing is done), // good, just do it if( qApp->thread() == QThread::currentThread()) { - return processYield( bWait, bHandleAllCurrentEvents ); + bWasEvent = processYield( bWait, bHandleAllCurrentEvents ); + if ( bWasEvent ) + m_aWaitingYieldCond.set(); } else { @@ -292,23 +295,40 @@ bool KDEXLib::Yield( bool bWait, bool bHandleAllCurrentEvents ) // release the yield lock to prevent deadlock with the main thread // (it's ok to release it here, since even normal processYield() would // temporarily do it while checking for new events) - SolarMutexReleaser aReleaser; - return Q_EMIT processYieldSignal( bWait, bHandleAllCurrentEvents ); + { + SolarMutexReleaser aReleaser; + bWasEvent = Q_EMIT processYieldSignal( false, bHandleAllCurrentEvents ); + } + if ( !bWasEvent && bWait ) + { + m_aWaitingYieldCond.reset(); + SolarMutexReleaser aReleaser; + m_aWaitingYieldCond.wait(); + bWasEvent = true; + } } + return bWasEvent; } -/** - * Quoting the Qt docs: [QAbstractEventDispatcher::processEvents] processes - * pending events that match flags until there are no more events to process. - */ -bool KDEXLib::processYield( bool bWait, bool ) +bool KDEXLib::processYield( bool bWait, bool bHandleAllCurrentEvents ) { - QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance( qApp->thread()); bool wasEvent = false; - if ( bWait ) + if ( m_isGlibEventLoopType ) + { + wasEvent = SalKDEDisplay::self()->DispatchInternalEvent( bHandleAllCurrentEvents ); + if ( !bHandleAllCurrentEvents && wasEvent ) + return true; + } + + /** + * Quoting the Qt docs: [QAbstractEventDispatcher::processEvents] processes + * pending events that match flags until there are no more events to process. + */ + QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance( qApp->thread()); + if ( bWait && !wasEvent ) wasEvent = dispatcher->processEvents( QEventLoop::WaitForMoreEvents ); else - wasEvent = dispatcher->processEvents( QEventLoop::AllEvents ); + wasEvent = dispatcher->processEvents( QEventLoop::AllEvents ) || wasEvent; return wasEvent; } @@ -336,18 +356,28 @@ void KDEXLib::StopTimer() timeoutTimer.stop(); } +bool KDEXLib::CheckTimeout( bool bExecuteTimers ) +{ + if( !m_isGlibEventLoopType ) + return SalXLib::CheckTimeout( bExecuteTimers ); + assert( !bExecuteTimers ); + return m_bTimedOut; +} + void KDEXLib::timeoutActivated() { // don't potentially wait in timeout, as QTimer is non-recursive + m_bTimedOut = true; QApplication::postEvent(this, new QEvent(QEvent::Type( m_timerEventId ))); } void KDEXLib::customEvent(QEvent* e) { if( e->type() == m_timerEventId ) + { + m_bTimedOut = false; X11SalData::Timeout(); - else if( e->type() == m_postUserEventId ) - SalKDEDisplay::self()->DispatchInternalEvent(); + } } void KDEXLib::Wakeup() diff --git a/vcl/unx/kde4/KDEXLib.hxx b/vcl/unx/kde4/KDEXLib.hxx index 4c06104b4c59..452aae8b3286 100644 --- a/vcl/unx/kde4/KDEXLib.hxx +++ b/vcl/unx/kde4/KDEXLib.hxx @@ -30,13 +30,14 @@ #include <QtCore/QTimer> #include <unx/salinst.h> +#include <osl/conditn.hxx> class VCLKDEApplication; class KDEXLib : public QObject, public SalXLib { Q_OBJECT - private: + bool m_bStartupDone; std::unique_ptr<VCLKDEApplication> m_pApplication; std::unique_ptr<char*[]> m_pFreeCmdLineArgs; @@ -56,23 +57,24 @@ class KDEXLib : public QObject, public SalXLib bool m_allowKdeDialogs; int m_timerEventId; int m_postUserEventId; + osl::Condition m_aWaitingYieldCond; + bool m_bTimedOut; - private: - void setupEventLoop(); + void setupEventLoop(); - private Q_SLOTS: +private Q_SLOTS: void socketNotifierActivated( int fd ); void timeoutActivated(); void startTimeoutTimer(); - static bool processYield( bool bWait, bool bHandleAllCurrentEvents ); + bool processYield( bool bWait, bool bHandleAllCurrentEvents ); - Q_SIGNALS: +Q_SIGNALS: void startTimeoutTimerSignal(); bool processYieldSignal( bool bWait, bool bHandleAllCurrentEvents ); css::uno::Reference< css::ui::dialogs::XFilePicker2 > createFilePickerSignal( const css::uno::Reference< css::uno::XComponentContext >& ); - public: +public: KDEXLib(); virtual ~KDEXLib() override; @@ -82,6 +84,7 @@ class KDEXLib : public QObject, public SalXLib virtual void Remove( int fd ) override; virtual void StartTimer( sal_uLong nMS ) override; virtual void StopTimer() override; + virtual bool CheckTimeout( bool bExecuteTimers = true ) override; virtual void Wakeup() override; void TriggerUserEventProcessing(); @@ -90,7 +93,7 @@ class KDEXLib : public QObject, public SalXLib virtual void customEvent(QEvent* e) override; - public Q_SLOTS: +public Q_SLOTS: css::uno::Reference< css::ui::dialogs::XFilePicker2 > createFilePicker( const css::uno::Reference< css::uno::XComponentContext >& ); }; |