268 lines
7.0 KiB
C++
268 lines
7.0 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/qt/evtloop.cpp
|
|
// Author: Mariano Reingart, Peter Most, Sean D'Epagnier, Javier Torres
|
|
// Copyright: (c) 2010 wxWidgets dev team
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#include "wx/app.h"
|
|
#include "wx/apptrait.h"
|
|
#include "wx/evtloop.h"
|
|
#include "wx/private/eventloopsourcesmanager.h"
|
|
|
|
#include <QtCore/QCoreApplication>
|
|
#include <QtCore/QAbstractEventDispatcher>
|
|
#include <QtCore/QSocketNotifier>
|
|
#include <QtCore/QTimer>
|
|
#include <QtCore/QEventLoop>
|
|
|
|
#include <QtWidgets/QApplication>
|
|
|
|
class wxQtIdleTimer : public QTimer
|
|
{
|
|
|
|
public:
|
|
wxQtIdleTimer( wxQtEventLoopBase *eventLoop );
|
|
virtual bool eventFilter( QObject * watched, QEvent * event );
|
|
|
|
private:
|
|
void idle();
|
|
|
|
private:
|
|
wxQtEventLoopBase *m_eventLoop;
|
|
};
|
|
|
|
wxQtIdleTimer::wxQtIdleTimer( wxQtEventLoopBase *eventLoop )
|
|
{
|
|
m_eventLoop = eventLoop;
|
|
|
|
connect( this, &QTimer::timeout, this, &wxQtIdleTimer::idle );
|
|
setSingleShot( true );
|
|
}
|
|
|
|
bool wxQtIdleTimer::eventFilter( QObject *WXUNUSED( watched ), QEvent *WXUNUSED( event ) )
|
|
{
|
|
// Called for each Qt event, start with timeout 0 (run as soon as idle)
|
|
if ( !isActive() )
|
|
m_eventLoop->ScheduleIdleCheck();
|
|
|
|
return false; // Continue handling the event
|
|
}
|
|
|
|
void wxQtIdleTimer::idle()
|
|
{
|
|
// Process pending events
|
|
if ( wxTheApp )
|
|
wxTheApp->ProcessPendingEvents();
|
|
|
|
// Send idle event
|
|
if ( m_eventLoop->ProcessIdle() )
|
|
m_eventLoop->ScheduleIdleCheck();
|
|
}
|
|
|
|
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)
|
|
m_qtIdleTimer = new wxQtIdleTimer( this );
|
|
|
|
// Pass all events to the idle timer, so it can be restarted each time
|
|
// an event is received
|
|
qApp->installEventFilter( m_qtIdleTimer );
|
|
|
|
|
|
m_qtEventLoop = new QEventLoop;
|
|
}
|
|
|
|
wxQtEventLoopBase::~wxQtEventLoopBase()
|
|
{
|
|
qApp->removeEventFilter(m_qtIdleTimer);
|
|
delete m_qtEventLoop;
|
|
delete m_qtIdleTimer;
|
|
}
|
|
|
|
void wxQtEventLoopBase::ScheduleExit(int rc)
|
|
{
|
|
wxCHECK_RET( IsInsideRun(), wxT("can't call ScheduleExit() if not started") );
|
|
m_shouldExit = true;
|
|
m_qtEventLoop->exit(rc);
|
|
}
|
|
|
|
int wxQtEventLoopBase::DoRun()
|
|
{
|
|
const int ret = m_qtEventLoop->exec();
|
|
OnExit();
|
|
return ret;
|
|
}
|
|
|
|
bool wxQtEventLoopBase::Pending() const
|
|
{
|
|
QAbstractEventDispatcher *instance = QAbstractEventDispatcher::instance();
|
|
return instance->hasPendingEvents();
|
|
}
|
|
|
|
bool wxQtEventLoopBase::Dispatch()
|
|
{
|
|
m_qtEventLoop->processEvents();
|
|
return true;
|
|
}
|
|
|
|
int wxQtEventLoopBase::DispatchTimeout(unsigned long timeout)
|
|
{
|
|
m_qtEventLoop->processEvents(QEventLoop::AllEvents, timeout);
|
|
return true;
|
|
}
|
|
|
|
void wxQtEventLoopBase::WakeUp()
|
|
{
|
|
QAbstractEventDispatcher *instance = QAbstractEventDispatcher::instance();
|
|
if ( instance )
|
|
instance->wakeUp();
|
|
}
|
|
|
|
void wxQtEventLoopBase::DoYieldFor(long eventsToProcess)
|
|
{
|
|
|
|
QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents;
|
|
|
|
if ( !(eventsToProcess & wxEVT_CATEGORY_USER_INPUT) )
|
|
flags |= QEventLoop::ExcludeUserInputEvents;
|
|
|
|
if ( !(eventsToProcess & wxEVT_CATEGORY_SOCKET) )
|
|
flags |= QEventLoop::ExcludeSocketNotifiers;
|
|
|
|
m_qtEventLoop->processEvents(flags);
|
|
|
|
wxEventLoopBase::DoYieldFor(eventsToProcess);
|
|
}
|
|
|
|
void wxQtEventLoopBase::ScheduleIdleCheck()
|
|
{
|
|
if ( IsInsideRun() && !m_shouldExit )
|
|
m_qtIdleTimer->start(0);
|
|
}
|
|
|
|
#if wxUSE_EVENTLOOP_SOURCE
|
|
|
|
template <void (wxEventLoopSourceHandler::*function)()>
|
|
class wxQtSocketNotifier : public QSocketNotifier
|
|
{
|
|
public:
|
|
wxQtSocketNotifier(int fd, Type type, wxEventLoopSourceHandler *handler)
|
|
: QSocketNotifier(fd, type),
|
|
m_handler(handler)
|
|
{
|
|
setEnabled(true);
|
|
|
|
connect(this, &wxQtSocketNotifier::activated, this, &wxQtSocketNotifier::OnWaiting);
|
|
}
|
|
|
|
void OnWaiting()
|
|
{
|
|
(m_handler->*function)();
|
|
}
|
|
|
|
wxEventLoopSourceHandler *m_handler;
|
|
};
|
|
|
|
class wxQtEventLoopSource : public wxEventLoopSource
|
|
{
|
|
public:
|
|
wxQtSocketNotifier<&wxEventLoopSourceHandler::OnReadWaiting> * m_reader;
|
|
wxQtSocketNotifier<&wxEventLoopSourceHandler::OnWriteWaiting> * m_writer;
|
|
wxQtSocketNotifier<&wxEventLoopSourceHandler::OnExceptionWaiting> * m_exception;
|
|
|
|
wxQtEventLoopSource(int fd, wxEventLoopSourceHandler *handler, int flags)
|
|
: wxEventLoopSource(handler, fd)
|
|
{
|
|
if ( flags & wxEVENT_SOURCE_INPUT )
|
|
m_reader = new wxQtSocketNotifier<&wxEventLoopSourceHandler::OnReadWaiting>
|
|
(fd, QSocketNotifier::Read, handler);
|
|
else
|
|
m_reader = NULL;
|
|
|
|
if ( flags & wxEVENT_SOURCE_OUTPUT )
|
|
m_writer = new wxQtSocketNotifier<&wxEventLoopSourceHandler::OnWriteWaiting>
|
|
(fd, QSocketNotifier::Write, handler);
|
|
else
|
|
m_writer = NULL;
|
|
|
|
if ( flags & wxEVENT_SOURCE_EXCEPTION )
|
|
m_exception = new wxQtSocketNotifier<&wxEventLoopSourceHandler::OnExceptionWaiting>
|
|
(fd, QSocketNotifier::Exception, handler);
|
|
else
|
|
m_exception = NULL;
|
|
}
|
|
|
|
virtual ~wxQtEventLoopSource()
|
|
{
|
|
// clean up notifiers
|
|
if (m_reader)
|
|
delete m_reader;
|
|
if (m_writer)
|
|
delete m_writer;
|
|
if (m_exception)
|
|
delete m_exception;
|
|
}
|
|
};
|
|
|
|
class wxQtEventLoopSourcesManager : public wxEventLoopSourcesManagerBase
|
|
{
|
|
public:
|
|
wxEventLoopSource*
|
|
AddSourceForFD(int fd, wxEventLoopSourceHandler* handler, int flags)
|
|
{
|
|
return new wxQtEventLoopSource(fd, handler, flags);
|
|
}
|
|
};
|
|
|
|
wxEventLoopSourcesManagerBase* wxGUIAppTraits::GetEventLoopSourcesManager()
|
|
{
|
|
static wxQtEventLoopSourcesManager s_eventLoopSourcesManager;
|
|
return &s_eventLoopSourcesManager;
|
|
}
|
|
|
|
#if !wxUSE_CONSOLE_EVENTLOOP
|
|
|
|
// Use the GUI event loop sources manager if console support is disabled
|
|
// (needed by some common code, will raise an undefinied reference if not done)
|
|
|
|
wxEventLoopSourcesManagerBase* wxAppTraits::GetEventLoopSourcesManager()
|
|
{
|
|
static wxQtEventLoopSourcesManager s_eventLoopSourcesManager;
|
|
return &s_eventLoopSourcesManager;
|
|
}
|
|
|
|
#endif
|
|
|
|
wxEventLoopSource *wxQtEventLoopBase::AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags)
|
|
{
|
|
wxGUIAppTraits *AppTraits = dynamic_cast<wxGUIAppTraits *>(wxApp::GetTraitsIfExists());
|
|
|
|
if ( AppTraits )
|
|
return AppTraits->GetEventLoopSourcesManager()->AddSourceForFD(fd, handler, flags);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#endif // wxUSE_EVENTLOOP_SOURCE
|
|
|
|
//#############################################################################
|
|
|
|
#if wxUSE_GUI
|
|
|
|
wxGUIEventLoop::wxGUIEventLoop()
|
|
{
|
|
}
|
|
|
|
#endif // wxUSE_GUI
|