Merge branch 'master' of http://scm.trinitydesktop.org/scm/git/qt3
commit
2211b1bf66
@ -0,0 +1,130 @@
|
||||
/**
|
||||
** Qt->glib main event loop integration by Norbert Frese 2005
|
||||
** code based on qeventloop_p.h 3.3.5
|
||||
**
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
** $Id: qt/qeventloop_glib_p.h
|
||||
**
|
||||
** Definition of QEventLoop class
|
||||
**
|
||||
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
|
||||
**
|
||||
** This file is part of the kernel module of the Qt GUI Toolkit.
|
||||
**
|
||||
** This file may be distributed and/or modified under the terms of the
|
||||
** GNU General Public License version 2 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file.
|
||||
**
|
||||
** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
|
||||
** licenses for Qt/Embedded may use this file in accordance with the
|
||||
** Qt Embedded Commercial License Agreement provided with the Software.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
|
||||
** information about Qt Commercial License Agreements.
|
||||
** See http://www.trolltech.com/gpl/ for GPL licensing information.
|
||||
**
|
||||
** Contact info@trolltech.com if any conditions of this licensing are
|
||||
** not clear to you.
|
||||
**
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef QEVENTLOOP_GLIB_P_H
|
||||
#define QEVENTLOOP_GLIB_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. This header file may
|
||||
// change from version to version without notice, or even be
|
||||
// removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef QT_H
|
||||
#include "qplatformdefs.h"
|
||||
#endif // QT_H
|
||||
|
||||
// SCO OpenServer redefines raise -> kill
|
||||
#if defined(raise)
|
||||
# undef raise
|
||||
#endif
|
||||
|
||||
#include "qeventloop.h"
|
||||
#include "qwindowdefs.h"
|
||||
|
||||
class QSocketNotifier;
|
||||
|
||||
#include "qptrlist.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
// uncomment this for main loop related debug-output
|
||||
|
||||
// #define DEBUG_QT_GLIBMAINLOOP 1
|
||||
|
||||
// Wrapper for QSocketNotifier Object and GPollFD
|
||||
|
||||
struct QSockNotGPollFD
|
||||
{
|
||||
QSocketNotifier *obj;
|
||||
GPollFD gPollFD;
|
||||
gushort events; // save events
|
||||
bool pending;
|
||||
};
|
||||
|
||||
class QEventLoopPrivate
|
||||
{
|
||||
public:
|
||||
QEventLoopPrivate()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
looplevel = 0;
|
||||
quitcode = 0;
|
||||
quitnow = FALSE;
|
||||
exitloop = FALSE;
|
||||
shortcut = FALSE;
|
||||
}
|
||||
|
||||
int looplevel;
|
||||
int quitcode;
|
||||
unsigned int quitnow : 1;
|
||||
unsigned int exitloop : 1;
|
||||
unsigned int shortcut : 1;
|
||||
|
||||
#if defined(Q_WS_X11)
|
||||
int xfd;
|
||||
|
||||
GPollFD x_gPollFD;
|
||||
|
||||
#endif // Q_WS_X11
|
||||
|
||||
int thread_pipe[2];
|
||||
|
||||
GPollFD threadPipe_gPollFD;
|
||||
|
||||
QPtrList<QSockNotGPollFD> sn_list;
|
||||
// pending socket notifiers list
|
||||
QPtrList<QSockNotGPollFD> sn_pending_list;
|
||||
|
||||
// store flags for one iteration
|
||||
uint pev_flags;
|
||||
|
||||
// My GSource
|
||||
|
||||
GSource * gSource;
|
||||
|
||||
};
|
||||
|
||||
#endif // QEVENTLOOP_GLIB_P_H
|
@ -0,0 +1,593 @@
|
||||
/**
|
||||
** Qt->glib main event loop integration by Norbert Frese 2005
|
||||
** code based on qeventloop_unix.cpp 3.3.5
|
||||
**
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
** $Id: qt/qeventloop_unix_glib.cpp
|
||||
**
|
||||
** Implementation of QEventLoop class
|
||||
**
|
||||
** Copyright (C) 2000-2005 Trolltech AS. All rights reserved.
|
||||
**
|
||||
** This file is part of the kernel module of the Qt GUI Toolkit.
|
||||
**
|
||||
** This file may be distributed under the terms of the Q Public License
|
||||
** as defined by Trolltech AS of Norway and appearing in the file
|
||||
** LICENSE.QPL included in the packaging of this file.
|
||||
**
|
||||
** This file may be distributed and/or modified under the terms of the
|
||||
** GNU General Public License version 2 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file.
|
||||
**
|
||||
** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
|
||||
** licenses for Unix/X11 or for Qt/Embedded may use this file in accordance
|
||||
** with the Qt Commercial License Agreement provided with the Software.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
|
||||
** information about Qt Commercial License Agreements.
|
||||
** See http://www.trolltech.com/qpl/ for QPL licensing information.
|
||||
** See http://www.trolltech.com/gpl/ for GPL licensing information.
|
||||
**
|
||||
** Contact info@trolltech.com if any conditions of this licensing are
|
||||
** not clear to you.
|
||||
**
|
||||
**********************************************************************/
|
||||
|
||||
|
||||
#include "qeventloop_glib_p.h" // includes qplatformdefs.h
|
||||
#include "qeventloop.h"
|
||||
#include "qapplication.h"
|
||||
#include "qbitarray.h"
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/*****************************************************************************
|
||||
Timer handling; UNIX has no application timer support so we'll have to
|
||||
make our own from scratch.
|
||||
|
||||
NOTE: These functions are for internal use. QObject::startTimer() and
|
||||
QObject::killTimer() are for public use.
|
||||
The QTimer class provides a high-level interface which translates
|
||||
timer events into signals.
|
||||
|
||||
qStartTimer( interval, obj )
|
||||
Starts a timer which will run until it is killed with qKillTimer()
|
||||
Arguments:
|
||||
int interval timer interval in milliseconds
|
||||
QObject *obj where to send the timer event
|
||||
Returns:
|
||||
int timer identifier, or zero if not successful
|
||||
|
||||
qKillTimer( timerId )
|
||||
Stops a timer specified by a timer identifier.
|
||||
Arguments:
|
||||
int timerId timer identifier
|
||||
Returns:
|
||||
bool TRUE if successful
|
||||
|
||||
qKillTimer( obj )
|
||||
Stops all timers that are sent to the specified object.
|
||||
Arguments:
|
||||
QObject *obj object receiving timer events
|
||||
Returns:
|
||||
bool TRUE if successful
|
||||
*****************************************************************************/
|
||||
|
||||
//
|
||||
// Internal data structure for timers
|
||||
//
|
||||
|
||||
struct TimerInfo { // internal timer info
|
||||
int id; // - timer identifier
|
||||
timeval interval; // - timer interval
|
||||
timeval timeout; // - when to sent event
|
||||
QObject *obj; // - object to receive event
|
||||
};
|
||||
|
||||
typedef QPtrList<TimerInfo> TimerList; // list of TimerInfo structs
|
||||
|
||||
static QBitArray *timerBitVec; // timer bit vector
|
||||
static TimerList *timerList = 0; // timer list
|
||||
|
||||
static void initTimers();
|
||||
void cleanupTimers();
|
||||
static timeval watchtime; // watch if time is turned back
|
||||
timeval *qt_wait_timer();
|
||||
timeval *qt_wait_timer_max = 0;
|
||||
|
||||
//
|
||||
// Internal operator functions for timevals
|
||||
//
|
||||
|
||||
static inline bool operator<( const timeval &t1, const timeval &t2 )
|
||||
{
|
||||
return t1.tv_sec < t2.tv_sec ||
|
||||
(t1.tv_sec == t2.tv_sec && t1.tv_usec < t2.tv_usec);
|
||||
}
|
||||
|
||||
static inline bool operator==( const timeval &t1, const timeval &t2 )
|
||||
{
|
||||
return t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec;
|
||||
}
|
||||
|
||||
static inline timeval &operator+=( timeval &t1, const timeval &t2 )
|
||||
{
|
||||
t1.tv_sec += t2.tv_sec;
|
||||
if ( (t1.tv_usec += t2.tv_usec) >= 1000000 ) {
|
||||
t1.tv_sec++;
|
||||
t1.tv_usec -= 1000000;
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
|
||||
static inline timeval operator+( const timeval &t1, const timeval &t2 )
|
||||
{
|
||||
timeval tmp;
|
||||
tmp.tv_sec = t1.tv_sec + t2.tv_sec;
|
||||
if ( (tmp.tv_usec = t1.tv_usec + t2.tv_usec) >= 1000000 ) {
|
||||
tmp.tv_sec++;
|
||||
tmp.tv_usec -= 1000000;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static inline timeval operator-( const timeval &t1, const timeval &t2 )
|
||||
{
|
||||
timeval tmp;
|
||||
tmp.tv_sec = t1.tv_sec - t2.tv_sec;
|
||||
if ( (tmp.tv_usec = t1.tv_usec - t2.tv_usec) < 0 ) {
|
||||
tmp.tv_sec--;
|
||||
tmp.tv_usec += 1000000;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Internal functions for manipulating timer data structures.
|
||||
// The timerBitVec array is used for keeping track of timer identifiers.
|
||||
//
|
||||
|
||||
static int allocTimerId() // find avail timer identifier
|
||||
{
|
||||
int i = timerBitVec->size()-1;
|
||||
while ( i >= 0 && (*timerBitVec)[i] )
|
||||
i--;
|
||||
if ( i < 0 ) {
|
||||
i = timerBitVec->size();
|
||||
timerBitVec->resize( 4 * i );
|
||||
for( int j=timerBitVec->size()-1; j > i; j-- )
|
||||
timerBitVec->clearBit( j );
|
||||
}
|
||||
timerBitVec->setBit( i );
|
||||
return i+1;
|
||||
}
|
||||
|
||||
static void insertTimer( const TimerInfo *ti ) // insert timer info into list
|
||||
{
|
||||
TimerInfo *t = timerList->first();
|
||||
int index = 0;
|
||||
#if defined(QT_DEBUG)
|
||||
int dangerCount = 0;
|
||||
#endif
|
||||
while ( t && t->timeout < ti->timeout ) { // list is sorted by timeout
|
||||
#if defined(QT_DEBUG)
|
||||
if ( t->obj == ti->obj )
|
||||
dangerCount++;
|
||||
#endif
|
||||
t = timerList->next();
|
||||
index++;
|
||||
}
|
||||
timerList->insert( index, ti ); // inserts sorted
|
||||
#if defined(QT_DEBUG)
|
||||
if ( dangerCount > 16 )
|
||||
qDebug( "QObject: %d timers now exist for object %s::%s",
|
||||
dangerCount, ti->obj->className(), ti->obj->name() );
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void getTime( timeval &t ) // get time of day
|
||||
{
|
||||
gettimeofday( &t, 0 );
|
||||
while ( t.tv_usec >= 1000000 ) { // NTP-related fix
|
||||
t.tv_usec -= 1000000;
|
||||
t.tv_sec++;
|
||||
}
|
||||
while ( t.tv_usec < 0 ) {
|
||||
if ( t.tv_sec > 0 ) {
|
||||
t.tv_usec += 1000000;
|
||||
t.tv_sec--;
|
||||
} else {
|
||||
t.tv_usec = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void repairTimer( const timeval &time ) // repair broken timer
|
||||
{
|
||||
timeval diff = watchtime - time;
|
||||
register TimerInfo *t = timerList->first();
|
||||
while ( t ) { // repair all timers
|
||||
t->timeout = t->timeout - diff;
|
||||
t = timerList->next();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Timer activation functions (called from the event loop)
|
||||
//
|
||||
|
||||
/*
|
||||
Returns the time to wait for the next timer, or null if no timers are
|
||||
waiting.
|
||||
|
||||
The result is bounded to qt_wait_timer_max if this exists.
|
||||
*/
|
||||
|
||||
timeval *qt_wait_timer()
|
||||
{
|
||||
static timeval tm;
|
||||
bool first = TRUE;
|
||||
timeval currentTime;
|
||||
if ( timerList && timerList->count() ) { // there are waiting timers
|
||||
getTime( currentTime );
|
||||
if ( first ) {
|
||||
if ( currentTime < watchtime ) // clock was turned back
|
||||
repairTimer( currentTime );
|
||||
first = FALSE;
|
||||
watchtime = currentTime;
|
||||
}
|
||||
TimerInfo *t = timerList->first(); // first waiting timer
|
||||
if ( currentTime < t->timeout ) { // time to wait
|
||||
tm = t->timeout - currentTime;
|
||||
} else {
|
||||
tm.tv_sec = 0; // no time to wait
|
||||
tm.tv_usec = 0;
|
||||
}
|
||||
if ( qt_wait_timer_max && *qt_wait_timer_max < tm )
|
||||
tm = *qt_wait_timer_max;
|
||||
return &tm;
|
||||
}
|
||||
if ( qt_wait_timer_max ) {
|
||||
tm = *qt_wait_timer_max;
|
||||
return &tm;
|
||||
}
|
||||
return 0; // no timers
|
||||
}
|
||||
|
||||
// Timer initialization
|
||||
static void initTimers() // initialize timers
|
||||
{
|
||||
timerBitVec = new QBitArray( 128 );
|
||||
Q_CHECK_PTR( timerBitVec );
|
||||
int i = timerBitVec->size();
|
||||
while( i-- > 0 )
|
||||
timerBitVec->clearBit( i );
|
||||
timerList = new TimerList;
|
||||
Q_CHECK_PTR( timerList );
|
||||
timerList->setAutoDelete( TRUE );
|
||||
gettimeofday( &watchtime, 0 );
|
||||
}
|
||||
|
||||
// Timer cleanup
|
||||
void cleanupTimers()
|
||||
{
|
||||
delete timerList;
|
||||
timerList = 0;
|
||||
delete timerBitVec;
|
||||
timerBitVec = 0;
|
||||
}
|
||||
|
||||
// Main timer functions for starting and killing timers
|
||||
int qStartTimer( int interval, QObject *obj )
|
||||
{
|
||||
if ( !timerList ) // initialize timer data
|
||||
initTimers();
|
||||
int id = allocTimerId(); // get free timer id
|
||||
if ( id <= 0 ||
|
||||
id > (int)timerBitVec->size() || !obj )// cannot create timer
|
||||
return 0;
|
||||
timerBitVec->setBit( id-1 ); // set timer active
|
||||
TimerInfo *t = new TimerInfo; // create timer
|
||||
Q_CHECK_PTR( t );
|
||||
t->id = id;
|
||||
t->interval.tv_sec = interval/1000;
|
||||
t->interval.tv_usec = (interval%1000)*1000;
|
||||
timeval currentTime;
|
||||
getTime( currentTime );
|
||||
t->timeout = currentTime + t->interval;
|
||||
t->obj = obj;
|
||||
insertTimer( t ); // put timer in list
|
||||
return id;
|
||||
}
|
||||
|
||||
bool qKillTimer( int id )
|
||||
{
|
||||
register TimerInfo *t;
|
||||
if ( !timerList || id <= 0 ||
|
||||
id > (int)timerBitVec->size() || !timerBitVec->testBit( id-1 ) )
|
||||
return FALSE; // not init'd or invalid timer
|
||||
t = timerList->first();
|
||||
while ( t && t->id != id ) // find timer info in list
|
||||
t = timerList->next();
|
||||
if ( t ) { // id found
|
||||
timerBitVec->clearBit( id-1 ); // set timer inactive
|
||||
return timerList->remove();
|
||||
}
|
||||
else // id not found
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool qKillTimer( QObject *obj )
|
||||
{
|
||||
register TimerInfo *t;
|
||||
if ( !timerList ) // not initialized
|
||||
return FALSE;
|
||||
t = timerList->first();
|
||||
while ( t ) { // check all timers
|
||||
if ( t->obj == obj ) { // object found
|
||||
timerBitVec->clearBit( t->id-1 );
|
||||
timerList->remove();
|
||||
t = timerList->current();
|
||||
} else {
|
||||
t = timerList->next();
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
QEventLoop implementations for Glib-Main-Loop
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
void QEventLoop::registerSocketNotifier( QSocketNotifier *notifier )
|
||||
{
|
||||
|
||||
|
||||
|
||||
int sockfd = notifier->socket();
|
||||
int type = notifier->type();
|
||||
if ( sockfd < 0 || type < 0 || type > 2 || notifier == 0 ) {
|
||||
#if defined(QT_CHECK_RANGE)
|
||||
qWarning( "QSocketNotifier: Internal error" );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("register socket notifier %d\n", sockfd);
|
||||
#endif
|
||||
|
||||
QPtrList<QSockNotGPollFD> *list = &d->sn_list;
|
||||
QSockNotGPollFD *sn;
|
||||
|
||||
/*
|
||||
if ( ! list ) {
|
||||
// create new list, the QSockNotType destructor will delete it for us
|
||||
list = new QPtrList<QSockNot>;
|
||||
Q_CHECK_PTR( list );
|
||||
list->setAutoDelete( TRUE );
|
||||
d->sn_list = list;
|
||||
}
|
||||
*/
|
||||
|
||||
gushort events=0;
|
||||
switch (type) {
|
||||
case 0:
|
||||
events = G_IO_IN | G_IO_HUP;
|
||||
break;
|
||||
case 1:
|
||||
events = G_IO_OUT;
|
||||
break;
|
||||
case 2:
|
||||
events = G_IO_PRI | G_IO_ERR | G_IO_NVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
sn = new QSockNotGPollFD;
|
||||
Q_CHECK_PTR( sn );
|
||||
sn->obj = notifier;
|
||||
sn->gPollFD.fd = sockfd;
|
||||
sn->gPollFD.events = events;
|
||||
sn->events = events; // save events!
|
||||
sn->pending = FALSE;
|
||||
|
||||
list->append( sn );
|
||||
|
||||
g_source_add_poll(d->gSource, &sn->gPollFD);
|
||||
|
||||
}
|
||||
|
||||
void QEventLoop::unregisterSocketNotifier( QSocketNotifier *notifier )
|
||||
{
|
||||
int sockfd = notifier->socket();
|
||||
int type = notifier->type();
|
||||
if ( sockfd < 0 || type < 0 || type > 2 || notifier == 0 ) {
|
||||
#if defined(QT_CHECK_RANGE)
|
||||
qWarning( "QSocketNotifier: Internal error" );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("unregister socket notifier %d\n", sockfd);
|
||||
#endif
|
||||
|
||||
QPtrList<QSockNotGPollFD> *list = &d->sn_list;
|
||||
QSockNotGPollFD *sn;
|
||||
if ( ! list )
|
||||
return;
|
||||
sn = list->first();
|
||||
while ( sn && !(sn->obj == notifier) )
|
||||
sn = list->next();
|
||||
if ( !sn ) // not found
|
||||
return;
|
||||
|
||||
d->sn_pending_list.removeRef( sn );
|
||||
list->remove(); // remove notifier found above
|
||||
g_source_remove_poll(d->gSource, &sn->gPollFD);
|
||||
|
||||
delete sn; // we don't autodelete - lets do it manually
|
||||
|
||||
}
|
||||
|
||||
void QEventLoop::setSocketNotifierPending( QSocketNotifier *notifier )
|
||||
{
|
||||
int sockfd = notifier->socket();
|
||||
int type = notifier->type();
|
||||
if ( sockfd < 0 || type < 0 || type > 2 || notifier == 0 ) {
|
||||
#if defined(QT_CHECK_RANGE)
|
||||
qWarning( "QSocketNotifier: Internal error" );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("set socket notifier pending %d\n", sockfd);
|
||||
#endif
|
||||
|
||||
QPtrList<QSockNotGPollFD> *list = &d->sn_list;
|
||||
QSockNotGPollFD *sn;
|
||||
if ( ! list )
|
||||
return;
|
||||
sn = list->first();
|
||||
while ( sn && !(sn->obj == notifier) )
|
||||
sn = list->next();
|
||||
if ( ! sn ) { // not found
|
||||
return;
|
||||
}
|
||||
|
||||
// We choose a random activation order to be more fair under high load.
|
||||
// If a constant order is used and a peer early in the list can
|
||||
// saturate the IO, it might grab our attention completely.
|
||||
// Also, if we're using a straight list, the callback routines may
|
||||
// delete other entries from the list before those other entries are
|
||||
// processed.
|
||||
if ( !sn->pending ) {
|
||||
d->sn_pending_list.insert( (rand() & 0xff) %
|
||||
(d->sn_pending_list.count()+1), sn );
|
||||
sn->pending = TRUE; // add it only once!
|
||||
}
|
||||
}
|
||||
|
||||
void QEventLoop::wakeUp()
|
||||
{
|
||||
/*
|
||||
Apparently, there is not consistency among different operating
|
||||
systems on how to use FIONREAD.
|
||||
|
||||
FreeBSD, Linux and Solaris all expect the 3rd argument to
|
||||
ioctl() to be an int, which is normally 32-bit even on 64-bit
|
||||
machines.
|
||||
|
||||
IRIX, on the other hand, expects a size_t, which is 64-bit on
|
||||
64-bit machines.
|
||||
|
||||
So, the solution is to use size_t initialized to zero to make
|
||||
sure all bits are set to zero, preventing underflow with the
|
||||
FreeBSD/Linux/Solaris ioctls.
|
||||
*/
|
||||
size_t nbytes = 0;
|
||||
char c = 0;
|
||||
if ( ::ioctl( d->thread_pipe[0], FIONREAD, (char*)&nbytes ) >= 0 && nbytes == 0 ) {
|
||||
::write( d->thread_pipe[1], &c, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
int QEventLoop::timeToWait() const
|
||||
{
|
||||
timeval *tm = qt_wait_timer();
|
||||
if ( ! tm ) // no active timers
|
||||
return -1;
|
||||
return (tm->tv_sec*1000) + (tm->tv_usec/1000);
|
||||
}
|
||||
|
||||
int QEventLoop::activateTimers()
|
||||
{
|
||||
if ( !timerList || !timerList->count() ) // no timers
|
||||
return 0;
|
||||
bool first = TRUE;
|
||||
timeval currentTime;
|
||||
int n_act = 0, maxCount = timerList->count();
|
||||
TimerInfo *begin = 0;
|
||||
register TimerInfo *t;
|
||||
|
||||
for ( ;; ) {
|
||||
if ( ! maxCount-- )
|
||||
break;
|
||||
getTime( currentTime ); // get current time
|
||||
if ( first ) {
|
||||
if ( currentTime < watchtime ) // clock was turned back
|
||||
repairTimer( currentTime );
|
||||
first = FALSE;
|
||||
watchtime = currentTime;
|
||||
}
|
||||
t = timerList->first();
|
||||
if ( !t || currentTime < t->timeout ) // no timer has expired
|
||||
break;
|
||||
if ( ! begin ) {
|
||||
begin = t;
|
||||
} else if ( begin == t ) {
|
||||
// avoid sending the same timer multiple times
|
||||
break;
|
||||
} else if ( t->interval < begin->interval || t->interval == begin->interval ) {
|
||||
begin = t;
|
||||
}
|
||||
timerList->take(); // unlink from list
|
||||
t->timeout += t->interval;
|
||||
if ( t->timeout < currentTime )
|
||||
t->timeout = currentTime + t->interval;
|
||||
insertTimer( t ); // relink timer
|
||||
if ( t->interval.tv_usec > 0 || t->interval.tv_sec > 0 )
|
||||
n_act++;
|
||||
QTimerEvent e( t->id );
|
||||
QApplication::sendEvent( t->obj, &e ); // send event
|
||||
if ( timerList->findRef( begin ) == -1 )
|
||||
begin = 0;
|
||||
}
|
||||
return n_act;
|
||||
}
|
||||
|
||||
int QEventLoop::activateSocketNotifiers()
|
||||
{
|
||||
if ( d->sn_pending_list.isEmpty() )
|
||||
return 0;
|
||||
|
||||
// activate entries
|
||||
int n_act = 0;
|
||||
QEvent event( QEvent::SockAct );
|
||||
QPtrListIterator<QSockNotGPollFD> it( d->sn_pending_list );
|
||||
QSockNotGPollFD *sn;
|
||||
while ( (sn=it.current()) ) {
|
||||
++it;
|
||||
d->sn_pending_list.removeRef( sn );
|
||||
if ( sn->pending ) {
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("activate sn : send event fd=%d\n", sn->gPollFD.fd );
|
||||
#endif
|
||||
|
||||
|
||||
sn->pending = FALSE;
|
||||
QApplication::sendEvent( sn->obj, &event );
|
||||
n_act++;
|
||||
}
|
||||
}
|
||||
|
||||
return n_act;
|
||||
}
|
@ -0,0 +1,618 @@
|
||||
/**
|
||||
** Qt->glib main event loop integration by Norbert Frese 2005
|
||||
** code based on qeventloop_x11.cpp 3.3.5
|
||||
**
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
** $Id: qt/qeventloop_x11_glib.cpp
|
||||
**
|
||||
** Implementation of QEventLoop class
|
||||
**
|
||||
** Copyright (C) 2000-2005 Trolltech AS. All rights reserved.
|
||||
**
|
||||
** This file is part of the kernel module of the Qt GUI Toolkit.
|
||||
**
|
||||
** This file may be distributed under the terms of the Q Public License
|
||||
** as defined by Trolltech AS of Norway and appearing in the file
|
||||
** LICENSE.QPL included in the packaging of this file.
|
||||
**
|
||||
** This file may be distributed and/or modified under the terms of the
|
||||
** GNU General Public License version 2 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file.
|
||||
**
|
||||
** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
|
||||
** licenses for Unix/X11 may use this file in accordance with the Qt Commercial
|
||||
** License Agreement provided with the Software.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
|
||||
** information about Qt Commercial License Agreements.
|
||||
** See http://www.trolltech.com/qpl/ for QPL licensing information.
|
||||
** See http://www.trolltech.com/gpl/ for GPL licensing information.
|
||||
**
|
||||
** Contact info@trolltech.com if any conditions of this licensing are
|
||||
** not clear to you.
|
||||
**
|
||||
**********************************************************************/
|
||||
|
||||
|
||||
#include "qeventloop_glib_p.h" // includes qplatformdefs.h
|
||||
#include "qeventloop.h"
|
||||
#include "qapplication.h"
|
||||
#include "qbitarray.h"
|
||||
#include "qcolor_p.h"
|
||||
#include "qt_x11_p.h"
|
||||
|
||||
#if defined(QT_THREAD_SUPPORT)
|
||||
# include "qmutex.h"
|
||||
#endif // QT_THREAD_SUPPORT
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
// Qt-GSource Structure and Callbacks
|
||||
|
||||
typedef struct {
|
||||
GSource source;
|
||||
QEventLoop * qeventLoop;
|
||||
} QtGSource;
|
||||
|
||||
static gboolean qt_gsource_prepare ( GSource *source,
|
||||
gint *timeout );
|
||||
static gboolean qt_gsource_check ( GSource *source );
|
||||
static gboolean qt_gsource_dispatch ( GSource *source,
|
||||
GSourceFunc callback, gpointer user_data );
|
||||
|
||||
static GSourceFuncs qt_gsource_funcs = {
|
||||
qt_gsource_prepare,
|
||||
qt_gsource_check,
|
||||
qt_gsource_dispatch,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
// forward main loop callbacks to QEventLoop methods!
|
||||
|
||||
static gboolean qt_gsource_prepare ( GSource *source,
|
||||
gint *timeout )
|
||||
{
|
||||
QtGSource * qtGSource;
|
||||
qtGSource = (QtGSource*) source;
|
||||
return qtGSource->qeventLoop->gsourcePrepare(source, timeout);
|
||||
}
|
||||
|
||||
static gboolean qt_gsource_check ( GSource *source )
|
||||
{
|
||||
QtGSource * qtGSource = (QtGSource*) source;
|
||||
return qtGSource->qeventLoop->gsourceCheck(source);
|
||||
}
|
||||
|
||||
static gboolean qt_gsource_dispatch ( GSource *source,
|
||||
GSourceFunc callback, gpointer user_data )
|
||||
{
|
||||
QtGSource * qtGSource = (QtGSource*) source;
|
||||
return qtGSource->qeventLoop->gsourceDispatch(source);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
// resolve the conflict between X11's FocusIn and QEvent::FocusIn
|
||||
#undef FocusOut
|
||||
#undef FocusIn
|
||||
|
||||
static const int XKeyPress = KeyPress;
|
||||
static const int XKeyRelease = KeyRelease;
|
||||
#undef KeyPress
|
||||
#undef KeyRelease
|
||||
|
||||
// from qapplication.cpp
|
||||
extern bool qt_is_gui_used;
|
||||
|
||||
// from qeventloop_unix.cpp
|
||||
extern timeval *qt_wait_timer();
|
||||
extern void cleanupTimers();
|
||||
|
||||
// ### this needs to go away at some point...
|
||||
typedef void (*VFPTR)();
|
||||
typedef QValueList<VFPTR> QVFuncList;
|
||||
void qt_install_preselect_handler( VFPTR );
|
||||
void qt_remove_preselect_handler( VFPTR );
|
||||
static QVFuncList *qt_preselect_handler = 0;
|
||||
void qt_install_postselect_handler( VFPTR );
|
||||
void qt_remove_postselect_handler( VFPTR );
|
||||
static QVFuncList *qt_postselect_handler = 0;
|
||||
|
||||
void qt_install_preselect_handler( VFPTR handler )
|
||||
{
|
||||
if ( !qt_preselect_handler )
|
||||
qt_preselect_handler = new QVFuncList;
|
||||
qt_preselect_handler->append( handler );
|
||||
}
|
||||
void qt_remove_preselect_handler( VFPTR handler )
|
||||
{
|
||||
if ( qt_preselect_handler ) {
|
||||
QVFuncList::Iterator it = qt_preselect_handler->find( handler );
|
||||
if ( it != qt_preselect_handler->end() )
|
||||
qt_preselect_handler->remove( it );
|
||||
}
|
||||
}
|
||||
void qt_install_postselect_handler( VFPTR handler )
|
||||
{
|
||||
if ( !qt_postselect_handler )
|
||||
qt_postselect_handler = new QVFuncList;
|
||||
qt_postselect_handler->prepend( handler );
|
||||
}
|
||||
void qt_remove_postselect_handler( VFPTR handler )
|
||||
{
|
||||
if ( qt_postselect_handler ) {
|
||||
QVFuncList::Iterator it = qt_postselect_handler->find( handler );
|
||||
if ( it != qt_postselect_handler->end() )
|
||||
qt_postselect_handler->remove( it );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QEventLoop::init()
|
||||
{
|
||||
// initialize ProcessEventFlags (all events & wait for more)
|
||||
|
||||
d->pev_flags = AllEvents | WaitForMore;
|
||||
|
||||
// initialize the common parts of the event loop
|
||||
pipe( d->thread_pipe );
|
||||
fcntl(d->thread_pipe[0], F_SETFD, FD_CLOEXEC);
|
||||
fcntl(d->thread_pipe[1], F_SETFD, FD_CLOEXEC);
|
||||
|
||||
// intitialize the X11 parts of the event loop
|
||||
d->xfd = -1;
|
||||
if ( qt_is_gui_used )
|
||||
d->xfd = XConnectionNumber( QPaintDevice::x11AppDisplay() );
|
||||
|
||||
// new GSource
|
||||
|
||||
QtGSource * qtGSource = (QtGSource*) g_source_new(&qt_gsource_funcs,
|
||||
sizeof(QtGSource));
|
||||
|
||||
g_source_set_can_recurse ((GSource*)qtGSource, TRUE);
|
||||
|
||||
qtGSource->qeventLoop = this;
|
||||
|
||||
// init main loop and attach gsource
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside init(1)\n");
|
||||
#endif
|
||||
|
||||
g_main_loop_new (NULL, 1);
|
||||
|
||||
g_source_attach( (GSource*)qtGSource, NULL );
|
||||
|
||||
d->gSource = (GSource*) qtGSource;
|
||||
|
||||
// poll for X11 events
|
||||
|
||||
if ( qt_is_gui_used ) {
|
||||
|
||||
|
||||
d->x_gPollFD.fd = d->xfd;
|
||||
d->x_gPollFD.events = G_IO_IN | G_IO_HUP;
|
||||
g_source_add_poll(d->gSource, &d->x_gPollFD);
|
||||
}
|
||||
|
||||
// poll thread-pipe
|
||||
|
||||
d->threadPipe_gPollFD.fd = d->thread_pipe[0];
|
||||
d->threadPipe_gPollFD.events = G_IO_IN | G_IO_HUP;
|
||||
|
||||
g_source_add_poll(d->gSource, &d->threadPipe_gPollFD);
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside init(2)\n");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void QEventLoop::cleanup()
|
||||
{
|
||||
// cleanup the common parts of the event loop
|
||||
close( d->thread_pipe[0] );
|
||||
close( d->thread_pipe[1] );
|
||||
cleanupTimers();
|
||||
|
||||
// cleanup the X11 parts of the event loop
|
||||
d->xfd = -1;
|
||||
|
||||
// todo: destroy gsource
|
||||
}
|
||||
|
||||
bool QEventLoop::processEvents( ProcessEventsFlags flags )
|
||||
{
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside processEvents(1) looplevel=%d\n", d->looplevel );
|
||||
#endif
|
||||
ProcessEventsFlags save_flags;
|
||||
int rval;
|
||||
save_flags = d->pev_flags;
|
||||
|
||||
d->pev_flags = flags;
|
||||
|
||||
rval = g_main_context_iteration(NULL, flags & WaitForMore ? TRUE : FALSE);
|
||||
|
||||
d->pev_flags = save_flags;
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside processEvents(2) looplevel=%d rval=%d\n", d->looplevel, rval );
|
||||
#endif
|
||||
|
||||
return rval; // were events processed?
|
||||
}
|
||||
|
||||
|
||||
bool QEventLoop::processX11Events()
|
||||
{
|
||||
ProcessEventsFlags flags = d->pev_flags;
|
||||
// process events from the X server
|
||||
XEvent event;
|
||||
int nevents = 0;
|
||||
|
||||
#if defined(QT_THREAD_SUPPORT)
|
||||
QMutexLocker locker( QApplication::qt_mutex );
|
||||
#endif
|
||||
|
||||
// handle gui and posted events
|
||||
if ( qt_is_gui_used ) {
|
||||
QApplication::sendPostedEvents();
|
||||
|
||||
// Two loops so that posted events accumulate
|
||||
while ( XPending( QPaintDevice::x11AppDisplay() ) ) {
|
||||
// also flushes output buffer
|
||||
while ( XPending( QPaintDevice::x11AppDisplay() ) ) {
|
||||
if ( d->shortcut ) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
XNextEvent( QPaintDevice::x11AppDisplay(), &event );
|
||||
|
||||
if ( flags & ExcludeUserInput ) {
|
||||
switch ( event.type ) {
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
case MotionNotify:
|
||||
case XKeyPress:
|
||||
case XKeyRelease:
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
continue;
|
||||
|
||||
case ClientMessage:
|
||||
{
|
||||
// from qapplication_x11.cpp
|
||||
extern Atom qt_wm_protocols;
|
||||
extern Atom qt_wm_take_focus;
|
||||
extern Atom qt_qt_scrolldone;
|
||||
|
||||
// only keep the wm_take_focus and
|
||||
// qt_qt_scrolldone protocols, discard all
|
||||
// other client messages
|
||||
if ( event.xclient.format != 32 )
|
||||
continue;
|
||||
|
||||
if ( event.xclient.message_type == qt_wm_protocols ||
|
||||
(Atom) event.xclient.data.l[0] == qt_wm_take_focus )
|
||||
break;
|
||||
if ( event.xclient.message_type == qt_qt_scrolldone )
|
||||
break;
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
nevents++;
|
||||
if ( qApp->x11ProcessEvent( &event ) == 1 )
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( d->shortcut ) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
QApplication::sendPostedEvents();
|
||||
|
||||
const uint exclude_all = ExcludeSocketNotifiers | 0x08;
|
||||
// 0x08 == ExcludeTimers for X11 only
|
||||
if ( nevents > 0 && ( flags & exclude_all ) == exclude_all &&
|
||||
( flags & WaitForMore ) ) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
bool QEventLoop::gsourcePrepare(GSource *gs, int * timeout)
|
||||
{
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside gsourcePrepare(1)\n");
|
||||
#endif
|
||||
|
||||
ProcessEventsFlags flags = d->pev_flags;
|
||||
|
||||
#if defined(QT_THREAD_SUPPORT)
|
||||
QMutexLocker locker( QApplication::qt_mutex );
|
||||
#endif
|
||||
|
||||
// don't block if exitLoop() or exit()/quit() has been called.
|
||||
bool canWait = d->exitloop || d->quitnow ? FALSE : (flags & WaitForMore);
|
||||
|
||||
// Process timers and socket notifiers - the common UNIX stuff
|
||||
|
||||
// return the maximum time we can wait for an event.
|
||||
static timeval zerotm;
|
||||
timeval *tm = 0;
|
||||
if ( ! ( flags & 0x08 ) ) { // 0x08 == ExcludeTimers for X11 only
|
||||
tm = qt_wait_timer(); // wait for timer or X event
|
||||
if ( !canWait ) {
|
||||
if ( !tm )
|
||||
tm = &zerotm;
|
||||
tm->tv_sec = 0; // no time to wait
|
||||
tm->tv_usec = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// include or exclude SocketNotifiers (by setting or cleaning poll events)
|
||||
|
||||
if ( ! ( flags & ExcludeSocketNotifiers ) ) {
|
||||
QPtrListIterator<QSockNotGPollFD> it( d->sn_list );
|
||||
QSockNotGPollFD *sn;
|
||||
while ( (sn=it.current()) ) {
|
||||
++it;
|
||||
sn->gPollFD.events = sn->events; // restore poll events
|
||||
}
|
||||
} else {
|
||||
QPtrListIterator<QSockNotGPollFD> it( d->sn_list );
|
||||
QSockNotGPollFD *sn;
|
||||
while ( (sn=it.current()) ) {
|
||||
++it;
|
||||
sn->gPollFD.events = 0; // delete poll events
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside gsourcePrepare(2) canwait=%d\n", canWait);
|
||||
#endif
|
||||
|
||||
if ( canWait )
|
||||
emit aboutToBlock();
|
||||
|
||||
|
||||
if ( qt_preselect_handler ) {
|
||||
QVFuncList::Iterator it, end = qt_preselect_handler->end();
|
||||
for ( it = qt_preselect_handler->begin(); it != end; ++it )
|
||||
(**it)();
|
||||
}
|
||||
|
||||
// unlock the GUI mutex and select. when we return from this function, there is
|
||||
// something for us to do
|
||||
#if defined(QT_THREAD_SUPPORT)
|
||||
locker.mutex()->unlock();
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside gsourcePrepare(2.1) canwait=%d\n", canWait);
|
||||
#endif
|
||||
|
||||
// do we have to dispatch events?
|
||||
if (hasPendingEvents()) {
|
||||
*timeout = 0; // no time to stay in poll
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside gsourcePrepare(3a)\n");
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// stay in poll until something happens?
|
||||
if (!tm) { // fixme
|
||||
*timeout = -1; // wait forever
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside gsourcePrepare(3b) timeout=%d \n", *timeout);
|
||||
#endif
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// else timeout >=0
|
||||
*timeout = tm->tv_sec * 1000 + tm->tv_usec/1000;
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside gsourcePrepare(3c) timeout=%d \n", *timeout);
|
||||
#endif
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
bool QEventLoop::gsourceCheck(GSource *gs) {
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside gsourceCheck(1)\n");
|
||||
#endif
|
||||
|
||||
|
||||
// Socketnotifier events?
|
||||
|
||||
QPtrList<QSockNotGPollFD> *list = &d->sn_list;
|
||||
|
||||
//if ( list ) {
|
||||
|
||||
|
||||
QSockNotGPollFD *sn = list->first();
|
||||
while ( sn ) {
|
||||
if ( sn->gPollFD.revents )
|
||||
return TRUE;
|
||||
sn = list->next();
|
||||
}
|
||||
//}
|
||||
|
||||
if (d->x_gPollFD.revents) {
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside gsourceCheck(2) xfd!\n");
|
||||
#endif
|
||||
|
||||
return TRUE; // we got events!
|
||||
}
|
||||
if (d->threadPipe_gPollFD.revents) {
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside gsourceCheck(2) threadpipe!!\n");
|
||||
#endif
|
||||
|
||||
return TRUE; // we got events!
|
||||
}
|
||||
if (hasPendingEvents()) {
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside gsourceCheck(2) pendingEvents!\n");
|
||||
#endif
|
||||
|
||||
return TRUE; // we got more X11 events!
|
||||
}
|
||||
// check if we have timers to activate?
|
||||
|
||||
timeval * tm =qt_wait_timer();
|
||||
|
||||
if (tm && (tm->tv_sec == 0 && tm->tv_usec == 0 )) {
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside gsourceCheck(2) qtwaittimer!\n");
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// nothing to dispatch
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside gsourceCheck(2) nothing to dispatch!\n");
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
bool QEventLoop::gsourceDispatch(GSource *gs) {
|
||||
|
||||
// relock the GUI mutex before processing any pending events
|
||||
#if defined(QT_THREAD_SUPPORT)
|
||||
QMutexLocker locker( QApplication::qt_mutex );
|
||||
#endif
|
||||
#if defined(QT_THREAD_SUPPORT)
|
||||
locker.mutex()->lock();
|
||||
#endif
|
||||
|
||||
int nevents=0;
|
||||
|
||||
ProcessEventsFlags flags = d->pev_flags;
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside gsourceDispatch(1)\n");
|
||||
#endif
|
||||
|
||||
// we are awake, broadcast it
|
||||
emit awake();
|
||||
emit qApp->guiThreadAwake();
|
||||
|
||||
// some other thread woke us up... consume the data on the thread pipe so that
|
||||
// select doesn't immediately return next time
|
||||
|
||||
if ( d->threadPipe_gPollFD.revents) {
|
||||
char c;
|
||||
::read( d->thread_pipe[0], &c, 1 );
|
||||
}
|
||||
|
||||
if ( qt_postselect_handler ) {
|
||||
QVFuncList::Iterator it, end = qt_postselect_handler->end();
|
||||
for ( it = qt_postselect_handler->begin(); it != end; ++it )
|
||||
(**it)();
|
||||
}
|
||||
|
||||
// activate socket notifiers
|
||||
if ( ! ( flags & ExcludeSocketNotifiers )) {
|
||||
// if select says data is ready on any socket, then set the socket notifier
|
||||
// to pending
|
||||
// if ( &d->sn_list ) {
|
||||
|
||||
|
||||
QPtrList<QSockNotGPollFD> *list = &d->sn_list;
|
||||
QSockNotGPollFD *sn = list->first();
|
||||
while ( sn ) {
|
||||
if ( sn->gPollFD.revents )
|
||||
setSocketNotifierPending( sn->obj );
|
||||
sn = list->next();
|
||||
}
|
||||
// }
|
||||
|
||||
nevents += activateSocketNotifiers();
|
||||
}
|
||||
|
||||
// activate timers
|
||||
if ( ! ( flags & 0x08 ) ) {
|
||||
// 0x08 == ExcludeTimers for X11 only
|
||||
nevents += activateTimers();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// return true if we handled events, false otherwise
|
||||
//return (nevents > 0);
|
||||
|
||||
// now process x11 events!
|
||||
|
||||
#ifdef DEBUG_QT_GLIBMAINLOOP
|
||||
printf("inside gsourceDispatch(2) hasPendingEvents=%d\n", hasPendingEvents());
|
||||
#endif
|
||||
|
||||
if (hasPendingEvents()) {
|
||||
|
||||
// color approx. optimization - only on X11
|
||||
qt_reset_color_avail();
|
||||
|
||||
processX11Events();
|
||||
|
||||
}
|
||||
|
||||
#if defined(QT_THREAD_SUPPORT)
|
||||
locker.mutex()->unlock();
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
bool QEventLoop::hasPendingEvents() const
|
||||
{
|
||||
extern uint qGlobalPostedEventsCount(); // from qapplication.cpp
|
||||
return ( qGlobalPostedEventsCount() || ( qt_is_gui_used ? XPending( QPaintDevice::x11AppDisplay() ) : 0));
|
||||
}
|
||||
|
||||
void QEventLoop::appStartingUp()
|
||||
{
|
||||
if ( qt_is_gui_used )
|
||||
d->xfd = XConnectionNumber( QPaintDevice::x11AppDisplay() );
|
||||
}
|
||||
|
||||
void QEventLoop::appClosingDown()
|
||||
{
|
||||
d->xfd = -1;
|
||||
}
|
Loading…
Reference in new issue