summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@suse.cz>2010-10-13 14:39:16 +0200
committerLuboš Luňák <l.lunak@suse.cz>2010-10-14 18:14:14 +0200
commit924673ea9afc389eaf04b9bccc6f9d8028e12f0d (patch)
tree60f08d0fc08cf864861ce68272111d01fad3a246 /vcl
parent6b5a13a80bef8026abb53d665af3240ad3148eeb (diff)
make KDE4 vclplug use Qt event loop as the event loop
Diffstat (limited to 'vcl')
-rw-r--r--vcl/unx/kde4/KDESalDisplay.cxx17
-rw-r--r--vcl/unx/kde4/KDESalDisplay.hxx5
-rw-r--r--vcl/unx/kde4/KDEXLib.cxx131
-rw-r--r--vcl/unx/kde4/KDEXLib.hxx41
-rw-r--r--vcl/unx/kde4/makefile.mk4
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 $@