Merge branch 'qt_more_event_loop_improvements' of https://github.com/GeoTeric/wxWidgets
Event loop and idle events improvements for wxQt See https://github.com/wxWidgets/wxWidgets/pull/1171
This commit is contained in:
@@ -8,7 +8,7 @@
|
|||||||
#ifndef _WX_QT_EVTLOOP_H_
|
#ifndef _WX_QT_EVTLOOP_H_
|
||||||
#define _WX_QT_EVTLOOP_H_
|
#define _WX_QT_EVTLOOP_H_
|
||||||
|
|
||||||
class QTimer;
|
class wxQtIdleTimer;
|
||||||
class QEventLoop;
|
class QEventLoop;
|
||||||
|
|
||||||
class WXDLLIMPEXP_CORE wxQtEventLoopBase : public wxEventLoopBase
|
class WXDLLIMPEXP_CORE wxQtEventLoopBase : public wxEventLoopBase
|
||||||
@@ -30,11 +30,10 @@ public:
|
|||||||
#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);
|
||||||
#endif // wxUSE_EVENTLOOP_SOURCE
|
#endif // wxUSE_EVENTLOOP_SOURCE
|
||||||
protected:
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QEventLoop *m_qtEventLoop;
|
QEventLoop *m_qtEventLoop;
|
||||||
QTimer *m_qtIdleTimer;
|
wxObjectDataPtr<wxQtIdleTimer> m_qtIdleTimer;
|
||||||
|
|
||||||
wxDECLARE_NO_COPY_CLASS(wxQtEventLoopBase);
|
wxDECLARE_NO_COPY_CLASS(wxQtEventLoopBase);
|
||||||
};
|
};
|
||||||
|
@@ -21,33 +21,48 @@
|
|||||||
|
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
|
|
||||||
class wxQtIdleTimer : public QTimer
|
class wxQtIdleTimer : public QTimer, public wxRefCounter
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wxQtIdleTimer( wxQtEventLoopBase *eventLoop );
|
wxQtIdleTimer();
|
||||||
|
~wxQtIdleTimer();
|
||||||
virtual bool eventFilter( QObject * watched, QEvent * event );
|
virtual bool eventFilter( QObject * watched, QEvent * event );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void idle();
|
void idle();
|
||||||
|
void ScheduleIdleCheck();
|
||||||
private:
|
|
||||||
wxQtEventLoopBase *m_eventLoop;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
wxQtIdleTimer::wxQtIdleTimer( wxQtEventLoopBase *eventLoop )
|
wxQtIdleTimer::wxQtIdleTimer()
|
||||||
{
|
{
|
||||||
m_eventLoop = eventLoop;
|
// We need a QCoreApplication for event loops, create it here if it doesn't
|
||||||
|
// already exist as we can't modify wxAppConsole
|
||||||
|
if ( !QCoreApplication::instance() )
|
||||||
|
{
|
||||||
|
new QApplication(wxAppConsole::GetInstance()->argc, wxAppConsole::GetInstance()->argv);
|
||||||
|
}
|
||||||
|
|
||||||
connect( this, &QTimer::timeout, this, &wxQtIdleTimer::idle );
|
|
||||||
setSingleShot( true );
|
// Pass all events to the idle timer, so it can be restarted each time
|
||||||
|
// an event is received
|
||||||
|
qApp->installEventFilter(this);
|
||||||
|
|
||||||
|
connect(this, &QTimer::timeout, this, &wxQtIdleTimer::idle);
|
||||||
|
setSingleShot(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxQtIdleTimer::~wxQtIdleTimer()
|
||||||
|
{
|
||||||
|
qApp->removeEventFilter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
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() )
|
||||||
m_eventLoop->ScheduleIdleCheck();
|
ScheduleIdleCheck();
|
||||||
|
|
||||||
return false; // Continue handling the event
|
return false; // Continue handling the event
|
||||||
}
|
}
|
||||||
@@ -59,35 +74,40 @@ void wxQtIdleTimer::idle()
|
|||||||
wxTheApp->ProcessPendingEvents();
|
wxTheApp->ProcessPendingEvents();
|
||||||
|
|
||||||
// Send idle event
|
// Send idle event
|
||||||
if ( m_eventLoop->ProcessIdle() )
|
if (wxTheApp->ProcessIdle())
|
||||||
m_eventLoop->ScheduleIdleCheck();
|
ScheduleIdleCheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
wxObjectDataPtr<wxQtIdleTimer> gs_idleTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxQtIdleTimer::ScheduleIdleCheck()
|
||||||
|
{
|
||||||
|
wxQtEventLoopBase *eventLoop = static_cast<wxQtEventLoopBase*>(wxEventLoop::GetActive());
|
||||||
|
if ( eventLoop )
|
||||||
|
eventLoop->ScheduleIdleCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxQtEventLoopBase::wxQtEventLoopBase()
|
wxQtEventLoopBase::wxQtEventLoopBase()
|
||||||
{
|
{
|
||||||
// We need a QCoreApplication for event loops, create it here if it doesn't
|
|
||||||
// already exist as we can't modify wxAppConsole
|
|
||||||
if ( !QCoreApplication::instance() )
|
|
||||||
{
|
|
||||||
new QApplication( wxAppConsole::GetInstance()->argc, wxAppConsole::GetInstance()->argv );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create an idle timer to run each time there are no events (timeout = 0)
|
// Create an idle timer to run each time there are no events (timeout = 0)
|
||||||
m_qtIdleTimer = new wxQtIdleTimer( this );
|
if ( !gs_idleTimer )
|
||||||
|
gs_idleTimer.reset(new wxQtIdleTimer());
|
||||||
// Pass all events to the idle timer, so it can be restarted each time
|
|
||||||
// an event is received
|
|
||||||
qApp->installEventFilter( m_qtIdleTimer );
|
|
||||||
|
|
||||||
|
|
||||||
|
m_qtIdleTimer = gs_idleTimer;
|
||||||
m_qtEventLoop = new QEventLoop;
|
m_qtEventLoop = new QEventLoop;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxQtEventLoopBase::~wxQtEventLoopBase()
|
wxQtEventLoopBase::~wxQtEventLoopBase()
|
||||||
{
|
{
|
||||||
qApp->removeEventFilter(m_qtIdleTimer);
|
//Clear the shared timer if this is the only external reference to it
|
||||||
|
if ( gs_idleTimer->GetRefCount() <= 2 )
|
||||||
|
gs_idleTimer.reset(NULL);
|
||||||
|
|
||||||
delete m_qtEventLoop;
|
delete m_qtEventLoop;
|
||||||
delete m_qtIdleTimer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxQtEventLoopBase::ScheduleExit(int rc)
|
void wxQtEventLoopBase::ScheduleExit(int rc)
|
||||||
@@ -131,16 +151,23 @@ void wxQtEventLoopBase::WakeUp()
|
|||||||
|
|
||||||
void wxQtEventLoopBase::DoYieldFor(long eventsToProcess)
|
void wxQtEventLoopBase::DoYieldFor(long eventsToProcess)
|
||||||
{
|
{
|
||||||
while (wxTheApp && wxTheApp->Pending())
|
|
||||||
// TODO: implement event filtering using the eventsToProcess mask
|
QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents;
|
||||||
wxTheApp->Dispatch();
|
|
||||||
|
if ( !(eventsToProcess & wxEVT_CATEGORY_USER_INPUT) )
|
||||||
|
flags |= QEventLoop::ExcludeUserInputEvents;
|
||||||
|
|
||||||
|
if ( !(eventsToProcess & wxEVT_CATEGORY_SOCKET) )
|
||||||
|
flags |= QEventLoop::ExcludeSocketNotifiers;
|
||||||
|
|
||||||
|
m_qtEventLoop->processEvents(flags);
|
||||||
|
|
||||||
wxEventLoopBase::DoYieldFor(eventsToProcess);
|
wxEventLoopBase::DoYieldFor(eventsToProcess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxQtEventLoopBase::ScheduleIdleCheck()
|
void wxQtEventLoopBase::ScheduleIdleCheck()
|
||||||
{
|
{
|
||||||
if ( IsInsideRun() )
|
if ( IsInsideRun() && !m_shouldExit )
|
||||||
m_qtIdleTimer->start(0);
|
m_qtIdleTimer->start(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user