diff options
author | Luboš Luňák <l.lunak@suse.cz> | 2010-10-14 17:54:48 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@suse.cz> | 2010-10-14 18:14:14 +0200 |
commit | fef486c99880d65b612831840a9f83e3fe4a0e17 (patch) | |
tree | 2c9da7bc04d6ef2edb801f45aa125dff4b4751b2 /vcl/unx | |
parent | 924673ea9afc389eaf04b9bccc6f9d8028e12f0d (diff) |
Qt event loop integration (when Glib is used) for KDE4 vclplug
So far disabled because of a pending bugfix for Qt, and support
for Qt's own event loop (without Glib) needs a missing feature
in Qt.
Diffstat (limited to 'vcl/unx')
-rw-r--r-- | vcl/unx/kde4/KDESalDisplay.cxx | 1 | ||||
-rw-r--r-- | vcl/unx/kde4/KDEXLib.cxx | 85 | ||||
-rw-r--r-- | vcl/unx/kde4/KDEXLib.hxx | 4 | ||||
-rw-r--r-- | vcl/unx/kde4/makefile.mk | 6 |
4 files changed, 83 insertions, 13 deletions
diff --git a/vcl/unx/kde4/KDESalDisplay.cxx b/vcl/unx/kde4/KDESalDisplay.cxx index 9877a9ed4974..dbfba3d4da6c 100644 --- a/vcl/unx/kde4/KDESalDisplay.cxx +++ b/vcl/unx/kde4/KDESalDisplay.cxx @@ -66,7 +66,6 @@ void 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/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx index 69f525993fcd..8ee186013231 100644 --- a/vcl/unx/kde4/KDEXLib.cxx +++ b/vcl/unx/kde4/KDEXLib.cxx @@ -36,6 +36,7 @@ #include <kcmdlineargs.h> #include <kstartupinfo.h> #include <qabstracteventdispatcher.h> +#include <qclipboard.h> #include <qthread.h> #undef Region @@ -54,9 +55,24 @@ #include <stdio.h> #endif +#include <stdio.h> + +#ifdef KDE_HAVE_GLIB +#if QT_VERSION >= QT_VERSION_CHECK( 4, 8, 0 ) +#if 0 // wait until fixed in Qt +#define GLIB_EVENT_LOOP_SUPPORT +#endif +#endif +#endif + +#ifdef GLIB_EVENT_LOOP_SUPPORT +#include <glib-2.0/glib.h> +#endif + KDEXLib::KDEXLib() : SalXLib(), m_bStartupDone(false), m_pApplication(0), - m_pFreeCmdLineArgs(0), m_pAppCmdLineArgs(0), m_nFakeCmdLineArgs( 0 ) + m_pFreeCmdLineArgs(0), m_pAppCmdLineArgs(0), m_nFakeCmdLineArgs( 0 ), + eventLoopType( LibreOfficeEventLoop ) { // the timers created here means they belong to the main thread connect( &timeoutTimer, SIGNAL( timeout()), this, SLOT( timeoutActivated())); @@ -156,6 +172,7 @@ void KDEXLib::Init() m_pApplication = new VCLKDEApplication(); kapp->disableSessionManagement(); KApplication::setQuitOnLastWindowClosed(false); + setupEventLoop(); Display* pDisp = QX11Info::display(); SalKDEDisplay *pSalDisplay = new SalKDEDisplay(pDisp); @@ -174,8 +191,52 @@ void KDEXLib::Init() pSalDisplay->SetKbdExtension( pKbdExtension ); } +// When we use Qt event loop, it can actually use its own event loop handling, or wrap +// the Glib event loop (the latter is the default is Qt is built with Glib support +// and $QT_NO_GLIB is not set). We mostly do not care which one it is, as QSocketNotifier's +// and QTimer's can handle it transparently, but it matters for the SolarMutex, which +// needs to be unlocked shortly before entering the main sleep (e.g. select()) and locked +// immediatelly after. So we need to know which event loop implementation is used and +// hook accordingly. +#ifdef GLIB_EVENT_LOOP_SUPPORT +static GPollFunc old_gpoll = NULL; +static gint gpoll_wrapper( GPollFD*, guint, gint ); +#endif + +void KDEXLib::setupEventLoop() +{ +#ifdef GLIB_EVENT_LOOP_SUPPORT +// Glib is simple, it has g_main_context_set_poll_func() for wrapping the sleep call. +// The catch is that Qt has a bug that allows triggering timers even when they should +// not be, leading to crashes caused by QClipboard re-entering the event loop. +// (http://bugreports.qt.nokia.com/browse/QTBUG-14461), so enable only with Qt>=4.8.0, +// where it is(?) fixed. + if( QAbstractEventDispatcher::instance()->inherits( "QEventDispatcherGlib" )) + { + eventLoopType = GlibEventLoop; + old_gpoll = g_main_context_get_poll_func( NULL ); + g_main_context_set_poll_func( NULL, gpoll_wrapper ); + // set QClipboard to use event loop, otherwise the main thread will hold + // SolarMutex locked, which will prevent the clipboard thread from answering + m_pApplication->clipboard()->setProperty( "useEventLoopWhenWaiting", true ); + return; + } +#endif + // TODO handle also Qt's own event loop (requires fixing Qt too) +} + +#ifdef GLIB_EVENT_LOOP_SUPPORT +gint gpoll_wrapper( GPollFD* ufds, guint nfds, gint timeout ) +{ + YieldMutexReleaser release; // release YieldMutex (and re-acquire at block end) + return old_gpoll( ufds, nfds, timeout ); +} +#endif + void KDEXLib::Insert( int fd, void* data, YieldFunc pending, YieldFunc queued, YieldFunc handle ) { + if( eventLoopType == LibreOfficeEventLoop ) + return SalXLib::Insert( fd, data, pending, queued, handle ); SocketData sdata; sdata.data = data; sdata.pending = pending; @@ -189,21 +250,22 @@ void KDEXLib::Insert( int fd, void* data, YieldFunc pending, YieldFunc queued, Y void KDEXLib::Remove( int fd ) { + if( eventLoopType == LibreOfficeEventLoop ) + return SalXLib::Remove( 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( eventLoopType == LibreOfficeEventLoop ) + return SalXLib::Yield( bWait, bHandleAllCurrentEvents ); // if we are the main thread (which is where the event processing is done), // good, just do it if( qApp->thread() == QThread::currentThread()) @@ -217,7 +279,6 @@ void KDEXLib::Yield( bool bWait, bool 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; @@ -234,6 +295,8 @@ void KDEXLib::processYield( bool bWait, bool bHandleAllCurrentEvents ) void KDEXLib::StartTimer( ULONG nMS ) { + if( eventLoopType == LibreOfficeEventLoop ) + return SalXLib::StartTimer( nMS ); timeoutTimer.setInterval( nMS ); // QTimer's can be started only in their thread (main thread here) if( qApp->thread() == QThread::currentThread()) @@ -249,25 +312,28 @@ void KDEXLib::startTimeoutTimer() void KDEXLib::StopTimer() { + if( eventLoopType == LibreOfficeEventLoop ) + return SalXLib::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() { + if( eventLoopType == LibreOfficeEventLoop ) + return SalXLib::Wakeup(); QAbstractEventDispatcher::instance( qApp->thread())->wakeUp(); // main thread event loop } void KDEXLib::PostUserEvent() { + if( eventLoopType == LibreOfficeEventLoop ) + return SalXLib::PostUserEvent(); if( qApp->thread() == QThread::currentThread()) startUserEventTimer(); else @@ -281,14 +347,11 @@ void KDEXLib::startUserEventTimer() 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 } diff --git a/vcl/unx/kde4/KDEXLib.hxx b/vcl/unx/kde4/KDEXLib.hxx index e05ac20f54c5..c3f8f27352b5 100644 --- a/vcl/unx/kde4/KDEXLib.hxx +++ b/vcl/unx/kde4/KDEXLib.hxx @@ -58,6 +58,10 @@ class KDEXLib : public QObject, public SalXLib QHash< int, SocketData > socketData; // key is fd QTimer timeoutTimer; QTimer userEventTimer; + enum { LibreOfficeEventLoop, GlibEventLoop } eventLoopType; + + private: + void setupEventLoop(); private slots: void socketNotifierActivated( int fd ); diff --git a/vcl/unx/kde4/makefile.mk b/vcl/unx/kde4/makefile.mk index f4ea1874a211..83ac1c0e6802 100644 --- a/vcl/unx/kde4/makefile.mk +++ b/vcl/unx/kde4/makefile.mk @@ -57,12 +57,16 @@ dummy: .IF "$(ENABLE_KDE4)" != "" -CFLAGS+=$(KDE4_CFLAGS) +CFLAGS+=$(KDE4_CFLAGS) $(KDE_GLIB_CFLAGS) .IF "$(ENABLE_RANDR)" != "" CDEFS+=-DUSE_RANDR .ENDIF +.IF "$(KDE_HAVE_GLIB)" != "" +CDEFS+=-DKDE_HAVE_GLIB +.ENDIF + SLOFILES=\ $(SLO)$/main.obj \ $(SLO)$/VCLKDEApplication.obj \ |