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>
This commit is contained in:
parent
53da556c60
commit
0d24dd25e6
8 changed files with 64 additions and 32 deletions
|
@ -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; }
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -51,6 +51,7 @@ bool SalUserEventList::DispatchUserEvents( bool bHandleAllCurrentEvents )
|
|||
|
||||
{
|
||||
osl::MutexGuard aGuard( m_aUserEventsMutex );
|
||||
assert( m_aProcessingUserEvents.empty() );
|
||||
if( ! m_aUserEvents.empty() )
|
||||
{
|
||||
if( bHandleAllCurrentEvents )
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 >& );
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue