diff options
author | Luboš Luňák <l.lunak@suse.cz> | 2010-10-13 14:39:16 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@suse.cz> | 2010-10-14 18:14:14 +0200 |
commit | 924673ea9afc389eaf04b9bccc6f9d8028e12f0d (patch) | |
tree | 60f08d0fc08cf864861ce68272111d01fad3a246 /vcl | |
parent | 6b5a13a80bef8026abb53d665af3240ad3148eeb (diff) |
make KDE4 vclplug use Qt event loop as the event loop
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/unx/kde4/KDESalDisplay.cxx | 17 | ||||
-rw-r--r-- | vcl/unx/kde4/KDESalDisplay.hxx | 5 | ||||
-rw-r--r-- | vcl/unx/kde4/KDEXLib.cxx | 131 | ||||
-rw-r--r-- | vcl/unx/kde4/KDEXLib.hxx | 41 | ||||
-rw-r--r-- | vcl/unx/kde4/makefile.mk | 4 |
5 files changed, 196 insertions, 2 deletions
diff --git a/vcl/unx/kde4/KDESalDisplay.cxx b/vcl/unx/kde4/KDESalDisplay.cxx index 69781c1d495b..9877a9ed4974 100644 --- a/vcl/unx/kde4/KDESalDisplay.cxx +++ b/vcl/unx/kde4/KDESalDisplay.cxx @@ -29,8 +29,10 @@ #include "KDESalDisplay.hxx" #include "KDEXLib.hxx" +#include "VCLKDEApplication.hxx" #include <assert.h> +#include <saldata.hxx> SalKDEDisplay* SalKDEDisplay::selfptr = NULL; @@ -52,4 +54,19 @@ SalKDEDisplay::~SalKDEDisplay() pDisp_ = NULL; } +void SalKDEDisplay::Yield() +{ + if( DispatchInternalEvent() ) + return; + + DBG_ASSERT( static_cast<SalYieldMutex*>(GetSalData()->m_pInstance->GetYieldMutex())->GetThreadId() == + osl::Thread::getCurrentIdentifier(), + "will crash soon since solar mutex not locked in SalKDEDisplay::Yield" ); + + XEvent event; + XNextEvent( pDisp_, &event ); + qApp->x11ProcessEvent( &event ); + // TODO maybe Qt needs locking and unlocking too? +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/kde4/KDESalDisplay.hxx b/vcl/unx/kde4/KDESalDisplay.hxx index 08201cbc747c..37a097f5051f 100644 --- a/vcl/unx/kde4/KDESalDisplay.hxx +++ b/vcl/unx/kde4/KDESalDisplay.hxx @@ -36,6 +36,11 @@ class SalKDEDisplay : public SalX11Display SalKDEDisplay( Display* pDisp ); virtual ~SalKDEDisplay(); static SalKDEDisplay* self(); + inline int userEventsCount() const { return m_aUserEvents.size(); } + inline void EventGuardAcquire() { osl_acquireMutex( hEventGuard_ ); } + inline void EventGuardRelease() { osl_releaseMutex( hEventGuard_ ); } +// virtual long Dispatch( XEvent *event ); + virtual void Yield(); private: static SalKDEDisplay* selfptr; }; diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx index 1937f9a3b722..69f525993fcd 100644 --- a/vcl/unx/kde4/KDEXLib.cxx +++ b/vcl/unx/kde4/KDEXLib.cxx @@ -35,6 +35,8 @@ #include <kaboutdata.h> #include <kcmdlineargs.h> #include <kstartupinfo.h> +#include <qabstracteventdispatcher.h> +#include <qthread.h> #undef Region @@ -56,6 +58,17 @@ KDEXLib::KDEXLib() : SalXLib(), m_bStartupDone(false), m_pApplication(0), m_pFreeCmdLineArgs(0), m_pAppCmdLineArgs(0), m_nFakeCmdLineArgs( 0 ) { + // the timers created here means they belong to the main thread + connect( &timeoutTimer, SIGNAL( timeout()), this, SLOT( timeoutActivated())); + connect( &userEventTimer, SIGNAL( timeout()), this, SLOT( userEventActivated())); + // QTimer::start() can be called only in its (here main) thread, so this will + // forward between threads if needed + connect( this, SIGNAL( startTimeoutTimerSignal()), this, SLOT( startTimeoutTimer()), Qt::QueuedConnection ); + connect( this, SIGNAL( startUserEventTimerSignal()), this, SLOT( startUserEventTimer()), Qt::QueuedConnection ); + // this one needs to be blocking, so that the handling in main thread is processed before + // the thread emitting the signal continues + connect( this, SIGNAL( processYieldSignal( bool, bool )), this, SLOT( processYield( bool, bool )), + Qt::BlockingQueuedConnection ); } KDEXLib::~KDEXLib() @@ -161,6 +174,124 @@ void KDEXLib::Init() pSalDisplay->SetKbdExtension( pKbdExtension ); } +void KDEXLib::Insert( int fd, void* data, YieldFunc pending, YieldFunc queued, YieldFunc handle ) +{ + SocketData sdata; + sdata.data = data; + sdata.pending = pending; + sdata.queued = queued; + sdata.handle = handle; + // qApp as parent to make sure it uses the main thread event loop + sdata.notifier = new QSocketNotifier( fd, QSocketNotifier::Read, qApp ); + connect( sdata.notifier, SIGNAL( activated( int )), this, SLOT( socketNotifierActivated( int ))); + socketData[ fd ] = sdata; +} + +void KDEXLib::Remove( int fd ) +{ + SocketData sdata = socketData.take( fd );// according to SalXLib::Remove() this should be safe + delete sdata.notifier; +} + +void KDEXLib::socketNotifierActivated( int fd ) +{ + SalData *pSalData = GetSalData(); + const SocketData& sdata = socketData[ fd ]; + pSalData->m_pInstance->GetYieldMutex()->acquire(); + sdata.handle( fd, sdata.data ); + pSalData->m_pInstance->GetYieldMutex()->release(); +} + +void KDEXLib::Yield( bool bWait, bool bHandleAllCurrentEvents ) +{ + // if we are the main thread (which is where the event processing is done), + // good, just do it + if( qApp->thread() == QThread::currentThread()) + processYield( bWait, bHandleAllCurrentEvents ); + else + { // if this deadlocks, event processing needs to go into a separate thread + // or some other solution needs to be found + emit processYieldSignal( bWait, bHandleAllCurrentEvents ); + } +} + +void KDEXLib::processYield( bool bWait, bool bHandleAllCurrentEvents ) +{ + YieldMutexReleaser aReleaser; + QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance( qApp->thread()); + bool wasEvent = false; + for( int cnt = bHandleAllCurrentEvents ? 100 : 1; + cnt > 0; + --cnt ) + { + if( !dispatcher->processEvents( QEventLoop::AllEvents )) + break; + wasEvent = true; + } + if( bWait && !wasEvent ) + dispatcher->processEvents( QEventLoop::WaitForMoreEvents ); +} + +void KDEXLib::StartTimer( ULONG nMS ) +{ + timeoutTimer.setInterval( nMS ); + // QTimer's can be started only in their thread (main thread here) + if( qApp->thread() == QThread::currentThread()) + startTimeoutTimer(); + else + emit startTimeoutTimerSignal(); +} + +void KDEXLib::startTimeoutTimer() +{ + timeoutTimer.start(); +} + +void KDEXLib::StopTimer() +{ + timeoutTimer.stop(); +} + +void KDEXLib::timeoutActivated() +{ + SalData *pSalData = GetSalData(); + pSalData->m_pInstance->GetYieldMutex()->acquire(); + GetX11SalData()->Timeout(); + // QTimer is not single shot, so will be restarted immediatelly + pSalData->m_pInstance->GetYieldMutex()->release(); +} + +void KDEXLib::Wakeup() +{ + QAbstractEventDispatcher::instance( qApp->thread())->wakeUp(); // main thread event loop +} + +void KDEXLib::PostUserEvent() +{ + if( qApp->thread() == QThread::currentThread()) + startUserEventTimer(); + else + emit startUserEventTimerSignal(); +} + +void KDEXLib::startUserEventTimer() +{ + userEventTimer.start( 0 ); +} + +void KDEXLib::userEventActivated() +{ + SalData *pSalData = GetSalData(); + pSalData->m_pInstance->GetYieldMutex()->acquire(); + SalKDEDisplay::self()->EventGuardAcquire(); + if( SalKDEDisplay::self()->userEventsCount() <= 1 ) + userEventTimer.stop(); + SalKDEDisplay::self()->EventGuardRelease(); + SalKDEDisplay::self()->DispatchInternalEvent(); + pSalData->m_pInstance->GetYieldMutex()->release(); + // QTimer is not single shot, so will be restarted immediatelly +} + void KDEXLib::doStartup() { if( ! m_bStartupDone ) diff --git a/vcl/unx/kde4/KDEXLib.hxx b/vcl/unx/kde4/KDEXLib.hxx index 7fbcbb6320e4..e05ac20f54c5 100644 --- a/vcl/unx/kde4/KDEXLib.hxx +++ b/vcl/unx/kde4/KDEXLib.hxx @@ -30,22 +30,59 @@ #include <saldisp.hxx> +#include <fixx11h.h> + +#include <qhash.h> +#include <qsocketnotifier.h> +#include <qtimer.h> + class VCLKDEApplication; -class KDEXLib : public SalXLib +class KDEXLib : public QObject, public SalXLib { + Q_OBJECT private: bool m_bStartupDone; VCLKDEApplication* m_pApplication; char** m_pFreeCmdLineArgs; char** m_pAppCmdLineArgs; int m_nFakeCmdLineArgs; + struct SocketData + { + void* data; + YieldFunc pending; + YieldFunc queued; + YieldFunc handle; + QSocketNotifier* notifier; + }; + QHash< int, SocketData > socketData; // key is fd + QTimer timeoutTimer; + QTimer userEventTimer; + + private slots: + void socketNotifierActivated( int fd ); + void timeoutActivated(); + void userEventActivated(); + void startTimeoutTimer(); + void startUserEventTimer(); + void processYield( bool bWait, bool bHandleAllCurrentEvents ); + signals: + void startTimeoutTimerSignal(); + void startUserEventTimerSignal(); + void processYieldSignal( bool bWait, bool bHandleAllCurrentEvents ); public: KDEXLib(); - virtual ~KDEXLib(); + virtual void Init(); + virtual void Yield( bool bWait, bool bHandleAllCurrentEvents ); + virtual void Insert( int fd, void* data, YieldFunc pending, YieldFunc queued, YieldFunc handle ); + virtual void Remove( int fd ); + virtual void StartTimer( ULONG nMS ); + virtual void StopTimer(); + virtual void Wakeup(); + virtual void PostUserEvent(); void doStartup(); }; diff --git a/vcl/unx/kde4/makefile.mk b/vcl/unx/kde4/makefile.mk index fd1e9ca59236..f4ea1874a211 100644 --- a/vcl/unx/kde4/makefile.mk +++ b/vcl/unx/kde4/makefile.mk @@ -67,6 +67,7 @@ SLOFILES=\ $(SLO)$/main.obj \ $(SLO)$/VCLKDEApplication.obj \ $(SLO)$/KDEXLib.obj \ + $(SLO)$/KDEXLib.moc.obj \ $(SLO)$/KDESalDisplay.obj \ $(SLO)$/KDESalFrame.obj \ $(SLO)$/KDESalGraphics.obj \ @@ -86,3 +87,6 @@ dummy: .INCLUDE : target.mk .INCLUDE : $(PRJ)$/util$/target.pmk + +$(MISC)$/KDEXLib.moc.cxx : KDEXLib.hxx + $(MOC4) $< -o $@ |