Merge branch 'qt_event_loop' of https://github.com/GeoTeric/wxWidgets
Use QEventLoop for wxEventLoop implementation in wxQt to fix several issues with wxEventLoop, notably avoid "QApplication::exec is already running" errors. See https://github.com/wxWidgets/wxWidgets/pull/1165
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
#define _WX_QT_EVTLOOP_H_
|
#define _WX_QT_EVTLOOP_H_
|
||||||
|
|
||||||
class QTimer;
|
class QTimer;
|
||||||
|
class QEventLoop;
|
||||||
|
|
||||||
class WXDLLIMPEXP_CORE wxQtEventLoopBase : public wxEventLoopBase
|
class WXDLLIMPEXP_CORE wxQtEventLoopBase : public wxEventLoopBase
|
||||||
{
|
{
|
||||||
@@ -16,13 +17,15 @@ public:
|
|||||||
wxQtEventLoopBase();
|
wxQtEventLoopBase();
|
||||||
~wxQtEventLoopBase();
|
~wxQtEventLoopBase();
|
||||||
|
|
||||||
virtual int DoRun();
|
virtual int DoRun() wxOVERRIDE;
|
||||||
virtual void ScheduleExit(int rc = 0);
|
virtual void ScheduleExit(int rc = 0) wxOVERRIDE;
|
||||||
virtual bool Pending() const;
|
virtual bool Pending() const wxOVERRIDE;
|
||||||
virtual bool Dispatch();
|
virtual bool Dispatch() wxOVERRIDE;
|
||||||
virtual int DispatchTimeout(unsigned long timeout);
|
virtual int DispatchTimeout(unsigned long timeout) wxOVERRIDE;
|
||||||
virtual void WakeUp();
|
virtual void WakeUp() wxOVERRIDE;
|
||||||
virtual void DoYieldFor(long eventsToProcess);
|
virtual void DoYieldFor(long eventsToProcess) wxOVERRIDE;
|
||||||
|
|
||||||
|
void ScheduleIdleCheck();
|
||||||
|
|
||||||
#if wxUSE_EVENTLOOP_SOURCE
|
#if wxUSE_EVENTLOOP_SOURCE
|
||||||
virtual wxEventLoopSource *AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags);
|
virtual wxEventLoopSource *AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags);
|
||||||
@@ -30,6 +33,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QEventLoop *m_qtEventLoop;
|
||||||
QTimer *m_qtIdleTimer;
|
QTimer *m_qtIdleTimer;
|
||||||
|
|
||||||
wxDECLARE_NO_COPY_CLASS(wxQtEventLoopBase);
|
wxDECLARE_NO_COPY_CLASS(wxQtEventLoopBase);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <QtCore/QAbstractEventDispatcher>
|
#include <QtCore/QAbstractEventDispatcher>
|
||||||
#include <QtCore/QSocketNotifier>
|
#include <QtCore/QSocketNotifier>
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
|
#include <QtCore/QEventLoop>
|
||||||
|
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
|
|
||||||
@@ -40,14 +41,13 @@ wxQtIdleTimer::wxQtIdleTimer( wxQtEventLoopBase *eventLoop )
|
|||||||
|
|
||||||
connect( this, &QTimer::timeout, this, &wxQtIdleTimer::idle );
|
connect( this, &QTimer::timeout, this, &wxQtIdleTimer::idle );
|
||||||
setSingleShot( true );
|
setSingleShot( true );
|
||||||
start( 0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxQtIdleTimer::eventFilter( QObject *WXUNUSED( watched ), QEvent *WXUNUSED( event ) )
|
bool wxQtIdleTimer::eventFilter( QObject *WXUNUSED( watched ), QEvent *WXUNUSED( event ) )
|
||||||
{
|
{
|
||||||
// Called for each Qt event, start with timeout 0 (run as soon as idle)
|
// Called for each Qt event, start with timeout 0 (run as soon as idle)
|
||||||
if ( !isActive() )
|
if ( !isActive() )
|
||||||
start( 0 );
|
m_eventLoop->ScheduleIdleCheck();
|
||||||
|
|
||||||
return false; // Continue handling the event
|
return false; // Continue handling the event
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ void wxQtIdleTimer::idle()
|
|||||||
|
|
||||||
// Send idle event
|
// Send idle event
|
||||||
if ( m_eventLoop->ProcessIdle() )
|
if ( m_eventLoop->ProcessIdle() )
|
||||||
start( 0 );
|
m_eventLoop->ScheduleIdleCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxQtEventLoopBase::wxQtEventLoopBase()
|
wxQtEventLoopBase::wxQtEventLoopBase()
|
||||||
@@ -78,10 +78,15 @@ wxQtEventLoopBase::wxQtEventLoopBase()
|
|||||||
// Pass all events to the idle timer, so it can be restarted each time
|
// Pass all events to the idle timer, so it can be restarted each time
|
||||||
// an event is received
|
// an event is received
|
||||||
qApp->installEventFilter( m_qtIdleTimer );
|
qApp->installEventFilter( m_qtIdleTimer );
|
||||||
|
|
||||||
|
|
||||||
|
m_qtEventLoop = new QEventLoop;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxQtEventLoopBase::~wxQtEventLoopBase()
|
wxQtEventLoopBase::~wxQtEventLoopBase()
|
||||||
{
|
{
|
||||||
|
qApp->removeEventFilter(m_qtIdleTimer);
|
||||||
|
delete m_qtEventLoop;
|
||||||
delete m_qtIdleTimer;
|
delete m_qtIdleTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,44 +94,31 @@ void wxQtEventLoopBase::ScheduleExit(int rc)
|
|||||||
{
|
{
|
||||||
wxCHECK_RET( IsInsideRun(), wxT("can't call ScheduleExit() if not started") );
|
wxCHECK_RET( IsInsideRun(), wxT("can't call ScheduleExit() if not started") );
|
||||||
m_shouldExit = true;
|
m_shouldExit = true;
|
||||||
QCoreApplication::exit( rc );
|
m_qtEventLoop->exit(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int wxQtEventLoopBase::DoRun()
|
int wxQtEventLoopBase::DoRun()
|
||||||
{
|
{
|
||||||
int ret;
|
const int ret = m_qtEventLoop->exec();
|
||||||
|
|
||||||
// This is placed inside of a loop to take into account nested event loops
|
|
||||||
while ( !m_shouldExit )
|
|
||||||
{
|
|
||||||
// This will print Qt warnins if app already started:
|
|
||||||
// "QCoreApplication::exec: The event loop is already running"
|
|
||||||
// TODO: check the loopLevel (nested) like in wxGTK
|
|
||||||
ret = QCoreApplication::exec();
|
|
||||||
// process pending events (if exec was started previously)
|
|
||||||
// TODO: use a real new QEventLoop() ?
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
|
||||||
OnExit();
|
OnExit();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxQtEventLoopBase::Pending() const
|
bool wxQtEventLoopBase::Pending() const
|
||||||
{
|
{
|
||||||
return QCoreApplication::hasPendingEvents();
|
QAbstractEventDispatcher *instance = QAbstractEventDispatcher::instance();
|
||||||
|
return instance->hasPendingEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxQtEventLoopBase::Dispatch()
|
bool wxQtEventLoopBase::Dispatch()
|
||||||
{
|
{
|
||||||
QCoreApplication::processEvents();
|
m_qtEventLoop->processEvents();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wxQtEventLoopBase::DispatchTimeout(unsigned long timeout)
|
int wxQtEventLoopBase::DispatchTimeout(unsigned long timeout)
|
||||||
{
|
{
|
||||||
QCoreApplication::processEvents( QEventLoop::AllEvents, timeout );
|
m_qtEventLoop->processEvents(QEventLoop::AllEvents, timeout);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,6 +138,12 @@ void wxQtEventLoopBase::DoYieldFor(long eventsToProcess)
|
|||||||
wxEventLoopBase::DoYieldFor(eventsToProcess);
|
wxEventLoopBase::DoYieldFor(eventsToProcess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxQtEventLoopBase::ScheduleIdleCheck()
|
||||||
|
{
|
||||||
|
if ( IsInsideRun() )
|
||||||
|
m_qtIdleTimer->start(0);
|
||||||
|
}
|
||||||
|
|
||||||
#if wxUSE_EVENTLOOP_SOURCE
|
#if wxUSE_EVENTLOOP_SOURCE
|
||||||
|
|
||||||
template <void (wxEventLoopSourceHandler::*function)()>
|
template <void (wxEventLoopSourceHandler::*function)()>
|
||||||
|
|||||||
Reference in New Issue
Block a user